Salome HOME
Task #3231: Sketcher Offset of a curve
authorArtem Zhidkov <Artem.Zhidkov@opencascade.com>
Tue, 23 Jun 2020 06:11:41 +0000 (09:11 +0300)
committerArtem Zhidkov <Artem.Zhidkov@opencascade.com>
Tue, 23 Jun 2020 06:11:41 +0000 (09:11 +0300)
Improve searching of coincidences in context of B-spline curve

src/SketchPlugin/SketchPlugin_Offset.cpp
src/SketchPlugin/SketchPlugin_Tools.cpp
src/SketchPlugin/SketchPlugin_Tools.h

index d789c85a714c8c7002d8125bd5b47501ce94bdbb..f941bc315dd73c5d85d895d1b0f569fcbc724873 100644 (file)
@@ -164,12 +164,19 @@ bool SketchPlugin_Offset::findWireOneWay (const FeaturePtr& theFirstEdge,
   FeaturePtr aNextEdgeFeature;
   int nbFound = 0;
 
-  std::set<AttributePoint2DPtr> aCoincPoints =
-    SketchPlugin_Tools::findPointsCoincidentToPoint(theEndPoint);
-
-  std::set<AttributePoint2DPtr>::iterator aPointsIt = aCoincPoints.begin();
-  for (; aPointsIt != aCoincPoints.end(); aPointsIt++) {
-    AttributePoint2DPtr aP = (*aPointsIt);
+  std::set<AttributePoint2DPtr> aCoincPoints;
+  std::map<AttributePoint2DArrayPtr, int> aCoincPointsInArray;
+  SketchPlugin_Tools::findPointsCoincidentToPoint(theEndPoint, aCoincPoints, aCoincPointsInArray);
+
+  // store all found attributes to a single array
+  std::set<AttributePtr> anAllCoincPoints;
+  anAllCoincPoints.insert(aCoincPoints.begin(), aCoincPoints.end());
+  for (auto it = aCoincPointsInArray.begin(); it != aCoincPointsInArray.end(); ++it)
+    anAllCoincPoints.insert(it->first);
+
+  std::set<AttributePtr>::iterator aPointsIt = anAllCoincPoints.begin();
+  for (; aPointsIt != anAllCoincPoints.end(); aPointsIt++) {
+    AttributePtr aP = (*aPointsIt);
     FeaturePtr aCoincFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aP->owner());
 
     // Condition 1: not a point feature
index 68765a14e9620b12df1d15b5c1c00f9648d186a1..6209b788d14ee0e2bd5e11ebbed34e2ae0085a04 100644 (file)
@@ -37,6 +37,7 @@
 #include <SketcherPrs_Tools.h>
 
 #include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
 
 #include <ModelGeomAlgo_Point2D.h>
 #include <ModelGeomAlgo_Shape.h>
@@ -113,10 +114,10 @@ std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin
   return aPnt;
 }
 
-std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature)
+std::set<FeaturePtr> findCoincidentConstraints(const ObjectPtr& theObject)
 {
   std::set<FeaturePtr> aCoincident;
-  const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
+  const std::set<AttributePtr>& aRefsList = theObject->data()->refsToMe();
   std::set<AttributePtr>::const_iterator aIt;
   for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
     FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
@@ -199,38 +200,53 @@ std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& th
 // Useful to find points coincident to a given point.
 class CoincidentPoints
 {
+  static const int THE_DEFAULT_INDEX = -1;
+
 public:
-  void addCoincidence(const AttributePoint2DPtr& thePoint1,
-                      const AttributePoint2DPtr& thePoint2 = AttributePoint2DPtr())
+  void addCoincidence(const AttributePtr& thePoint1, const int theIndex1,
+                      const AttributePtr& thePoint2, const int theIndex2)
   {
-    std::list< std::set<AttributePoint2DPtr> >::iterator aFound1 = find(thePoint1);
-    std::list< std::set<AttributePoint2DPtr> >::iterator aFound2 = find(thePoint2);
+    auto aFound1 = find(thePoint1, theIndex1);
+    auto aFound2 = find(thePoint2, theIndex2);
     if (aFound1 == myCoincidentPoints.end()) {
       if (aFound2 == myCoincidentPoints.end()) {
-        std::set<AttributePoint2DPtr> aNewSet;
-        aNewSet.insert(thePoint1);
+        std::map<AttributePtr, std::set<int> > aNewSet;
+        aNewSet[thePoint1].insert(theIndex1);
         if (thePoint2)
-          aNewSet.insert(thePoint2);
+          aNewSet[thePoint2].insert(theIndex2);
         myCoincidentPoints.push_back(aNewSet);
       } else
-        aFound2->insert(thePoint1);
+        (*aFound2)[thePoint1].insert(theIndex1);
     } else if (aFound2 == myCoincidentPoints.end()) {
       if (thePoint2)
-        aFound1->insert(thePoint2);
+        (*aFound1)[thePoint2].insert(theIndex2);
     } else {
-      aFound1->insert(aFound2->begin(), aFound2->end());
+      for (auto it = aFound2->begin(); it != aFound2->end(); ++it)
+        (*aFound1)[it->first].insert(it->second.begin(), it->second.end());
       myCoincidentPoints.erase(aFound2);
     }
   }
 
-  std::set<AttributePoint2DPtr> coincidentPoints(const AttributePoint2DPtr& thePoint)
+  void coincidentPoints(const AttributePoint2DPtr& thePoint,
+                        std::set<AttributePoint2DPtr>& thePoints,
+                        std::map<AttributePoint2DArrayPtr, int>& thePointsInArray)
   {
     collectCoincidentPoints(thePoint);
 
-    std::list< std::set<AttributePoint2DPtr> >::iterator aFound = find(thePoint);
-    if (aFound == myCoincidentPoints.end())
-      return std::set<AttributePoint2DPtr>();
-    return *aFound;
+    auto aFound = find(thePoint, THE_DEFAULT_INDEX);
+    if (aFound != myCoincidentPoints.end()) {
+      for (auto it = aFound->begin(); it != aFound->end(); ++it) {
+        AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(it->first);
+        if (aPoint)
+          thePoints.insert(aPoint);
+        else {
+          AttributePoint2DArrayPtr aPointArray =
+              std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(it->first);
+          if (aPointArray)
+            thePointsInArray[aPointArray] = *it->second.begin();
+        }
+      }
+    }
   }
 
 private:
@@ -239,7 +255,11 @@ private:
   {
     // iterate through coincideces for the given feature
     std::set<FeaturePtr> aCoincidences = SketchPlugin_Tools::findCoincidentConstraints(theFeature);
-    std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
+    if (theFeature->getKind() == SketchPlugin_Point::ID()) {
+      std::set<FeaturePtr> aCoincToRes =
+          SketchPlugin_Tools::findCoincidentConstraints(theFeature->lastResult());
+      aCoincidences.insert(aCoincToRes.begin(), aCoincToRes.end());
+    }\r    std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
     for (; aCIt != aCoincidences.end(); ++aCIt)
     {
       if (theCoincidences.find(*aCIt) != theCoincidences.end())
@@ -248,12 +268,18 @@ private:
       // iterate on coincident attributes
       for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
         AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
-        if (aRefAttr && !aRefAttr->isObject())
-        {
-          FeaturePtr anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner());
-          if (anOwner != theFeature)
-            coincidences(anOwner, theCoincidences);
+        if (!aRefAttr)
+          continue;
+        FeaturePtr anOwner;
+        if (aRefAttr->isObject()) {
+          FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+          if (aFeature->getKind() == SketchPlugin_Point::ID())
+            anOwner = aFeature;
         }
+        else
+          anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner());
+        if (anOwner && anOwner != theFeature)
+          coincidences(anOwner, theCoincidences);
       }
     }
   }
