Salome HOME
Fix for the big models (like flange) naming correctness. Make sketch sub-elements...
authormpv <mpv@opencascade.com>
Thu, 4 Oct 2018 11:47:58 +0000 (14:47 +0300)
committermpv <mpv@opencascade.com>
Thu, 4 Oct 2018 11:48:19 +0000 (14:48 +0300)
src/GeomAPI/GeomAPI_Edge.cpp
src/Model/Model_ResultConstruction.cpp
src/Model/Model_SelectionNaming.cpp
src/Model/Model_SelectionNaming.h

index cd3c08466eb0e937d30813ed62f194e239e1f5f8..01c98124c438de5cc5fd096a8412f0a68d49526d 100644 (file)
@@ -217,16 +217,16 @@ bool GeomAPI_Edge::isEqual(const std::shared_ptr<GeomAPI_Shape> theEdge) const
   double aInStart, aInEnd;
   Handle(Geom_Curve) aInCurve = BRep_Tool::Curve(TopoDS::Edge(aInShape), aInStart, aInEnd);
 
+  // Check that end point parameters are the same
+  if ((aMyStart != aInStart) || (aMyEnd != aInEnd))
+    return false;
+
   // Check that curves a the same type
   GeomAdaptor_Curve aMyAdaptor(aMyCurve);
   GeomAdaptor_Curve aInAdaptor(aInCurve);
   if (aMyAdaptor.GetType() != aInAdaptor.GetType())
     return false;
 
-  // Check that end point parameters are the same
-  if ((aMyStart != aInStart) || (aMyEnd != aInEnd))
-    return false;
-
   // Check that end points are equal
   gp_Pnt aMyPnt1 = aMyAdaptor.Value(aMyStart);
   gp_Pnt aMyPnt2 = aMyAdaptor.Value(aMyEnd);
index ad9c9a3070e2f9c060b0a9affef787a4e46d243f..432f56b13191571d6ed1e14277ec4e6c6a5da052 100644 (file)
@@ -177,12 +177,16 @@ std::string fullName(CompositeFeaturePtr theComposite, const TopoDS_Shape& theSu
 {
   TopAbs_ShapeEnum aShapeType = theSubShape.ShapeType();
   gp_Pnt aVertexPos;
-  TColStd_MapOfTransient allCurves;
+  NCollection_Map<TopoDS_Edge> allExactEdges;
+  NCollection_Map<TopoDS_Edge, Model_EdgesHasher> allEdges;
+  NCollection_Map<Handle(Geom_Curve), Model_CurvesHasher> allCurves;
   if (aShapeType == TopAbs_VERTEX) { // compare positions
     aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(theSubShape));
   } else {
     for(TopExp_Explorer anEdgeExp(theSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) {
       TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current());
+      allExactEdges.Add(anEdge);
+      allEdges.Add(anEdge);
       Standard_Real aFirst, aLast;
       Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
       allCurves.Add(aCurve);
@@ -193,47 +197,58 @@ std::string fullName(CompositeFeaturePtr theComposite, const TopoDS_Shape& theSu
   TColStd_PackedMapOfInteger aRefs; // indixes of sub-elements in composite
 
   const int aSubNum = theComposite->numberOfSubs();
-  for(int a = 0; a < aSubNum; a++) {
-    FeaturePtr aSub = theComposite->subFeature(a);
-    const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
-    std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
-    // there may be many shapes (circle and center): register if at least one is in selection
-    for(; aRes != aResults.cend(); aRes++) {
-      ResultConstructionPtr aConstr =
-        std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
-      if (!aConstr->shape()) {
-        continue;
-      }
-      if (aShapeType == TopAbs_VERTEX) {
-        if (aConstr->shape()->isVertex()) { // compare vertices positions
-          const TopoDS_Shape& aVertex = aConstr->shape()->impl<TopoDS_Shape>();
-          gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex));
-          if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) {
-            aRefs.Add(theComposite->subFeatureId(a));
-            aSubNames[theComposite->subFeatureId(a)] = Model_SelectionNaming::shortName(aConstr);
-          }
-        } else { // get first or last vertex of the edge: last is stored with additional delta
-          const TopoDS_Shape& anEdge = aConstr->shape()->impl<TopoDS_Shape>();
-          int aDelta = kSTART_VERTEX_DELTA;
-          for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) {
-            gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVExp.Current()));
+  // reduce equality criteria from strong to weak
+  for(int aTypeOfIdentification = 0; aTypeOfIdentification < 3; aTypeOfIdentification++) {
+    for(int a = 0; a < aSubNum; a++) {
+      FeaturePtr aSub = theComposite->subFeature(a);
+      const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
+      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
+      // there may be many shapes (circle and center): register if at least one is in selection
+      for(; aRes != aResults.cend(); aRes++) {
+        ResultConstructionPtr aConstr =
+          std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
+        if (!aConstr->shape()) {
+          continue;
+        }
+        if (aShapeType == TopAbs_VERTEX) {
+          if (aConstr->shape()->isVertex()) { // compare vertices positions
+            const TopoDS_Shape& aVertex = aConstr->shape()->impl<TopoDS_Shape>();
+            gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex));
             if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) {
-              aRefs.Add(aDelta + theComposite->subFeatureId(a));
-              aSubNames[aDelta + theComposite->subFeatureId(a)] =
-                Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA);
-              break;
+              aRefs.Add(theComposite->subFeatureId(a));
+              aSubNames[theComposite->subFeatureId(a)] = Model_SelectionNaming::shortName(aConstr);
+            }
+          } else { // get first or last vertex of the edge: last is stored with additional delta
+            const TopoDS_Shape& anEdge = aConstr->shape()->impl<TopoDS_Shape>();
+            int aDelta = kSTART_VERTEX_DELTA;
+            for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) {
+              gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVExp.Current()));
+              if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) {
+                aRefs.Add(aDelta + theComposite->subFeatureId(a));
+                aSubNames[aDelta + theComposite->subFeatureId(a)] =
+                  Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA);
+                break;
+              }
+              aDelta += kSTART_VERTEX_DELTA;
             }
