]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Issue #2133: Edge with middle node constraint can be moved
authorazv <azv@opencascade.com>
Tue, 25 Apr 2017 08:31:09 +0000 (11:31 +0300)
committerazv <azv@opencascade.com>
Tue, 25 Apr 2017 08:31:20 +0000 (11:31 +0300)
Move entities similar as FreeCAD (2 steps):
1. Initialize solver with initial positions of the feature and add temporary constraints.
2. Set new coordinates and then solve the set of constraints.

src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.h
src/SketchSolver/SketchSolver_ConstraintFixed.cpp
src/SketchSolver/SketchSolver_ConstraintFixed.h
src/SketchSolver/SketchSolver_Group.cpp

index 1cae520726c32b8c8a8609f04ea509a903ddef07..a6feb1f9ea6b3c099eb7cea4f931661b867aeeaa 100644 (file)
@@ -51,7 +51,8 @@ static EntityWrapperPtr createScalar(const AttributePtr&     theAttribute,
   else
     aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(theStorage)));
 
-  aWrapper->setValue(aScalar->value());
+  if (aScalar->isInitialized())
+    aWrapper->setValue(aScalar->value());
   return aWrapper;
 }
 
@@ -66,9 +67,11 @@ static EntityWrapperPtr createPoint(const AttributePtr&     theAttribute,
   GCSPointPtr aNewPoint(new GCS::Point);
 
   aNewPoint->x = createParameter(theStorage);
-  *(aNewPoint->x) = aPoint2D->x();
   aNewPoint->y = createParameter(theStorage);
-  *(aNewPoint->y) = aPoint2D->y();
+  if (aPoint2D->isInitialized()) {
+    *(aNewPoint->x) = aPoint2D->x();
+    *(aNewPoint->y) = aPoint2D->y();
+  }
 
   return EntityWrapperPtr(new PlaneGCSSolver_PointWrapper(aNewPoint));
 }
index 47d783dcec8649e042feedd37b1847b16d686811..eb8868409fbcf49e072b8d6d122525737f3beeed 100644 (file)
@@ -11,6 +11,7 @@
 PlaneGCSSolver_Solver::PlaneGCSSolver_Solver()
   : myEquationSystem(new GCS::System),
     myDiagnoseBeforeSolve(false),
+    myInitilized(false),
     myConfCollected(false),
     myDOF(0)
 {
@@ -69,6 +70,18 @@ void PlaneGCSSolver_Solver::removeParameters(const GCS::SET_pD& theParams)
     }
 }
 
+void PlaneGCSSolver_Solver::initialize()
+{
+  Events_LongOp::start(this);
+  if (myDiagnoseBeforeSolve)
+    diagnose();
+  myEquationSystem->declareUnknowns(myParameters);
+  myEquationSystem->initSolution();
+  Events_LongOp::end(this);
+
+  myInitilized = true;
+}
+
 PlaneGCSSolver_Solver::SolveStatus PlaneGCSSolver_Solver::solve()
 {
   // clear list of conflicting constraints
@@ -80,11 +93,15 @@ PlaneGCSSolver_Solver::SolveStatus PlaneGCSSolver_Solver::solve()
   if (myParameters.empty())
     return STATUS_INCONSISTENT;
 
+  GCS::SolveStatus aResult = GCS::Success;
   Events_LongOp::start(this);
-  if (myDiagnoseBeforeSolve)
-    diagnose();
-  // solve equations
-  GCS::SolveStatus aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
+  if (myInitilized) {
+    aResult = (GCS::SolveStatus)myEquationSystem->solve();
+  } else {
+    if (myDiagnoseBeforeSolve)
+      diagnose();
+    aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
+  }
   Events_LongOp::end(this);
 
   // collect information about conflicting constraints every time,
@@ -104,6 +121,7 @@ PlaneGCSSolver_Solver::SolveStatus PlaneGCSSolver_Solver::solve()
     aStatus = STATUS_OK;
   }
 
+  myInitilized = false;
   return aStatus;
 }
 
index a5a411dfa4fb4e366a03cd6fb6df21e66fd34e85..cb195ada3b7ba2b7e1dd79e4d22c881fc3a2d8f5 100644 (file)
@@ -42,6 +42,10 @@ public:
   /// \brief Release memory occupied by parameters
   void removeParameters(const GCS::SET_pD& theParams);
 
