]> SALOME platform Git repositories - modules/shaper.git/blobdiff - src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp
Salome HOME
Add tools
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_Revolution.cpp
index b6e10dbe9b763373c51d1ab3ec003759e07f6939..544ff79b883cd76ae4eca544f12feb8c68811cc4 100644 (file)
@@ -142,14 +142,14 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr<GeomAPI_Shape>& theBasi
 
   // Geting base plane.
   std::shared_ptr<GeomAPI_Face> aBaseFace;
-  if(theBasis->shapeType() == GeomAPI_Shape::SHELL) {
+  if(theBasis->shapeType() == GeomAPI_Shape::FACE) {
+    aBaseFace = std::shared_ptr<GeomAPI_Face>(new GeomAPI_Face(theBasis));
+  } else if(theBasis->shapeType() == GeomAPI_Shape::SHELL) {
     GeomAPI_ShapeExplorer anExp(theBasis, GeomAPI_Shape::FACE);
     if(anExp.more()) {
       std::shared_ptr<GeomAPI_Shape> aFaceOnShell = anExp.current();
       aBaseFace = std::shared_ptr<GeomAPI_Face>(new GeomAPI_Face(aFaceOnShell));
     }
-  } else {
-    aBaseFace = std::shared_ptr<GeomAPI_Face>(new GeomAPI_Face(theBasis));
   }
   if(!aBaseFace.get()) {
     return;
@@ -158,14 +158,21 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr<GeomAPI_Shape>& theBasi
   GeomLib_IsPlanarSurface isBasisPlanar(BRep_Tool::Surface(aBasisFace));
   gp_Pln aBasisPln = isBasisPlanar.Plan();
   Geom_Plane aBasisPlane(aBasisPln);
+  gp_Ax1 anAxis = theAxis->impl<gp_Ax1>();
+  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>();
+  gp_Pnt aStartPnt = aBasisCentre;
   const TopoDS_Shape& aBasisShape = theBasis->impl<TopoDS_Shape>();
-  gp_Ax1 anAxis = theAxis->impl<gp_Ax1>();
-  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,9 +185,6 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr<GeomAPI_Shape>& 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);
-    aCircle = gp_Circ(gp_Ax2(aProjection.NearestPoint(), anAxis.Direction(), gp_Vec(aProjection.NearestPoint(), aFromPnt)),
-                      aRadius);
     BRepBuilderAPI_Transform* aBaseTransform = new BRepBuilderAPI_Transform(aBasisShape,
                                                                             aBaseTrsf,
                                                                             true);
@@ -190,36 +194,63 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr<GeomAPI_Shape>& theBasi
     aListOfMakeShape.push_back(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aBaseTransform)));
     TopoDS_Shape aRotatedBaseShape = aBaseTransform->Shape();
 
-    // 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;
-    }
-    std::shared_ptr<GeomAPI_Shape> aWire(new GeomAPI_Shape);
-    std::shared_ptr<GeomAPI_Shape> aBShape(new GeomAPI_Shape);
-    aWire->setImpl(new TopoDS_Shape(aPipeWire));
-    aBShape->setImpl(new TopoDS_Shape(aRotatedBaseShape));
-    aListOfMakeShape.push_back(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aPipeBuilder, aWire, aBShape)));
-    aResult = aPipeBuilder->Shape();
-    TopoDS_Shape aToShape = aPipeBuilder->LastShape();
-    TopoDS_Shape aFromShape = aPipeBuilder->FirstShape();
+    if(theBasis->shapeType() == GeomAPI_Shape::FACE) {
+      // 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()) {
+        return;
+      }
+      aListOfMakeShape.push_back(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
+      aResult = aRevolBuilder->Shape();
 
-    // Setting naming.
-    TopExp_Explorer anExp(aToShape, TopAbs_FACE);
-    for(; anExp.More(); anExp.Next()) {
-      std::shared_ptr<GeomAPI_Shape> 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()) {
+      // Setting naming.
       std::shared_ptr<GeomAPI_Shape> aFSHape(new GeomAPI_Shape);
-      aFSHape->setImpl(new TopoDS_Shape(anExp.Current()));
+      aFSHape->setImpl(new TopoDS_Shape(aRevolBuilder->FirstShape()));
       myFromFaces.push_back(aFSHape);
+      std::shared_ptr<GeomAPI_Shape> aTSHape(new GeomAPI_Shape);
+      aTSHape->setImpl(new TopoDS_Shape(aRevolBuilder->LastShape()));
+      myToFaces.push_back(aTSHape);
+    } else {
+      gp_Pnt aFromPnt = aStartPnt.Transformed(aBaseTrsf);
+      aCircle = gp_Circ(gp_Ax2(aProjection.NearestPoint(), anAxis.Direction(), gp_Vec(aProjection.NearestPoint(), aFromPnt)),
+                        aRadius);
+
+      // 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;
+      }
+      std::shared_ptr<GeomAPI_Shape> aWire(new GeomAPI_Shape);
+      std::shared_ptr<GeomAPI_Shape> aBShape(new GeomAPI_Shape);
+      aWire->setImpl(new TopoDS_Shape(aPipeWire));
+      aBShape->setImpl(new TopoDS_Shape(aRotatedBaseShape));
+      aListOfMakeShape.push_back(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aPipeBuilder, aWire, aBShape)));
+      aResult = aPipeBuilder->Shape();
+      TopoDS_Shape aToShape = aPipeBuilder->LastShape();
+      TopoDS_Shape aFromShape = aPipeBuilder->FirstShape();
+
+      // Setting naming.
+      TopExp_Explorer anExp(aToShape, TopAbs_FACE);
+      for(; anExp.More(); anExp.Next()) {
+        std::shared_ptr<GeomAPI_Shape> 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<GeomAPI_Shape> 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.
@@ -258,21 +289,29 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr<GeomAPI_Shape>& theBasi
     aFromSolid = aFromTransform.Shape();
     aToSolid = aToTransform.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;
+    // Making revolution to the 360 angle.
+    if(theBasis->shapeType() == GeomAPI_Shape::FACE) {
+      BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aBasisShape, anAxis, 2 * M_PI, Standard_True);
+      aRevolBuilder->Build();
+      aListOfMakeShape.push_back(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
+      aResult = aRevolBuilder->Shape();
+    } else {
+      // 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<GeomAPI_Shape> aWire(new GeomAPI_Shape);
+      std::shared_ptr<GeomAPI_Shape> aBShape(new GeomAPI_Shape);
+      aWire->setImpl(new TopoDS_Shape(aPipeWire));
+      aBShape->setImpl(new TopoDS_Shape(aBasisShape));
+      aListOfMakeShape.push_back(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aPipeBuilder, aWire, aBShape)));
+      aResult = aPipeBuilder->Shape();
     }
