X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGeomAlgoAPI%2FGeomAlgoAPI_ShapeTools.cpp;h=a8df94d7dbd49d0fcbae3da17db9a159078a9fb2;hb=0a9f5debb92e0ca530f21d57be0fe236223a0de6;hp=197569345369b4f7940438fd77cb795223639e05;hpb=5cb371dddedb829bd1a58cc5e61827eaa85ef64e;p=modules%2Fshaper.git diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp index 197569345..a8df94d7d 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp @@ -22,16 +22,18 @@ #include "GeomAlgoAPI_SketchBuilder.h" +#include #include #include #include #include #include +#include #include -#include #include #include +#include #include #include #include @@ -42,14 +44,19 @@ #include #include #include +#include #include +#include #include #include #include #include +#include #include +#include #include #include +#include #include #include #include @@ -64,9 +71,11 @@ #include #include #include +#include #include #include + #include #include #include @@ -83,7 +92,27 @@ double GeomAlgoAPI_ShapeTools::volume(const std::shared_ptr theSh 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 theShape) +{ + GProp_GProps aGProps; + 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; + + BRepGProp::SurfaceProperties(aShape, aGProps, anEps); return aGProps.Mass(); } @@ -106,7 +135,8 @@ std::shared_ptr BRepGProp::LinearProperties(aShape, aGProps); aCentre = aGProps.CentreOfMass(); } else { - BRepGProp::SurfaceProperties(aShape, aGProps); + const Standard_Real anEps = 1.e-6; + BRepGProp::SurfaceProperties(aShape, aGProps, anEps); aCentre = aGProps.CentreOfMass(); } return std::shared_ptr(new GeomAPI_Pnt(aCentre.X(), aCentre.Y(), aCentre.Z())); @@ -151,8 +181,8 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes( } // Map subshapes and shapes. - BOPCol_IndexedDataMapOfShapeListOfShape aMapSA; - BOPTools::MapShapesAndAncestors(aShapesComp, aTS, aTA, aMapSA); + TopTools_IndexedDataMapOfShapeListOfShape aMapSA; + TopExp::MapShapesAndAncestors(aShapesComp, aTS, aTA, aMapSA); if(aMapSA.IsEmpty()) { return aResult; } @@ -160,10 +190,10 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes( // Get all shapes with common subshapes 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; } @@ -174,40 +204,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); - } - 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(); } } } @@ -310,7 +339,7 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::groupSharedTopology( { GeomShapePtr aResult = theCompound; - if(!theCompound.get()) { + if (!theCompound.get()) { return aResult; } @@ -319,23 +348,24 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::groupSharedTopology( addSimpleShapeToList(anInShape, anUngroupedShapes); // Iterate over all shapes and find shapes with shared vertices. - TopTools_ListOfShape aMapOrder; - BOPCol_DataMapOfShapeListOfShape aVertexShapesMap; - for(NCollection_List::Iterator aShapesIt(anUngroupedShapes); - aShapesIt.More(); - aShapesIt.Next()) { + 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()) { + 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); - 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); } } @@ -343,55 +373,56 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::groupSharedTopology( } // Iterate over the map and group shapes. - NCollection_Vector aGroups; - while (!aMapOrder.IsEmpty()) { + 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 = 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 containt 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. + // Sort shapes from the most complicated to the simplest ones TopTools_ListOfShape aSortedGroup; - for(int aST = TopAbs_COMPOUND; aST <= TopAbs_SHAPE; ++aST) { - TopTools_ListOfShape::Iterator anIt(aGroupedShapes); + for (int aST = TopAbs_COMPOUND; aST <= TopAbs_SHAPE; ++aST) { + TopTools_ListOfShape::Iterator anIt(aConnectedShapes); while (anIt.More()) { - if(anIt.Value().ShapeType() == aST) { + if (anIt.Value().ShapeType() == aST) { aSortedGroup.Append(anIt.Value()); - aGroupedShapes.Remove(anIt); - } else { + aConnectedShapes.Remove(anIt); + } + else { anIt.Next(); } } @@ -743,6 +774,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, @@ -780,7 +846,7 @@ void GeomAlgoAPI_ShapeTools::splitShape(const std::shared_ptr& th } aBOP.Perform(); - if (aBOP.ErrorStatus()) + if (aBOP.HasErrors()) return; // Collect splits @@ -825,7 +891,7 @@ void GeomAlgoAPI_ShapeTools::splitShape_p(const std::shared_ptr& } aBOP.Perform(); - if (aBOP.ErrorStatus()) + if (aBOP.HasErrors()) return; // Collect splits @@ -868,3 +934,73 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::findShape( return aResultShape; } + +//================================================================================================== +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; +} + +//================================================================================================== +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; +}