]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Merge branch 'Dev_1.1.0' of newgeom:newgeom.git into Dev_1.1.0
authorsbh <sergey.belash@opencascade.com>
Fri, 10 Apr 2015 12:03:51 +0000 (15:03 +0300)
committersbh <sergey.belash@opencascade.com>
Fri, 10 Apr 2015 12:03:51 +0000 (15:03 +0300)
20 files changed:
src/Model/Model_AttributeDouble.cpp
src/ModuleBase/ModuleBase_Tools.cpp
src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp
src/ParametersPlugin/ParametersPlugin_PyInterp.cpp
src/SketchPlugin/SketchPlugin_ConstraintDistance.cpp
src/SketchSolver/SketchSolver_Constraint.cpp
src/SketchSolver/SketchSolver_Constraint.h
src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp
src/SketchSolver/SketchSolver_ConstraintCoincidence.h
src/SketchSolver/SketchSolver_ConstraintMirror.cpp
src/SketchSolver/SketchSolver_ConstraintRigid.cpp
src/SketchSolver/SketchSolver_ConstraintRigid.h
src/SketchSolver/SketchSolver_Error.h
src/SketchSolver/SketchSolver_FeatureStorage.cpp
src/SketchSolver/SketchSolver_Group.cpp
src/SketchSolver/SketchSolver_Storage.cpp
src/SketchSolver/SketchSolver_Storage.h
src/XGUI/XGUI_Displayer.cpp
src/XGUI/XGUI_Displayer.h
src/XGUI/XGUI_Workshop.cpp

index 87bba89cfcb414356737172b932e57058adcf23c..86cbc9e14bfbe5e7083d86a5f1a9b8b8ab5e70e0 100644 (file)
@@ -33,6 +33,8 @@ Model_AttributeDouble::Model_AttributeDouble(TDF_Label& theLabel)
   if (!myIsInitialized) {
     // create attribute: not initialized by value yet, just zero
     myReal = TDataStd_Real::Set(theLabel, 0.);
+  }
+  if (!theLabel.FindAttribute(TDataStd_Name::GetID(), myText)) {
     myText = TDataStd_Name::Set(theLabel, TCollection_ExtendedString());
   }
 }
index a2c393658c6b0a5fd972593781b0df6a60dc9325..6639a548af29b5a294a5a29f05ff89e3db655e71 100644 (file)
@@ -112,11 +112,11 @@ void setSpinValue(QDoubleSpinBox* theSpin, double theValue)
 QString objectInfo(const ObjectPtr& theObj)
 {
   ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObj);
-  FeaturePtr aFeature;// = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
   QString aFeatureStr = "feature";
   if(aRes.get()) {
     aFeatureStr.append("(Result)");
-    //aFeature = ModelAPI_Feature::feature(aRes);
+    aFeature = ModelAPI_Feature::feature(aRes);
   }
   if (aFeature.get()) {
     aFeatureStr.append(QString(": %1").arg(aFeature->getKind().c_str()).toStdString().c_str());
index 9d74cc2fb48bb08f67d546bcf00611bf0389cf2b..53f0352756df1ebd3c712260df79170dbc05b39d 100644 (file)
@@ -282,11 +282,10 @@ void ModuleBase_WidgetMultiSelector::onSelectionChanged()
       }
     }
   }
+  emit valuesChanged();
   // the updateObject method should be called to flush the updated sigal. The workshop listens it,
   // calls validators for the feature and, as a result, updates the Apply button state.
   updateObject(myFeature);
-
-  emit valuesChanged();
 }
 
 //********************************************************************
@@ -334,6 +333,8 @@ void ModuleBase_WidgetMultiSelector::updateSelectionList(AttributeSelectionListP
     AttributeSelectionPtr aAttr = theList->value(i);
     myListControl->addItem(aAttr->namingName().c_str());
   }
+  // We have to call repaint because sometimes the List control is not updated
+  myListControl->repaint();
 }
 
 //********************************************************************
index 61b8cfd3326baf960cb579913b036b652a233aef..7a5f42c4fe5243e9abf000951c50ce36971aded1 100644 (file)
@@ -8,6 +8,7 @@
 #include <ParametersPlugin_PyInterp.h>
 
 #include <string>
+#include <stdexcept>
 
 ParametersPlugin_PyInterp::ParametersPlugin_PyInterp()
 : PyInterp_Interp()
