Salome HOME
Issues #2150 and #2151: Frequently appeared "Conflicting constraints" message for...
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_UpdateCoincidence.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);
 }