@@ -262,7 +288,8 @@ private:
   // (two points may be coincident through the third point)
   void collectCoincidentPoints(const AttributePoint2DPtr& thePoint)
   {
-    AttributePoint2DPtr aPoints[2];
+    AttributePtr aPoints[2];
+    int anIndicesInArray[2];
 
     FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
     std::set<FeaturePtr> aCoincidences;
@@ -270,38 +297,72 @@ private:
 
     std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
     for (; aCIt != aCoincidences.end(); ++aCIt) {
-      aPoints[0] = AttributePoint2DPtr();
-      aPoints[1] = AttributePoint2DPtr();
+      aPoints[0] = aPoints[1] = AttributePtr();
+      anIndicesInArray[0] = anIndicesInArray[1] = THE_DEFAULT_INDEX;
       for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
         AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
-        if (aRefAttr && !aRefAttr->isObject())
-          aPoints[aPtInd++] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
+        if (!aRefAttr)
+          continue;
+        if (aRefAttr->isObject()) {
+          FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+          if (aFeature && aFeature->getKind() == SketchPlugin_Point::ID())
+            aPoints[aPtInd++] = aFeature->attribute(SketchPlugin_Point::COORD_ID());
+        }
+        else {
+          AttributePoint2DPtr aPointAttr =
+              std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
+          AttributePoint2DArrayPtr aPointArray =
+              std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(aRefAttr->attr());
+          if (aPointAttr)
+            aPoints[aPtInd++] = aPointAttr;
+          else if (aPointArray) {
+            AttributeIntegerPtr anIndexAttr = (*aCIt)->integer(i == 0 ?
+                SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_A() :
+                SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_B());
+            aPoints[aPtInd] = aPointArray;
+            anIndicesInArray[aPtInd++] = anIndexAttr->value();
+          }
+        }
       }
 
       if (aPoints[0] && aPoints[1])
-        addCoincidence(aPoints[0], aPoints[1]);
+        addCoincidence(aPoints[0], anIndicesInArray[0], aPoints[1], anIndicesInArray[1]);
     }
   }
 