index b7f708a9c59578efdec9e6d06e6b9690e1c46058..3ee3e65ead27b6677f80a7f2e8537a300cc62b72 100644 (file)
@@ -105,7 +105,7 @@ bool SketchPlugin_ConstraintDistance::compute(const std::string& theAttributeId)
   std::shared_ptr<GeomAPI_Pnt> aPoint1 = sketch()->to3D(aPnt_A->x(), aPnt_A->y());
   std::shared_ptr<GeomAPI_Pnt> aPoint2 = sketch()->to3D(aPnt_B->x(), aPnt_B->y());
   // it is not possible to create lin2d on the points with equal position
-  if (aPoint1->distance(aPoint1) < tolerance)
+  if (aPoint1->distance(aPoint2) < tolerance)
     return false;
 
   std::shared_ptr<GeomAPI_Lin2d> aLine = std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPnt_A, aPnt_B));
index 36bde98f820d2a17ad264f40cf414f4b4a3a3cda..2a2c85f383839a78c2844797a789d5f8edf6dd41 100644 (file)
@@ -33,10 +33,16 @@ SketchSolver_Constraint::~SketchSolver_Constraint()
     myStorage->removeEntity(anIt2->second);
   myAttributeMap.clear();
 
-  std::map<FeaturePtr, Slvs_hEntity>::const_iterator anIt3 =  myFeatureMap.begin();
-  for (; anIt3 != myFeatureMap.end(); anIt3++)
-    myStorage->removeEntity(anIt3->second);
-  myFeatureMap.clear();
+  std::map<FeaturePtr, Slvs_hEntity>::iterator anIt3 =  myFeatureMap.begin();
+  while (!myFeatureMap.empty()) {
+    std::shared_ptr<SketchPlugin_Feature> aFeature =
+        std::dynamic_pointer_cast<SketchPlugin_Feature>(anIt3->first);
+    Slvs_hEntity anEnt = anIt3->second;
+    std::map<FeaturePtr, Slvs_hEntity>::iterator aRemIt = anIt3++;
+    myFeatureMap.erase(aRemIt);
+    if (!myGroup->isInteract(aFeature))
+      myStorage->removeEntity(anEnt);
+  }
 
   std::vector<Slvs_hConstraint>::const_iterator anIt4 = mySlvsConstraints.begin();
   for (; anIt4 != mySlvsConstraints.end(); anIt4++)
@@ -56,6 +62,12 @@ void SketchSolver_Constraint::setGroup(SketchSolver_Group* theGroup)
   process();
 }
 
+void SketchSolver_Constraint::addFeature(FeaturePtr theFeature)
+{
+  int aType;
+  changeEntity(theFeature, aType);
+}
+
 
 void SketchSolver_Constraint::process()
 {
@@ -521,7 +533,7 @@ void SketchSolver_Constraint::refresh()
         }
         if (fabs(aPoint2D->x() - aXY[0]) > tolerance ||
             fabs(aPoint2D->y() - aXY[1]) > tolerance)
-        aPoint2D->setValue(aXY[0], aXY[1]);
+          aPoint2D->setValue(aXY[0], aXY[1]);
       } else {
         // Scalar value (used for the distance entities)
         AttributeDoublePtr aScalar =
index 134263412da5574997e456bb728db825191de3ef..b6ff8f55bdca282594442ec350b5e550d3bb3464 100644 (file)
@@ -66,6 +66,9 @@ public:
   /// \brief Return identifier of SolveSpace entity relating to the attribute
   Slvs_hEntity getId(AttributePtr theAttribute) const;
 
+  /// \brief Adds a feature to constraint and create its analogue in SolveSpace
+  void addFeature(FeaturePtr theFeature);
+
   /// \brief Shows error message
   const std::string& error() const
   { return myErrorMsg; }
index 2ae6bf381b4922a07398f41495e7f3254fc3fd12..bfa65c19ec3f50ccf8afdd0621f378d76f86df67 100644 (file)
@@ -28,13 +28,9 @@ std::list<ConstraintPtr> SketchSolver_ConstraintCoincidence::constraints() const
 bool SketchSolver_ConstraintCoincidence::isCoincide(
     std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const
 {
-  std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFeatIter = myFeatureMap.begin();
-  for (; aFeatIter != myFeatureMap.end(); aFeatIter++)
-    if (theConstraint->myFeatureMap.find(aFeatIter->first) != theConstraint->myFeatureMap.end())
-      return true;
-  std::map<AttributePtr, Slvs_hEntity>::const_iterator anAttrIter = myAttributeMap.begin();
-  for (; anAttrIter != myAttributeMap.end(); anAttrIter++)
-    if (theConstraint->myAttributeMap.find(anAttrIter->first) != theConstraint->myAttributeMap.end())
+  std::set<AttributePtr>::const_iterator anAttrIter = theConstraint->myCoincidentPoints.begin();
+  for (; anAttrIter != theConstraint->myCoincidentPoints.end(); anAttrIter++)
+    if (myCoincidentPoints.find(*anAttrIter) != myCoincidentPoints.end())
       return true;
   return false;
 }
@@ -96,6 +92,7 @@ void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstrai
     if (anEntityID == SLVS_E_UNKNOWN)
       anEntityID = changeEntity(aRefAttr->attr(), aType);
     anEntities.push_back(anEntityID);
+    myCoincidentPoints.insert(aRefAttr->attr());
   }
 
   Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
@@ -176,6 +173,7 @@ bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
   while (anAttrIter != myAttributeMap.end()) {
     if (anEntRemoved.find(anAttrIter->second) != anEntRemoved.end()) {
       std::map<AttributePtr, Slvs_hEntity>::iterator aTempIt = anAttrIter++;
+      myCoincidentPoints.erase(aTempIt->first);
       myAttributeMap.erase(aTempIt);
       continue;
     }
index f726020c766e3e76bb1112bd8a1288523e152541..e8cbb8e402759896ac983a6bc8221e20ceef874c 100644 (file)
@@ -50,6 +50,7 @@ private:
 
 private:
   std::map<Slvs_hConstraint, ConstraintPtr> myExtraCoincidence; ///< multiple coincidence of points
+  std::set<AttributePtr> myCoincidentPoints; ///< list of points under the Coincidence constraint
 };
 
 #endif
index fde4b811ecd73e1b72683d306a5c836f8f2222bf..8ed85ff49cbfc140c1e1b57065a9040ce602c8eb 100644 (file)
@@ -207,6 +207,7 @@ void SketchSolver_ConstraintMirror::update(ConstraintPtr theConstraint)
     if (aMirroredRefList->size() != myNumberOfObjects) {
       remove(myBaseConstraint);
       process();
+      return;
     }
   }
   SketchSolver_Constraint::update();
