Salome HOME
Update behavior of calculation of Multi-Translation constraint
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintCoincidence.cpp
index 52dc868babdf4facc6a676da3c473e1e66871d0b..5144f14fc6bcf6fce4d8a7e266abcb16c376b254 100644 (file)
@@ -4,6 +4,30 @@
 
 #include <map>
 
+void SketchSolver_ConstraintCoincidence::getAttributes(
+    double& theValue,
+    std::vector<Slvs_hEntity>& theAttributes)
+{
+  SketchSolver_Constraint::getAttributes(theValue, theAttributes);
+  if (!myErrorMsg.empty() || theAttributes[0] == SLVS_E_UNKNOWN)
+    return;
+
+  if (theAttributes[1] != SLVS_E_UNKNOWN)
+    myType = SLVS_C_POINTS_COINCIDENT;
+  else if (theAttributes[2] != SLVS_E_UNKNOWN) {
+    // check the type of entity (line or circle)
+    Slvs_Entity anEnt = myStorage->getEntity(theAttributes[2]);
+    if (anEnt.type == SLVS_E_LINE_SEGMENT)
+      myType = SLVS_C_PT_ON_LINE;
+    else if (anEnt.type == SLVS_E_CIRCLE || anEnt.type == SLVS_E_ARC_OF_CIRCLE)
+      myType = SLVS_C_PT_ON_CIRCLE;
+    else
+      myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+  } else
+    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+}
+
+
 bool SketchSolver_ConstraintCoincidence::hasConstraint(ConstraintPtr theConstraint) const
 {
   if (myBaseConstraint == theConstraint)
@@ -28,13 +52,13 @@ std::list<ConstraintPtr> SketchSolver_ConstraintCoincidence::constraints() const
 bool SketchSolver_ConstraintCoincidence::isCoincide(
     std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const
 {
-  std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFeatIter = myFeatureMap.begin();
-  for (; aFeatIter != myFeatureMap.end(); aFeatIter++)
-    if (theConstraint->myFeatureMap.find(aFeatIter->first) != theConstraint->myFeatureMap.end())
-      return true;
-  std::map<AttributePtr, Slvs_hEntity>::const_iterator anAttrIter = myAttributeMap.begin();
-  for (; anAttrIter != myAttributeMap.end(); anAttrIter++)
-    if (theConstraint->myAttributeMap.find(anAttrIter->first) != theConstraint->myAttributeMap.end())
+  // Multi-coincidence allowed for two points only
+  if (getType() != theConstraint->getType() || getType() != SLVS_C_POINTS_COINCIDENT)
+    return false;
+
+  std::set<AttributePtr>::const_iterator anAttrIter = theConstraint->myCoincidentPoints.begin();
+  for (; anAttrIter != theConstraint->myCoincidentPoints.end(); anAttrIter++)
+    if (myCoincidentPoints.find(*anAttrIter) != myCoincidentPoints.end())
       return true;
   return false;
 }
@@ -43,7 +67,6 @@ void SketchSolver_ConstraintCoincidence::attach(
     std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint)
 {
   cleanErrorMsg();
-  Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
   // Remove constraints from theConstraint
   std::vector<Slvs_hConstraint>::iterator aCIter = theConstraint->mySlvsConstraints.begin();
   for (; aCIter != theConstraint->mySlvsConstraints.end(); aCIter++)
@@ -72,10 +95,16 @@ void SketchSolver_ConstraintCoincidence::attach(
 Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint(
     Slvs_hEntity thePoint1, Slvs_hEntity thePoint2)
 {
+  bool hasDuplicated = myStorage->hasDuplicatedConstraint();
   Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
       SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), 0.0, thePoint1, thePoint2, 
       SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
   Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
+  if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) {
+    // the duplicated constraint appears
+    myStorage->removeConstraint(aNewID);
+    return SLVS_E_UNKNOWN;
+  }
   mySlvsConstraints.push_back(aNewID);
   return aNewID;
 }
@@ -96,16 +125,37 @@ void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstrai
     if (anEntityID == SLVS_E_UNKNOWN)
       anEntityID = changeEntity(aRefAttr->attr(), aType);
     anEntities.push_back(anEntityID);
+    myCoincidentPoints.insert(aRefAttr->attr());
   }
 
-  Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
   Slvs_hConstraint aNewConstr = SLVS_E_UNKNOWN;
   std::vector<Slvs_hEntity>::iterator anEntIter = anEntities.begin();
+  if (mySlvsConstraints.empty()) {
+    aNewConstr = addConstraint(*anEntIter, *(anEntIter + 1));
+    anEntIter += 2;
+  }
+  Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
   for (; anEntIter != anEntities.end(); anEntIter++)
     aNewConstr = addConstraint(aBaseCoincidence.ptA, *anEntIter);
   myExtraCoincidence[aNewConstr] = theConstraint;
 }
 