+  /// \brief Preliminary initialization of solver (useful for moving a feature).
+  ///        When called, the solve() method does not reinitialize a set of constraints.
+  void initialize();
+
   /// \brief Solve the set of equations
   /// \return identifier whether solution succeeded
   SolveStatus solve();
@@ -69,6 +73,7 @@ private:
 
   std::shared_ptr<GCS::System> myEquationSystem; ///< set of equations for solving in FreeGCS
   bool                         myDiagnoseBeforeSolve; ///< is the diagnostic necessary
+  bool                         myInitilized;     ///< is the system already initialized
 
   GCS::SET_I                   myConflictingIDs; ///< list of IDs of conflicting constraints
   /// specifies the conflicting constraints are already collected
index 52408859619c66430373162997115b711760c8a7..63813ba7555663d5512928142132a8b33008dead 100644 (file)
@@ -123,9 +123,11 @@ SolverConstraintPtr PlaneGCSSolver_Tools::createConstraint(ConstraintPtr theCons
   return SolverConstraintPtr(new SketchSolver_Constraint(theConstraint));
 }
 
-SolverConstraintPtr PlaneGCSSolver_Tools::createMovementConstraint(FeaturePtr theMovedFeature)
+std::shared_ptr<SketchSolver_ConstraintFixed> PlaneGCSSolver_Tools::createMovementConstraint(
+    FeaturePtr theMovedFeature)
 {
-  return SolverConstraintPtr(new SketchSolver_ConstraintFixed(theMovedFeature));
+  return std::shared_ptr<SketchSolver_ConstraintFixed>(
+      new SketchSolver_ConstraintFixed(theMovedFeature));
 }
 
 
index db4820107eba0eb4c1e6f7983941cf2780cab9da..4e43206c177ce64032ca3680939eee913d8fe426 100644 (file)
@@ -8,6 +8,7 @@
 #define PlaneGCSSolver_Tools_H_
 
 #include <SketchSolver_Constraint.h>
+#include <SketchSolver_ConstraintFixed.h>
 #include <SketchPlugin_Constraint.h>
 
 #include <GeomAPI_Lin2d.h>
@@ -24,7 +25,8 @@ namespace PlaneGCSSolver_Tools
   SolverConstraintPtr createConstraint(ConstraintPtr theConstraint);
 
   /// \brief Creates temporary constraint to fix the feature after movement
-  SolverConstraintPtr createMovementConstraint(FeaturePtr theMovedFeature);
+  std::shared_ptr<SketchSolver_ConstraintFixed>
+      createMovementConstraint(FeaturePtr theMovedFeature);
 
   /// \brief Creates new constraint using given parameters
   /// \param theConstraint [in]  original constraint
index 7cf8a2abe0a1b387cccd92852b887dfe8909f1c5..9c4f2333006bdda7d600c3869722bdbfa8287970 100644 (file)
@@ -5,6 +5,8 @@
 
 #include <PlaneGCSSolver_ConstraintWrapper.h>
 #include <PlaneGCSSolver_EdgeWrapper.h>
+#include <PlaneGCSSolver_EntityDestroyer.h>
+#include <PlaneGCSSolver_FeatureBuilder.h>
 #include <PlaneGCSSolver_PointWrapper.h>
 
 #include <GeomDataAPI_Point2D.h>
 
 #include <cmath>
 
-// Find parameters of the feature that have been updated during the movement
-static EntityWrapperPtr getChangedEntity(const FeaturePtr& theFeature,
-                                         const StoragePtr& theStorage);
+// Verify the entities are equal
+static bool isEqual(const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2);
+// Convert entity to the list of parameters
+static GCS::VEC_pD toParameters(const EntityWrapperPtr& theEntity);
 
 
 SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(ConstraintPtr theConstraint)
@@ -46,61 +49,21 @@ void SketchSolver_ConstraintFixed::process()
     return;
   }
 
-  EntityWrapperPtr aValue;
-  std::vector<EntityWrapperPtr> anEntities;
-  getAttributes(aValue, anEntities);
-  if (anEntities.empty())
+  EntityWrapperPtr aBaseEntity;
+  getAttributes(aBaseEntity, myFixedEntity);
+  if (!aBaseEntity) {
+    moveFeature(); // remove myFixed entity
     myErrorMsg = SketchSolver_Error::ALREADY_FIXED();
+  }
   if (!myErrorMsg.empty())
     return;