index 956f4b727549d5a33923878541ecd3d42997d04b..7f12c7d32b1238285d9cc76c62c65f15485e7ab4 100644 (file)
@@ -5,6 +5,7 @@
 #include <SketchPlugin_Arc.h>
 #include <SketchPlugin_Circle.h>
 #include <SketchPlugin_ConstraintRigid.h>
+#include <SketchPlugin_Line.h>
 
 #include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_XY.h>
@@ -31,63 +32,20 @@ void SketchSolver_ConstraintRigid::process()
   double aValue;
   std::vector<Slvs_hEntity> anEntities;
   getAttributes(aValue, anEntities);
-  if (!myErrorMsg.empty())
+  if (!myErrorMsg.empty() || myFeatureMap.empty())
     return;
 
-  Slvs_Constraint aConstraint;
-  std::vector<Slvs_hConstraint>::iterator aConstrIter = mySlvsConstraints.begin();
-  bool isEmpty = aConstrIter == mySlvsConstraints.end();
-
-  // Check the fixed entity is an arc
-  if (isEmpty) {
-    if (!myFeatureMap.empty() && myFeatureMap.begin()->first->getKind() == SketchPlugin_Arc::ID()) {
-      Slvs_Entity anArc = myStorage->getEntity(myFeatureMap.begin()->second);
-      fixArc(anArc);
-      return;
-    }
+  if (myFeatureMap.begin()->first->getKind() == SketchPlugin_Line::ID()) {
+    Slvs_Entity aLine = myStorage->getEntity(myFeatureMap.begin()->second);
+    fixLine(aLine);
   }
-
-  std::vector<Slvs_hEntity>::const_iterator anEntIter = anEntities.begin();
-  for (; anEntIter != anEntities.end(); anEntIter++) {
-    if (*anEntIter == SLVS_E_UNKNOWN)
-      continue;
-    Slvs_hConstraint aConstrID = myStorage->isPointFixed(*anEntIter);
-    bool isForceUpdate = (aConstrID != SLVS_E_UNKNOWN && !myBaseConstraint &&
-                          myStorage->isTemporary(aConstrID));
-    if (isEmpty && !isForceUpdate) { // create new constraint
-      if (aConstrID != SLVS_E_UNKNOWN)
-        continue; // the coincident point is already fixed
-      aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(),
-          aValue, *anEntIter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-      aConstraint.h = myStorage->addConstraint(aConstraint);
-      mySlvsConstraints.push_back(aConstraint.h);
-      if (!myBaseConstraint)
-        myStorage->addConstraintWhereDragged(aConstraint.h);
-    } else { // update already existent constraint
-      if (aConstrID == SLVS_E_UNKNOWN || myBaseConstraint)
-        aConstrID = *aConstrIter;
-      aConstraint = myStorage->getConstraint(aConstrID);
-      aConstraint.ptA = *anEntIter;
-      myStorage->addConstraint(aConstraint);
-      if (!myBaseConstraint)
-        myStorage->addConstraintWhereDragged(aConstraint.h);
-      if (!isEmpty) {
-        aConstrIter++;
-        isEmpty = aConstrIter == mySlvsConstraints.end();
-      }
-    }
+  else if (myFeatureMap.begin()->first->getKind() == SketchPlugin_Arc::ID()) {
+    Slvs_Entity anArc = myStorage->getEntity(myFeatureMap.begin()->second);
+    fixArc(anArc);
   }
-
-  if (!myFeatureMap.empty() && myFeatureMap.begin()->first->getKind() == SketchPlugin_Circle::ID()) {
-    // Fix radius of a circle
-    AttributeDoublePtr aRadiusAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
-        myFeatureMap.begin()->first->attribute(SketchPlugin_Circle::RADIUS_ID()));
-    aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER, myGroup->getWorkplaneId(),
-      aRadiusAttr->value() * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, myFeatureMap.begin()->second, SLVS_E_UNKNOWN);
-    aConstraint.h = myStorage->addConstraint(aConstraint);
-    mySlvsConstraints.push_back(aConstraint.h);
-    if (!myBaseConstraint)
-      myStorage->addConstraintWhereDragged(aConstraint.h);
+  else if (myFeatureMap.begin()->first->getKind() == SketchPlugin_Circle::ID()) {
+    Slvs_Entity aCirc = myStorage->getEntity(myFeatureMap.begin()->second);
+    fixArc(aCirc);
   }
 }
 
