Salome HOME
Merge branch 'occ/shaper2smesh'
[modules/shaper.git] / src / GeomAPI / GeomAPI_Shape.cpp
index fc736ac749e379a753d92ebd081d988d59d5430b..78a10ac3c5ffb0bb6940a29828e1a07dca6c034d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 //
 // You should have received a copy of the GNU Lesser General Public
 // License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-// See http://www.salome-platform.org/ or
-// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
 #include "GeomAPI_Shape.h"
 
+#include <GeomAPI_Pnt.h>
 #include <GeomAPI_Vertex.h>
 #include <GeomAPI_Edge.h>
 #include <GeomAPI_Wire.h>
 #include <GeomAPI_Face.h>
 #include <GeomAPI_Shell.h>
 #include <GeomAPI_Solid.h>
+#include <GeomAPI_Trsf.h>
 
 #include <BRep_Tool.hxx>
 #include <BRepAlgoAPI_Section.hxx>
 #include <BRepBndLib.hxx>
 #include <BRepBuilderAPI_FindPlane.hxx>
+#include <BRepBuilderAPI_Copy.hxx>
 #include <BRepExtrema_DistShapeShape.hxx>
 #include <BRepTools.hxx>
 #include <Bnd_Box.hxx>
@@ -50,6 +52,9 @@
 #include <TopoDS_Shape.hxx>
 #include <NCollection_List.hxx>
 
+#include <BOPAlgo_CheckerSI.hxx>
+#include <BOPDS_DS.hxx>
+
 #include <sstream>
 #include <algorithm> // for std::transform
 
@@ -98,6 +103,15 @@ bool GeomAPI_Shape::isSame(const std::shared_ptr<GeomAPI_Shape> theShape) const
   return MY_SHAPE->IsSame(theShape->impl<TopoDS_Shape>()) == Standard_True;
 }
 
+bool GeomAPI_Shape::isSameGeometry(const std::shared_ptr<GeomAPI_Shape> theShape) const
+{
+  if (isFace())
+    return face()->isSameGeometry(theShape);
+  else if (isEdge())
+    return edge()->isSameGeometry(theShape);
+  return false;
+}
+
 bool GeomAPI_Shape::isVertex() const
 {
   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
@@ -148,6 +162,7 @@ bool GeomAPI_Shape::isCompoundOfSolids() const
   return isAtLeastOne;
 }
 
+// LCOV_EXCL_START
 GeomAPI_Shape::ShapeType GeomAPI_Shape::typeOfCompoundShapes() const
 {
   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
@@ -164,6 +179,7 @@ GeomAPI_Shape::ShapeType GeomAPI_Shape::typeOfCompoundShapes() const
   }
   return (GeomAPI_Shape::ShapeType) aType;
 }
+// LCOV_EXCL_STOP
 
 // adds the nopt-compound elements recursively to the list
 static void addSimpleToList(const TopoDS_Shape& theShape, NCollection_List<TopoDS_Shape>& theList)
@@ -385,12 +401,29 @@ GeomAPI_Shape::subShapes(ShapeType theSubShapeType) const
   if (aShape.IsNull())
     return aSubs;
 
-  for (TopExp_Explorer anExp(aShape, (TopAbs_ShapeEnum)theSubShapeType);
-       anExp.More(); anExp.Next()) {
+  // process multi-level compounds
+  if (shapeType() == COMPOUND && theSubShapeType == COMPOUND) {
+    for (TopoDS_Iterator anIt(aShape); anIt.More(); anIt.Next()) {
+      const TopoDS_Shape& aCurrent = anIt.Value();
+      if (aCurrent.ShapeType() == TopAbs_COMPOUND) {
+        GeomShapePtr aSub(new GeomAPI_Shape);
+        aSub->setImpl(new TopoDS_Shape(aCurrent));
+        aSubs.push_back(aSub);
+      }
+    }
+    // add self
     GeomShapePtr aSub(new GeomAPI_Shape);
-    aSub->setImpl(new TopoDS_Shape(anExp.Current()));
+    aSub->setImpl(new TopoDS_Shape(aShape));
     aSubs.push_back(aSub);
   }
+  else {
+    for (TopExp_Explorer anExp(aShape, (TopAbs_ShapeEnum)theSubShapeType);
+         anExp.More(); anExp.Next()) {
+      GeomShapePtr aSub(new GeomAPI_Shape);
+      aSub->setImpl(new TopoDS_Shape(anExp.Current()));
+      aSubs.push_back(aSub);
+    }
+  }
   return aSubs;
 }
 
