Salome HOME
Issue #1383 Preview button: correction for the case: switch off auto_preview in extru...
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_ShapeTools.cpp
index 3a4f577ac27be670f7974e4f6a8d88c477b5c35f..fda821e1f4eb5ee5d578ab6ae6acbdc70d990617 100644 (file)
 
 #include <gp_Pln.hxx>
 
+#include <Bnd_Box.hxx>
 #include <BOPTools.hxx>
+#include <BRepBndLib.hxx>
 #include <BRepBuilderAPI_MakeFace.hxx>
 #include <BRepGProp.hxx>
 #include <BRepTools.hxx>
 #include <BRep_Tool.hxx>
 #include <Geom_Plane.hxx>
+#include <GeomLib_IsPlanarSurface.hxx>
+#include <GeomLib_Tool.hxx>
 #include <GProp_GProps.hxx>
+#include <IntAna_IntConicQuad.hxx>
+#include <IntAna_Quadric.hxx>
 #include <NCollection_Vector.hxx>
+#include <ShapeAnalysis.hxx>
 #include <TCollection_AsciiString.hxx>
 #include <TopoDS_Builder.hxx>
 #include <TopoDS_Face.hxx>
 #include <TopoDS_Shape.hxx>
 #include <TopoDS_Shell.hxx>
+#include <TopoDS_Vertex.hxx>
 #include <TopoDS.hxx>
 #include <TopExp_Explorer.hxx>
 
 
 //=================================================================================================
-double GeomAlgoAPI_ShapeTools::volume(std::shared_ptr<GeomAPI_Shape> theShape)
+double GeomAlgoAPI_ShapeTools::volume(const std::shared_ptr<GeomAPI_Shape> theShape)
 {
   GProp_GProps aGProps;
-  if(!theShape) {
+  if(!theShape.get()) {
     return 0.0;
   }
   const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
   if(aShape.IsNull()) {
     return 0.0;
   }
-  BRepGProp::VolumeProperties(aShape, aGProps);
+  const Standard_Real anEps = 1.e-6;
+  BRepGProp::VolumeProperties(aShape, aGProps, anEps);
   return aGProps.Mass();
 }
 
 //=================================================================================================
-std::shared_ptr<GeomAPI_Pnt> GeomAlgoAPI_ShapeTools::centreOfMass(std::shared_ptr<GeomAPI_Shape> theShape)
+std::shared_ptr<GeomAPI_Pnt> GeomAlgoAPI_ShapeTools::centreOfMass(const std::shared_ptr<GeomAPI_Shape> theShape)
 {
   GProp_GProps aGProps;
   if(!theShape) {
@@ -53,8 +62,16 @@ std::shared_ptr<GeomAPI_Pnt> GeomAlgoAPI_ShapeTools::centreOfMass(std::shared_pt
   if(aShape.IsNull()) {
     return std::shared_ptr<GeomAPI_Pnt>();
   }
-  BRepGProp::SurfaceProperties(aShape, aGProps);
-  gp_Pnt aCentre = aGProps.CentreOfMass();
+  gp_Pnt aCentre;
+  if(aShape.ShapeType() == TopAbs_VERTEX) {
+    aCentre = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
+  } else if(aShape.ShapeType() == TopAbs_EDGE || aShape.ShapeType() == TopAbs_WIRE) {
+    BRepGProp::LinearProperties(aShape, aGProps);
+    aCentre = aGProps.CentreOfMass();
+  } else {
+    BRepGProp::SurfaceProperties(aShape, aGProps);
+    aCentre = aGProps.CentreOfMass();
+  }
   return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aCentre.X(), aCentre.Y(), aCentre.Z()));
 }
 
@@ -79,18 +96,28 @@ void GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr<GeomAPI_Shape>
     aTA = TopAbs_SOLID;
   }
 
-  // Map subshapes and shapes.
+  // Get free shapes.
   const TopoDS_Shape& aShapesComp = theCompound->impl<TopoDS_Shape>();