@@ -184,14 +142,131 @@ bool SketchSolver_ConstraintRigid::remove(ConstraintPtr theConstraint)
   return true;
 }
 
+void SketchSolver_ConstraintRigid::fixPoint(const Slvs_hEntity& thePointID)
+{
+  if (thePointID == SLVS_E_UNKNOWN)
+    return;
+
+  Slvs_Constraint aConstraint;
+  Slvs_hConstraint aConstrID = myStorage->isPointFixed(thePointID);
+  bool isForceUpdate = (aConstrID != SLVS_E_UNKNOWN && !myBaseConstraint &&
+                        myStorage->isTemporary(aConstrID));
+  if (!isForceUpdate) { // create new constraint
+    if (aConstrID != SLVS_E_UNKNOWN)
+      return; // the coincident point is already fixed
+    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);
+    mySlvsConstraints.push_back(aConstraint.h);
+    if (!myBaseConstraint)
+      myStorage->addConstraintWhereDragged(aConstraint.h);
+  } else { // update already existent constraint
+    if (aConstrID == SLVS_E_UNKNOWN || myBaseConstraint)
+      return;
+    aConstraint = myStorage->getConstraint(aConstrID);
+    aConstraint.ptA = thePointID;
+    myStorage->addConstraint(aConstraint);
+    if (!myBaseConstraint)
+      myStorage->addConstraintWhereDragged(aConstraint.h);
+  }
+}
+
+void SketchSolver_ConstraintRigid::fixLine(const Slvs_Entity& theLine)
+{
+  Slvs_Constraint anEqual;
+  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)) {
+      // 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)
+        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];
+      // Firstly, search already fixed point on line
+      bool isPonLineFixed = false;
+      Slvs_hEntity aFixedPoint;
+      std::list<Slvs_Constraint> aPonLineList = myStorage->getConstraintsByType(SLVS_C_PT_ON_LINE);
+      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);
+          aFixedPoint = aPLIter->ptA;
+        }
+
+      if (isPonLineFixed) { // update existent constraint
+        myStorage->copyEntity(aPointToCopy, aFixedPoint);
+      } else { // create new constraint
+        Slvs_hEntity aCopied = myStorage->copyEntity(aPointToCopy);
+        Slvs_Constraint aPonLine = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_ON_LINE,
+            myGroup->getWorkplaneId(), 0.0, aCopied, SLVS_E_UNKNOWN, theLine.h, SLVS_E_UNKNOWN);
+        aPonLine.h = myStorage->addConstraint(aPonLine);
+        mySlvsConstraints.push_back(aPonLine.h);
+        fixPoint(aCopied);
+      }
+      return;
+    }
+  }
+
+  for (int i = 0; i < 2; i++)
+    fixPoint(theLine.point[i]);
+}
+
+void SketchSolver_ConstraintRigid::fixCircle(const Slvs_Entity& theCircle)
+{
+  bool isFixRadius = true;
+  // Verify the arc is under Equal constraint
+  Slvs_Constraint anEqual;
+  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))
+      isFixRadius = false;
+  }
+
+  fixPoint(theCircle.point[0]);
+
+  if (isFixRadius) {
+    // Fix radius of a circle
+    AttributeDoublePtr aRadiusAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+        myFeatureMap.begin()->first->attribute(SketchPlugin_Circle::RADIUS_ID()));
+    Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER,
+        myGroup->getWorkplaneId(), aRadiusAttr->value() * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
+        myFeatureMap.begin()->second, SLVS_E_UNKNOWN);
+    aFixedR.h = myStorage->addConstraint(aFixedR);
+    mySlvsConstraints.push_back(aFixedR.h);
+  }
+}
 
 void SketchSolver_ConstraintRigid::fixArc(const Slvs_Entity& theArc)
 {
-  Slvs_Constraint aConstraint;
+  bool isFixRadius = true;
+  std::list<Slvs_hEntity> aPointsToFix;
+  aPointsToFix.push_back(theArc.point[1]);
+  aPointsToFix.push_back(theArc.point[2]);
+
+  // Verify the arc is under Equal constraint
+  Slvs_Constraint anEqual;
+  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)) {
+      isFixRadius = false;
+      if (anOtherEntity.type == SLVS_E_LINE_SEGMENT) {
+        aPointsToFix.pop_back();
+        aPointsToFix.push_back(theArc.point[0]);
+      }
+    }
+  }
+
   Slvs_hConstraint aConstrID = myStorage->isPointFixed(theArc.point[0]);
