-// Copyright (C) 2014-2017 CEA/DEN, EDF R&D
+// Copyright (C) 2014-2024 CEA, EDF
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
-// See http://www.salome-platform.org/ or
-// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
#include "GeomAlgoAPI_ShapeTools.h"
#include "GeomAlgoAPI_SketchBuilder.h"
+#include <Basics_OCCTVersion.hxx>
+
#include <GeomAPI_Ax1.h>
#include <GeomAPI_Edge.h>
#include <GeomAPI_Dir.h>
#include <GeomAPI_Face.h>
#include <GeomAPI_Pln.h>
#include <GeomAPI_Pnt.h>
+#include <GeomAPI_Wire.h>
+
+#include <Approx_CurvilinearParameter.hxx>
#include <Bnd_Box.hxx>
-#include <BOPTools.hxx>
+
+#include <BRep_Tool.hxx>
#include <BRep_Builder.hxx>
-#include <BRepAdaptor_Curve.hxx>
+#include <BRepAlgo.hxx>
#include <BRepAlgo_FaceRestrictor.hxx>
+#include <BRepAdaptor_Curve.hxx>
#include <BRepBndLib.hxx>
+#include <BRepBuilderAPI_Copy.hxx>
#include <BRepBuilderAPI_FindPlane.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
+#include <BRepBuilderAPI_MakeVertex.hxx>
+#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepCheck_Analyzer.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
#include <BRepExtrema_ExtCF.hxx>
+#include <BRepExtrema_ShapeProximity.hxx>
#include <BRepGProp.hxx>
+#include <BRepMesh_IncrementalMesh.hxx>
#include <BRepTools.hxx>
+#include <BRepTools_WireExplorer.hxx>
#include <BRepTopAdaptor_FClass2d.hxx>
+#include <BRepClass_FaceClassifier.hxx>
+#include <BRepLib_CheckCurveOnSurface.hxx>
+#include <BRepLProp.hxx>
+
+#include <BOPAlgo_Builder.hxx>
+
+#include <Extrema_GenLocateExtCS.hxx>
+#include <Extrema_GenLocateExtSS.hxx>
+#include <Extrema_GenLocateExtPS.hxx>
+#include <Extrema_LocateExtCC.hxx>
+#include <Extrema_LocateExtPC.hxx>
+
#include <Geom2d_Curve.hxx>
#include <Geom2d_Curve.hxx>
-#include <BRepLib_CheckCurveOnSurface.hxx>
-#include <BRep_Tool.hxx>
+
+#include <Geom_BSplineCurve.hxx>
+#include <Geom_CylindricalSurface.hxx>
#include <Geom_Line.hxx>
#include <Geom_Plane.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
+
+#if OCC_VERSION_LARGE < 0x07070000
+#include <GeomAdaptor_HCurve.hxx>
+#else
+#include <GeomAdaptor_Curve.hxx>
+#endif
+
#include <GeomAPI_ProjectPointOnCurve.hxx>
+#include <GeomAPI_ShapeIterator.h>
+
#include <GeomLib_IsPlanarSurface.hxx>
#include <GeomLib_Tool.hxx>
+#include <GeomAPI_IntCS.hxx>
+
#include <gp_Pln.hxx>
#include <GProp_GProps.hxx>
+
#include <IntAna_IntConicQuad.hxx>
#include <IntAna_Quadric.hxx>
-#include <NCollection_Vector.hxx>
+
#include <ShapeAnalysis.hxx>
#include <ShapeAnalysis_Surface.hxx>
-#include <TopoDS_Builder.hxx>
+
+#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Shell.hxx>
#include <TopoDS_Vertex.hxx>
-#include <TopoDS.hxx>
+#include <TopoDS_Builder.hxx>
+
+#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
+
#include <TopTools_ListIteratorOfListOfShape.hxx>
-#include <BOPAlgo_Builder.hxx>
-#include <BRepBuilderAPI_MakeVertex.hxx>
-#include <TopoDS_Edge.hxx>
+#include <NCollection_Vector.hxx>
+
+#include <LocalAnalysis_SurfaceContinuity.hxx>
+#include<array>
+
+//==================================================================================================
+static GProp_GProps props(const TopoDS_Shape& theShape)
+{
+ GProp_GProps aGProps;
+
+ if (theShape.ShapeType() == TopAbs_EDGE || theShape.ShapeType() == TopAbs_WIRE)
+ {
+ BRepGProp::LinearProperties(theShape, aGProps);
+ }
+ else if (theShape.ShapeType() == TopAbs_FACE || theShape.ShapeType() == TopAbs_SHELL)
+ {
+ const Standard_Real anEps = 1.e-6;
+ BRepGProp::SurfaceProperties(theShape, aGProps, anEps);
+ }
+ else if (theShape.ShapeType() == TopAbs_SOLID || theShape.ShapeType() == TopAbs_COMPSOLID)
+ {
+ BRepGProp::VolumeProperties(theShape, aGProps);
+ }
+ else if (theShape.ShapeType() == TopAbs_COMPOUND)
+ {
+ for (TopoDS_Iterator anIt(theShape); anIt.More(); anIt.Next())
+ {
+ aGProps.Add(props(anIt.Value()));
+ }
+ }
+
+ return aGProps;
+}
+
+//==================================================================================================
+double GeomAlgoAPI_ShapeTools::length(const std::shared_ptr<GeomAPI_Shape> theShape)
+{
+ GProp_GProps aGProps;
+ if (!theShape.get()) {
+ return 0.0;
+ }
+ const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
+ if (aShape.IsNull()) {
+ return 0.0;
+ }
+
+ BRepGProp::LinearProperties(aShape, aGProps, Standard_True);
+ return aGProps.Mass();
+}
//==================================================================================================
double GeomAlgoAPI_ShapeTools::volume(const std::shared_ptr<GeomAPI_Shape> theShape)
+{
+ if (!theShape.get()) {
+ return 0.0;
+ }
+ const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
+ if (aShape.IsNull()) {
+ return 0.0;
+ }
+ const Standard_Real anEps = 1.e-6;
+ double aVolume = 0.0;
+ for (TopExp_Explorer anExp(aShape, TopAbs_SOLID); anExp.More(); anExp.Next()) {
+ GProp_GProps aGProps;
+ BRepGProp::VolumeProperties(anExp.Current(), aGProps, anEps);
+ aVolume += aGProps.Mass();
+ }
+ return aVolume;
+}
+
+//==================================================================================================
+double GeomAlgoAPI_ShapeTools::area (const std::shared_ptr<GeomAPI_Shape> theShape)
{
GProp_GProps aGProps;
- if(!theShape.get()) {
+ if (!theShape.get()) {
return 0.0;
}
const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
- if(aShape.IsNull()) {
+ if (aShape.IsNull()) {
return 0.0;
}
const Standard_Real anEps = 1.e-6;
- BRepGProp::VolumeProperties(aShape, aGProps, anEps);
+
+ BRepGProp::SurfaceProperties(aShape, aGProps, anEps);
return aGProps.Mass();
}
+//==================================================================================================
+bool GeomAlgoAPI_ShapeTools::isContinuousFaces(const GeomShapePtr& theFace1,
+ const GeomShapePtr& theFace2,
+ const GeomPointPtr& thePoint,
+ const double & theAngle,
+ std::string& theError)
+{
+
+ #ifdef _DEBUG
+ std::cout << "isContinuousFaces " << std::endl;
+ #endif
+
+ if (!thePoint.get()) {
+ theError = "isContinuousFaces : An invalid argument";
+ return false;
+ }
+ const gp_Pnt& aPoint = thePoint->impl<gp_Pnt>();
+
+ // Getting base shape.
+ if (!theFace1.get()) {
+ theError = "isContinuousFaces : An invalid argument";
+ return false;
+ }
+
+ TopoDS_Shape aShape1 = theFace1->impl<TopoDS_Shape>();
+
+ if (aShape1.IsNull()) {
+ theError = "isContinuousFaces : An invalid argument";
+ return false;
+ }
+
+ // Getting base shape.
+ if (!theFace2.get()) {
+ theError = "isContinuousFaces : An invalid argument";
+ return false;
+ }
+
+ TopoDS_Shape aShape2 = theFace2->impl<TopoDS_Shape>();
+
+ if (aShape2.IsNull()) {
+ theError = "isContinuousFaces : An invalid argument";
+ return false;
+ }
+
+ TopoDS_Face aFace1 = TopoDS::Face(aShape1);
+ if (aFace1.IsNull()) {
+ theError = "isContinuousFaces : An invalid argument";
+ return false;
+ }
+
+ Handle(Geom_Surface) aSurf1 = BRep_Tool::Surface(aFace1);
+ if (aSurf1.IsNull()) {
+ theError = "isContinuousFaces : An invalid surface";
+ return false;
+ }
+
+ ShapeAnalysis_Surface aSAS1(aSurf1);
+ gp_Pnt2d aPointOnFace1 = aSAS1.ValueOfUV(aPoint, Precision::Confusion());
+
+ TopoDS_Face aFace2 = TopoDS::Face(aShape2);
+ if (aFace2.IsNull()) {
+ theError = "isContinuousFaces : An invalid argument";
+ return false;
+ }
+
+ Handle(Geom_Surface) aSurf2 = BRep_Tool::Surface(aFace2);
+ if (aSurf2.IsNull()) {
+ theError = "isContinuousFaces : An invalid surface";
+ return false;
+ }
+
+ ShapeAnalysis_Surface aSAS2(aSurf2);
+ gp_Pnt2d aPointOnFace2= aSAS2.ValueOfUV(aPoint, Precision::Confusion());
+
+ bool aRes = false;
+ try {
+ OCC_CATCH_SIGNALS;
+ LocalAnalysis_SurfaceContinuity aLocAnal(aSurf1,
+ aPointOnFace1.X(),
+ aPointOnFace1.Y(),
+ aSurf2,
+ aPointOnFace2.X(),
+ aPointOnFace2.Y(),
+ GeomAbs_Shape::GeomAbs_G1, // Order
+ 0.001, // EpsNul
+ 0.001, // EpsC0
+ 0.001, // EpsC1
+ 0.001, // EpsC2
+ theAngle * M_PI / 180.0); //EpsG1
+ aRes = aLocAnal.IsG1();
+ }
+ catch (Standard_Failure const& anException) {
+ theError = "LocalAnalysis_SurfaceContinuity error :";
+ theError += anException.GetMessageString();
+ }
+
+ return aRes;
+}
+
//==================================================================================================
std::shared_ptr<GeomAPI_Pnt>
GeomAlgoAPI_ShapeTools::centreOfMass(const std::shared_ptr<GeomAPI_Shape> theShape)
{
GProp_GProps aGProps;
- if(!theShape) {
+ if (!theShape) {
return std::shared_ptr<GeomAPI_Pnt>();
}
const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
- if(aShape.IsNull()) {
+ if (aShape.IsNull()) {
return std::shared_ptr<GeomAPI_Pnt>();
}
gp_Pnt aCentre;
- if(aShape.ShapeType() == TopAbs_VERTEX) {
+ if (aShape.ShapeType() == TopAbs_VERTEX) {
aCentre = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
- } else if(aShape.ShapeType() == TopAbs_EDGE || aShape.ShapeType() == TopAbs_WIRE) {
- BRepGProp::LinearProperties(aShape, aGProps);
- aCentre = aGProps.CentreOfMass();
} else {
- BRepGProp::SurfaceProperties(aShape, aGProps);
+ aGProps = props(aShape);
aCentre = aGProps.CentreOfMass();
}
+
return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aCentre.X(), aCentre.Y(), aCentre.Z()));
}
+//==================================================================================================
+double GeomAlgoAPI_ShapeTools::radius(const std::shared_ptr<GeomAPI_Face>& theCylinder)
+{
+ double aRadius = -1.0;
+ if (theCylinder->isCylindrical()) {
+ const TopoDS_Shape& aShape = theCylinder->impl<TopoDS_Shape>();
+ Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aShape));
+ Handle(Geom_CylindricalSurface) aCyl = Handle(Geom_CylindricalSurface)::DownCast(aSurf);
+ if (!aCyl.IsNull())
+ aRadius = aCyl->Radius();
+ }
+ return aRadius;
+}
+
+//==================================================================================================
+namespace {
+
+auto getExtemaDistShape = [](const GeomShapePtr& theShape1,
+ const GeomShapePtr& theShape2) -> BRepExtrema_DistShapeShape
+{
+ const TopoDS_Shape& aShape1 = theShape1->impl<TopoDS_Shape>();
+ const TopoDS_Shape& aShape2 = theShape2->impl<TopoDS_Shape>();
+
+ BRepExtrema_DistShapeShape aDist(aShape1, aShape2);
+ aDist.Perform();
+ return aDist;
+};
+
+static void tessellateShape(const TopoDS_Shape& theShape)
+{
+ Standard_Boolean isTessellate = Standard_False;
+ TopLoc_Location aLoc;
+ for (TopExp_Explorer anExp(theShape, TopAbs_FACE); anExp.More() && !isTessellate; anExp.Next()) {
+ Handle(Poly_Triangulation) aTria = BRep_Tool::Triangulation(TopoDS::Face(anExp.Value()), aLoc);
+ isTessellate = aTria.IsNull();
+ }
+ for (TopExp_Explorer anExp(theShape, TopAbs_EDGE); anExp.More() && !isTessellate; anExp.Next()) {
+ Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(TopoDS::Edge(anExp.Value()), aLoc);
+ isTessellate = aPoly.IsNull();
+ }
+
+ if (isTessellate) {
+ BRepMesh_IncrementalMesh aMesher(theShape, 0.1);
+ Standard_ProgramError_Raise_if(!aMesher.IsDone(), "Meshing failed");
+ }
+}
+
+static Standard_Real paramOnCurve(const BRepAdaptor_Curve& theCurve,
+ const gp_Pnt& thePoint,
+ const Standard_Real theTol)
+{
+ Extrema_ExtPC aParamSearch(thePoint,
+ theCurve,
+ theCurve.FirstParameter(),
+ theCurve.LastParameter());
+ if (aParamSearch.IsDone()) {
+ Standard_Integer anIndMin = 0, aNbExt = aParamSearch.NbExt();
+ Standard_Real aSqDistMin = RealLast();
+ for (Standard_Integer i = 1; i <= aNbExt; ++i) {
+ if (aParamSearch.SquareDistance(i) < aSqDistMin) {
+ anIndMin = i;
+ aSqDistMin = aParamSearch.SquareDistance(i);
+ }
+ }
+ if (anIndMin != 0 && aSqDistMin <= theTol * theTol)
+ return aParamSearch.Point(anIndMin).Parameter();
+ }
+ return 0.5 * (theCurve.FirstParameter() + theCurve.LastParameter());
+}
+
+static void paramsOnSurf(const BRepAdaptor_Surface& theSurf,
+ const gp_Pnt& thePoint,
+ const Standard_Real theTol,
+ Standard_Real& theU,
+ Standard_Real& theV)
+{
+ Extrema_ExtPS aParamSearch(thePoint, theSurf, Precision::PConfusion(), Precision::PConfusion());
+ if (aParamSearch.IsDone()) {
+ Standard_Integer anIndMin = 0, aNbExt = aParamSearch.NbExt();
+ Standard_Real aSqDistMin = RealLast();
+ for (Standard_Integer i = 1; i <= aNbExt; ++i) {
+ if (aParamSearch.SquareDistance(i) < aSqDistMin) {
+ anIndMin = i;
+ aSqDistMin = aParamSearch.SquareDistance(i);
+ }
+ }
+ if (anIndMin != 0 && aSqDistMin <= theTol * theTol)
+ return aParamSearch.Point(anIndMin).Parameter(theU, theV);
+ }
+ theU = 0.5 * (theSurf.FirstUParameter() + theSurf.LastUParameter());
+ theV = 0.5 * (theSurf.FirstVParameter() + theSurf.LastVParameter());
+}
+
+static Standard_Real extremaEE(const TopoDS_Edge& theEdge1,
+ const TopoDS_Edge& theEdge2,
+ const gp_Pnt& thePoint1,
+ const gp_Pnt& thePoint2)
+{
+ BRepAdaptor_Curve aCurve1(theEdge1);
+ BRepAdaptor_Curve aCurve2(theEdge2);
+
+ Standard_Real aU1 = paramOnCurve(aCurve1, thePoint1, BRep_Tool::Tolerance(theEdge1));
+ Standard_Real aU2 = paramOnCurve(aCurve2, thePoint2, BRep_Tool::Tolerance(theEdge2));
+
+ Standard_Real aValue = -1.0;
+ Extrema_LocateExtCC anExtr(aCurve1, aCurve2, aU1, aU2);
+ if (anExtr.IsDone() && aValue > Precision::Confusion())
+ aValue = Sqrt(anExtr.SquareDistance());
+ return aValue;
+}
+
+static Standard_Real extremaPE(const gp_Pnt& thePoint,
+ const TopoDS_Edge& theEdge,
+ gp_Pnt& thePointOnEdge)
+{
+ BRepAdaptor_Curve aCurve (theEdge);
+
+ TopLoc_Location aLoc;
+ Standard_Real aTol = BRep_Tool::Tolerance(theEdge);
+ Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D (theEdge, aLoc);
+ if (!aPoly.IsNull())
+ aTol = Max (aTol, aPoly->Deflection());
+
+ Standard_Real aParam = paramOnCurve (aCurve, thePointOnEdge, 2*aTol);
+
+ Standard_Real aValue = -1.0;
+ Extrema_LocateExtPC anExtr (thePoint, aCurve, aParam, Precision::PConfusion());
+ if (anExtr.IsDone())
+ {
+ aValue = Sqrt(anExtr.SquareDistance());
+
+ Extrema_POnCurv aPointOnCurve = anExtr.Point();
+ thePointOnEdge = aPointOnCurve.Value();
+ }
+ return aValue;
+}
+
+static Standard_Real extremaPF(const gp_Pnt& thePoint,
+ const TopoDS_Face& theFace,
+ gp_Pnt& thePointOnFace)
+{
+ BRepAdaptor_Surface aSurf (theFace);
+
+ TopLoc_Location aLoc;
+ Standard_Real aTol = BRep_Tool::Tolerance(theFace);
+ Handle(Poly_Triangulation) aTria = BRep_Tool::Triangulation (theFace, aLoc);
+ if (!aTria.IsNull())
+ aTol = Max (aTol, aTria->Deflection());
+
+ Standard_Real aU, aV;
+ paramsOnSurf(aSurf, thePointOnFace, 2*aTol, aU, aV);
+
+ Standard_Real aValue = -1.0;
+ Extrema_GenLocateExtPS anExtr (aSurf);
+ anExtr.Perform (thePoint, aU, aV);
+ if (anExtr.IsDone())
+ {
+ aValue = Sqrt(anExtr.SquareDistance());
+
+ Extrema_POnSurf aPointOnSurf = anExtr.Point();
+ thePointOnFace = aPointOnSurf.Value();
+ }
+ return aValue;
+}
+
+static Standard_Real extremaEF(const TopoDS_Edge& theEdge,
+ const TopoDS_Face& theFace,
+ const gp_Pnt& thePonE,
+ const gp_Pnt& thePonF)
+{
+ BRepAdaptor_Curve aCurve(theEdge);
+ BRepAdaptor_Surface aSurf(theFace);
+
+ Standard_Real aP = paramOnCurve(aCurve, thePonE, BRep_Tool::Tolerance(theEdge));
+ Standard_Real aU, aV;
+ paramsOnSurf(aSurf, thePonF, BRep_Tool::Tolerance(theFace), aU, aV);
+
+ Standard_Real aValue = -1.0;
+ Extrema_GenLocateExtCS anExtr(aCurve, aSurf, aP, aU, aV, Precision::PConfusion(), Precision::PConfusion());
+ if (anExtr.IsDone() && aValue > Precision::Confusion())
+ aValue = Sqrt(anExtr.SquareDistance());
+ return aValue;
+}
+
+static Standard_Real extremaFF(const TopoDS_Face& theFace1,
+ const TopoDS_Face& theFace2,
+ const gp_Pnt& thePoint1,
+ const gp_Pnt& thePoint2)
+{
+ BRepAdaptor_Surface aSurf1(theFace1);
+ BRepAdaptor_Surface aSurf2(theFace2);
+
+ Standard_Real aU1, aV1;
+ paramsOnSurf(aSurf1, thePoint1, BRep_Tool::Tolerance(theFace1), aU1, aV1);
+ Standard_Real aU2, aV2;
+ paramsOnSurf(aSurf2, thePoint2, BRep_Tool::Tolerance(theFace2), aU2, aV2);
+
+ Standard_Real aValue = -1.0;
+ Extrema_GenLocateExtSS anExtr(aSurf1, aSurf2, aU1, aV1, aU2, aV2, Precision::PConfusion(), Precision::PConfusion());
+ if (anExtr.IsDone() && aValue > Precision::Confusion())
+ aValue = Sqrt(anExtr.SquareDistance());
+ return aValue;
+}
+
+} // namespace
+
+double GeomAlgoAPI_ShapeTools::minimalDistance(const GeomShapePtr& theShape1,
+ const GeomShapePtr& theShape2)
+{
+ BRepExtrema_DistShapeShape aDist = getExtemaDistShape(theShape1, theShape2);
+ return aDist.IsDone() ? aDist.Value() : Precision::Infinite();
+}
+
+double GeomAlgoAPI_ShapeTools::minimalDistance(const GeomShapePtr& theShape1,
+ const GeomShapePtr& theShape2,
+ std::array<double, 3> & fromShape1To2)
+{
+ BRepExtrema_DistShapeShape aDist = getExtemaDistShape(theShape1, theShape2);
+ const auto & pt1 = aDist.PointOnShape1(1);
+ const auto & pt2 = aDist.PointOnShape2(1) ;
+ fromShape1To2[0] = pt2.X() - pt1.X();
+ fromShape1To2[1] = pt2.Y() - pt1.Y();
+ fromShape1To2[2] = pt2.Z() - pt1.Z();
+ return aDist.IsDone() ? aDist.Value() : Precision::Infinite();
+}
+
+//==================================================================================================
+double GeomAlgoAPI_ShapeTools::shapeProximity(const GeomShapePtr& theShape1,
+ const GeomShapePtr& theShape2)
+{
+ double aResult = -1.0;
+ if (!theShape1.get() || !theShape2.get())
+ return aResult;
+
+ const TopoDS_Shape& aShape1 = theShape1->impl<TopoDS_Shape>();
+ const TopoDS_Shape& aShape2 = theShape2->impl<TopoDS_Shape>();
+
+ TopAbs_ShapeEnum aType1 = aShape1.ShapeType();
+ TopAbs_ShapeEnum aType2 = aShape2.ShapeType();
+
+ // tessellate shapes if there is no mesh exists
+ tessellateShape(aShape1);
+ tessellateShape(aShape2);
+
+ BRepExtrema_ShapeProximity aDist (aShape1, aShape2);
+ aDist.Perform();
+ if (aDist.IsDone()) {
+ aResult = aDist.Proximity();
+
+ // refine the result
+ gp_Pnt aPnt1 = aDist.ProximityPoint1();
+ gp_Pnt aPnt2 = aDist.ProximityPoint2();
+
+ BRepExtrema_ProximityDistTool::ProxPnt_Status aStatus1 = aDist.ProxPntStatus1();
+ BRepExtrema_ProximityDistTool::ProxPnt_Status aStatus2 = aDist.ProxPntStatus2();
+
+ double aValue = -1.0;
+
+ if (aType1 == TopAbs_EDGE)
+ {
+ if (aType2 == TopAbs_EDGE)
+ {
+ if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
+ aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
+ {
+ aValue = extremaEE(TopoDS::Edge(aShape1), TopoDS::Edge(aShape2), aPnt1, aPnt2);
+ }
+ else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER &&
+ aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
+ {
+ aValue = extremaPE(aPnt1, TopoDS::Edge(aShape2), aPnt2);
+ }
+ else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
+ aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER)
+ {
+ aValue = extremaPE(aPnt2, TopoDS::Edge(aShape1), aPnt1);
+ }
+ }
+ else if (aType2 == TopAbs_FACE)
+ {
+ if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
+ aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
+ {
+ aValue = extremaEF(TopoDS::Edge(aShape1), TopoDS::Face(aShape2), aPnt1, aPnt2);
+ }
+ else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER &&
+ aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
+ {
+ aValue = extremaPF(aPnt1, TopoDS::Face(aShape2), aPnt2);
+ }
+ else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
+ aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER)
+ {
+ aValue = extremaPE(aPnt2, TopoDS::Edge(aShape1), aPnt1);
+ }
+ }
+ }
+ else if (aType1 == TopAbs_FACE)
+ {
+ if (aType2 == TopAbs_EDGE)
+ {
+ if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
+ aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
+ {
+ aValue = extremaEF(TopoDS::Edge(aShape2), TopoDS::Face(aShape1), aPnt2, aPnt1);
+ }
+ else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER &&
+ aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
+ {
+ aValue = extremaPE(aPnt1, TopoDS::Edge(aShape2), aPnt2);
+ }
+ else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
+ aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER)
+ {
+ aValue = extremaPF(aPnt2, TopoDS::Face(aShape1), aPnt1);
+ }
+ }
+ else if (aType2 == TopAbs_FACE)
+ {
+ if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
+ aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
+ {
+ aValue = extremaFF(TopoDS::Face(aShape1), TopoDS::Face(aShape2), aPnt1, aPnt2);
+ }
+ else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER &&
+ aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
+ {
+ aValue = extremaPF(aPnt1, TopoDS::Face(aShape2), aPnt2);
+ }
+ else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
+ aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER)
+ {
+ aValue = extremaPF(aPnt2, TopoDS::Face(aShape1), aPnt1);
+ }
+ }
+ }
+
+ if (aValue > 0.0)
+ aResult = aValue;
+ }
+ return aResult;
+}
+
//==================================================================================================
std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::combineShapes(
const std::shared_ptr<GeomAPI_Shape> theCompound,
const GeomAPI_Shape::ShapeType theType,
- ListOfShape& theCombinedShapes,
- ListOfShape& theFreeShapes)
+ ListOfShape& theResuts)
{
+
+ ListOfShape aResCombinedShapes;
+ ListOfShape aResFreeShapes;
+
GeomShapePtr aResult = theCompound;
- if(!theCompound.get()) {
+ if (!theCompound.get()) {
return aResult;
}
- if(theType != GeomAPI_Shape::SHELL && theType != GeomAPI_Shape::COMPSOLID) {
+ if (theType != GeomAPI_Shape::SHELL && theType != GeomAPI_Shape::COMPSOLID) {
return aResult;
}
TopAbs_ShapeEnum aTS = TopAbs_EDGE;
TopAbs_ShapeEnum aTA = TopAbs_FACE;
- if(theType == GeomAPI_Shape::COMPSOLID) {
+ if (theType == GeomAPI_Shape::COMPSOLID) {
aTS = TopAbs_FACE;
aTA = TopAbs_SOLID;
}
- theCombinedShapes.clear();
- theFreeShapes.clear();
+ // map from the resulting shapes to minimal index of the used shape from theCompound list
+ std::map<GeomShapePtr, int> anInputOrder;
+ // map from ancestors-shapes to the index of shapes in theCompound
+ NCollection_DataMap<TopoDS_Shape, int> anAncestorsOrder;
// Get free shapes.
+ int anOrder = 0;
const TopoDS_Shape& aShapesComp = theCompound->impl<TopoDS_Shape>();
- for(TopoDS_Iterator anIter(aShapesComp); anIter.More(); anIter.Next() ) {
+ for (TopoDS_Iterator anIter(aShapesComp); anIter.More(); anIter.Next(), anOrder++) {
const TopoDS_Shape& aShape = anIter.Value();
- if(aShape.ShapeType() > aTA) {
+ if (aShape.ShapeType() > aTA) {
std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
aGeomShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aShape));
- theFreeShapes.push_back(aGeomShape);
+ aResFreeShapes.push_back(aGeomShape);
+ anInputOrder[aGeomShape] = anOrder;
+ } else {
+ for (TopExp_Explorer anExp(aShape, aTA); anExp.More(); anExp.Next()) {
+ anAncestorsOrder.Bind(anExp.Current(), anOrder);
+ }
}
}
- // Map subshapes and shapes.
- BOPCol_IndexedDataMapOfShapeListOfShape aMapSA;
- BOPTools::MapShapesAndAncestors(aShapesComp, aTS, aTA, aMapSA);
- if(aMapSA.IsEmpty()) {
+ // Map sub-shapes and shapes.
+ TopTools_IndexedDataMapOfShapeListOfShape aMapSA;
+ TopExp::MapShapesAndAncestors(aShapesComp, aTS, aTA, aMapSA);
+ if (aMapSA.IsEmpty()) {
return aResult;
}
+ theResuts.clear();
- // Get all shapes with common subshapes and free shapes.
+ // Get all shapes with common sub-shapes and free shapes.
NCollection_Map<TopoDS_Shape> aFreeShapes;
NCollection_Vector<NCollection_Map<TopoDS_Shape>> aShapesWithCommonSubshapes;
- for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator
+ for (TopTools_IndexedDataMapOfShapeListOfShape::Iterator
anIter(aMapSA); anIter.More(); anIter.Next()) {
- const TopoDS_Shape& aShape = anIter.Key();
- BOPCol_ListOfShape& aListOfShape = anIter.ChangeValue();
- if(aListOfShape.IsEmpty()) {
+ TopTools_ListOfShape& aListOfShape = anIter.ChangeValue();
+ if (aListOfShape.IsEmpty()) {
continue;
}
- else if(aListOfShape.Size() == 1) {
+ else if (aListOfShape.Size() == 1) {
const TopoDS_Shape& aF = aListOfShape.First();
aFreeShapes.Add(aF);
aListOfShape.Clear();
} else {
NCollection_List<TopoDS_Shape> aTempList;
NCollection_Map<TopoDS_Shape> aTempMap;
- const TopoDS_Shape& aF = aListOfShape.First();
- const TopoDS_Shape& aL = aListOfShape.Last();
- aTempList.Append(aF);
- aTempList.Append(aL);
- aTempMap.Add(aF);
- aTempMap.Add(aL);
- aFreeShapes.Remove(aF);
- aFreeShapes.Remove(aL);
+ for (TopTools_ListOfShape::Iterator aListIt(aListOfShape); aListIt.More(); aListIt.Next()) {
+ aTempList.Append(aListIt.Value());
+ aTempMap.Add(aListIt.Value());
+ aFreeShapes.Remove(aListIt.Value());
+ }
aListOfShape.Clear();
- for(NCollection_List<TopoDS_Shape>::Iterator
+ for (NCollection_List<TopoDS_Shape>::Iterator
aTempIter(aTempList); aTempIter.More(); aTempIter.Next()) {
const TopoDS_Shape& aTempShape = aTempIter.Value();
- for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator
- anIter(aMapSA); anIter.More(); anIter.Next()) {
- BOPCol_ListOfShape& aTempListOfShape = anIter.ChangeValue();
- if(aTempListOfShape.IsEmpty()) {
+ for (TopTools_IndexedDataMapOfShapeListOfShape::Iterator
+ anIter2(aMapSA); anIter2.More(); anIter2.Next()) {
+ TopTools_ListOfShape& aTempListOfShape = anIter2.ChangeValue();
+ if (aTempListOfShape.IsEmpty()) {
continue;
- } else if(aTempListOfShape.Size() == 1 && aTempListOfShape.First() == aTempShape) {
+ } else if (aTempListOfShape.Size() == 1 && aTempListOfShape.First() == aTempShape) {
aTempListOfShape.Clear();
- } else if(aTempListOfShape.Size() > 1) {
- if(aTempListOfShape.First() == aTempShape) {
- const TopoDS_Shape& aTL = aTempListOfShape.Last();
- if(aTempMap.Add(aTL)) {
- aTempList.Append(aTL);
- aFreeShapes.Remove(aTL);
- }
- aTempListOfShape.Clear();
- } else if(aTempListOfShape.Last() == aTempShape) {
- const TopoDS_Shape& aTF = aTempListOfShape.First();
- if(aTempMap.Add(aTF)) {
- aTempList.Append(aTF);
- aFreeShapes.Remove(aTF);
+ } else if (aTempListOfShape.Size() > 1) {
+ TopTools_ListOfShape::Iterator anIt1(aTempListOfShape);
+ for (; anIt1.More(); anIt1.Next()) {
+ if (anIt1.Value() == aTempShape) {
+ TopTools_ListOfShape::Iterator anIt2(aTempListOfShape);
+ for (; anIt2.More(); anIt2.Next())
+ {
+ if (anIt2.Value() != anIt1.Value()) {
+ if (aTempMap.Add(anIt2.Value())) {
+ aTempList.Append(anIt2.Value());
+ aFreeShapes.Remove(anIt2.Value());
+ }
+ }
+ }
+ aTempListOfShape.Clear();
+ break;
}
- aTempListOfShape.Clear();
}
}
}
}
}
- // Combine shapes with common subshapes.
- for(NCollection_Vector<NCollection_Map<TopoDS_Shape>>::Iterator
+ // Combine shapes with common sub-shapes.
+ for (NCollection_Vector<NCollection_Map<TopoDS_Shape>>::Iterator
anIter(aShapesWithCommonSubshapes); anIter.More(); anIter.Next()) {
TopoDS_Shell aShell;
TopoDS_CompSolid aCSolid;
TopoDS_Builder aBuilder;
+ anOrder = -1;
theType ==
GeomAPI_Shape::COMPSOLID ? aBuilder.MakeCompSolid(aCSolid) : aBuilder.MakeShell(aShell);
NCollection_Map<TopoDS_Shape>& aShapesMap = anIter.ChangeValue();
- for(TopExp_Explorer anExp(aShapesComp, aTA); anExp.More(); anExp.Next()) {
+ for (TopExp_Explorer anExp(aShapesComp, aTA); anExp.More(); anExp.Next()) {
const TopoDS_Shape& aShape = anExp.Current();
- if(aShapesMap.Contains(aShape)) {
+ if (aShapesMap.Contains(aShape)) {
theType ==
GeomAPI_Shape::COMPSOLID ? aBuilder.Add(aCSolid, aShape) : aBuilder.Add(aShell, aShape);
aShapesMap.Remove(aShape);
+ int aThisOrder = anAncestorsOrder.Find(aShape);
+ if (anOrder == -1 || aThisOrder < anOrder)
+ anOrder = aThisOrder; // take the minimum order position
}
}
std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
TopoDS_Shape* aSh = theType == GeomAPI_Shape::COMPSOLID ? new TopoDS_Shape(aCSolid) :
new TopoDS_Shape(aShell);
aGeomShape->setImpl<TopoDS_Shape>(aSh);
- theCombinedShapes.push_back(aGeomShape);
+ aResCombinedShapes.push_back(aGeomShape);
+ anInputOrder[aGeomShape] = anOrder;
}
// Adding free shapes.
- for(TopExp_Explorer anExp(aShapesComp, aTA); anExp.More(); anExp.Next()) {
+ for (TopExp_Explorer anExp(aShapesComp, aTA); anExp.More(); anExp.Next()) {
const TopoDS_Shape& aShape = anExp.Current();
- if(aFreeShapes.Contains(aShape)) {
+ if (aFreeShapes.Contains(aShape)) {
std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
aGeomShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aShape));
- theFreeShapes.push_back(aGeomShape);
+ aResFreeShapes.push_back(aGeomShape);
+ anInputOrder[aGeomShape] = anAncestorsOrder.Find(aShape);
}
}
- if(theCombinedShapes.size() == 1 && theFreeShapes.size() == 0) {
- aResult = theCombinedShapes.front();
- } else if(theCombinedShapes.size() == 0 && theFreeShapes.size() == 1) {
- aResult = theFreeShapes.front();
+ if (aResCombinedShapes.size() == 1 && aResFreeShapes.size() == 0) {
+ aResult = aResCombinedShapes.front();
+ theResuts.push_back(aResult);
+ } else if (aResCombinedShapes.size() == 0 && aResFreeShapes.size() == 1) {
+ aResult = aResFreeShapes.front();
+ theResuts.push_back(aResult);
} else {
TopoDS_Compound aResultComp;
TopoDS_Builder aBuilder;
aBuilder.MakeCompound(aResultComp);
- for(ListOfShape::const_iterator anIter = theCombinedShapes.cbegin();
- anIter != theCombinedShapes.cend(); anIter++) {
- aBuilder.Add(aResultComp, (*anIter)->impl<TopoDS_Shape>());
- }
- for(ListOfShape::const_iterator anIter = theFreeShapes.cbegin();
- anIter != theFreeShapes.cend(); anIter++) {
- aBuilder.Add(aResultComp, (*anIter)->impl<TopoDS_Shape>());
+ // put to result compound and result list in accordance to the order numbers
+ std::map<GeomShapePtr, int>::iterator anInputIter = anInputOrder.begin();
+ std::map<int, GeomShapePtr> aNums;
+ for (; anInputIter != anInputOrder.end(); anInputIter++)
+ aNums[anInputIter->second] = anInputIter->first;
+ std::map<int, GeomShapePtr>::iterator aNumsIter = aNums.begin();
+ for (; aNumsIter != aNums.end(); aNumsIter++) {
+ aBuilder.Add(aResultComp, (aNumsIter->second)->impl<TopoDS_Shape>());
+ theResuts.push_back(aNumsIter->second);
}
aResult->setImpl(new TopoDS_Shape(aResultComp));
}
static void addSimpleShapeToList(const TopoDS_Shape& theShape,
NCollection_List<TopoDS_Shape>& theList)
{
- if(theShape.IsNull()) {
+ if (theShape.IsNull()) {
return;
}
- if(theShape.ShapeType() == TopAbs_COMPOUND) {
- for(TopoDS_Iterator anIt(theShape); anIt.More(); anIt.Next()) {
+ if (theShape.ShapeType() == TopAbs_COMPOUND) {
+ for (TopoDS_Iterator anIt(theShape); anIt.More(); anIt.Next()) {
addSimpleShapeToList(anIt.Value(), theList);
}
} else {
BRep_Builder aBuilder;
aBuilder.MakeCompound(aCompound);
- for(NCollection_List<TopoDS_Shape>::Iterator anIt(theShapes); anIt.More(); anIt.Next()) {
+ for (NCollection_List<TopoDS_Shape>::Iterator anIt(theShapes); anIt.More(); anIt.Next()) {
aBuilder.Add(aCompound, anIt.Value());
}
{
GeomShapePtr aResult = theCompound;
- if(!theCompound.get()) {
+ if (!theCompound.get()) {
return aResult;
}
addSimpleShapeToList(anInShape, anUngroupedShapes);
// Iterate over all shapes and find shapes with shared vertices.
- TopTools_ListOfShape aMapOrder;
- BOPCol_DataMapOfShapeListOfShape aVertexShapesMap;
- for(NCollection_List<TopoDS_Shape>::Iterator aShapesIt(anUngroupedShapes);
- aShapesIt.More();
- aShapesIt.Next()) {
+ TopTools_ListOfShape allVertices;
+ TopTools_DataMapOfShapeListOfShape aVertexShapesMap;
+ for (NCollection_List<TopoDS_Shape>::Iterator aShapesIt(anUngroupedShapes);
+ aShapesIt.More();
+ aShapesIt.Next()) {
const TopoDS_Shape& aShape = aShapesIt.Value();
- for(TopExp_Explorer aShapeExp(aShape, TopAbs_VERTEX);
- aShapeExp.More();
- aShapeExp.Next()) {
+ for (TopExp_Explorer aShapeExp(aShape, TopAbs_VERTEX);
+ aShapeExp.More();
+ aShapeExp.Next()) {
const TopoDS_Shape& aVertex = aShapeExp.Current();
if (!aVertexShapesMap.IsBound(aVertex)) {
NCollection_List<TopoDS_Shape> aList;
aList.Append(aShape);
- aMapOrder.Append(aVertex);
+ allVertices.Append(aVertex);
aVertexShapesMap.Bind(aVertex, aList);
- } else {
- if(!aVertexShapesMap.ChangeFind(aVertex).Contains(aShape)) {
+ }
+ else {
+ if (!aVertexShapesMap.ChangeFind(aVertex).Contains(aShape)) {
aVertexShapesMap.ChangeFind(aVertex).Append(aShape);
}
}
}
// Iterate over the map and group shapes.
- NCollection_Vector<TopTools_ListOfShape> aGroups;
- while (!aMapOrder.IsEmpty()) {
+ NCollection_Vector<TopTools_MapOfShape> aGroups; // groups of shapes connected by vertices
+ while (!allVertices.IsEmpty()) {
// Get first group of shapes in map, and then unbind it.
- const TopoDS_Shape& aKey = aMapOrder.First();
- TopTools_ListOfShape aGroupedShapes = aVertexShapesMap.Find(aKey);
+ const TopoDS_Shape& aKey = allVertices.First();
+ TopTools_ListOfShape aConnectedShapes = aVertexShapesMap.Find(aKey);
aVertexShapesMap.UnBind(aKey);
- aMapOrder.Remove(aKey);
+ allVertices.Remove(aKey);
// Iterate over shapes in this group and add to it shapes from groups in map.
- for(TopTools_ListOfShape::Iterator aGroupIt(aGroupedShapes);
- aGroupIt.More(); aGroupIt.Next()) {
- const TopoDS_Shape& aGroupedShape = aGroupIt.Value();
+ for (TopTools_ListOfShape::Iterator aConnectedIt(aConnectedShapes);
+ aConnectedIt.More(); aConnectedIt.Next()) {
+ const TopoDS_Shape& aConnected = aConnectedIt.Value();
TopTools_ListOfShape aKeysToUnbind;
- for(TopTools_ListOfShape::Iterator aKeysIt(aMapOrder);
- aKeysIt.More();
- aKeysIt.Next()) {
- const TopTools_ListOfShape& aGroupInMap = aVertexShapesMap(aKeysIt.Value());
- if(!aGroupInMap.Contains(aGroupedShape)) {
- // Group in map does not containt shape from our group, so go to the next group in map.
+ for (TopTools_ListOfShape::Iterator aKeysIt(allVertices);
+ aKeysIt.More();
+ aKeysIt.Next()) {
+ const TopTools_ListOfShape& anOtherConnected = aVertexShapesMap(aKeysIt.Value());
+ if (!anOtherConnected.Contains(aConnected)) {
+ // Other connected group does not contain shape from our connected group
continue;
}
- // Iterate over shape in group in map, and add new shapes into our group.
- for(TopTools_ListOfShape::Iterator aGroupInMapIt(aGroupInMap);
- aGroupInMapIt.More();
- aGroupInMapIt.Next()) {
- const TopoDS_Shape& aShape = aGroupInMapIt.Value();
- if (!aGroupedShapes.Contains(aShape)) {
- aGroupedShapes.Append(aShape);
+ // Other is connected to our, so add them to our connected
+ for (TopTools_ListOfShape::Iterator anOtherIt(anOtherConnected);
+ anOtherIt.More();
+ anOtherIt.Next()) {
+ const TopoDS_Shape& aShape = anOtherIt.Value();
+ if (!aConnectedShapes.Contains(aShape)) {
+ aConnectedShapes.Append(aShape);
}
}
// Save key to unbind from this map.
aKeysToUnbind.Append(aKeysIt.Value());
}
// Unbind groups from map that we added to our group.
- for(TopTools_ListOfShape::Iterator aKeysIt(aKeysToUnbind);
- aKeysIt.More();
- aKeysIt.Next()) {
+ for (TopTools_ListOfShape::Iterator aKeysIt(aKeysToUnbind);
+ aKeysIt.More();
+ aKeysIt.Next()) {
aVertexShapesMap.UnBind(aKeysIt.Value());
- aMapOrder.Remove(aKeysIt.Value());
+ allVertices.Remove(aKeysIt.Value());
}
}
- // Sort shapes.
- TopTools_ListOfShape aSortedGroup;
- for(int aST = TopAbs_COMPOUND; aST <= TopAbs_SHAPE; ++aST) {
- TopTools_ListOfShape::Iterator anIt(aGroupedShapes);
+ // Sort shapes from the most complicated to the simplest ones
+ TopTools_MapOfShape aSortedGroup;
+ for (int aST = TopAbs_COMPOUND; aST <= TopAbs_SHAPE; ++aST) {
+ TopTools_ListOfShape::Iterator anIt(aConnectedShapes);
while (anIt.More()) {
- if(anIt.Value().ShapeType() == aST) {
- aSortedGroup.Append(anIt.Value());
- aGroupedShapes.Remove(anIt);
- } else {
+ if (anIt.Value().ShapeType() == aST) {
+ aSortedGroup.Add(anIt.Value());
+ aConnectedShapes.Remove(anIt);
+ }
+ else {
anIt.Next();
}
}
TopoDS_Compound aCompound;
BRep_Builder aBuilder;
aBuilder.MakeCompound(aCompound);
- ListOfShape aCompSolids, aFreeSolids;
- for(NCollection_Vector<NCollection_List<TopoDS_Shape>>::Iterator
- anIt(aGroups); anIt.More(); anIt.Next()) {
- NCollection_List<TopoDS_Shape> aGroup = anIt.Value();
+ ListOfShape aSolids;
+ for (NCollection_Vector<TopTools_MapOfShape>::Iterator anIt(aGroups); anIt.More(); anIt.Next()) {
+ const TopTools_MapOfShape& aGroup = anIt.ChangeValue();
GeomShapePtr aGeomShape(new GeomAPI_Shape());
- if(aGroup.Size() == 1) {
- aGeomShape->setImpl(new TopoDS_Shape(aGroup.First()));
+ if (aGroup.Size() == 1) {
+ TopTools_MapOfShape::Iterator aOneShapeIter(aGroup);
+ aGeomShape->setImpl(new TopoDS_Shape(aOneShapeIter.Value()));
} else {
- aGeomShape->setImpl(new TopoDS_Shape(makeCompound(aGroup)));
+ // make sub-shapes in the group have order same as in original shape
+ TopTools_ListOfShape anOrderedGoup;
+ NCollection_List<TopoDS_Shape>::Iterator anUngrouped(anUngroupedShapes);
+ for (; anUngrouped.More(); anUngrouped.Next()) {
+ if (aGroup.Contains(anUngrouped.Value()))
+ anOrderedGoup.Append(anUngrouped.Value());
+ }
+ aGeomShape->setImpl(new TopoDS_Shape(makeCompound(anOrderedGoup)));
aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
GeomAPI_Shape::COMPSOLID,
- aCompSolids,
- aFreeSolids);
+ aSolids);
}
aBuilder.Add(aCompound, aGeomShape->impl<TopoDS_Shape>());
}
- if(!aCompound.IsNull()) {
+ if (!aCompound.IsNull()) {
aResult->setImpl(new TopoDS_Shape(aCompound));
}
return aResult;
}
+//==================================================================================================
+bool GeomAlgoAPI_ShapeTools::hasSharedTopology(const ListOfShape& theShapes,
+ const GeomAPI_Shape::ShapeType theShapeType)
+{
+ TopTools_IndexedMapOfShape aSubs;
+ for (ListOfShape::const_iterator anIt = theShapes.begin(); anIt != theShapes.end(); ++anIt) {
+ TopTools_IndexedMapOfShape aCurSubs;
+ TopExp::MapShapes((*anIt)->impl<TopoDS_Shape>(), (TopAbs_ShapeEnum)theShapeType, aCurSubs);
+ for (TopTools_IndexedMapOfShape::Iterator aSubIt(aCurSubs); aSubIt.More(); aSubIt.Next()) {
+ if (aSubs.Contains(aSubIt.Value()))
+ return true;
+ else
+ aSubs.Add(aSubIt.Value());
+ }
+ }
+ return false;
+}
+
//==================================================================================================
std::list<std::shared_ptr<GeomAPI_Pnt> >
GeomAlgoAPI_ShapeTools::getBoundingBox(const ListOfShape& theShapes, const double theEnlarge)
BRepBndLib::Add(aShape, aBndBox);
}
- if(theEnlarge != 0.0) {
+ if (theEnlarge != 0.0) {
// We enlarge bounding box just to be sure that plane will be large enough to cut all objects.
aBndBox.Enlarge(theEnlarge);
}
Standard_Real aYArr[2] = {aBndBox.CornerMin().Y(), aBndBox.CornerMax().Y()};
Standard_Real aZArr[2] = {aBndBox.CornerMin().Z(), aBndBox.CornerMax().Z()};
std::list<std::shared_ptr<GeomAPI_Pnt> > aResultPoints;
- int aNum = 0;
- for(int i = 0; i < 2; i++) {
- for(int j = 0; j < 2; j++) {
- for(int k = 0; k < 2; k++) {
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 2; j++) {
+ for (int k = 0; k < 2; k++) {
std::shared_ptr<GeomAPI_Pnt> aPnt(new GeomAPI_Pnt(aXArr[i], aYArr[j], aZArr[k]));
aResultPoints.push_back(aPnt);
}
return aResultPoints;
}
-//==================================================================================================
-std::shared_ptr<GeomAPI_Shape>
- GeomAlgoAPI_ShapeTools::faceToInfinitePlane(const std::shared_ptr<GeomAPI_Shape> theFace)
-{
- if (!theFace.get())
- return std::shared_ptr<GeomAPI_Shape>();
-
- TopoDS_Face aPlaneFace = TopoDS::Face(theFace->impl<TopoDS_Shape>());
- if (aPlaneFace.IsNull())
- return std::shared_ptr<GeomAPI_Shape>();
-
- Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(aPlaneFace));
- if (aPlane.IsNull())
- return std::shared_ptr<GeomAPI_Shape>();
-
- // make an infinity face on the plane
- TopoDS_Shape anInfiniteFace = BRepBuilderAPI_MakeFace(aPlane->Pln()).Shape();
-
- std::shared_ptr<GeomAPI_Shape> aResult(new GeomAPI_Shape);
- aResult->setImpl(new TopoDS_Shape(anInfiniteFace));
- return aResult;
-}
-
//==================================================================================================
std::shared_ptr<GeomAPI_Face> GeomAlgoAPI_ShapeTools::fitPlaneToBox(
const std::shared_ptr<GeomAPI_Shape> thePlane,
{
std::shared_ptr<GeomAPI_Face> aResultFace;
- if(!thePlane.get()) {
+ if (!thePlane.get()) {
return aResultFace;
}
const TopoDS_Shape& aShape = thePlane->impl<TopoDS_Shape>();
- if(aShape.ShapeType() != TopAbs_FACE) {
+ if (aShape.ShapeType() != TopAbs_FACE) {
return aResultFace;
}
TopoDS_Face aFace = TopoDS::Face(aShape);
Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
- if(aSurf.IsNull()) {
+ if (aSurf.IsNull()) {
return aResultFace;
}
GeomLib_IsPlanarSurface isPlanar(aSurf);
- if(!isPlanar.IsPlanar()) {
+ if (!isPlanar.IsPlanar()) {
return aResultFace;
}
- if(thePoints.size() != 8) {
+ if (thePoints.size() != 8) {
return aResultFace;
}
const gp_Pnt& aPntOnFace = anIntAna.Point(1);
Standard_Real aPntU(0), aPntV(0);
GeomLib_Tool::Parameters(aFacePlane, aPntOnFace, Precision::Confusion(), aPntU, aPntV);
- if(aPntU < UMin) UMin = aPntU;
- if(aPntU > UMax) UMax = aPntU;
- if(aPntV < VMin) VMin = aPntV;
- if(aPntV > VMax) VMax = aPntV;
+ if (aPntU < UMin) UMin = aPntU;
+ if (aPntU > UMax) UMax = aPntU;
+ if (aPntV < VMin) VMin = aPntV;
+ if (aPntV > VMax) VMax = aPntV;
}
aResultFace.reset(new GeomAPI_Face());
aResultFace->setImpl(new TopoDS_Face(BRepLib_MakeFace(aFacePln, UMin, UMax, VMin, VMax).Face()));
std::shared_ptr<GeomAPI_Vertex>& theV1,
std::shared_ptr<GeomAPI_Vertex>& theV2)
{
- if(!theShape.get()) {
- std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex);
+ static GeomVertexPtr aVertex;
+ if (!aVertex) {
+ aVertex = GeomVertexPtr(new GeomAPI_Vertex);
aVertex->setImpl(new TopoDS_Vertex());
- theV1 = aVertex;
- theV2 = aVertex;
- return;
}
- const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
- TopoDS_Vertex aV1, aV2;
- ShapeAnalysis::FindBounds(aShape, aV1, aV2);
+ theV1 = aVertex;
+ theV2 = aVertex;
+
+ if (theShape) {
+ const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
+ TopoDS_Vertex aV1, aV2;
+ ShapeAnalysis::FindBounds(aShape, aV1, aV2);
- std::shared_ptr<GeomAPI_Vertex> aGeomV1(new GeomAPI_Vertex()), aGeomV2(new GeomAPI_Vertex());
- aGeomV1->setImpl(new TopoDS_Vertex(aV1));
- aGeomV2->setImpl(new TopoDS_Vertex(aV2));
- theV1 = aGeomV1;
- theV2 = aGeomV2;
+ std::shared_ptr<GeomAPI_Vertex> aGeomV1(new GeomAPI_Vertex()), aGeomV2(new GeomAPI_Vertex());
+ aGeomV1->setImpl(new TopoDS_Vertex(aV1));
+ aGeomV2->setImpl(new TopoDS_Vertex(aV2));
+ theV1 = aGeomV1;
+ theV2 = aGeomV2;
+ }
}
//==================================================================================================
BRepAlgo_FaceRestrictor aFRestrictor;
aFRestrictor.Init(aFace, Standard_False, Standard_True);
- for(ListOfShape::const_iterator anIt = theWires.cbegin();
+ for (ListOfShape::const_iterator anIt = theWires.cbegin();
anIt != theWires.cend();
++anIt) {
TopoDS_Wire aWire = TopoDS::Wire((*anIt)->impl<TopoDS_Shape>());
aFRestrictor.Perform();
- if(!aFRestrictor.IsDone()) {
+ if (!aFRestrictor.IsDone()) {
return;
}
- for(; aFRestrictor.More(); aFRestrictor.Next()) {
+ for (; aFRestrictor.More(); aFRestrictor.Next()) {
GeomShapePtr aShape(new GeomAPI_Shape());
aShape->setImpl(new TopoDS_Shape(aFRestrictor.Current()));
theFaces.push_back(aShape);
BRep_Builder aBuilder;
aBuilder.MakeCompound(aCompound);
- for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
+ for (ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
aBuilder.Add(aCompound, (*anIt)->impl<TopoDS_Shape>());
}
BRepBuilderAPI_FindPlane aFindPlane(aCompound);
- if(aFindPlane.Found() != Standard_True) {
+ if (aFindPlane.Found() != Standard_True) {
return std::shared_ptr<GeomAPI_Pln>();
}
const std::shared_ptr<GeomAPI_Shape> theSubShape,
const std::shared_ptr<GeomAPI_Shape> theBaseShape)
{
- if(!theSubShape.get() || !theBaseShape.get()) {
+ if (!theSubShape.get() || !theBaseShape.get()) {
return false;
}
const TopoDS_Shape& aSubShape = theSubShape->impl<TopoDS_Shape>();
const TopoDS_Shape& aBaseShape = theBaseShape->impl<TopoDS_Shape>();
- if(aSubShape.ShapeType() == TopAbs_VERTEX) {
+ if (aSubShape.ShapeType() == TopAbs_VERTEX) {
// If sub-shape is a vertex check distance to shape. If it is <= Precision::Confusion() then OK.
BRepExtrema_DistShapeShape aDist(aBaseShape, aSubShape);
aDist.Perform();
- if(!aDist.IsDone() || aDist.Value() > Precision::Confusion()) {
+ if (!aDist.IsDone() || aDist.Value() > Precision::Confusion()) {
return false;
}
} else if (aSubShape.ShapeType() == TopAbs_EDGE) {
- if(aBaseShape.ShapeType() == TopAbs_FACE) {
+ if (aBaseShape.ShapeType() == TopAbs_FACE) {
// Check that edge is on face surface.
TopoDS_Face aFace = TopoDS::Face(aBaseShape);
TopoDS_Edge anEdge = TopoDS::Edge(aSubShape);
BRepLib_CheckCurveOnSurface aCheck(anEdge, aFace);
aCheck.Perform();
- if(!aCheck.IsDone() || aCheck.MaxDistance() > Precision::Confusion()) {
+ if (!aCheck.IsDone() || aCheck.MaxDistance() > Precision::Confusion()) {
return false;
}
ShapeAnalysis::FindBounds(anEdge, aV1, aV2);
gp_Pnt aPnt1 = BRep_Tool::Pnt(aV1);
gp_Pnt aPnt2 = BRep_Tool::Pnt(aV2);
- for(TopExp_Explorer anExp(aBaseShape, TopAbs_EDGE); anExp.More(); anExp.Next()) {
+ for (TopExp_Explorer anExp(aBaseShape, TopAbs_EDGE); anExp.More(); anExp.Next()) {
const TopoDS_Shape& anEdgeOnFace = anExp.Current();
BRepExtrema_DistShapeShape aDist(anEdgeOnFace, anEdge);
aDist.Perform();
- if(aDist.IsDone() && aDist.Value() <= Precision::Confusion()) {
+ if (aDist.IsDone() && aDist.Value() <= Precision::Confusion()) {
// Edge intersect face bound. Check that it is not on edge begin or end.
- for(Standard_Integer anIndex = 1; anIndex <= aDist.NbSolution(); ++anIndex) {
+ for (Standard_Integer anIndex = 1; anIndex <= aDist.NbSolution(); ++anIndex) {
gp_Pnt aPntOnSubShape = aDist.PointOnShape2(anIndex);
- if(aPntOnSubShape.Distance(aPnt1) > Precision::Confusion()
+ if (aPntOnSubShape.Distance(aPnt1) > Precision::Confusion()
&& aPntOnSubShape.Distance(aPnt2) > Precision::Confusion()) {
return false;
}
ShapeAnalysis_Surface aSAS(aSurface);
gp_Pnt2d aPointOnFace = aSAS.ValueOfUV(aPointToCheck, Precision::Confusion());
BRepTopAdaptor_FClass2d aFClass2d(aFace, Precision::Confusion());
- if(aFClass2d.Perform(aPointOnFace) == TopAbs_OUT) {
+ if (aFClass2d.Perform(aPointOnFace) == TopAbs_OUT) {
return false;
}
//==================================================================================================
bool GeomAlgoAPI_ShapeTools::isShapeValid(const std::shared_ptr<GeomAPI_Shape> theShape)
{
- if(!theShape.get()) {
+ if (!theShape.get()) {
return false;
}
{
GeomShapePtr anOuterWire;
- if(!theFace.get() || !theFace->isFace()) {
+ if (!theFace.get() || !theFace->isFace()) {
return anOuterWire;
}
return anOuterWire;
}
+//==================================================================================================
+static bool boundaryOfEdge(const std::shared_ptr<GeomAPI_Edge> theEdge,
+ const std::shared_ptr<GeomAPI_Vertex> theVertex,
+ double& theParam)
+{
+ GeomPointPtr aPoint = theVertex->point();
+ GeomPointPtr aFirstPnt = theEdge->firstPoint();
+ double aFirstPntTol = theEdge->firstPointTolerance();
+ GeomPointPtr aLastPnt = theEdge->lastPoint();
+ double aLastPntTol = theEdge->lastPointTolerance();
+
+ double aFirst, aLast;
+ theEdge->getRange(aFirst, aLast);
+
+ bool isFirst = aPoint->distance(aFirstPnt) <= aFirstPntTol;
+ bool isLast = aPoint->distance(aLastPnt) <= aLastPntTol;
+ if (isFirst)
+ theParam = aFirst;
+ else if (isLast)
+ theParam = aLast;
+
+ return isFirst != isLast;
+}
+
+bool GeomAlgoAPI_ShapeTools::isTangent(const std::shared_ptr<GeomAPI_Edge> theEdge1,
+ const std::shared_ptr<GeomAPI_Edge> theEdge2,
+ const std::shared_ptr<GeomAPI_Vertex> theTgPoint)
+{
+ double aParE1 = 0, aParE2 = 0;
+ if (!boundaryOfEdge(theEdge1, theTgPoint, aParE1) ||
+ !boundaryOfEdge(theEdge2, theTgPoint, aParE2))
+ return false;
+
+ BRepAdaptor_Curve aC1(theEdge1->impl<TopoDS_Edge>());
+ BRepAdaptor_Curve aC2(theEdge2->impl<TopoDS_Edge>());
+ return BRepLProp::Continuity(aC1, aC2, aParE1, aParE2) >= GeomAbs_G1;
+}
+
//==================================================================================================
bool GeomAlgoAPI_ShapeTools::isParallel(const std::shared_ptr<GeomAPI_Edge> theEdge,
const std::shared_ptr<GeomAPI_Face> theFace)
{
- if(!theEdge.get() || !theFace.get()) {
+ if (!theEdge.get() || !theFace.get()) {
return false;
}
return anExt.IsParallel() == Standard_True;
}
+//==================================================================================================
+std::list<std::shared_ptr<GeomAPI_Vertex> > GeomAlgoAPI_ShapeTools::intersect(
+ const std::shared_ptr<GeomAPI_Edge> theEdge, const std::shared_ptr<GeomAPI_Face> theFace)
+{
+ std::list<std::shared_ptr<GeomAPI_Vertex> > aResult;
+ if (!theEdge.get() || !theFace.get()) {
+ return aResult;
+ }
+
+ TopoDS_Edge anEdge = TopoDS::Edge(theEdge->impl<TopoDS_Shape>());
+ double aFirstOnCurve, aLastOnCurve;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirstOnCurve, aLastOnCurve);
+
+ TopoDS_Face aFace = TopoDS::Face(theFace->impl<TopoDS_Shape>());
+ Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
+
+ GeomAPI_IntCS anIntAlgo(aCurve, aSurf);
+ if (!anIntAlgo.IsDone())
+ return aResult;
+ // searching for points-intersection
+ for (int anIntNum = 1; anIntNum <= anIntAlgo.NbPoints() + anIntAlgo.NbSegments(); anIntNum++) {
+ gp_Pnt anInt;
+ if (anIntNum <= anIntAlgo.NbPoints()) {
+ anInt = anIntAlgo.Point(anIntNum);
+ } else { // take the middle point on the segment of the intersection
+ Handle(Geom_Curve) anIntCurve = anIntAlgo.Segment(anIntNum - anIntAlgo.NbPoints());
+ anIntCurve->D0((anIntCurve->FirstParameter() + anIntCurve->LastParameter()) / 2., anInt);
+ }
+ aResult.push_back(std::shared_ptr<GeomAPI_Vertex>(
+ new GeomAPI_Vertex(anInt.X(), anInt.Y(), anInt.Z())));
+ }
+ return aResult;
+}
+
//==================================================================================================
void GeomAlgoAPI_ShapeTools::splitShape(const std::shared_ptr<GeomAPI_Shape>& theBaseShape,
const GeomAlgoAPI_ShapeTools::PointToRefsMap& thePointsInfo,
}
aBOP.Perform();
- if (aBOP.ErrorStatus())
+ if (aBOP.HasErrors())
return;
// Collect splits
}
aBOP.Perform();
- if (aBOP.ErrorStatus())
+ if (aBOP.HasErrors())
return;
// Collect splits
}
//==================================================================================================
+#ifdef FEATURE_MULTIROTATION_TWO_DIRECTIONS
std::shared_ptr<GeomAPI_Dir> GeomAlgoAPI_ShapeTools::buildDirFromAxisAndShape(
const std::shared_ptr<GeomAPI_Shape> theBaseShape,
const std::shared_ptr<GeomAPI_Ax1> theAxis)
aCentreOfMassPoint.Y()-aPoint.Y(),
aCentreOfMassPoint.Z()-aPoint.Z()));
return aDir;
-}
\ No newline at end of file
+}
+#endif
+
+//==================================================================================================
+static TopoDS_Wire fixParametricGaps(const TopoDS_Wire& theWire)
+{
+ TopoDS_Wire aFixedWire;
+ Handle(Geom_Curve) aPrevCurve;
+ double aPrevLastParam = -Precision::Infinite();
+
+ BRep_Builder aBuilder;
+ aBuilder.MakeWire(aFixedWire);
+
+ BRepTools_WireExplorer aWExp(theWire);
+ for (; aWExp.More(); aWExp.Next()) {
+ TopoDS_Edge anEdge = aWExp.Current();
+ double aFirst, aLast;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+ if (aCurve == aPrevCurve && Abs(aFirst - aPrevLastParam) > Precision::Confusion()) {
+ // if parametric gap occurs, create new edge based on the copied curve
+ aCurve = Handle(Geom_Curve)::DownCast(aCurve->Copy());
+ TopoDS_Vertex aV1, aV2;
+ TopExp::Vertices(anEdge, aV1, aV2);
+ anEdge = TopoDS::Edge(anEdge.EmptyCopied());
+ aBuilder.UpdateEdge(anEdge, aCurve, BRep_Tool::Tolerance(anEdge));
+ aBuilder.Add(anEdge, aV1);
+ aBuilder.Add(anEdge, aV2);
+ }
+
+ aBuilder.Add(aFixedWire, anEdge);
+
+ aPrevCurve = aCurve;
+ aPrevLastParam = aLast;
+ }
+
+ return aFixedWire;
+}
+
+//==================================================================================================
+std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_ShapeTools::wireToEdge(
+ const std::shared_ptr<GeomAPI_Wire>& theWire)
+{
+ GeomEdgePtr anEdge;
+ if (theWire) {
+ TopoDS_Wire aWire = theWire->impl<TopoDS_Wire>();
+ BRepTools_WireExplorer aWExp(aWire);
+ TopoDS_Edge aNewEdge = aWExp.Current();
+ aWExp.Next();
+ if (aWExp.More()) {
+ // Workaround for the closed wire to avoid jumping of its start point:
+ // split this wire for two parts, convert them to edges, then compose together
+ if (BRep_Tool::IsClosed(aWire)) {
+ aWire = TopoDS::Wire(BRepBuilderAPI_Copy(aWire).Shape());
+ aWExp.Init(aWire);
+ aNewEdge = aWExp.Current();
+
+ BRep_Builder().Remove(aWire, aNewEdge);
+ GeomWirePtr aSplitWire(new GeomAPI_Wire);
+ aSplitWire->setImpl(new TopoDS_Wire(aWire));
+ GeomEdgePtr aMergedEdge = wireToEdge(aSplitWire);
+
+ aWire = BRepBuilderAPI_MakeWire(aNewEdge, aMergedEdge->impl<TopoDS_Edge>());
+ }
+
+ // Workaround: when concatenate a wire consisting of two edges based on the same B-spline
+ // curve (non-periodic, but having equal start and end points), first of which is placed
+ // at the end on the curve and second is placed at the start, this workaround copies
+ // second curve to avoid treating these edges as a single curve by setting trim parameters.
+ aWire = fixParametricGaps(aWire);
+ aWire = BRepAlgo::ConcatenateWire(aWire, GeomAbs_G1); // join smooth parts of wire
+ aNewEdge = BRepAlgo::ConcatenateWireC0(aWire); // join C0 parts of wire
+
+ // Reapproximate the result edge to have the parameter equal to curvilinear abscissa.
+ static const int THE_MAX_DEGREE = 14;
+ static const int THE_MAX_INTERVALS = 32;
+ double aFirst, aLast;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aNewEdge, aFirst, aLast);
+#if OCC_VERSION_LARGE < 0x07070000
+ Handle(GeomAdaptor_HCurve) aHCurve = new GeomAdaptor_HCurve(aCurve);
+#else
+ Handle(GeomAdaptor_Curve) aHCurve = new GeomAdaptor_Curve(aCurve);
+#endif
+ Approx_CurvilinearParameter anApprox(aHCurve, Precision::Confusion(), aCurve->Continuity(),
+ THE_MAX_DEGREE, THE_MAX_INTERVALS);
+ if (anApprox.HasResult()) {
+ Handle(Geom_BSplineCurve) aNewCurve = anApprox.Curve3d();
+ TColStd_Array1OfReal aKnots = aNewCurve->Knots();
+ BSplCLib::Reparametrize(aFirst, aLast, aKnots);
+ aNewCurve->SetKnots(aKnots);
+ BRep_Builder().UpdateEdge(aNewEdge, aNewCurve, BRep_Tool::Tolerance(aNewEdge));
+ }
+ }
+ anEdge = GeomEdgePtr(new GeomAPI_Edge);
+ anEdge->setImpl(new TopoDS_Edge(aNewEdge));
+ }
+ return anEdge;
+}
+
+//==================================================================================================
+ListOfShape GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(const GeomShapePtr& theShape)
+{
+ ListOfShape aSubShapes;
+
+ if (!theShape->isCompound() && !theShape->isCompSolid() &&
+ !theShape->isShell() && !theShape->isWire()) {
+ return aSubShapes;
+ }
+
+ for (GeomAPI_ShapeIterator anIt(theShape); anIt.more(); anIt.next()) {
+ GeomShapePtr aSubShape = anIt.current();
+ if (aSubShape->isVertex() || aSubShape->isEdge() ||
+ aSubShape->isFace() || aSubShape->isSolid()) {
+ aSubShapes.push_back(aSubShape);
+ } else {
+ aSubShapes.splice(aSubShapes.end(), getLowLevelSubShapes(aSubShape));
+ }
+ }
+
+ return aSubShapes;
+}
+
+//==================================================================================================
+static void getMinMaxPointsOnLine(const std::list<std::shared_ptr<GeomAPI_Pnt> >& thePoints,
+ const gp_Dir theDir,
+ double& theMin, double& theMax)
+{
+ theMin = RealLast();
+ theMax = RealFirst();
+ // Project bounding points on theDir
+ for (std::list<std::shared_ptr<GeomAPI_Pnt> >::const_iterator
+ aPointsIt = thePoints.begin(); aPointsIt != thePoints.end(); aPointsIt++) {
+ const gp_Pnt& aPnt = (*aPointsIt)->impl<gp_Pnt>();
+ gp_Dir aPntDir (aPnt.XYZ());
+ Standard_Real proj = (theDir*aPntDir) * aPnt.XYZ().Modulus();
+ if (proj < theMin) theMin = proj;
+ if (proj > theMax) theMax = proj;
+ }
+}
+
+//==================================================================================================
+void GeomAlgoAPI_ShapeTools::computeThroughAll(const ListOfShape& theObjects,
+ const ListOfShape& theBaseShapes,
+ const std::shared_ptr<GeomAPI_Dir> theDir,
+ double& theToSize, double& theFromSize)
+{
+ // Bounding box of objects
+ std::list<std::shared_ptr<GeomAPI_Pnt> > aBndObjs =
+ GeomAlgoAPI_ShapeTools::getBoundingBox(theObjects);
+ if (aBndObjs.size() != 8) {
+ return;
+ }
+
+ // the value to enlarge the bounding box of each object to make the extruded shape
+ // a little bit larger than overall objects to get the correct result of Boolean CUT operation
+ double anEnlargement = 0.1 * aBndObjs.front()->distance(aBndObjs.back());
+
+ // Prism direction
+ if (theDir.get()) {
+ // One direction for all prisms
+ gp_Dir aDir = theDir->impl<gp_Dir>();
+
+ // Bounding box of the base
+ std::list<std::shared_ptr<GeomAPI_Pnt> > aBndBases =
+ GeomAlgoAPI_ShapeTools::getBoundingBox(theBaseShapes);
+ if (aBndBases.size() != 8) {
+ return;
+ }
+
+ // Objects bounds
+ Standard_Real lowBnd, upperBnd;
+ getMinMaxPointsOnLine(aBndObjs, aDir, lowBnd, upperBnd);
+
+ // Base bounds
+ Standard_Real lowBase, upperBase;
+ getMinMaxPointsOnLine(aBndBases, aDir, lowBase, upperBase);
+
+ // ----------.-----.---------.--------------.-----------> theDir
+ // lowBnd lowBase upperBase upperBnd
+
+ theToSize = upperBnd - lowBase;
+ theFromSize = upperBase - lowBnd;
+ } else {
+ // Direction is a normal to each base shape (different normals to bases)
+ // So we calculate own sizes for each base shape
+ theToSize = 0.0;
+ theFromSize = 0.0;
+
+ for (ListOfShape::const_iterator anIt = theBaseShapes.begin();
+ anIt != theBaseShapes.end(); ++anIt) {
+ const GeomShapePtr& aBaseShape_i = (*anIt);
+ ListOfShape aBaseShapes_i;
+ aBaseShapes_i.push_back(aBaseShape_i);
+
+ // Bounding box of the base
+ std::list<std::shared_ptr<GeomAPI_Pnt> > aBndBases =
+ GeomAlgoAPI_ShapeTools::getBoundingBox(aBaseShapes_i, anEnlargement);
+ if (aBndBases.size() != 8) {
+ return;
+ }
+
+ // Direction (normal to aBaseShapes_i)
+ // Code like in GeomAlgoAPI_Prism
+ gp_Dir aDir;
+ const TopoDS_Shape& aBaseShape = aBaseShape_i->impl<TopoDS_Shape>();
+ BRepBuilderAPI_FindPlane aFindPlane(aBaseShape);
+ if (aFindPlane.Found() == Standard_True) {
+ Handle(Geom_Plane) aPlane;
+ if (aBaseShape.ShapeType() == TopAbs_FACE || aBaseShape.ShapeType() == TopAbs_SHELL) {
+ TopExp_Explorer anExp(aBaseShape, TopAbs_FACE);
+ const TopoDS_Shape& aFace = anExp.Current();
+ Handle(Geom_Surface) aSurface = BRep_Tool::Surface(TopoDS::Face(aFace));
+ if (aSurface->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
+ Handle(Geom_RectangularTrimmedSurface) aTrimSurface =
+ Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
+ aSurface = aTrimSurface->BasisSurface();
+ }
+ if (aSurface->DynamicType() != STANDARD_TYPE(Geom_Plane)) {
+ return;
+ }
+ aPlane = Handle(Geom_Plane)::DownCast(aSurface);
+ } else {
+ aPlane = aFindPlane.Plane();
+ }
+ aDir = aPlane->Axis().Direction();
+ } else {
+ return;
+ }
+
+ // Objects bounds
+ Standard_Real lowBnd, upperBnd;
+ getMinMaxPointsOnLine(aBndObjs, aDir, lowBnd, upperBnd);
+
+ // Base bounds
+ Standard_Real lowBase, upperBase;
+ getMinMaxPointsOnLine(aBndBases, aDir, lowBase, upperBase);
+
+ // ----------.-----.---------.--------------.-----------> theDir
+ // lowBnd lowBase upperBase upperBnd
+
+ double aToSize_i = upperBnd - lowBase;
+ double aFromSize_i = upperBase - lowBnd;
+
+ if (aToSize_i > theToSize) theToSize = aToSize_i;
+ if (aFromSize_i > theFromSize) theFromSize = aFromSize_i;
+ }
+ }
+}
+
+ListOfShape GeomAlgoAPI_ShapeTools::getSharedFaces(const GeomShapePtr& theShape)
+{
+ ListOfShape aSharedFaces;
+ TopTools_IndexedDataMapOfShapeListOfShape aMapFS;
+ TopExp::MapShapesAndUniqueAncestors(theShape->impl<TopoDS_Shape>(),
+ TopAbs_FACE, TopAbs_SOLID, aMapFS);
+ for (Standard_Integer i = 1; i <= aMapFS.Extent(); i++) {
+ const TopTools_ListOfShape& ancestors = aMapFS.FindFromIndex(i);
+ if (ancestors.Size() > 1) {
+ GeomShapePtr aFace(new GeomAPI_Shape);
+ aFace->setImpl<TopoDS_Shape>(new TopoDS_Shape(aMapFS.FindKey(i)));
+ aSharedFaces.push_back(aFace);
+ }
+ }
+ return aSharedFaces;
+}