From 915db9619165301046d038f6ee2196c73006a405 Mon Sep 17 00:00:00 2001 From: Clarisse Genrault Date: Mon, 20 Apr 2020 13:20:37 +0200 Subject: [PATCH] Add the new mode to create a root sphere (the following) --- src/GeomAlgoAPI/GeomAlgoAPI_Sphere.cpp | 184 ++++++++++++++++++++++--- 1 file changed, 163 insertions(+), 21 deletions(-) diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Sphere.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Sphere.cpp index d307fe54e..6f4f673e4 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Sphere.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Sphere.cpp @@ -23,26 +23,52 @@ #include +#include + +#include +#include +#include + +#include #include //================================================================================================= GeomAlgoAPI_Sphere::GeomAlgoAPI_Sphere(std::shared_ptr theCenterPoint, const double theRadius) { + isRootGeo = false; myCenterPoint = theCenterPoint; myRadius = theRadius; } +//================================================================================================= +GeomAlgoAPI_Sphere::GeomAlgoAPI_Sphere(const double theRMin, const double theRMax, + const double thePhiMin, const double thePhiMax, + const double theThetaMin, const double theThetaMax) +{ + isRootGeo = true; + myRMin = theRMin; + myRMax = theRMax; + myPhiMin = thePhiMin; + myPhiMax = thePhiMax; + myThetaMin = theThetaMin; + myThetaMax = theThetaMax; +} + //================================================================================================= bool GeomAlgoAPI_Sphere::check() { - if (!myCenterPoint) { - myError = "Sphere builder :: center is not valid."; - return false; - } - if (myRadius < Precision::Confusion()) { - myError = "Sphere builder :: radius is negative or null."; - return false; + if (isRootGeo) { + // traitement a faire plus tard + } else { + if (!myCenterPoint) { + myError = "Sphere builder :: center is not valid."; + return false; + } + if (myRadius < Precision::Confusion()) { + myError = "Sphere builder :: radius is negative or null."; + return false; + } } return true; } @@ -51,30 +77,146 @@ bool GeomAlgoAPI_Sphere::check() void GeomAlgoAPI_Sphere::build() { myCreatedFaces.clear(); + if (isRootGeo) { + buildRootSphere(); + } else { + const gp_Pnt& aCenterPoint = myCenterPoint->impl(); - const gp_Pnt& aCenterPoint = myCenterPoint->impl(); + // Construct the sphere + BRepPrimAPI_MakeSphere *aSphereMaker = new BRepPrimAPI_MakeSphere(aCenterPoint, myRadius); - // Construct the sphere - BRepPrimAPI_MakeSphere *aSphereMaker = new BRepPrimAPI_MakeSphere(aCenterPoint, myRadius); + aSphereMaker->Build(); - aSphereMaker->Build(); + if (!aSphereMaker->IsDone()) { + return; + } - if (!aSphereMaker->IsDone()) { - return; + TopoDS_Shape aResult = aSphereMaker->Shape(); + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aResult)); + setShape(aShape); + + // Test on the shapes + if (!aShape.get() || aShape->isNull()) { + myError = "Sphere builder :: resulting shape is null."; + return; + } + + setImpl(aSphereMaker); + + setDone(true); } +} + +//================================================================================================= +void GeomAlgoAPI_Sphere::buildRootSphere() +{ + myCreatedFaces.clear(); + + const double aStartPhiRad = myPhiMin * M_PI / 180.; + BRepBuilderAPI_MakeWire aWireBuilder; - TopoDS_Shape aResult = aSphereMaker->Shape(); - std::shared_ptr aShape(new GeomAPI_Shape()); - aShape->setImpl(new TopoDS_Shape(aResult)); - setShape(aShape); + gp_Pnt anOrigin(0., 0., 0.); + gp_Dir aNormal(-sin(aStartPhiRad), cos(aStartPhiRad), 0.); - // Test on the shapes - if (!aShape.get() || aShape->isNull()) { - myError = "Sphere builder :: resulting shape is null."; + + //The section is defined by 4 points and up to 4 wires. In the rmin = 0 case, two of the points will actually be the origin + double aX = myRMax*sin(myThetaMin * M_PI/180.); + double aZ = myRMax*cos(myThetaMin * M_PI/180.); + gp_Pnt aTopOuterStart(aX*cos(aStartPhiRad), aX*sin(aStartPhiRad), aZ); + + aX = myRMax*sin((myThetaMin+myThetaMax) * M_PI/180.); + aZ = myRMax*cos((myThetaMin+myThetaMax) * M_PI/180.); + gp_Pnt aBaseOuterEnd(aX*cos(aStartPhiRad), aX*sin(aStartPhiRad), aZ); + + aX = myRMin*sin(myThetaMin * M_PI/180.); + aZ = myRMin*cos(myThetaMin * M_PI/180.); + gp_Pnt aTopInnerStart(aX*cos(aStartPhiRad), aX*sin(aStartPhiRad), aZ); + + aX = myRMin*sin((myThetaMin+myThetaMax) * M_PI/180.); + aZ = myRMin*cos((myThetaMin+myThetaMax) * M_PI/180.); + gp_Pnt aBaseInnerEnd(aX*cos(aStartPhiRad), aX*sin(aStartPhiRad), aZ); + + // There will always be the rmax arc since rmax can't be zero + gp_Circ anOuterCircle(gp_Ax2(anOrigin, aNormal), myRMax); + BRepBuilderAPI_MakeEdge anArcOuterBuilder; + if (aTopOuterStart.IsEqual(aBaseOuterEnd, Precision::Confusion())) + anArcOuterBuilder = BRepBuilderAPI_MakeEdge(anOuterCircle); + else + anArcOuterBuilder = BRepBuilderAPI_MakeEdge(anOuterCircle, aTopOuterStart, aBaseOuterEnd); + anArcOuterBuilder.Build(); + + //Two cases : either we need four edges (one being an arc with curvature radius rmin) or we need three (if rmin=0). + // In the later case the top and bottom edges intersect at the origin + // Add the edges to the wire in consecutive order (very important for the face to make sense topologically) + if(myRMin >= Precision::Confusion()){ + gp_Circ anInnerCircle(gp_Ax2(anOrigin, aNormal), myRMin); + BRepBuilderAPI_MakeEdge anArcInnerBuilder; + if (aTopInnerStart.IsEqual(aBaseInnerEnd, Precision::Confusion())) + anArcInnerBuilder = BRepBuilderAPI_MakeEdge(anInnerCircle); + else + anArcInnerBuilder = BRepBuilderAPI_MakeEdge(anInnerCircle, aTopInnerStart, aBaseInnerEnd); + anArcInnerBuilder.Build(); + + BRepBuilderAPI_MakeEdge anEdgeStartBuilder(aTopInnerStart, aTopOuterStart); + anEdgeStartBuilder.Build(); + BRepBuilderAPI_MakeEdge anEdgeEndBuilder(aBaseInnerEnd, aBaseOuterEnd); + anEdgeEndBuilder.Build(); + + aWireBuilder.Add(anEdgeStartBuilder.Edge()); + aWireBuilder.Add(anArcOuterBuilder.Edge()); + aWireBuilder.Add(anEdgeEndBuilder.Edge()); + aWireBuilder.Add(anArcInnerBuilder.Edge()); + } + else{ + BRepBuilderAPI_MakeEdge anEdgeStartBuilder(anOrigin, aTopOuterStart); + anEdgeStartBuilder.Build(); + BRepBuilderAPI_MakeEdge anEdgeEndBuilder(anOrigin, aBaseOuterEnd); + anEdgeEndBuilder.Build(); + + aWireBuilder.Add(anArcOuterBuilder.Edge()); + aWireBuilder.Add(anEdgeStartBuilder.Edge()); + aWireBuilder.Add(anEdgeEndBuilder.Edge()); + } + + // Make a face from the wire + aWireBuilder.Build(); + BRepBuilderAPI_MakeFace aFaceBuilder(aWireBuilder.Wire()); + aFaceBuilder.Build(); + + if (!aFaceBuilder.IsDone()){ + myError = "GDML sphere builder :: section is not valid"; return; } - setImpl(aSphereMaker); + // Mathematical tool objects needed by the revolution builder + gp_Dir aZDir(0., 0., 1.); + gp_Ax1 aZAxis(anOrigin, aZDir); + + // Build the solid using the section face we've created and a revolution builder + BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aFaceBuilder.Face(), aZAxis, myPhiMax * M_PI / 180., Standard_True); + if(!aRevolBuilder) { + return; + myError = "GDML Sphere builder :: section revolution did not succeed"; + } + if(!aRevolBuilder->IsDone()) { + myError = "GDML Sphere builder :: section revolution did not succeed"; + return; + } + // Get the shape, verify it, build a GeomAPI_Shape. + std::shared_ptr aResultShape = std::shared_ptr(new GeomAPI_Shape()) ; + aResultShape->setImpl(new TopoDS_Shape(aRevolBuilder->Shape())); + setShape(aResultShape); + + // Test on the shapes + if (!(aResultShape).get() || aResultShape->isNull()) { + myError = "GDML Sphere builder :: resulting shape is null."; + return; + } + + setImpl(aRevolBuilder); + setBuilderType(OCCT_BRepBuilderAPI_MakeShape); + setDone(true); } -- 2.39.2