Salome HOME
Issue #19058: Error in sketch projection when changing parameter
authorArtem Zhidkov <Artem.Zhidkov@opencascade.com>
Wed, 13 May 2020 16:04:04 +0000 (19:04 +0300)
committerArtem Zhidkov <Artem.Zhidkov@opencascade.com>
Thu, 14 May 2020 07:57:41 +0000 (10:57 +0300)
Fix crash on Linux, when loading HDF then changing parameter

src/GeomAlgoAPI/GeomAlgoAPI_NExplode.cpp
src/GeomAlgoAPI/GeomAlgoAPI_NExplode.h
src/Selector/CMakeLists.txt
src/Selector/Selector_NExplode.cpp
src/Selector/Selector_NExplode.h

index 58333bf27337c38533a54f8ca5c7118caf073c73..c36623ad01a057495a42789bd24784790a1da3e2 100644 (file)
 
 #include "GeomAlgoAPI_NExplode.h"
 
-#include <TopoDS_Shape.hxx>
+#include <GeomAPI_Pnt.h>
+#include <GeomAPI_ShapeExplorer.h>
+
+#include <Bnd_Box.hxx>
 #include <BRep_Tool.hxx>
-#include <TopoDS.hxx>
-#include <GProp_GProps.hxx>
+#include <BRepBndLib.hxx>
 #include <BRepGProp.hxx>
-#include <NCollection_DataMap.hxx>
+#include <GProp_GProps.hxx>
 #include <Precision.hxx>
-#include <Bnd_Box.hxx>
-#include <BRepBndLib.hxx>
-#include <TopExp_Explorer.hxx>
-#include <TopTools_MapOfShape.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Shape.hxx>
 
-#include <vector>
 #include <algorithm>
+#include <set>
+#include <unordered_map>
 
-static std::pair<double, double> ShapeToDouble (const TopoDS_Shape& S)
+namespace NExplodeTools
 {
-  // Computing of CentreOfMass
-  gp_Pnt GPoint;
-  double Len;
+  void dummy(gp_Pnt&)
+  {
+    // do nothing (new approach to order shapes)
+  }
 
-  if (S.ShapeType() == TopAbs_VERTEX) {
-    GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S));
-    Len = (double)S.Orientation();
+  void pointToDouble(gp_Pnt& thePoint)
+  {
+    // old approach to order shapes
+    double dMidXYZ = thePoint.X() * 999.0 + thePoint.Y() * 99.0 + thePoint.Z() * 0.9;
+    thePoint.SetCoord(dMidXYZ, 0.0, 0.0);
   }
-  else {
-    GProp_GProps GPr;
-    if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
-      BRepGProp::LinearProperties(S, GPr);
-    }
-    else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
-      BRepGProp::SurfaceProperties(S, GPr);
+
+  std::pair<GeomPointPtr, double> ShapeToDouble(const GeomShapePtr& theShape,
+                                                void(*convertPoint)(gp_Pnt&))
+  {
+    // Computing of CentreOfMass
+    gp_Pnt GPoint;
+    double Len;
+
+    TopoDS_Shape S = theShape->impl<TopoDS_Shape>();
+    if (S.ShapeType() == TopAbs_VERTEX) {
+      GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S));
+      Len = (double)S.Orientation();
     }
     else {
-      BRepGProp::VolumeProperties(S, GPr);
+      GProp_GProps GPr;
+      if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
+        BRepGProp::LinearProperties(S, GPr);
+      }
+      else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
+        BRepGProp::SurfaceProperties(S, GPr);
+      }
+      else {
+        BRepGProp::VolumeProperties(S, GPr);
+      }
+      GPoint = GPr.CentreOfMass();
+      Len = GPr.Mass();
     }
-    GPoint = GPr.CentreOfMass();
-    Len = GPr.Mass();
-  }
 