@@ -438,21 +471,21 @@ GeomAPI_Shape::ShapeType GeomAPI_Shape::shapeType() const
 GeomAPI_Shape::ShapeType GeomAPI_Shape::shapeTypeByStr(std::string theType)
 {
   std::transform(theType.begin(), theType.end(), theType.begin(), ::toupper);
-  if (theType == "COMPOUND")
+  if (theType == "COMPOUND" || theType == "COMPOUNDS")
     return COMPOUND;
-  if (theType == "COMPSOLID")
+  if (theType == "COMPSOLID" || theType == "COMPSOLIDS")
     return COMPSOLID;
-  if (theType == "SOLID")
+  if (theType == "SOLID" || theType == "SOLIDS")
     return SOLID;
-  if (theType == "SHELL")
+  if (theType == "SHELL" || theType == "SHELLS")
     return SHELL;
-  if (theType == "FACE")
+  if (theType == "FACE" || theType == "FACES")
     return FACE;
-  if (theType == "WIRE")
+  if (theType == "WIRE" || theType == "WIRES")
     return WIRE;
-  if (theType == "EDGE")
+  if (theType == "EDGE" || theType == "EDGES")
     return EDGE;
-  if (theType == "VERTEX")
+  if (theType == "VERTEX" || theType == "VERTICES")
     return VERTEX;
   return SHAPE; // default
 }
@@ -563,18 +596,63 @@ bool GeomAPI_Shape::computeSize(double& theXmin, double& theYmin, double& theZmi
   if (aShape.IsNull())
     return false;
   Bnd_Box aBndBox;
-  BRepBndLib::Add(aShape, aBndBox);
+  BRepBndLib::Add(aShape, aBndBox, false);
+  if (aBndBox.IsVoid())
+    return false;
   aBndBox.Get(theXmin, theYmin, theZmin, theXmax, theYmax, theZmax);
   return true;
 }
 
-std::string GeomAPI_Shape::getShapeStream() const
+GeomPointPtr GeomAPI_Shape::middlePoint() const
+{
+  GeomPointPtr aMiddlePoint;
+
+  switch (shapeType()) {
+  case VERTEX:
+    aMiddlePoint = vertex()->point();
+    break;
+  case EDGE:
+    aMiddlePoint = edge()->middlePoint();
+    break;
+  case WIRE:
+    aMiddlePoint = wire()->middlePoint();
+    break;
+  case FACE:
+    aMiddlePoint = face()->middlePoint();
+    break;
+  case SHELL:
+    aMiddlePoint = shell()->middlePoint();
+    break;
+  case SOLID:
+    aMiddlePoint = solid()->middlePoint();
+    break;
+  default: {
+      // get middle point as center of the bounding box
+      double aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ;
+      computeSize(aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ);
+      aMiddlePoint = GeomPointPtr(new GeomAPI_Pnt(
+          (aMinX + aMaxX) * 0.5, (aMinY + aMaxY) * 0.5, (aMinZ + aMaxZ) * 0.5));
+    }
+  }
+
+  return aMiddlePoint;
+}
+
+// LCOV_EXCL_START
+std::string GeomAPI_Shape::getShapeStream(const bool theWithTriangulation) const
 {
   std::ostringstream aStream;
   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
-  BRepTools::Write(aShape, aStream);
+  if (!theWithTriangulation) { // make a copy of shape without triangulation
+    BRepBuilderAPI_Copy aCopy(aShape, Standard_False, Standard_False);
+    const TopoDS_Shape& aCopyShape = aCopy.Shape();
+    BRepTools::Write(aCopyShape, aStream);
+  } else {
+    BRepTools::Write(aShape, aStream);
+  }
   return aStream.str();
 }