-  int aPointsToFix = 2; // number of fixed points for the arc
+  int aNbPointsToFix = 2; // number of fixed points for the arc
   if (aConstrID != SLVS_E_UNKNOWN)
-    aPointsToFix--;
+    aNbPointsToFix--;
 
   // Radius of the arc
   FeaturePtr aFeature = myFeatureMap.begin()->first;
@@ -218,32 +293,69 @@ void SketchSolver_ConstraintRigid::fixArc(const Slvs_Entity& theArc)
     myStorage->updateParameter(aParam);
   }
 
-  for (int i = 1; aPointsToFix > 0; i++, aPointsToFix--) {
-    aConstrID = myStorage->isPointFixed(theArc.point[i]);
-    if (aConstrID != SLVS_E_UNKNOWN)
-      continue; // the coincident point is already fixed
-    aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(),
-        0.0, theArc.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-    aConstraint.h = myStorage->addConstraint(aConstraint);
-    mySlvsConstraints.push_back(aConstraint.h);
-    if (!myBaseConstraint)
-      myStorage->addConstraintWhereDragged(aConstraint.h);
+  std::list<Slvs_hEntity>::iterator aPtIt = aPointsToFix.begin();
+  for (; aNbPointsToFix > 0; aPtIt++, aNbPointsToFix--)
+    fixPoint(*aPtIt);
+
+  if (isFixRadius) {
+    // Fix radius of the arc
+    bool isExists = false;
+    std::list<Slvs_Constraint> aDiamConstraints = myStorage->getConstraintsByType(SLVS_C_DIAMETER);
+    std::list<Slvs_Constraint>::iterator anIt = aDiamConstraints.begin();
+    for (; anIt != aDiamConstraints.end() && !isExists; anIt++)
+      if (anIt->entityA == myFeatureMap.begin()->second)
+        isExists = true;
+    if (!isExists) {
+      Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER,
+          myGroup->getWorkplaneId(), aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
+          myFeatureMap.begin()->second, SLVS_E_UNKNOWN);
+      aFixedR.h = myStorage->addConstraint(aFixedR);
+      mySlvsConstraints.push_back(aFixedR.h);
+      if (!myBaseConstraint)
+        myStorage->addConstraintWhereDragged(aFixedR.h);
+    }
   }
+}
 
