]> SALOME platform Git repositories - modules/shaper.git/blobdiff - src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp
Salome HOME
Add tools
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintCoincidence.cpp
index 0840c3714423d08c45d6a38435cb7d14d52bc8cd..e1242606ea82f1f6c216f3f46da63f628175c105 100644 (file)
@@ -2,6 +2,9 @@
 #include <SketchSolver_Error.h>
 #include <SketchSolver_Group.h>
 
+#include <SketchPlugin_Point.h>
+#include <GeomDataAPI_Point2D.h>
+
 #include <map>
 
 void SketchSolver_ConstraintCoincidence::getAttributes(
@@ -12,8 +15,20 @@ void SketchSolver_ConstraintCoincidence::getAttributes(
   if (!myErrorMsg.empty() || theAttributes[0] == SLVS_E_UNKNOWN)
     return;
 
-  if (theAttributes[1] != SLVS_E_UNKNOWN)
+  if (theAttributes[1] != SLVS_E_UNKNOWN) {
     myType = SLVS_C_POINTS_COINCIDENT;
+
+    // set coordinates of slave (second) point equal to the master (first) point
+    Slvs_Entity aFirst  = myStorage->getEntity(theAttributes[0]);
+    Slvs_Entity aSecond = myStorage->getEntity(theAttributes[1]);
+    for (int i = 0; i < 4; i++)
+      if (aFirst.param[i] != SLVS_E_UNKNOWN && aSecond.param[i] != SLVS_E_UNKNOWN) {
+        Slvs_Param aPar1 = myStorage->getParameter(aFirst.param[i]);
+        Slvs_Param aPar2 = myStorage->getParameter(aSecond.param[i]);
+        aPar2.val = aPar1.val;
+        myStorage->updateParameter(aPar2);
+      }
+  }
   else if (theAttributes[2] != SLVS_E_UNKNOWN) {
     // check the type of entity (line or circle)
     Slvs_Entity anEnt = myStorage->getEntity(theAttributes[2]);
@@ -48,10 +63,6 @@ std::list<ConstraintPtr> SketchSolver_ConstraintCoincidence::constraints() const
 bool SketchSolver_ConstraintCoincidence::isCoincide(
     std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const
 {
-  // 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())
@@ -112,6 +123,9 @@ void SketchSolver_ConstraintCoincidence::attach(
 Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint(
     Slvs_hEntity thePoint1, Slvs_hEntity thePoint2)
 {
+  if (thePoint1 == thePoint2)
+    return SLVS_E_UNKNOWN;
+
   bool hasDuplicated = myStorage->hasDuplicatedConstraint();
   Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
       SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), 0.0, thePoint1, thePoint2, 
@@ -126,34 +140,117 @@ Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint(
   return aNewID;
 }
 
+Slvs_hConstraint SketchSolver_ConstraintCoincidence::addPointOnEntity(
+    Slvs_hEntity thePoint, Slvs_hEntity theEntity)
+{
+  // Check the point is not coincident with boundaries of the entity
+  Slvs_Entity anEnt = myStorage->getEntity(theEntity);
+  int aPos = anEnt.type == SLVS_E_LINE_SEGMENT ? 0 : 1;
+  for (; anEnt.point[aPos] != SLVS_E_UNKNOWN; aPos++)
+    if (anEnt.point[aPos] == thePoint ||
+        myStorage->isCoincident(anEnt.point[aPos], thePoint))
+      return SLVS_E_UNKNOWN;
+
+  bool hasDuplicated = myStorage->hasDuplicatedConstraint();
+  Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
+  Slvs_hConstraint aType = anEnt.type == SLVS_E_LINE_SEGMENT ?
+      SLVS_C_PT_ON_LINE : SLVS_C_PT_ON_CIRCLE;
+  Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+      aType, myGroup->getWorkplaneId(), 0.0, aBaseCoincidence.ptA, SLVS_E_UNKNOWN,
+      theEntity, 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;
+}
+
 void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstraint)
 {
+  if (mySlvsConstraints.empty()) {
+    // This constraint is empty, rebuild it from scratch
+    myBaseConstraint = theConstraint;
+    process();
+    return;
+  }
+
   std::list<AttributePtr> anAttrList =
       theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
   std::list<AttributePtr>::iterator anIter = anAttrList.begin();
-  std::vector<Slvs_hEntity> anEntities;
+  std::vector<Slvs_hEntity> aPoints;
+  Slvs_hEntity anEntity = SLVS_E_UNKNOWN;
+  int anEntType;
   for (; anIter != anAttrList.end(); anIter++) {
+    Slvs_hEntity aPointID = SLVS_E_UNKNOWN;
     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
-    if (!aRefAttr || aRefAttr->isObject() ||
-        myAttributeMap.find(aRefAttr->attr()) != myAttributeMap.end())
+    if (!aRefAttr)
       continue;
-    int aType;
-    Slvs_hEntity anEntityID = myGroup->getAttributeId(aRefAttr->attr());
-    if (anEntityID == SLVS_E_UNKNOWN)
-      anEntityID = changeEntity(aRefAttr->attr(), aType);
-    anEntities.push_back(anEntityID);
-    myCoincidentPoints.insert(aRefAttr->attr());
+
+    AttributePtr aPointAttr;
+    if (aRefAttr->isObject()) {
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+      std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFeatFound = 
+          myFeatureMap.find(aFeature);
+      if (aFeatFound != myFeatureMap.end())
+        anEntity = aFeatFound->second;
+      else {
+        anEntity = myGroup->getFeatureId(aFeature);
+        if (anEntity == SLVS_E_UNKNOWN)
+          anEntity = changeEntity(aFeature, anEntType);
+        else {
+          myFeatureMap[aFeature] = anEntity;
+          // Obtain relations between attributes of the feature and SolveSpace entities
+          std::list<AttributePtr> anAttrList =
+              aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+          std::list<AttributePtr>::iterator anIt = anAttrList.begin();
+          for (; anIt != anAttrList.end(); ++anIt) {
+            Slvs_hEntity anAttrID = myGroup->getAttributeId(*anIt);
+            if (anAttrID != SLVS_E_UNKNOWN)
+              myAttributeMap[*anIt] = anAttrID;
+          }
+        }
+      }
+      // If the feature is a point, add it to the list of coincident points
+      if (aFeature->getKind() == SketchPlugin_Point::ID()) {
+        aPointID = anEntity;
+        anEntity = SLVS_E_UNKNOWN;
+        aPointAttr = aFeature->attribute(SketchPlugin_Point::COORD_ID());
+      }
+    } else {
+      aPointAttr = aRefAttr->attr();
+      std::map<AttributePtr, Slvs_hEntity>::const_iterator anAttrFound =
+          myAttributeMap.find(aPointAttr);
+      if (anAttrFound != myAttributeMap.end())
+        aPointID = anAttrFound->second;
+      else {
+        aPointID = myGroup->getAttributeId(aPointAttr);
+        if (aPointID == SLVS_E_UNKNOWN)
+          aPointID = changeEntity(aPointAttr, anEntType);
+      }
+    }
+
+    if (aPointAttr) { // the point is found
+      aPoints.push_back(aPointID);
+      myCoincidentPoints.insert(aPointAttr);
+      myAttributeMap[aPointAttr] = aPointID;
+    }
   }
 
   Slvs_hConstraint aNewConstr = SLVS_E_UNKNOWN;
-  std::vector<Slvs_hEntity>::iterator anEntIter = anEntities.begin();
-  if (mySlvsConstraints.empty()) {
-    aNewConstr = addConstraint(*anEntIter, *(anEntIter + 1));
-    anEntIter += 2;
+  if (anEntity != SLVS_E_UNKNOWN)
+    aNewConstr = addPointOnEntity(aPoints.front(), anEntity);
+  else { // coincidence between two points
+    Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
+    std::vector<Slvs_hEntity>::const_iterator aPtIter = aPoints.begin();
+    for (; aPtIter != aPoints.end(); aPtIter++) {
+      Slvs_hConstraint aC = addConstraint(aBaseCoincidence.ptA, *aPtIter);
+      if (aC != SLVS_E_UNKNOWN)
+        aNewConstr = aC;
+    }
   }
-  Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
-  for (; anEntIter != anEntities.end(); anEntIter++)
-    aNewConstr = addConstraint(aBaseCoincidence.ptA, *anEntIter);
   myExtraCoincidence[theConstraint] = aNewConstr;
 }