-  BOPCol_IndexedDataMapOfShapeListOfShape aMapEF;
-  BOPTools::MapShapesAndAncestors(aShapesComp, aTS, aTA, aMapEF);
-  if(aMapEF.IsEmpty()) {
+  for(TopoDS_Iterator anIter(aShapesComp); anIter.More(); anIter.Next() ) {
+    const TopoDS_Shape& aShape = anIter.Value();
+    if(aShape.ShapeType() > aTA) {
+      std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
+      aGeomShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aShape));
+      theFreeShapes.push_back(aGeomShape);
+    }
+  }
+
+  // Map subshapes and shapes.
+  BOPCol_IndexedDataMapOfShapeListOfShape aMapSA;
+  BOPTools::MapShapesAndAncestors(aShapesComp, aTS, aTA, aMapSA);
+  if(aMapSA.IsEmpty()) {
     return;
   }
 
   // Get all shapes with common subshapes and free shapes.
   NCollection_Map<TopoDS_Shape> aFreeShapes;
   NCollection_Vector<NCollection_Map<TopoDS_Shape>> aShapesWithCommonSubshapes;
-  for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator anIter(aMapEF); anIter.More(); anIter.Next()) {
+  for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator anIter(aMapSA); anIter.More(); anIter.Next()) {
     const TopoDS_Shape& aShape = anIter.Key();
     BOPCol_ListOfShape& aListOfShape = anIter.ChangeValue();
     if(aListOfShape.IsEmpty()) {
@@ -114,7 +141,7 @@ void GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr<GeomAPI_Shape>
       aListOfShape.Clear();
       for(NCollection_List<TopoDS_Shape>::Iterator aTempIter(aTempList); aTempIter.More(); aTempIter.Next()) {
         const TopoDS_Shape& aTempShape = aTempIter.Value();
-        for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator anIter(aMapEF); anIter.More(); anIter.Next()) {
+        for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator anIter(aMapSA); anIter.More(); anIter.Next()) {
           BOPCol_ListOfShape& aTempListOfShape = anIter.ChangeValue();
           if(aTempListOfShape.IsEmpty()) {
             continue;
@@ -175,7 +202,41 @@ void GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr<GeomAPI_Shape>
 }
 
 //=================================================================================================
-std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::faceToInfinitePlane(const std::shared_ptr<GeomAPI_Shape>& theFace)
+std::list<std::shared_ptr<GeomAPI_Pnt> > GeomAlgoAPI_ShapeTools::getBoundingBox(const ListOfShape& theShapes, const double theEnlarge)
+{
+  // Bounding box of all objects.
+  Bnd_Box aBndBox;
+
+  // Getting box.
+  for (ListOfShape::const_iterator anObjectsIt = theShapes.begin(); anObjectsIt != theShapes.end(); anObjectsIt++) {
+    const TopoDS_Shape& aShape = (*anObjectsIt)->impl<TopoDS_Shape>();
+    BRepBndLib::Add(aShape, aBndBox);
+  }
+
+  if(theEnlarge != 0.0) {
+    // We enlarge bounding box just to be sure that plane will be large enough to cut all objects.
+    aBndBox.Enlarge(theEnlarge);
+  }
+
+  Standard_Real aXArr[2] = {aBndBox.CornerMin().X(), aBndBox.CornerMax().X()};
+  Standard_Real aYArr[2] = {aBndBox.CornerMin().Y(), aBndBox.CornerMax().Y()};
+  Standard_Real aZArr[2] = {aBndBox.CornerMin().Z(), aBndBox.CornerMax().Z()};
+  std::list<std::shared_ptr<GeomAPI_Pnt> > aResultPoints;
+  int aNum = 0;
+  for(int i = 0; i < 2; i++) {
+    for(int j = 0; j < 2; j++) {
+      for(int k = 0; k < 2; k++) {
+        std::shared_ptr<GeomAPI_Pnt> aPnt(new GeomAPI_Pnt(aXArr[i], aYArr[j], aZArr[k]));
+        aResultPoints.push_back(aPnt);
+      }
+    }
+  }
+
+  return aResultPoints;
+}
+
+//=================================================================================================
+std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::faceToInfinitePlane(const std::shared_ptr<GeomAPI_Shape> theFace)
 {
   if (!theFace.get())
     return std::shared_ptr<GeomAPI_Shape>();
@@ -195,3 +256,80 @@ std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::faceToInfinitePlane(const
   aResult->setImpl(new TopoDS_Shape(anInfiniteFace));
   return aResult;
 }
+
+//=================================================================================================
+std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::fitPlaneToBox(const std::shared_ptr<GeomAPI_Shape> thePlane,
+                                                                     const std::list<std::shared_ptr<GeomAPI_Pnt> >& thePoints)
+{
+  std::shared_ptr<GeomAPI_Shape> aResultShape;
+
+  if(!thePlane.get()) {
+    return aResultShape;
+  }
+
+  const TopoDS_Shape& aShape = thePlane->impl<TopoDS_Shape>();
+  if(aShape.ShapeType() != TopAbs_FACE) {
+    return aResultShape;
+  }
+
+  TopoDS_Face aFace = TopoDS::Face(aShape);
+  Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
+  if(aSurf.IsNull()) {
+    return aResultShape;
+  }
+
+  GeomLib_IsPlanarSurface isPlanar(aSurf);
+  if(!isPlanar.IsPlanar()) {
+    return aResultShape;
+  }
+
+  if(thePoints.size() != 8) {
+    return aResultShape;
+  }
+
+  const gp_Pln& aFacePln = isPlanar.Plan();
+  Handle(Geom_Plane) aFacePlane = new Geom_Plane(aFacePln);
+  IntAna_Quadric aQuadric(aFacePln);
+  Standard_Real UMin, UMax, VMin, VMax;
+  UMin = UMax = VMin = VMax = 0;
+  for (std::list<std::shared_ptr<GeomAPI_Pnt> >::const_iterator aPointsIt = thePoints.begin(); aPointsIt != thePoints.end(); aPointsIt++) {
+    const gp_Pnt& aPnt = (*aPointsIt)->impl<gp_Pnt>();
+    gp_Lin aLin(aPnt, aFacePln.Axis().Direction());
+    IntAna_IntConicQuad anIntAna(aLin, aQuadric);
+    const gp_Pnt& aPntOnFace = anIntAna.Point(1);
+    Standard_Real aPntU(0), aPntV(0);
+    GeomLib_Tool::Parameters(aFacePlane, aPntOnFace, Precision::Confusion(), aPntU, aPntV);
+    if(aPntU < UMin) UMin = aPntU;
+    if(aPntU > UMax) UMax = aPntU;
+    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()));
+
+  return aResultShape;
+}
+
+//=================================================================================================
+void GeomAlgoAPI_ShapeTools::findBounds(const std::shared_ptr<GeomAPI_Shape> theShape,
+                                        std::shared_ptr<GeomAPI_Vertex>& theV1,
+                                        std::shared_ptr<GeomAPI_Vertex>& theV2)
+{
+  if(!theShape.get()) {
+    std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex);
+    aVertex->setImpl(new TopoDS_Vertex());
+    theV1 = aVertex;
+    theV2 = aVertex;
+    return;
+  }
+
+  const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
+  TopoDS_Vertex aV1, aV2;
+  ShapeAnalysis::FindBounds(aShape, aV1, aV2);
+
+  std::shared_ptr<GeomAPI_Vertex> aGeomV1(new GeomAPI_Vertex()), aGeomV2(new GeomAPI_Vertex());
+  aGeomV1->setImpl(new TopoDS_Vertex(aV1));
+  aGeomV2->setImpl(new TopoDS_Vertex(aV2));
+  theV1 = aGeomV1;
+  theV2 = aGeomV2;
+}