-  // Fix radius of the arc
-  bool isExists = false;
-  std::list<Slvs_Constraint> aDiamConstraints = myStorage->getConstraintsByType(SLVS_C_DIAMETER);
-  std::list<Slvs_Constraint>::iterator anIt = aDiamConstraints.begin();
-  for (; anIt != aDiamConstraints.end() && !isExists; anIt++)
-    if (anIt->entityA == myFeatureMap.begin()->second)
-      isExists = true;
-  if (!isExists) {
-    aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER, myGroup->getWorkplaneId(),
-      aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, myFeatureMap.begin()->second, SLVS_E_UNKNOWN);
-    aConstraint.h = myStorage->addConstraint(aConstraint);
-    mySlvsConstraints.push_back(aConstraint.h);
-    if (!myBaseConstraint)
-      myStorage->addConstraintWhereDragged(aConstraint.h);
+bool SketchSolver_ConstraintRigid::isUsedInEqual(
+    const Slvs_Entity& theEntity, Slvs_Constraint& theEqual) const
+{
+  // Check the entity is used in Equal constraint
+  std::list<Slvs_Constraint> anEqualConstr = myStorage->getConstraintsByType(SLVS_C_EQUAL_LENGTH_LINES);
+  std::list<Slvs_Constraint> anAddList = myStorage->getConstraintsByType(SLVS_C_EQUAL_LINE_ARC_LEN);
+  anEqualConstr.insert(anEqualConstr.end(), anAddList.begin(), anAddList.end());
+  anAddList = myStorage->getConstraintsByType(SLVS_C_EQUAL_RADIUS);
+  anEqualConstr.insert(anEqualConstr.end(), anAddList.begin(), anAddList.end());
+
+  std::list<Slvs_Constraint>::const_iterator anEqIter = anEqualConstr.begin();
+  for (; anEqIter != anEqualConstr.end(); anEqIter++)
+    if (anEqIter->entityA == theEntity.h || anEqIter->entityB == theEntity.h) {
+      theEqual = *anEqIter;
+      return true;
+    }
+  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 dd148778262f96732317f7b56cdf3c718f9c555e..93de5836226da0e16e3e5750b81056ae415c7aa9 100644 (file)
@@ -49,11 +49,27 @@ protected:
   virtual void adjustConstraint();
 
 private:
+  /// \brief Fixing line position (start and end points)
+  void fixLine(const Slvs_Entity& theLine);
+  /// \brief Fixing circle (center and radius)
+  void fixCircle(const Slvs_Entity& theCircle);
   /// \brief The arc is fixed differently to avoid SolveSpace problems (overconstraint)
   ///
   /// There will be fixed start and end points and the radius of the arc.
   void fixArc(const Slvs_Entity& theArc);
 
+  /// \brief Fix given point
+  void fixPoint(const Slvs_hEntity& thePointID);
+
+  /// \brief Verifies the entity is used in any equal constraint
+  /// \param[in]  theEntity entity to be found
+  /// \param[out] theEqual  constraint, which uses the entity
+  /// \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 3623354b196aa582c6fb4233eb8825702e852a73..e0446b558eb8e699510a45d027ecfafe3bb782aa 100644 (file)
@@ -59,6 +59,12 @@ class SketchSolver_Error
     static const std::string MY_ERROR_VALUE("Mirror constraint has wrong attributes");
     return MY_ERROR_VALUE;
   }
+  /// Crash in SolveSpace
+  inline static const std::string& SOLVESPACE_CRASH()
+  {
+    static const std::string MY_ERROR_VALUE("Caution: SolveSpace crash! Constraints are wrong");
+    return MY_ERROR_VALUE;
+  }
 };
 
 #endif
index d647d075b6f1cca79b74cf3d17e4dd20bd5e21b2..e274244fb3dba6eb56dfbf4f24a371e28021c09c 100644 (file)
@@ -248,6 +248,8 @@ bool SketchSolver_FeatureStorage::isInteract(FeaturePtr theFeature) const
 {
   if (myFeatures.find(theFeature) != myFeatures.end())
     return true;
+  if (!theFeature->data() || !theFeature->data()->isValid())
+    return false;
 
   std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
   std::list<AttributePtr>::iterator anIter = anAttributes.begin();
index 7fdc32a4c5e74b5c2c1ee514339fd2d28f60e298..3c5832cdb793c7155a872ba79dce491c84416a0e 100644 (file)
@@ -258,6 +258,10 @@ 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())
+      continue;
+    myFeatureStorage->changeFeature(theFeature, aSolConIter->first);
+    aSolConIter->second->addFeature(theFeature);
     aSolConIter->second->update();
   }
   return true;
@@ -384,7 +388,13 @@ bool SketchSolver_Group::resolveConstraints()
     myConstrSolver.setGroupID(myID);
     myStorage->initializeSolver(myConstrSolver);
 
