Merge branch 'master' into bugfix/path-invalid-base-geometry-robustness
This commit is contained in:
@@ -73,7 +73,7 @@ class OrthoArray(gui_base.GuiCommandBase):
|
||||
We add callbacks that connect the 3D view with
|
||||
the widgets of the task panel.
|
||||
"""
|
||||
_log("GuiCommand: {}".format(_self.command_name))
|
||||
_log("GuiCommand: {}".format(self.command_name))
|
||||
#_msg("{}".format(16*"-"))
|
||||
#_msg("GuiCommand: {}".format(self.command_name))
|
||||
|
||||
|
||||
@@ -297,7 +297,7 @@ class TaskPanelCircularArray:
|
||||
"App.ActiveDocument.recompute()"]
|
||||
|
||||
# We commit the command list through the parent command
|
||||
self.source_command.commit(translate("draft","Circular array", _cmd_list))
|
||||
self.source_command.commit(translate("draft","Circular array"), _cmd_list)
|
||||
|
||||
def get_distances(self):
|
||||
"""Get the distance parameters from the widgets."""
|
||||
|
||||
@@ -1497,6 +1497,30 @@ void MeshObject::validateIndices()
|
||||
this->_segments.clear();
|
||||
}
|
||||
|
||||
bool MeshObject::hasInvalidNeighbourhood() const
|
||||
{
|
||||
MeshCore::MeshEvalNeighbourhood eval(_kernel);
|
||||
return !eval.Evaluate();
|
||||
}
|
||||
|
||||
bool MeshObject::hasPointsOutOfRange() const
|
||||
{
|
||||
MeshCore::MeshEvalRangePoint eval(_kernel);
|
||||
return !eval.Evaluate();
|
||||
}
|
||||
|
||||
bool MeshObject::hasFacetsOutOfRange() const
|
||||
{
|
||||
MeshCore::MeshEvalRangeFacet eval(_kernel);
|
||||
return !eval.Evaluate();
|
||||
}
|
||||
|
||||
bool MeshObject::hasCorruptedFacets() const
|
||||
{
|
||||
MeshCore::MeshEvalCorruptedFacets eval(_kernel);
|
||||
return !eval.Evaluate();
|
||||
}
|
||||
|
||||
void MeshObject::validateDeformations(float fMaxAngle, float fEps)
|
||||
{
|
||||
unsigned long count = _kernel.CountFacets();
|
||||
|
||||
@@ -283,6 +283,10 @@ public:
|
||||
void removeDuplicatedPoints();
|
||||
void removeDuplicatedFacets();
|
||||
bool hasNonManifolds() const;
|
||||
bool hasInvalidNeighbourhood() const;
|
||||
bool hasPointsOutOfRange() const;
|
||||
bool hasFacetsOutOfRange() const;
|
||||
bool hasCorruptedFacets() const;
|
||||
void removeNonManifolds();
|
||||
void removeNonManifoldPoints();
|
||||
bool hasSelfIntersections() const;
|
||||
|
||||
@@ -229,7 +229,7 @@ for c in mesh.getSeparatecomponents():
|
||||
<UserDocu>Check if the mesh has non-manifolds</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="removeNonManifolds">
|
||||
<Methode Name="removeNonManifolds">
|
||||
<Documentation>
|
||||
<UserDocu>Remove non-manifolds</UserDocu>
|
||||
</Documentation>
|
||||
@@ -284,7 +284,27 @@ for c in mesh.getSeparatecomponents():
|
||||
<UserDocu>Remove points with invalid coordinates (NaN)</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="countComponents" Const="true">
|
||||
<Methode Name="hasInvalidNeighbourhood" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Check if the mesh has invalid neighbourhood indices</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="hasPointsOutOfRange" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Check if the mesh has point indices that are out of range</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="hasFacetsOutOfRange" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Check if the mesh has facet indices that are out of range</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="hasCorruptedFacets" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Check if the mesh has corrupted facets</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="countComponents" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Get the number of topologic independent areas</UserDocu>
|
||||
</Documentation>
|
||||
|
||||
@@ -972,6 +972,38 @@ PyObject* MeshPy::hasNonManifolds(PyObject *args)
|
||||
return Py_BuildValue("O", (ok ? Py_True : Py_False));
|
||||
}
|
||||
|
||||
PyObject* MeshPy::hasInvalidNeighbourhood(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
bool ok = getMeshObjectPtr()->hasInvalidNeighbourhood();
|
||||
return Py_BuildValue("O", (ok ? Py_True : Py_False));
|
||||
}
|
||||
|
||||
PyObject* MeshPy::hasPointsOutOfRange(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
bool ok = getMeshObjectPtr()->hasPointsOutOfRange();
|
||||
return Py_BuildValue("O", (ok ? Py_True : Py_False));
|
||||
}
|
||||
|
||||
PyObject* MeshPy::hasFacetsOutOfRange(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
bool ok = getMeshObjectPtr()->hasFacetsOutOfRange();
|
||||
return Py_BuildValue("O", (ok ? Py_True : Py_False));
|
||||
}
|
||||
|
||||
PyObject* MeshPy::hasCorruptedFacets(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
bool ok = getMeshObjectPtr()->hasFacetsOutOfRange();
|
||||
return Py_BuildValue("O", (ok ? Py_True : Py_False));
|
||||
}
|
||||
|
||||
PyObject* MeshPy::removeNonManifolds(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
|
||||
@@ -19,120 +19,224 @@ except Exception:
|
||||
|
||||
|
||||
class MeshTopoTestCases(unittest.TestCase):
|
||||
def setUp(self):
|
||||
# set up a planar face with 18 triangles
|
||||
self.planarMesh = []
|
||||
for x in range(3):
|
||||
for y in range(3):
|
||||
self.planarMesh.append( [0.0 + x, 0.0 + y,0.0000] )
|
||||
self.planarMesh.append( [1.0 + x, 1.0 + y,0.0000] )
|
||||
self.planarMesh.append( [0.0 + x, 1.0 + y,0.0000] )
|
||||
self.planarMesh.append( [0.0 + x, 0.0 + y,0.0000] )
|
||||
self.planarMesh.append( [1.0 + x, 0.0 + y,0.0000] )
|
||||
self.planarMesh.append( [1.0 + x, 1.0 + y,0.0000] )
|
||||
def setUp(self):
|
||||
# set up a planar face with 18 triangles
|
||||
self.planarMesh = []
|
||||
for x in range(3):
|
||||
for y in range(3):
|
||||
self.planarMesh.append( [0.0 + x, 0.0 + y,0.0000] )
|
||||
self.planarMesh.append( [1.0 + x, 1.0 + y,0.0000] )
|
||||
self.planarMesh.append( [0.0 + x, 1.0 + y,0.0000] )
|
||||
self.planarMesh.append( [0.0 + x, 0.0 + y,0.0000] )
|
||||
self.planarMesh.append( [1.0 + x, 0.0 + y,0.0000] )
|
||||
self.planarMesh.append( [1.0 + x, 1.0 + y,0.0000] )
|
||||
|
||||
|
||||
def testCollapseFacetsSingle(self):
|
||||
for i in range(18):
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
planarMeshObject.collapseFacets([i])
|
||||
def testCollapseFacetsSingle(self):
|
||||
for i in range(18):
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
planarMeshObject.collapseFacets([i])
|
||||
|
||||
def testCollapseFacetsMultible(self):
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
planarMeshObject.collapseFacets(range(7))
|
||||
def testCollapseFacetsMultible(self):
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
planarMeshObject.collapseFacets(range(7))
|
||||
|
||||
def testCollapseFacetsAll(self):
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
planarMeshObject.collapseFacets(range(18))
|
||||
def testCollapseFacetsAll(self):
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
planarMeshObject.collapseFacets(range(18))
|
||||
|
||||
|
||||
class MeshSplitTestCases(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.mesh = Mesh.createBox(1.0, 1.0, 1.0)
|
||||
|
||||
def testSplitFacetOnOneEdge(self):
|
||||
p1 = self.mesh.Points[0].Vector
|
||||
p2 = self.mesh.Points[1].Vector
|
||||
p3 = self.mesh.Points[2].Vector
|
||||
self.mesh.splitFacet(0, p1, (p2 + p3) / 2)
|
||||
self.assertFalse(self.mesh.hasNonManifolds())
|
||||
self.assertFalse(self.mesh.hasInvalidNeighbourhood())
|
||||
self.assertFalse(self.mesh.hasPointsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasFacetsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasCorruptedFacets())
|
||||
self.assertTrue(self.mesh.isSolid())
|
||||
|
||||
def testSplitFacetOnTwoEdges_21(self):
|
||||
p1 = self.mesh.Points[0].Vector
|
||||
p2 = self.mesh.Points[1].Vector
|
||||
p3 = self.mesh.Points[2].Vector
|
||||
self.mesh.splitFacet(0, (p1 + p3) / 2, (p2 + p3) / 2)
|
||||
self.assertFalse(self.mesh.hasNonManifolds())
|
||||
self.assertFalse(self.mesh.hasInvalidNeighbourhood())
|
||||
self.assertFalse(self.mesh.hasPointsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasFacetsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasCorruptedFacets())
|
||||
self.assertTrue(self.mesh.isSolid())
|
||||
|
||||
def testSplitFacetOnTwoEdges_12(self):
|
||||
p1 = self.mesh.Points[0].Vector
|
||||
p2 = self.mesh.Points[1].Vector
|
||||
p3 = self.mesh.Points[2].Vector
|
||||
self.mesh.splitFacet(0, (p2 + p3) / 2, (p1 + p3) / 2)
|
||||
self.assertFalse(self.mesh.hasNonManifolds())
|
||||
self.assertFalse(self.mesh.hasInvalidNeighbourhood())
|
||||
self.assertFalse(self.mesh.hasPointsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasFacetsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasCorruptedFacets())
|
||||
self.assertTrue(self.mesh.isSolid())
|
||||
|
||||
def testSplitFacetOnTwoEdges_01(self):
|
||||
p1 = self.mesh.Points[0].Vector
|
||||
p2 = self.mesh.Points[1].Vector
|
||||
p3 = self.mesh.Points[2].Vector
|
||||
self.mesh.splitFacet(0, (p1 + p2) / 2, (p2 + p3) / 2)
|
||||
self.assertFalse(self.mesh.hasNonManifolds())
|
||||
self.assertFalse(self.mesh.hasInvalidNeighbourhood())
|
||||
self.assertFalse(self.mesh.hasPointsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasFacetsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasCorruptedFacets())
|
||||
self.assertTrue(self.mesh.isSolid())
|
||||
|
||||
def testSplitFacetOnTwoEdges_10(self):
|
||||
p1 = self.mesh.Points[0].Vector
|
||||
p2 = self.mesh.Points[1].Vector
|
||||
p3 = self.mesh.Points[2].Vector
|
||||
self.mesh.splitFacet(0, (p2 + p3) / 2, (p1 + p2) / 2)
|
||||
self.assertFalse(self.mesh.hasNonManifolds())
|
||||
self.assertFalse(self.mesh.hasInvalidNeighbourhood())
|
||||
self.assertFalse(self.mesh.hasPointsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasFacetsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasCorruptedFacets())
|
||||
self.assertTrue(self.mesh.isSolid())
|
||||
|
||||
def testSplitFacetOnTwoEdges_02(self):
|
||||
p1 = self.mesh.Points[0].Vector
|
||||
p2 = self.mesh.Points[1].Vector
|
||||
p3 = self.mesh.Points[2].Vector
|
||||
self.mesh.splitFacet(0, (p1 + p2) / 2, (p1 + p3) / 2)
|
||||
self.assertFalse(self.mesh.hasNonManifolds())
|
||||
self.assertFalse(self.mesh.hasInvalidNeighbourhood())
|
||||
self.assertFalse(self.mesh.hasPointsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasFacetsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasCorruptedFacets())
|
||||
self.assertTrue(self.mesh.isSolid())
|
||||
|
||||
def testSplitFacetOnTwoEdges_20(self):
|
||||
p1 = self.mesh.Points[0].Vector
|
||||
p2 = self.mesh.Points[1].Vector
|
||||
p3 = self.mesh.Points[2].Vector
|
||||
self.mesh.splitFacet(0, (p1 + p3) / 2, (p1 + p2) / 2)
|
||||
self.assertFalse(self.mesh.hasNonManifolds())
|
||||
self.assertFalse(self.mesh.hasInvalidNeighbourhood())
|
||||
self.assertFalse(self.mesh.hasPointsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasFacetsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasCorruptedFacets())
|
||||
self.assertTrue(self.mesh.isSolid())
|
||||
|
||||
def testSplitFacetOnTwoEdges_5teps(self):
|
||||
Vec3d = FreeCAD.Vector
|
||||
for i in range(5):
|
||||
f = self.mesh.Facets[0]
|
||||
p1 = Vec3d(f.Points[0])
|
||||
p2 = Vec3d(f.Points[1])
|
||||
p3 = Vec3d(f.Points[2])
|
||||
self.mesh.splitFacet(0, (p1 + p3) / 2, (p2 + p3) / 2)
|
||||
|
||||
self.assertFalse(self.mesh.hasNonManifolds())
|
||||
self.assertFalse(self.mesh.hasInvalidNeighbourhood())
|
||||
self.assertFalse(self.mesh.hasPointsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasFacetsOutOfRange())
|
||||
self.assertFalse(self.mesh.hasCorruptedFacets())
|
||||
self.assertTrue(self.mesh.isSolid())
|
||||
|
||||
class MeshGeoTestCases(unittest.TestCase):
|
||||
def setUp(self):
|
||||
# set up a planar face with 2 triangles
|
||||
self.planarMesh = []
|
||||
def setUp(self):
|
||||
# set up a planar face with 2 triangles
|
||||
self.planarMesh = []
|
||||
|
||||
|
||||
def testIntersection(self):
|
||||
self.planarMesh.append( [0.9961,1.5413,4.3943] )
|
||||
self.planarMesh.append( [9.4796,10.024,-3.0937] )
|
||||
self.planarMesh.append( [1.4308,11.3841,2.6829] )
|
||||
self.planarMesh.append( [2.6493,2.2536,3.0679] )
|
||||
self.planarMesh.append( [13.1126,0.4857,-4.4417] )
|
||||
self.planarMesh.append( [10.2410,8.9040,-3.5002] )
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
f1 = planarMeshObject.Facets[0]
|
||||
f2 = planarMeshObject.Facets[1]
|
||||
res=f1.intersect(f2)
|
||||
self.failUnless(len(res) == 0)
|
||||
def testIntersection(self):
|
||||
self.planarMesh.append( [0.9961,1.5413,4.3943] )
|
||||
self.planarMesh.append( [9.4796,10.024,-3.0937] )
|
||||
self.planarMesh.append( [1.4308,11.3841,2.6829] )
|
||||
self.planarMesh.append( [2.6493,2.2536,3.0679] )
|
||||
self.planarMesh.append( [13.1126,0.4857,-4.4417] )
|
||||
self.planarMesh.append( [10.2410,8.9040,-3.5002] )
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
f1 = planarMeshObject.Facets[0]
|
||||
f2 = planarMeshObject.Facets[1]
|
||||
res=f1.intersect(f2)
|
||||
self.failUnless(len(res) == 0)
|
||||
|
||||
|
||||
def testIntersection2(self):
|
||||
self.planarMesh.append( [-16.097176,-29.891157,15.987688] )
|
||||
self.planarMesh.append( [-16.176304,-29.859991,15.947966] )
|
||||
self.planarMesh.append( [-16.071451,-29.900553,15.912505] )
|
||||
self.planarMesh.append( [-16.092241,-29.893408,16.020439] )
|
||||
self.planarMesh.append( [-16.007210,-29.926180,15.967641] )
|
||||
self.planarMesh.append( [-16.064457,-29.904951,16.090832] )
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
f1 = planarMeshObject.Facets[0]
|
||||
f2 = planarMeshObject.Facets[1]
|
||||
# does definitely NOT intersect
|
||||
res=f1.intersect(f2)
|
||||
self.failUnless(len(res) == 0)
|
||||
def testIntersection2(self):
|
||||
self.planarMesh.append( [-16.097176,-29.891157,15.987688] )
|
||||
self.planarMesh.append( [-16.176304,-29.859991,15.947966] )
|
||||
self.planarMesh.append( [-16.071451,-29.900553,15.912505] )
|
||||
self.planarMesh.append( [-16.092241,-29.893408,16.020439] )
|
||||
self.planarMesh.append( [-16.007210,-29.926180,15.967641] )
|
||||
self.planarMesh.append( [-16.064457,-29.904951,16.090832] )
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
f1 = planarMeshObject.Facets[0]
|
||||
f2 = planarMeshObject.Facets[1]
|
||||
# does definitely NOT intersect
|
||||
res=f1.intersect(f2)
|
||||
self.failUnless(len(res) == 0)
|
||||
|
||||
class PivyTestCases(unittest.TestCase):
|
||||
def setUp(self):
|
||||
# set up a planar face with 2 triangles
|
||||
self.planarMesh = []
|
||||
FreeCAD.newDocument("MeshTest")
|
||||
def setUp(self):
|
||||
# set up a planar face with 2 triangles
|
||||
self.planarMesh = []
|
||||
FreeCAD.newDocument("MeshTest")
|
||||
|
||||
def testRayPick(self):
|
||||
if not FreeCAD.GuiUp:
|
||||
return
|
||||
self.planarMesh.append( [-16.097176,-29.891157,15.987688] )
|
||||
self.planarMesh.append( [-16.176304,-29.859991,15.947966] )
|
||||
self.planarMesh.append( [-16.071451,-29.900553,15.912505] )
|
||||
self.planarMesh.append( [-16.092241,-29.893408,16.020439] )
|
||||
self.planarMesh.append( [-16.007210,-29.926180,15.967641] )
|
||||
self.planarMesh.append( [-16.064457,-29.904951,16.090832] )
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
def testRayPick(self):
|
||||
if not FreeCAD.GuiUp:
|
||||
return
|
||||
self.planarMesh.append( [-16.097176,-29.891157,15.987688] )
|
||||
self.planarMesh.append( [-16.176304,-29.859991,15.947966] )
|
||||
self.planarMesh.append( [-16.071451,-29.900553,15.912505] )
|
||||
self.planarMesh.append( [-16.092241,-29.893408,16.020439] )
|
||||
self.planarMesh.append( [-16.007210,-29.926180,15.967641] )
|
||||
self.planarMesh.append( [-16.064457,-29.904951,16.090832] )
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
|
||||
from pivy import coin; import FreeCADGui
|
||||
Mesh.show(planarMeshObject)
|
||||
view=FreeCADGui.ActiveDocument.ActiveView.getViewer()
|
||||
rp=coin.SoRayPickAction(view.getSoRenderManager().getViewportRegion())
|
||||
rp.setRay(coin.SbVec3f(-16.05,16.0,16.0),coin.SbVec3f(0,-1,0))
|
||||
rp.apply(view.getSoRenderManager().getSceneGraph())
|
||||
pp=rp.getPickedPoint()
|
||||
self.failUnless(pp != None)
|
||||
det=pp.getDetail()
|
||||
self.failUnless(det.getTypeId() == coin.SoFaceDetail.getClassTypeId())
|
||||
det=coin.cast(det,str(det.getTypeId().getName()))
|
||||
self.failUnless(det.getFaceIndex() == 1)
|
||||
from pivy import coin; import FreeCADGui
|
||||
Mesh.show(planarMeshObject)
|
||||
view=FreeCADGui.ActiveDocument.ActiveView.getViewer()
|
||||
rp=coin.SoRayPickAction(view.getSoRenderManager().getViewportRegion())
|
||||
rp.setRay(coin.SbVec3f(-16.05,16.0,16.0),coin.SbVec3f(0,-1,0))
|
||||
rp.apply(view.getSoRenderManager().getSceneGraph())
|
||||
pp=rp.getPickedPoint()
|
||||
self.failUnless(pp != None)
|
||||
det=pp.getDetail()
|
||||
self.failUnless(det.getTypeId() == coin.SoFaceDetail.getClassTypeId())
|
||||
det=coin.cast(det,str(det.getTypeId().getName()))
|
||||
self.failUnless(det.getFaceIndex() == 1)
|
||||
|
||||
def testPrimitiveCount(self):
|
||||
if not FreeCAD.GuiUp:
|
||||
return
|
||||
self.planarMesh.append( [-16.097176,-29.891157,15.987688] )
|
||||
self.planarMesh.append( [-16.176304,-29.859991,15.947966] )
|
||||
self.planarMesh.append( [-16.071451,-29.900553,15.912505] )
|
||||
self.planarMesh.append( [-16.092241,-29.893408,16.020439] )
|
||||
self.planarMesh.append( [-16.007210,-29.926180,15.967641] )
|
||||
self.planarMesh.append( [-16.064457,-29.904951,16.090832] )
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
def testPrimitiveCount(self):
|
||||
if not FreeCAD.GuiUp:
|
||||
return
|
||||
self.planarMesh.append( [-16.097176,-29.891157,15.987688] )
|
||||
self.planarMesh.append( [-16.176304,-29.859991,15.947966] )
|
||||
self.planarMesh.append( [-16.071451,-29.900553,15.912505] )
|
||||
self.planarMesh.append( [-16.092241,-29.893408,16.020439] )
|
||||
self.planarMesh.append( [-16.007210,-29.926180,15.967641] )
|
||||
self.planarMesh.append( [-16.064457,-29.904951,16.090832] )
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
|
||||
from pivy import coin; import FreeCADGui
|
||||
Mesh.show(planarMeshObject)
|
||||
view=FreeCADGui.ActiveDocument.ActiveView
|
||||
view.setAxisCross(False)
|
||||
pc=coin.SoGetPrimitiveCountAction()
|
||||
pc.apply(view.getSceneGraph())
|
||||
self.failUnless(pc.getTriangleCount() == 2)
|
||||
#self.failUnless(pc.getPointCount() == 6)
|
||||
from pivy import coin; import FreeCADGui
|
||||
Mesh.show(planarMeshObject)
|
||||
view=FreeCADGui.ActiveDocument.ActiveView
|
||||
view.setAxisCross(False)
|
||||
pc=coin.SoGetPrimitiveCountAction()
|
||||
pc.apply(view.getSceneGraph())
|
||||
self.failUnless(pc.getTriangleCount() == 2)
|
||||
#self.failUnless(pc.getPointCount() == 6)
|
||||
|
||||
def tearDown(self):
|
||||
#closing doc
|
||||
FreeCAD.closeDocument("MeshTest")
|
||||
def tearDown(self):
|
||||
#closing doc
|
||||
FreeCAD.closeDocument("MeshTest")
|
||||
|
||||
# Threads
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
|
||||
|
||||
namespace Part {
|
||||
const App::PropertyQuantityConstraint::Constraints apexRange = {0.0,90.0,0.1};
|
||||
const App::PropertyQuantityConstraint::Constraints apexRange = {-90.0,90.0,0.1};
|
||||
const App::PropertyQuantityConstraint::Constraints torusRangeV = {-180.0,180.0,1.0};
|
||||
const App::PropertyQuantityConstraint::Constraints angleRangeU = {0.0,360.0,1.0};
|
||||
const App::PropertyQuantityConstraint::Constraints angleRangeV = {-90.0,90.0,1.0};
|
||||
@@ -801,7 +801,7 @@ Helix::Helix(void)
|
||||
Height.setConstraints(&quantityRange);
|
||||
ADD_PROPERTY_TYPE(Radius,(1.0),"Helix",App::Prop_None,"The radius of the helix");
|
||||
Radius.setConstraints(&quantityRange);
|
||||
ADD_PROPERTY_TYPE(Angle,(0.0),"Helix",App::Prop_None,"If angle is > 0 a conical otherwise a cylindircal surface is used");
|
||||
ADD_PROPERTY_TYPE(Angle,(0.0),"Helix",App::Prop_None,"If angle is != 0 a conical otherwise a cylindircal surface is used");
|
||||
Angle.setConstraints(&apexRange);
|
||||
ADD_PROPERTY_TYPE(LocalCoord,(long(0)),"Coordinate System",App::Prop_None,"Orientation of the local coordinate system of the helix");
|
||||
LocalCoord.setEnums(LocalCSEnums);
|
||||
|
||||
@@ -261,7 +261,7 @@ DlgPrimitives::DlgPrimitives(QWidget* parent, Part::Primitive* feature)
|
||||
ui->helixPitch->setRange(0, INT_MAX);
|
||||
ui->helixHeight->setRange(0, INT_MAX);
|
||||
ui->helixRadius->setRange(0, INT_MAX);
|
||||
ui->helixAngle->setRange(0, 90);
|
||||
ui->helixAngle->setRange(-90, 90);
|
||||
// circle
|
||||
ui->circleRadius->setRange(0, INT_MAX);
|
||||
ui->circleAngle0->setRange(0, 360);
|
||||
@@ -560,7 +560,7 @@ DlgPrimitives::DlgPrimitives(QWidget* parent, Part::Primitive* feature)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Destroys the object and frees any allocated resources
|
||||
*/
|
||||
DlgPrimitives::~DlgPrimitives()
|
||||
@@ -1937,7 +1937,7 @@ TaskPrimitives::~TaskPrimitives()
|
||||
}
|
||||
|
||||
QDialogButtonBox::StandardButtons TaskPrimitives::getStandardButtons() const
|
||||
{
|
||||
{
|
||||
return QDialogButtonBox::Close|
|
||||
QDialogButtonBox::Ok;
|
||||
}
|
||||
|
||||
@@ -515,7 +515,7 @@ class ObjectSlot(PathOp.ObjectOp):
|
||||
(p1, p2) = pnts
|
||||
begExt = obj.ExtendPathStart.Value
|
||||
endExt = obj.ExtendPathEnd.Value
|
||||
# invert endExt, begExt args to apply extentions to correct ends
|
||||
# invert endExt, begExt args to apply extensions to correct ends
|
||||
# XY geom is postitive CCW; Gcode postitive CW
|
||||
pnts = self._extendArcSlot(p1, p2, self.arcCenter, endExt, begExt)
|
||||
|
||||
@@ -925,7 +925,7 @@ class ObjectSlot(PathOp.ObjectOp):
|
||||
# Check that all Z values are equal (isRoughly same)
|
||||
if (abs(z1 - z2) > tolrnc or
|
||||
abs(z1 - z3) > tolrnc ):
|
||||
# abs(z2 - z3) > tolrnc): 3rd test reduntant.
|
||||
# abs(z2 - z3) > tolrnc): 3rd test redundant.
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -1230,8 +1230,8 @@ class ObjectSlot(PathOp.ObjectOp):
|
||||
|
||||
|
||||
# Convert extension to radians; make a generic chord ( line ) on XY plane from the x axis
|
||||
# rotate and shift into place so it has same vertices as the required arc extention
|
||||
# adjust rotation angle to provide +ve or -ve extention as needed
|
||||
# rotate and shift into place so it has same vertices as the required arc extension
|
||||
# adjust rotation angle to provide +ve or -ve extension as needed
|
||||
origin = FreeCAD.Vector(0.0, 0.0, 0.0)
|
||||
if begExt:
|
||||
ExtRadians = abs(begExt / self.newRadius)
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
# include <BRepAdaptor_Curve.hxx>
|
||||
# include <Precision.hxx>
|
||||
|
||||
# include <QDebug>
|
||||
# include <QGraphicsScene>
|
||||
# include <QGraphicsSceneMouseEvent>
|
||||
# include <QPainter>
|
||||
@@ -48,7 +49,6 @@
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Parameter.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/Control.h>
|
||||
#include <Gui/Tools.h>
|
||||
#include <string>
|
||||
|
||||
@@ -74,7 +74,6 @@
|
||||
#include "QGIViewDimension.h"
|
||||
#include "QGVPage.h"
|
||||
#include "MDIViewPage.h"
|
||||
#include "TaskBalloon.h"
|
||||
|
||||
//TODO: hide the Qt coord system (+y down).
|
||||
|
||||
@@ -140,8 +139,11 @@ void QGIBalloonLabel::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
|
||||
|
||||
void QGIBalloonLabel::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
|
||||
{
|
||||
if(scene() && this == scene()->mouseGrabberItem()) {
|
||||
Q_EMIT dragFinished();
|
||||
if (QLineF(event->screenPos(), event->buttonDownScreenPos(Qt::LeftButton))
|
||||
.length() > 0) {
|
||||
if (scene() && this == scene()->mouseGrabberItem()) {
|
||||
Q_EMIT dragFinished();
|
||||
}
|
||||
}
|
||||
m_ctrl = false;
|
||||
m_drag = false;
|
||||
@@ -152,13 +154,17 @@ void QGIBalloonLabel::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * event)
|
||||
{
|
||||
QGIViewBalloon* qgivBalloon = dynamic_cast<QGIViewBalloon*>(parentItem());
|
||||
if (qgivBalloon == nullptr) {
|
||||
qWarning() << "QGIBalloonLabel::mouseDoubleClickEvent: No parent item";
|
||||
return;
|
||||
}
|
||||
auto ViewProvider = static_cast<ViewProviderBalloon*>(qgivBalloon->getViewProvider(qgivBalloon->getViewObject()));
|
||||
|
||||
auto ViewProvider = dynamic_cast<ViewProviderBalloon*>(qgivBalloon->getViewProvider(qgivBalloon->getViewObject()));
|
||||
if (ViewProvider == nullptr) {
|
||||
qWarning() << "QGIBalloonLabel::mouseDoubleClickEvent: No valid view provider";
|
||||
return;
|
||||
}
|
||||
Gui::Control().showDialog(new TaskDlgBalloon(qgivBalloon, ViewProvider));
|
||||
|
||||
ViewProvider->startDefaultEditMode();
|
||||
QGraphicsItem::mouseDoubleClickEvent(event);
|
||||
}
|
||||
|
||||
@@ -482,7 +488,7 @@ void QGIViewBalloon::balloonLabelDragged(bool ctrl)
|
||||
m_saveOffset = dvb->getOriginOffset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double scale = 1.0;
|
||||
DrawView* balloonParent = getSourceView();
|
||||
if (balloonParent != nullptr) {
|
||||
@@ -499,7 +505,7 @@ void QGIViewBalloon::balloonLabelDragged(bool ctrl)
|
||||
if (ctrl) {
|
||||
Base::Vector3d pos(x, -y, 0.0);
|
||||
Base::Vector3d newOrg = pos - m_saveOffset;
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.OriginX = %f",
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.OriginX = %f",
|
||||
dvb->getNameInDocument(), newOrg.x);
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.OriginY = %f",
|
||||
dvb->getNameInDocument(), newOrg.y);
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
# include <BRepAdaptor_Curve.hxx>
|
||||
# include <Precision.hxx>
|
||||
|
||||
# include <QApplication>
|
||||
# include <QDebug>
|
||||
# include <QGraphicsScene>
|
||||
# include <QGraphicsSceneMouseEvent>
|
||||
# include <QPainter>
|
||||
@@ -52,7 +54,6 @@
|
||||
#include <Base/Parameter.h>
|
||||
#include <Base/UnitsApi.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/Control.h>
|
||||
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
|
||||
@@ -76,7 +77,6 @@
|
||||
#include "QGIViewDimension.h"
|
||||
#include "ViewProviderDimension.h"
|
||||
#include "DrawGuiUtil.h"
|
||||
#include "TaskDimension.h"
|
||||
|
||||
#define NORMAL 0
|
||||
#define PRE 1
|
||||
@@ -149,10 +149,7 @@ void QGIDatumLabel::mousePressEvent(QGraphicsSceneMouseEvent * event)
|
||||
m_ctrl = true;
|
||||
}
|
||||
|
||||
if(scene() && this == scene()->mouseGrabberItem()) {
|
||||
Q_EMIT dragFinished();
|
||||
}
|
||||
QGraphicsItem::mousePressEvent(event);
|
||||
QGraphicsItem::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void QGIDatumLabel::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
|
||||
@@ -164,8 +161,11 @@ void QGIDatumLabel::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
|
||||
{
|
||||
// Base::Console().Message("QGIDL::mouseReleaseEvent()\n");
|
||||
m_ctrl = false;
|
||||
if(scene() && this == scene()->mouseGrabberItem()) {
|
||||
Q_EMIT dragFinished();
|
||||
if (QLineF(event->screenPos(), event->buttonDownScreenPos(Qt::LeftButton))
|
||||
.length() > 0) {
|
||||
if (scene() && this == scene()->mouseGrabberItem()) {
|
||||
Q_EMIT dragFinished();
|
||||
}
|
||||
}
|
||||
|
||||
QGraphicsItem::mouseReleaseEvent(event);
|
||||
@@ -175,13 +175,17 @@ void QGIDatumLabel::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
|
||||
{
|
||||
QGIViewDimension* qgivDimension = dynamic_cast<QGIViewDimension*>(parentItem());
|
||||
if (qgivDimension == nullptr) {
|
||||
qWarning() << "QGIDatumLabel::mouseDoubleClickEvent: No parent item";
|
||||
return;
|
||||
}
|
||||
auto ViewProvider = static_cast<ViewProviderDimension*>(qgivDimension->getViewProvider(qgivDimension->getViewObject()));
|
||||
|
||||
auto ViewProvider = dynamic_cast<ViewProviderDimension*>(qgivDimension->getViewProvider(qgivDimension->getViewObject()));
|
||||
if (ViewProvider == nullptr) {
|
||||
qWarning() << "QGIDatumLabel::mouseDoubleClickEvent: No valid view provider";
|
||||
return;
|
||||
}
|
||||
Gui::Control().showDialog(new TaskDlgDimension(qgivDimension, ViewProvider));
|
||||
|
||||
ViewProvider->startDefaultEditMode();
|
||||
QGraphicsItem::mouseDoubleClickEvent(event);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,14 +63,12 @@ public:
|
||||
virtual void unsetEdit(int ModNum);
|
||||
virtual bool doubleClicked(void);
|
||||
virtual bool canDelete(App::DocumentObject* obj) const;
|
||||
void startDefaultEditMode();
|
||||
|
||||
virtual TechDraw::DrawViewBalloon* getViewObject() const;
|
||||
|
||||
protected:
|
||||
virtual void handleChangedPropertyType(Base::XMLReader &reader, const char *TypeName, App::Property * prop);
|
||||
|
||||
private:
|
||||
void startDefaultEditMode();
|
||||
};
|
||||
|
||||
} // namespace TechDrawGui
|
||||
|
||||
@@ -76,6 +76,7 @@ public:
|
||||
virtual bool setEdit(int ModNum);
|
||||
virtual void unsetEdit(int ModNum);
|
||||
virtual bool doubleClicked(void);
|
||||
void startDefaultEditMode();
|
||||
|
||||
virtual TechDraw::DrawViewDimension* getViewObject() const;
|
||||
|
||||
@@ -89,9 +90,6 @@ public:
|
||||
protected:
|
||||
virtual void handleChangedPropertyType(Base::XMLReader &reader, const char *TypeName, App::Property * prop);
|
||||
|
||||
private:
|
||||
void startDefaultEditMode();
|
||||
|
||||
private:
|
||||
static const char *StandardAndStyleEnums[];
|
||||
static const char *RenderingExtentEnums[];
|
||||
|
||||
Reference in New Issue
Block a user