Salome HOME
Issue #604 Creation of an unexpected line in the Sketcher
[modules/shaper.git] / src / SketchSolver / SketchSolver_Group.cpp
index 9a4623428c65f1b639ee05aeae935ed18ccce43e..11f334f51922cf00be3712b150d2560a9f06f34a 100644 (file)
@@ -180,7 +180,8 @@ bool SketchSolver_Group::changeConstraint(
   if (!theConstraint)
     return false;
 
-  if (myConstraints.find(theConstraint) == myConstraints.end()) {
+  bool isNewConstraint = myConstraints.find(theConstraint) == myConstraints.end();
+  if (isNewConstraint) {
     // Add constraint to the current group
     SolverConstraintPtr aConstraint =
         SketchSolver_Builder::getInstance()->createConstraint(theConstraint);
@@ -216,7 +217,7 @@ bool SketchSolver_Group::changeConstraint(
     myConstraints[theConstraint]->update();
 
   // Fix base features for fillet
-  if (theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) {
+  if (isNewConstraint && theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) {
     std::list<AttributePtr> anAttrList =
         theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
     std::list<AttributePtr>::iterator anAttrIter = anAttrList.begin();
@@ -235,12 +236,23 @@ bool SketchSolver_Group::changeConstraint(
       setTemporary(aConstraint);
     }
   }
-  //// Fix base features for mirror
-  //if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
-  //  AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-  //      theConstraint->attribute(SketchPlugin_ConstraintMirror::ENTITY_B()));
-  //  fixFeaturesList(aRefList);
-  //}
+  // Fix mirror line
+  if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
+    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+        theConstraint->attribute(SketchPlugin_ConstraintMirror::ENTITY_A()));
+    if (aRefAttr && aRefAttr->isObject()) {
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+      if (aFeature) {
+        SolverConstraintPtr aConstraint =
+            SketchSolver_Builder::getInstance()->createRigidConstraint(aFeature);
+        if (aConstraint) {
+          aConstraint->setGroup(this);
+          aConstraint->setStorage(myStorage);
+          setTemporary(aConstraint);
+        }
+      }
+    }
+  }
 
   if (!myFeatureStorage)
     myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage);
@@ -259,7 +271,8 @@ bool SketchSolver_Group::updateFeature(std::shared_ptr<SketchPlugin_Feature> the
   std::set<ConstraintPtr>::iterator aCIter = aConstraints.begin();
   for (; aCIter != aConstraints.end(); aCIter++) {
     ConstraintConstraintMap::iterator aSolConIter = myConstraints.find(*aCIter);
-    if (aSolConIter == myConstraints.end())
+    if (aSolConIter == myConstraints.end() || !aSolConIter->first->data() ||
+        !aSolConIter->first->data()->isValid())
       continue;
     myFeatureStorage->changeFeature(theFeature, aSolConIter->first);
     aSolConIter->second->addFeature(theFeature);
@@ -270,16 +283,17 @@ bool SketchSolver_Group::updateFeature(std::shared_ptr<SketchPlugin_Feature> the
 
 void SketchSolver_Group::moveFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
 {
-  updateFeature(theFeature);
-  // Temporary rigid constraint
+  // Firstly, create temporary rigid constraint
   SolverConstraintPtr aConstraint =
-      SketchSolver_Builder::getInstance()->createRigidConstraint(theFeature);
+      SketchSolver_Builder::getInstance()->createMovementConstraint(theFeature);
   if (!aConstraint)
     return;
   aConstraint->setGroup(this);
   aConstraint->setStorage(myStorage);
   if (aConstraint->error().empty())
     setTemporary(aConstraint);
+  // Secondly, update the feature
+  updateFeature(theFeature);
 }
 
 // ============================================================================
@@ -407,7 +421,20 @@ bool SketchSolver_Group::resolveConstraints()
 
     int aResult = SLVS_RESULT_OKAY;
     try {
-      aResult = myConstrSolver.solve();
+      if (myStorage->hasDuplicatedConstraint())
+        aResult = SLVS_RESULT_INCONSISTENT;
+      else {
+        // To avoid overconstraint situation, we will remove temporary constraints one-by-one
+        // and try to find the case without overconstraint
+        int aNbTemp = myStorage->numberTemporary();
+        while (true) {
+          aResult = myConstrSolver.solve();
+          if (aResult == SLVS_RESULT_OKAY || aNbTemp <= 0)
+            break;
+          aNbTemp = myStorage->deleteTemporaryConstraint();
+          myStorage->initializeSolver(myConstrSolver);
+        }
+      }
     } catch (...) {
       Events_Error::send(SketchSolver_Error::SOLVESPACE_CRASH(), this);
       return false;
@@ -550,7 +577,8 @@ bool SketchSolver_Group::isConsistent()
 void SketchSolver_Group::removeTemporaryConstraints()
 {
   myTempConstraints.clear();
-  myStorage->removeTemporaryConstraints();
+  while (myStorage->numberTemporary())
+    myStorage->deleteTemporaryConstraint();
   // Clean lists of removed entities in the storage
   std::set<Slvs_hParam> aRemPar;
   std::set<Slvs_hEntity> aRemEnt;