From 8fbee802bd4c0e7c7e2a1d23e4b800174373f932 Mon Sep 17 00:00:00 2001 From: dbv Date: Wed, 19 Aug 2015 16:55:43 +0300 Subject: [PATCH] Combine solids in compounds after extrusion/revolution to compsolids --- .../FeaturesPlugin_Extrusion.cpp | 4 +- .../FeaturesPlugin_Revolution.cpp | 4 +- src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp | 26 ++++++- src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp | 39 ++++++++-- src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp | 75 ++++++++++--------- src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h | 12 +-- 6 files changed, 110 insertions(+), 50 deletions(-) diff --git a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp index 029fd2bdb..09e3e3c14 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -130,7 +131,8 @@ void FeaturesPlugin_Extrusion::execute() // Searching faces with common edges. ListOfShape aShells; ListOfShape aFreeFaces; - GeomAlgoAPI_ShapeTools::combineFacesToShells(aFacesList, aShells, aFreeFaces); + std::shared_ptr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aFacesList); + GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aShells, aFreeFaces); if(aShells.empty()) { aShells = aFreeFaces; } else { diff --git a/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp b/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp index 4bbbca96f..52b00ffc1 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -140,7 +141,8 @@ void FeaturesPlugin_Revolution::execute() // Searching faces with common edges. ListOfShape aShells; ListOfShape aFreeFaces; - GeomAlgoAPI_ShapeTools::combineFacesToShells(aFacesList, aShells, aFreeFaces); + std::shared_ptr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aFacesList); + GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aShells, aFreeFaces); if(aShells.empty()) { aShells = aFreeFaces; } else { diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp index b77b08dad..f4c7218af 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp @@ -264,9 +264,26 @@ void GeomAlgoAPI_Prism::build(const std::shared_ptr& theBasis, if(aResult.ShapeType() == TopAbs_COMPOUND) { aResult = GeomAlgoAPI_DFLoader::refineResult(aResult); } - - myShape = std::shared_ptr(new GeomAPI_Shape); - myShape->setImpl(new TopoDS_Shape(aResult)); + if(aResult.ShapeType() == TopAbs_COMPOUND) { + std::shared_ptr aCompound(new GeomAPI_Shape); + aCompound->setImpl(new TopoDS_Shape(aResult)); + ListOfShape aCompSolids, aFreeSolids; + GeomAlgoAPI_ShapeTools::combineShapes(aCompound, GeomAPI_Shape::COMPSOLID, aCompSolids, aFreeSolids); + if(aCompSolids.size() == 1 && aFreeSolids.size() == 0) { + aResult = aCompSolids.front()->impl(); + } else if (aCompSolids.size() > 1 || (aCompSolids.size() >= 1 && aFreeSolids.size() >= 1)) { + TopoDS_Compound aResultComp; + TopoDS_Builder aBuilder; + aBuilder.MakeCompound(aResultComp); + for(ListOfShape::const_iterator anIter = aCompSolids.cbegin(); anIter != aCompSolids.cend(); anIter++) { + aBuilder.Add(aResultComp, (*anIter)->impl()); + } + for(ListOfShape::const_iterator anIter = aFreeSolids.cbegin(); anIter != aFreeSolids.cend(); anIter++) { + aBuilder.Add(aResultComp, (*anIter)->impl()); + } + aResult = aResultComp; + } + } // Fill data map to keep correct orientation of sub-shapes. myMap = std::shared_ptr(new GeomAPI_DataMapOfShapeShape); @@ -275,7 +292,8 @@ void GeomAlgoAPI_Prism::build(const std::shared_ptr& theBasis, aCurrentShape->setImpl(new TopoDS_Shape(Exp.Current())); myMap->bind(aCurrentShape, aCurrentShape); } - + myShape = std::shared_ptr(new GeomAPI_Shape); + myShape->setImpl(new TopoDS_Shape(aResult)); myMkShape = std::shared_ptr(new GeomAlgoAPI_MakeShapeList(aListOfMakeShape)); myDone = true; } diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp index b6e10dbe9..4b29cf0c7 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp @@ -158,14 +158,21 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBasi GeomLib_IsPlanarSurface isBasisPlanar(BRep_Tool::Surface(aBasisFace)); gp_Pln aBasisPln = isBasisPlanar.Plan(); Geom_Plane aBasisPlane(aBasisPln); + gp_Ax1 anAxis = theAxis->impl(); + if(aBasisPlane.Axis().Angle(anAxis) < Precision::Confusion()) { + return; + } + gp_Lin anAxisLin(anAxis); // Creating circle for pipe. gp_Pnt aBasisCentre = GeomAlgoAPI_ShapeTools::centreOfMass(theBasis)->impl(); + gp_Pnt aStartPnt = aBasisCentre; const TopoDS_Shape& aBasisShape = theBasis->impl(); - gp_Ax1 anAxis = theAxis->impl(); - gp_Lin anAxisLin(anAxis); Handle(Geom_Line) anAxisLine = new Geom_Line(anAxis); - GeomAPI_ProjectPointOnCurve aProjection(aBasisCentre, anAxisLine); + if(anAxisLin.Contains(aStartPnt, Precision::Confusion())) { + aStartPnt.Translate(anAxis.Direction() ^ aBasisPln.Axis().Direction()); + } + GeomAPI_ProjectPointOnCurve aProjection(aStartPnt, anAxisLine); if(aProjection.NbPoints() != 1) { return; } @@ -178,7 +185,7 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBasi // Rotating base face with the negative value of "from angle". gp_Trsf aBaseTrsf; aBaseTrsf.SetRotation(anAxis, -theFromAngle / 180.0 * M_PI); - gp_Pnt aFromPnt = aBasisCentre.Transformed(aBaseTrsf); + gp_Pnt aFromPnt = aStartPnt.Transformed(aBaseTrsf); aCircle = gp_Circ(gp_Ax2(aProjection.NearestPoint(), anAxis.Direction(), gp_Vec(aProjection.NearestPoint(), aFromPnt)), aRadius); BRepBuilderAPI_Transform* aBaseTransform = new BRepBuilderAPI_Transform(aBasisShape, @@ -446,6 +453,29 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBasi if(!anExp.More()) { return; } + if(aResult.ShapeType() == TopAbs_COMPOUND) { + aResult = GeomAlgoAPI_DFLoader::refineResult(aResult); + } + if(aResult.ShapeType() == TopAbs_COMPOUND) { + std::shared_ptr aCompound(new GeomAPI_Shape); + aCompound->setImpl(new TopoDS_Shape(aResult)); + ListOfShape aCompSolids, aFreeSolids; + GeomAlgoAPI_ShapeTools::combineShapes(aCompound, GeomAPI_Shape::COMPSOLID, aCompSolids, aFreeSolids); + if(aCompSolids.size() == 1 && aFreeSolids.size() == 0) { + aResult = aCompSolids.front()->impl(); + } else if (aCompSolids.size() > 1 || (aCompSolids.size() >= 1 && aFreeSolids.size() >= 1)) { + TopoDS_Compound aResultComp; + TopoDS_Builder aBuilder; + aBuilder.MakeCompound(aResultComp); + for(ListOfShape::const_iterator anIter = aCompSolids.cbegin(); anIter != aCompSolids.cend(); anIter++) { + aBuilder.Add(aResultComp, (*anIter)->impl()); + } + for(ListOfShape::const_iterator anIter = aFreeSolids.cbegin(); anIter != aFreeSolids.cend(); anIter++) { + aBuilder.Add(aResultComp, (*anIter)->impl()); + } + aResult = aResultComp; + } + } // fill data map to keep correct orientation of sub-shapes myMap = std::shared_ptr(new GeomAPI_DataMapOfShapeShape()); @@ -458,7 +488,6 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBasi myShape->setImpl(new TopoDS_Shape(aResult)); myMkShape = std::shared_ptr(new GeomAlgoAPI_MakeShapeList(aListOfMakeShape)); myDone = true; - return; } //================================================================================================= diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp index 338581782..6955720e2 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp @@ -50,31 +50,37 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::centreOfMass(std::shared_pt } //================================================================================================= -void GeomAlgoAPI_ShapeTools::combineFacesToShells(const ListOfShape& theFacesList, - ListOfShape& theShells, - ListOfShape& theFreeFaces) +void GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr theCompound, + const GeomAPI_Shape::ShapeType theType, + ListOfShape& theCombinedShapes, + ListOfShape& theFreeShapes) { - if(theFacesList.empty()) { + if(!theCompound.get()) { return; } - // Adding all faces to compoud. - std::shared_ptr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(theFacesList); - if(!aFacesCompound.get()) { + if(theType != GeomAPI_Shape::SHELL && theType != GeomAPI_Shape::COMPSOLID) { return; } - // Map edges and faces. - const TopoDS_Shape& aFacesComp = aFacesCompound->impl(); + TopAbs_ShapeEnum aTS = TopAbs_EDGE; + TopAbs_ShapeEnum aTA = TopAbs_FACE; + if(theType == GeomAPI_Shape::COMPSOLID) { + aTS = TopAbs_FACE; + aTA = TopAbs_SOLID; + } + + // Map subshapes and shapes. + const TopoDS_Shape& aShapesComp = theCompound->impl(); BOPCol_IndexedDataMapOfShapeListOfShape aMapEF; - BOPTools::MapShapesAndAncestors(aFacesComp, TopAbs_EDGE, TopAbs_FACE, aMapEF); + BOPTools::MapShapesAndAncestors(aShapesComp, aTS, aTA, aMapEF); if(aMapEF.IsEmpty()) { return; } - // Get all faces with common edges and free faces. - NCollection_Map aFreeFaces; - NCollection_Vector> aFacesWithCommonEdges; + // Get all shapes with common subshapes and free shapes. + NCollection_Map aFreeShapes; + NCollection_Vector> aShapesWithCommonSubshapes; for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator anIter(aMapEF); anIter.More(); anIter.Next()) { const TopoDS_Shape& aShape = anIter.Key(); BOPCol_ListOfShape& aListOfShape = anIter.ChangeValue(); @@ -82,14 +88,14 @@ void GeomAlgoAPI_ShapeTools::combineFacesToShells(const ListOfShape& theFacesLis continue; } else if(aListOfShape.Size() == 1) { - aFreeFaces.Add(aListOfShape.First()); + aFreeShapes.Add(aListOfShape.First()); aListOfShape.Clear(); } else { NCollection_Map aTempMap; aTempMap.Add(aListOfShape.First()); aTempMap.Add(aListOfShape.Last()); - aFreeFaces.Remove(aListOfShape.First()); - aFreeFaces.Remove(aListOfShape.Last()); + aFreeShapes.Remove(aListOfShape.First()); + aFreeShapes.Remove(aListOfShape.Last()); aListOfShape.Clear(); for(NCollection_Map::Iterator aTempIter(aTempMap); aTempIter.More(); aTempIter.Next()) { const TopoDS_Shape& aTempShape = aTempIter.Value(); @@ -102,41 +108,42 @@ void GeomAlgoAPI_ShapeTools::combineFacesToShells(const ListOfShape& theFacesLis } else if(aTempListOfShape.Size() > 1) { if(aTempListOfShape.First() == aTempShape) { aTempMap.Add(aTempListOfShape.Last()); - aFreeFaces.Remove(aTempListOfShape.Last()); + aFreeShapes.Remove(aTempListOfShape.Last()); aTempListOfShape.Clear(); } else if(aTempListOfShape.Last() == aTempShape) { aTempMap.Add(aTempListOfShape.First()); - aFreeFaces.Remove(aTempListOfShape.First()); + aFreeShapes.Remove(aTempListOfShape.First()); aTempListOfShape.Clear(); } } } } - aFacesWithCommonEdges.Append(aTempMap); + aShapesWithCommonSubshapes.Append(aTempMap); } } - // Make shells from faces with common edges. - NCollection_Vector aShells; - for(NCollection_Vector>::Iterator anIter(aFacesWithCommonEdges); anIter.More(); anIter.Next()) { + // Combine shapes with common subshapes. + for(NCollection_Vector>::Iterator anIter(aShapesWithCommonSubshapes); anIter.More(); anIter.Next()) { TopoDS_Shell aShell; + TopoDS_CompSolid aCSolid; TopoDS_Builder aBuilder; - aBuilder.MakeShell(aShell); + theType == GeomAPI_Shape::COMPSOLID ? aBuilder.MakeCompSolid(aCSolid) : aBuilder.MakeShell(aShell); const NCollection_Map& aShapesMap = anIter.Value(); for(NCollection_Map::Iterator aShIter(aShapesMap); aShIter.More(); aShIter.Next()) { - const TopoDS_Shape& aFace = aShIter.Value(); - aBuilder.Add(aShell, aFace); + const TopoDS_Shape& aShape = aShIter.Value(); + theType == GeomAPI_Shape::COMPSOLID ? aBuilder.Add(aCSolid, aShape) : aBuilder.Add(aShell, aShape); } - std::shared_ptr aGeomShell(new GeomAPI_Shape); - aGeomShell->setImpl(new TopoDS_Shape(aShell)); - theShells.push_back(aGeomShell); + 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); } - // Adding free faces. - for(NCollection_Map::Iterator aShIter(aFreeFaces); aShIter.More(); aShIter.Next()) { - const TopoDS_Shape& aFace = aShIter.Value(); - std::shared_ptr aGeomFace(new GeomAPI_Shape); - aGeomFace->setImpl(new TopoDS_Shape(aFace)); - theFreeFaces.push_back(aGeomFace); + // Adding free shapes. + for(NCollection_Map::Iterator aShIter(aFreeShapes); aShIter.More(); aShIter.Next()) { + const TopoDS_Shape& aShape = aShIter.Value(); + std::shared_ptr aGeomShape(new GeomAPI_Shape); + aGeomShape->setImpl(new TopoDS_Shape(aShape)); + theFreeShapes.push_back(aGeomShape); } } diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h index 9dce03c2d..009828dc7 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h @@ -27,14 +27,16 @@ public: /// are expressed in the absolute Cartesian coordinate system. (This function works only for surfaces). static std::shared_ptr centreOfMass(std::shared_ptr theShape); - /** \brief Combines faces with common edges to shells - * \param[in] theFacesList list of faces to be combined. + /** \brief Combines faces with common edges to shells, or solids to compsolids. + * \param[in] theCompound compound of shapes. + * \param[in] theType type of combine. * \param[out] theShells resulting shells. * \param[out] theFreeFaces faces that does not have common edges. */ - static void combineFacesToShells(const ListOfShape& theFacesList, - ListOfShape& theShells, - ListOfShape& theFreeFaces); + static void combineShapes(const std::shared_ptr theCompound, + const GeomAPI_Shape::ShapeType theType, + ListOfShape& theCombinedShapes, + ListOfShape& theFreeShapes); }; #endif -- 2.39.2