-            aDelta += kSTART_VERTEX_DELTA;
           }
-        }
-      } else {
-        if (aConstr->shape()->isEdge()) {
-          const TopoDS_Shape& aResShape = aConstr->shape()->impl<TopoDS_Shape>();
-          TopoDS_Edge anEdge = TopoDS::Edge(aResShape);
-          if (!anEdge.IsNull()) {
-            Standard_Real aFirst, aLast;
-            Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
-            if (allCurves.Contains(aCurve)) {
+        } else {
+          if (aConstr->shape()->isEdge()) {
+            const TopoDS_Shape& aResShape = aConstr->shape()->impl<TopoDS_Shape>();
+            TopoDS_Edge anEdge = TopoDS::Edge(aResShape);
+            if (anEdge.IsNull())
+              continue;
+            bool aIsEqual = false;
+            if (aTypeOfIdentification == 0) { // check equality of curves
+              aIsEqual = allExactEdges.Contains(anEdge);
+            } else if (aTypeOfIdentification == 1) { // check EdgesHash equality of edges
+              aIsEqual = allEdges.Contains(anEdge);
+            } else { // check CurvesHash equality of curves
+              Standard_Real aFirst, aLast;
+              Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+              aIsEqual = allCurves.Contains(aCurve);
+            }
+            if (aIsEqual) {
               int anID = theComposite->subFeatureId(a);
               aRefs.Add(anID);
               aSubNames[anID] = Model_SelectionNaming::shortName(aConstr);
@@ -241,11 +256,20 @@ std::string fullName(CompositeFeaturePtr theComposite, const TopoDS_Shape& theSu
                 // add edges to sub-label to support naming for edges selection
                 TopExp_Explorer anEdgeExp(theSubShape, TopAbs_EDGE);
                 for(; anEdgeExp.More(); anEdgeExp.Next()) {
-                  TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current());
-                  Standard_Real aFirst, aLast;
-                  Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
-                  if (aFaceCurve == aCurve) {
-                    int anOrient = Model_SelectionNaming::edgeOrientation(theSubShape, anEdge);
+                  TopoDS_Edge aFaceEdge = TopoDS::Edge(anEdgeExp.Current());
+                  bool aIsEqual = false;
+                  if (aTypeOfIdentification == 0) { // check equality of curves
+                    aIsEqual = anEdge.IsSame(aFaceEdge);
+                  } else if (aTypeOfIdentification == 1) { // check EdgesHash equality of edges
+                    aIsEqual = Model_EdgesHasher::IsEqual(aFaceEdge, anEdge);
+                  } else { // check CurvesHash equality of curves
+                    Standard_Real aFirst, aLast;
+                    Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(aFaceEdge, aFirst, aLast);
+                    Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+                    aIsEqual = Model_CurvesHasher::IsEqual(aFaceCurve, aCurve);
+                  }
+                  if (aIsEqual) {
+                    int anOrient = Model_SelectionNaming::edgeOrientation(theSubShape, aFaceEdge);
                     anOrientations[anID] = anOrient;
                   }
                 }
@@ -255,6 +279,8 @@ std::string fullName(CompositeFeaturePtr theComposite, const TopoDS_Shape& theSu
         }
       }
     }
+    if (!aRefs.IsEmpty() || aShapeType == TopAbs_VERTEX)
+      break;
   }
   std::stringstream aName;
   // #1839 : do not store name of the feature in the tree, since this name could be changed
@@ -303,7 +329,7 @@ static void saveSubName(CompositeFeaturePtr theComposite,
           TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());
           Standard_Real aFirst, aLast;
           Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
-          if (aCurve == aSubCurve &&
+          if (Model_CurvesHasher::IsEqual(aCurve, aSubCurve) &&
               ((fabs(aFirst - aSubFirst) < 1.e-9 &&  fabs(aLast - aSubLast) < 1.e-9)) ||
               (fabs(aFirst - aSubLast) < 1.e-9 &&  fabs(aLast - aSubFirst) < 1.e-9)) {
             aSub = anEdge;
@@ -474,7 +500,7 @@ int Model_ResultConstruction::select(const std::shared_ptr<GeomAPI_Shape>& theSu
   TopAbs_ShapeEnum aShapeType = aSubShape.ShapeType();
   TDataStd_Integer::Set(aLab, (int)aShapeType);
   gp_Pnt aVertexPos;
-  TColStd_MapOfTransient allCurves;
+  TColStd_MapOfTransient allCurves; // curves of the sketc hsub-elements are used, so, edges are not equal
   if (aShapeType == TopAbs_VERTEX) { // compare positions
     aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(aSubShape));
   } else {
@@ -521,7 +547,7 @@ int Model_ResultConstruction::select(const std::shared_ptr<GeomAPI_Shape>& theSu
                   TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current());
                   Standard_Real aFirst, aLast;
                   Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
-                  if (aFaceCurve == aCurve) {
+                  if (Model_CurvesHasher::IsEqual(aFaceCurve, aCurve)) {
                     while(aUsedIDMap.Contains(anID))
                       anID += 100000;
                     aUsedIDMap.Add(anID);
@@ -700,7 +726,7 @@ bool Model_ResultConstruction::update(const int theIndex,
       } else { // searching for most looks-like initial face by the indexes
         // prepare edges of the current result for the fast searching
         // curves and orientations of edges
-        NCollection_DataMap<Handle(Geom_Curve), int> allCurves;
+        NCollection_DataMap<Handle(Geom_Curve), int, Model_CurvesHasher> allCurves;
         const int aSubNum = aComposite->numberOfSubs();
         for(int a = 0; a < aSubNum; a++) {
           int aSubID = aComposite->subFeatureId(a);
index 1b1c51e9ec70901a076e22a19d15503fb263dae5..9daf02c95f81b037869662d39efbfbda868c848d 100644 (file)
@@ -30,6 +30,7 @@
 #include <ModelAPI_CompositeFeature.h>
 #include <ModelAPI_ResultBody.h>
 #include <GeomAPI_Wire.h>
+#include <GeomAPI_Edge.h>
 
 #include <TopoDS_Iterator.hxx>
 #include <TopoDS.hxx>
@@ -50,6 +51,7 @@
 #include <TNaming_SameShapeIterator.hxx>
 #include <TDataStd_Name.hxx>
 #include <TColStd_MapOfTransient.hxx>
+#include <Precision.hxx>
 #include <algorithm>
 #include <stdexcept>
 
@@ -700,9 +702,67 @@ int Model_SelectionNaming::edgeOrientation(const TopoDS_Shape& theContext, TopoD
   return 0; // unknown
 }
 
+int Model_CurvesHasher::HashCode(const Handle(Geom_Curve)& theCurve, const Standard_Integer Upper)
+{
+  double aFirstParam = theCurve->FirstParameter();
+  if (aFirstParam < -1.e+100 || aFirstParam > 1.e+100)
+    aFirstParam = 0;
+  double aLastParam = theCurve->LastParameter();
+  if (aLastParam < -1.e+100 || aLastParam > 1.e+100)
+    aLastParam = 2;
+  else aLastParam = (aLastParam + aFirstParam) / 2.; // to avoid in periodic same first and last
+
+  gp_XYZ aCoordSum = theCurve->Value(aFirstParam).XYZ() + theCurve->Value(aLastParam).XYZ();
+  return ::HashCode(aCoordSum.X() + aCoordSum.Y() / 123. + aCoordSum.Z() / 123456., Upper);
+}
+bool Model_CurvesHasher::IsEqual(const Handle(Geom_Curve)& theC1, const Handle(Geom_Curve)& theC2)
+{
+  if (theC1->DynamicType() != theC2->DynamicType())
+    return false;
+  double aFirstParam1 = theC1->FirstParameter();
+  if (aFirstParam1 < -1.e+100 || aFirstParam1 > 1.e+100)
+    aFirstParam1 = 0;
+  double aFirstParam2 = theC2->FirstParameter();
+  if (aFirstParam2 < -1.e+100 || aFirstParam2 > 1.e+100)
+    aFirstParam2 = 0;
+  if (fabs(aFirstParam1 - aFirstParam2) > 1.e-9)
+    return false;
+
+  double aLastParam1 = theC1->LastParameter();
+  if (aLastParam1 < -1.e+100 || aLastParam1 > 1.e+100)
+    aLastParam1 = 2.;
+  else aLastParam1 = (aLastParam1 + aFirstParam1) / 2.; // to avoid in periodic same first and last
+  double aLastParam2 = theC2->LastParameter();
+  if (aLastParam2 < -1.e+100 || aLastParam2 > 1.e+100)
+    aLastParam2 = 2.;
+  else aLastParam2 = (aLastParam2 + aFirstParam2) / 2.; // to avoid in periodic same first and last
+
+  if (fabs(aLastParam1 - aLastParam2) > 1.e-9)
+    return false;
+
+  return theC1->Value(aFirstParam1).IsEqual(theC2->Value(aFirstParam2), Precision::Confusion()) &&
+    theC1->Value(aLastParam1).IsEqual(theC2->Value(aLastParam2), Precision::Confusion());
+}
+
+int Model_EdgesHasher::HashCode(const TopoDS_Edge& theEdge, const Standard_Integer Upper)
+{
+  Standard_Real aFirst, aLast;
+  Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, aFirst, aLast);
+  return Model_CurvesHasher::HashCode(aCurve, Upper);
+}
+
+bool Model_EdgesHasher::IsEqual(const TopoDS_Edge& theE1, const TopoDS_Edge& theE2)
+{
+  GeomEdgePtr aSh1(new GeomAPI_Edge);
+  aSh1->setImpl(new TopoDS_Shape(theE1));
+  GeomEdgePtr aSh2(new GeomAPI_Edge);
+  aSh2->setImpl(new TopoDS_Shape(theE2));
+  return aSh1->isEqual(aSh2);
+}
+
 std::shared_ptr<GeomAPI_Shape> Model_SelectionNaming::findAppropriateFace(
   std::shared_ptr<ModelAPI_Result>& theConstr,
-  NCollection_DataMap<Handle(Geom_Curve), int>& theCurves, const bool theIsWire)
+  NCollection_DataMap<Handle(Geom_Curve), int, Model_CurvesHasher>& theCurves, const bool theIsWire)
 {
   int aBestFound = 0; // best number of found edges (not percentage: issue 1019)
   int aBestOrient = 0; // for the equal "BestFound" additional parameter is orientation
@@ -726,7 +786,7 @@ std::shared_ptr<GeomAPI_Shape> Model_SelectionNaming::findAppropriateFace(
     std::list<TopoDS_Shape>::iterator aFW = aFacesWires.begin();
     for(; aFW != aFacesWires.end(); aFW++) {
       TopExp_Explorer anEdgesExp(*aFW, TopAbs_EDGE);
-      TColStd_MapOfTransient alreadyProcessed; // to avoid counting edges with same curved (841)
+      TColStd_MapOfTransient alreadyProcessed; // to avoid counting edges with same curves (841)
       for(; anEdgesExp.More(); anEdgesExp.Next()) {
         TopoDS_Edge anEdge = TopoDS::Edge(anEdgesExp.Current());
         if (!anEdge.IsNull()) {
@@ -1048,7 +1108,7 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType,
             return false;
 
           // curves and orientations of edges
-          NCollection_DataMap<Handle(Geom_Curve), int> allCurves;
+          NCollection_DataMap<Handle(Geom_Curve), int, Model_CurvesHasher> allCurves;
           const int aSubNum = aComposite->numberOfSubs();
           for(int a = 0; a < aSubNum; a++) {
             int aSubID = aComposite->subFeatureId(a);
@@ -1084,7 +1144,7 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType,
             return false;
 
            // curves and orientations of edges
-          NCollection_DataMap<Handle(Geom_Curve), int> allCurves;
+          NCollection_DataMap<Handle(Geom_Curve), int, Model_CurvesHasher> allCurves;
           const int aSubNum = aComposite->numberOfSubs();
           for(int a = 0; a < aSubNum; a++) {
             int aSubID = aComposite->subFeatureId(a);
index d6ebc71372a1e4e20f5d181960f0f3005d608e1d..3494369df56d3aef00b4dbd799dc34a2b5f95c94 100644 (file)
 #include <Geom_Curve.hxx>
 #include <TopoDS_Edge.hxx>
 
+// class to compare curves in the same way as in GeomAPI_Edge
+class Model_CurvesHasher
+{
+public:
+  DEFINE_STANDARD_ALLOC
+  /// standard hash code
+  static int HashCode (const Handle(Geom_Curve)& theCurve, const Standard_Integer Upper);
+  /// comapre curves by parameters and points on them
+  static bool IsEqual (const Handle(Geom_Curve)& theC1, const Handle(Geom_Curve)& theC2);
+};
+
+// class to compare edges in the same way as in GeomAPI_Edge
+class Model_EdgesHasher
+{
+public:
+  DEFINE_STANDARD_ALLOC
+  /// standard hash code
+  static int HashCode (const TopoDS_Edge& theEdge, const Standard_Integer Upper);
+  /// comapre curves by parameters and points on them
+  static bool IsEqual (const TopoDS_Edge& theE1, const TopoDS_Edge& theE2);
+};
+
+
 /**\class Model_SelectionNaming
  * \ingroup DataModel
  * \brief The set of methods that allow to generate a string-name for the selection attribute.
  */
-
 class Model_SelectionNaming
 {
   TDF_Label myLab; ///< Selection label of the selection attribute
@@ -66,7 +88,8 @@ public:
   /// \returns faces fron this construction if found
   static std::shared_ptr<GeomAPI_Shape> findAppropriateFace(
     std::shared_ptr<ModelAPI_Result>& theConstr,
-    NCollection_DataMap<Handle(Geom_Curve), int>& theCurves, const bool theIsWire);
+    NCollection_DataMap<Handle(Geom_Curve), int, Model_CurvesHasher>& theCurves,
+    const bool theIsWire);
 
   /// Returns orientation of the edge in the context shape
   static int edgeOrientation(const TopoDS_Shape& theContext, TopoDS_Edge& theEdge);