X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGeomAlgoAPI%2FGeomAlgoAPI_ShapeTools.cpp;h=7c0f462e086a033cd980920130a521a79856ba09;hb=f0cec241aae9ca16d86e166f45cb5c4987d2c792;hp=87e6d83c210e11c32c19f7afe222ecc0534f5bd3;hpb=5f2dd854a118fb9dffec8658d1d234e6587c539f;p=modules%2Fshaper.git diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp index 87e6d83c2..7c0f462e0 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp @@ -8,8 +8,9 @@ #include "GeomAlgoAPI_SketchBuilder.h" +#include #include -#include +#include #include #include @@ -22,17 +23,19 @@ #include #include #include +#include #include +#include #include +#include #include -#include #include +#include #include #include #include #include #include -#include #include #include #include @@ -48,8 +51,13 @@ #include #include #include +#include -//================================================================================================= +#include +#include +#include + +//================================================================================================== double GeomAlgoAPI_ShapeTools::volume(const std::shared_ptr theShape) { GProp_GProps aGProps; @@ -65,7 +73,7 @@ double GeomAlgoAPI_ShapeTools::volume(const std::shared_ptr theSh return aGProps.Mass(); } -//================================================================================================= +//================================================================================================== std::shared_ptr GeomAlgoAPI_ShapeTools::centreOfMass(const std::shared_ptr theShape) { GProp_GProps aGProps; @@ -89,7 +97,7 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::centreOfMass(const std::sha return std::shared_ptr(new GeomAPI_Pnt(aCentre.X(), aCentre.Y(), aCentre.Z())); } -//================================================================================================= +//================================================================================================== std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr theCompound, const GeomAPI_Shape::ShapeType theType, ListOfShape& theCombinedShapes, @@ -112,6 +120,9 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes(const std:: aTA = TopAbs_SOLID; } + theCombinedShapes.clear(); + theFreeShapes.clear(); + // Get free shapes. const TopoDS_Shape& aShapesComp = theCompound->impl(); for(TopoDS_Iterator anIter(aShapesComp); anIter.More(); anIter.Next() ) { @@ -218,7 +229,9 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes(const std:: if(theCombinedShapes.size() == 1 && theFreeShapes.size() == 0) { aResult = theCombinedShapes.front(); - } else if (theCombinedShapes.size() > 1 || (theCombinedShapes.size() >= 1 && theFreeShapes.size() >= 1)) { + } else if(theCombinedShapes.size() == 0 && theFreeShapes.size() == 1) { + aResult = theFreeShapes.front(); + } else { TopoDS_Compound aResultComp; TopoDS_Builder aBuilder; aBuilder.MakeCompound(aResultComp); @@ -234,7 +247,122 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes(const std:: return aResult; } -//================================================================================================= +//================================================================================================== +static void addSimpleShapeToList(const TopoDS_Shape& theShape, NCollection_List& theList) +{ + if(theShape.IsNull()) { + return; + } + + if(theShape.ShapeType() == TopAbs_COMPOUND) { + for(TopoDS_Iterator anIt(theShape); anIt.More(); anIt.Next()) { + addSimpleShapeToList(anIt.Value(), theList); + } + } else { + theList.Append(theShape); + } +} + +//================================================================================================== +static TopoDS_Compound makeCompound(const NCollection_List theShapes) +{ + TopoDS_Compound aCompound; + + BRep_Builder aBuilder; + aBuilder.MakeCompound(aCompound); + + for(NCollection_List::Iterator anIt(theShapes); anIt.More(); anIt.Next()) { + aBuilder.Add(aCompound, anIt.Value()); + } + + return aCompound; +} + +//================================================================================================== +std::shared_ptr GeomAlgoAPI_ShapeTools::groupSharedTopology(const std::shared_ptr theCompound) +{ + GeomShapePtr aResult = theCompound; + + if(!theCompound.get()) { + return aResult; + } + + TopoDS_Shape anInShape = aResult->impl(); + NCollection_List anUngroupedShapes; + 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& aGroupShape = aGroupIt.Value(); + for(NCollection_List::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; + } + } + if(!anUngroupedIt.More()) { + break; + } + } + } + aGroups.Append(aGroupedShapes); + } + + if(aGroups.Size() == 1) { + NCollection_List aGroup = aGroups.First(); + GeomShapePtr aGeomShape(new GeomAPI_Shape()); + aGeomShape->setImpl(new TopoDS_Shape(makeCompound(aGroup))); + ListOfShape aCompSolids, aFreeSolids; + aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape, + GeomAPI_Shape::COMPSOLID, + aCompSolids, + aFreeSolids); + aResult = aGeomShape; + } else { + 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(); + GeomShapePtr aGeomShape(new GeomAPI_Shape()); + if(aGroup.Size() == 1) { + aGeomShape->setImpl(new TopoDS_Shape(aGroup.First())); + } else { + aGeomShape->setImpl(new TopoDS_Shape(makeCompound(aGroup))); + aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape, + GeomAPI_Shape::COMPSOLID, + aCompSolids, + aFreeSolids); + } + aBuilder.Add(aCompound, aGeomShape->impl()); + } + + if(!aCompound.IsNull()) { + aResult->setImpl(new TopoDS_Shape(aCompound)); + } + } + + return aResult; +} + +//================================================================================================== std::list > GeomAlgoAPI_ShapeTools::getBoundingBox(const ListOfShape& theShapes, const double theEnlarge) { // Bounding box of all objects. @@ -268,7 +396,7 @@ std::list > GeomAlgoAPI_ShapeTools::getBoundingBox( return aResultPoints; } -//================================================================================================= +//================================================================================================== std::shared_ptr GeomAlgoAPI_ShapeTools::faceToInfinitePlane(const std::shared_ptr theFace) { if (!theFace.get()) @@ -290,34 +418,34 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::faceToInfinitePlane(const return aResult; } -//================================================================================================= -std::shared_ptr GeomAlgoAPI_ShapeTools::fitPlaneToBox(const std::shared_ptr thePlane, - const std::list >& thePoints) +//================================================================================================== +std::shared_ptr GeomAlgoAPI_ShapeTools::fitPlaneToBox(const std::shared_ptr thePlane, + const std::list >& thePoints) { - std::shared_ptr aResultShape; + std::shared_ptr aResultFace; if(!thePlane.get()) { - return aResultShape; + return aResultFace; } const TopoDS_Shape& aShape = thePlane->impl(); if(aShape.ShapeType() != TopAbs_FACE) { - return aResultShape; + return aResultFace; } TopoDS_Face aFace = TopoDS::Face(aShape); Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); if(aSurf.IsNull()) { - return aResultShape; + return aResultFace; } GeomLib_IsPlanarSurface isPlanar(aSurf); if(!isPlanar.IsPlanar()) { - return aResultShape; + return aResultFace; } if(thePoints.size() != 8) { - return aResultShape; + return aResultFace; } const gp_Pln& aFacePln = isPlanar.Plan(); @@ -337,13 +465,13 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::fitPlaneToBox(const std:: if(aPntV < VMin) VMin = aPntV; if(aPntV > VMax) VMax = aPntV; } - aResultShape.reset(new GeomAPI_Shape); - aResultShape->setImpl(new TopoDS_Shape(BRepLib_MakeFace(aFacePln, UMin, UMax, VMin, VMax).Face())); + aResultFace.reset(new GeomAPI_Face()); + aResultFace->setImpl(new TopoDS_Face(BRepLib_MakeFace(aFacePln, UMin, UMax, VMin, VMax).Face())); - return aResultShape; + return aResultFace; } -//================================================================================================= +//================================================================================================== void GeomAlgoAPI_ShapeTools::findBounds(const std::shared_ptr theShape, std::shared_ptr& theV1, std::shared_ptr& theV2) @@ -367,14 +495,14 @@ void GeomAlgoAPI_ShapeTools::findBounds(const std::shared_ptr the theV2 = aGeomV2; } -//================================================================================================= +//================================================================================================== void GeomAlgoAPI_ShapeTools::makeFacesWithHoles(const std::shared_ptr theOrigin, const std::shared_ptr theDirection, const ListOfShape& theWires, ListOfShape& theFaces) { BRepBuilderAPI_MakeFace aMKFace(gp_Pln(theOrigin->impl(), - theDirection->impl())); + theDirection->impl())); TopoDS_Face aFace = aMKFace.Face(); BRepAlgo_FaceRestrictor aFRestrictor; @@ -399,7 +527,7 @@ void GeomAlgoAPI_ShapeTools::makeFacesWithHoles(const std::shared_ptr GeomAlgoAPI_ShapeTools::findPlane(const ListOfShape& theShapes) { TopoDS_Compound aCompound; @@ -427,9 +555,9 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::findPlane(const ListOfShape return aPln; } -//================================================================================================= -bool GeomAlgoAPI_ShapeTools::isSubShapeInShape(const std::shared_ptr theSubShape, - const std::shared_ptr theBaseShape) +//================================================================================================== +bool GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(const std::shared_ptr theSubShape, + const std::shared_ptr theBaseShape) { if(!theSubShape.get() || !theBaseShape.get()) { return false; @@ -497,3 +625,92 @@ bool GeomAlgoAPI_ShapeTools::isSubShapeInShape(const std::shared_ptr theShape) +{ + if(!theShape.get()) { + return false; + } + + BRepCheck_Analyzer aChecker(theShape->impl()); + return (aChecker.IsValid() == Standard_True); +} + +//================================================================================================== +std::shared_ptr GeomAlgoAPI_ShapeTools::getFaceOuterWire(const std::shared_ptr theFace) +{ + GeomShapePtr anOuterWire; + + if(!theFace.get() || !theFace->isFace()) { + return anOuterWire; + } + + TopoDS_Face aFace = TopoDS::Face(theFace->impl()); + TopoDS_Wire aWire = BRepTools::OuterWire(aFace); + + anOuterWire.reset(new GeomAPI_Shape()); + anOuterWire->setImpl(new TopoDS_Shape(aWire)); + + return anOuterWire; +} + +//================================================================================================== +bool GeomAlgoAPI_ShapeTools::isParallel(const std::shared_ptr theEdge, + const std::shared_ptr theFace) +{ + if(!theEdge.get() || !theFace.get()) { + return false; + } + + TopoDS_Edge anEdge = TopoDS::Edge(theEdge->impl()); + TopoDS_Face aFace = TopoDS::Face(theFace->impl()); + + BRepExtrema_ExtCF anExt(anEdge, aFace); + return anExt.IsParallel() == Standard_True; +} + +//================================================================================================== +void GeomAlgoAPI_ShapeTools::splitShape(const std::shared_ptr& theBaseShape, + const std::set >& thePoints, + std::set >& theShapes) +{ + // General Fuse to split edge by vertices + BOPAlgo_Builder aBOP; + TopoDS_Edge aBaseEdge = theBaseShape->impl(); + // 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::set >::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::set >::const_iterator aPtIt = thePoints.begin(); + for (; aPtIt != thePoints.end(); ++aPtIt) { + std::shared_ptr aPnt = *aPtIt; + TopoDS_Vertex aV = BRepBuilderAPI_MakeVertex(gp_Pnt(aPnt->x(), aPnt->y(), aPnt->z())); + aBOP.AddArgument(aV); + } + + aBOP.Perform(); + if (aBOP.ErrorStatus()) + return; + + // Collect splits + const TopTools_ListOfShape& aSplits = aBOP.Modified(aBaseEdge); + TopTools_ListIteratorOfListOfShape anIt(aSplits); + for (; anIt.More(); anIt.Next()) { + std::shared_ptr anEdge(new GeomAPI_Shape); + anEdge->setImpl(new TopoDS_Shape(anIt.Value())); + theShapes.insert(anEdge); + } +}