Salome HOME
Issues #2150 and #2151: Frequently appeared "Conflicting constraints" message for...
authorazv <azv@opencascade.com>
Thu, 4 May 2017 08:03:03 +0000 (11:03 +0300)
committerazv <azv@opencascade.com>
Thu, 4 May 2017 08:03:03 +0000 (11:03 +0300)
Improve processing of multi-coincidence by placing coincident points into different groups. Since now it is taken into account only the points to form the group (on the other works, the feature cannot be an initializer of the coincidence group).

src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.h
src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp
src/SketchSolver/SketchSolver_ConstraintMiddle.cpp

index 1b7252e2bf17abf6fb2ef1ebe50ba6c1232b7fb1..4ea868a110ee423e1700f9a5dac6c12509db3ee2 100644 (file)
@@ -52,39 +52,38 @@ static bool hasAnotherExternalPoint(const std::set<EntityWrapperPtr>& theCoincid
   return false;
 }
 
-bool PlaneGCSSolver_UpdateCoincidence::checkCoincidence(
+bool PlaneGCSSolver_UpdateCoincidence::addCoincidence(
     const EntityWrapperPtr& theEntity1,
     const EntityWrapperPtr& theEntity2)
 {
   bool isAccepted = true;
-
-  std::list<CoincidentEntities>::iterator anIt = myCoincident.begin();
-  std::list<CoincidentEntities>::iterator
-      aFound[2] = {myCoincident.end(), myCoincident.end()};
-
-  for (; anIt != myCoincident.end(); ++anIt) {
-    if (anIt->isExist(theEntity1))
-      aFound[0] = anIt;
-    if (anIt->isExist(theEntity2))
-      aFound[1] = anIt;
-    if (aFound[0] != myCoincident.end() && aFound[1] != myCoincident.end())
-      break;
-  }
+  std::list<CoincidentEntities>::iterator aFound[2] = {
+    findGroupOfCoincidence(theEntity1),
+    findGroupOfCoincidence(theEntity2)
+  };
 
   if (aFound[0] == myCoincident.end() && aFound[1] == myCoincident.end()) {
     // new group of coincidence
     myCoincident.push_back(CoincidentEntities(theEntity1, theEntity2));
-  } else if (aFound[0] == aFound[1]) // same group => already coincident
+  } else if (aFound[0] == myCoincident.end()) {
+    isAccepted = addToGroupOfCoincidence(*aFound[1], theEntity1);
+  } else if (aFound[1] == myCoincident.end()) {
+    isAccepted = addToGroupOfCoincidence(*aFound[0], theEntity2);
+  } else if (aFound[0] == aFound[1]) { // same group => already coincident
     isAccepted = false;
-  else {
-    if (aFound[0] == myCoincident.end())
-      isAccepted = aFound[1]->isNewCoincidence(theEntity2, theEntity1);
-    else if (aFound[1] == myCoincident.end())
-      isAccepted = aFound[0]->isNewCoincidence(theEntity1, theEntity2);
-    else { // merge two groups
-      isAccepted = aFound[0]->isNewCoincidence(theEntity1, *(aFound[1]), theEntity2);
-      myCoincident.erase(aFound[1]);
+  } else { // merge two groups
+    EntityWrapperPtr anEntityToAdd = theEntity1;
+    if (theEntity1->isExternal()) { // swap found groups;
+      anEntityToAdd = theEntity2;
+      std::list<CoincidentEntities>::iterator aTempIt = aFound[0];
+      aFound[0] = aFound[1];
+      aFound[1] = aTempIt;
     }
+
+    aFound[1]->remove(anEntityToAdd);
+    aFound[0]->merge(*aFound[1]);
+    isAccepted = aFound[0]->add(anEntityToAdd);
+    myCoincident.erase(aFound[1]);
   }
 
   return isAccepted;
@@ -94,11 +93,7 @@ bool PlaneGCSSolver_UpdateCoincidence::isPointOnEntity(
     const EntityWrapperPtr& thePoint,
     const EntityWrapperPtr& theEntity)
 {
-  std::list<CoincidentEntities>::iterator anIt = myCoincident.begin();
-  for (; anIt != myCoincident.end(); ++anIt)
-    if (anIt->isExist(thePoint))
-      break;
-
+  std::list<CoincidentEntities>::iterator anIt = findGroupOfCoincidence(thePoint);
   if (anIt == myCoincident.end())
     return false;
 
@@ -113,156 +108,119 @@ bool PlaneGCSSolver_UpdateCoincidence::isPointOnEntity(
   return false;
 }
 
+std::list<PlaneGCSSolver_UpdateCoincidence::CoincidentEntities>::iterator
+  PlaneGCSSolver_UpdateCoincidence::findGroupOfCoincidence(const EntityWrapperPtr& theEntity)
+{
+  if (theEntity->type() != ENTITY_POINT)
+    return myCoincident.end();
 
+  std::list<CoincidentEntities>::iterator aFound = myCoincident.begin();
+  for (; aFound != myCoincident.end(); ++aFound)
+    if (aFound->isExist(theEntity))
+      break;
+  return aFound;
+}
 
+bool PlaneGCSSolver_UpdateCoincidence::addToGroupOfCoincidence(
+    CoincidentEntities& theGroup, const EntityWrapperPtr& theEntity)
+{
+  if (theGroup.isExist(theEntity))
+    return false;
 
+  theGroup.add(theEntity);
+  return true;
+}
 
-PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::CoincidentEntities(
-    const EntityWrapperPtr& theEntity1,
-    const EntityWrapperPtr& theEntity2)
+
+
+
+
+static const GCS::Point& toPoint(const EntityWrapperPtr& theEntity)
 {
-  if (theEntity1->isExternal() && theEntity2->isExternal()) {
-    myExternalAndConnected[theEntity1] = std::set<EntityWrapperPtr>();
-    myExternalAndConnected[theEntity2] = std::set<EntityWrapperPtr>();
-  } else if (theEntity1->isExternal())
-    myExternalAndConnected[theEntity1].insert(theEntity2);
-  else if (theEntity2->isExternal())
-    myExternalAndConnected[theEntity2].insert(theEntity1);
-  else {
-    std::set<EntityWrapperPtr> aGroup;
-    aGroup.insert(theEntity1);
-    aGroup.insert(theEntity2);
-    myExternalAndConnected[EntityWrapperPtr()] = aGroup;
-  }
+  PointWrapperPtr aPoint = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
+  return *(aPoint->point());
 }
 
-bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::hasExternal() const
+static double squareDistance(const GCS::Point& thePoint1, const GCS::Point& thePoint2)
 {
-  return myExternalAndConnected.size() != 1 ||
-         myExternalAndConnected.find(EntityWrapperPtr()) == myExternalAndConnected.end();
+  double dx = *thePoint1.x - *thePoint2.x;
+  double dy = *thePoint1.y - *thePoint2.y;
+  return dx * dx + dy * dy;
 }
 
-bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist(
-    const EntityWrapperPtr& theEntity) const
+static bool hasSamePoint(const std::set<EntityWrapperPtr>& theList, const GCS::Point& thePoint)
 {
-  std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::const_iterator
-      anIt = myExternalAndConnected.begin();
-  for (; anIt != myExternalAndConnected.end(); ++anIt)
-    if (anIt->first == theEntity ||
-        anIt->second.find(theEntity) != anIt->second.end())
+  std::set<EntityWrapperPtr>::const_iterator anIt = theList.begin();
+  for (; anIt != theList.end(); ++anIt)
+    if (squareDistance(thePoint, toPoint(*anIt)) < 1.e-14)
       return true;
   return false;
 }
 
-static bool isEqual(const GCS::Point& thePoint1, const GCS::Point& thePoint2)
+static bool hasSamePoint(const std::set<EntityWrapperPtr>& theList, const EntityWrapperPtr& thePoint)
 {
-  return thePoint1.x == thePoint2.x && thePoint1.y == thePoint2.y;
+  return hasSamePoint(theList, toPoint(thePoint));
 }
 
-bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist(
-    const GCS::Point& thePoint) const
-{
-  std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::const_iterator
-      anIt = myExternalAndConnected.begin();
-  for (; anIt != myExternalAndConnected.end(); ++anIt) {
-    if (anIt->first && anIt->first->type() == ENTITY_POINT) {
-      const GCSPointPtr& aPoint =
-          std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->first)->point();
-      if (isEqual(*aPoint, thePoint))
-        return true;
-    }
 
-    std::set<EntityWrapperPtr>::const_iterator anEntIt = anIt->second.begin();
-    for (; anEntIt != anIt->second.end(); ++anEntIt)
-      if ((*anEntIt)->type() == ENTITY_POINT) {
-        const GCSPointPtr& aPoint =
-            std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anEntIt)->point();
-        if (isEqual(*aPoint, thePoint))
-          return true;
-      }
-  }
-  return false;
+PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::CoincidentEntities(
+    const EntityWrapperPtr& theEntity1,
+    const EntityWrapperPtr& theEntity2)
+{
+  add(theEntity1);
+  add(theEntity2);
 }
 
-bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isNewCoincidence(
-    const EntityWrapperPtr& theEntityExist,
-    const EntityWrapperPtr& theOtherEntity)
+bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::add(
+    const EntityWrapperPtr& theEntity)
 {
-  if (theOtherEntity->isExternal()) {
-    if (hasExternal()) {
-      if (myExternalAndConnected.find(theOtherEntity) == myExternalAndConnected.end())
-        myExternalAndConnected[theOtherEntity] = std::set<EntityWrapperPtr>();
-      // check whether all external entities are edges
-      bool isNewCoinc = true;
-      std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::iterator
-          anIt = myExternalAndConnected.begin();
-      for (; anIt != myExternalAndConnected.end() && isNewCoinc; ++anIt)
-        isNewCoinc = (anIt->first->type() != ENTITY_POINT);
-      return isNewCoinc;
-    } else {
-      myExternalAndConnected[theOtherEntity] = myExternalAndConnected[EntityWrapperPtr()];
-      myExternalAndConnected.erase(EntityWrapperPtr());
-      return true;
-    }
-  }
-
-  if (theEntityExist->isExternal()) {
-    myExternalAndConnected[theEntityExist].insert(theOtherEntity);
-    return true;
-  }
+  bool isAdded = true;
+  if (theEntity->type() == ENTITY_POINT) {
+    if (theEntity->isExternal()) {
+      isAdded = !hasSamePoint(myExternalPoints, theEntity);
+      myExternalPoints.insert(theEntity);
+    } else
+      myPoints.insert(theEntity);
+  } else
+    myFeatures.insert(theEntity);
+  return isAdded;
+}
 
-  std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::iterator
-      anIt = myExternalAndConnected.begin();
-  for (; anIt != myExternalAndConnected.end(); ++anIt)
-    if (anIt->second.find(theEntityExist) != anIt->second.end()) {
-      anIt->second.insert(theOtherEntity);
-      break;
-    }
-  return true;
+void PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::remove(
+    const EntityWrapperPtr& theEntity)
+{
+  if (theEntity->type() == ENTITY_POINT) {
+    if (theEntity->isExternal())
+      myExternalPoints.erase(theEntity);
+    else
+      myPoints.erase(theEntity);
+  } else
+    myFeatures.erase(theEntity);
 }
 
-bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isNewCoincidence(
-    const EntityWrapperPtr&   theEntityExist,
-    const CoincidentEntities& theOtherGroup,
-    const EntityWrapperPtr&   theEntityInOtherGroup)
+void PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::merge(
+    const CoincidentEntities& theOther)
 {
-  bool hasExt[2] = {hasExternal(), theOtherGroup.hasExternal()};
-  if (hasExt[0] && hasExt[1]) {
-    myExternalAndConnected.insert(theOtherGroup.myExternalAndConnected.begin(),
-                                  theOtherGroup.myExternalAndConnected.end());
-    return false;
-  } else if (!hasExt[0] && !hasExt[1]) {
-    std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::const_iterator
-        aFound = theOtherGroup.myExternalAndConnected.find(EntityWrapperPtr());
+  myExternalPoints.insert(theOther.myExternalPoints.begin(), theOther.myExternalPoints.end());
+  myPoints.insert(theOther.myPoints.begin(), theOther.myPoints.end());
+  myFeatures.insert(theOther.myFeatures.begin(), theOther.myFeatures.end());
+}
 
-    myExternalAndConnected[EntityWrapperPtr()].insert(
-        aFound->second.begin(), aFound->second.end());
-    return true;
-  } else {
-    std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> > aSource, aDest;
-    EntityWrapperPtr aTarget;
-    if (hasExt[0]) {
-      aDest = myExternalAndConnected;
-      aSource = theOtherGroup.myExternalAndConnected;
-      aTarget = theEntityExist;
-    } else {
-      aSource = myExternalAndConnected;
-      aDest = theOtherGroup.myExternalAndConnected;
-      aTarget = theEntityInOtherGroup;
-    }
+bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist(
+    const EntityWrapperPtr& theEntity) const
+{
+  if (theEntity->type() == ENTITY_POINT) {
+    if (theEntity->isExternal())
+      return myExternalPoints.find(theEntity) != myExternalPoints.end();
+    else
+      return myPoints.find(theEntity) != myPoints.end();
+  }
 
-    std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::const_iterator
-        aFound = aSource.find(EntityWrapperPtr());
+  return myFeatures.find(theEntity) != myFeatures.end();
+}
 
-    std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::iterator anIt = aDest.begin();
-    for (; anIt != aDest.end(); ++anIt)
-      if (anIt->first == aTarget ||
-          anIt->second.find(aTarget) != anIt->second.end()) {
-        anIt->second.insert(aFound->second.begin(), aFound->second.end());
-        break;
-      }
-    return true;
-  }
-  // impossible case
-  return false;
+bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist(
+    const GCS::Point& thePoint) const
+{
+  return hasSamePoint(myExternalPoints, thePoint) || hasSamePoint(myPoints, thePoint);
 }
index 558756492fa68c7406ad86e8ab59d57bf65dd04b..d5acf494af430a2776bb1750a644678d0e3f5773 100644 (file)
@@ -43,9 +43,9 @@ public:
   /// \brief Send notification about update of the feature to all interested
   virtual void update(const FeaturePtr& theFeature);
 
-  /// \brief Verifies the entities are not coincident yet
-  /// \return \c true if the entities does not coincident
-  bool checkCoincidence(const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2);
+  /// \brief Set coincidence between two given entities
+  /// \return \c true if the entities does not coincident yet
+  bool addCoincidence(const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2);
 
   /// \brief Verifies the point is coincident to the feature
   /// \return \c true if the point is on the feature
@@ -63,21 +63,31 @@ private:
     bool isExist(const EntityWrapperPtr& theEntity) const;
     /// Verify the point is already in the list
     bool isExist(const GCS::Point& thePoint) const;
-    /// Check the coincidence is not in list yet
-    bool isNewCoincidence(const EntityWrapperPtr& theEntityExist,
-                          const EntityWrapperPtr& theOtherEntity);
-    bool isNewCoincidence(const EntityWrapperPtr& theEntityExist,
-                          const CoincidentEntities& theOtherGroup,
-                          const EntityWrapperPtr& theEntityInOtherGroup);
 
-  private:
-    bool hasExternal() const;
+    /// Add entity to group
+    bool add(const EntityWrapperPtr& theEntity);
+
+    /// Remove entity from group
+    void remove(const EntityWrapperPtr& theEntity);
+
+    /// Merge two groups
+    void merge(const CoincidentEntities& theOther);
 
   private:
-    /// external entity and set of entities connected to it
-    std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> > myExternalAndConnected;
+    std::set<EntityWrapperPtr> myPoints; ///< coincident points
+    std::set<EntityWrapperPtr> myExternalPoints; //< external points coincident to other points
+    std::set<EntityWrapperPtr> myFeatures; ///< other entities containing points
   };
 
+  /// \brief Search the group of coincidences containing given entity.
+  ///        Searches points only.
+  std::list<CoincidentEntities>::iterator findGroupOfCoincidence(const EntityWrapperPtr& theEntity);
+
+  /// \brief Add entity to group of coincidences
+  /// \reutrn \c true if the entity is added, thus the coincidence is new
+  bool addToGroupOfCoincidence(CoincidentEntities& theGroup, const EntityWrapperPtr& theEntity);
+
+private:
   std::list<CoincidentEntities> myCoincident; ///< list of coincidences
 };
 
index 81130989bb52931c81b465d2450e73f102124fb0..4c589919a18b6834efd5bc3c59e049e768d11226 100644 (file)
@@ -99,7 +99,7 @@ void SketchSolver_ConstraintCoincidence::notify(const FeaturePtr&      theFeatur
 {
   PlaneGCSSolver_UpdateCoincidence* anUpdater =
       static_cast<PlaneGCSSolver_UpdateCoincidence*>(theUpdater);
-  bool isAccepted = anUpdater->checkCoincidence(myAttributes.front(), myAttributes.back());
+  bool isAccepted = anUpdater->addCoincidence(myAttributes.front(), myAttributes.back());
 
   // additionally check the point is coincident to extremity of coincident feature
   if (myFeatureExtremities[0] && myFeatureExtremities[1]) {
index 6680004c8f633395b340b231f0ca80381b6c4976..e5388276c4b61db0b069f30d6a9f2aab631d66d5 100644 (file)
@@ -16,7 +16,7 @@ void SketchSolver_ConstraintMiddle::notify(const FeaturePtr&      theFeature,
 {
   PlaneGCSSolver_UpdateCoincidence* anUpdater =
       static_cast<PlaneGCSSolver_UpdateCoincidence*>(theUpdater);
-  bool isAccepted = anUpdater->checkCoincidence(myAttributes.front(), myAttributes.back());
+  bool isAccepted = anUpdater->addCoincidence(myAttributes.front(), myAttributes.back());
   if (isAccepted) {
     if (!myInSolver) {
       myInSolver = true;