From 1ba7f96679673e8b2aa558b9844461d54ba939b1 Mon Sep 17 00:00:00 2001 From: dbv Date: Tue, 18 Aug 2015 09:44:58 +0300 Subject: [PATCH] Compsolids creation in revolution --- .../FeaturesPlugin_CompositeBoolean.cpp | 7 +- .../FeaturesPlugin_Extrusion.cpp | 17 +- .../FeaturesPlugin_Revolution.cpp | 198 ++++++++------- .../FeaturesPlugin_Revolution.h | 6 +- src/FeaturesPlugin/revolution_widget.xml | 4 - src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.cpp | 26 +- src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.h | 5 +- src/GeomAlgoAPI/GeomAlgoAPI_MakeShapeList.cpp | 1 + src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp | 8 +- src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp | 226 +++++++++++++----- src/GeomAlgoAPI/GeomAlgoAPI_Revolution.h | 16 +- src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp | 4 +- 12 files changed, 324 insertions(+), 194 deletions(-) diff --git a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp index 50343a5ba..f8896999d 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp @@ -236,7 +236,7 @@ void FeaturesPlugin_CompositeBoolean::loadNamingDS(std::shared_ptrmapOfShapes(); theResultBody->loadAndOrientGeneratedShapes(aPrismAlgo->makeShape().get(), *aFaceIter, GeomAPI_Shape::EDGE, aGenTag, aLatName, *aSubShapes.get()); - //TODO:fix + //TODO: fix //aFromFace = aPrismAlgo->firstShape(); //aToFace = aPrismAlgo->lastShape(); } else if(std::dynamic_pointer_cast(*aSolidsAlgosIter)) { @@ -244,8 +244,9 @@ void FeaturesPlugin_CompositeBoolean::loadNamingDS(std::shared_ptrmapOfShapes(); theResultBody->loadAndOrientGeneratedShapes(aRevolAlgo->makeShape().get(), *aFaceIter, GeomAPI_Shape::EDGE, aGenTag, aLatName, *aSubShapes.get()); - aFromFace = aRevolAlgo->firstShape(); - aToFace = aRevolAlgo->lastShape(); + //TODO: fix + //aFromFace = aRevolAlgo->firstShape(); + //aToFace = aRevolAlgo->lastShape(); } /* diff --git a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp index a4436599c..029fd2bdb 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp @@ -131,10 +131,14 @@ void FeaturesPlugin_Extrusion::execute() ListOfShape aShells; ListOfShape aFreeFaces; GeomAlgoAPI_ShapeTools::combineFacesToShells(aFacesList, aShells, aFreeFaces); - aShells.merge(aFreeFaces); + if(aShells.empty()) { + aShells = aFreeFaces; + } else { + aShells.merge(aFreeFaces); + } // Generating result for each shell and face. - int anIndex = 0, aResultIndex = 0; + int aResultIndex = 0; for(ListOfShape::const_iterator anIter = aShells.cbegin(); anIter != aShells.cend(); anIter++) { std::shared_ptr aBaseShape = *anIter; @@ -175,20 +179,17 @@ void FeaturesPlugin_Extrusion::loadNamingDS(GeomAlgoAPI_Prism& thePrismAlgo, std::shared_ptr theBasis) { //load result - if(thePrismAlgo.shape()->shapeType() == GeomAPI_Shape::COMPSOLID) { - int a = 1; - } theResultBody->storeGenerated(theBasis, thePrismAlgo.shape()); std::shared_ptr aSubShapes = thePrismAlgo.mapOfShapes(); //Insert lateral face : Face from Edge - std::string aLatName = "LateralFace"; + const std::string aLatName = "LateralFace"; const int aLatTag = 1; theResultBody->loadAndOrientGeneratedShapes(thePrismAlgo.makeShape().get(), theBasis, GeomAPI_Shape::EDGE, aLatTag, aLatName, *aSubShapes); //Insert to faces - std::string aToName = "ToFace"; + const std::string aToName = "ToFace"; const int aToTag = 2; const ListOfShape& aToFaces = thePrismAlgo.toFaces(); for(ListOfShape::const_iterator anIt = aToFaces.cbegin(); anIt != aToFaces.cend(); anIt++) { @@ -200,7 +201,7 @@ void FeaturesPlugin_Extrusion::loadNamingDS(GeomAlgoAPI_Prism& thePrismAlgo, } //Insert from faces - std::string aFromName = "FromFace"; + const std::string aFromName = "FromFace"; const int aFromTag = 3; const ListOfShape& aFromFaces = thePrismAlgo.fromFaces(); for(ListOfShape::const_iterator anIt = aFromFaces.cbegin(); anIt != aFromFaces.cend(); anIt++) { diff --git a/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp b/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp index 7716583e1..4bbbca96f 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp @@ -15,15 +15,10 @@ #include #include +#include #include #include -#define FACE 4 -#define EDGE 6 -#define _LATERAL_TAG 1 -#define _FROM_TAG 2 -#define _TO_TAG 3 - //================================================================================================= FeaturesPlugin_Revolution::FeaturesPlugin_Revolution() { @@ -58,7 +53,43 @@ void FeaturesPlugin_Revolution::initAttributes() //================================================================================================= void FeaturesPlugin_Revolution::execute() { - AttributeSelectionListPtr aFaceRefs = selectionList(LIST_ID()); + // Getting faces. + ListOfShape aFacesList; + AttributeSelectionListPtr aFacesSelectionList = selectionList(LIST_ID()); + for(int anIndex = 0; anIndex < aFacesSelectionList->size(); anIndex++) { + std::shared_ptr aFaceSel = aFacesSelectionList->value(anIndex); + ResultPtr aContext = aFaceSel->context(); + std::shared_ptr aContextShape = aContext->shape(); + if(!aContextShape.get()) { + static const std::string aContextError = "The selection context is bad"; + setError(aContextError); + break; + } + + std::shared_ptr aFaceShape = aFaceSel->value(); + int aFacesNum = -1; // this mean that "aFace" is used + ResultConstructionPtr aConstruction = + std::dynamic_pointer_cast(aContext); + if(!aFaceShape.get()) { // this may be the whole sketch result selected, check and get faces + if (aConstruction.get()) { + aFacesNum = aConstruction->facesNum(); + } else { + static const std::string aFaceError = "Can not find basis for revolution"; + setError(aFaceError); + break; + } + } + for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) { + std::shared_ptr aBaseShape; + if (aFacesNum == -1) { + aFacesList.push_back(aFaceShape); + break; + } else { + aFaceShape = std::dynamic_pointer_cast(aConstruction->face(aFaceIndex)); + aFacesList.push_back(aFaceShape); + } + } + } //Getting axis. std::shared_ptr anAxis; @@ -106,107 +137,88 @@ void FeaturesPlugin_Revolution::execute() } } - // for each selected face generate a result - int anIndex = 0, aResultIndex = 0; - for(; anIndex < aFaceRefs->size(); anIndex++) { - std::shared_ptr aFaceRef = aFaceRefs->value(anIndex); - ResultPtr aContextRes = aFaceRef->context(); - std::shared_ptr aContext = aContextRes->shape(); - if (!aContext.get()) { - static const std::string aContextError = "The selection context is bad"; - setError(aContextError); + // Searching faces with common edges. + ListOfShape aShells; + ListOfShape aFreeFaces; + GeomAlgoAPI_ShapeTools::combineFacesToShells(aFacesList, aShells, aFreeFaces); + if(aShells.empty()) { + aShells = aFreeFaces; + } else { + aShells.merge(aFreeFaces); + } + + // Generating result for each shell and face. + int aResultIndex = 0; + for(ListOfShape::const_iterator anIter = aShells.cbegin(); anIter != aShells.cend(); anIter++) { + std::shared_ptr aBaseShape = *anIter; + + GeomAlgoAPI_Revolution aRevolAlgo(aBaseShape, anAxis, aToShape, aToAngle, aFromShape, aFromAngle); + if(!aRevolAlgo.isDone()) { + static const std::string aPrismAlgoError = "Revolution algorithm failed"; + setError(aPrismAlgoError); + aResultIndex = 0; break; } - std::shared_ptr aValueFace = aFaceRef->value(); - int aFacesNum = -1; // this mean that "aFace" is used - ResultConstructionPtr aConstruction = - std::dynamic_pointer_cast(aContextRes); - if (!aValueFace.get()) { // this may be the whole sketch result selected, check and get faces - if (aConstruction.get()) { - aFacesNum = aConstruction->facesNum(); - } else { - static const std::string aFaceError = "Can not find basis for extrusion"; - setError(aFaceError); - break; - } + // Check if shape is valid + if(!aRevolAlgo.shape().get() || aRevolAlgo.shape()->isNull()) { + static const std::string aShapeError = "Resulting shape is Null"; + setError(aShapeError); + aResultIndex = 0; + break; } - - for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) { - ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); - std::shared_ptr aBaseShape; - if (aFacesNum == -1) { - aBaseShape = aValueFace; - } else { - aBaseShape = std::dynamic_pointer_cast(aConstruction->face(aFaceIndex)); - } - - GeomAlgoAPI_Revolution aFeature(aBaseShape, anAxis, aToShape, aToAngle, aFromShape, aFromAngle); - if(!aFeature.isDone()) { - static const std::string aFeatureError = "Revolution algorithm failed"; - setError(aFeatureError); - break; - } - - // Check if shape is valid - if(aFeature.shape()->isNull()) { - static const std::string aShapeError = "Resulting shape is Null"; - setError(aShapeError); - break; - } - if(!aFeature.isValid()) { - std::string aFeatureError = "Warning: resulting shape is not valid"; - setError(aFeatureError); - break; - } - //LoadNamingDS - LoadNamingDS(aFeature, aResultBody, aBaseShape, aContext); - - setResult(aResultBody, aResultIndex); - aResultIndex++; - - if (aFacesNum == -1) - break; + if(!aRevolAlgo.isValid()) { + std::string aPrismAlgoError = "Warning: resulting shape is not valid"; + setError(aPrismAlgoError); + aResultIndex = 0; + break; } + + ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); + loadNamingDS(aRevolAlgo, aResultBody, aBaseShape); + setResult(aResultBody, aResultIndex); + aResultIndex++; } - // remove the rest results if there were produced in the previous pass + removeResults(aResultIndex); } //================================================================================================= -void FeaturesPlugin_Revolution::LoadNamingDS(GeomAlgoAPI_Revolution& theFeature, +void FeaturesPlugin_Revolution::loadNamingDS(GeomAlgoAPI_Revolution& theRevolAlgo, std::shared_ptr theResultBody, - std::shared_ptr theBasis, - std::shared_ptr theContext) + std::shared_ptr theBasis) { - if(theBasis->isEqual(theContext)) - theResultBody->store(theFeature.shape()); - else - theResultBody->storeGenerated(theContext, theFeature.shape()); - - std::shared_ptr aSubShapes = theFeature.mapOfShapes(); - - std::string aGeneratedName = "LateralFace"; - theResultBody->loadAndOrientGeneratedShapes(theFeature.makeShape().get(), theBasis, EDGE,_LATERAL_TAG, aGeneratedName, *aSubShapes); - - //Insert from face - std::string aBotName = "FromFace"; - std::shared_ptr aBottomFace = theFeature.firstShape(); - if(!aBottomFace->isNull()) { - if(aSubShapes->isBound(aBottomFace)) { - aBottomFace = aSubShapes->find(aBottomFace); + //load result + theResultBody->storeGenerated(theBasis, theRevolAlgo.shape()); + + std::shared_ptr aSubShapes = theRevolAlgo.mapOfShapes(); + + //Insert lateral face : Face from Edge + const std::string aLatName = "LateralFace"; + const int aLatTag = 1; + theResultBody->loadAndOrientGeneratedShapes(theRevolAlgo.makeShape().get(), theBasis, GeomAPI_Shape::EDGE, aLatTag, aLatName, *aSubShapes); + + //Insert to faces + const std::string aToName = "ToFace"; + const int aToTag = 2; + const ListOfShape& aToFaces = theRevolAlgo.toFaces(); + for(ListOfShape::const_iterator anIt = aToFaces.cbegin(); anIt != aToFaces.cend(); anIt++) { + std::shared_ptr aToFace = *anIt; + if(aSubShapes->isBound(aToFace)) { + aToFace = aSubShapes->find(aToFace); } - theResultBody->generated(aBottomFace, aBotName, _FROM_TAG); + theResultBody->generated(aToFace, aToName, aToTag); } - //Insert to face - std::string aTopName = "ToFace"; - std::shared_ptr aTopFace = theFeature.lastShape(); - if (!aTopFace->isNull()) { - if (aSubShapes->isBound(aTopFace)) { - aTopFace = aSubShapes->find(aTopFace); + //Insert from faces + const std::string aFromName = "FromFace"; + const int aFromTag = 3; + const ListOfShape& aFromFaces = theRevolAlgo.fromFaces(); + for(ListOfShape::const_iterator anIt = aFromFaces.cbegin(); anIt != aFromFaces.cend(); anIt++) { + std::shared_ptr aFromFace = *anIt; + if(aSubShapes->isBound(aFromFace)) { + aFromFace = aSubShapes->find(aFromFace); } - theResultBody->generated(aTopFace, aTopName, _TO_TAG); + theResultBody->generated(aFromFace, aFromName, aFromTag); } - } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Revolution.h b/src/FeaturesPlugin/FeaturesPlugin_Revolution.h index 57150bdf7..44a9b773a 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Revolution.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Revolution.h @@ -113,9 +113,9 @@ class FeaturesPlugin_Revolution : public ModelAPI_Feature private: /// Load Naming data structure of the feature to the document. - void LoadNamingDS(GeomAlgoAPI_Revolution& theFeature, std::shared_ptr theResultBody, - std::shared_ptr theBasis, - std::shared_ptr theContext); + void loadNamingDS(GeomAlgoAPI_Revolution& theRevolAlgo, + std::shared_ptr theResultBody, + std::shared_ptr theBasis); }; #endif diff --git a/src/FeaturesPlugin/revolution_widget.xml b/src/FeaturesPlugin/revolution_widget.xml index 1ce674bf8..a9912994a 100644 --- a/src/FeaturesPlugin/revolution_widget.xml +++ b/src/FeaturesPlugin/revolution_widget.xml @@ -22,7 +22,6 @@ setImpl(new TopoDS_Shape(implPtr()->Shape())); } -GeomAlgoAPI_MakeShape::GeomAlgoAPI_MakeShape(void* theMkShape, const std::shared_ptr theWire) +GeomAlgoAPI_MakeShape::GeomAlgoAPI_MakeShape(void* theMkShape, + const std::shared_ptr theWire, + const std::shared_ptr theBaseShape) : GeomAPI_Interface(theMkShape), myShape(new GeomAPI_Shape()), - myWire(theWire) + myWire(theWire), + myBaseShape(theBaseShape) { myShape->setImpl(new TopoDS_Shape(implPtr()->Shape())); } @@ -53,7 +56,24 @@ void GeomAlgoAPI_MakeShape::generated( if(aPipeBuilder) { TopExp_Explorer aShapeExplorer(myWire->impl(), TopAbs_EDGE); for (; aShapeExplorer.More(); aShapeExplorer.Next ()) { - const TopoDS_Shape& aGeneratedShape = aPipeBuilder->Generated(aShapeExplorer.Current(), theShape->impl()); + const TopoDS_Shape& aSpine = aShapeExplorer.Current(); + const TopoDS_Shape& aProfile = theShape->impl(); + if(aProfile.ShapeType() != TopAbs_EDGE && aProfile.ShapeType() != TopAbs_VERTEX) { + return; + } + const TopoDS_Shape& aBaseShape = myBaseShape->impl(); + TopExp_Explorer anExp(aBaseShape, aProfile.ShapeType()); + Standard_Boolean hasShape = Standard_False; + for(; anExp.More(); anExp.Next()) { + if(anExp.Current().IsSame(aProfile)) { + hasShape = Standard_True; + break; + } + } + if(!hasShape) { + return; + } + const TopoDS_Shape& aGeneratedShape = aPipeBuilder->Generated(aSpine, aProfile); std::shared_ptr aShape(new GeomAPI_Shape()); aShape->setImpl(new TopoDS_Shape(aGeneratedShape)); theHistory.push_back(aShape); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.h b/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.h index f028855ed..efafeceee 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.h @@ -25,7 +25,9 @@ public: GEOMALGOAPI_EXPORT GeomAlgoAPI_MakeShape(void* theBuilder); /// Constructor by the builder and wire. Used for pipe builder. - GEOMALGOAPI_EXPORT GeomAlgoAPI_MakeShape(void* theBuilder, const std::shared_ptr theWire); + GEOMALGOAPI_EXPORT GeomAlgoAPI_MakeShape(void* theBuilder, + const std::shared_ptr theWire, + const std::shared_ptr theBaseShape); /// Returns a shape built by the shape construction algorithm GEOMALGOAPI_EXPORT const std::shared_ptr shape() const; @@ -45,6 +47,7 @@ public: /// The resulting shape std::shared_ptr myShape; std::shared_ptr myWire; + std::shared_ptr myBaseShape; }; typedef std::list > ListOfMakeShape; diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_MakeShapeList.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_MakeShapeList.cpp index b6270b594..7b1bb7be3 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_MakeShapeList.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_MakeShapeList.cpp @@ -86,6 +86,7 @@ void GeomAlgoAPI_MakeShapeList::result(const std::shared_ptr theS std::shared_ptr aShape(new GeomAPI_Shape); aShape->setImpl(new TopoDS_Shape(aShapeIt.Value())); ListOfShape aGeneratedShapes; + const TopoDS_Shape& aSh = aShape->impl(); aMakeShape->generated(aShape, aGeneratedShapes); for(ListOfShape::const_iterator anIt = aGeneratedShapes.cbegin(); anIt != aGeneratedShapes.cend(); anIt++) { aTempShapes.Add((*anIt)->impl()); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp index c084b60a6..b77b08dad 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp @@ -175,8 +175,10 @@ void GeomAlgoAPI_Prism::build(const std::shared_ptr& theBasis, return; } std::shared_ptr aWire(new GeomAPI_Shape); + std::shared_ptr aBShape(new GeomAPI_Shape); aWire->setImpl(new TopoDS_Shape(aPipeWire)); - aListOfMakeShape.push_back(std::make_shared(aPipeBuilder, aWire)); + aBShape->setImpl(new TopoDS_Shape(aBasisShape)); + aListOfMakeShape.push_back(std::shared_ptr(new GeomAlgoAPI_MakeShape(aPipeBuilder, aWire, aBShape))); TopoDS_Shape aResult = aPipeBuilder->Shape(); // Orienting bounding planes. @@ -231,7 +233,7 @@ void GeomAlgoAPI_Prism::build(const std::shared_ptr& theBasis, if(!aToCutBuilder->IsDone()) { return; } - aListOfMakeShape.push_back(std::make_shared(aToCutBuilder)); + aListOfMakeShape.push_back(std::shared_ptr(new GeomAlgoAPI_MakeShape(aToCutBuilder))); const TopTools_ListOfShape& aToShapes = aToCutBuilder->Modified(aToShape); for(TopTools_ListIteratorOfListOfShape anIt(aToShapes); anIt.More(); anIt.Next()) { std::shared_ptr aShape(new GeomAPI_Shape()); @@ -246,7 +248,7 @@ void GeomAlgoAPI_Prism::build(const std::shared_ptr& theBasis, if(!aFromCutBuilder->IsDone()) { return; } - aListOfMakeShape.push_back(std::make_shared(aFromCutBuilder)); + aListOfMakeShape.push_back(std::shared_ptr(new GeomAlgoAPI_MakeShape(aFromCutBuilder))); const TopTools_ListOfShape& aFromShapes = aFromCutBuilder->Modified(aFromShape); for(TopTools_ListIteratorOfListOfShape anIt(aFromShapes); anIt.More(); anIt.Next()) { std::shared_ptr aShape(new GeomAPI_Shape()); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp index 11c8091b0..b6e10dbe9 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp @@ -6,6 +6,8 @@ #include +#include +#include #include #include #include @@ -14,18 +16,26 @@ #include #include #include +#include #include #include +#include #include #include #include +#include +#include +#include +#include #include -#include +#include #include +#include #include #include #include #include +#include //================================================================================================= GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(std::shared_ptr theBasis, @@ -63,14 +73,18 @@ TopoDS_Face GeomAlgoAPI_Revolution::makeFaceFromPlane(gp_Pln& thePlane, const gp } //================================================================================================= -TopoDS_Solid GeomAlgoAPI_Revolution::makeSolidFromFace(const TopoDS_Face& theFace) +TopoDS_Solid GeomAlgoAPI_Revolution::makeSolidFromShape(const TopoDS_Shape& theShape) { TopoDS_Shell aShell; TopoDS_Solid aSolid; BRep_Builder aBoundingBuilder; - aBoundingBuilder.MakeShell(aShell); - aBoundingBuilder.Add(aShell, theFace); + if(theShape.ShapeType() == TopAbs_SHELL) { + aShell = TopoDS::Shell(theShape); + } else { + aBoundingBuilder.MakeShell(aShell); + aBoundingBuilder.Add(aShell, theShape); + } aBoundingBuilder.MakeSolid(aSolid); aBoundingBuilder.Add(aSolid, aShell); @@ -114,49 +128,99 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBasi { if(!theBasis || !theAxis || (((!theFromShape && !theToShape) || (theFromShape && theToShape && theFromShape->isEqual(theToShape))) - && (theFromAngle == 0.0 && theToAngle == 0.0))) { + && (theFromAngle == -theToAngle))) { return; } - TopoDS_Face aBasisFace = TopoDS::Face(theBasis->impl()); - GeomLib_IsPlanarSurface isBasisPlanar(BRep_Tool::Surface(aBasisFace)); - if(!isBasisPlanar.IsPlanar()) {// non-planar shapes is not supported for revolution + // Checking that shell is planar. + TopoDS_Shape aBasis = theBasis->impl(); + // TODO: fix planar checking + //TopExp_Explorer aBasisExp(aBasis, TopAbs_FACE); + //for(; aBasisExp.More(); aBasisExp.Next()) { + // const TopoDS_Shape& aCurSh = aBasisExp.Current(); + //} + + // Geting base plane. + std::shared_ptr aBaseFace; + if(theBasis->shapeType() == GeomAPI_Shape::SHELL) { + GeomAPI_ShapeExplorer anExp(theBasis, GeomAPI_Shape::FACE); + if(anExp.more()) { + std::shared_ptr aFaceOnShell = anExp.current(); + aBaseFace = std::shared_ptr(new GeomAPI_Face(aFaceOnShell)); + } + } else { + aBaseFace = std::shared_ptr(new GeomAPI_Face(theBasis)); + } + if(!aBaseFace.get()) { return; } + TopoDS_Face aBasisFace = TopoDS::Face(aBaseFace->impl()); + GeomLib_IsPlanarSurface isBasisPlanar(BRep_Tool::Surface(aBasisFace)); gp_Pln aBasisPln = isBasisPlanar.Plan(); - gp_Ax1 anAxis = theAxis->impl(); + Geom_Plane aBasisPlane(aBasisPln); - ListOfMakeShape aListOfMakeShape; - myFirst = std::shared_ptr(new GeomAPI_Shape()); - myLast = std::shared_ptr(new GeomAPI_Shape()); + // Creating circle for pipe. + gp_Pnt aBasisCentre = GeomAlgoAPI_ShapeTools::centreOfMass(theBasis)->impl(); + 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(aProjection.NbPoints() != 1) { + return; + } + Standard_Real aRadius = aProjection.Distance(1); + gp_Circ aCircle(gp_Ax2(aProjection.NearestPoint(), anAxis.Direction()), aRadius); TopoDS_Shape aResult; + ListOfMakeShape aListOfMakeShape; if(!theFromShape && !theToShape) { // Case 1: When only angles was set. // Rotating base face with the negative value of "from angle". gp_Trsf aBaseTrsf; aBaseTrsf.SetRotation(anAxis, -theFromAngle / 180.0 * M_PI); - BRepBuilderAPI_Transform* aBaseTransform = new BRepBuilderAPI_Transform(aBasisFace, + gp_Pnt aFromPnt = aBasisCentre.Transformed(aBaseTrsf); + aCircle = gp_Circ(gp_Ax2(aProjection.NearestPoint(), anAxis.Direction(), gp_Vec(aProjection.NearestPoint(), aFromPnt)), + aRadius); + BRepBuilderAPI_Transform* aBaseTransform = new BRepBuilderAPI_Transform(aBasisShape, aBaseTrsf, true); + if(!aBaseTransform || !aBaseTransform->IsDone()) { + return; + } aListOfMakeShape.push_back(std::shared_ptr(new GeomAlgoAPI_MakeShape(aBaseTransform))); TopoDS_Shape aRotatedBaseShape = aBaseTransform->Shape(); - // Making revolution to the angle equal to the sum of "from angle" and "to angle". - double anAngle = theFromAngle + theToAngle; - BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aRotatedBaseShape, - anAxis, - anAngle / 180 * M_PI, - Standard_True); - aRevolBuilder->Build(); - if(!aRevolBuilder->IsDone()) { + // Making wire for pipe. + TopoDS_Edge aPipeEdge = BRepBuilderAPI_MakeEdge(aCircle, 0, (theFromAngle + theToAngle) / 180.0 * M_PI); + TopoDS_Wire aPipeWire = BRepBuilderAPI_MakeWire(aPipeEdge).Wire(); + + // Making pipe. + BRepOffsetAPI_MakePipe* aPipeBuilder = new BRepOffsetAPI_MakePipe(aPipeWire, aRotatedBaseShape); + if(!aPipeBuilder || !aPipeBuilder->IsDone()) { return; } - aListOfMakeShape.push_back(std::shared_ptr(new GeomAlgoAPI_MakeShape(aRevolBuilder))); - aResult = aRevolBuilder->Shape(); + std::shared_ptr aWire(new GeomAPI_Shape); + std::shared_ptr aBShape(new GeomAPI_Shape); + aWire->setImpl(new TopoDS_Shape(aPipeWire)); + aBShape->setImpl(new TopoDS_Shape(aRotatedBaseShape)); + aListOfMakeShape.push_back(std::shared_ptr(new GeomAlgoAPI_MakeShape(aPipeBuilder, aWire, aBShape))); + aResult = aPipeBuilder->Shape(); + TopoDS_Shape aToShape = aPipeBuilder->LastShape(); + TopoDS_Shape aFromShape = aPipeBuilder->FirstShape(); // Setting naming. - myFirst->setImpl(new TopoDS_Shape(aRevolBuilder->FirstShape())); - myLast->setImpl(new TopoDS_Shape(aRevolBuilder->LastShape())); + TopExp_Explorer anExp(aToShape, TopAbs_FACE); + for(; anExp.More(); anExp.Next()) { + std::shared_ptr aTSHape(new GeomAPI_Shape); + aTSHape->setImpl(new TopoDS_Shape(anExp.Current())); + myToFaces.push_back(aTSHape); + } + anExp.Init(aFromShape, TopAbs_FACE); + for(; anExp.More(); anExp.Next()) { + std::shared_ptr aFSHape(new GeomAPI_Shape); + aFSHape->setImpl(new TopoDS_Shape(anExp.Current())); + myFromFaces.push_back(aFSHape); + } } else if(theFromShape && theToShape) { // Case 2: When both bounding planes were set. // Getting bounding faces. TopoDS_Face aFromFace = TopoDS::Face(theFromShape->impl()); @@ -173,13 +237,12 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBasi // Orienting bounding planes properly so that the center of mass of the base face stays // on the result shape after cut. - gp_Pnt aBasisCentr = GeomAlgoAPI_ShapeTools::centreOfMass(theBasis)->impl(); - aFromFace = makeFaceFromPlane(aFromPln, aBasisCentr); - aToFace = makeFaceFromPlane(aToPln, aBasisCentr); + aFromFace = makeFaceFromPlane(aFromPln, aBasisCentre); + aToFace = makeFaceFromPlane(aToPln, aBasisCentre); // Making solids from bounding planes and putting them in compound. - TopoDS_Shape aFromSolid = makeSolidFromFace(aFromFace); - TopoDS_Shape aToSolid = makeSolidFromFace(aToFace); + TopoDS_Shape aFromSolid = makeSolidFromShape(aFromFace); + TopoDS_Shape aToSolid = makeSolidFromShape(aToFace); // Rotating bounding planes to the specified angle. gp_Trsf aFromTrsf; @@ -195,14 +258,24 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBasi aFromSolid = aFromTransform.Shape(); aToSolid = aToTransform.Shape(); - // Making revolution to the 360 angle. - BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aBasisFace, anAxis, 2 * M_PI, Standard_True); - aRevolBuilder->Build(); - aListOfMakeShape.push_back(std::shared_ptr(new GeomAlgoAPI_MakeShape(aRevolBuilder))); - TopoDS_Shape aRevolShape = aRevolBuilder->Shape(); + // Making wire for pipe. + TopoDS_Edge aPipeEdge = BRepBuilderAPI_MakeEdge(aCircle, 0, 2 * M_PI); + TopoDS_Wire aPipeWire = BRepBuilderAPI_MakeWire(aPipeEdge).Wire(); + + // Making pipe. + BRepOffsetAPI_MakePipe* aPipeBuilder = new BRepOffsetAPI_MakePipe(aPipeWire, aBasisShape); + if(!aPipeBuilder || !aPipeBuilder->IsDone()) { + return; + } + std::shared_ptr aWire(new GeomAPI_Shape); + std::shared_ptr aBShape(new GeomAPI_Shape); + aWire->setImpl(new TopoDS_Shape(aPipeWire)); + aBShape->setImpl(new TopoDS_Shape(aBasisShape)); + aListOfMakeShape.push_back(std::shared_ptr(new GeomAlgoAPI_MakeShape(aPipeBuilder, aWire, aBShape))); + aResult = aPipeBuilder->Shape(); // Cutting revolution with from plane. - BRepAlgoAPI_Cut* aFromCutBuilder = new BRepAlgoAPI_Cut(aRevolShape, aFromSolid); + BRepAlgoAPI_Cut* aFromCutBuilder = new BRepAlgoAPI_Cut(aResult, aFromSolid); aFromCutBuilder->Build(); if(!aFromCutBuilder->IsDone()) { return; @@ -220,7 +293,7 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBasi aResult = aToCutBuilder->Shape(); // If after cut we got more than one solids then take closest to the center of mass of the base face. - aResult = findClosest(aResult, aBasisCentr); + //aResult = findClosest(aResult, aBasisCentre); // Setting naming. for(TopExp_Explorer anExp(aResult, TopAbs_FACE); anExp.More (); anExp.Next ()) { @@ -229,10 +302,14 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBasi Handle(Geom_Surface) aFromSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedFromFace)); Handle(Geom_Surface) aToSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedToFace)); if(aFaceSurface == aFromSurface) { - myFirst->setImpl(new TopoDS_Shape(aFaceOnResult)); + std::shared_ptr aFSHape(new GeomAPI_Shape); + aFSHape->setImpl(new TopoDS_Shape(aFaceOnResult)); + myFromFaces.push_back(aFSHape); } if(aFaceSurface == aToSurface) { - myLast->setImpl(new TopoDS_Shape(aFaceOnResult)); + std::shared_ptr aTSHape(new GeomAPI_Shape); + aTSHape->setImpl(new TopoDS_Shape(aFaceOnResult)); + myToFaces.push_back(aTSHape); } } } else { //Case 3: When only one bounding plane was set. @@ -259,7 +336,7 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBasi aBoundingFace = makeFaceFromPlane(aBoundingPln, aBasisCentr); // Making solid from bounding plane. - TopoDS_Shape aBoundingSolid = makeSolidFromFace(aBoundingFace); + TopoDS_Shape aBoundingSolid = makeSolidFromShape(aBoundingFace); // Rotating bounding plane to the specified angle. double aBoundingRotAngle = isFromFaceSet ? theFromAngle : theToAngle; @@ -278,45 +355,59 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBasi TopoDS_Shape aRotatedBoundingFace = aBoundingTransform.Modified(aBoundingFace).First(); aBoundingSolid = aBoundingTransform.Shape(); - // Making revolution to the 360 angle. - BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aBasisFace, anAxis, 2 * M_PI, Standard_True); - aRevolBuilder->Build(); - aListOfMakeShape.push_back(std::shared_ptr(new GeomAlgoAPI_MakeShape(aRevolBuilder))); - TopoDS_Shape aRevolShape = aRevolBuilder->Shape(); + // Making wire for pipe. + TopoDS_Edge aPipeEdge = BRepBuilderAPI_MakeEdge(aCircle, 0, 2 * M_PI); + TopoDS_Wire aPipeWire = BRepBuilderAPI_MakeWire(aPipeEdge).Wire(); + + // Making pipe. + BRepOffsetAPI_MakePipe* aPipeBuilder = new BRepOffsetAPI_MakePipe(aPipeWire, aBasisShape); + if(!aPipeBuilder || !aPipeBuilder->IsDone()) { + return; + } + std::shared_ptr aWire(new GeomAPI_Shape); + std::shared_ptr aBShape(new GeomAPI_Shape); + aWire->setImpl(new TopoDS_Shape(aPipeWire)); + aBShape->setImpl(new TopoDS_Shape(aBasisShape)); + aListOfMakeShape.push_back(std::shared_ptr(new GeomAlgoAPI_MakeShape(aPipeBuilder, aWire, aBShape))); + aResult = aPipeBuilder->Shape(); // Cutting revolution with bounding plane. - BRepAlgoAPI_Cut* aBoundingCutBuilder = new BRepAlgoAPI_Cut(aRevolShape, aBoundingSolid); + BRepAlgoAPI_Cut* aBoundingCutBuilder = new BRepAlgoAPI_Cut(aResult, aBoundingSolid); aBoundingCutBuilder->Build(); if(!aBoundingCutBuilder->IsDone()) { return; } aListOfMakeShape.push_back(std::shared_ptr(new GeomAlgoAPI_MakeShape(aBoundingCutBuilder))); aResult = aBoundingCutBuilder->Shape(); - TopExp_Explorer anExp1(aResult, TopAbs_SOLID); // Setting naming. - if(aBoundingCutBuilder->Modified(aBoundingFace).Extent() > 0) { - std::shared_ptr aPtr = isFromFaceSet ? myFirst : myLast; - aPtr->setImpl(new TopoDS_Shape(aBoundingCutBuilder->Modified(aBoundingFace).First())); + const TopTools_ListOfShape& aBndShapes = aBoundingCutBuilder->Modified(aBoundingFace); + for(TopTools_ListIteratorOfListOfShape anIt(aBndShapes); anIt.More(); anIt.Next()) { + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(anIt.Value())); + isFromFaceSet ? myFromFaces.push_back(aShape) : myToFaces.push_back(aShape); } // Try to cut with base face. If it can not be done then keep result of cut with bounding plane. if(isFromFaceSet) { - aBasisFace.Orientation(TopAbs_REVERSED); + gp_Trsf aMirrorTrsf; + aMirrorTrsf.SetMirror(aBasisPlane.Position().Ax2()); + BRepBuilderAPI_Transform aMirrorTransform(aBasis, aMirrorTrsf, true); + aBasis = aMirrorTransform.Shape(); } // Making solid from basis face. - TopoDS_Shape aBasisSolid = makeSolidFromFace(aBasisFace); + TopoDS_Shape aBasisSolid = makeSolidFromShape(aBasis); // Rotating basis face to the specified angle. gp_Trsf aBasisTrsf; double aBasisRotAngle = isFromFaceSet ? theToAngle : -theFromAngle; aBasisTrsf.SetRotation(anAxis, aBasisRotAngle / 180.0 * M_PI); BRepBuilderAPI_Transform aBasisTransform(aBasisSolid, aBasisTrsf, true); - TopoDS_Shape aRotatedBasisFace = aBasisTransform.Modified(aBasisFace).First(); + TopoDS_Shape aRotatedBasis = aBasisTransform.Modified(aBasis).First(); aBasisSolid = aBasisTransform.Shape(); - // Cutting revolution with basis face. + // Cutting revolution with basis. BRepAlgoAPI_Cut* aBasisCutBuilder = new BRepAlgoAPI_Cut(aResult, aBasisSolid); aBasisCutBuilder->Build(); if(aBasisCutBuilder->IsDone()) { @@ -328,22 +419,25 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBasi } } + const TopTools_ListOfShape& aBsShapes = aBasisCutBuilder->Modified(aBoundingFace); + for(TopTools_ListIteratorOfListOfShape anIt(aBsShapes); anIt.More(); anIt.Next()) { + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(anIt.Value())); + isFromFaceSet ? myToFaces.push_back(aShape) : myFromFaces.push_back(aShape); + } + // If after cut we got more than one solids then take closest to the center of mass of the base face. - aResult = findClosest(aResult, aBasisCentr); + //aResult = findClosest(aResult, aBasisCentr); // Setting naming. for(TopExp_Explorer anExp(aResult, TopAbs_FACE); anExp.More (); anExp.Next ()) { const TopoDS_Shape& aFaceOnResult = anExp.Current(); Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aFaceOnResult)); Handle(Geom_Surface) aBoundingSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedBoundingFace)); - Handle(Geom_Surface) aBasisSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedBasisFace)); if(aFaceSurface == aBoundingSurface) { - std::shared_ptr aPtr = isFromFaceSet ? myFirst : myLast; - aPtr->setImpl(new TopoDS_Shape(aFaceOnResult)); - } - if(aFaceSurface == aBasisSurface) { - std::shared_ptr aPtr = isFromFaceSet ? myLast : myFirst; - aPtr->setImpl(new TopoDS_Shape(aFaceOnResult)); + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aFaceOnResult)); + isFromFaceSet ? myFromFaces.push_back(aShape) : myToFaces.push_back(aShape); } } } @@ -401,15 +495,15 @@ const std::shared_ptr& GeomAlgoAPI_Revolution::shape () const } //================================================================================================= -const std::shared_ptr& GeomAlgoAPI_Revolution::firstShape() +const ListOfShape& GeomAlgoAPI_Revolution::fromFaces() const { - return myFirst; + return myFromFaces; } //================================================================================================= -const std::shared_ptr& GeomAlgoAPI_Revolution::lastShape() +const ListOfShape& GeomAlgoAPI_Revolution::toFaces() const { - return myLast; + return myToFaces; } //================================================================================================= diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.h b/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.h index 8e6a0033c..c3562f75a 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.h @@ -68,11 +68,11 @@ public: /// \return result of the Revolution algorithm. GEOMALGOAPI_EXPORT const std::shared_ptr& shape() const; - /// \return the first shape. - GEOMALGOAPI_EXPORT const std::shared_ptr& firstShape(); + /// \returns the list of from faces. + GEOMALGOAPI_EXPORT const ListOfShape& fromFaces() const; - /// \return the last shape. - GEOMALGOAPI_EXPORT const std::shared_ptr& lastShape(); + /// \return the list of to faces. + GEOMALGOAPI_EXPORT const ListOfShape& toFaces() const; /// \return map of sub-shapes of the result. To be used for History keeping. GEOMALGOAPI_EXPORT std::shared_ptr mapOfShapes() const; @@ -89,8 +89,8 @@ private: */ TopoDS_Face makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint); - /// \return solid created from face. - TopoDS_Solid makeSolidFromFace(const TopoDS_Face& theFace); + /// \return solid created from face or shell. + TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape); /** \brief Selects solid from theShape with closest center of mass to thePoint * \param[in] theShape compound with solids. @@ -111,8 +111,8 @@ private: /// Fields. bool myDone; std::shared_ptr myShape; - std::shared_ptr myFirst; - std::shared_ptr myLast; + ListOfShape myFromFaces; + ListOfShape myToFaces; std::shared_ptr myMap; std::shared_ptr myMkShape; }; diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp index aa5486888..338581782 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp @@ -127,7 +127,7 @@ void GeomAlgoAPI_ShapeTools::combineFacesToShells(const ListOfShape& theFacesLis const TopoDS_Shape& aFace = aShIter.Value(); aBuilder.Add(aShell, aFace); } - std::shared_ptr aGeomShell(std::make_shared()); + std::shared_ptr aGeomShell(new GeomAPI_Shape); aGeomShell->setImpl(new TopoDS_Shape(aShell)); theShells.push_back(aGeomShell); } @@ -135,7 +135,7 @@ void GeomAlgoAPI_ShapeTools::combineFacesToShells(const ListOfShape& theFacesLis // Adding free faces. for(NCollection_Map::Iterator aShIter(aFreeFaces); aShIter.More(); aShIter.Next()) { const TopoDS_Shape& aFace = aShIter.Value(); - std::shared_ptr aGeomFace(std::make_shared()); + std::shared_ptr aGeomFace(new GeomAPI_Shape); aGeomFace->setImpl(new TopoDS_Shape(aFace)); theFreeFaces.push_back(aGeomFace); } -- 2.39.2