Patches FreeCAD to work with OpenCascade v7.6.0 using upstream commits that resolve the issue. This patch can be removed once FreeCAD v0.20.0 is released as it will be compatible with OpenCascade v7.6.0 Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/6f3b00d67ec0bd0072b7b493e2a38d2a2e3af27d.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/77b198048a63f1e9ca15eef64c8042d599a14cf3.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/9b4db7e06472bf5550d0b7627b28b425bfcc8470.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/74639da997d5f2e53f001d9f256be86ceee901f5.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/c9d17ebde2400f83d1e1e799bdb0a7f85a0da96d.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/442c8d52a1989da8f17d60fafea5b81d79cbf0ab.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/8e6dab209ee59be61d83a0ff249283a8809fa917.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/0f3b5d275070477b7cd2bbfa2dc930135448fb0c.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/08d46b5f882420c8d4066427fcc8dab5b1882097.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/51e4366085e59a9b511f7160d66493e9b3dfc7d8.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/c2c5ae1bf0c571270ecacf257a51e9b064fc609a.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/302568d177ddde171c28eaca89e8b4a49466974f.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/66d3dd897f63c2e4f8ffd6eced730c6a3372ad51.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/03be15cc6b460ab62548142287eb9f677f463a44.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/f628050732cc5d1d49fc18282ed508ca3061bb10.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/16ff933b09176d83fb0785e74f36038311f0eaeb.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/03da9d3501c6b596ad1828b99cb8d923cea56485.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/fecf9c2e8492ddab0858b4af23b56da36bff6f6a.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/8453d415150f289d36dfe4cbe6b91dfc512e82fe.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/3131b97aa88736ac628428a8ceb025d9b7a8a965.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/5b4c246944c72459016efff6ae903ac66c090991.patch Patch-Source:https://github.com/FreeCAD/FreeCAD/commit/f55c46cc86344a6d7389156c015194f7d0fd2b63.patch From 6f3b00d67ec0bd0072b7b493e2a38d2a2e3af27d Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 11 Oct 2021 00:30:22 +0200 Subject: [PATCH] SMESH: port to OCCT 7.6 --- .../src/NETGENPlugin/NETGENPlugin_Mesher.cpp | 7 +++++++ .../salomesmesh/src/SMESH/SMESH_MeshAlgos.cpp | 7 +++++-- .../src/StdMeshers/StdMeshers_Adaptive1D.cpp | 14 ++++++++++++++ .../src/StdMeshers/StdMeshers_Quadrangle_2D.cpp | 2 +- .../src/StdMeshers/StdMeshers_ViscousLayers.cpp | 8 ++++++++ 5 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/3rdParty/salomesmesh/src/NETGENPlugin/NETGENPlugin_Mesher.cpp b/src/3rdParty/salomesmesh/src/NETGENPlugin/NETGENPlugin_Mesher.cpp index cd6f0b2b075..ea83984b976 100644 --- a/src/3rdParty/salomesmesh/src/NETGENPlugin/NETGENPlugin_Mesher.cpp +++ b/src/3rdParty/salomesmesh/src/NETGENPlugin/NETGENPlugin_Mesher.cpp @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -700,7 +701,13 @@ double NETGENPlugin_Mesher::GetDefaultMinSize(const TopoDS_Shape& geom, BRep_Tool::Triangulation ( TopoDS::Face( fExp.Current() ), loc); if ( triangulation.IsNull() ) continue; const double fTol = BRep_Tool::Tolerance( TopoDS::Face( fExp.Current() )); +#if OCC_VERSION_HEX < 0x070600 const TColgp_Array1OfPnt& points = triangulation->Nodes(); +#else + auto points = [&triangulation](Standard_Integer index) { + return triangulation->Node(index); + }; +#endif const Poly_Array1OfTriangle& trias = triangulation->Triangles(); for ( int iT = trias.Lower(); iT <= trias.Upper(); ++iT ) { diff --git a/src/3rdParty/salomesmesh/src/SMESH/SMESH_MeshAlgos.cpp b/src/3rdParty/salomesmesh/src/SMESH/SMESH_MeshAlgos.cpp index 5a07308310e..fbb1b250087 100644 --- a/src/3rdParty/salomesmesh/src/SMESH/SMESH_MeshAlgos.cpp +++ b/src/3rdParty/salomesmesh/src/SMESH/SMESH_MeshAlgos.cpp @@ -38,10 +38,13 @@ #include #include #include -#include -#include +#include +#include #include #include +#include +#include +#include #include #include diff --git a/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Adaptive1D.cpp b/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Adaptive1D.cpp index 88970f36b55..7c51601c7bb 100644 --- a/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Adaptive1D.cpp +++ b/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Adaptive1D.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -318,13 +319,26 @@ namespace // internal utils { myFaceTol = SMESH_MesherHelper::MaxTolerance( face ); myTree = triaTree; +#if OCC_VERSION_HEX < 0x070600 myNodes = & tr->Nodes(); +#else + TColgp_Array1OfPnt* trNodes = new TColgp_Array1OfPnt( 1, tr->NbNodes() ); + for (Standard_Integer i = myNodes->Lower(); i <= myNodes->Upper(); i++) + { + trNodes->SetValue(i, tr->Node(i)); + } + myNodes = trNodes; + myOwnNodes = true; +#endif myPolyTrias = & tr->Triangles(); myTriasDeflection = tr->Deflection(); if ( !loc.IsIdentity() ) // transform nodes if necessary { TColgp_Array1OfPnt* trsfNodes = new TColgp_Array1OfPnt( myNodes->Lower(), myNodes->Upper() ); trsfNodes->Assign( *myNodes ); +#if OCC_VERSION_HEX >= 0x070600 + delete myNodes; // it's already a copy +#endif myNodes = trsfNodes; myOwnNodes = true; const gp_Trsf& trsf = loc; diff --git a/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Quadrangle_2D.cpp b/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Quadrangle_2D.cpp index f7ac411d9a5..5d5c15c3661 100644 --- a/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Quadrangle_2D.cpp +++ b/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Quadrangle_2D.cpp @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_ViscousLayers.cpp b/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_ViscousLayers.cpp index 8ee0e268325..e9f46183059 100644 --- a/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_ViscousLayers.cpp +++ b/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_ViscousLayers.cpp @@ -44,7 +44,10 @@ #include "SMESH_subMeshEventListener.hxx" #include "StdMeshers_FaceSide.hxx" +#include +#if OCC_VERSION_HEX < 0x070600 #include +#endif #include #include #include @@ -1340,8 +1343,13 @@ namespace VISCOUS_3D //case GeomAbs_SurfaceOfExtrusion: case GeomAbs_OffsetSurface: { +#if OCC_VERSION_HEX < 0x070600 Handle(Adaptor3d_HSurface) base = surface.BasisSurface(); return getRovolutionAxis( base->Surface(), axis ); +#else + Handle(Adaptor3d_Surface) base = surface.BasisSurface(); + return getRovolutionAxis( *base, axis ); +#endif } default: return false; } From 77b198048a63f1e9ca15eef64c8042d599a14cf3 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 7 Oct 2021 11:10:12 +0200 Subject: [PATCH] SMESH: [skip ci] do not undefine the guard of a header file --- src/3rdParty/salomesmesh/src/SMESH/SMESH_Mesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdParty/salomesmesh/src/SMESH/SMESH_Mesh.cpp b/src/3rdParty/salomesmesh/src/SMESH/SMESH_Mesh.cpp index 24dc2d00a67..8e78712f4a4 100644 --- a/src/3rdParty/salomesmesh/src/SMESH/SMESH_Mesh.cpp +++ b/src/3rdParty/salomesmesh/src/SMESH/SMESH_Mesh.cpp @@ -64,7 +64,7 @@ #include -#undef _Precision_HeaderFile +//#undef _Precision_HeaderFile #include #include #include From 9b4db7e06472bf5550d0b7627b28b425bfcc8470 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 15:32:41 +0200 Subject: [PATCH] Part: in Part.getFacets() use functions of Tools class --- src/Mod/Part/App/AppPartPy.cpp | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/Mod/Part/App/AppPartPy.cpp b/src/Mod/Part/App/AppPartPy.cpp index 08e3e9fd470..f16ae7e221a 100644 --- a/src/Mod/Part/App/AppPartPy.cpp +++ b/src/Mod/Part/App/AppPartPy.cpp @@ -134,6 +134,7 @@ #include "PartFeature.h" #include "PartPyCXX.h" #include "modelRefine.h" +#include "Tools.h" #ifdef FCUseFreeType # include "FT2FC.h" @@ -804,33 +805,24 @@ class Module : public Py::ExtensionModule auto theShape = static_cast(shape)->getTopoShapePtr()->getShape(); for (TopExp_Explorer ex(theShape, TopAbs_FACE); ex.More(); ex.Next()) { TopoDS_Face currentFace = TopoDS::Face(ex.Current()); - TopLoc_Location loc; - Handle(Poly_Triangulation) facets = BRep_Tool::Triangulation(currentFace, loc); - const TopAbs_Orientation anOrientation = currentFace.Orientation(); - bool flip = (anOrientation == TopAbs_REVERSED); - if (!facets.IsNull()) { - const TColgp_Array1OfPnt& nodes = facets->Nodes(); - const Poly_Array1OfTriangle& triangles = facets->Triangles(); - for (int i = 1; i <= triangles.Length(); i++) { + + std::vector points; + std::vector facets; + if (Tools::getTriangulation(currentFace, points, facets)) { + for (const auto& it : facets) { Standard_Integer n1,n2,n3; - triangles(i).Get(n1, n2, n3); - gp_Pnt p1 = nodes(n1); - gp_Pnt p2 = nodes(n2); - gp_Pnt p3 = nodes(n3); - p1.Transform(loc.Transformation()); - p2.Transform(loc.Transformation()); - p3.Transform(loc.Transformation()); + it.Get(n1, n2, n3); + + gp_Pnt p1 = points[n1]; + gp_Pnt p2 = points[n2]; + gp_Pnt p3 = points[n3]; + // TODO: verify if tolerance should be hard coded if (!p1.IsEqual(p2, 0.01) && !p2.IsEqual(p3, 0.01) && !p3.IsEqual(p1, 0.01)) { PyObject *t1 = PyTuple_Pack(3, PyFloat_FromDouble(p1.X()), PyFloat_FromDouble(p1.Y()), PyFloat_FromDouble(p1.Z())); PyObject *t2 = PyTuple_Pack(3, PyFloat_FromDouble(p2.X()), PyFloat_FromDouble(p2.Y()), PyFloat_FromDouble(p2.Z())); PyObject *t3 = PyTuple_Pack(3, PyFloat_FromDouble(p3.X()), PyFloat_FromDouble(p3.Y()), PyFloat_FromDouble(p3.Z())); - if (flip) { - list.append(Py::asObject(PyTuple_Pack(3, t2, t1, t3))); - } - else { - list.append(Py::asObject(PyTuple_Pack(3, t1, t2, t3))); - } + list.append(Py::asObject(PyTuple_Pack(3, t1, t2, t3))); } } } From 74639da997d5f2e53f001d9f256be86ceee901f5 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Oct 2021 13:49:02 +0200 Subject: [PATCH] OCCT: port FreeCAD sources to version 7.6 SMESH is not yet ported Although FreeCAD code compiles with OCCT 7.6 it doesn't work at the moment --- src/Mod/Drawing/App/DrawingExport.cpp | 11 ++- src/Mod/Drawing/App/ProjectionAlgos.cpp | 3 - src/Mod/Import/App/ImpExpDxf.cpp | 9 +- .../App/GeomPlate/CurveConstraintPyImp.cpp | 41 +++++++++- src/Mod/Part/App/Geometry.cpp | 7 +- src/Mod/Part/App/PartFeatures.cpp | 22 ++--- src/Mod/Part/App/TopoShape.cpp | 82 ++++++------------- src/Mod/Part/App/TopoShapeFacePyImp.cpp | 10 +++ src/Mod/Part/App/TopoShapeWirePyImp.cpp | 6 +- src/Mod/Part/Gui/TaskCheckGeometry.cpp | 6 +- src/Mod/Part/Gui/ViewProviderExt.cpp | 17 ++++ src/Mod/Path/App/AppPathPy.cpp | 5 +- src/Mod/TechDraw/App/Geometry.cpp | 12 ++- 13 files changed, 138 insertions(+), 93 deletions(-) diff --git a/src/Mod/Drawing/App/DrawingExport.cpp b/src/Mod/Drawing/App/DrawingExport.cpp index b87891ed507..7572be417cf 100644 --- a/src/Mod/Drawing/App/DrawingExport.cpp +++ b/src/Mod/Drawing/App/DrawingExport.cpp @@ -64,10 +64,7 @@ #include #include -#include #include -#include -#include #include #include #include @@ -75,11 +72,19 @@ #include #include #include +#include +#if OCC_VERSION_HEX < 0x070600 +#include +#endif #include "DrawingExport.h" #include #include +#if OCC_VERSION_HEX >= 0x070600 +using BRepAdaptor_HCurve = BRepAdaptor_Curve; +#endif + using namespace Drawing; using namespace std; diff --git a/src/Mod/Drawing/App/ProjectionAlgos.cpp b/src/Mod/Drawing/App/ProjectionAlgos.cpp index 9afae7e9c00..da03d490579 100644 --- a/src/Mod/Drawing/App/ProjectionAlgos.cpp +++ b/src/Mod/Drawing/App/ProjectionAlgos.cpp @@ -61,10 +61,7 @@ #include #include #include -#include #include -#include -#include #include #include #include diff --git a/src/Mod/Import/App/ImpExpDxf.cpp b/src/Mod/Import/App/ImpExpDxf.cpp index 09827bd9285..dcd88ef1384 100644 --- a/src/Mod/Import/App/ImpExpDxf.cpp +++ b/src/Mod/Import/App/ImpExpDxf.cpp @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -47,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +55,9 @@ #include #include #include +#if OCC_VERSION_HEX < 0x070600 +#include +#endif #include #include @@ -68,6 +71,10 @@ using namespace Import; +#if OCC_VERSION_HEX >= 0x070600 +using BRepAdaptor_HCurve = BRepAdaptor_Curve; +#endif + //****************************************************************************** // reading diff --git a/src/Mod/Part/App/GeomPlate/CurveConstraintPyImp.cpp b/src/Mod/Part/App/GeomPlate/CurveConstraintPyImp.cpp index 3271f3651a8..b63227d5374 100644 --- a/src/Mod/Part/App/GeomPlate/CurveConstraintPyImp.cpp +++ b/src/Mod/Part/App/GeomPlate/CurveConstraintPyImp.cpp @@ -24,10 +24,13 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include -# include # include -# include # include +# include +# if OCC_VERSION_HEX < 0x070600 +# include +# include +# endif #endif #include "GeomPlate/CurveConstraintPy.h" @@ -76,6 +79,16 @@ int CurveConstraintPy::PyInit(PyObject* args, PyObject* kwds) return -1; } +#if OCC_VERSION_HEX >= 0x070600 + Handle(Adaptor3d_Curve) hCurve; + if (curve->getTypeId().isDerivedFrom(GeomTrimmedCurve::getClassTypeId())) { + GeomTrimmedCurve* trim = static_cast(curve); + hCurve = new GeomAdaptor_Curve(handle, trim->getFirstParameter(), trim->getLastParameter()); + } + else { + hCurve = new GeomAdaptor_Curve(handle); + } +#else Handle(Adaptor3d_HCurve) hCurve; if (curve->getTypeId().isDerivedFrom(GeomTrimmedCurve::getClassTypeId())) { GeomTrimmedCurve* trim = static_cast(curve); @@ -86,6 +99,7 @@ int CurveConstraintPy::PyInit(PyObject* args, PyObject* kwds) GeomAdaptor_Curve adapt(handle); hCurve = new GeomAdaptor_HCurve(adapt); } +#endif ptr.reset(new GeomPlate_CurveConstraint(hCurve, order, nbPts, tolDist, tolAng, tolCurv)); } @@ -212,11 +226,15 @@ PyObject* CurveConstraintPy::curve3d(PyObject *args) return nullptr; try { - Handle(Adaptor3d_HCurve) hAdapt = getGeomPlate_CurveConstraintPtr()->Curve3d(); + auto hAdapt = getGeomPlate_CurveConstraintPtr()->Curve3d(); if (hAdapt.IsNull()) Py_Return; +#if OCC_VERSION_HEX >= 0x070600 + const Adaptor3d_Curve& a3d = *hAdapt; +#else const Adaptor3d_Curve& a3d = hAdapt->Curve(); +#endif std::unique_ptr ptr(Part::makeFromCurveAdaptor(a3d)); return ptr->getPyObject(); } @@ -282,6 +300,16 @@ PyObject* CurveConstraintPy::setProjectedCurve(PyObject *args) return nullptr; } +#if OCC_VERSION_HEX >= 0x070600 + Handle(Adaptor2d_Curve2d) hCurve; + if (handle->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) { + Handle(Geom2d_TrimmedCurve) aTC (Handle(Geom2d_TrimmedCurve)::DownCast (handle)); + hCurve = new Geom2dAdaptor_Curve(handle, aTC->FirstParameter(), aTC->LastParameter()); + } + else { + hCurve = new Geom2dAdaptor_Curve(handle); + } +#else Handle(Adaptor2d_HCurve2d) hCurve; if (handle->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) { Handle(Geom2d_TrimmedCurve) aTC (Handle(Geom2d_TrimmedCurve)::DownCast (handle)); @@ -292,6 +320,7 @@ PyObject* CurveConstraintPy::setProjectedCurve(PyObject *args) Geom2dAdaptor_Curve adapt(handle); hCurve = new Geom2dAdaptor_HCurve(adapt); } +#endif getGeomPlate_CurveConstraintPtr()->SetProjectedCurve(hCurve, tolU, tolV); Py_Return; @@ -308,11 +337,15 @@ PyObject* CurveConstraintPy::projectedCurve(PyObject *args) return nullptr; try { - Handle(Adaptor2d_HCurve2d) hAdapt = getGeomPlate_CurveConstraintPtr()->ProjectedCurve(); + auto hAdapt = getGeomPlate_CurveConstraintPtr()->ProjectedCurve(); if (hAdapt.IsNull()) Py_Return; +#if OCC_VERSION_HEX >= 0x070600 + const Adaptor2d_Curve2d& a2d = *hAdapt; +#else const Adaptor2d_Curve2d& a2d = hAdapt->Curve2d(); +#endif std::unique_ptr ptr(Part::makeFromCurveAdaptor2d(a2d)); return ptr->getPyObject(); } diff --git a/src/Mod/Part/App/Geometry.cpp b/src/Mod/Part/App/Geometry.cpp index e6d6396ca94..1d1d67d4f01 100644 --- a/src/Mod/Part/App/Geometry.cpp +++ b/src/Mod/Part/App/Geometry.cpp @@ -51,7 +51,6 @@ # include # include # include -# include # include # include # include @@ -101,6 +100,9 @@ # include # include # include +# if OCC_VERSION_HEX < 0x070600 +# include +# endif # include # include @@ -144,6 +146,9 @@ #include "Geometry.h" +#if OCC_VERSION_HEX >= 0x070600 +using GeomAdaptor_HCurve = GeomAdaptor_Curve; +#endif using namespace Part; diff --git a/src/Mod/Part/App/PartFeatures.cpp b/src/Mod/Part/App/PartFeatures.cpp index 2dc503bdf21..4d9e1fc0f99 100644 --- a/src/Mod/Part/App/PartFeatures.cpp +++ b/src/Mod/Part/App/PartFeatures.cpp @@ -25,9 +25,7 @@ #ifndef _PreComp_ # include # include -# include # include -# include # include # include # include @@ -43,7 +41,7 @@ # include # include # include -# include +# include #endif @@ -170,22 +168,18 @@ App::DocumentObjectExecReturn *RuledSurface::execute(void) if (Orientation.getValue() == 0) { // Automatic - Handle(Adaptor3d_HCurve) a1; - Handle(Adaptor3d_HCurve) a2; + std::unique_ptr a1; + std::unique_ptr a2; if (!isWire) { - BRepAdaptor_Curve adapt1(TopoDS::Edge(S1)); - BRepAdaptor_Curve adapt2(TopoDS::Edge(S2)); - a1 = new BRepAdaptor_HCurve(adapt1); - a2 = new BRepAdaptor_HCurve(adapt2); + a1 = std::make_unique(TopoDS::Edge(S1)); + a2 = std::make_unique(TopoDS::Edge(S2)); } else { - BRepAdaptor_CompCurve adapt1(TopoDS::Wire(S1)); - BRepAdaptor_CompCurve adapt2(TopoDS::Wire(S2)); - a1 = new BRepAdaptor_HCompCurve(adapt1); - a2 = new BRepAdaptor_HCompCurve(adapt2); + a1 = std::make_unique(TopoDS::Wire(S1)); + a2 = std::make_unique(TopoDS::Wire(S2)); } - if (!a1.IsNull() && !a2.IsNull()) { + if (a1 && a2) { // get end points of 1st curve Standard_Real first, last; first = a1->FirstParameter(); diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index 05341de3d66..b7617a3943e 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -38,8 +38,6 @@ # include # include # include -# include -# include # include # include # include @@ -186,6 +184,12 @@ #if OCC_VERSION_HEX >= 0x070300 # include #endif + +#if OCC_VERSION_HEX < 0x070600 +# include +# include +#endif + #endif // _PreComp_ #include @@ -2133,12 +2137,20 @@ TopoDS_Shape TopoShape::makeTube(double radius, double tol, int cont, int maxdeg if (this->_Shape.IsNull()) Standard_Failure::Raise("Cannot sweep along empty spine"); +#if OCC_VERSION_HEX >= 0x070600 + Handle(Adaptor3d_Curve) myPath; + if (this->_Shape.ShapeType() == TopAbs_EDGE) { + const TopoDS_Edge& path_edge = TopoDS::Edge(this->_Shape); + myPath = new BRepAdaptor_Curve(path_edge); + } +#else Handle(Adaptor3d_HCurve) myPath; if (this->_Shape.ShapeType() == TopAbs_EDGE) { const TopoDS_Edge& path_edge = TopoDS::Edge(this->_Shape); BRepAdaptor_Curve path_adapt(path_edge); myPath = new BRepAdaptor_HCurve(path_adapt); } +#endif //else if (this->_Shape.ShapeType() == TopAbs_WIRE) { // const TopoDS_Wire& path_wire = TopoDS::Wire(this->_Shape); // BRepAdaptor_CompCurve path_adapt(path_wire); @@ -3777,72 +3789,32 @@ void TopoShape::getLinesFromSubElement(const Data::Segment* element, for(TopExp_Explorer exp(shape,TopAbs_EDGE);exp.More();exp.Next()) { TopoDS_Edge aEdge = TopoDS::Edge(exp.Current()); - TopLoc_Location aLoc; - Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc); + std::vector points; - gp_Trsf myTransf; - Standard_Integer nbNodesInFace; - - auto line_start = vertices.size(); - - // triangulation succeeded? - if (!aPoly.IsNull()) { - if (!aLoc.IsIdentity()) { - myTransf = aLoc.Transformation(); - } - nbNodesInFace = aPoly->NbNodes(); - - const TColgp_Array1OfPnt& Nodes = aPoly->Nodes(); - - gp_Pnt V; - for (Standard_Integer i=0;i < nbNodesInFace;i++) { - V = Nodes(i+1); - V.Transform(myTransf); - vertices.emplace_back(V.X(),V.Y(),V.Z()); - } - } - else { + if (!Tools::getPolygon3D(aEdge, points)) { // the edge has not its own triangulation, but then a face the edge is attached to // must provide this triangulation // Look for one face in our map (it doesn't care which one we take) int index = edge2Face.FindIndex(aEdge); - if(!index) + if (index < 1) continue; const auto &faces = edge2Face.FindFromIndex(index); - if(!faces.Extent()) + if (faces.Extent() == 0) continue; const TopoDS_Face& aFace = TopoDS::Face(faces.First()); - // take the face's triangulation instead - Handle(Poly_Triangulation) aPolyTria = BRep_Tool::Triangulation(aFace,aLoc); - if (!aLoc.IsIdentity()) { - myTransf = aLoc.Transformation(); - } - - if (aPolyTria.IsNull()) break; - - // this holds the indices of the edge's triangulation to the actual points - Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(aEdge, aPolyTria, aLoc); - if (aPoly.IsNull()) - continue; // polygon does not exist - - // getting size and create the array - nbNodesInFace = aPoly->NbNodes(); - - const TColStd_Array1OfInteger& indices = aPoly->Nodes(); - const TColgp_Array1OfPnt& Nodes = aPolyTria->Nodes(); - - gp_Pnt V; - // go through the index array - for (Standard_Integer i=indices.Lower();i <= indices.Upper();i++) { - V = Nodes(indices(i)); - V.Transform(myTransf); - vertices.emplace_back(V.X(),V.Y(),V.Z()); - } + if (!Part::Tools::getPolygonOnTriangulation(aEdge, aFace, points)) + continue; } - if(line_start+1 < vertices.size()) { + auto line_start = vertices.size(); + vertices.reserve(vertices.size() + points.size()); + std::for_each(points.begin(), points.end(), [&vertices](const gp_Pnt& p) { + vertices.push_back(Base::convertTo(p)); + }); + + if (line_start+1 < vertices.size()) { lines.emplace_back(); lines.back().I1 = line_start; lines.back().I2 = vertices.size()-1; diff --git a/src/Mod/Part/App/TopoShapeFacePyImp.cpp b/src/Mod/Part/App/TopoShapeFacePyImp.cpp index ea6cd98bdf4..63e8bead74d 100644 --- a/src/Mod/Part/App/TopoShapeFacePyImp.cpp +++ b/src/Mod/Part/App/TopoShapeFacePyImp.cpp @@ -493,6 +493,15 @@ PyObject* TopoShapeFacePy::getUVNodes(PyObject *args) return Py::new_reference_to(list); } +#if OCC_VERSION_HEX >= 0x070600 + for (int i=1; i<=mesh->NbNodes(); i++) { + gp_Pnt2d pt2d = mesh->UVNode(i); + Py::Tuple uv(2); + uv.setItem(0, Py::Float(pt2d.X())); + uv.setItem(1, Py::Float(pt2d.Y())); + list.append(uv); + } +#else const TColgp_Array1OfPnt2d& aNodesUV = mesh->UVNodes(); for (int i=aNodesUV.Lower(); i<=aNodesUV.Upper(); i++) { gp_Pnt2d pt2d = aNodesUV(i); @@ -501,6 +510,7 @@ PyObject* TopoShapeFacePy::getUVNodes(PyObject *args) uv.setItem(1, Py::Float(pt2d.Y())); list.append(uv); } +#endif return Py::new_reference_to(list); } diff --git a/src/Mod/Part/App/TopoShapeWirePyImp.cpp b/src/Mod/Part/App/TopoShapeWirePyImp.cpp index 95c1aff6814..a1f32d6d03c 100644 --- a/src/Mod/Part/App/TopoShapeWirePyImp.cpp +++ b/src/Mod/Part/App/TopoShapeWirePyImp.cpp @@ -344,9 +344,9 @@ PyObject* TopoShapeWirePy::approximate(PyObject *args, PyObject *kwds) return 0; try { BRepAdaptor_CompCurve adapt(TopoDS::Wire(getTopoShapePtr()->getShape())); - Handle(Adaptor3d_HCurve) hcurve = adapt.Trim(adapt.FirstParameter(), - adapt.LastParameter(), - tol2d); + auto hcurve = adapt.Trim(adapt.FirstParameter(), + adapt.LastParameter(), + tol2d); Approx_Curve3d approx(hcurve, tol3d, GeomAbs_C0, maxseg, maxdeg); if (approx.IsDone()) { return new BSplineCurvePy(new GeomBSplineCurve(approx.Curve())); diff --git a/src/Mod/Part/Gui/TaskCheckGeometry.cpp b/src/Mod/Part/Gui/TaskCheckGeometry.cpp index 5de7c169205..aaef13d9d07 100644 --- a/src/Mod/Part/Gui/TaskCheckGeometry.cpp +++ b/src/Mod/Part/Gui/TaskCheckGeometry.cpp @@ -711,8 +711,10 @@ int TaskCheckGeometryResults::goBOPSingleCheck(const TopoDS_Shape& shapeIn, Resu #if OCC_VERSION_HEX >= 0x060900 #if OCC_VERSION_HEX < 0x070500 BOPCheck.SetProgressIndicator(theProgress); -#else +#elif OCC_VERSION_HEX < 0x070600 BOPCheck.SetProgressIndicator(theScope); +#else + Q_UNUSED(theScope) #endif // 0x070500 #else Q_UNUSED(theProgress); @@ -740,7 +742,7 @@ int TaskCheckGeometryResults::goBOPSingleCheck(const TopoDS_Shape& shapeIn, Resu Base::TimeInfo start_time; #endif -BOPCheck.Perform(); + BOPCheck.Perform(); #ifdef FC_DEBUG float bopAlgoTime = Base::TimeInfo::diffTimeF(start_time,Base::TimeInfo()); diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index 77cefbe3e08..8a52f1701ba 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -1102,7 +1111,11 @@ void ViewProviderPartExt::updateVisual() } // get the 3 points of this triangle +#if OCC_VERSION_HEX < 0x070600 gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3)); +#else + gp_Pnt V1(mesh->Node(N1)), V2(mesh->Node(N2)), V3(mesh->Node(N3)); +#endif // get the 3 normals of this triangle gp_Vec NV1, NV2, NV3; @@ -1179,7 +1192,11 @@ void ViewProviderPartExt::updateVisual() // rare cases where some points are only referenced by the polygon // but not by any triangle. Thus, we must apply the coordinates to // make sure that everything is properly set. +#if OCC_VERSION_HEX < 0x070600 gp_Pnt p(Nodes(nodeIndex)); +#else + gp_Pnt p(mesh->Node(nodeIndex)); +#endif if (!identity) p.Transform(myTransf); verts[index].setValue((float)(p.X()),(float)(p.Y()),(float)(p.Z())); diff --git a/src/Mod/Path/App/AppPathPy.cpp b/src/Mod/Path/App/AppPathPy.cpp index 6e0c72d2f53..ce912b44749 100644 --- a/src/Mod/Path/App/AppPathPy.cpp +++ b/src/Mod/Path/App/AppPathPy.cpp @@ -49,10 +49,7 @@ #include #include #include -#include -#include -#include -#include +#include #include "CommandPy.h" #include "PathPy.h" diff --git a/src/Mod/TechDraw/App/Geometry.cpp b/src/Mod/TechDraw/App/Geometry.cpp index b6c36371377..59a92d7e51b 100644 --- a/src/Mod/TechDraw/App/Geometry.cpp +++ b/src/Mod/TechDraw/App/Geometry.cpp @@ -28,13 +28,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include #include #include @@ -58,14 +58,16 @@ #include #include #include +#include #include #include #include #include #include #include -#include - +#if OCC_VERSION_HEX < 0x070600 +#include +#endif #include #endif // #ifndef _PreComp_ @@ -86,6 +88,10 @@ using namespace TechDraw; using namespace std; +#if OCC_VERSION_HEX >= 0x070600 +using BRepAdaptor_HCurve = BRepAdaptor_Curve; +#endif + #define GEOMETRYEDGE 0 #define COSMETICEDGE 1 #define CENTERLINE 2 diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index 77cefbe3e0..8a52f1701b 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -1154,16 +1154,25 @@ // cycling through the poly mesh +#if OCC_VERSION_HEX < 0x070600 const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); TColgp_Array1OfDir Normals (Nodes.Lower(), Nodes.Upper()); +#else + int numNodes = mesh->NbNodes(); + TColgp_Array1OfDir Normals (1, numNodes); +#endif if (NormalsFromUV) getNormals(actFace, mesh, Normals); for (int g=1;g<=nbTriInFace;g++) { // Get the triangle Standard_Integer N1,N2,N3; +#if OCC_VERSION_HEX < 0x070600 Triangles(g).Get(N1,N2,N3); +#else + mesh->Triangle(g).Get(N1,N2,N3); +#endif // change orientation of the triangle if the face is reversed if ( orient != TopAbs_FORWARD ) { From c9d17ebde2400f83d1e1e799bdb0a7f85a0da96d Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 12:41:07 +0200 Subject: [PATCH] Part: add convenience functions to retrieve triangulation of a face or edge --- src/Mod/Part/App/Tools.cpp | 170 ++++++++++++++++++++++++++++++++++++- src/Mod/Part/App/Tools.h | 31 ++++++- 2 files changed, 198 insertions(+), 3 deletions(-) diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index b02c0560453..c0e59445089 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -25,25 +25,31 @@ # include # include # include -# include +# include # include # include -# include # include # include # include +# include # include # include # include # include # include +# include # include # include # include +# include # include # include # include # include +# if OCC_VERSION_HEX < 0x070600 +# include +# include +# endif #endif #include @@ -138,6 +144,20 @@ Part::Tools::makeSurface(const TColStd_ListOfTransient &theBoundaries, assert (0); Standard_ConstructionError::Raise ("Tools::makeSurface()"); } +#if OCC_VERSION_HEX >= 0x070600 + else if (aCur->IsKind (STANDARD_TYPE (Adaptor3d_CurveOnSurface))) { + //G1 constraint + Handle(Adaptor3d_CurveOnSurface) aHCOS (Handle(Adaptor3d_CurveOnSurface)::DownCast (aCur)); + Handle (GeomPlate_CurveConstraint) aConst = new GeomPlate_CurveConstraint (aHCOS, 1 /*GeomAbs_G1*/,aNbPnts, aTol3d, anAngTol, aCurvTol); + aPlateBuilder.Add (aConst); + } + else if (aCur->IsKind (STANDARD_TYPE (GeomAdaptor_Curve))) { + //G0 constraint + Handle(GeomAdaptor_Curve) aHC (Handle(GeomAdaptor_Curve)::DownCast (aCur)); + Handle (GeomPlate_CurveConstraint) aConst = new GeomPlate_CurveConstraint (aHC, 0 /*GeomAbs_G0*/, aNbPnts, aTol3d); + aPlateBuilder.Add (aConst); + } +#else else if (aCur->IsKind (STANDARD_TYPE (Adaptor3d_HCurveOnSurface))) { //G1 constraint Handle(Adaptor3d_HCurveOnSurface) aHCOS (Handle(Adaptor3d_HCurveOnSurface)::DownCast (aCur)); @@ -150,6 +170,7 @@ Part::Tools::makeSurface(const TColStd_ListOfTransient &theBoundaries, Handle (GeomPlate_CurveConstraint) aConst = new GeomPlate_CurveConstraint (aHC, 0 /*GeomAbs_G0*/, aNbPnts, aTol3d); aPlateBuilder.Add (aConst); } +#endif else if (aCur->IsKind (STANDARD_TYPE (Geom_Point))) { //Point constraint Handle(Geom_Point) aGP (Handle(Geom_Point)::DownCast (aCur)); @@ -190,3 +211,148 @@ Part::Tools::makeSurface(const TColStd_ListOfTransient &theBoundaries, return aRes; } + +bool Part::Tools::getTriangulation(const TopoDS_Face& face, std::vector& points, std::vector& facets) +{ + TopLoc_Location loc; + Handle(Poly_Triangulation) hTria = BRep_Tool::Triangulation(face, loc); + if (hTria.IsNull()) + return false; + + // getting the transformation of the face + gp_Trsf transf; + bool identity = true; + if (!loc.IsIdentity()) { + identity = false; + transf = loc.Transformation(); + } + + // check orientation + TopAbs_Orientation orient = face.Orientation(); + + Standard_Integer nbNodes = hTria->NbNodes(); + Standard_Integer nbTriangles = hTria->NbTriangles(); +#if OCC_VERSION_HEX < 0x070600 + const TColgp_Array1OfPnt& nodes = hTria->Nodes(); + const Poly_Array1OfTriangle& triangles = hTria->Triangles(); +#endif + + points.reserve(nbNodes); + facets.reserve(nbTriangles); + + // cycling through the poly mesh + // + for (int i = 1; i <= nbNodes; i++) { +#if OCC_VERSION_HEX < 0x070600 + gp_Pnt p = nodes(i); +#else + gp_Pnt p = hTria->Node(i); +#endif + + // transform the vertices to the location of the face + if (!identity) { + p.Transform(transf); + } + + points.push_back(p); + } + + for (int i = 1; i <= nbTriangles; i++) { + // Get the triangle + Standard_Integer n1,n2,n3; +#if OCC_VERSION_HEX < 0x070600 + triangles(i).Get(n1, n2, n3); +#else + hTria->Triangle(i).Get(n1, n2, n3); +#endif + --n1; --n2; --n3; + + // change orientation of the triangles + if (orient != TopAbs_FORWARD) { + std::swap(n1, n2); + } + + facets.emplace_back(n1, n2, n3); + } + + return true; +} + +bool Part::Tools::getPolygonOnTriangulation(const TopoDS_Edge& edge, const TopoDS_Face& face, std::vector& points) +{ + TopLoc_Location loc; + Handle(Poly_Triangulation) hTria = BRep_Tool::Triangulation(face, loc); + if (hTria.IsNull()) + return false; + + // this holds the indices of the edge's triangulation to the actual points + Handle(Poly_PolygonOnTriangulation) hPoly = BRep_Tool::PolygonOnTriangulation(edge, hTria, loc); + if (hPoly.IsNull()) + return false; + + // getting the transformation of the edge + gp_Trsf transf; + bool identity = true; + if (!loc.IsIdentity()) { + identity = false; + transf = loc.Transformation(); + } + + // getting size and create the array + Standard_Integer nbNodes = hPoly->NbNodes(); + points.reserve(nbNodes); + const TColStd_Array1OfInteger& indices = hPoly->Nodes(); +#if OCC_VERSION_HEX < 0x070600 + const TColgp_Array1OfPnt& Nodes = hTria->Nodes(); +#endif + + // go through the index array + for (Standard_Integer i = indices.Lower(); i <= indices.Upper(); i++) { +#if OCC_VERSION_HEX < 0x070600 + gp_Pnt p = Nodes(indices(i)); +#else + gp_Pnt p = hTria->Node(indices(i)); +#endif + if (!identity) { + p.Transform(transf); + } + + points.push_back(p); + } + + return true; +} + +bool Part::Tools::getPolygon3D(const TopoDS_Edge& edge, std::vector& points) +{ + TopLoc_Location loc; + Handle(Poly_Polygon3D) hPoly = BRep_Tool::Polygon3D(edge, loc); + if (hPoly.IsNull()) + return false; + + // getting the transformation of the edge + gp_Trsf transf; + bool identity = true; + if (!loc.IsIdentity()) { + identity = false; + transf = loc.Transformation(); + } + + // getting size and create the array + Standard_Integer nbNodes = hPoly->NbNodes(); + points.reserve(nbNodes); + const TColgp_Array1OfPnt& nodes = hPoly->Nodes(); + + for (int i = 1; i <= nbNodes; i++) { + gp_Pnt p = nodes(i); + + // transform the vertices to the location of the face + if (!identity) { + p.Transform(transf); + } + + points.push_back(p); + } + + return true; +} diff --git a/src/Mod/Part/App/Tools.h b/src/Mod/Part/App/Tools.h index a936c352c65..19ecf937fda 100644 --- a/src/Mod/Part/App/Tools.h +++ b/src/Mod/Part/App/Tools.h @@ -30,7 +30,11 @@ #include #include #include +#include #include +#include +#include +#include class gp_Lin; class gp_Pln; @@ -104,7 +108,32 @@ class PartExport Tools const Standard_Integer theNbPnts, const Standard_Integer theNbIter, const Standard_Integer theMaxDeg); - + /*! + * @brief getTriangulation + * The indexes of the triangles are adjusted to the points vector. + * @param face + * @param points + * @param facets + * @return true if a triangulation exists or false otherwise + */ + static bool getTriangulation(const TopoDS_Face& face, std::vector& points, std::vector& facets); + /*! + * \brief getPolygonOnTriangulation + * Get the polygon of edge. + * \note \a edge must belong to face. + * \param edge + * \param face + * \param points + * \return true if a triangulation exists or false otherwise + */ + static bool getPolygonOnTriangulation(const TopoDS_Edge& edge, const TopoDS_Face& face, std::vector& points); + /*! + * \brief getPolygon3D + * \param edge + * \param points + * \return true if a polygon exists or false otherwise + */ + static bool getPolygon3D(const TopoDS_Edge& edge, std::vector& points); }; } //namespace Part From 442c8d52a1989da8f17d60fafea5b81d79cbf0ab Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 15:32:19 +0200 Subject: [PATCH] Part: in TopoShape::getDomains use functions of Tools class --- src/Mod/Part/App/TopoShape.cpp | 56 +++++++++++++++------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index 09cfab45bb0..05341de3d66 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -3360,46 +3360,40 @@ void TopoShape::getDomains(std::vector& domains) const for (TopExp_Explorer xp(this->_Shape, TopAbs_FACE); xp.More(); xp.Next()) { TopoDS_Face face = TopoDS::Face(xp.Current()); - TopLoc_Location loc; - Handle(Poly_Triangulation) theTriangulation = BRep_Tool::Triangulation(face, loc); - if (theTriangulation.IsNull()) { + std::vector points; + std::vector facets; + if (!Tools::getTriangulation(face, points, facets)) { // For a face that cannot be meshed append an empty domain. // It's important for some algorithms (e.g. color mapping) that the numbers of // faces and domains match Domain domain; domains.push_back(domain); - continue; } + else { + Domain domain; + // copy the points + domain.points.reserve(points.size()); + for (const auto& it : points) { + Standard_Real X, Y, Z; + it.Coord (X, Y, Z); + domain.points.emplace_back(X, Y, Z); + } - Domain domain; - // copy the points - const TColgp_Array1OfPnt& points = theTriangulation->Nodes(); - domain.points.reserve(points.Length()); - for (int i = 1; i <= points.Length(); i++) { - gp_Pnt p = points(i); - p.Transform(loc.Transformation()); - Standard_Real X, Y, Z; - p.Coord (X, Y, Z); - domain.points.emplace_back(X, Y, Z); - } + // copy the triangles + domain.facets.reserve(facets.size()); + for (const auto& it : facets) { + Standard_Integer N1, N2, N3; + it.Get(N1, N2, N3); + + Facet tria; + tria.I1 = N1; + tria.I2 = N2; + tria.I3 = N3; + domain.facets.push_back(tria); + } - // copy the triangles - const TopAbs_Orientation anOrientation = face.Orientation(); - bool flip = (anOrientation == TopAbs_REVERSED); - const Poly_Array1OfTriangle& faces = theTriangulation->Triangles(); - domain.facets.reserve(faces.Length()); - for (int i = 1; i <= faces.Length(); i++) { - Standard_Integer N1, N2, N3; - faces(i).Get(N1, N2, N3); - - Facet tria; - tria.I1 = N1-1; tria.I2 = N2-1; tria.I3 = N3-1; - if (flip) - std::swap(tria.I1, tria.I2); - domain.facets.push_back(tria); + domains.push_back(domain); } - - domains.push_back(domain); } } From 8e6dab209ee59be61d83a0ff249283a8809fa917 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 12:43:06 +0200 Subject: [PATCH] Part: change TopoShape::exportFaceSet and TopoShape::exportLineSet to use the functions of the Tools class --- src/Mod/Part/App/TopoShape.cpp | 141 +++++++-------------------------- 1 file changed, 29 insertions(+), 112 deletions(-) diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index 614661594d0..09cfab45bb0 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -1097,65 +1097,27 @@ void TopoShape::exportFaceSet(double dev, double ca, for (ex.Init(this->_Shape, TopAbs_FACE); ex.More(); ex.Next(), index++) { // get the shape and mesh it const TopoDS_Face& aFace = TopoDS::Face(ex.Current()); - Standard_Integer nbNodesInFace,nbTriInFace; + std::vector points; + std::vector facets; + if (!Tools::getTriangulation(aFace, points, facets)) + continue; + std::vector vertices; std::vector indices; + vertices.resize(points.size()); + indices.resize(4 * facets.size()); - // doing the meshing and checking the result - TopLoc_Location aLoc; - Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc); - if (aPoly.IsNull()) continue; - - // getting the transformation of the shape/face - gp_Trsf myTransf; - Standard_Boolean identity = true; - if (!aLoc.IsIdentity()) { - identity = false; - myTransf = aLoc.Transformation(); + for (std::size_t i = 0; i < points.size(); i++) { + vertices[i] = Base::convertTo(points[i]); } - // getting size and create the array - nbNodesInFace = aPoly->NbNodes(); - nbTriInFace = aPoly->NbTriangles(); - vertices.resize(nbNodesInFace); - indices.resize(4*nbTriInFace); - - // check orientation - TopAbs_Orientation orient = aFace.Orientation(); - - // cycling through the poly mesh - const Poly_Array1OfTriangle& Triangles = aPoly->Triangles(); - const TColgp_Array1OfPnt& Nodes = aPoly->Nodes(); - for (int i=1;i<=nbTriInFace;i++) { - // Get the triangle - Standard_Integer N1,N2,N3; - Triangles(i).Get(N1,N2,N3); - - // change orientation of the triangles - if (orient != TopAbs_FORWARD) { - Standard_Integer tmp = N1; - N1 = N2; - N2 = tmp; - } - - gp_Pnt V1 = Nodes(N1); - gp_Pnt V2 = Nodes(N2); - gp_Pnt V3 = Nodes(N3); - - // transform the vertices to the place of the face - if (!identity) { - V1.Transform(myTransf); - V2.Transform(myTransf); - V3.Transform(myTransf); - } - - vertices[N1-1].Set((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z())); - vertices[N2-1].Set((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z())); - vertices[N3-1].Set((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z())); - - int j = i - 1; - N1--; N2--; N3--; - indices[4*j] = N1; indices[4*j+1] = N2; indices[4*j+2] = N3; indices[4*j+3] = -1; + for (std::size_t i = 0; i < facets.size(); i++) { + Standard_Integer n1,n2,n3; + facets[i].Get(n1, n2, n3); + indices[4 * i ] = n1; + indices[4 * i + 1] = n2; + indices[4 * i + 2] = n3; + indices[4 * i + 3] = -1; } builder.beginSeparator(); @@ -1170,7 +1132,7 @@ void TopoShape::exportFaceSet(double dev, double ca, builder.endPoints(); builder.addIndexedFaceSet(indices); builder.endSeparator(); - } // end of face loop + } } void TopoShape::exportLineSet(std::ostream& str) const @@ -1183,72 +1145,27 @@ void TopoShape::exportLineSet(std::ostream& str) const // build up map edge->face TopTools_IndexedDataMapOfShapeListOfShape edge2Face; TopExp::MapShapesAndAncestors(this->_Shape, TopAbs_EDGE, TopAbs_FACE, edge2Face); - for (int i=0; i vertices; - Standard_Integer nbNodesInFace; - - // triangulation succeeded? - if (!aPoly.IsNull()) { - if (!aLoc.IsIdentity()) { - myTransf = aLoc.Transformation(); - } - nbNodesInFace = aPoly->NbNodes(); - vertices.resize(nbNodesInFace); - const TColgp_Array1OfPnt& Nodes = aPoly->Nodes(); + for (int i=0; i points; - gp_Pnt V; - for (Standard_Integer i=0;i < nbNodesInFace;i++) { - V = Nodes(i+1); - V.Transform(myTransf); - vertices[i].Set((float)(V.X()),(float)(V.Y()),(float)(V.Z())); - } - } - else { + if (!Tools::getPolygon3D(aEdge, points)) { // the edge has not its own triangulation, but then a face the edge is attached to // must provide this triangulation // Look for one face in our map (it doesn't care which one we take) const TopoDS_Face& aFace = TopoDS::Face(edge2Face.FindFromKey(aEdge).First()); - - // take the face's triangulation instead - Handle(Poly_Triangulation) aPolyTria = BRep_Tool::Triangulation(aFace,aLoc); - if (!aLoc.IsIdentity()) { - myTransf = aLoc.Transformation(); - } - - if (aPolyTria.IsNull()) break; - - // this holds the indices of the edge's triangulation to the actual points - Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(aEdge, aPolyTria, aLoc); - if (aPoly.IsNull()) - continue; // polygon does not exist - - // getting size and create the array - nbNodesInFace = aPoly->NbNodes(); - vertices.resize(nbNodesInFace); - - const TColStd_Array1OfInteger& indices = aPoly->Nodes(); - const TColgp_Array1OfPnt& Nodes = aPolyTria->Nodes(); - - gp_Pnt V; - int pos = 0; - // go through the index array - for (Standard_Integer i=indices.Lower();i <= indices.Upper();i++) { - V = Nodes(indices(i)); - V.Transform(myTransf); - vertices[pos++].Set((float)(V.X()),(float)(V.Y()),(float)(V.Z())); - } + if (!Tools::getPolygonOnTriangulation(aEdge, aFace, points)) + continue; } + std::vector vertices; + vertices.reserve(points.size()); + std::for_each(points.begin(), points.end(), [&vertices](const gp_Pnt& p) { + vertices.push_back(Base::convertTo(p)); + }); + builder.addLineSet(vertices, 2, 0, 0, 0); } } From 0f3b5d275070477b7cd2bbfa2dc930135448fb0c Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 15:29:36 +0200 Subject: [PATCH] Raytracing: in PovTools/LuxTools use functions of Tools class --- src/Mod/Raytracing/App/LuxTools.cpp | 34 ++--- src/Mod/Raytracing/App/PovTools.cpp | 220 ++++++---------------------- src/Mod/Raytracing/App/PovTools.h | 3 - 3 files changed, 62 insertions(+), 195 deletions(-) diff --git a/src/Mod/Raytracing/App/LuxTools.cpp b/src/Mod/Raytracing/App/LuxTools.cpp index 881317f137b..86db2ee16f6 100644 --- a/src/Mod/Raytracing/App/LuxTools.cpp +++ b/src/Mod/Raytracing/App/LuxTools.cpp @@ -44,6 +44,7 @@ #include "PovTools.h" #include "LuxTools.h" +#include using Base::Console; @@ -95,35 +96,34 @@ void LuxTools::writeShape(std::ostream &out, const char *PartName, const TopoDS_ // get the shape and mesh it const TopoDS_Face& aFace = TopoDS::Face(ex.Current()); - // this block mesh the face and transfers it in a C array of vertices and face indexes - Standard_Integer nbNodesInFace,nbTriInFace; - gp_Vec* vertices=0; - gp_Vec* vertexnormals=0; - long* cons=0; + std::vector points; + std::vector vertexnormals; + std::vector facets; + if (!Part::Tools::getTriangulation(aFace, points, facets)) { + break; + } - PovTools::transferToArray(aFace,&vertices,&vertexnormals,&cons,nbNodesInFace,nbTriInFace); + Part::Tools::getPointNormals(points, facets, vertexnormals); + Part::Tools::getPointNormals(points, aFace, vertexnormals); - if (!vertices) break; // writing vertices - for (int i=0; i < nbNodesInFace; i++) { - P << vertices[i].X() << " " << vertices[i].Y() << " " << vertices[i].Z() << " "; + for (std::size_t i=0; i < points.size(); i++) { + P << points[i].X() << " " << points[i].Y() << " " << points[i].Z() << " "; } // writing per vertex normals - for (int j=0; j < nbNodesInFace; j++) { + for (std::size_t j=0; j < vertexnormals.size(); j++) { N << vertexnormals[j].X() << " " << vertexnormals[j].Y() << " " << vertexnormals[j].Z() << " "; } // writing triangle indices - for (int k=0; k < nbTriInFace; k++) { - triindices << cons[3*k]+vi << " " << cons[3*k+2]+vi << " " << cons[3*k+1]+vi << " "; + for (std::size_t k=0; k < facets.size(); k++) { + Standard_Integer n1, n2, n3; + facets[k].Get(n1, n2, n3); + triindices << n1 + vi << " " << n3 + vi << " " << n2 + vi << " "; } - vi = vi + nbNodesInFace; - - delete [] vertexnormals; - delete [] vertices; - delete [] cons; + vi = vi + points.size(); seq.next(); diff --git a/src/Mod/Raytracing/App/PovTools.cpp b/src/Mod/Raytracing/App/PovTools.cpp index e2d7c1f4d7b..049308c8b9d 100644 --- a/src/Mod/Raytracing/App/PovTools.cpp +++ b/src/Mod/Raytracing/App/PovTools.cpp @@ -41,6 +41,7 @@ #include "PovTools.h" +#include using Base::Console; @@ -242,53 +243,53 @@ void PovTools::writeShape(std::ostream &out, const char *PartName, // get the shape and mesh it const TopoDS_Face& aFace = TopoDS::Face(ex.Current()); - // this block mesh the face and transfers it in a C array of vertices and face indexes - Standard_Integer nbNodesInFace,nbTriInFace; - gp_Vec* vertices=0; - gp_Vec* vertexnormals=0; - long* cons=0; - - transferToArray(aFace,&vertices,&vertexnormals,&cons,nbNodesInFace,nbTriInFace); + std::vector points; + std::vector vertexnormals; + std::vector facets; + if (!Part::Tools::getTriangulation(aFace, points, facets)) { + break; + } + Part::Tools::getPointNormals(points, facets, vertexnormals); + Part::Tools::getPointNormals(points, aFace, vertexnormals); - if (!vertices) break; // writing per face header out << "// face number" << l << " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl << "#declare " << PartName << l << " = mesh2{" << endl << " vertex_vectors {" << endl - << " " << nbNodesInFace << "," << endl; + << " " << points.size() << "," << endl; // writing vertices - for (int i=0; i < nbNodesInFace; i++) { - out << " <" << vertices[i].X() << "," - << vertices[i].Z() << "," - << vertices[i].Y() << ">," - << endl; + for (std::size_t i=0; i < points.size(); i++) { + out << " <" + << points[i].X() << "," + << points[i].Z() << "," + << points[i].Y() << ">," + << endl; } out << " }" << endl // writing per vertex normals << " normal_vectors {" << endl - << " " << nbNodesInFace << "," << endl; - for (int j=0; j < nbNodesInFace; j++) { - out << " <" << vertexnormals[j].X() << "," - << vertexnormals[j].Z() << "," - << vertexnormals[j].Y() << ">," - << endl; + << " " << vertexnormals.size() << "," << endl; + for (std::size_t j=0; j < vertexnormals.size(); j++) { + out << " <" + << vertexnormals[j].X() << "," + << vertexnormals[j].Z() << "," + << vertexnormals[j].Y() << ">," + << endl; } out << " }" << endl // writing triangle indices << " face_indices {" << endl - << " " << nbTriInFace << "," << endl; - for (int k=0; k < nbTriInFace; k++) { - out << " <" << cons[3*k] << ","<< cons[3*k+2] << ","<< cons[3*k+1] << ">," << endl; + << " " << facets.size() << "," << endl; + for (std::size_t k=0; k < facets.size(); k++) { + Standard_Integer n1, n2, n3; + facets[k].Get(n1, n2, n3); + out << " <" << n1 << ","<< n3 << "," << n2 << ">," << endl; } // end of face out << " }" << endl << "} // end of Face"<< l << endl << endl; - delete [] vertexnormals; - delete [] vertices; - delete [] cons; - seq.next(); } // end of face loop @@ -323,167 +324,36 @@ void PovTools::writeShapeCSV(const char *FileName, Base::SequencerLauncher seq("Writing file", l); // write the file - l = 1; - for (ex.Init(Shape, TopAbs_FACE); ex.More(); ex.Next(),l++) { + for (ex.Init(Shape, TopAbs_FACE); ex.More(); ex.Next()) { // get the shape and mesh it const TopoDS_Face& aFace = TopoDS::Face(ex.Current()); - // this block mesh the face and transfers it in a C array of vertices and face indexes - Standard_Integer nbNodesInFace,nbTriInFace; - gp_Vec* vertices=0; - gp_Vec* vertexnormals=0; - long* cons=0; + std::vector points; + std::vector vertexnormals; + std::vector facets; + if (!Part::Tools::getTriangulation(aFace, points, facets)) { + break; + } - transferToArray(aFace,&vertices,&vertexnormals,&cons,nbNodesInFace,nbTriInFace); + Part::Tools::getPointNormals(points, facets, vertexnormals); + Part::Tools::getPointNormals(points, aFace, vertexnormals); - if (!vertices) break; // writing per face header // writing vertices - for (int i=0; i < nbNodesInFace; i++) { - fout << vertices[i].X() << cSeperator - << vertices[i].Z() << cSeperator - << vertices[i].Y() << cSeperator - << vertexnormals[i].X() * fLength <NbNodes(); - nbTriInFace = aPoly->NbTriangles(); - *vertices = new gp_Vec[nbNodesInFace]; - *vertexnormals = new gp_Vec[nbNodesInFace]; - for (i=0; i < nbNodesInFace; i++) { - (*vertexnormals)[i]= gp_Vec(0.0,0.0,0.0); - } - - *cons = new long[3*(nbTriInFace)+1]; - - // check orientation - TopAbs_Orientation orient = aFace.Orientation(); - - // cycling through the poly mesh - const Poly_Array1OfTriangle& Triangles = aPoly->Triangles(); - const TColgp_Array1OfPnt& Nodes = aPoly->Nodes(); - for (i=1; i<=nbTriInFace; i++) { - // Get the triangle - Standard_Integer N1,N2,N3; - Triangles(i).Get(N1,N2,N3); - - // change orientation of the triangles - if ( orient != TopAbs_FORWARD ) - { - Standard_Integer tmp = N1; - N1 = N2; - N2 = tmp; - } - - gp_Pnt V1 = Nodes(N1); - gp_Pnt V2 = Nodes(N2); - gp_Pnt V3 = Nodes(N3); - - // transform the vertices to the place of the face - if (!identity) { - V1.Transform(myTransf); - V2.Transform(myTransf); - V3.Transform(myTransf); - } - - // Calculate triangle normal - gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z()); - gp_Vec Normal = (v2-v1)^(v3-v1); - - //Standard_Real Area = 0.5 * Normal.Magnitude(); - - // add the triangle normal to the vertex normal for all points of this triangle - (*vertexnormals)[N1-1] += gp_Vec(Normal.X(),Normal.Y(),Normal.Z()); - (*vertexnormals)[N2-1] += gp_Vec(Normal.X(),Normal.Y(),Normal.Z()); - (*vertexnormals)[N3-1] += gp_Vec(Normal.X(),Normal.Y(),Normal.Z()); - - (*vertices)[N1-1].SetX((float)(V1.X())); - (*vertices)[N1-1].SetY((float)(V1.Y())); - (*vertices)[N1-1].SetZ((float)(V1.Z())); - (*vertices)[N2-1].SetX((float)(V2.X())); - (*vertices)[N2-1].SetY((float)(V2.Y())); - (*vertices)[N2-1].SetZ((float)(V2.Z())); - (*vertices)[N3-1].SetX((float)(V3.X())); - (*vertices)[N3-1].SetY((float)(V3.Y())); - (*vertices)[N3-1].SetZ((float)(V3.Z())); - - int j = i - 1; - N1--; - N2--; - N3--; - (*cons)[3*j] = N1; - (*cons)[3*j+1] = N2; - (*cons)[3*j+2] = N3; - } - - // normalize all vertex normals - for (i=0; i < nbNodesInFace; i++) { - - gp_Dir clNormal; - - try { - Handle(Geom_Surface) Surface = BRep_Tool::Surface(aFace); - - gp_Pnt vertex((*vertices)[i].XYZ()); -// gp_Pnt vertex((*vertices)[i][0], (*vertices)[i][1], (*vertices)[i][2]); - GeomAPI_ProjectPointOnSurf ProPntSrf(vertex, Surface); - Standard_Real fU, fV; - ProPntSrf.Parameters(1, fU, fV); - - GeomLProp_SLProps clPropOfFace(Surface, fU, fV, 2, gp::Resolution()); - - clNormal = clPropOfFace.Normal(); - gp_Vec temp = clNormal; - //Base::Console().Log("unterschied:%.2f",temp.dot((*vertexnormals)[i])); - if ( temp * (*vertexnormals)[i] < 0 ) - temp = -temp; - (*vertexnormals)[i] = temp; - - } - catch (...) { - } - - (*vertexnormals)[i].Normalize(); - } -} diff --git a/src/Mod/Raytracing/App/PovTools.h b/src/Mod/Raytracing/App/PovTools.h index d499e003a08..09088c5755d 100644 --- a/src/Mod/Raytracing/App/PovTools.h +++ b/src/Mod/Raytracing/App/PovTools.h @@ -110,9 +110,6 @@ class AppRaytracingExport PovTools const TopoDS_Shape& Shape, float fMeshDeviation, float fLength); - - - static void transferToArray(const TopoDS_Face& aFace,gp_Vec** vertices,gp_Vec** vertexnormals, long** cons,int &nbNodesInFace,int &nbTriInFace ); }; From 08d46b5f882420c8d4066427fcc8dab5b1882097 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 15:28:22 +0200 Subject: [PATCH] Part: add methods to get the point normals of the triangulation or surface --- src/Mod/Part/App/Tools.cpp | 58 ++++++++++++++++++++++++++++++++++++++ src/Mod/Part/App/Tools.h | 17 +++++++++++ 2 files changed, 75 insertions(+) diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index c0e59445089..41284befede 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -29,6 +29,7 @@ # include # include # include +# include # include # include # include @@ -356,3 +357,60 @@ bool Part::Tools::getPolygon3D(const TopoDS_Edge& edge, std::vector& poi return true; } + +void Part::Tools::getPointNormals(const std::vector& points, const std::vector& facets, std::vector& vertexnormals) +{ + vertexnormals.resize(points.size()); + + for (const auto& it : facets) { + // Get the triangle + Standard_Integer n1,n2,n3; + it.Get(n1,n2,n3); + + // Calculate triangle normal + gp_Vec v1(points[n1].XYZ()); + gp_Vec v2(points[n2].XYZ()); + gp_Vec v3(points[n3].XYZ()); + gp_Vec n = (v2 - v1) ^ (v3 - v1); + + // add the triangle normal to the vertex normal for all points of this triangle + vertexnormals[n1] += n; + vertexnormals[n2] += n; + vertexnormals[n3] += n; + } + + for (auto& it : vertexnormals) + it.Normalize(); +} + +void Part::Tools::getPointNormals(const std::vector& points, const TopoDS_Face& face, std::vector& vertexnormals) +{ + if (points.size() != vertexnormals.size()) + return; + + Handle(Geom_Surface) hSurface = BRep_Tool::Surface(face); + if (hSurface.IsNull()) + return; + + // normalize all vertex normals + for (std::size_t i = 0; i < points.size(); i++) { + try { + GeomAPI_ProjectPointOnSurf ProPntSrf(points[i], hSurface); + Standard_Real u, v; + ProPntSrf.Parameters(1, u, v); + + GeomLProp_SLProps propOfFace(hSurface, u, v, 2, gp::Resolution()); + + gp_Dir normal = propOfFace.Normal(); + gp_Vec temp = normal; + if (temp * vertexnormals[i] < 0.0) + temp = -temp; + vertexnormals[i] = temp; + + } + catch (...) { + } + + vertexnormals[i].Normalize(); + } +} diff --git a/src/Mod/Part/App/Tools.h b/src/Mod/Part/App/Tools.h index 19ecf937fda..a487530a7dc 100644 --- a/src/Mod/Part/App/Tools.h +++ b/src/Mod/Part/App/Tools.h @@ -134,6 +134,23 @@ class PartExport Tools * \return true if a polygon exists or false otherwise */ static bool getPolygon3D(const TopoDS_Edge& edge, std::vector& points); + /*! + * \brief getPointNormals + * Calculate the point normals of the given triangulation. + * \param points + * \param facets + * \param normals + */ + static void getPointNormals(const std::vector& points, const std::vector& facets, std::vector& vertexnormals); + /*! + * \brief getPointNormals + * Computes the more accurate surface normals for the points. If the calculation for a point fails then the precomputed + * point normal of the triangulation is used. + * \param points + * \param face + * \param vertexnormals + */ + static void getPointNormals(const std::vector& points, const TopoDS_Face& face, std::vector& vertexnormals); }; } //namespace Part From 51e4366085e59a9b511f7160d66493e9b3dfc7d8 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 11 Oct 2021 00:28:12 +0200 Subject: [PATCH] OCCT: port FreeCAD sources to version 7.6 --- src/Mod/Fem/App/FemConstraint.cpp | 12 ++++++++++-- src/Mod/Fem/App/FemConstraintFixed.cpp | 2 -- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Mod/Fem/App/FemConstraint.cpp b/src/Mod/Fem/App/FemConstraint.cpp index 18f72e87d20..8003fd6d79c 100644 --- a/src/Mod/Fem/App/FemConstraint.cpp +++ b/src/Mod/Fem/App/FemConstraint.cpp @@ -36,8 +36,6 @@ # include # include # include -# include -# include # include # include # include @@ -51,6 +49,11 @@ # include # include # include +# include +# if OCC_VERSION_HEX < 0x070600 +# include +# include +# endif #endif #include "FemConstraint.h" @@ -74,6 +77,11 @@ double round(double r) { } #endif +#if OCC_VERSION_HEX >= 0x070600 +using Adaptor3d_HSurface = Adaptor3d_Surface; +using BRepAdaptor_HSurface = BRepAdaptor_Surface; +#endif + PROPERTY_SOURCE(Fem::Constraint, App::DocumentObject) Constraint::Constraint() diff --git a/src/Mod/Fem/App/FemConstraintFixed.cpp b/src/Mod/Fem/App/FemConstraintFixed.cpp index 4d809454903..5b8874ec90b 100644 --- a/src/Mod/Fem/App/FemConstraintFixed.cpp +++ b/src/Mod/Fem/App/FemConstraintFixed.cpp @@ -32,8 +32,6 @@ #include #include #include -#include -#include #include #include #include From c2c5ae1bf0c571270ecacf257a51e9b064fc609a Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 19:34:48 +0200 Subject: [PATCH] Part: remove ViewProviderPartExt::getNormals --- src/Mod/Part/Gui/ViewProviderExt.cpp | 91 +------------------ src/Mod/Part/Gui/ViewProviderExt.h | 2 - src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp | 5 +- 3 files changed, 5 insertions(+), 93 deletions(-) diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index ba197f18113..77cefbe3e08 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -125,6 +125,7 @@ #include #include +#include FC_LOG_LEVEL_INIT("Part", true, true) @@ -133,94 +134,6 @@ using namespace PartGui; PROPERTY_SOURCE(PartGui::ViewProviderPartExt, Gui::ViewProviderGeometryObject) -void ViewProviderPartExt::getNormals(const TopoDS_Face& theFace, - const Handle(Poly_Triangulation)& aPolyTri, - TColgp_Array1OfDir& theNormals) -{ - const TColgp_Array1OfPnt& aNodes = aPolyTri->Nodes(); - - if(aPolyTri->HasNormals()) - { - // normals pre-computed in triangulation structure - const TShort_Array1OfShortReal& aNormals = aPolyTri->Normals(); - const Standard_ShortReal* aNormArr = &(aNormals.Value(aNormals.Lower())); - - for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) - { - const Standard_Integer anId = 3 * (aNodeIter - aNodes.Lower()); - const gp_Dir aNorm(aNormArr[anId + 0], - aNormArr[anId + 1], - aNormArr[anId + 2]); - theNormals(aNodeIter) = aNorm; - } - - if(theFace.Orientation() == TopAbs_REVERSED) - { - for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) - { - theNormals.ChangeValue(aNodeIter).Reverse(); - } - } - - return; - } - - // take in face the surface location - Poly_Connect thePolyConnect(aPolyTri); - const TopoDS_Face aZeroFace = TopoDS::Face(theFace.Located(TopLoc_Location())); - Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aZeroFace); - const Standard_Real aTol = Precision::Confusion(); - Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal(1, aPolyTri->NbNodes() * 3); - const Poly_Array1OfTriangle& aTriangles = aPolyTri->Triangles(); - const TColgp_Array1OfPnt2d* aNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull() - ? &aPolyTri->UVNodes() - : NULL; - Standard_Integer aTri[3]; - - for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) - { - // try to retrieve normal from real surface first, when UV coordinates are available - if(aNodesUV == NULL - || GeomLib::NormEstim(aSurf, aNodesUV->Value(aNodeIter), aTol, theNormals(aNodeIter)) > 1) - { - // compute flat normals - gp_XYZ eqPlan(0.0, 0.0, 0.0); - - for(thePolyConnect.Initialize(aNodeIter); thePolyConnect.More(); thePolyConnect.Next()) - { - aTriangles(thePolyConnect.Value()).Get(aTri[0], aTri[1], aTri[2]); - const gp_XYZ v1(aNodes(aTri[1]).Coord() - aNodes(aTri[0]).Coord()); - const gp_XYZ v2(aNodes(aTri[2]).Coord() - aNodes(aTri[1]).Coord()); - const gp_XYZ vv = v1 ^ v2; - const Standard_Real aMod = vv.Modulus(); - - if(aMod >= aTol) - { - eqPlan += vv / aMod; - } - } - - const Standard_Real aModMax = eqPlan.Modulus(); - theNormals(aNodeIter) = (aModMax > aTol) ? gp_Dir(eqPlan) : gp::DZ(); - } - - const Standard_Integer anId = (aNodeIter - aNodes.Lower()) * 3; - aNormals->SetValue(anId + 1, (Standard_ShortReal)theNormals(aNodeIter).X()); - aNormals->SetValue(anId + 2, (Standard_ShortReal)theNormals(aNodeIter).Y()); - aNormals->SetValue(anId + 3, (Standard_ShortReal)theNormals(aNodeIter).Z()); - } - - aPolyTri->SetNormals(aNormals); - - if(theFace.Orientation() == TopAbs_REVERSED) - { - for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) - { - theNormals.ChangeValue(aNodeIter).Reverse(); - } - } -} - //************************************************************************** // Construction/Destruction @@ -1174,7 +1087,7 @@ void ViewProviderPartExt::updateVisual() const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); TColgp_Array1OfDir Normals (Nodes.Lower(), Nodes.Upper()); if (NormalsFromUV) - getNormals(actFace, mesh, Normals); + Part::Tools::getPointNormals(actFace, mesh, Normals); for (int g=1;g<=nbTriInFace;g++) { // Get the triangle diff --git a/src/Mod/Part/Gui/ViewProviderExt.h b/src/Mod/Part/Gui/ViewProviderExt.h index d890e9a716e..2cb55c1873c 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.h +++ b/src/Mod/Part/Gui/ViewProviderExt.h @@ -158,8 +158,6 @@ class PartGuiExport ViewProviderPartExt : public Gui::ViewProviderGeometryObject virtual void onChanged(const App::Property* prop) override; bool loadParameter(); void updateVisual(); - void getNormals(const TopoDS_Face& theFace, const Handle(Poly_Triangulation)& aPolyTri, - TColgp_Array1OfDir& theNormals); // nodes for the data representation SoMaterialBinding * pcFaceBind; diff --git a/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp b/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp index 85bcf6e551d..642eb9dc76a 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp @@ -40,7 +40,8 @@ #endif #include "ViewProviderAddSub.h" -#include "Mod/Part/Gui/SoBrepFaceSet.h" +#include +#include #include #include #include @@ -196,7 +197,7 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() { const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); TColgp_Array1OfDir Normals (Nodes.Lower(), Nodes.Upper()); - getNormals(actFace, mesh, Normals); + Part::Tools::getPointNormals(actFace, mesh, Normals); for (int g=1;g<=nbTriInFace;g++) { // Get the triangle From 302568d177ddde171c28eaca89e8b4a49466974f Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 16:55:09 +0200 Subject: [PATCH] Part: copy ViewProviderPartExt::getNormals to Tools class --- src/Mod/Part/App/PreCompiled.h | 1 + src/Mod/Part/App/Tools.cpp | 87 ++++++++++++++++++++++++++++++++++ src/Mod/Part/App/Tools.h | 3 ++ 3 files changed, 91 insertions(+) diff --git a/src/Mod/Part/App/PreCompiled.h b/src/Mod/Part/App/PreCompiled.h index bb9b1cb04fb..636b5ea3cb8 100644 --- a/src/Mod/Part/App/PreCompiled.h +++ b/src/Mod/Part/App/PreCompiled.h @@ -94,6 +94,7 @@ #include "OpenCascadeAll.h" #include #include +#include #elif defined(FC_OS_WIN32) #define WIN32_LEAN_AND_MEAN diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index 41284befede..74664dfa50a 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -33,11 +33,13 @@ # include # include # include +# include # include # include # include # include # include +# include # include # include # include @@ -47,6 +49,7 @@ # include # include # include +# include # if OCC_VERSION_HEX < 0x070600 # include # include @@ -414,3 +417,87 @@ void Part::Tools::getPointNormals(const std::vector& points, const TopoD vertexnormals[i].Normalize(); } } + +void Part::Tools::getPointNormals(const TopoDS_Face& theFace, Handle(Poly_Triangulation) aPolyTri, TColgp_Array1OfDir& theNormals) +{ + const TColgp_Array1OfPnt& aNodes = aPolyTri->Nodes(); + + if(aPolyTri->HasNormals()) + { + // normals pre-computed in triangulation structure + const TShort_Array1OfShortReal& aNormals = aPolyTri->Normals(); + const Standard_ShortReal* aNormArr = &(aNormals.Value(aNormals.Lower())); + + for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + const Standard_Integer anId = 3 * (aNodeIter - aNodes.Lower()); + const gp_Dir aNorm(aNormArr[anId + 0], + aNormArr[anId + 1], + aNormArr[anId + 2]); + theNormals(aNodeIter) = aNorm; + } + + if(theFace.Orientation() == TopAbs_REVERSED) + { + for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + theNormals.ChangeValue(aNodeIter).Reverse(); + } + } + } + else { + // take in face the surface location + Poly_Connect thePolyConnect(aPolyTri); + const TopoDS_Face aZeroFace = TopoDS::Face(theFace.Located(TopLoc_Location())); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aZeroFace); + const Standard_Real aTol = Precision::Confusion(); + Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal(1, aPolyTri->NbNodes() * 3); + const Poly_Array1OfTriangle& aTriangles = aPolyTri->Triangles(); + const TColgp_Array1OfPnt2d* aNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull() + ? &aPolyTri->UVNodes() + : nullptr; + Standard_Integer aTri[3]; + + for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + // try to retrieve normal from real surface first, when UV coordinates are available + if (!aNodesUV || GeomLib::NormEstim(aSurf, aNodesUV->Value(aNodeIter), aTol, theNormals(aNodeIter)) > 1) + { + // compute flat normals + gp_XYZ eqPlan(0.0, 0.0, 0.0); + + for(thePolyConnect.Initialize(aNodeIter); thePolyConnect.More(); thePolyConnect.Next()) + { + aTriangles(thePolyConnect.Value()).Get(aTri[0], aTri[1], aTri[2]); + const gp_XYZ v1(aNodes(aTri[1]).Coord() - aNodes(aTri[0]).Coord()); + const gp_XYZ v2(aNodes(aTri[2]).Coord() - aNodes(aTri[1]).Coord()); + const gp_XYZ vv = v1 ^ v2; + const Standard_Real aMod = vv.Modulus(); + + if(aMod >= aTol) + { + eqPlan += vv / aMod; + } + } + + const Standard_Real aModMax = eqPlan.Modulus(); + theNormals(aNodeIter) = (aModMax > aTol) ? gp_Dir(eqPlan) : gp::DZ(); + } + + const Standard_Integer anId = (aNodeIter - aNodes.Lower()) * 3; + aNormals->SetValue(anId + 1, (Standard_ShortReal)theNormals(aNodeIter).X()); + aNormals->SetValue(anId + 2, (Standard_ShortReal)theNormals(aNodeIter).Y()); + aNormals->SetValue(anId + 3, (Standard_ShortReal)theNormals(aNodeIter).Z()); + } + + aPolyTri->SetNormals(aNormals); + + if(theFace.Orientation() == TopAbs_REVERSED) + { + for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + theNormals.ChangeValue(aNodeIter).Reverse(); + } + } + } +} diff --git a/src/Mod/Part/App/Tools.h b/src/Mod/Part/App/Tools.h index a487530a7dc..43a01123b71 100644 --- a/src/Mod/Part/App/Tools.h +++ b/src/Mod/Part/App/Tools.h @@ -31,7 +31,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -151,6 +153,7 @@ class PartExport Tools * \param vertexnormals */ static void getPointNormals(const std::vector& points, const TopoDS_Face& face, std::vector& vertexnormals); + static void getPointNormals(const TopoDS_Face& face, Handle(Poly_Triangulation) aPoly, TColgp_Array1OfDir& normals); }; } //namespace Part From 66d3dd897f63c2e4f8ffd6eced730c6a3372ad51 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Oct 2021 11:37:18 +0200 Subject: [PATCH] Part: add convenience function to convert TColgp_Array1OfDir to std::vector --- src/Mod/Part/App/Tools.cpp | 88 ++++++++++++++++++++++++++++++++++++++ src/Mod/Part/App/Tools.h | 23 ++++++++++ 2 files changed, 111 insertions(+) diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index 74664dfa50a..0a85e0c6df6 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -420,6 +420,7 @@ void Part::Tools::getPointNormals(const std::vector& points, const TopoD void Part::Tools::getPointNormals(const TopoDS_Face& theFace, Handle(Poly_Triangulation) aPolyTri, TColgp_Array1OfDir& theNormals) { +#if OCC_VERSION_HEX < 0x070600 const TColgp_Array1OfPnt& aNodes = aPolyTri->Nodes(); if(aPolyTri->HasNormals()) @@ -500,4 +501,91 @@ void Part::Tools::getPointNormals(const TopoDS_Face& theFace, Handle(Poly_Triang } } } +#else + Standard_Integer numNodes = aPolyTri->NbNodes(); + + if(aPolyTri->HasNormals()) + { + for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter) + { + theNormals(aNodeIter) = aPolyTri->Normal(aNodeIter); + } + + if(theFace.Orientation() == TopAbs_REVERSED) + { + for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter) + { + theNormals.ChangeValue(aNodeIter).Reverse(); + } + } + } + else { + // take in face the surface location + Poly_Connect thePolyConnect(aPolyTri); + const TopoDS_Face aZeroFace = TopoDS::Face(theFace.Located(TopLoc_Location())); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aZeroFace); + const Standard_Real aTol = Precision::Confusion(); + Standard_Boolean hasNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull(); + Standard_Integer aTri[3]; + + for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter) + { + // try to retrieve normal from real surface first, when UV coordinates are available + if (!hasNodesUV || GeomLib::NormEstim(aSurf, aPolyTri->UVNode(aNodeIter), aTol, theNormals(aNodeIter)) > 1) + { + // compute flat normals + gp_XYZ eqPlan(0.0, 0.0, 0.0); + + for(thePolyConnect.Initialize(aNodeIter); thePolyConnect.More(); thePolyConnect.Next()) + { + aPolyTri->Triangle(thePolyConnect.Value()).Get(aTri[0], aTri[1], aTri[2]); + const gp_XYZ v1(aPolyTri->Node(aTri[1]).Coord() - aPolyTri->Node(aTri[0]).Coord()); + const gp_XYZ v2(aPolyTri->Node(aTri[2]).Coord() - aPolyTri->Node(aTri[1]).Coord()); + const gp_XYZ vv = v1 ^ v2; + const Standard_Real aMod = vv.Modulus(); + + if(aMod >= aTol) + { + eqPlan += vv / aMod; + } + } + + const Standard_Real aModMax = eqPlan.Modulus(); + theNormals(aNodeIter) = (aModMax > aTol) ? gp_Dir(eqPlan) : gp::DZ(); + } + + aPolyTri->SetNormal(aNodeIter, theNormals(aNodeIter)); + } + + if(theFace.Orientation() == TopAbs_REVERSED) + { + for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter) + { + theNormals.ChangeValue(aNodeIter).Reverse(); + } + } + } +#endif +} + +void Part::Tools::getPointNormals(const TopoDS_Face& face, Handle(Poly_Triangulation) aPoly, std::vector& normals) +{ + TColgp_Array1OfDir dirs (1, aPoly->NbNodes()); + getPointNormals(face, aPoly, dirs); + normals.reserve(aPoly->NbNodes()); + + for (int i = dirs.Lower(); i <= dirs.Upper(); ++i) { + normals.emplace_back(dirs(i).XYZ()); + } +} + +void Part::Tools::applyTransformationOnNormals(const TopLoc_Location& loc, std::vector& normals) +{ + if (!loc.IsIdentity()) { + gp_Trsf myTransf = loc.Transformation(); + + for (auto& it : normals) { + it.Transform(myTransf); + } + } } diff --git a/src/Mod/Part/App/Tools.h b/src/Mod/Part/App/Tools.h index 43a01123b71..425032a12d9 100644 --- a/src/Mod/Part/App/Tools.h +++ b/src/Mod/Part/App/Tools.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -153,7 +154,29 @@ class PartExport Tools * \param vertexnormals */ static void getPointNormals(const std::vector& points, const TopoDS_Face& face, std::vector& vertexnormals); + /*! + * \brief getPointNormals + * Computes the exact surface normals for the points by using the UV coordinates of the mesh vertexes. + * \param face + * \param aPoly + * \param vertexnormals + */ static void getPointNormals(const TopoDS_Face& face, Handle(Poly_Triangulation) aPoly, TColgp_Array1OfDir& normals); + /*! + * \brief getPointNormals + * Computes the exact surface normals for the points by using the UV coordinates of the mesh vertexes. + * \param face + * \param aPoly + * \param vertexnormals + */ + static void getPointNormals(const TopoDS_Face& face, Handle(Poly_Triangulation) aPoly, std::vector& normals); + /*! + * \brief applyTransformationOnNormals + * Apply the transformation to the vectors + * \param loc + * \param normals + */ + static void applyTransformationOnNormals(const TopLoc_Location& loc, std::vector& normals); }; } //namespace Part From 03be15cc6b460ab62548142287eb9f677f463a44 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Oct 2021 14:34:04 +0200 Subject: [PATCH] Part: fix bug in Part::Tools::getPointNormals for OCCT 7.6 --- src/Mod/Part/App/Tools.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index 0a85e0c6df6..d95e49eaf4f 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -528,6 +528,7 @@ void Part::Tools::getPointNormals(const TopoDS_Face& theFace, Handle(Poly_Triang Standard_Boolean hasNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull(); Standard_Integer aTri[3]; + aPolyTri->AddNormals(); for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter) { // try to retrieve normal from real surface first, when UV coordinates are available From f628050732cc5d1d49fc18282ed508ca3061bb10 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Oct 2021 11:38:25 +0200 Subject: [PATCH] PD: simplify code to display add/sub shape --- src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp | 111 ++++++------------ 1 file changed, 39 insertions(+), 72 deletions(-) diff --git a/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp b/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp index 642eb9dc76a..2e2d2a55e54 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp @@ -116,9 +116,6 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() { return; } - int numTriangles=0,numNodes=0,numNorms=0,numFaces=0; - std::set faceEdges; - try { // calculating the deflection value Bnd_Box bounds; @@ -126,16 +123,14 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() { bounds.SetGap(0.0); Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); - Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * - Deviation.getValue(); + Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue(); // create or use the mesh on the data structure #if OCC_VERSION_HEX >= 0x060600 Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI; - BRepMesh_IncrementalMesh(cShape,deflection,Standard_False, - AngDeflectionRads,Standard_True); + BRepMesh_IncrementalMesh(cShape, deflection, Standard_False, AngDeflectionRads, Standard_True); #else - BRepMesh_IncrementalMesh(cShape,deflection); + BRepMesh_IncrementalMesh(cShape, deflection); #endif // We must reset the location here because the transformation data // are set in the placement property @@ -143,6 +138,7 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() { cShape.Location(aLoc); // count triangles and nodes in the mesh + int numTriangles=0,numNodes=0,numNorms=0,numFaces=0; TopExp_Explorer Ex; for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) { Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc); @@ -160,11 +156,12 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() { previewNorm ->vector .setNum(numNorms); previewFaceSet ->coordIndex .setNum(numTriangles*4); previewFaceSet ->partIndex .setNum(numFaces); + // get the raw memory for fast fill up - SbVec3f* verts = previewCoords ->point .startEditing(); - SbVec3f* previewNorms = previewNorm ->vector .startEditing(); - int32_t* index = previewFaceSet ->coordIndex .startEditing(); - int32_t* parts = previewFaceSet ->partIndex .startEditing(); + SbVec3f* verts = previewCoords ->point .startEditing(); + SbVec3f* previewNorms = previewNorm ->vector .startEditing(); + int32_t* index = previewFaceSet ->coordIndex .startEditing(); + int32_t* parts = previewFaceSet ->partIndex .startEditing(); // preset the previewNormal vector with null vector for (int i=0;i < numNorms;i++) @@ -172,76 +169,46 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() { int ii = 0,faceNodeOffset=0,faceTriaOffset=0; for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) { - TopLoc_Location aLoc; const TopoDS_Face &actFace = TopoDS::Face(Ex.Current()); - // get the mesh of the shape - Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc); - if (mesh.IsNull()) continue; - - // getting the transformation of the shape/face - gp_Trsf myTransf; - Standard_Boolean identity = true; - if (!aLoc.IsIdentity()) { - identity = false; - myTransf = aLoc.Transformation(); - } + + TopLoc_Location loc; + Handle(Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace, loc); + if (mesh.IsNull()) + continue; + + // get triangulation + std::vector points; + std::vector facets; + Part::Tools::getTriangulation(actFace, points, facets); + + // get normal per vertex + std::vector vertexnormals; + Part::Tools::getPointNormals(actFace, mesh, vertexnormals); + Part::Tools::applyTransformationOnNormals(loc, vertexnormals); // getting size of node and triangle array of this face - int nbNodesInFace = mesh->NbNodes(); - int nbTriInFace = mesh->NbTriangles(); - // check orientation - TopAbs_Orientation orient = actFace.Orientation(); + std::size_t nbNodesInFace = points.size(); + std::size_t nbTriInFace = facets.size(); + for (std::size_t i = 0; i < points.size(); i++) { + verts[faceNodeOffset+i] = SbVec3f(points[i].X(), points[i].Y(), points[i].Z()); + } - // cycling through the poly mesh - const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); - const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); - TColgp_Array1OfDir Normals (Nodes.Lower(), Nodes.Upper()); - Part::Tools::getPointNormals(actFace, mesh, Normals); + for (std::size_t i = 0; i < vertexnormals.size(); i++) { + previewNorms[faceNodeOffset+i] = SbVec3f(vertexnormals[i].X(), vertexnormals[i].Y(), vertexnormals[i].Z()); + } - for (int g=1;g<=nbTriInFace;g++) { + // cycling through the poly mesh + for (std::size_t g=0; g < nbTriInFace; g++) { // Get the triangle Standard_Integer N1,N2,N3; - Triangles(g).Get(N1,N2,N3); - - // change orientation of the triangle if the face is reversed - if ( orient != TopAbs_FORWARD ) { - Standard_Integer tmp = N1; - N1 = N2; - N2 = tmp; - } - - // get the 3 points of this triangle - gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3)); - - // get the 3 previewNormals of this triangle - gp_Dir NV1(Normals(N1)), NV2(Normals(N2)), NV3(Normals(N3)); - - // transform the vertices and previewNormals to the place of the face - if(!identity) { - V1.Transform(myTransf); - V2.Transform(myTransf); - V3.Transform(myTransf); - NV1.Transform(myTransf); - NV2.Transform(myTransf); - NV3.Transform(myTransf); - } - - // add the previewNormals for all points of this triangle - previewNorms[faceNodeOffset+N1-1] += SbVec3f(NV1.X(),NV1.Y(),NV1.Z()); - previewNorms[faceNodeOffset+N2-1] += SbVec3f(NV2.X(),NV2.Y(),NV2.Z()); - previewNorms[faceNodeOffset+N3-1] += SbVec3f(NV3.X(),NV3.Y(),NV3.Z()); - - // set the vertices - verts[faceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z())); - verts[faceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z())); - verts[faceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z())); + facets[g].Get(N1,N2,N3); // set the index vector with the 3 point indexes and the end delimiter - index[faceTriaOffset*4+4*(g-1)] = faceNodeOffset+N1-1; - index[faceTriaOffset*4+4*(g-1)+1] = faceNodeOffset+N2-1; - index[faceTriaOffset*4+4*(g-1)+2] = faceNodeOffset+N3-1; - index[faceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX; + index[faceTriaOffset*4+4*g] = faceNodeOffset+N1; + index[faceTriaOffset*4+4*g+1] = faceNodeOffset+N2; + index[faceTriaOffset*4+4*g+2] = faceNodeOffset+N3; + index[faceTriaOffset*4+4*g+3] = SO_END_FACE_INDEX; } parts[ii] = nbTriInFace; // new part From 16ff933b09176d83fb0785e74f36038311f0eaeb Mon Sep 17 00:00:00 2001 From: David Osterberg Date: Sat, 27 Feb 2021 09:27:23 +0100 Subject: [PATCH] PartDesign: Transformded. Align the "property category" of Refine with other PD commands --- src/Mod/PartDesign/App/FeatureTransformed.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Mod/PartDesign/App/FeatureTransformed.cpp b/src/Mod/PartDesign/App/FeatureTransformed.cpp index 1818338dbcf..d24a0199f20 100644 --- a/src/Mod/PartDesign/App/FeatureTransformed.cpp +++ b/src/Mod/PartDesign/App/FeatureTransformed.cpp @@ -65,7 +65,7 @@ Transformed::Transformed() Originals.setSize(0); Placement.setStatus(App::Property::ReadOnly, true); - ADD_PROPERTY_TYPE(Refine,(0),"SketchBased",(App::PropertyType)(App::Prop_None),"Refine shape (clean up redundant edges) after adding/subtracting"); + ADD_PROPERTY_TYPE(Refine,(0),"Part Design",(App::PropertyType)(App::Prop_None),"Refine shape (clean up redundant edges) after adding/subtracting"); //init Refine property Base::Reference hGrp = App::GetApplication().GetUserParameter() @@ -89,7 +89,7 @@ Part::Feature* Transformed::getBaseObject(bool silent) const { const char* err = nullptr; const std::vector & originals = Originals.getValues(); - // NOTE: may be here supposed to be last origin but in order to keep the old behaviour keep here first + // NOTE: may be here supposed to be last origin but in order to keep the old behaviour keep here first App::DocumentObject* firstOriginal = originals.empty() ? NULL : originals.front(); if (firstOriginal) { if(firstOriginal->isDerivedFrom(Part::Feature::getClassTypeId())) { @@ -272,7 +272,7 @@ App::DocumentObjectExecReturn *Transformed::execute(void) fuseShape = fuseShape.makETransform(trsf); if (!cutShape.isNull()) cutShape = cutShape.makETransform(trsf); - } + } else { return new App::DocumentObjectExecReturn("Only additive and subtractive features can be transformed"); } @@ -323,17 +323,17 @@ App::DocumentObjectExecReturn *Transformed::execute(void) // // Therefore, if the transformation succeeded, then we fuse it with the support now, before checking the intersection // of the next transformation. - + /*v_transformations.push_back(t); v_transformedShapes.push_back(mkTrf.Shape());*/ - + // Note: Transformations that do not intersect the support are ignored in the overlap tests - + //insert scheme here. /*TopoDS_Compound compoundTool; std::vector individualTools; divideTools(v_transformedShapes, individualTools, compoundTool);*/ - + // Fuse/Cut the compounded transformed shapes with the support //TopoDS_Shape result; @@ -361,7 +361,7 @@ App::DocumentObjectExecReturn *Transformed::execute(void) shape = copy.Shape(); if (shape.IsNull()) return new App::DocumentObjectExecReturn("Transformed: Linked shape object is empty"); - + BRepBuilderAPI_Transform mkTrf(shape, *t, false); // No need to copy, now if (!mkTrf.IsDone()) return new App::DocumentObjectExecReturn("Transformation failed", (*o)); @@ -378,7 +378,7 @@ App::DocumentObjectExecReturn *Transformed::execute(void) } catch (Standard_Failure& e) { // Note: Ignoring this failure is probably pointless because if the intersection check fails, the later // fuse operation of the transformation result will also fail - + std::string msg("Transformation: Intersection check failed"); if (e.GetMessageString() != NULL) msg += std::string(": '") + e.GetMessageString() + "'"; From 03da9d3501c6b596ad1828b99cb8d923cea56485 Mon Sep 17 00:00:00 2001 From: David Osterberg Date: Sun, 21 Feb 2021 15:33:35 +0100 Subject: [PATCH] PartDesign: Performance improvements in Transformed (pattern) - Use fuzzy fuse/cut method with tolerance Precision::Confusion() - Use parallel computation feature - Allow that individual patterned item fail to intersect the baseobject. Issue warning instead of error. This was done for performance reasons but it can also be considered a feature. - Simplify the code a bit - Distinguish between overlapping mode and non-overlapping mode. In non-overlapping mode the tool shapes are compounded instead of fused. For huge benefit in performance. --- src/Mod/PartDesign/App/FeatureTransformed.cpp | 191 ++++++++---------- 1 file changed, 79 insertions(+), 112 deletions(-) diff --git a/src/Mod/PartDesign/App/FeatureTransformed.cpp b/src/Mod/PartDesign/App/FeatureTransformed.cpp index d24a0199f20..9e638f32d7f 100644 --- a/src/Mod/PartDesign/App/FeatureTransformed.cpp +++ b/src/Mod/PartDesign/App/FeatureTransformed.cpp @@ -36,6 +36,9 @@ # include #endif +#ifndef FC_DEBUG +#include +#endif #include "FeatureTransformed.h" #include "FeatureMultiTransform.h" @@ -198,7 +201,11 @@ short Transformed::mustExecute() const App::DocumentObjectExecReturn *Transformed::execute(void) { - rejected.clear(); + +#ifndef FC_DEBUG + std::clock_t start0; + start0 = std::clock(); +#endif std::vector originals = Originals.getValues(); if (originals.empty()) // typically InsideMultiTransform @@ -246,10 +253,6 @@ App::DocumentObjectExecReturn *Transformed::execute(void) supportShape.setTransform(Base::Matrix4D()); TopoDS_Shape support = supportShape.getShape(); - typedef std::set::const_iterator> trsf_it; - typedef std::map rej_it_map; - rej_it_map nointersect_trsfms; - // NOTE: It would be possible to build a compound from all original addShapes/subShapes and then // transform the compounds as a whole. But we choose to apply the transformations to each // Original separately. This way it is easier to discover what feature causes a fuse/cut @@ -276,132 +279,93 @@ App::DocumentObjectExecReturn *Transformed::execute(void) else { return new App::DocumentObjectExecReturn("Only additive and subtractive features can be transformed"); } + TopoDS_Shape origShape = fuseShape.isNull()?cutShape.getShape():fuseShape.getShape(); + + TopoDS_Shape current = support; - // Transform the add/subshape and collect the resulting shapes for overlap testing - /*typedef std::vector::const_iterator> trsf_it_vec; - trsf_it_vec v_transformations; - std::vector v_transformedShapes;*/ + BRep_Builder builder; + TopoDS_Compound compShape; + builder.MakeCompound(compShape); + std::vector shapes; + bool overlapping = false; std::vector::const_iterator t = transformations.begin(); ++t; // Skip first transformation, which is always the identity transformation for (; t != transformations.end(); ++t) { // Make an explicit copy of the shape because the "true" parameter to BRepBuilderAPI_Transform // seems to be pretty broken - BRepBuilderAPI_Copy copy(fuseShape.isNull()?cutShape.getShape():fuseShape.getShape()); + BRepBuilderAPI_Copy copy(origShape); + shape = copy.Shape(); - if (shape.IsNull()) - return new App::DocumentObjectExecReturn("Transformed: Linked shape object is empty"); - - BRepBuilderAPI_Transform mkTrf(shape, *t, false); // No need to copy, now - if (!mkTrf.IsDone()) - return new App::DocumentObjectExecReturn("Transformation failed", (*o)); - - shape = mkTrf.Shape(); - try { - // Intersection checking for additive shape is redundant. - // Because according to CheckIntersection() source code, it is - // implemented using fusion and counting of the resulting - // solid, which will be done in the following modeling step - // anyway. - // - // There is little reason for doing intersection checking on - // subtractive shape either, because it does not produce - // multiple solids. - // - // if (!Part::checkIntersection(support, mkTrf.Shape(), false, true)) { - - - TopoDS_Shape current = support; - - if (!fuseShape.isNull()) { - // We cannot wait to fuse a transformation with the support until all the transformations are done, - // because the "support" potentially changes with every transformation, basically when checking intersection - // above you need: - // 1. The original support - // 2. Any extra support gained by any previous transformation of any previous feature (multi-feature transform) - // 3. Any extra support gained by any previous transformation of this feature (feature multi-trasform) - // - // Therefore, if the transformation succeeded, then we fuse it with the support now, before checking the intersection - // of the next transformation. - - /*v_transformations.push_back(t); - v_transformedShapes.push_back(mkTrf.Shape());*/ - - // Note: Transformations that do not intersect the support are ignored in the overlap tests - - //insert scheme here. - /*TopoDS_Compound compoundTool; - std::vector individualTools; - divideTools(v_transformedShapes, individualTools, compoundTool);*/ - - // Fuse/Cut the compounded transformed shapes with the support - //TopoDS_Shape result; - - BRepAlgoAPI_Fuse mkFuse(current, shape); - if (!mkFuse.IsDone()) - return new App::DocumentObjectExecReturn("Fusion with support failed", *o); - - if(Part::TopoShape(current).countSubShapes(TopAbs_SOLID) - != Part::TopoShape(mkFuse.Shape()).countSubShapes(TopAbs_SOLID)) - { -#ifdef FC_DEBUG // do not write this in release mode because a message appears already in the task view - Base::Console().Warning("Transformed shape does not intersect support %s: Removed\n", (*o)->getNameInDocument()); + + shape.Move(*t); + shapes.emplace_back(shape); + builder.Add(compShape, shape); + + overlapping = overlapping || (countSolids(TopoShape(origShape).fuse(shape))==1); + + } + + TopoDS_Shape toolShape; + + if (overlapping) { + +#ifndef FC_DEBUG + Base::Console().Message("Transformed: Overlapping feature mode (fusing tool shapes)\n"); #endif - nointersect_trsfms[*o].insert(t); - continue; - } - // we have to get the solids (fuse sometimes creates compounds) - current = this->getSolid(mkFuse.Shape()); - // lets check if the result is a solid - if (current.IsNull()) - return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o); - - if (!cutShape.isNull()) { - BRepBuilderAPI_Copy copy(cutShape.getShape()); - shape = copy.Shape(); - if (shape.IsNull()) - return new App::DocumentObjectExecReturn("Transformed: Linked shape object is empty"); - - BRepBuilderAPI_Transform mkTrf(shape, *t, false); // No need to copy, now - if (!mkTrf.IsDone()) - return new App::DocumentObjectExecReturn("Transformation failed", (*o)); - shape = mkTrf.Shape(); - } - } - if (!cutShape.isNull()) { - BRepAlgoAPI_Cut mkCut(current, shape); - if (!mkCut.IsDone()) - return new App::DocumentObjectExecReturn("Cut out of support failed", *o); - current = mkCut.Shape(); - } - support = current; // Use result of this operation for fuse/cut of next original - } catch (Standard_Failure& e) { - // Note: Ignoring this failure is probably pointless because if the intersection check fails, the later - // fuse operation of the transformation result will also fail - - std::string msg("Transformation: Intersection check failed"); - if (e.GetMessageString() != NULL) - msg += std::string(": '") + e.GetMessageString() + "'"; - return new App::DocumentObjectExecReturn(msg.c_str()); + + toolShape = TopoShape(origShape).fuse(shapes, Precision::Confusion()); + } else { + +#ifndef FC_DEBUG + Base::Console().Message("Transformed: Non-Overlapping feature mode (compound of tool shapes)\n"); +#endif + + toolShape = compShape; + } + + if (!fuseShape.isNull()) { + std::unique_ptr mkBool(new BRepAlgoAPI_Fuse(current, toolShape)); + if (!mkBool->IsDone()) { + std::stringstream error; + error << "Boolean operation failed"; + return new App::DocumentObjectExecReturn(error.str()); + } + current = mkBool->Shape(); + } else { + std::unique_ptr mkBool(new BRepAlgoAPI_Cut(current, toolShape)); + if (!mkBool->IsDone()) { + std::stringstream error; + error << "Boolean operation failed"; + return new App::DocumentObjectExecReturn(error.str()); } + current = mkBool->Shape(); + } + try {} catch (Standard_Failure& e) { + // Note: Ignoring this failure is probably pointless because if the intersection check fails, the later + // fuse operation of the transformation result will also fail + + std::string msg("Transformation: Intersection check failed"); + if (e.GetMessageString() != NULL) + msg += std::string(": '") + e.GetMessageString() + "'"; + return new App::DocumentObjectExecReturn(msg.c_str()); } + + support = current; // Use result of this operation for fuse/cut of next original } - support = refineShapeIfActive(support); - for (rej_it_map::const_iterator it = nointersect_trsfms.begin(); it != nointersect_trsfms.end(); ++it) - for (trsf_it::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) - rejected[it->first].push_back(**it2); + support = refineShapeIfActive(support); int solidCount = countSolids(support); if (solidCount > 1) { - return new App::DocumentObjectExecReturn("Transformed: Result has multiple solids. This is not supported at this time."); + Base::Console().Warning("Transformed: Result has multiple solids. Only keeping the first.\n"); } - this->Shape.setValue(getSolid(support)); + this->Shape.setValue(getSolid(support)); // picking the first solid - if (rejected.size() > 0) { - return new App::DocumentObjectExecReturn("Transformation failed"); - } +#ifndef FC_DEBUG + Base::Console().Message("Transformed: Elapsed CPU time: %f s\n", (std::clock() - start0 ) / (double)(CLOCKS_PER_SEC)); +#endif return App::DocumentObject::StdReturn; } @@ -412,6 +376,9 @@ TopoDS_Shape Transformed::refineShapeIfActive(const TopoDS_Shape& oldShape) cons try { Part::BRepBuilderAPI_RefineModel mkRefine(oldShape); TopoDS_Shape resShape = mkRefine.Shape(); + if (!TopoShape(resShape).isClosed()) { + return oldShape; + } return resShape; } catch (Standard_Failure&) { From fecf9c2e8492ddab0858b4af23b56da36bff6f6a Mon Sep 17 00:00:00 2001 From: David Osterberg Date: Tue, 23 Feb 2021 13:35:05 +0100 Subject: [PATCH] PartDesign: Transformed: Allow explict selection of overlap mode --- src/Mod/PartDesign/App/FeatureTransformed.cpp | 23 +++++++++++-------- src/Mod/PartDesign/App/FeatureTransformed.h | 8 +++++-- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/Mod/PartDesign/App/FeatureTransformed.cpp b/src/Mod/PartDesign/App/FeatureTransformed.cpp index 9e638f32d7f..cd35a4e3e69 100644 --- a/src/Mod/PartDesign/App/FeatureTransformed.cpp +++ b/src/Mod/PartDesign/App/FeatureTransformed.cpp @@ -60,6 +60,8 @@ using namespace PartDesign; namespace PartDesign { +const char* Transformed::OverlapEnums[] = { "Detect", "Overlap mode", "Non-overlap mode", NULL}; + PROPERTY_SOURCE(PartDesign::Transformed, PartDesign::Feature) Transformed::Transformed() @@ -69,6 +71,8 @@ Transformed::Transformed() Placement.setStatus(App::Property::ReadOnly, true); ADD_PROPERTY_TYPE(Refine,(0),"Part Design",(App::PropertyType)(App::Prop_None),"Refine shape (clean up redundant edges) after adding/subtracting"); + ADD_PROPERTY_TYPE(Overlap, (0L), "Transform", App::Prop_None, "Feature overlapping behaviour"); + Overlap.setEnums(OverlapEnums); //init Refine property Base::Reference hGrp = App::GetApplication().GetUserParameter() @@ -201,6 +205,8 @@ short Transformed::mustExecute() const App::DocumentObjectExecReturn *Transformed::execute(void) { + std::string overlapMode = Overlap.getValueAsString(); + bool overlapDetectionMode = overlapMode == "Detect"; #ifndef FC_DEBUG std::clock_t start0; @@ -302,27 +308,24 @@ App::DocumentObjectExecReturn *Transformed::execute(void) shapes.emplace_back(shape); builder.Add(compShape, shape); - overlapping = overlapping || (countSolids(TopoShape(origShape).fuse(shape))==1); + if (overlapDetectionMode) + overlapping = overlapping || (countSolids(TopoShape(origShape).fuse(shape))==1); } TopoDS_Shape toolShape; - if (overlapping) { - #ifndef FC_DEBUG + if (overlapping || overlapMode == "Overlap mode") Base::Console().Message("Transformed: Overlapping feature mode (fusing tool shapes)\n"); -#endif - - toolShape = TopoShape(origShape).fuse(shapes, Precision::Confusion()); - } else { - -#ifndef FC_DEBUG + else Base::Console().Message("Transformed: Non-Overlapping feature mode (compound of tool shapes)\n"); #endif + if (overlapping || overlapMode == "Overlap mode") + toolShape = TopoShape(origShape).fuse(shapes, Precision::Confusion()); + else toolShape = compShape; - } if (!fuseShape.isNull()) { std::unique_ptr mkBool(new BRepAlgoAPI_Fuse(current, toolShape)); diff --git a/src/Mod/PartDesign/App/FeatureTransformed.h b/src/Mod/PartDesign/App/FeatureTransformed.h index ccb807ba433..b3ab64bc774 100644 --- a/src/Mod/PartDesign/App/FeatureTransformed.h +++ b/src/Mod/PartDesign/App/FeatureTransformed.h @@ -50,12 +50,13 @@ class PartDesignExport Transformed : public PartDesign::Feature App::PropertyLinkList Originals; App::PropertyBool Refine; + App::PropertyEnumeration Overlap; /** * Returns the BaseFeature property's object(if any) otherwise return first original, * which serves as "Support" for old style workflows * @param silent if couldn't determine the base feature and silent == true, - * silently return a nullptr, otherwise throw Base::Exception. + * silently return a nullptr, otherwise throw Base::Exception. * Default is false. */ virtual Part::Feature* getBaseObject(bool silent=false) const; @@ -93,9 +94,12 @@ class PartDesignExport Transformed : public PartDesign::Feature virtual void positionBySupport(void); TopoDS_Shape refineShapeIfActive(const TopoDS_Shape&) const; void divideTools(const std::vector &toolsIn, std::vector &individualsOut, - TopoDS_Compound &compoundOut) const; + TopoDS_Compound &compoundOut) const; rejectedMap rejected; + +private: + static const char* OverlapEnums[]; }; } //namespace PartDesign From 8453d415150f289d36dfe4cbe6b91dfc512e82fe Mon Sep 17 00:00:00 2001 From: David Osterberg Date: Sun, 28 Feb 2021 10:10:29 +0100 Subject: [PATCH] PartDesign: Transformed. Fix regression for Mirrored, and multiple features --- src/Mod/PartDesign/App/FeatureTransformed.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Mod/PartDesign/App/FeatureTransformed.cpp b/src/Mod/PartDesign/App/FeatureTransformed.cpp index cd35a4e3e69..d241e767bf8 100644 --- a/src/Mod/PartDesign/App/FeatureTransformed.cpp +++ b/src/Mod/PartDesign/App/FeatureTransformed.cpp @@ -296,7 +296,8 @@ App::DocumentObjectExecReturn *Transformed::execute(void) bool overlapping = false; std::vector::const_iterator t = transformations.begin(); - ++t; // Skip first transformation, which is always the identity transformation + //++t; // Skip first transformation, which is always the identity transformation + bool first = true; for (; t != transformations.end(); ++t) { // Make an explicit copy of the shape because the "true" parameter to BRepBuilderAPI_Transform // seems to be pretty broken @@ -304,13 +305,19 @@ App::DocumentObjectExecReturn *Transformed::execute(void) shape = copy.Shape(); - shape.Move(*t); + BRepBuilderAPI_Transform mkTrf(shape, *t, false); // No need to copy, now + if (!mkTrf.IsDone()) + return new App::DocumentObjectExecReturn("Transformation failed", (*o)); + shape = mkTrf.Shape(); + shapes.emplace_back(shape); builder.Add(compShape, shape); - if (overlapDetectionMode) + if (overlapDetectionMode && !first) overlapping = overlapping || (countSolids(TopoShape(origShape).fuse(shape))==1); + if (first) + first = false; } TopoDS_Shape toolShape; From 3131b97aa88736ac628428a8ceb025d9b7a8a965 Mon Sep 17 00:00:00 2001 From: David Osterberg Date: Sun, 28 Feb 2021 13:35:14 +0100 Subject: [PATCH] PartDesign: Transformed. Fix regression in preview --- src/Mod/PartDesign/App/FeatureTransformed.cpp | 21 ++++- src/Mod/PartDesign/App/FeatureTransformed.h | 10 +-- .../Gui/ViewProviderTransformed.cpp | 78 ++++++++----------- 3 files changed, 56 insertions(+), 53 deletions(-) diff --git a/src/Mod/PartDesign/App/FeatureTransformed.cpp b/src/Mod/PartDesign/App/FeatureTransformed.cpp index d241e767bf8..1acf6193b2a 100644 --- a/src/Mod/PartDesign/App/FeatureTransformed.cpp +++ b/src/Mod/PartDesign/App/FeatureTransformed.cpp @@ -296,7 +296,6 @@ App::DocumentObjectExecReturn *Transformed::execute(void) bool overlapping = false; std::vector::const_iterator t = transformations.begin(); - //++t; // Skip first transformation, which is always the identity transformation bool first = true; for (; t != transformations.end(); ++t) { // Make an explicit copy of the shape because the "true" parameter to BRepBuilderAPI_Transform @@ -372,6 +371,7 @@ App::DocumentObjectExecReturn *Transformed::execute(void) } this->Shape.setValue(getSolid(support)); // picking the first solid + rejected = getRemainingSolids(support); #ifndef FC_DEBUG Base::Console().Message("Transformed: Elapsed CPU time: %f s\n", (std::clock() - start0 ) / (double)(CLOCKS_PER_SEC)); @@ -454,4 +454,23 @@ void Transformed::divideTools(const std::vector &toolsIn, std::vec } } +TopoDS_Shape Transformed::getRemainingSolids(const TopoDS_Shape& shape) +{ + BRep_Builder builder; + TopoDS_Compound compShape; + builder.MakeCompound(compShape); + + if (shape.IsNull()) + Standard_Failure::Raise("Shape is null"); + TopExp_Explorer xp; + xp.Init(shape,TopAbs_SOLID); + xp.Next(); // skip the first + + for (; xp.More(); xp.Next()) { + builder.Add(compShape, xp.Current()); + } + + return compShape; +} + } diff --git a/src/Mod/PartDesign/App/FeatureTransformed.h b/src/Mod/PartDesign/App/FeatureTransformed.h index b3ab64bc774..e3068714976 100644 --- a/src/Mod/PartDesign/App/FeatureTransformed.h +++ b/src/Mod/PartDesign/App/FeatureTransformed.h @@ -83,20 +83,18 @@ class PartDesignExport Transformed : public PartDesign::Feature short mustExecute() const; //@} - /** returns a list of the transformations that where rejected during the last execute + /** returns the compound of the shapes that were rejected during the last execute * because they did not overlap with the support */ - typedef std::map > rejectedMap; - const rejectedMap getRejectedTransformations(void) { return rejected; } + TopoDS_Shape rejected; protected: void Restore(Base::XMLReader &reader); virtual void positionBySupport(void); TopoDS_Shape refineShapeIfActive(const TopoDS_Shape&) const; void divideTools(const std::vector &toolsIn, std::vector &individualsOut, - TopoDS_Compound &compoundOut) const; - - rejectedMap rejected; + TopoDS_Compound &compoundOut) const; + static TopoDS_Shape getRemainingSolids(const TopoDS_Shape&); private: static const char* OverlapEnums[]; diff --git a/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp b/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp index 1f83738f164..0d402d0b71a 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp @@ -157,10 +157,15 @@ void ViewProviderTransformed::recomputeFeature(bool recompute) PartDesign::Transformed* pcTransformed = static_cast(getObject()); if(recompute || (pcTransformed->isError() || pcTransformed->mustExecute())) pcTransformed->recomputeFeature(true); - const PartDesign::Transformed::rejectedMap &rejected_trsf = pcTransformed->getRejectedTransformations(); + unsigned rejected = 0; - for (PartDesign::Transformed::rejectedMap::const_iterator r = rejected_trsf.begin(); r != rejected_trsf.end(); r++) - rejected += r->second.size(); + TopoDS_Shape cShape = pcTransformed->rejected; + TopExp_Explorer xp; + xp.Init(cShape, TopAbs_SOLID); + for (; xp.More(); xp.Next()) { + rejected++; + } + QString msg = QString::fromLatin1("%1"); if (rejected > 0) { msg = QString::fromLatin1("%1
\r\n%2"); @@ -192,21 +197,9 @@ void ViewProviderTransformed::recomputeFeature(bool recompute) pcRejectedRoot ->removeChild(7); } - for (PartDesign::Transformed::rejectedMap::const_iterator o = rejected_trsf.begin(); o != rejected_trsf.end(); o++) { - if (o->second.empty()) continue; - - Part::TopoShape fuseShape; - Part::TopoShape cutShape; - if ((o->first)->getTypeId().isDerivedFrom(PartDesign::FeatureAddSub::getClassTypeId())) { - PartDesign::FeatureAddSub* feature = static_cast(o->first); - feature->getAddSubShape(fuseShape, cutShape); - } - - if (fuseShape.isNull()) continue; - - // Display the rejected transformations in red - TopoDS_Shape cShape(fuseShape.getShape()); + // Display the rejected transformations in red + if (rejected > 0) { try { // calculating the deflection value Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; @@ -333,41 +326,34 @@ void ViewProviderTransformed::recomputeFeature(bool recompute) // counting up the per Face offsets FaceNodeOffset += nbNodesInFace; FaceTriaOffset += nbTriInFace; - } - // normalize all normals - for (int i=0; i < nbrNodes; i++) - norms[i].normalize(); - - // end the editing of the nodes - rejectedCoords ->point .finishEditing(); - rejectedNorms ->vector .finishEditing(); - rejectedFaceSet ->coordIndex .finishEditing(); - - // fill in the transformation matrices - SoMultipleCopy* rejectedTrfms = new SoMultipleCopy(); - rejectedTrfms->matrix.setNum((o->second).size()); - SbMatrix* mats = rejectedTrfms->matrix.startEditing(); - - std::list::const_iterator trsf = (o->second).begin(); - for (unsigned int i=0; i < (o->second).size(); i++,trsf++) { - Base::Matrix4D mat; - Part::TopoShape::convertToMatrix(*trsf,mat); - mats[i] = convert(mat); + + // normalize all normals + for (int i=0; i < nbrNodes; i++) + norms[i].normalize(); + + // end the editing of the nodes + rejectedCoords ->point .finishEditing(); + rejectedNorms ->vector .finishEditing(); + rejectedFaceSet ->coordIndex .finishEditing(); + + // fill in the transformation matrices + SoMultipleCopy* rejectedTrfms = new SoMultipleCopy(); + + + rejectedTrfms->matrix.finishEditing(); + rejectedTrfms->addChild(rejectedFaceSet); + SoSeparator* sep = new SoSeparator(); + sep->addChild(rejectedCoords); + sep->addChild(rejectedNorms); + sep->addChild(rejectedTrfms); + pcRejectedRoot->addChild(sep); } - rejectedTrfms->matrix.finishEditing(); - rejectedTrfms->addChild(rejectedFaceSet); - SoSeparator* sep = new SoSeparator(); - sep->addChild(rejectedCoords); - sep->addChild(rejectedNorms); - sep->addChild(rejectedTrfms); - pcRejectedRoot->addChild(sep); } catch (...) { Base::Console().Error("Cannot compute Inventor representation for the rejected transformations of shape of %s.\n", - pcTransformed->getNameInDocument()); + pcTransformed->getNameInDocument()); } } - } From 5b4c246944c72459016efff6ae903ac66c090991 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Oct 2021 22:32:26 +0200 Subject: [PATCH] PD: simplify code to display rejected shape and move it to its own function --- .../Gui/ViewProviderTransformed.cpp | 262 ++++++++---------- .../PartDesign/Gui/ViewProviderTransformed.h | 3 + 2 files changed, 119 insertions(+), 146 deletions(-) diff --git a/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp b/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp index 0d402d0b71a..0e3b7f0b068 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -198,162 +199,131 @@ void ViewProviderTransformed::recomputeFeature(bool recompute) } // Display the rejected transformations in red - if (rejected > 0) { - try { - // calculating the deflection value - Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; - { - Bnd_Box bounds; - BRepBndLib::Add(cShape, bounds); - bounds.SetGap(0.0); - bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); - } - Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue(); + showRejectedShape(cShape); + } +} - // create or use the mesh on the data structure - // Note: This DOES have an effect on cShape +void ViewProviderTransformed::showRejectedShape(TopoDS_Shape shape) +{ + try { + // calculating the deflection value + Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; + { + Bnd_Box bounds; + BRepBndLib::Add(shape, bounds); + bounds.SetGap(0.0); + bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); + } + Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue(); + + // create or use the mesh on the data structure + // Note: This DOES have an effect on shape #if OCC_VERSION_HEX >= 0x060600 - Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI; - BRepMesh_IncrementalMesh(cShape,deflection,Standard_False, - AngDeflectionRads,Standard_True); + Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI; + BRepMesh_IncrementalMesh(shape, deflection, Standard_False, AngDeflectionRads, Standard_True); #else - BRepMesh_IncrementalMesh(cShape,deflection); + BRepMesh_IncrementalMesh(shape, deflection); #endif - // We must reset the location here because the transformation data - // are set in the placement property - TopLoc_Location aLoc; - cShape.Location(aLoc); - - // count triangles and nodes in the mesh - int nbrTriangles=0, nbrNodes=0; - TopExp_Explorer Ex; - for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) { - Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc); - // Note: we must also count empty faces - if (!mesh.IsNull()) { - nbrTriangles += mesh->NbTriangles(); - nbrNodes += mesh->NbNodes(); - } + // We must reset the location here because the transformation data + // are set in the placement property + TopLoc_Location aLoc; + shape.Location(aLoc); + + // count triangles and nodes in the mesh + int nbrTriangles=0, nbrNodes=0; + TopExp_Explorer Ex; + for (Ex.Init(shape, TopAbs_FACE); Ex.More(); Ex.Next()) { + Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc); + // Note: we must also count empty faces + if (!mesh.IsNull()) { + nbrTriangles += mesh->NbTriangles(); + nbrNodes += mesh->NbNodes(); } + } - // create memory for the nodes and indexes - SoCoordinate3* rejectedCoords = new SoCoordinate3(); - rejectedCoords ->point .setNum(nbrNodes); - SoNormal* rejectedNorms = new SoNormal(); - rejectedNorms ->vector .setNum(nbrNodes); - SoIndexedFaceSet* rejectedFaceSet = new SoIndexedFaceSet(); - rejectedFaceSet ->coordIndex .setNum(nbrTriangles*4); + // create memory for the nodes and indexes + SoCoordinate3* rejectedCoords = new SoCoordinate3(); + rejectedCoords ->point .setNum(nbrNodes); + SoNormal* rejectedNorms = new SoNormal(); + rejectedNorms ->vector .setNum(nbrNodes); + SoIndexedFaceSet* rejectedFaceSet = new SoIndexedFaceSet(); + rejectedFaceSet ->coordIndex .setNum(nbrTriangles*4); + + // get the raw memory for fast fill up + SbVec3f* verts = rejectedCoords ->point .startEditing(); + SbVec3f* norms = rejectedNorms ->vector .startEditing(); + int32_t* index = rejectedFaceSet ->coordIndex .startEditing(); + + // preset the normal vector with null vector + for (int i=0; i < nbrNodes; i++) + norms[i]= SbVec3f(0.0,0.0,0.0); + + int FaceNodeOffset=0,FaceTriaOffset=0; + for (Ex.Init(shape, TopAbs_FACE); Ex.More(); Ex.Next()) { + const TopoDS_Face &actFace = TopoDS::Face(Ex.Current()); + + // get triangulation + std::vector points; + std::vector facets; + if (!Part::Tools::getTriangulation(actFace, points, facets)) + continue; + + // get normal per vertex + std::vector vertexnormals; + Part::Tools::getPointNormals(points, facets, vertexnormals); + + // getting size of node and triangle array of this face + std::size_t nbNodesInFace = points.size(); + std::size_t nbTriInFace = facets.size(); + + for (std::size_t i = 0; i < points.size(); i++) { + verts[FaceNodeOffset+i] = SbVec3f(points[i].X(), points[i].Y(), points[i].Z()); + } - // get the raw memory for fast fill up - SbVec3f* verts = rejectedCoords ->point .startEditing(); - SbVec3f* norms = rejectedNorms ->vector .startEditing(); - int32_t* index = rejectedFaceSet ->coordIndex .startEditing(); + for (std::size_t i = 0; i < vertexnormals.size(); i++) { + norms[FaceNodeOffset+i] = SbVec3f(vertexnormals[i].X(), vertexnormals[i].Y(), vertexnormals[i].Z()); + } - // preset the normal vector with null vector - for (int i=0; i < nbrNodes; i++) - norms[i]= SbVec3f(0.0,0.0,0.0); - - int ii = 0,FaceNodeOffset=0,FaceTriaOffset=0; - for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) { - TopLoc_Location aLoc; - const TopoDS_Face &actFace = TopoDS::Face(Ex.Current()); - // get the mesh of the shape - Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc); - if (mesh.IsNull()) continue; - - // getting the transformation of the shape/face - gp_Trsf myTransf; - Standard_Boolean identity = true; - if (!aLoc.IsIdentity()) { - identity = false; - myTransf = aLoc.Transformation(); - } - - // getting size of node and triangle array of this face - int nbNodesInFace = mesh->NbNodes(); - int nbTriInFace = mesh->NbTriangles(); - // check orientation - TopAbs_Orientation orient = actFace.Orientation(); - - // cycling through the poly mesh - const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); - const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); - for (int g=1; g <= nbTriInFace; g++) { - // Get the triangle - Standard_Integer N1,N2,N3; - Triangles(g).Get(N1,N2,N3); - - // change orientation of the triangle if the face is reversed - if ( orient != TopAbs_FORWARD ) { - Standard_Integer tmp = N1; - N1 = N2; - N2 = tmp; - } - - // get the 3 points of this triangle - gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3)); - - // transform the vertices to the place of the face - if (!identity) { - V1.Transform(myTransf); - V2.Transform(myTransf); - V3.Transform(myTransf); - } - - // calculating per vertex normals - // Calculate triangle normal - gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z()); - gp_Vec Normal = (v2-v1)^(v3-v1); - - // add the triangle normal to the vertex normal for all points of this triangle - norms[FaceNodeOffset+N1-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); - norms[FaceNodeOffset+N2-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); - norms[FaceNodeOffset+N3-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); - - // set the vertices - verts[FaceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z())); - verts[FaceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z())); - verts[FaceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z())); - - // set the index vector with the 3 point indexes and the end delimiter - index[FaceTriaOffset*4+4*(g-1)] = FaceNodeOffset+N1-1; - index[FaceTriaOffset*4+4*(g-1)+1] = FaceNodeOffset+N2-1; - index[FaceTriaOffset*4+4*(g-1)+2] = FaceNodeOffset+N3-1; - index[FaceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX; - } - - // counting up the per Face offsets - FaceNodeOffset += nbNodesInFace; - FaceTriaOffset += nbTriInFace; - - - // normalize all normals - for (int i=0; i < nbrNodes; i++) - norms[i].normalize(); - - // end the editing of the nodes - rejectedCoords ->point .finishEditing(); - rejectedNorms ->vector .finishEditing(); - rejectedFaceSet ->coordIndex .finishEditing(); - - // fill in the transformation matrices - SoMultipleCopy* rejectedTrfms = new SoMultipleCopy(); - - - rejectedTrfms->matrix.finishEditing(); - rejectedTrfms->addChild(rejectedFaceSet); - SoSeparator* sep = new SoSeparator(); - sep->addChild(rejectedCoords); - sep->addChild(rejectedNorms); - sep->addChild(rejectedTrfms); - pcRejectedRoot->addChild(sep); + // cycling through the poly mesh + for (std::size_t g=0; g < nbTriInFace; g++) { + // Get the triangle + Standard_Integer N1,N2,N3; + facets[g].Get(N1,N2,N3); + + // set the index vector with the 3 point indexes and the end delimiter + index[FaceTriaOffset*4+4*g] = FaceNodeOffset+N1; + index[FaceTriaOffset*4+4*g+1] = FaceNodeOffset+N2; + index[FaceTriaOffset*4+4*g+2] = FaceNodeOffset+N3; + index[FaceTriaOffset*4+4*g+3] = SO_END_FACE_INDEX; } - } - catch (...) { - Base::Console().Error("Cannot compute Inventor representation for the rejected transformations of shape of %s.\n", - pcTransformed->getNameInDocument()); + + // counting up the per Face offsets + FaceNodeOffset += nbNodesInFace; + FaceTriaOffset += nbTriInFace; + + // normalize all normals + for (int i=0; i < nbrNodes; i++) + norms[i].normalize(); + + // end the editing of the nodes + rejectedCoords ->point .finishEditing(); + rejectedNorms ->vector .finishEditing(); + rejectedFaceSet ->coordIndex .finishEditing(); + + // fill in the transformation matrices + SoMultipleCopy* rejectedTrfms = new SoMultipleCopy(); + rejectedTrfms->matrix.finishEditing(); + rejectedTrfms->addChild(rejectedFaceSet); + SoSeparator* sep = new SoSeparator(); + sep->addChild(rejectedCoords); + sep->addChild(rejectedNorms); + sep->addChild(rejectedTrfms); + pcRejectedRoot->addChild(sep); } } + catch (...) { + Base::Console().Error("Cannot compute Inventor representation for the rejected transformations of shape of %s.\n", + getObject()->getNameInDocument()); + } } - diff --git a/src/Mod/PartDesign/Gui/ViewProviderTransformed.h b/src/Mod/PartDesign/Gui/ViewProviderTransformed.h index 50a72ca1aeb..ec4b8e12263 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderTransformed.h +++ b/src/Mod/PartDesign/Gui/ViewProviderTransformed.h @@ -68,6 +68,9 @@ class PartDesignGuiExport ViewProviderTransformed : public ViewProvider public: void recomputeFeature(bool recompute=true); QString getMessage() const {return diagMessage;} + +private: + void showRejectedShape(TopoDS_Shape shape); }; From f55c46cc86344a6d7389156c015194f7d0fd2b63 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 13 Mar 2021 14:47:39 +0100 Subject: [PATCH] PD: adjust unit test for mirrored offset that doesn't fail any more --- src/Mod/PartDesign/PartDesignTests/TestMirrored.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/PartDesign/PartDesignTests/TestMirrored.py b/src/Mod/PartDesign/PartDesignTests/TestMirrored.py index fd6b32a34f2..7faf0ffb971 100644 --- a/src/Mod/PartDesign/PartDesignTests/TestMirrored.py +++ b/src/Mod/PartDesign/PartDesignTests/TestMirrored.py @@ -69,7 +69,7 @@ def testMirroredPrimitiveCase(self): self.Doc.recompute() self.assertAlmostEqual(self.Mirrored.Shape.Volume, 2.0) - def testMirroredOffsetFailureCase(self): + def testMirroredOffsetCase(self): self.Body = self.Doc.addObject('PartDesign::Body','Body') self.Rect = self.Doc.addObject('Sketcher::SketchObject','Rect') self.Body.addObject(self.Rect) @@ -85,7 +85,7 @@ def testMirroredOffsetFailureCase(self): self.Mirrored.MirrorPlane = (self.Rect, ["H_Axis"]) self.Body.addObject(self.Mirrored) self.Doc.recompute() - self.assertIn("Invalid", self.Mirrored.State) + self.assertIn("Up-to-date", self.Mirrored.State) def tearDown(self): #closing doc