-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: GeomAlgoAPI_ShapeTools.h
-// Created: 3 August 2015
-// Author: Dmitry Bobylev
+// Copyright (C) 2014-2017 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
#include "GeomAlgoAPI_ShapeTools.h"
#include "GeomAlgoAPI_SketchBuilder.h"
+#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 <Bnd_Box.hxx>
-#include <BOPTools.hxx>
#include <BRep_Builder.hxx>
#include <BRepAdaptor_Curve.hxx>
+#include <BRepAlgo.hxx>
#include <BRepAlgo_FaceRestrictor.hxx>
#include <BRepBndLib.hxx>
#include <BRepBuilderAPI_FindPlane.hxx>
#include <BRepExtrema_ExtCF.hxx>
#include <BRepGProp.hxx>
#include <BRepTools.hxx>
+#include <BRepTools_WireExplorer.hxx>
#include <BRepTopAdaptor_FClass2d.hxx>
+#include <BRepClass_FaceClassifier.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_Curve.hxx>
#include <BRepLib_CheckCurveOnSurface.hxx>
#include <BRep_Tool.hxx>
+#include <Geom_CylindricalSurface.hxx>
+#include <Geom_Line.hxx>
#include <Geom_Plane.hxx>
+#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 <TopoDS_Shell.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS.hxx>
+#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
+
#include <BOPAlgo_Builder.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <TopoDS_Edge.hxx>
+//==================================================================================================
+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::volume(const std::shared_ptr<GeomAPI_Shape> theShape)
{
return 0.0;
}
const Standard_Real anEps = 1.e-6;
- BRepGProp::VolumeProperties(aShape, aGProps, anEps);
+ if (aShape.ShapeType() <= TopAbs_SOLID)
+ BRepGProp::VolumeProperties(aShape, aGProps, anEps);
+ else
+ BRepGProp::SurfaceProperties(aShape, aGProps, anEps);
+ return aGProps.Mass();
+}
+
+//==================================================================================================
+double GeomAlgoAPI_ShapeTools::area (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;
+ }
+ const Standard_Real anEps = 1.e-6;
+
+ BRepGProp::SurfaceProperties(aShape, aGProps, anEps);
return aGProps.Mass();
}
gp_Pnt aCentre;
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;
+}
+
+//==================================================================================================
+double GeomAlgoAPI_ShapeTools::minimalDistance(const GeomShapePtr& theShape1,
+ const GeomShapePtr& theShape2)
+{
+ 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.IsDone() ? aDist.Value() : Precision::Infinite();
+}
+
//==================================================================================================
std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::combineShapes(
const std::shared_ptr<GeomAPI_Shape> theCompound,
}
}
- // Map subshapes and shapes.
- BOPCol_IndexedDataMapOfShapeListOfShape aMapSA;
- BOPTools::MapShapesAndAncestors(aShapesComp, aTS, aTA, aMapSA);
+ // Map sub-shapes and shapes.
+ TopTools_IndexedDataMapOfShapeListOfShape aMapSA;
+ TopExp::MapShapesAndAncestors(aShapesComp, aTS, aTA, aMapSA);
if(aMapSA.IsEmpty()) {
return aResult;
}
- // 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();
+ TopTools_ListOfShape& aListOfShape = anIter.ChangeValue();
if(aListOfShape.IsEmpty()) {
continue;
}
} 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
aTempIter(aTempList); aTempIter.More(); aTempIter.Next()) {
const TopoDS_Shape& aTempShape = aTempIter.Value();
- for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator
+ for(TopTools_IndexedDataMapOfShapeListOfShape::Iterator
anIter(aMapSA); anIter.More(); anIter.Next()) {
- BOPCol_ListOfShape& aTempListOfShape = anIter.ChangeValue();
+ TopTools_ListOfShape& aTempListOfShape = anIter.ChangeValue();
if(aTempListOfShape.IsEmpty()) {
continue;
} 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);
+ 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.
+ // Combine shapes with common sub-shapes.
for(NCollection_Vector<NCollection_Map<TopoDS_Shape>>::Iterator
anIter(aShapesWithCommonSubshapes); anIter.More(); anIter.Next()) {
TopoDS_Shell aShell;
{
GeomShapePtr aResult = theCompound;
- if(!theCompound.get()) {
+ if (!theCompound.get()) {
return aResult;
}
TopoDS_Shape anInShape = aResult->impl<TopoDS_Shape>();
- NCollection_List<TopoDS_Shape> anUngroupedShapes;
+ NCollection_List<TopoDS_Shape> anUngroupedShapes, aStillUngroupedShapes;
addSimpleShapeToList(anInShape, anUngroupedShapes);
- NCollection_Vector<NCollection_List<TopoDS_Shape>> aGroups;
- while(!anUngroupedShapes.IsEmpty()) {
- NCollection_List<TopoDS_Shape> aGroupedShapes;
- aGroupedShapes.Append(anUngroupedShapes.First());
- anUngroupedShapes.RemoveFirst();
- for(NCollection_List<TopoDS_Shape>::Iterator aGroupIt(aGroupedShapes);
- aGroupIt.More(); aGroupIt.Next()) {
- const TopoDS_Shape& aGroupShape = aGroupIt.Value();
- for(NCollection_List<TopoDS_Shape>::Iterator anUngroupedIt(anUngroupedShapes);
- anUngroupedIt.More(); anUngroupedIt.Next()) {
- const TopoDS_Shape& anUngroupedShape = anUngroupedIt.Value();
- bool isFound = false;
- for(TopExp_Explorer aGroupShapeExp(aGroupShape, TopAbs_VERTEX);
- aGroupShapeExp.More(); aGroupShapeExp.Next()) {
- const TopoDS_Shape& aVertex1 = aGroupShapeExp.Current();
- for(TopExp_Explorer anUngroupedShapeExp(anUngroupedShape, TopAbs_VERTEX);
- anUngroupedShapeExp.More(); anUngroupedShapeExp.Next()) {
- const TopoDS_Shape& aVertex2 = anUngroupedShapeExp.Current();
- if(aVertex1.IsSame(aVertex2)) {
- aGroupedShapes.Append(anUngroupedShape);
- anUngroupedShapes.Remove(anUngroupedIt);
- isFound = true;
- break;
- }
- }
- if(isFound) {
- break;
+ // Iterate over all shapes and find shapes with shared vertices.
+ 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()) {
+ const TopoDS_Shape& aVertex = aShapeExp.Current();
+ if (!aVertexShapesMap.IsBound(aVertex)) {
+ NCollection_List<TopoDS_Shape> aList;
+ aList.Append(aShape);
+ allVertices.Append(aVertex);
+ aVertexShapesMap.Bind(aVertex, aList);
+ }
+ else {
+ if (!aVertexShapesMap.ChangeFind(aVertex).Contains(aShape)) {
+ aVertexShapesMap.ChangeFind(aVertex).Append(aShape);
+ }
+ }
+ }
+ }
+
+ // Iterate over the map and group shapes.
+ 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 = allVertices.First();
+ TopTools_ListOfShape aConnectedShapes = aVertexShapesMap.Find(aKey);
+ aVertexShapesMap.UnBind(aKey);
+ allVertices.Remove(aKey);
+ // Iterate over shapes in this group and add to it shapes from groups in map.
+ for (TopTools_ListOfShape::Iterator aConnectedIt(aConnectedShapes);
+ aConnectedIt.More(); aConnectedIt.Next()) {
+ const TopoDS_Shape& aConnected = aConnectedIt.Value();
+ TopTools_ListOfShape aKeysToUnbind;
+ 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;
+ }
+ // 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);
}
}
- if(!anUngroupedIt.More()) {
- break;
+ // 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()) {
+ aVertexShapesMap.UnBind(aKeysIt.Value());
+ allVertices.Remove(aKeysIt.Value());
+ }
+ }
+ // 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.Add(anIt.Value());
+ aConnectedShapes.Remove(anIt);
+ }
+ else {
+ anIt.Next();
}
}
}
- aGroups.Append(aGroupedShapes);
+ aGroups.Append(aSortedGroup);
}
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();
+ 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()));
+ 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,
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_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);
-
- 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;
+ 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;
+ }
}
//==================================================================================================
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,
+ 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)
{
}
aBOP.Perform();
- if (aBOP.ErrorStatus())
+ if (aBOP.HasErrors())
return;
// Collect splits
return aResultShape;
}
+
+//==================================================================================================
+#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)
+{
+ 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;
+}
+#endif
+
+//==================================================================================================
+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