diff --git a/src/Mod/Mesh/App/Mesh.cpp b/src/Mod/Mesh/App/Mesh.cpp
index f3347c8b32..26b7666be7 100644
--- a/src/Mod/Mesh/App/Mesh.cpp
+++ b/src/Mod/Mesh/App/Mesh.cpp
@@ -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();
diff --git a/src/Mod/Mesh/App/Mesh.h b/src/Mod/Mesh/App/Mesh.h
index bcb2148948..1086ee01a5 100644
--- a/src/Mod/Mesh/App/Mesh.h
+++ b/src/Mod/Mesh/App/Mesh.h
@@ -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;
diff --git a/src/Mod/Mesh/App/MeshPy.xml b/src/Mod/Mesh/App/MeshPy.xml
index a43402f289..fdaad6cf92 100644
--- a/src/Mod/Mesh/App/MeshPy.xml
+++ b/src/Mod/Mesh/App/MeshPy.xml
@@ -229,7 +229,7 @@ for c in mesh.getSeparatecomponents():
Check if the mesh has non-manifolds
-
+
Remove non-manifolds
@@ -284,7 +284,27 @@ for c in mesh.getSeparatecomponents():
Remove points with invalid coordinates (NaN)
-
+
+
+ Check if the mesh has invalid neighbourhood indices
+
+
+
+
+ Check if the mesh has point indices that are out of range
+
+
+
+
+ Check if the mesh has facet indices that are out of range
+
+
+
+
+ Check if the mesh has corrupted facets
+
+
+
Get the number of topologic independent areas
diff --git a/src/Mod/Mesh/App/MeshPyImp.cpp b/src/Mod/Mesh/App/MeshPyImp.cpp
index 394a2ed88e..c984ffe3a8 100644
--- a/src/Mod/Mesh/App/MeshPyImp.cpp
+++ b/src/Mod/Mesh/App/MeshPyImp.cpp
@@ -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, ""))
diff --git a/src/Mod/Mesh/App/MeshTestsApp.py b/src/Mod/Mesh/App/MeshTestsApp.py
index f91f0f41eb..449d91a1f0 100644
--- a/src/Mod/Mesh/App/MeshTestsApp.py
+++ b/src/Mod/Mesh/App/MeshTestsApp.py
@@ -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
diff --git a/src/Mod/Part/App/PrimitiveFeature.cpp b/src/Mod/Part/App/PrimitiveFeature.cpp
index 4841f871f6..119078c35f 100644
--- a/src/Mod/Part/App/PrimitiveFeature.cpp
+++ b/src/Mod/Part/App/PrimitiveFeature.cpp
@@ -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);
diff --git a/src/Mod/Part/Gui/DlgPrimitives.cpp b/src/Mod/Part/Gui/DlgPrimitives.cpp
index 9fef631f58..f1a410bfbe 100644
--- a/src/Mod/Part/Gui/DlgPrimitives.cpp
+++ b/src/Mod/Part/Gui/DlgPrimitives.cpp
@@ -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;
}
diff --git a/src/Mod/Path/PathScripts/PathSlot.py b/src/Mod/Path/PathScripts/PathSlot.py
index 32ea97cf15..d5c40c019d 100644
--- a/src/Mod/Path/PathScripts/PathSlot.py
+++ b/src/Mod/Path/PathScripts/PathSlot.py
@@ -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)
diff --git a/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp b/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp
index fb094498ce..e5fee48d14 100644
--- a/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp
+++ b/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp
@@ -31,6 +31,7 @@
# include
# include
+ # include
# include
# include
# include
@@ -48,7 +49,6 @@
#include
#include
#include
-#include
#include
#include
@@ -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(parentItem());
if (qgivBalloon == nullptr) {
+ qWarning() << "QGIBalloonLabel::mouseDoubleClickEvent: No parent item";
return;
}
- auto ViewProvider = static_cast(qgivBalloon->getViewProvider(qgivBalloon->getViewObject()));
+
+ auto ViewProvider = dynamic_cast(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);
diff --git a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp
index 2bef981208..c23ba6d2ec 100644
--- a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp
+++ b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp
@@ -36,6 +36,8 @@
# include
# include
+ # include
+ # include
# include
# include
# include
@@ -52,7 +54,6 @@
#include
#include
#include
-#include
#include
@@ -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(parentItem());
if (qgivDimension == nullptr) {
+ qWarning() << "QGIDatumLabel::mouseDoubleClickEvent: No parent item";
return;
}
- auto ViewProvider = static_cast(qgivDimension->getViewProvider(qgivDimension->getViewObject()));
+
+ auto ViewProvider = dynamic_cast(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);
}
diff --git a/src/Mod/TechDraw/Gui/ViewProviderBalloon.h b/src/Mod/TechDraw/Gui/ViewProviderBalloon.h
index 3dcc7580fb..9dcef1b50f 100644
--- a/src/Mod/TechDraw/Gui/ViewProviderBalloon.h
+++ b/src/Mod/TechDraw/Gui/ViewProviderBalloon.h
@@ -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
diff --git a/src/Mod/TechDraw/Gui/ViewProviderDimension.h b/src/Mod/TechDraw/Gui/ViewProviderDimension.h
index 6bc047e1aa..156369a840 100644
--- a/src/Mod/TechDraw/Gui/ViewProviderDimension.h
+++ b/src/Mod/TechDraw/Gui/ViewProviderDimension.h
@@ -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[];