X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGeomAlgoAPI%2FGeomAlgoAPI_ShapeTools.cpp;h=7c0f462e086a033cd980920130a521a79856ba09;hb=f0cec241aae9ca16d86e166f45cb5c4987d2c792;hp=fda821e1f4eb5ee5d578ab6ae6acbdc70d990617;hpb=3a927e455d0639a65e2bf4fd3f1dfe4459fc9608;p=modules%2Fshaper.git diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp index fda821e1f..7c0f462e0 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp @@ -4,38 +4,60 @@ // Created: 3 August 2015 // Author: Dmitry Bobylev -#include +#include "GeomAlgoAPI_ShapeTools.h" -#include +#include "GeomAlgoAPI_SketchBuilder.h" -#include +#include +#include +#include +#include +#include #include #include +#include +#include +#include #include +#include +#include #include +#include +#include +#include #include #include +#include +#include +#include +#include #include #include #include #include +#include #include #include #include #include #include -#include +#include #include +#include #include #include #include #include #include #include +#include +#include +#include +#include -//================================================================================================= +//================================================================================================== double GeomAlgoAPI_ShapeTools::volume(const std::shared_ptr theShape) { GProp_GProps aGProps; @@ -51,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; @@ -75,18 +97,20 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::centreOfMass(const std::sha return std::shared_ptr(new GeomAPI_Pnt(aCentre.X(), aCentre.Y(), aCentre.Z())); } -//================================================================================================= -void GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr theCompound, - const GeomAPI_Shape::ShapeType theType, - ListOfShape& theCombinedShapes, - ListOfShape& theFreeShapes) +//================================================================================================== +std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr theCompound, + const GeomAPI_Shape::ShapeType theType, + ListOfShape& theCombinedShapes, + ListOfShape& theFreeShapes) { + GeomShapePtr aResult = theCompound; + if(!theCompound.get()) { - return; + return aResult; } if(theType != GeomAPI_Shape::SHELL && theType != GeomAPI_Shape::COMPSOLID) { - return; + return aResult; } TopAbs_ShapeEnum aTS = TopAbs_EDGE; @@ -96,6 +120,9 @@ void GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr 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() ) { @@ -111,7 +138,7 @@ void GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr BOPCol_IndexedDataMapOfShapeListOfShape aMapSA; BOPTools::MapShapesAndAncestors(aShapesComp, aTS, aTA, aMapSA); if(aMapSA.IsEmpty()) { - return; + return aResult; } // Get all shapes with common subshapes and free shapes. @@ -199,9 +226,143 @@ void GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr theFreeShapes.push_back(aGeomShape); } } + + if(theCombinedShapes.size() == 1 && theFreeShapes.size() == 0) { + aResult = theCombinedShapes.front(); + } else if(theCombinedShapes.size() == 0 && theFreeShapes.size() == 1) { + aResult = theFreeShapes.front(); + } 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()); + } + aResult->setImpl(new TopoDS_Shape(aResultComp)); + } + + 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. @@ -235,7 +396,7 @@ std::list > GeomAlgoAPI_ShapeTools::getBoundingBox( return aResultPoints; } -//================================================================================================= +//================================================================================================== std::shared_ptr GeomAlgoAPI_ShapeTools::faceToInfinitePlane(const std::shared_ptr theFace) { if (!theFace.get()) @@ -257,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(); @@ -304,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) @@ -333,3 +494,223 @@ void GeomAlgoAPI_ShapeTools::findBounds(const std::shared_ptr the theV1 = aGeomV1; 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())); + TopoDS_Face aFace = aMKFace.Face(); + + BRepAlgo_FaceRestrictor aFRestrictor; + aFRestrictor.Init(aFace, Standard_False, Standard_True); + for(ListOfShape::const_iterator anIt = theWires.cbegin(); + anIt != theWires.cend(); + ++anIt) { + TopoDS_Wire aWire = TopoDS::Wire((*anIt)->impl()); + aFRestrictor.Add(aWire); + } + + aFRestrictor.Perform(); + + if(!aFRestrictor.IsDone()) { + return; + } + + for(; aFRestrictor.More(); aFRestrictor.Next()) { + GeomShapePtr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aFRestrictor.Current())); + theFaces.push_back(aShape); + } +} + +//================================================================================================== +std::shared_ptr GeomAlgoAPI_ShapeTools::findPlane(const ListOfShape& theShapes) +{ + TopoDS_Compound aCompound; + BRep_Builder aBuilder; + aBuilder.MakeCompound(aCompound); + + for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) { + aBuilder.Add(aCompound, (*anIt)->impl()); + } + BRepBuilderAPI_FindPlane aFindPlane(aCompound); + + if(aFindPlane.Found() != Standard_True) { + return std::shared_ptr(); + } + + Handle(Geom_Plane) aPlane = aFindPlane.Plane(); + gp_Pnt aLoc = aPlane->Location(); + gp_Dir aDir = aPlane->Axis().Direction(); + + std::shared_ptr aGeomPnt(new GeomAPI_Pnt(aLoc.X(), aLoc.Y(), aLoc.Z())); + std::shared_ptr aGeomDir(new GeomAPI_Dir(aDir.X(), aDir.Y(), aDir.Z())); + + std::shared_ptr aPln(new GeomAPI_Pln(aGeomPnt, aGeomDir)); + + return aPln; +} + +//================================================================================================== +bool GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(const std::shared_ptr theSubShape, + const std::shared_ptr theBaseShape) +{ + if(!theSubShape.get() || !theBaseShape.get()) { + return false; + } + + const TopoDS_Shape& aSubShape = theSubShape->impl(); + const TopoDS_Shape& aBaseShape = theBaseShape->impl(); + + if(aSubShape.ShapeType() == TopAbs_VERTEX) { + // If sub-shape is a vertex check distance to shape. If it is <= Precision::Confusion() then OK. + BRepExtrema_DistShapeShape aDist(aBaseShape, aSubShape); + aDist.Perform(); + if(!aDist.IsDone() || aDist.Value() > Precision::Confusion()) { + return false; + } + } else if (aSubShape.ShapeType() == TopAbs_EDGE) { + if(aBaseShape.ShapeType() == TopAbs_FACE) { + // Check that edge is on face surface. + TopoDS_Face aFace = TopoDS::Face(aBaseShape); + TopoDS_Edge anEdge = TopoDS::Edge(aSubShape); + BRepLib_CheckCurveOnSurface aCheck(anEdge, aFace); + aCheck.Perform(); + if(!aCheck.IsDone() || aCheck.MaxDistance() > Precision::Confusion()) { + return false; + } + + // Check intersections. + TopoDS_Vertex aV1, aV2; + ShapeAnalysis::FindBounds(anEdge, aV1, aV2); + gp_Pnt aPnt1 = BRep_Tool::Pnt(aV1); + gp_Pnt aPnt2 = BRep_Tool::Pnt(aV2); + for(TopExp_Explorer anExp(aBaseShape, TopAbs_EDGE); anExp.More(); anExp.Next()) { + const TopoDS_Shape& anEdgeOnFace = anExp.Current(); + BRepExtrema_DistShapeShape aDist(anEdgeOnFace, anEdge); + aDist.Perform(); + if(aDist.IsDone() && aDist.Value() <= Precision::Confusion()) { + // Edge intersect face bound. Check that it is not on edge begin or end. + for(Standard_Integer anIndex = 1; anIndex <= aDist.NbSolution(); ++anIndex) { + gp_Pnt aPntOnSubShape = aDist.PointOnShape2(anIndex); + if(aPntOnSubShape.Distance(aPnt1) > Precision::Confusion() + && aPntOnSubShape.Distance(aPnt2) > Precision::Confusion()) { + return false; + } + } + } + } + + // No intersections found. Edge is inside or outside face. Check it. + BRepAdaptor_Curve aCurveAdaptor(anEdge); + gp_Pnt aPointToCheck = aCurveAdaptor.Value((aCurveAdaptor.FirstParameter() + aCurveAdaptor.LastParameter()) / 2.0); + Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace); + ShapeAnalysis_Surface aSAS(aSurface); + gp_Pnt2d aPointOnFace = aSAS.ValueOfUV(aPointToCheck, Precision::Confusion()); + BRepTopAdaptor_FClass2d aFClass2d(aFace, Precision::Confusion()); + if(aFClass2d.Perform(aPointOnFace) == TopAbs_OUT) { + return false; + } + + } else { + return false; + } + } else { + return false; + } + + return true; +} + +//================================================================================================== +bool GeomAlgoAPI_ShapeTools::isShapeValid(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); + } +}