-    int aResult = myConstrSolver.solve();
+    int aResult = SLVS_RESULT_OKAY;
+    try {
+      aResult = myConstrSolver.solve();
+    } catch (...) {
+      Events_Error::send(SketchSolver_Error::SOLVESPACE_CRASH(), this);
+      return false;
+    }
     if (aResult == SLVS_RESULT_OKAY) {  // solution succeeded, store results into correspondent attributes
       myFeatureStorage->blockEvents(true);
       ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin();
index 40d1d281f55e1c7afd4f5c8808720c2143833162..f13ad6b6f861d5aa026a06407c1fa94337686509 100644 (file)
@@ -192,6 +192,60 @@ const Slvs_Entity& SketchSolver_Storage::getEntity(const Slvs_hEntity& theEntity
   return aDummy;
 }
 
+Slvs_hEntity SketchSolver_Storage::copyEntity(const Slvs_hEntity& theCopied)
+{
+  int aPos = Search(theCopied, myEntities);
+  if (aPos < 0 || aPos >= (int)myEntities.size())
+    return SLVS_E_UNKNOWN;
+
+  Slvs_Entity aCopy = myEntities[aPos];
+  aCopy.h = SLVS_E_UNKNOWN;
+  int i = 0;
+  while (aCopy.point[i] != SLVS_E_UNKNOWN) {
+    aCopy.point[i] = copyEntity(aCopy.point[i]);
+    i++;
+  }
+  if (aCopy.param[0] != SLVS_E_UNKNOWN) {
+    aPos = Search(aCopy.param[0], myParameters);
+    i = 0;
+    while (aCopy.param[i] != SLVS_E_UNKNOWN) {
+      Slvs_Param aNewParam = myParameters[aPos];
+      aNewParam.h = SLVS_E_UNKNOWN;
+      aCopy.param[i] = addParameter(aNewParam);
+      i++;
+      aPos++;
+    }
+  }
+  return addEntity(aCopy);
+}
+
+void SketchSolver_Storage::copyEntity(const Slvs_hEntity& theFrom, const Slvs_hEntity& theTo)
+{
+  int aPosFrom = Search(theFrom, myEntities);
+  int aPosTo = Search(theTo, myEntities);
+  if (aPosFrom < 0 || aPosFrom >= (int)myEntities.size() || 
+      aPosTo < 0 || aPosTo >= (int)myEntities.size())
+    return;
+
+  Slvs_Entity aEntFrom = myEntities[aPosFrom];
+  Slvs_Entity aEntTo = myEntities[aPosTo];
+  int i = 0;
+  while (aEntFrom.point[i] != SLVS_E_UNKNOWN) {
+    copyEntity(aEntFrom.point[i], aEntTo.point[i]);
+    i++;
+  }
+  if (aEntFrom.param[0] != SLVS_E_UNKNOWN) {
+    aPosFrom = Search(aEntFrom.param[0], myParameters);
+    aPosTo = Search(aEntTo.param[0], myParameters);
+    i = 0;
+    while (aEntFrom.param[i] != SLVS_E_UNKNOWN) {
+      myParameters[aPosTo++].val = myParameters[aPosFrom++].val;
+      i++;
+    }
+  }
+}
+
+
 Slvs_hConstraint SketchSolver_Storage::isPointFixed(const Slvs_hEntity& thePointID) const
 {
   // Search the set of coincident points
index a95d83c72c032a9b7bda639641a02fadf27e8c27..613e0ec29ab812af6b1f4c6b6afe388e36356342 100644 (file)
@@ -60,6 +60,10 @@ public:
   bool removeEntity(const Slvs_hEntity& theEntityID);
   /// \brief Returns the entity by its ID
   const Slvs_Entity& getEntity(const Slvs_hEntity& theEntityID) const;
+  /// \brief Makes a full copy of the given entity
+  Slvs_hEntity copyEntity(const Slvs_hEntity& theCopied);
+  /// \brief Copy one entity to another
+  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
index 368dbb57469080e6f02d66e23a37690cb3388df4..0eff27bb2944ec5c70e7539661fc943330c15904 100644 (file)
@@ -45,6 +45,8 @@ const int MOUSE_SENSITIVITY_IN_PIXEL = 10;  ///< defines the local context mouse
 
 //#define DEBUG_DISPLAY
 //#define DEBUG_ACTIVATE
+//#define DEBUG_FEATURE_REDISPLAY
+//#define DEBUG_SELECTION_FILTERS
 
 // Workaround for bug #25637
 void displayedObjects(const Handle(AIS_InteractiveContext)& theAIS, AIS_ListOfInteractive& theList)
@@ -248,8 +250,15 @@ void XGUI_Displayer::redisplay(ObjectPtr theObject, bool isUpdateViewer)
     }
     // Customization of presentation
     bool isCustomized = customizeObject(theObject);
+    #ifdef DEBUG_FEATURE_REDISPLAY
+      qDebug(QString("Redisplay: %1, isEqualShapes=%2, isCustomized=%3").
+        arg(!isEqualShapes || isCustomized).arg(isEqualShapes).arg(isCustomized).toStdString().c_str());
+    #endif
     if (!isEqualShapes || isCustomized) {
       aContext->Redisplay(aAISIO, false);
+      #ifdef DEBUG_FEATURE_REDISPLAY
+      //qDebug("  Redisplay happens");
+      #endif
       if (isUpdateViewer)
         updateViewer();
     }
@@ -698,7 +707,17 @@ void XGUI_Displayer::addSelectionFilter(const Handle(SelectMgr_Filter)& theFilte
     if (theFilter.Access() == aIt.Value().Access())
       return;
   }
-  GetFilter()->Add(theFilter);
+  Handle(SelectMgr_CompositionFilter) aCompFilter = GetFilter();
+  const SelectMgr_ListOfFilter& aStoredFilters = aCompFilter->StoredFilters();
+  for (aIt.Initialize(aStoredFilters); aIt.More(); aIt.Next()) {
+    if (theFilter.Access() == aIt.Value().Access())
+      return;
+  }
+  aCompFilter->Add(theFilter);
+#ifdef DEBUG_SELECTION_FILTERS
+  int aCount = GetFilter()->StoredFilters().Extent();
+  qDebug(QString("addSelectionFilter: filters.count() = %1").arg(aCount).toStdString().c_str());
+#endif
 }
 
 void XGUI_Displayer::removeSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