-    std::shared_ptr<GeomAPI_Shape> aWire(new GeomAPI_Shape);
-    std::shared_ptr<GeomAPI_Shape> aBShape(new GeomAPI_Shape);
-    aWire->setImpl(new TopoDS_Shape(aPipeWire));
-    aBShape->setImpl(new TopoDS_Shape(aBasisShape));
-    aListOfMakeShape.push_back(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aPipeBuilder, aWire, aBShape)));
-    aResult = aPipeBuilder->Shape();
 
     // Cutting revolution with from plane.
     BRepAlgoAPI_Cut* aFromCutBuilder = new BRepAlgoAPI_Cut(aResult, aFromSolid);
@@ -293,7 +332,7 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr<GeomAPI_Shape>& 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, aBasisCentre);
+    aResult = findClosest(aResult, aBasisCentre);
 
     // Setting naming.
     for(TopExp_Explorer anExp(aResult, TopAbs_FACE); anExp.More (); anExp.Next ()) {
@@ -355,21 +394,29 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr<GeomAPI_Shape>& theBasi
     TopoDS_Shape aRotatedBoundingFace = aBoundingTransform.Modified(aBoundingFace).First();
     aBoundingSolid = aBoundingTransform.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;
+    // Making revolution to the 360 angle.
+    if(theBasis->shapeType() == GeomAPI_Shape::FACE) {
+      BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aBasisShape, anAxis, 2 * M_PI, Standard_True);
+      aRevolBuilder->Build();
+      aListOfMakeShape.push_back(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
+      aResult = aRevolBuilder->Shape();
+    } else {
+      // 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<GeomAPI_Shape> aWire(new GeomAPI_Shape);
+      std::shared_ptr<GeomAPI_Shape> aBShape(new GeomAPI_Shape);
+      aWire->setImpl(new TopoDS_Shape(aPipeWire));
+      aBShape->setImpl(new TopoDS_Shape(aBasisShape));
+      aListOfMakeShape.push_back(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aPipeBuilder, aWire, aBShape)));
+      aResult = aPipeBuilder->Shape();
     }
-    std::shared_ptr<GeomAPI_Shape> aWire(new GeomAPI_Shape);
-    std::shared_ptr<GeomAPI_Shape> aBShape(new GeomAPI_Shape);
-    aWire->setImpl(new TopoDS_Shape(aPipeWire));
-    aBShape->setImpl(new TopoDS_Shape(aBasisShape));
-    aListOfMakeShape.push_back(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aPipeBuilder, aWire, aBShape)));
-    aResult = aPipeBuilder->Shape();
 
     // Cutting revolution with bounding plane.
     BRepAlgoAPI_Cut* aBoundingCutBuilder = new BRepAlgoAPI_Cut(aResult, aBoundingSolid);
@@ -427,7 +474,7 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr<GeomAPI_Shape>& theBasi
     }
 
     // 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 ()) {
@@ -446,6 +493,29 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr<GeomAPI_Shape>& theBasi
   if(!anExp.More()) {
     return;
   }
+  if(aResult.ShapeType() == TopAbs_COMPOUND) {
+    aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
+  }
+  if(aResult.ShapeType() == TopAbs_COMPOUND) {
+    std::shared_ptr<GeomAPI_Shape> 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<TopoDS_Shape>();
+    } 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<TopoDS_Shape>());
+      }
+      for(ListOfShape::const_iterator anIter = aFreeSolids.cbegin(); anIter != aFreeSolids.cend(); anIter++) {
+        aBuilder.Add(aResultComp, (*anIter)->impl<TopoDS_Shape>());
+      }
+      aResult = aResultComp;
+    }
+  }
 
   // fill data map to keep correct orientation of sub-shapes
   myMap = std::shared_ptr<GeomAPI_DataMapOfShapeShape>(new GeomAPI_DataMapOfShapeShape());
@@ -458,7 +528,6 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr<GeomAPI_Shape>& theBasi
   myShape->setImpl(new TopoDS_Shape(aResult));
   myMkShape = std::shared_ptr<GeomAlgoAPI_MakeShapeList>(new GeomAlgoAPI_MakeShapeList(aListOfMakeShape));
   myDone = true;
-  return;
 }
 
 //=================================================================================================