Salome HOME
Merge branch 'task_5_2_4' into CEA_2019
[modules/shaper.git] / src / SketchSolver / SketchSolver_Group.cpp
index 93bbfa69d406369bea25307cbe7a7ea0eb3d498e..84d701e2b2c10c9b1f7d77566a1c3a64638e5129 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 //
 // You should have received a copy of the GNU Lesser General Public
 // License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-// See http://www.salome-platform.org/ or
-// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
 #include "SketchSolver_Group.h"
@@ -74,14 +73,14 @@ static void sendMessage(const char* theMessageName,
 // ========================================================
 
 SketchSolver_Group::SketchSolver_Group(const CompositeFeaturePtr& theWorkplane)
-  : mySketch(theWorkplane),
-    myPrevResult(PlaneGCSSolver_Solver::STATUS_UNKNOWN),
-    myDOF(0),
+  : myPrevResult(PlaneGCSSolver_Solver::STATUS_UNKNOWN),
+    myDOF(-1),
     myIsEventsBlocked(false),
     myMultiConstraintUpdateStack(0)
 {
   mySketchSolver = SolverPtr(new PlaneGCSSolver_Solver);
   myStorage = StoragePtr(new PlaneGCSSolver_Storage(mySketchSolver));
+  updateSketch(theWorkplane);
 }
 
 SketchSolver_Group::~SketchSolver_Group()
@@ -124,6 +123,34 @@ bool SketchSolver_Group::changeConstraint(
   return true;
 }
 
+bool SketchSolver_Group::updateSketch(CompositeFeaturePtr theSketch)
+{
+  static const double THE_TOLERANCE = 1.e-7;
+  bool isChanged = theSketch != mySketch;
+
+  AttributePointPtr anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
+      theSketch->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
+  AttributeDirPtr aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+      theSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
+  AttributeDirPtr aDirX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+      theSketch->attribute(SketchPlugin_Sketch::DIRX_ID()));
+
+  isChanged = isChanged
+      || (mySketchOrigin && anOrigin && anOrigin->pnt()->distance(mySketchOrigin) > THE_TOLERANCE)
+      || (mySketchNormal && aNorm && aNorm->xyz()->distance(mySketchNormal->xyz()) > THE_TOLERANCE)
+      || (mySketchXDir && aDirX && aDirX->xyz()->distance(mySketchXDir->xyz()) > THE_TOLERANCE);
+
+  if (isChanged) {
+    mySketch = theSketch;
+    mySketchOrigin = anOrigin->pnt();
+    mySketchNormal = aNorm->dir();
+    mySketchXDir = aDirX->dir();
+
+    myStorage->notify(theSketch);
+  }
+  return true;
+}
+
 bool SketchSolver_Group::updateFeature(FeaturePtr theFeature)
 {
   return myStorage->update(theFeature);
@@ -152,6 +179,7 @@ static SolverConstraintPtr move(StoragePtr theStorage,
     SolverConstraintPtr(aConstraint)->process(theStorage, theEventsBlocked);
     if (aConstraint->error().empty()) {
       aConstraint->startPoint(theFrom);
+      theStorage->adjustParametrizationOfArcs();
       theSketchSolver->initialize();
       aConstraint->moveTo(theTo);
       theStorage->setNeedToResolve(true);
@@ -209,14 +237,19 @@ bool SketchSolver_Group::resolveConstraints()
 
     PlaneGCSSolver_Solver::SolveStatus aResult = PlaneGCSSolver_Solver::STATUS_OK;
     try {
-      if (!isGroupEmpty)
+      if (!isGroupEmpty) {
+        myStorage->adjustParametrizationOfArcs();
         aResult = mySketchSolver->solve();
+      }
       if (aResult == PlaneGCSSolver_Solver::STATUS_FAILED &&
           !myTempConstraints.empty()) {
         mySketchSolver->undo();
         removeTemporaryConstraints();
         aResult = mySketchSolver->solve();
       }
+      // check degenerated geometry after constraints resolving
+      if (aResult == PlaneGCSSolver_Solver::STATUS_OK)
+        aResult = myStorage->checkDegeneratedGeometry();
     } catch (...) {
       getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())
         ->setValue(SketchSolver_Error::SOLVESPACE_CRASH());
@@ -262,8 +295,10 @@ bool SketchSolver_Group::resolveConstraints()
       mySketchSolver->undo();
       if (!myConstraints.empty()) {
         // the error message should be changed before sending the message
-        getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())
-          ->setValue(SketchSolver_Error::CONSTRAINTS());
+        const std::string& aErrorMsg = aResult == PlaneGCSSolver_Solver::STATUS_DEGENERATED ?
+                                       SketchSolver_Error::DEGENERATED_GEOMETRY() :
+                                       SketchSolver_Error::CONSTRAINTS();
+        getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(aErrorMsg);
         if (myPrevResult != aResult ||
             myPrevResult == PlaneGCSSolver_Solver::STATUS_UNKNOWN ||
             myPrevResult == PlaneGCSSolver_Solver::STATUS_FAILED) {
@@ -285,10 +320,25 @@ bool SketchSolver_Group::resolveConstraints()
           myPrevResult = aResult;
         }
       }
+
+      // show degrees of freedom only if the degenerated geometry appears
+      if (aResult == PlaneGCSSolver_Solver::STATUS_DEGENERATED)
+        computeDoF();
+    }
+
+  }
+  else if (isGroupEmpty && isWorkplaneValid()) {
+    // clear error related to previously degenerated entities
+    if (myPrevResult == PlaneGCSSolver_Solver::STATUS_DEGENERATED) {
+      getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue("");
+      myPrevResult = PlaneGCSSolver_Solver::STATUS_OK;
+      // the error message should be changed before sending the message
+      myConflictingConstraints.clear();
+      sendMessage(EVENT_SOLVER_REPAIRED, myConflictingConstraints);
     }
 
-  } else if (isGroupEmpty && isWorkplaneValid())
     computeDoF();
+  }
   removeTemporaryConstraints();
   myStorage->setNeedToResolve(false);
   return aResolved;
@@ -311,9 +361,9 @@ void SketchSolver_Group::computeDoF()
     aDoFMsg << "DoF (degrees of freedom) = " << aDoF;
   mySketch->string(SketchPlugin_Sketch::SOLVER_DOF())->setValue(aDoFMsg.str());
 
-  if (aDoF > 0 && myDOF == 0)
+  if (aDoF > 0 && myDOF <= 0)
     sendMessage(EVENT_SKETCH_UNDER_CONSTRAINED, mySketch, aDoF);
-  else if (aDoF == 0 && myDOF > 0)
+  else if (aDoF == 0 && myDOF != 0)
     sendMessage(EVENT_SKETCH_FULLY_CONSTRAINED, mySketch, aDoF);
   else if (aDoF < 0)
     sendMessage(EVENT_SKETCH_OVER_CONSTRAINED, mySketch, aDoF);