-  fixFeature(anEntities.front());
+
+  fixFeature(aBaseEntity);
 }
 
 void SketchSolver_ConstraintFixed::fixFeature(EntityWrapperPtr theFeature)
 {
-  std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
-      std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theFeature);
-
-  GCS::VEC_pD aParameters; // parameters of entity to be fixed
-
-  // Collect parameters for each type of entity
-  switch (theFeature->type()) {
-  case ENTITY_POINT: {
-    std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
-        std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theFeature);
-    aParameters.push_back(aPoint->point()->x);
-    aParameters.push_back(aPoint->point()->y);
-    break;
-    }
-  case ENTITY_LINE: {
-    std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
-    aParameters.push_back(aLine->p1.x);
-    aParameters.push_back(aLine->p1.y);
-    aParameters.push_back(aLine->p2.x);
-    aParameters.push_back(aLine->p2.y);
-    break;
-    }
-  case ENTITY_CIRCLE: {
-    std::shared_ptr<GCS::Circle> aCircle =
-        std::dynamic_pointer_cast<GCS::Circle>(anEntity->entity());
-    aParameters.push_back(aCircle->center.x);
-    aParameters.push_back(aCircle->center.y);
-    aParameters.push_back(aCircle->rad);
-    break;
-    }
-  case ENTITY_ARC: {
-    myFixedValues.reserve(4);
-    std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEntity->entity());
-    aParameters.push_back(anArc->center.x);
-    aParameters.push_back(anArc->center.y);
-    aParameters.push_back(anArc->rad);
-    aParameters.push_back(anArc->startAngle);
-    aParameters.push_back(anArc->endAngle);
-    break;
-    }
-  default:
-    break;
-  }
+  GCS::VEC_pD aParameters = toParameters(theFeature);
 
   // Fix given list of parameters
   std::list<GCSConstraintPtr> aConstraints;
@@ -109,7 +72,7 @@ void SketchSolver_ConstraintFixed::fixFeature(EntityWrapperPtr theFeature)
   for (int i = 0; anIt != aParameters.end(); ++anIt, ++i) {
     myFixedValues.push_back(**anIt);
     aConstraints.push_back(
-        GCSConstraintPtr(new GCS::ConstraintEqual(*anIt, &myFixedValues[i])));
+        GCSConstraintPtr(new GCS::ConstraintEqual(&myFixedValues[i], *anIt)));
   }
 
   myConstraint = ConstraintWrapperPtr(
@@ -121,9 +84,8 @@ void SketchSolver_ConstraintFixed::fixFeature(EntityWrapperPtr theFeature)
     myStorage->addTemporaryConstraint(myConstraint);
 }
 
-void SketchSolver_ConstraintFixed::getAttributes(
-    EntityWrapperPtr& theValue,
-    std::vector<EntityWrapperPtr>& theAttributes)
+void SketchSolver_ConstraintFixed::getAttributes(EntityWrapperPtr& theBaseEntity,
+                                                 EntityWrapperPtr& theFixedEntity)
 {
   if (myBaseFeature) {
     // if the feature is copy, do not move it
@@ -135,59 +97,113 @@ void SketchSolver_ConstraintFixed::getAttributes(
     }
 
     // The feature is fixed.
-    EntityWrapperPtr aSolverEntity = getChangedEntity(myBaseFeature, myStorage);
-    myStorage->update(myBaseFeature);
-    if (aSolverEntity)
-      theAttributes.push_back(aSolverEntity);
+    PlaneGCSSolver_FeatureBuilder aBuilder;
+    std::list<AttributePtr> aBaseAttr = myBaseFeature->data()->attributes(std::string());
+    std::list<AttributePtr>::const_iterator anIt = aBaseAttr.begin();
+    for (; anIt != aBaseAttr.end(); ++anIt)
+      aBuilder.createAttribute(*anIt);
+    theFixedEntity = aBuilder.createFeature(myBaseFeature);
+
+    theBaseEntity = myStorage->entity(myBaseFeature);
+    if (isEqual(theBaseEntity, theFixedEntity))
+      theBaseEntity = EntityWrapperPtr(); // do not want to fix already fixed entity
+
   } else if (myBaseConstraint) {
     // Constraint Fixed is added by user.
     // Get the attribute of constraint (it should be alone in the list of constraints).
+    EntityWrapperPtr aValue;
     std::vector<EntityWrapperPtr> anAttributes;
-    SketchSolver_Constraint::getAttributes(theValue, anAttributes);
+    SketchSolver_Constraint::getAttributes(aValue, anAttributes);
     std::vector<EntityWrapperPtr>::const_iterator anIt = anAttributes.begin();
     for (; anIt != anAttributes.end(); ++anIt)
       if (*anIt)
-        theAttributes.push_back(*anIt);
+        theBaseEntity = *anIt;
   } else
     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
 }
 
