+
+//==================================================================================================
+std::list<std::shared_ptr<GeomAPI_Vertex> > GeomAlgoAPI_ShapeTools::intersect(
+ const std::shared_ptr<GeomAPI_Edge> theEdge, const std::shared_ptr<GeomAPI_Face> theFace,
+ const bool thePointsOutsideFace)
+{
+ 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,
+ std::set<std::shared_ptr<GeomAPI_Shape> >& theShapes)
+{
+ // to split shape at least one point should be presented in the points container
+ if (thePointsInfo.empty())
+ return;
+
+ // General Fuse to split edge by vertices
+ BOPAlgo_Builder aBOP;
+ TopoDS_Edge aBaseEdge = theBaseShape->impl<TopoDS_Edge>();
+ // Rebuild closed edge to place vertex to one of split points.
+ // This will prevent edge to be split on same vertex.
+ if (BRep_Tool::IsClosed(aBaseEdge))
+ {
+ Standard_Real aFirst, aLast;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aBaseEdge, aFirst, aLast);
+
+ PointToRefsMap::const_iterator aPIt = thePointsInfo.begin();
+ std::shared_ptr<GeomAPI_Pnt> aPnt = aPIt->first;
+ gp_Pnt aPoint(aPnt->x(), aPnt->y(), aPnt->z());
+
+ TopAbs_Orientation anOrientation = aBaseEdge.Orientation();
+ aBaseEdge = BRepBuilderAPI_MakeEdge(aCurve, aPoint, aPoint).Edge();
+ aBaseEdge.Orientation(anOrientation);
+ }
+ aBOP.AddArgument(aBaseEdge);
+
+ PointToRefsMap::const_iterator aPIt = thePointsInfo.begin();
+ for (; aPIt != thePointsInfo.end(); ++aPIt) {
+ std::shared_ptr<GeomAPI_Pnt> aPnt = aPIt->first;
+ TopoDS_Vertex aV = BRepBuilderAPI_MakeVertex(gp_Pnt(aPnt->x(), aPnt->y(), aPnt->z()));
+ aBOP.AddArgument(aV);
+ }
+
+ aBOP.Perform();
+ if (aBOP.HasErrors())
+ return;
+
+ // Collect splits
+ const TopTools_ListOfShape& aSplits = aBOP.Modified(aBaseEdge);
+ TopTools_ListIteratorOfListOfShape anIt(aSplits);
+ for (; anIt.More(); anIt.Next()) {
+ std::shared_ptr<GeomAPI_Shape> anEdge(new GeomAPI_Shape);
+ anEdge->setImpl(new TopoDS_Shape(anIt.Value()));
+ theShapes.insert(anEdge);
+ }
+}
+
+//==================================================================================================
+void GeomAlgoAPI_ShapeTools::splitShape_p(const std::shared_ptr<GeomAPI_Shape>& theBaseShape,
+ const std::list<std::shared_ptr<GeomAPI_Pnt> >& thePoints,
+ std::set<std::shared_ptr<GeomAPI_Shape> >& theShapes)
+{
+ // General Fuse to split edge by vertices
+ BOPAlgo_Builder aBOP;
+ TopoDS_Edge aBaseEdge = theBaseShape->impl<TopoDS_Edge>();
+ // Rebuild closed edge to place vertex to one of split points.
+ // This will prevent edge to be split on seam vertex.
+ if (BRep_Tool::IsClosed(aBaseEdge))
+ {
+ Standard_Real aFirst, aLast;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aBaseEdge, aFirst, aLast);
+
+ std::list<std::shared_ptr<GeomAPI_Pnt> >::const_iterator aPIt = thePoints.begin();
+ gp_Pnt aPoint((*aPIt)->x(), (*aPIt)->y(), (*aPIt)->z());
+
+ TopAbs_Orientation anOrientation = aBaseEdge.Orientation();
+ aBaseEdge = BRepBuilderAPI_MakeEdge(aCurve, aPoint, aPoint).Edge();
+ aBaseEdge.Orientation(anOrientation);
+ }
+ aBOP.AddArgument(aBaseEdge);
+
+ std::list<std::shared_ptr<GeomAPI_Pnt> >::const_iterator aPtIt = thePoints.begin();
+ for (; aPtIt != thePoints.end(); ++aPtIt) {
+ std::shared_ptr<GeomAPI_Pnt> aPnt = *aPtIt;
+ TopoDS_Vertex aV = BRepBuilderAPI_MakeVertex(gp_Pnt(aPnt->x(), aPnt->y(), aPnt->z()));
+ aBOP.AddArgument(aV);
+ }
+
+ aBOP.Perform();
+ if (aBOP.HasErrors())
+ return;
+
+ // Collect splits
+ const TopTools_ListOfShape& aSplits = aBOP.Modified(aBaseEdge);
+ TopTools_ListIteratorOfListOfShape anIt(aSplits);
+ for (; anIt.More(); anIt.Next()) {
+ std::shared_ptr<GeomAPI_Shape> anEdge(new GeomAPI_Shape);
+ anEdge->setImpl(new TopoDS_Shape(anIt.Value()));
+ theShapes.insert(anEdge);
+ }
+}
+
+//==================================================================================================
+std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::findShape(
+ const std::list<std::shared_ptr<GeomAPI_Pnt> >& thePoints,
+ const std::set<std::shared_ptr<GeomAPI_Shape> >& theShapes)
+{
+ std::shared_ptr<GeomAPI_Shape> aResultShape;
+
+ if (thePoints.size() == 2) {
+ std::list<std::shared_ptr<GeomAPI_Pnt> >::const_iterator aPntIt = thePoints.begin();
+ std::shared_ptr<GeomAPI_Pnt> aFirstPoint = *aPntIt;
+ aPntIt++;
+ std::shared_ptr<GeomAPI_Pnt> aLastPoint = *aPntIt;
+
+ std::set<std::shared_ptr<GeomAPI_Shape> >::const_iterator anIt = theShapes.begin(),
+ aLast = theShapes.end();
+ for (; anIt != aLast; anIt++) {
+ GeomShapePtr aShape = *anIt;
+ std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aShape));
+ if (anEdge.get()) {
+ std::shared_ptr<GeomAPI_Pnt> anEdgeFirstPoint = anEdge->firstPoint();
+ std::shared_ptr<GeomAPI_Pnt> anEdgeLastPoint = anEdge->lastPoint();
+ if (anEdgeFirstPoint->isEqual(aFirstPoint) &&
+ anEdgeLastPoint->isEqual(aLastPoint))
+ aResultShape = aShape;
+ }
+ }
+ }
+
+ return aResultShape;
+}
+
+//==================================================================================================
+std::shared_ptr<GeomAPI_Dir> GeomAlgoAPI_ShapeTools::buildDirFromAxisAndShape(
+ const std::shared_ptr<GeomAPI_Shape> theBaseShape,
+ const std::shared_ptr<GeomAPI_Ax1> theAxis)
+{
+ gp_Pnt aCentreOfMassPoint =
+ GeomAlgoAPI_ShapeTools::centreOfMass(theBaseShape)->impl<gp_Pnt>();
+ Handle(Geom_Line) aLine = new Geom_Line(theAxis->impl<gp_Ax1>());
+ GeomAPI_ProjectPointOnCurve aPrjTool(aCentreOfMassPoint, aLine);
+ gp_Pnt aPoint = aPrjTool.NearestPoint();
+
+ std::shared_ptr<GeomAPI_Dir> aDir(new GeomAPI_Dir(aCentreOfMassPoint.X()-aPoint.X(),
+ aCentreOfMassPoint.Y()-aPoint.Y(),
+ aCentreOfMassPoint.Z()-aPoint.Z()));
+ return aDir;
+}
+
+//==================================================================================================
+static TopoDS_Wire fixParametricGaps(const TopoDS_Wire& theWire)
+{
+ TopoDS_Wire aFixedWire;
+ Handle(Geom_Curve) aPrevCurve;
+ double aPrevLastParam = 0.0;
+
+ 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) {
+ // 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>();
+ // 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);
+ TopoDS_Edge aNewEdge = BRepAlgo::ConcatenateWireC0(aWire);
+ 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;
+}
\ No newline at end of file