-  double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9;
-  return std::make_pair(dMidXYZ, Len);
-}
+    (*convertPoint)(GPoint);
+    GeomPointPtr aMidPoint(new GeomAPI_Pnt(GPoint.X(), GPoint.Y(), GPoint.Z()));
+    return std::make_pair(aMidPoint, Len);
+  }
 
-/*!
-* \brief Sort shapes in the list by their coordinates.
-*/
-struct CompareShapes : public std::binary_function<TopoDS_Shape, TopoDS_Shape, bool>
-{
-  typedef NCollection_DataMap<TopoDS_Shape, std::pair<double, double> > DataMapOfShapeDouble;
+  /*!
+  * \brief Sort shapes in the list by their coordinates.
+  */
+  struct CompareShapes : public std::binary_function<TopoDS_Shape, TopoDS_Shape, bool>
+  {
+    typedef std::unordered_map<GeomShapePtr,
+                               std::pair<GeomPointPtr, double>,
+                               GeomAPI_Shape::Hash,
+                               GeomAPI_Shape::Equal > DataMapOfShapeDouble;
 
-  CompareShapes(DataMapOfShapeDouble* theCashMap) : myMap(theCashMap) {}
+    CompareShapes(void(*convertPoint)(gp_Pnt&))
+      : myConvertPoint(convertPoint) {}
 
-  bool operator() (const TopoDS_Shape& lhs, const TopoDS_Shape& rhs);
+    bool operator() (const GeomShapePtr& lhs, const GeomShapePtr& rhs);
 
-  DataMapOfShapeDouble* myMap;
-};
+    DataMapOfShapeDouble myMap;
+    void(*myConvertPoint)(gp_Pnt&);
+  };
+}
 