+void SketchSolver_ConstraintCoincidence::process()
+{
+  SketchSolver_Constraint::process();
+
+  // Fill the list of coincident points
+  std::list<AttributePtr> anAttrList =
+      myBaseConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
+  std::list<AttributePtr>::iterator anIt = anAttrList.begin();
+  for (; anIt != anAttrList.end(); anIt++) {
+    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIt);
+    if (!aRefAttr || aRefAttr->isObject())
+      continue;
+    myCoincidentPoints.insert(aRefAttr->attr());
+  }
+}
+
 bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
 {
   cleanErrorMsg();
@@ -121,8 +171,18 @@ bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
         break;
     if (aPos >= (int)myExtraCoincidence.size())
       return false; // there is no constraint, which is specified to remove
-    else
+    else {
+      bool isEmpty = anExtraIt->first == SLVS_E_UNKNOWN;
+      if (!isEmpty) {
+        for (aPos = 0; aPos < (int)mySlvsConstraints.size(); aPos++)
+          if (mySlvsConstraints[aPos] == anExtraIt->first)
+            break;
+        aPos -= 1;
+      }
       myExtraCoincidence.erase(anExtraIt);
+      if (isEmpty)
+        return false;
+    }
   }
 
   bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints[aPos+1]);
@@ -148,18 +208,21 @@ bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
       anExtraIt++;
     }
     // Find first non-extra conststraint
+    anExtraIt = myExtraCoincidence.begin();
     while (anExtraIt != myExtraCoincidence.end() && anExtraIt->first == SLVS_E_UNKNOWN)
       anExtraIt++;
     if (anExtraIt != myExtraCoincidence.end()) {
       // Need to specify another base coincidence constraint
       myBaseConstraint = anExtraIt->second;
       myExtraCoincidence.erase(anExtraIt);
-      std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
-      Slvs_Constraint aBase = myStorage->getConstraint(*aCIter);
-      for (++aCIter; aCIter != mySlvsConstraints.end(); aCIter++) {
-        Slvs_Constraint aConstr = myStorage->getConstraint(*aCIter);
-        aConstr.ptA = aBase.ptA;
-        myStorage->updateConstraint(aConstr);
+      if (mySlvsConstraints.empty()) {
+        std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
+        Slvs_Constraint aBase = myStorage->getConstraint(*aCIter);
+        for (++aCIter; aCIter != mySlvsConstraints.end(); aCIter++) {
+          Slvs_Constraint aConstr = myStorage->getConstraint(*aCIter);
+          aConstr.ptA = aBase.ptA;
+          myStorage->updateConstraint(aConstr);
+        }
       }
     }
   }
@@ -172,6 +235,7 @@ bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
   while (anAttrIter != myAttributeMap.end()) {
     if (anEntRemoved.find(anAttrIter->second) != anEntRemoved.end()) {
       std::map<AttributePtr, Slvs_hEntity>::iterator aTempIt = anAttrIter++;
+      myCoincidentPoints.erase(aTempIt->first);
       myAttributeMap.erase(aTempIt);
       continue;
     }
@@ -198,6 +262,6 @@ bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
     }
     anExtraIt++;
   }
-  return isFullyRemoved;
+  return mySlvsConstraints.empty();
 }