+void SketchSolver_ConstraintFixed::moveFeature()
+{
+  if (!myFixedEntity)
+    return;
 
+  GCS::VEC_pD aFixedParams = toParameters(myFixedEntity);
+  for (int i = 0; i < aFixedParams.size() && i < myFixedValues.size(); ++i)
+    myFixedValues[i] = *(aFixedParams[i]);
 
+  // Remove fixed entity due to its parameters already copied into the constraint
+  PlaneGCSSolver_EntityDestroyer aDestroyer;
+  aDestroyer.remove(myFixedEntity);
+  std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(myStorage)->removeParameters(
+      aDestroyer.parametersToRemove());
 
-// ====================   Auxiliary functions   ===============================
-static bool isSameCoordinates(const AttributePoint2DPtr& thePointAttr,
-                              const PointWrapperPtr& thePointWrapper)
-{
-  GCSPointPtr aGCSPoint = thePointWrapper->point();
-  return fabs(*aGCSPoint->x - thePointAttr->x()) < tolerance &&
-         fabs(*aGCSPoint->y - thePointAttr->y()) < tolerance;
+  myFixedEntity = EntityWrapperPtr();
 }
 
-EntityWrapperPtr getChangedEntity(const FeaturePtr& theFeature,
-                                  const StoragePtr& theStorage)
+
+
+
+// ====================   Auxiliary functions   ===============================
+GCS::VEC_pD toParameters(const EntityWrapperPtr& theEntity)
 {
-  std::list<AttributePtr> aPoints = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
-  std::list<EntityWrapperPtr> aChangedPoints;
-
-  std::list<AttributePtr>::const_iterator aPIt = aPoints.begin();
-  for (; aPIt != aPoints.end(); ++aPIt) {
-    AttributePoint2DPtr aPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPIt);
-    EntityWrapperPtr anEnt = theStorage->entity(*aPIt);
-    if (anEnt) {
-      PointWrapperPtr aPW = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anEnt);
-      if (!isSameCoordinates(aPnt, aPW))
-        aChangedPoints.push_back(anEnt);
-    } else {
-      theStorage->update(*aPIt);
-      aChangedPoints.push_back(theStorage->entity(*aPIt));
+  GCS::VEC_pD aParameters;
+  if (!theEntity)
+    return aParameters;
+
+  std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
+      std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
+
+  // Collect parameters for each type of entity
+  switch (theEntity->type()) {
+  case ENTITY_POINT: {
+    std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+        std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
+    aParameters.push_back(aPoint->point()->x);
+    aParameters.push_back(aPoint->point()->y);
+    break;
     }
+  case ENTITY_LINE: {
+    std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
+    aParameters.push_back(aLine->p1.x);
+    aParameters.push_back(aLine->p1.y);
+    aParameters.push_back(aLine->p2.x);
+    aParameters.push_back(aLine->p2.y);
+    break;
+    }
+  case ENTITY_CIRCLE: {
+    std::shared_ptr<GCS::Circle> aCircle =
+        std::dynamic_pointer_cast<GCS::Circle>(anEntity->entity());
+    aParameters.push_back(aCircle->center.x);
+    aParameters.push_back(aCircle->center.y);
+    aParameters.push_back(aCircle->rad);
+    break;
+    }
+  case ENTITY_ARC: {
+    std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEntity->entity());
+    aParameters.push_back(anArc->center.x);
+    aParameters.push_back(anArc->center.y);
+    aParameters.push_back(anArc->rad);
+    aParameters.push_back(anArc->startAngle);
+    aParameters.push_back(anArc->endAngle);
+    break;
+    }
+  default:
+    break;
   }
 
-  EntityWrapperPtr aChanged;
-  if (aChangedPoints.size() == 1)
-    aChanged = aChangedPoints.front();
-  else if (!aChangedPoints.empty()) // update whole feature
-    aChanged = theStorage->entity(theFeature);
-  return aChanged;
+  return aParameters;
+}
+
+bool isEqual(const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2)
+{
+  GCS::VEC_pD aParamList1 = toParameters(theEntity1);
+  GCS::VEC_pD aParamList2 = toParameters(theEntity2);
+
+  GCS::VEC_pD::const_iterator anIt1 = aParamList1.begin();
+  GCS::VEC_pD::const_iterator anIt2 = aParamList2.begin();
+  for (; anIt1 != aParamList1.end() && anIt2 != aParamList2.end(); ++anIt1, ++anIt2)
+    if (fabs((**anIt1) - (**anIt2)) > tolerance)
+      return false;
+
+  return anIt1 == aParamList1.end() && anIt2 == aParamList2.end();
 }
