]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Avoid conflicting constraints when mirror a group of entities with Equal constraint
authorazv <azv@opencascade.com>
Fri, 10 Apr 2015 12:03:57 +0000 (15:03 +0300)
committerazv <azv@opencascade.com>
Fri, 10 Apr 2015 12:04:17 +0000 (15:04 +0300)
src/SketchSolver/SketchSolver_ConstraintRigid.cpp
src/SketchSolver/SketchSolver_ConstraintRigid.h
src/SketchSolver/SketchSolver_Group.cpp
src/SketchSolver/SketchSolver_Storage.cpp
src/SketchSolver/SketchSolver_Storage.h

index 7f12c7d32b1238285d9cc76c62c65f15485e7ab4..3483973fe30f2ae5661d04de2e26a16984926532 100644 (file)
@@ -148,12 +148,12 @@ void SketchSolver_ConstraintRigid::fixPoint(const Slvs_hEntity& thePointID)
     return;
 
   Slvs_Constraint aConstraint;
-  Slvs_hConstraint aConstrID = myStorage->isPointFixed(thePointID);
-  bool isForceUpdate = (aConstrID != SLVS_E_UNKNOWN && !myBaseConstraint &&
+  Slvs_hConstraint aConstrID = SLVS_E_UNKNOWN;
+  bool isFixed = myStorage->isPointFixed(thePointID, aConstrID, true);
+  bool isForceUpdate = (isFixed && !myBaseConstraint &&
                         myStorage->isTemporary(aConstrID));
   if (!isForceUpdate) { // create new constraint
-    if (aConstrID != SLVS_E_UNKNOWN)
-      return; // the coincident point is already fixed
+    if (isFixed) return;
     aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(),
         0.0, thePointID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
     aConstraint.h = myStorage->addConstraint(aConstraint);
@@ -161,7 +161,7 @@ void SketchSolver_ConstraintRigid::fixPoint(const Slvs_hEntity& thePointID)
     if (!myBaseConstraint)
       myStorage->addConstraintWhereDragged(aConstraint.h);
   } else { // update already existent constraint
-    if (aConstrID == SLVS_E_UNKNOWN || myBaseConstraint)
+    if (!isFixed || aConstrID == SLVS_E_UNKNOWN || myBaseConstraint)
       return;
     aConstraint = myStorage->getConstraint(aConstrID);
     aConstraint.ptA = thePointID;
@@ -177,11 +177,11 @@ void SketchSolver_ConstraintRigid::fixLine(const Slvs_Entity& theLine)
   if (isUsedInEqual(theLine, anEqual)) {
     // Check another entity of Equal is already fixed
     Slvs_hEntity anOtherEntID = anEqual.entityA == theLine.h ? anEqual.entityB : anEqual.entityA;
-    Slvs_Entity anOtherEntity = myStorage->getEntity(anOtherEntID);
-    if (isFixed(anOtherEntity)) {
+    if (myStorage->isEntityFixed(anOtherEntID, true)) {
       // Fix start point of the line (if end point is not fixed yet) ...
-      Slvs_hConstraint anEndFixedID = myStorage->isPointFixed(theLine.point[1]);
-      if (anEndFixedID == SLVS_E_UNKNOWN)
+      Slvs_hConstraint anEndFixedID = SLVS_E_UNKNOWN;
+      bool isFixed = myStorage->isPointFixed(theLine.point[1], anEndFixedID, true);
+      if (isFixed == SLVS_E_UNKNOWN)
         fixPoint(theLine.point[0]);
       // ...  and create fixed point lying on this line
       Slvs_hEntity aPointToCopy = anEndFixedID == SLVS_E_UNKNOWN ? theLine.point[1] : theLine.point[0];
@@ -192,7 +192,7 @@ void SketchSolver_ConstraintRigid::fixLine(const Slvs_Entity& theLine)
       std::list<Slvs_Constraint>::const_iterator aPLIter = aPonLineList.begin();
       for (; aPLIter != aPonLineList.end() && !isPonLineFixed; aPLIter++)
         if (aPLIter->entityA == theLine.h) {
-          isPonLineFixed = (myStorage->isPointFixed(aPLIter->ptA) != SLVS_E_UNKNOWN);
+          isPonLineFixed = myStorage->isPointFixed(aPLIter->ptA, anEndFixedID);
           aFixedPoint = aPLIter->ptA;
         }
 
@@ -222,8 +222,7 @@ void SketchSolver_ConstraintRigid::fixCircle(const Slvs_Entity& theCircle)
   if (isUsedInEqual(theCircle, anEqual)) {
     // Check another entity of Equal is already fixed
     Slvs_hEntity anOtherEntID = anEqual.entityA == theCircle.h ? anEqual.entityB : anEqual.entityA;
-    Slvs_Entity anOtherEntity = myStorage->getEntity(anOtherEntID);
-    if (isFixed(anOtherEntity))
+    if (myStorage->isEntityFixed(anOtherEntID, true))
       isFixRadius = false;
   }
 
@@ -253,9 +252,9 @@ void SketchSolver_ConstraintRigid::fixArc(const Slvs_Entity& theArc)
   if (isUsedInEqual(theArc, anEqual)) {
     // Check another entity of Equal is already fixed
     Slvs_hEntity anOtherEntID = anEqual.entityA == theArc.h ? anEqual.entityB : anEqual.entityA;
-    Slvs_Entity anOtherEntity = myStorage->getEntity(anOtherEntID);
-    if (isFixed(anOtherEntity)) {
+    if (myStorage->isEntityFixed(anOtherEntID, true)) {
       isFixRadius = false;
+      Slvs_Entity anOtherEntity = myStorage->getEntity(anOtherEntID);
       if (anOtherEntity.type == SLVS_E_LINE_SEGMENT) {
         aPointsToFix.pop_back();
         aPointsToFix.push_back(theArc.point[0]);
@@ -263,9 +262,9 @@ void SketchSolver_ConstraintRigid::fixArc(const Slvs_Entity& theArc)
     }
   }
 
-  Slvs_hConstraint aConstrID = myStorage->isPointFixed(theArc.point[0]);
+  Slvs_hConstraint aConstrID;
   int aNbPointsToFix = 2; // number of fixed points for the arc
-  if (aConstrID != SLVS_E_UNKNOWN)
+  if (myStorage->isPointFixed(theArc.point[0], aConstrID, true))
     aNbPointsToFix--;
 
   // Radius of the arc
@@ -336,26 +335,3 @@ bool SketchSolver_ConstraintRigid::isUsedInEqual(
   return false;
 }
 
-bool SketchSolver_ConstraintRigid::isFixed(const Slvs_Entity& theEntity) const
-{
-  if (theEntity.type == SLVS_E_POINT_IN_2D)
-    return myStorage->isPointFixed(theEntity.h) != SLVS_E_UNKNOWN;
-
-  // Check all the points of entity are fixed
-  int aNbFixed = 0;
-  for (int i = 0; i < 4; i++) {
-    if (theEntity.point[i] != SLVS_E_UNKNOWN &&
-        myStorage->isPointFixed(theEntity.point[i]) != SLVS_E_UNKNOWN)
-      aNbFixed++;
-  }
-
-  switch (theEntity.type) {
-  case SLVS_E_LINE_SEGMENT:
-  case SLVS_E_ARC_OF_CIRCLE:
-    if (aNbFixed == 2) return true;
-  case SLVS_E_CIRCLE:
-    if (aNbFixed == 1) return true;
-  }
-  return false;
-}
-
index 93de5836226da0e16e3e5750b81056ae415c7aa9..4cde524793f1161767233c140efd1f403a023941 100644 (file)
@@ -67,9 +67,6 @@ private:
   /// \return \c true, if the Equal constrait is found
   bool isUsedInEqual(const Slvs_Entity& theEntity, Slvs_Constraint& theEqual) const;
 
-  /// \brief Verifies the entity is already fixed
-  bool isFixed(const Slvs_Entity& theEntity) const;
-
 protected:
   FeaturePtr myBaseFeature; ///< fixed feature (when it is set, myBaseConstraint should be NULL)
 };
index 3c5832cdb793c7155a872ba79dce491c84416a0e..9ccf3fa73d003b22f7743c08506a2cd0e11bd2d6 100644 (file)
@@ -25,6 +25,7 @@
 #include <ModelAPI_ResultConstruction.h>
 
 #include <SketchPlugin_Constraint.h>
+#include <SketchPlugin_ConstraintEqual.h>
 #include <SketchPlugin_ConstraintFillet.h>
 #include <SketchPlugin_ConstraintLength.h>
 #include <SketchPlugin_ConstraintCoincidence.h>
@@ -289,12 +290,27 @@ void SketchSolver_Group::fixFeaturesList(AttributeRefListPtr theList)
 {
   std::list<ObjectPtr> aList = theList->list();
   std::list<ObjectPtr>::iterator anIt = aList.begin();
+  std::list<FeaturePtr> aFeatures;
+  // Sort features, at begining there are features used by Equal constraint
   for (; anIt != aList.end(); anIt++) {
     if (!(*anIt))
       continue;
     FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+    std::set<ConstraintPtr> aConstraints = myFeatureStorage->getConstraints(aFeature);
+    std::set<ConstraintPtr>::iterator aCIter = aConstraints.begin();
+    for (; aCIter != aConstraints.end(); aCIter++)
+      if ((*aCIter)->getKind() == SketchPlugin_ConstraintEqual::ID())
+        break;
+    if (aCIter != aConstraints.end())
+      aFeatures.push_front(aFeature);
+    else
+      aFeatures.push_back(aFeature);
+  }
+
+  std::list<FeaturePtr>::iterator aFeatIter = aFeatures.begin();
+  for (; aFeatIter != aFeatures.end(); aFeatIter++) {
     SolverConstraintPtr aConstraint =
-        SketchSolver_Builder::getInstance()->createRigidConstraint(aFeature);
+        SketchSolver_Builder::getInstance()->createRigidConstraint(*aFeatIter);
     if (!aConstraint)
       continue;
     aConstraint->setGroup(this);
index f13ad6b6f861d5aa026a06407c1fa94337686509..eddd630c94aa4f9365e79673b170c13436306d5e 100644 (file)
@@ -246,31 +246,164 @@ void SketchSolver_Storage::copyEntity(const Slvs_hEntity& theFrom, const Slvs_hE
 }
 
 
-Slvs_hConstraint SketchSolver_Storage::isPointFixed(const Slvs_hEntity& thePointID) const
+bool SketchSolver_Storage::isPointFixed(
+    const Slvs_hEntity& thePointID, Slvs_hConstraint& theFixed, bool theAccurate) const
 {
   // Search the set of coincident points
+  std::set<Slvs_hEntity> aCoincident;
+  aCoincident.insert(thePointID);
   std::vector< std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
   for (; aCPIter != myCoincidentPoints.end(); aCPIter++)
-    if (aCPIter->find(thePointID) != aCPIter->end())
+    if (aCPIter->find(thePointID) != aCPIter->end()) {
+      aCoincident = *aCPIter;
       break;
-  if (aCPIter == myCoincidentPoints.end()) {
-    std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
-    for (; aConstrIter != myConstraints.end(); aConstrIter++)
-      if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
-          aConstrIter->ptA == thePointID)
-        return aConstrIter->h;
-    return SLVS_E_UNKNOWN;
-  }
+    }
 
   // Search the Rigid constraint
   std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
   for (; aConstrIter != myConstraints.end(); aConstrIter++)
     if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
-        aCPIter->find(aConstrIter->ptA) != aCPIter->end())
-      return aConstrIter->h;
+        aCoincident.find(aConstrIter->ptA) != aCoincident.end()) {
+      theFixed = aConstrIter->h;
+      return true;
+    }
+
+  if (theAccurate) {
+    // Try to find the fixed entity which uses such point or its coincidence
+    std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
+    for (; anEntIter != myEntities.end(); anEntIter++) {
+      for (int i = 0; i < 4; i++) {
+        Slvs_hEntity aPt = anEntIter->point[i];
+        if (aPt != SLVS_E_UNKNOWN &&
+            (aPt == thePointID || aCoincident.find(aPt) != aCoincident.end())) {
+          if (isEntityFixed(anEntIter->h, true))
+            return true;
+        }
+      }
+    }
+  }
   return SLVS_E_UNKNOWN;
 }
 
+bool SketchSolver_Storage::isEntityFixed(const Slvs_hEntity& theEntityID, bool theAccurate) const
+{
+  int aPos = Search(theEntityID, myEntities);
+  if (aPos < 0 || aPos >= (int)myEntities.size())
+    return false;
+
+  // Firstly, find how many points are under Rigid constraint
+  int aNbFixed = 0;
+  for (int i = 0; i < 4; i++) {
+    Slvs_hEntity aPoint = myEntities[aPos].point[i];
+    if (aPoint == SLVS_E_UNKNOWN)
+      continue;
+
+    std::set<Slvs_hEntity> aCoincident;
+    aCoincident.insert(aPoint);
+    std::vector< std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
+    for (; aCPIter != myCoincidentPoints.end(); aCPIter++)
+      if (aCPIter->find(aPoint) != aCPIter->end()) {
+        aCoincident = *aCPIter;
+        break;
+      }
+
+    // Search the Rigid constraint
+    std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
+    for (; aConstrIter != myConstraints.end(); aConstrIter++)
+      if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
+          aCoincident.find(aConstrIter->ptA) != aCoincident.end())
+        aNbFixed++;
+  }
+
+  std::list<Slvs_Constraint> aList;
+  std::list<Slvs_Constraint>::iterator anIt;
+  Slvs_hConstraint aTempID; // used in isPointFixed() method
+
+  if (myEntities[aPos].type == SLVS_E_LINE_SEGMENT) {
+    if (aNbFixed == 2)
+      return true;
+    else if (aNbFixed == 0 || !theAccurate)
+      return false;
+    // Additional check (the line may be fixed if it is used by different constraints):
+    // 1. The line is used in Equal constraint, another entity is fixed and there is a fixed point on line
+    aList = getConstraintsByType(SLVS_C_PT_ON_LINE);
+    for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+      if (anIt->entityA == theEntityID && isPointFixed(anIt->ptA, aTempID))
+        break;
+    if (anIt != aList.end()) {
+      aList = getConstraintsByType(SLVS_C_EQUAL_LENGTH_LINES);
+      aList.splice(aList.end(), getConstraintsByType(SLVS_C_EQUAL_LINE_ARC_LEN));
+      for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+        if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
+          Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
+          if (isEntityFixed(anOther, false))
+            return true;
+        }
+    }
+    // 2. The line is used in Parallel/Perpendicular and Length constraints
+    aList = getConstraintsByType(SLVS_C_PARALLEL);
+    aList.splice(aList.end(), getConstraintsByType(SLVS_C_PERPENDICULAR));
+    for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+      if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
+        Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
+        if (isEntityFixed(anOther, false))
+          break;
+      }
+    if (anIt != aList.end()) {
+      aList = getConstraintsByType(SLVS_C_PT_PT_DISTANCE);
+      for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+        if ((anIt->ptA == myEntities[aPos].point[0] && anIt->ptB == myEntities[aPos].point[1]) ||
+            (anIt->ptA == myEntities[aPos].point[1] && anIt->ptB == myEntities[aPos].point[0]))
+          return true;
+    }
+    // 3. Another verifiers ...
+  } else if (myEntities[aPos].type == SLVS_E_CIRCLE) {
+    if (aNbFixed == 0)
+      return false;
+    // Search for Diameter constraint
+    aList = getConstraintsByType(SLVS_C_DIAMETER);
+    for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+      if (anIt->entityA == theEntityID)
+        return true;
+    if (!theAccurate)
+      return false;
+    // Additional check (the circle may be fixed if it is used by different constraints):
+    // 1. The circle is used in Equal constraint and another entity is fixed
+    aList = getConstraintsByType(SLVS_C_EQUAL_RADIUS);
+    for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+      if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
+        Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
+        if (isEntityFixed(anOther, false))
+          return true;
+      }
+    // 2. Another verifiers ...
+  } else if (myEntities[aPos].type == SLVS_E_ARC_OF_CIRCLE) {
+    if (aNbFixed > 2)
+      return true;
+    else if (aNbFixed <= 1)
+      return false;
+    // Search for Diameter constraint
+    aList = getConstraintsByType(SLVS_C_DIAMETER);
+    for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+      if (anIt->entityA == theEntityID)
+        return true;
+    if (!theAccurate)
+      return false;
+    // Additional check (the arc may be fixed if it is used by different constraints):
+    // 1. The arc is used in Equal constraint and another entity is fixed
+    aList = getConstraintsByType(SLVS_C_EQUAL_RADIUS);
+    aList.splice(aList.end(), getConstraintsByType(SLVS_C_EQUAL_LINE_ARC_LEN));
+    for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+      if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
+        Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
+        if (isEntityFixed(anOther, false))
+          return true;
+      }
+    // 2. Another verifiers ...
+  }
+  return false;
+}
+
 
 Slvs_hConstraint SketchSolver_Storage::addConstraint(const Slvs_Constraint& theConstraint)
 {
index 613e0ec29ab812af6b1f4c6b6afe388e36356342..80fce4563c8911e1d6370ed1c25a1fe5cd2c4b4c 100644 (file)
@@ -66,8 +66,18 @@ public:
   void copyEntity(const Slvs_hEntity& theFrom, const Slvs_hEntity& theTo);
 
   /// \brief Verifies the current point or another coincident one is fixed
-  /// \return the ID of the Fixed constraint or SLVS_E_UNKNOWN
-  Slvs_hConstraint isPointFixed(const Slvs_hEntity& thePointID) const;
+  /// \param[in]  thePointID  entity to be checked fixed
+  /// \param[out] theFixed    ID of constraint
+  /// \param[in]  theAccurate if \c true, the calculation will be made for all type of constraints,
+  ///                         if \c false, only the point is verified
+  /// \return \c true if the point is fixed
+  bool isPointFixed(const Slvs_hEntity& thePointID, Slvs_hConstraint& theFixed, bool theAccurate = false) const;
+  /// \brief Verifies the current entity is fully fixed (may not be changed by constraints)
+  /// \param[in] theEntityID entity to be checked fixed
+  /// \param[in] theAccurate if \c true, the calculation will be made for all type of constraints,
+  ///                        if \c false, only points are verified
+  /// \return \c true if the entity is fixed
+  bool isEntityFixed(const Slvs_hEntity& theEntityID, bool theAccurate = false) const;
 
   /** \brief Add new constraint to the current group
    *  \param[in] theConstraint   SolveSpace's constraint