-  std::list< std::set<AttributePoint2DPtr> >::iterator find(const AttributePoint2DPtr& thePoint)
+  std::list< std::map<AttributePtr, std::set<int> > >::iterator find(const AttributePtr& thePoint,
+                                                                     const int theIndex)
   {
-    std::list< std::set<AttributePoint2DPtr> >::iterator aSeek = myCoincidentPoints.begin();
-    for (; aSeek != myCoincidentPoints.end(); ++aSeek)
-      if (aSeek->find(thePoint) != aSeek->end())
+    auto aSeek = myCoincidentPoints.begin();
+    for (; aSeek != myCoincidentPoints.end(); ++aSeek) {
+      auto aFound = aSeek->find(thePoint);
+      if (aFound != aSeek->end() && aFound->second.find(theIndex) != aFound->second.end())
         return aSeek;
+    }
     return myCoincidentPoints.end();
   }
 
 private:
-  std::list< std::set<AttributePoint2DPtr> > myCoincidentPoints;
+  std::list< std::map<AttributePtr, std::set<int> > > myCoincidentPoints;
 };
 
 std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint)
+{
+  std::set<AttributePoint2DPtr> aPoints;
+  std::map<AttributePoint2DArrayPtr, int> aPointsInArray;
+  findPointsCoincidentToPoint(thePoint, aPoints, aPointsInArray);
+  return aPoints;
+}
+
+void findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint,
+                                 std::set<AttributePoint2DPtr>& thePoints,
+                                 std::map<AttributePoint2DArrayPtr, int>& thePointsInArray)
 {
   CoincidentPoints aCoincidentPoints;
-  return aCoincidentPoints.coincidentPoints(thePoint);
+  aCoincidentPoints.coincidentPoints(thePoint, thePoints, thePointsInArray);
 }
 
+
 void resetAttribute(SketchPlugin_Feature* theFeature,
                     const std::string& theId)
 {
index 1a12945c955a508a0c5a81a82266aa2bea2b9725..11aa5a1ac0322392a09e89adb2f28c8655421989 100644 (file)
@@ -28,6 +28,7 @@
 #include <GeomAPI_Shape.h>
 #include <GeomAPI_AISObject.h>
 #include <GeomDataAPI_Point2D.h>
+#include <GeomDataAPI_Point2DArray.h>
 #include <GeomAlgoAPI_ShapeTools.h>
 
 #include <list>
@@ -49,7 +50,7 @@ void clearExpressions(FeaturePtr theFeature);
 std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin);
 
 /// Find all Coincident constraints referred to the feature or its attribute
-std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature);
+std::set<FeaturePtr> findCoincidentConstraints(const ObjectPtr& theObject);
 
 /// Finds lines coincident at point
 /// \param[in] theStartCoin coincidence feature
@@ -67,6 +68,13 @@ std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& th
 /// Find all points the given point is coincident to.
 std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint);
 
+/// Find all points the given point is coincident to.
+/// Returns GeomDataAPI_Point2D attribute and
+/// GeomDataAPI_Point2DArray with the index of coincident point.
+void findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint,
+                                 std::set<AttributePoint2DPtr>& thePoints,
+                                 std::map<AttributePoint2DArrayPtr, int>& thePointsInArray);
+
 void resetAttribute(SketchPlugin_Feature* theFeature, const std::string& theId);
 
 /// Create new constraint between given attributes