index 61b5ec82483bad51b982364866e236892a978e9d..7fc02b203f7af254aa297485c47048604b87b9e3 100644 (file)
@@ -27,15 +27,19 @@ public:
   /// \brief Block or unblock events from this constraint
   virtual void blockEvents(bool isBlocked);
 
+  /// \brief Set coordinates of fixed feature to the values where it has been dragged.
+  ///        Useful when the feature is being moved.
+  void moveFeature();
+
 protected:
   /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
   virtual void process();
 
   /// \brief Generate list of attributes of constraint in order useful for constraints
-  /// \param[out] theValue      numerical characteristic of constraint (e.g. distance)
-  /// \param[out] theAttributes list of attributes to be filled
-  virtual void getAttributes(EntityWrapperPtr&              theValue,
-                             std::vector<EntityWrapperPtr>& theAttributes);
+  /// \param[out] theBaseEntity  the entity which coordinates should be fixed
+  /// \param[out] theFixedEntity the entity containing fixed values
+  virtual void getAttributes(EntityWrapperPtr& theBaseEntity,
+                             EntityWrapperPtr& theFixedEntity);
 
   /// \brief Fixed feature basing on its type
   /// \param theFeature [in]  feature, converted to solver specific format
@@ -46,6 +50,7 @@ private:
 
   ConstraintWrapperPtr myConstraint;
   std::vector<double> myFixedValues;
+  EntityWrapperPtr    myFixedEntity;
 };
 
 #endif
index cee34791d04186f88319f5d36c0cc130cca425f8..a0a7d362408d8fa2d5b6df058fcbc7d3b1511d0a 100644 (file)
@@ -125,13 +125,19 @@ bool SketchSolver_Group::moveFeature(FeaturePtr theFeature)
   }
 
   // Create temporary Fixed constraint
-  SolverConstraintPtr aConstraint = PlaneGCSSolver_Tools::createMovementConstraint(theFeature);
+  std::shared_ptr<SketchSolver_ConstraintFixed> aConstraint =
+      PlaneGCSSolver_Tools::createMovementConstraint(theFeature);
   if (!aConstraint)
     return false;
-  aConstraint->process(myStorage, myIsEventsBlocked);
-  if (aConstraint->error().empty())
+  SolverConstraintPtr(aConstraint)->process(myStorage, myIsEventsBlocked);
+  if (aConstraint->error().empty()) {
     setTemporary(aConstraint);
-  else
+    if (!myStorage->isEmpty())
+      myStorage->setNeedToResolve(true);
+
+    mySketchSolver->initialize();
+    aConstraint->moveFeature();
+  } else
     myStorage->notify(theFeature);
 
   return true;
@@ -141,7 +147,6 @@ bool SketchSolver_Group::moveFeature(FeaturePtr theFeature)
 //  Function: resolveConstraints
 //  Class:    SketchSolver_Group
 //  Purpose:  solve the set of constraints for the current group
-#include <iostream>
 // ============================================================================
 bool SketchSolver_Group::resolveConstraints()
 {