-bool CompareShapes::operator() (const TopoDS_Shape& theShape1,
-  const TopoDS_Shape& theShape2)
+bool NExplodeTools::CompareShapes::operator() (const GeomShapePtr& lhs, const GeomShapePtr& rhs)
 {
-  if (!myMap->IsBound(theShape1)) {
-    myMap->Bind(theShape1, ShapeToDouble(theShape1));
+  if (myMap.find(lhs) == myMap.end()) {
+    myMap[lhs] = ShapeToDouble(lhs, myConvertPoint);
   }
 
-  if (!myMap->IsBound(theShape2)) {
-    myMap->Bind(theShape2, ShapeToDouble(theShape2));
+  if (myMap.find(rhs) == myMap.end()) {
+    myMap[rhs] = ShapeToDouble(rhs, myConvertPoint);
   }
 
-  std::pair<double, double> val1 = myMap->Find(theShape1);
-  std::pair<double, double> val2 = myMap->Find(theShape2);
+  const std::pair<GeomPointPtr, double>& val1 = myMap.at(lhs);
+  const std::pair<GeomPointPtr, double>& val2 = myMap.at(rhs);
 
-  double tol = Precision::Confusion();
+  double tol = 10.0 * Precision::Confusion();
   bool exchange = Standard_False;
 
-  double dMidXYZ = val1.first - val2.first;
-  if (dMidXYZ >= tol) {
+  // compare coordinates of center points
+  if (val2.first->isLess(val1.first, tol)) {
     exchange = Standard_True;
   }
-  else if (Abs(dMidXYZ) < tol) {
+  else if (!val1.first->isLess(val2.first, tol)) {
     double dLength = val1.second - val2.second;
     if (dLength >= tol) {
       exchange = Standard_True;
     }
-    else if (Abs(dLength) < tol && theShape1.ShapeType() <= TopAbs_FACE) {
+    else if (Abs(dLength) < tol && lhs->shapeType() <= GeomAPI_Shape::FACE) {
       // equal values possible on shapes such as two halves of a sphere and
       // a membrane inside the sphere
-      Bnd_Box box1,box2;
-      BRepBndLib::Add(theShape1, box1);
+      Bnd_Box box1, box2;
+      BRepBndLib::Add(lhs->impl<TopoDS_Shape>(), box1);
       if (!box1.IsVoid()) {
-        BRepBndLib::Add(theShape2, box2);
+        BRepBndLib::Add(rhs->impl<TopoDS_Shape>(), box2);
         Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
         if (dSquareExtent >= tol) {
           exchange = Standard_True;
         }
         else if (Abs(dSquareExtent) < tol) {
-          Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
+          Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, value1, value2;
           box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
-          val1 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
+          value1 = (aXmin + aXmax)*999.0 + (aYmin + aYmax)*99.0 + (aZmin + aZmax)*0.9;
           box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
-          val2 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
-          if ((val1 - val2) >= tol) {
+          value2 = (aXmin + aXmax)*999.0 + (aYmin + aYmax)*99.0 + (aZmin + aZmax)*0.9;
+          if (value1 - value2 >= tol) {
             exchange = Standard_True;
           }
-          else // compare adresses if shapes are geometrically equal
-            exchange = theShape1.TShape().get() > theShape2.TShape().get();
+          else { // compare adresses if shapes are geometrically equal
+            exchange = lhs->impl<TopoDS_Shape>().TShape().get() >
+                       rhs->impl<TopoDS_Shape>().TShape().get();
+          }
         }
       }
-    } else // compare adresses if shapes are geometrically equal
-      exchange = theShape1.TShape().get() > theShape2.TShape().get();
+    }
+    else { // compare adresses if shapes are geometrically equal
+      exchange = lhs->impl<TopoDS_Shape>().TShape().get() >
+                 rhs->impl<TopoDS_Shape>().TShape().get();
+     }
   }
 
   //return val1 < val2;
   return !exchange;
 }
 
-GeomAlgoAPI_NExplode::GeomAlgoAPI_NExplode(
-  const GeomShapePtr theContext, const GeomAPI_Shape::ShapeType theShapeType)
+GeomAlgoAPI_NExplode::GeomAlgoAPI_NExplode(const GeomShapePtr theContext,
+                                           const GeomAPI_Shape::ShapeType theShapeType,
+                                           const ShapeOrder theOrder)
 {
-  std::vector<TopoDS_Shape> aShapesVec;
-
-  const TopoDS_Shape& aContext = theContext->impl<TopoDS_Shape>();
-  TopExp_Explorer anExp(aContext, (TopAbs_ShapeEnum)theShapeType);
-  TopTools_MapOfShape aMapShape;
-  for(; anExp.More(); anExp.Next()) {
-    if (aMapShape.Add(anExp.Current()))
-      aShapesVec.push_back(anExp.Current());
+  std::set<GeomShapePtr, GeomAPI_Shape::Comparator> aMapShape;
+  GeomAPI_ShapeExplorer anExp(theContext, theShapeType);
+  for (; anExp.more(); anExp.next()) {
+    GeomShapePtr aCurrent = anExp.current();
+    if (aMapShape.find(aCurrent) == aMapShape.end()) {
+      mySorted.push_back(aCurrent);
+      aMapShape.insert(aCurrent);
+    }
   }
+  reorder(theOrder);
+}
 
-  CompareShapes::DataMapOfShapeDouble aCash;
-  CompareShapes shComp(&aCash);
-  std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp);
-
-  std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin();
-  for (; anIter != aShapesVec.end(); ++anIter) {
-    GeomShapePtr aShapePtr(new GeomAPI_Shape);
-    aShapePtr->setImpl<TopoDS_Shape>(new TopoDS_Shape(*anIter));
-    mySorted.push_back(aShapePtr);
-  }
+GeomAlgoAPI_NExplode::GeomAlgoAPI_NExplode(const ListOfShape& theShapes,
+                                           const ShapeOrder theOrder)
+  : mySorted(theShapes.begin(), theShapes.end())
+{
+  reorder(theOrder);
 }
 
 int GeomAlgoAPI_NExplode::index(const GeomShapePtr theSubShape)
 {
-  ListOfShape::iterator anIter = mySorted.begin();
+  std::vector<GeomShapePtr>::iterator anIter = mySorted.begin();
   for(int anIndex = 1; anIter != mySorted.end(); anIter++, anIndex++) {
     if ((*anIter)->isSame(theSubShape))
       return anIndex;
@@ -172,10 +198,17 @@ int GeomAlgoAPI_NExplode::index(const GeomShapePtr theSubShape)
 
 GeomShapePtr GeomAlgoAPI_NExplode::shape(const int theIndex)
 {
-  ListOfShape::iterator anIter = mySorted.begin();
+  std::vector<GeomShapePtr>::iterator anIter = mySorted.begin();
   for(int anIndex = 1; anIter != mySorted.end(); anIter++, anIndex++) {
     if (anIndex == theIndex)
       return *anIter;
   }
   return GeomShapePtr(); // not found
 }
+
+void GeomAlgoAPI_NExplode::reorder(const ShapeOrder theNewOrder)
+{
+  NExplodeTools::CompareShapes shComp(
+      theNewOrder == ORDER_BY_HASH_VALUE ? NExplodeTools::pointToDouble : NExplodeTools::dummy);
+  std::stable_sort(mySorted.begin(), mySorted.end(), shComp);
+}
index 81870ddaac94c2c8a3be3af76ccd232921c0d7f5..006a3fdaf9de67c00accf242514e08e9fb04e886 100644 (file)
@@ -24,6 +24,8 @@
 
 #include <GeomAPI_Shape.h>
 
+#include <vector>
+
 /// \class GeomAlgoAPI_NExplode
 /// \ingroup DataAlgo
 /// \brief Sort shapes by their centers of mass, using formula X*999 + Y*99 + Z*0.9.
 /// Used for getting index of sub0shape in WeakNaming algorithm.
 class GeomAlgoAPI_NExplode
 {
- public:
+public:
+  /// Different orders of shape explosion
+  enum ShapeOrder {
+    ORDER_BY_HASH_VALUE,  ///< kept for compatibility
+    ORDER_BY_MIDDLE_POINT ///< modern approach comparing middle points of shapes
+  };
+
+public:
    /// \brief Initializes the sorted list of shapes by the context shape and type of sub-shapes.
-   GEOMALGOAPI_EXPORT GeomAlgoAPI_NExplode(
-     const GeomShapePtr theContext, const GeomAPI_Shape::ShapeType theShapeType);
+   GEOMALGOAPI_EXPORT GeomAlgoAPI_NExplode(const GeomShapePtr theContext,
+                                           const GeomAPI_Shape::ShapeType theShapeType,
+                                           const ShapeOrder theOrder = ORDER_BY_MIDDLE_POINT);
+
+   /// \brief Initializes the sorted list of shapes.
+   GEOMALGOAPI_EXPORT GeomAlgoAPI_NExplode(const ListOfShape& theShapes,
+                                           const ShapeOrder theOrder = ORDER_BY_MIDDLE_POINT);
 
    /// Returns an index (started from one) of sub-shape in the sorted list. Returns 0 if not found.
    GEOMALGOAPI_EXPORT int index(const GeomShapePtr theSubShape);
    /// Returns a shape by an index (started from one). Returns null if not found.
    GEOMALGOAPI_EXPORT GeomShapePtr shape(const int theIndex);
 
+   /// Reorder the shapes
+   GEOMALGOAPI_EXPORT void reorder(const ShapeOrder theNewOrder);
+
 protected:
-  ListOfShape mySorted;
+  std::vector<GeomShapePtr> mySorted;
 };
 
 #endif
index ec8d882402dbc67d62fe76536e1097c6b9f524f7..d3ab25d0a1e0fe613d001e67c80663fe9c029357 100644 (file)
@@ -51,10 +51,12 @@ SET(PROJECT_SOURCES
 SET(PROJECT_LIBRARIES
     ${OpenCASCADE_ApplicationFramework_LIBRARIES}
     GeomAPI
+    GeomAlgoAPI
 )
 SET(PROJECT_INCLUDES
   ${OpenCASCADE_INCLUDE_DIR}
   ../GeomAPI
+  ../GeomAlgoAPI
 )
 
 
index 2a69c252768da29922fe6fe187031449a4243653..9ea2ba8d956c1fa5f3d48900bd6342d9743ea348 100644 (file)
 
 #include "Selector_NExplode.h"
 
-#include <GeomAPI_Pnt.h>
-
-#include <TopoDS_Shape.hxx>
-#include <BRep_Tool.hxx>
-#include <TopoDS.hxx>
-#include <GProp_GProps.hxx>
-#include <BRepGProp.hxx>
-#include <NCollection_DataMap.hxx>
-#include <Precision.hxx>
-#include <Bnd_Box.hxx>
-#include <BRepBndLib.hxx>
-#include <TopExp_Explorer.hxx>
-#include <TopTools_MapOfShape.hxx>
-
-#include <algorithm>
-
-static void dummy(gp_Pnt& thePoint)
-{
-  // do nothing (new approach to order shapes)
-}
-
-static void pointToDouble(gp_Pnt& thePoint)
+#include <GeomAPI_Shape.h>
+#include <GeomAlgoAPI_NExplode.h>
+
+////#include <TopoDS_Shape.hxx>
+////#include <BRep_Tool.hxx>
+////#include <TopoDS.hxx>
+////#include <GProp_GProps.hxx>
+////#include <BRepGProp.hxx>
+////#include <NCollection_DataMap.hxx>
+////#include <Precision.hxx>
+////#include <Bnd_Box.hxx>
+////#include <BRepBndLib.hxx>
+////#include <TopExp_Explorer.hxx>
+////#include <TopTools_MapOfShape.hxx>
+
+static GeomAlgoAPI_NExplode::ShapeOrder getOrder(const bool isOld)
 {
-  // old approach to order shapes
-  double dMidXYZ = thePoint.X() * 999.0 + thePoint.Y() * 99.0 + thePoint.Z() * 0.9;
-  thePoint.SetCoord(dMidXYZ, 0.0, 0.0);
-}
-
-static std::pair<gp_Pnt, double> ShapeToDouble (const TopoDS_Shape& S,
-                                                void (*convertPoint)(gp_Pnt&))
-{
-  // Computing of CentreOfMass
-  gp_Pnt GPoint;
-  double Len;
-
-  if (S.ShapeType() == TopAbs_VERTEX) {
-    GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S));
-    Len = (double)S.Orientation();
-  }
-  else {
-    GProp_GProps GPr;
-    if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
-      BRepGProp::LinearProperties(S, GPr);
-    }
-    else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
-      BRepGProp::SurfaceProperties(S, GPr);
-    }
-    else {
-      BRepGProp::VolumeProperties(S, GPr);
-    }
-    GPoint = GPr.CentreOfMass();
-    Len = GPr.Mass();
-  }
-
-  (*convertPoint)(GPoint);
-  return std::make_pair(GPoint, Len);
+  return isOld ? GeomAlgoAPI_NExplode::ORDER_BY_HASH_VALUE
+               : GeomAlgoAPI_NExplode::ORDER_BY_MIDDLE_POINT;
 }
 
-/*!
-* \brief Sort shapes in the list by their coordinates.
-*/
-struct CompareShapes : public std::binary_function<TopoDS_Shape, TopoDS_Shape, bool>
-{
-  typedef NCollection_DataMap<TopoDS_Shape, std::pair<gp_Pnt, double> > DataMapOfShapeDouble;
-
-  CompareShapes(DataMapOfShapeDouble* theCashMap, void (*convertPoint)(gp_Pnt&))
-    : myMap(theCashMap), myConvertPoint(convertPoint) {}
-
-  bool operator() (const TopoDS_Shape& lhs, const TopoDS_Shape& rhs);
-
-  DataMapOfShapeDouble* myMap;
-  void (*myConvertPoint)(gp_Pnt&);
-};
-
-bool CompareShapes::operator() (const TopoDS_Shape& theShape1,
-  const TopoDS_Shape& theShape2)
+static GeomShapePtr convertShape(const TopoDS_Shape& theShape)
 {
-  if (!myMap->IsBound(theShape1)) {
-    myMap->Bind(theShape1, ShapeToDouble(theShape1, myConvertPoint));
-  }
-
-  if (!myMap->IsBound(theShape2)) {
-    myMap->Bind(theShape2, ShapeToDouble(theShape2, myConvertPoint));
-  }
-
-  const std::pair<gp_Pnt, double>& val1 = myMap->Find(theShape1);
-  const std::pair<gp_Pnt, double>& val2 = myMap->Find(theShape2);
-
-  double tol = 10.0 * Precision::Confusion();
-  bool exchange = Standard_False;
-
-  // compare coordinates of center points
-  GeomPointPtr aPnt1(new GeomAPI_Pnt(val1.first.X(), val1.first.Y(), val1.first.Z()));
-  GeomPointPtr aPnt2(new GeomAPI_Pnt(val2.first.X(), val2.first.Y(), val2.first.Z()));
-  if (aPnt2->isLess(aPnt1, tol)) {
-    exchange = Standard_True;
-  }
-  else if (!aPnt1->isLess(aPnt2, tol)) {
-    double dLength = val1.second - val2.second;
-    if (dLength >= tol) {
-      exchange = Standard_True;
-    }
-    else if (Abs(dLength) < tol && theShape1.ShapeType() <= TopAbs_FACE) {
-      // equal values possible on shapes such as two halves of a sphere and
-      // a membrane inside the sphere
-// LCOV_EXCL_START
-      // this part of code is taken from GEOM module, but can not reproduce in SHAPER
-      Bnd_Box box1,box2;
-      BRepBndLib::Add(theShape1, box1);
-      if (!box1.IsVoid()) {
-        BRepBndLib::Add(theShape2, box2);
-        Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
-        if (dSquareExtent >= tol) {
-          exchange = Standard_True;
-        }
-        else if (Abs(dSquareExtent) < tol) {
-          Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
-          box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
-          val1 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
-          box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
-          val2 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
-          if ((val1 - val2) >= tol) {
-            exchange = Standard_True;
-          }
-        }
-      }
-// LCOV_EXCL_STOP
-    } else // compare addresses if shapes are geometrically equal
-      return theShape1.TShape().get() > theShape2.TShape().get();
-  }
-
-  //return val1 < val2;
-  return !exchange;
+  GeomShapePtr aNewShape(new GeomAPI_Shape);
+  aNewShape->setImpl(new TopoDS_Shape(theShape));
+  return aNewShape;
 }
 
 Selector_NExplode::Selector_NExplode(const TopoDS_ListOfShape& theShapes, const bool theOldOrder)
   : myToBeReordered(theOldOrder)
 {
-  for(TopoDS_ListOfShape::Iterator anIter(theShapes); anIter.More(); anIter.Next()) {
-    mySorted.push_back(anIter.Value());
-  }
+  ListOfShape aShapes;
+  for (TopoDS_ListOfShape::Iterator anIt(theShapes); anIt.More(); anIt.Next())
+    aShapes.push_back(convertShape(anIt.Value()));
 
-  CompareShapes::DataMapOfShapeDouble aCash;
-  CompareShapes shComp(&aCash, theOldOrder ? pointToDouble : dummy);
-  std::stable_sort(mySorted.begin(), mySorted.end(), shComp);
+  mySorted = std::make_shared<GeomAlgoAPI_NExplode>(aShapes, getOrder(theOldOrder));
 }
 
 Selector_NExplode::Selector_NExplode(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType,
                                      const bool theOldOrder)
   : myToBeReordered(theOldOrder)
 {
-  TopTools_MapOfShape anAdded; // to avoid same shapes duplication
-  for(TopExp_Explorer anExp(theShape, theType); anExp.More(); anExp.Next()) {
-    if (anAdded.Add(anExp.Current()))
-      mySorted.push_back(anExp.Current());
-  }
-
-  CompareShapes::DataMapOfShapeDouble aCash;
-  CompareShapes shComp(&aCash, theOldOrder ? pointToDouble : dummy);
-  std::stable_sort(mySorted.begin(), mySorted.end(), shComp);
+  GeomShapePtr aShape = convertShape(theShape);
+  GeomAPI_Shape::ShapeType aType = (GeomAPI_Shape::ShapeType)theType;
+  mySorted = std::make_shared<GeomAlgoAPI_NExplode>(aShape, aType, getOrder(theOldOrder));
 }
 
 
 int Selector_NExplode::index(const TopoDS_Shape& theSubShape)
 {
-  // reorder if necessary
-  reorder();
-
-  std::vector<TopoDS_Shape>::iterator anIter = mySorted.begin();
-  for(int anIndex = 1; anIter != mySorted.end(); anIter++, anIndex++) {
-    if ((*anIter).IsSame(theSubShape))
-      return anIndex;
-  }
-  return -1; // not found
+  int anIndex = mySorted->index(convertShape(theSubShape));
+  return anIndex > 0 ? anIndex : -1; // -1 if not found
 }
 
 TopoDS_Shape Selector_NExplode::shape(int& theIndex)
 {
-  std::vector<TopoDS_Shape>::iterator anIter = mySorted.begin();
-  for(int anIndex = 1; anIter != mySorted.end(); anIter++, anIndex++) {
-    if (anIndex == theIndex) {
-      TopoDS_Shape aShape = *anIter;
-      if (myToBeReordered)
-        theIndex = index(aShape);
-      return aShape;
+  TopoDS_Shape aResult;
+  GeomShapePtr aShape = mySorted->shape(theIndex);
+  if (aShape) {
+    aResult = aShape->impl<TopoDS_Shape>();
+    if (myToBeReordered) {
+      mySorted->reorder(GeomAlgoAPI_NExplode::ORDER_BY_MIDDLE_POINT);
+      theIndex = mySorted->index(aShape);
     }
   }
-  return TopoDS_Shape(); // not found
-}
-
-void Selector_NExplode::reorder()
-{
-  if (!myToBeReordered)
-    return;
-
-  myToBeReordered = false;
-  CompareShapes::DataMapOfShapeDouble aCash;
-  CompareShapes shComp(&aCash, dummy);
-  std::stable_sort(mySorted.begin(), mySorted.end(), shComp);
+  return aResult;
 }
index 412620b8cf4629f902389e91907ee95bc9d41347..21fff0c3fa47a986705be2e6f0941ca05cc08932 100644 (file)
@@ -24,7 +24,9 @@
 
 #include <TopoDS_Shape.hxx>
 
-#include <vector>
+#include <memory>
+
+class GeomAlgoAPI_NExplode;
 
 /// \class Selector_NExplode
 /// \ingroup DataModel
@@ -48,12 +50,8 @@ class Selector_NExplode
    /// Recompute the index if the old order was used. The value will contain the new ordered index.
    SELECTOR_EXPORT TopoDS_Shape shape(int& theIndex);
 
-private:
-  /// Reorder list of shapes.
-  void reorder();
-
 protected:
-  std::vector<TopoDS_Shape> mySorted; ///< keep the ordered list of shapes
+  std::shared_ptr<GeomAlgoAPI_NExplode> mySorted; ///< keep the ordered list of shapes
   bool myToBeReordered; ///< the list has to be reordered
 };