+// LCOV_EXCL_STOP
 
 GeomShapePtr GeomAPI_Shape::intersect(const GeomShapePtr theShape) const
 {
@@ -628,3 +706,73 @@ void GeomAPI_Shape::translate(const std::shared_ptr<GeomAPI_Dir> theDir, const d
   TopoDS_Shape aResult = MY_SHAPE->Moved(aTranslation);
   setImpl(new TopoDS_Shape(aResult));
 }
+
+void GeomAPI_Shape::move(const std::shared_ptr<GeomAPI_Trsf> theTransformation)
+{
+  TopoDS_Shape aResult = MY_SHAPE->Moved(theTransformation->impl<gp_Trsf>());
+  setImpl(new TopoDS_Shape(aResult));
+}
+
+bool GeomAPI_Shape::isSelfIntersected(const int theLevelOfCheck) const
+{
+  BOPAlgo_CheckerSI aCSI;  // checker of self-interferences
+  aCSI.SetLevelOfCheck(theLevelOfCheck);
+  TopTools_ListOfShape aList;
+  const TopoDS_Shape& aThisShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
+  aList.Append(aThisShape);
+  aCSI.SetArguments(aList);
+  aCSI.Perform();
+  if (aCSI.HasErrors() || aCSI.DS().Interferences().Extent() > 0) {
+    return true;
+  }
+
+  return false;
+}
+
+bool GeomAPI_Shape::Comparator::operator()(const std::shared_ptr<GeomAPI_Shape>& theShape1,
+                                           const std::shared_ptr<GeomAPI_Shape>& theShape2) const
+{
+  const TopoDS_Shape& aShape1 = theShape1->impl<TopoDS_Shape>();
+  const TopoDS_Shape& aShape2 = theShape2->impl<TopoDS_Shape>();
+  bool isLess = aShape1.TShape() < aShape2.TShape();
+  if (aShape1.TShape() == aShape2.TShape()) {
+    Standard_Integer aHash1 = aShape1.Location().HashCode(IntegerLast());
+    Standard_Integer aHash2 = aShape2.Location().HashCode(IntegerLast());
+    isLess = aHash1 < aHash2;
+  }
+  return isLess;
+}
+
+bool GeomAPI_Shape::ComparatorWithOri::operator()(
+    const std::shared_ptr<GeomAPI_Shape>& theShape1,
+    const std::shared_ptr<GeomAPI_Shape>& theShape2) const
+{
+  const TopoDS_Shape& aShape1 = theShape1->impl<TopoDS_Shape>();
+  const TopoDS_Shape& aShape2 = theShape2->impl<TopoDS_Shape>();
+  bool isLess = aShape1.TShape() < aShape2.TShape();
+  if (aShape1.TShape() == aShape2.TShape()) {
+    Standard_Integer aHash1 = aShape1.Location().HashCode(IntegerLast());
+    Standard_Integer aHash2 = aShape2.Location().HashCode(IntegerLast());
+    isLess = (aHash1 < aHash2) ||
+             (aHash1 == aHash2 && aShape1.Orientation() < aShape2.Orientation());
+  }
+  return isLess;
+}
+
+int GeomAPI_Shape::Hash::operator()(const std::shared_ptr<GeomAPI_Shape>& theShape) const
+{
+  const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
+  return aShape.HashCode(IntegerLast());
+}
+
+bool GeomAPI_Shape::Equal::operator()(const std::shared_ptr<GeomAPI_Shape>& theShape1,
+                                      const std::shared_ptr<GeomAPI_Shape>& theShape2) const
+{
+  const TopoDS_Shape& aShape1 = theShape1->impl<TopoDS_Shape>();
+  const TopoDS_Shape& aShape2 = theShape2->impl<TopoDS_Shape>();
+
+  Standard_Integer aHash1 = aShape1.Location().HashCode(IntegerLast());
+  Standard_Integer aHash2 = aShape2.Location().HashCode(IntegerLast());
+
+  return aShape1.TShape() == aShape2.TShape() && aHash1 == aHash2;
+}