X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGeomAlgoAPI%2FGeomAlgoAPI_ShapeTools.cpp;h=d1d3abe8b5317f5b03ee1e892e3e19c53f65b07f;hb=fd49e1d69802ac4fa4f4c6bd54b9bc483db92105;hp=63c9912778102892652a781e5cb288d383cd8619;hpb=2532fb2df83ee1ddd9ff3e8b381d3788eaa15b69;p=modules%2Fshaper.git diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp index 63c991277..d1d3abe8b 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// Copyright (C) 2014-2019 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 @@ -12,25 +12,27 @@ // // 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 +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include "GeomAlgoAPI_ShapeTools.h" #include "GeomAlgoAPI_SketchBuilder.h" +#include #include #include #include #include #include +#include #include -#include #include #include +#include #include #include #include @@ -41,14 +43,21 @@ #include #include #include +#include #include +#include #include #include #include #include +#include +#include #include +#include +#include #include #include +#include #include #include #include @@ -63,15 +72,73 @@ #include #include #include +#include #include #include + #include #include #include +//================================================================================================== +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 theShape) +{ + if(!theShape.get()) { + return 0.0; + } + const TopoDS_Shape& aShape = theShape->impl(); + if(aShape.IsNull()) { + return 0.0; + } + const Standard_Real anEps = 1.e-6; + TopExp_Explorer anExp(aShape, TopAbs_SOLID); + if (anExp.More()) { // return volume if there is at least one solid + double aVolume = 0.0; + for (; anExp.More(); anExp.Next()) { + GProp_GProps aGProps; + BRepGProp::VolumeProperties(anExp.Current(), aGProps, anEps); + aVolume += aGProps.Mass(); + } + return aVolume; + } + // return surfaces area + GProp_GProps aGProps; + BRepGProp::SurfaceProperties(aShape, aGProps, anEps); + return aGProps.Mass(); +} + +//================================================================================================== +double GeomAlgoAPI_ShapeTools::area (const std::shared_ptr theShape) { GProp_GProps aGProps; if(!theShape.get()) { @@ -82,7 +149,8 @@ double GeomAlgoAPI_ShapeTools::volume(const std::shared_ptr theSh return 0.0; } const Standard_Real anEps = 1.e-6; - BRepGProp::VolumeProperties(aShape, aGProps, anEps); + + BRepGProp::SurfaceProperties(aShape, aGProps, anEps); return aGProps.Mass(); } @@ -101,23 +169,50 @@ std::shared_ptr 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(new GeomAPI_Pnt(aCentre.X(), aCentre.Y(), aCentre.Z())); } +//================================================================================================== +double GeomAlgoAPI_ShapeTools::radius(const std::shared_ptr& theCylinder) +{ + double aRadius = -1.0; + if (theCylinder->isCylindrical()) { + const TopoDS_Shape& aShape = theCylinder->impl(); + 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(); + const TopoDS_Shape& aShape2 = theShape2->impl(); + + BRepExtrema_DistShapeShape aDist(aShape1, aShape2); + aDist.Perform(); + return aDist.IsDone() ? aDist.Value() : Precision::Infinite(); +} + //================================================================================================== std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes( const std::shared_ptr theCompound, const GeomAPI_Shape::ShapeType theType, - ListOfShape& theCombinedShapes, - ListOfShape& theFreeShapes) + ListOfShape& theResuts) { + + ListOfShape aResCombinedShapes; + ListOfShape aResFreeShapes; + GeomShapePtr aResult = theCompound; if(!theCompound.get()) { @@ -135,34 +230,43 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes( aTA = TopAbs_SOLID; } - theCombinedShapes.clear(); - theFreeShapes.clear(); + // map from the resulting shapes to minimal index of the used shape from theCompound list + std::map anInputOrder; + // map from ancestors-shapes to the index of shapes in theCompound + NCollection_DataMap anAncestorsOrder; // Get free shapes. + int anOrder = 0; const TopoDS_Shape& aShapesComp = theCompound->impl(); - 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) { std::shared_ptr aGeomShape(new GeomAPI_Shape); aGeomShape->setImpl(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); + // 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 aFreeShapes; NCollection_Vector> 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; } @@ -173,40 +277,39 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes( } else { NCollection_List aTempList; NCollection_Map 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::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); + 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(); - } else if(aTempListOfShape.Last() == aTempShape) { - const TopoDS_Shape& aTF = aTempListOfShape.First(); - if(aTempMap.Add(aTF)) { - aTempList.Append(aTF); - aFreeShapes.Remove(aTF); - } - aTempListOfShape.Clear(); } } } @@ -215,12 +318,13 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes( } } - // Combine shapes with common subshapes. + // Combine shapes with common sub-shapes. for(NCollection_Vector>::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& aShapesMap = anIter.ChangeValue(); @@ -230,13 +334,17 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes( 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 aGeomShape(new GeomAPI_Shape); TopoDS_Shape* aSh = theType == GeomAPI_Shape::COMPSOLID ? new TopoDS_Shape(aCSolid) : new TopoDS_Shape(aShell); aGeomShape->setImpl(aSh); - theCombinedShapes.push_back(aGeomShape); + aResCombinedShapes.push_back(aGeomShape); + anInputOrder[aGeomShape] = anOrder; } // Adding free shapes. @@ -245,25 +353,30 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes( if(aFreeShapes.Contains(aShape)) { std::shared_ptr aGeomShape(new GeomAPI_Shape); aGeomShape->setImpl(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()); - } - for(ListOfShape::const_iterator anIter = theFreeShapes.cbegin(); - anIter != theFreeShapes.cend(); anIter++) { - aBuilder.Add(aResultComp, (*anIter)->impl()); + // put to result compound and result list in accordance to the order numbers + std::map::iterator anInputIter = anInputOrder.begin(); + std::map aNums; + for(; anInputIter != anInputOrder.end(); anInputIter++) + aNums[anInputIter->second] = anInputIter->first; + std::map::iterator aNumsIter = aNums.begin(); + for(; aNumsIter != aNums.end(); aNumsIter++) { + aBuilder.Add(aResultComp, (aNumsIter->second)->impl()); + theResuts.push_back(aNumsIter->second); } aResult->setImpl(new TopoDS_Shape(aResultComp)); } @@ -309,7 +422,7 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::groupSharedTopology( { GeomShapePtr aResult = theCompound; - if(!theCompound.get()) { + if (!theCompound.get()) { return aResult; } @@ -317,67 +430,111 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::groupSharedTopology( NCollection_List anUngroupedShapes, aStillUngroupedShapes; addSimpleShapeToList(anInShape, anUngroupedShapes); - NCollection_Vector> aGroups; - while(!anUngroupedShapes.IsEmpty()) { - NCollection_List aGroupedShapes; - aGroupedShapes.Append(anUngroupedShapes.First()); - anUngroupedShapes.RemoveFirst(); - for(NCollection_List::Iterator aGroupIt(aGroupedShapes); - aGroupIt.More(); aGroupIt.Next()) { - const TopoDS_Shape& aGroupedShape = aGroupIt.Value(); - for(TopExp_Explorer aGroupShapeExp(aGroupedShape, TopAbs_VERTEX); - aGroupShapeExp.More(); - aGroupShapeExp.Next()) { - // Find all shapes which have same vertex. - aStillUngroupedShapes.Clear(); - const TopoDS_Shape& aVertex1 = aGroupShapeExp.Current(); - for(NCollection_List::Iterator anUngroupedIt(anUngroupedShapes); - anUngroupedIt.More(); - anUngroupedIt.Next()) { - const TopoDS_Shape& anUngroupedShape = anUngroupedIt.Value(); - bool isAdded = false; - for(TopExp_Explorer anUgroupedShapeExp(anUngroupedShape, TopAbs_VERTEX); - anUgroupedShapeExp.More(); - anUgroupedShapeExp.Next()) { - const TopoDS_Shape& aVertex2 = anUgroupedShapeExp.Current(); - if(aVertex1.IsSame(aVertex2)) { - aGroupedShapes.Append(anUngroupedShape); - isAdded = true; - break; - } - } - if(!isAdded) { - aStillUngroupedShapes.Append(anUngroupedShape); - } + // Iterate over all shapes and find shapes with shared vertices. + TopTools_ListOfShape allVertices; + TopTools_DataMapOfShapeListOfShape aVertexShapesMap; + for (NCollection_List::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 aList; + aList.Append(aShape); + allVertices.Append(aVertex); + aVertexShapesMap.Bind(aVertex, aList); + } + else { + if (!aVertexShapesMap.ChangeFind(aVertex).Contains(aShape)) { + aVertexShapesMap.ChangeFind(aVertex).Append(aShape); } - anUngroupedShapes = aStillUngroupedShapes; - if(anUngroupedShapes.IsEmpty()) { - break; + } + } + } + + // Iterate over the map and group shapes. + NCollection_Vector 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); + } } + // Save key to unbind from this map. + aKeysToUnbind.Append(aKeysIt.Value()); } - if(anUngroupedShapes.IsEmpty()) { - break; + // 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>::Iterator - anIt(aGroups); anIt.More(); anIt.Next()) { - NCollection_List aGroup = anIt.Value(); + ListOfShape aSolids; + for (NCollection_Vector::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::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()); } @@ -389,6 +546,24 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::groupSharedTopology( 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(), (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 > GeomAlgoAPI_ShapeTools::getBoundingBox(const ListOfShape& theShapes, const double theEnlarge) @@ -425,29 +600,6 @@ std::list > return aResultPoints; } -//================================================================================================== -std::shared_ptr - GeomAlgoAPI_ShapeTools::faceToInfinitePlane(const std::shared_ptr theFace) -{ - if (!theFace.get()) - return std::shared_ptr(); - - TopoDS_Face aPlaneFace = TopoDS::Face(theFace->impl()); - if (aPlaneFace.IsNull()) - return std::shared_ptr(); - - Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(aPlaneFace)); - if (aPlane.IsNull()) - return std::shared_ptr(); - - // make an infinity face on the plane - TopoDS_Shape anInfiniteFace = BRepBuilderAPI_MakeFace(aPlane->Pln()).Shape(); - - std::shared_ptr aResult(new GeomAPI_Shape); - aResult->setImpl(new TopoDS_Shape(anInfiniteFace)); - return aResult; -} - //================================================================================================== std::shared_ptr GeomAlgoAPI_ShapeTools::fitPlaneToBox( const std::shared_ptr thePlane, @@ -508,23 +660,26 @@ void GeomAlgoAPI_ShapeTools::findBounds(const std::shared_ptr the std::shared_ptr& theV1, std::shared_ptr& theV2) { - if(!theShape.get()) { - std::shared_ptr 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_Vertex aV1, aV2; - ShapeAnalysis::FindBounds(aShape, aV1, aV2); - - std::shared_ptr 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_Vertex aV1, aV2; + ShapeAnalysis::FindBounds(aShape, aV1, aV2); + + std::shared_ptr aGeomV1(new GeomAPI_Vertex()), aGeomV2(new GeomAPI_Vertex()); + aGeomV1->setImpl(new TopoDS_Vertex(aV1)); + aGeomV2->setImpl(new TopoDS_Vertex(aV2)); + theV1 = aGeomV1; + theV2 = aGeomV2; + } } //================================================================================================== @@ -706,6 +861,41 @@ bool GeomAlgoAPI_ShapeTools::isParallel(const std::shared_ptr theE return anExt.IsParallel() == Standard_True; } +//================================================================================================== +std::list > GeomAlgoAPI_ShapeTools::intersect( + const std::shared_ptr theEdge, const std::shared_ptr theFace, + const bool thePointsOutsideFace) +{ + std::list > aResult; + if(!theEdge.get() || !theFace.get()) { + return aResult; + } + + TopoDS_Edge anEdge = TopoDS::Edge(theEdge->impl()); + double aFirstOnCurve, aLastOnCurve; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirstOnCurve, aLastOnCurve); + + TopoDS_Face aFace = TopoDS::Face(theFace->impl()); + 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( + new GeomAPI_Vertex(anInt.X(), anInt.Y(), anInt.Z()))); + } + return aResult; +} + //================================================================================================== void GeomAlgoAPI_ShapeTools::splitShape(const std::shared_ptr& theBaseShape, const GeomAlgoAPI_ShapeTools::PointToRefsMap& thePointsInfo, @@ -743,7 +933,7 @@ void GeomAlgoAPI_ShapeTools::splitShape(const std::shared_ptr& th } aBOP.Perform(); - if (aBOP.ErrorStatus()) + if (aBOP.HasErrors()) return; // Collect splits @@ -788,7 +978,7 @@ void GeomAlgoAPI_ShapeTools::splitShape_p(const std::shared_ptr& } aBOP.Perform(); - if (aBOP.ErrorStatus()) + if (aBOP.HasErrors()) return; // Collect splits @@ -831,3 +1021,97 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::findShape( return aResultShape; } + +//================================================================================================== +#ifdef FEATURE_MULTIROTATION_TWO_DIRECTIONS +std::shared_ptr GeomAlgoAPI_ShapeTools::buildDirFromAxisAndShape( + const std::shared_ptr theBaseShape, + const std::shared_ptr theAxis) +{ + gp_Pnt aCentreOfMassPoint = + GeomAlgoAPI_ShapeTools::centreOfMass(theBaseShape)->impl(); + Handle(Geom_Line) aLine = new Geom_Line(theAxis->impl()); + GeomAPI_ProjectPointOnCurve aPrjTool(aCentreOfMassPoint, aLine); + gp_Pnt aPoint = aPrjTool.NearestPoint(); + + std::shared_ptr 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 GeomAlgoAPI_ShapeTools::wireToEdge( + const std::shared_ptr& theWire) +{ + GeomEdgePtr anEdge; + if (theWire) { + TopoDS_Wire aWire = theWire->impl(); + // 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