@@ -709,6 +728,10 @@ void XGUI_Displayer::removeSelectionFilter(const Handle(SelectMgr_Filter)& theFi
   Handle(SelectMgr_AndFilter) aCompositeFilter = GetFilter();
   if (aCompositeFilter->IsIn(theFilter))
     aCompositeFilter->Remove(theFilter);
+#ifdef DEBUG_SELECTION_FILTERS
+  int aCount = GetFilter()->StoredFilters().Extent();
+  qDebug(QString("removeSelectionFilter: filters.count() = %1").arg(aCount).toStdString().c_str());
+#endif
 }
 
 void XGUI_Displayer::removeFilters()
@@ -754,6 +777,14 @@ void XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO,
     return;
 
   // deactivate object in all modes, which are not in the list of activation
+  // It seems that after the IO deactivation the selected state of the IO's owners
+  // is modified in OCC(version: 6.8.0) and the selection of the object later is lost.
+  // By this reason, the number of the IO deactivate is decreased and the object is deactivated
+  // only if there is a difference in the current modes and the parameters modes.
+  // If the selection problem happens again, it is possible to write a test scenario and create
+  // a bug. The bug steps are the following:
+  // Create two IO, activate them in 5 modes, select the first IO, deactivate 3 modes for both,
+  // with clicked SHIFT select the second object. The result is the selection of the first IO is lost.
   TColStd_ListOfInteger aTColModes;
   aContext->ActivatedModes(theIO, aTColModes);
   TColStd_ListIteratorOfListOfInteger itr( aTColModes );
index 6811bafdfb13f1850f8749b7af97be2a00db8788..b2860a24069e7f77d7b5afccb2ce12a4643bc064 100644 (file)
@@ -72,6 +72,12 @@ class XGUI_EXPORT XGUI_Displayer: public QObject
   /// \param isUpdate the parameter whether the viewer should be update immediatelly
   void displayAIS(AISObjectPtr theAIS, bool isUpdate = true);
 
+  /** Redisplay the shape if it was displayed
+   * \param theObject an object instance
+   * \param isUpdateViewer the parameter whether the viewer should be update immediatelly
+   */
+  void redisplay(ObjectPtr theObject, bool isUpdateViewer = true);
+
   /**
    * Add presentations which corresponds to the given features to current selection
    * \param theFeatures a list of features to be selected
@@ -226,12 +232,7 @@ signals:
   void display(ObjectPtr theObject, AISObjectPtr theAIS, bool isShading,
                bool isUpdateViewer = true);
 
-  /** Redisplay the shape if it was displayed
-   * \param theObject an object instance
-   * \param isUpdateViewer the parameter whether the viewer should be update immediatelly
-   */
-  void redisplay(ObjectPtr theObject, bool isUpdateViewer = true);
-
+private:
   /// Activates the interactive object in the local context.
   /// \param theIO an interactive object
   /// \param theModes - modes on which it has to be activated (can be empty)
index 41c911529b558fc01f1ebe6032f7a178c3fe7b33..7571de5f16faa9364bbcfb140ca71fe808a66f33 100644 (file)
@@ -550,7 +550,11 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptr<ModelAPI_ObjectU
       #endif
 
       if (isVisibleObject)  { // redisplay visible object
-        displayObject(aObj);  // In order to update presentation
+        //displayObject(aObj);  // In order to update presentation
+        // in order to avoid the check whether the object can be redisplayed, the exact method
+        // of redisplay is called. This modification is made in order to have the line is updated
+        // by creation of a horizontal constraint on the line by preselection
+        myDisplayer->redisplay(aObj, false);
         if (myOperationMgr->hasOperation()) {
           ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
           if (!aOperation->isEditOperation() &&