]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
SketchSolver library refactoring
authorazv <azv@opencascade.com>
Tue, 31 Mar 2015 14:20:40 +0000 (17:20 +0300)
committerazv <azv@opencascade.com>
Fri, 3 Apr 2015 06:26:38 +0000 (09:26 +0300)
1. Implemented distance and length constraints

16 files changed:
src/SketchSolver/CMakeLists.txt
src/SketchSolver/SketchSolver_Builder.cpp
src/SketchSolver/SketchSolver_Constraint.cpp
src/SketchSolver/SketchSolver_Constraint.h
src/SketchSolver/SketchSolver_ConstraintDistance.cpp [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintDistance.h [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintLength.cpp [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintLength.h [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintManager.cpp
src/SketchSolver/SketchSolver_ConstraintRigid.cpp
src/SketchSolver/SketchSolver_Error.h
src/SketchSolver/SketchSolver_Group.cpp
src/SketchSolver/SketchSolver_Group.h
src/SketchSolver/SketchSolver_Solver.cpp
src/SketchSolver/SketchSolver_Storage.cpp
src/SketchSolver/SketchSolver_Storage.h

index fed46c0ec6414e91013c3e60e214087cca2343b0..334ee0451d2af19c1dc983d0c5a43e32627909f7 100644 (file)
@@ -9,6 +9,8 @@ SET(PROJECT_HEADERS
     SketchSolver_Solver.h
     SketchSolver_Constraint.h
     SketchSolver_ConstraintCoincidence.h
+    SketchSolver_ConstraintDistance.h
+    SketchSolver_ConstraintLength.h
     SketchSolver_ConstraintRigid.h
     SketchSolver_Builder.h
     SketchSolver_Group.h
@@ -21,6 +23,8 @@ SET(PROJECT_SOURCES
     SketchSolver_Solver.cpp
     SketchSolver_Constraint.cpp
     SketchSolver_ConstraintCoincidence.cpp
+    SketchSolver_ConstraintDistance.cpp
+    SketchSolver_ConstraintLength.cpp
     SketchSolver_ConstraintRigid.cpp
     SketchSolver_Builder.cpp
     SketchSolver_Group.cpp
index 67fbdc1f2266400f29ef1a8fb05ce66f3a3dc0a5..4f0d05ab11b06196a0b7eafdba20453ce7248090 100644 (file)
@@ -6,6 +6,8 @@
 
 #include "SketchSolver_Builder.h"
 #include <SketchSolver_ConstraintCoincidence.h>
+#include <SketchSolver_ConstraintDistance.h>
+#include <SketchSolver_ConstraintLength.h>
 #include <SketchSolver_ConstraintRigid.h>
 
 #include <GeomAPI_Edge.h>
@@ -65,7 +67,7 @@ SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theCons
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintHorizontal::ID()) {
     return SolverConstraintPtr(new SketchSolver_ConstraintHorizontal(theConstraint));
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) {
-////    return SolverConstraintPtr(new SketchSolver_ConstraintLength(theConstraint));
+    return SolverConstraintPtr(new SketchSolver_ConstraintLength(theConstraint));
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
 ////    return SolverConstraintPtr(new SketchSolver_ConstraintMirror(theConstraint));
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintParallel::ID()) {
index d8d3df086193ca2a2d3689d04b5a7d96464ce4ec..2cdd24eb796e3840682658844ca98449624b604f 100644 (file)
@@ -97,6 +97,7 @@ void SketchSolver_Constraint::process()
     mySlvsConstraints.push_back(anID);
   else
     mySlvsConstraints[0] = anID;
+  adjustConstraint();
 }
 
 void SketchSolver_Constraint::update(ConstraintPtr theConstraint)
@@ -110,13 +111,48 @@ void SketchSolver_Constraint::update(ConstraintPtr theConstraint)
     process();
   }
 
+  // Update all attributes
   int aType;
+  std::map<Slvs_hEntity, Slvs_hEntity> aRelocationMap;
   std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIter = myFeatureMap.begin();
-  for (; aFeatIter != myFeatureMap.end(); aFeatIter++)
+  for (; aFeatIter != myFeatureMap.end(); aFeatIter++) {
+    Slvs_hEntity aPrevID = aFeatIter->second;
     aFeatIter->second = changeEntity(aFeatIter->first, aType);
+    if (aFeatIter->second != aPrevID)
+      aRelocationMap[aPrevID] = aFeatIter->second;
+  }
   std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
-  for (; anAttrIter != myAttributeMap.end(); anAttrIter++)
+  for (; anAttrIter != myAttributeMap.end(); anAttrIter++) {
+    Slvs_hEntity aPrevID = anAttrIter->second;
     anAttrIter->second = changeEntity(anAttrIter->first, aType);
+    if (anAttrIter->second != aPrevID)
+      aRelocationMap[aPrevID] = anAttrIter->second;
+  }
+
+  // Value if exists
+  AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+    myBaseConstraint->data()->attribute(SketchPlugin_Constraint::VALUE()));
+  double aValue = aValueAttr ? aValueAttr->value() : 0.0;
+
+  // Update constraint
+  std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
+  for (; aCIter != mySlvsConstraints.end(); aCIter++) {
+    Slvs_Constraint aConstraint = myStorage->getConstraint(*aCIter);
+    aConstraint.valA = aValue;
+    Slvs_hEntity* aCoeffs[6] = {
+        &aConstraint.ptA, &aConstraint.ptB,
+        &aConstraint.entityA, &aConstraint.entityB,
+        &aConstraint.entityC, &aConstraint.entityD};
+    for (int i = 0; i < 6; i++) {
+      if (*(aCoeffs[i]) == SLVS_E_UNKNOWN)
+        continue;
+      std::map<Slvs_hEntity, Slvs_hEntity>::iterator aFound = aRelocationMap.find(*(aCoeffs[i]));
+      if (aFound != aRelocationMap.end())
+        *(aCoeffs[i]) = aFound->second;
+    }
+    *aCIter = myStorage->addConstraint(aConstraint);
+  }
+  adjustConstraint();
 }
 
 bool SketchSolver_Constraint::remove(ConstraintPtr theConstraint)
@@ -363,7 +399,7 @@ Slvs_hEntity SketchSolver_Constraint::changeEntity(FeaturePtr theEntity, int& th
     int anAttrType;
 
     // Line
-    if (aFeatureKind.compare(SketchPlugin_Line::ID()) == 0) {
+    if (aFeatureKind == SketchPlugin_Line::ID()) {
       anAttribute = aFeature->data()->attribute(SketchPlugin_Line::START_ID());
       if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
       Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
@@ -381,7 +417,7 @@ Slvs_hEntity SketchSolver_Constraint::changeEntity(FeaturePtr theEntity, int& th
       aResult = myStorage->addEntity(aCurrentEntity);
     }
     // Circle
-    else if (aFeatureKind.compare(SketchPlugin_Circle::ID()) == 0) {
+    else if (aFeatureKind == SketchPlugin_Circle::ID()) {
       anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID());
       if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
       Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
@@ -401,7 +437,7 @@ Slvs_hEntity SketchSolver_Constraint::changeEntity(FeaturePtr theEntity, int& th
       aResult = myStorage->addEntity(aCurrentEntity);
     }
     // Arc
-    else if (aFeatureKind.compare(SketchPlugin_Arc::ID()) == 0) {
+    else if (aFeatureKind == SketchPlugin_Arc::ID()) {
       anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID());
       if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
       Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
@@ -426,7 +462,7 @@ Slvs_hEntity SketchSolver_Constraint::changeEntity(FeaturePtr theEntity, int& th
       aResult = myStorage->addEntity(aCurrentEntity);
     }
     // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
-    else if (aFeatureKind.compare(SketchPlugin_Point::ID()) == 0) {
+    else if (aFeatureKind == SketchPlugin_Point::ID()) {
       anAttribute = aFeature->data()->attribute(SketchPlugin_Point::COORD_ID());
       if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
       // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier
@@ -435,8 +471,10 @@ Slvs_hEntity SketchSolver_Constraint::changeEntity(FeaturePtr theEntity, int& th
     }
   }
 
-  myFeatureMap[theEntity] = aResult;
-  theType = aCurrentEntity.type;
+  if (aResult != SLVS_E_UNKNOWN) {
+    myFeatureMap[theEntity] = aResult;
+    theType = aCurrentEntity.type;
+  }
   return aResult;
 }
 
index b7925d66c9c400190818c55426f0709d29d8efcf..6a57f6b2182def8f4382a7d02a3a602f509bbc3f 100644 (file)
@@ -76,6 +76,11 @@ protected:
   /// \param[out] theAttributes list of attributes to be filled
   virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
 
+  /// \brief This method is used in derived objects to check consistence of constraint.
+  ///        E.g. the distance between line and point may be signed.
+  virtual void adjustConstraint()
+  {}
+
   /// \brief Create or change SlveSpace entity according to the given attribute
   /// \param[in]  theAttribute  reference to the entity to be changed
   /// \param[out] theType       type of created entity
@@ -109,22 +114,6 @@ typedef std::shared_ptr<SketchSolver_Constraint> SolverConstraintPtr;
 
 
 
-/** \class   SketchSolver_ConstraintDistance
- *  \ingroup Plugins
- *  \brief   Convert distance constraint to SolveSpace structure
- */
-class SketchSolver_ConstraintDistance : public SketchSolver_Constraint
-{
-public:
-  SketchSolver_ConstraintDistance(ConstraintPtr theConstraint) :
-      SketchSolver_Constraint(theConstraint)
-  {}
-
-  virtual int getType() const
-  { return SLVS_C_PT_PT_DISTANCE; }
-};
-
-
 /** \class   SketchSolver_ConstraintParallel
  *  \ingroup Plugins
  *  \brief   Convert Parallel constraint to SolveSpace structure
diff --git a/src/SketchSolver/SketchSolver_ConstraintDistance.cpp b/src/SketchSolver/SketchSolver_ConstraintDistance.cpp
new file mode 100644 (file)
index 0000000..51f0d73
--- /dev/null
@@ -0,0 +1,87 @@
+#include <SketchSolver_ConstraintDistance.h>
+#include <SketchSolver_Group.h>
+#include <SketchSolver_Error.h>
+
+#include <GeomAPI_XY.h>
+
+
+void SketchSolver_ConstraintDistance::process()
+{
+  cleanErrorMsg();
+  if (!myBaseConstraint || !myStorage || myGroup == 0) {
+    /// TODO: Put error message here
+    return;
+  }
+  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+    update(myBaseConstraint);
+
+  double aValue;
+  std::vector<Slvs_hEntity> anEntities;
+  getAttributes(aValue, anEntities);
+  if (!myErrorMsg.empty())
+    return;
+
+  // Obtain entities to identify the type of distance
+  static const int aNbPoints = 2;
+  Slvs_hEntity aPoint[aNbPoints] = {SLVS_E_UNKNOWN, SLVS_E_UNKNOWN};
+  Slvs_hEntity aLine = SLVS_E_UNKNOWN;
+  myType = SLVS_C_PT_PT_DISTANCE;
+  int aPtPos = 0;
+  std::vector<Slvs_hEntity>::iterator anEntIter = anEntities.begin();
+  for (; anEntIter != anEntities.end(); anEntIter++) {
+    if (*anEntIter == SLVS_E_UNKNOWN)
+      continue;
+    Slvs_Entity anEnt = myStorage->getEntity(*anEntIter);
+    if (anEnt.type == SLVS_E_POINT_IN_2D || anEnt.type == SLVS_E_POINT_IN_3D) {
+      if (aPtPos >= aNbPoints) {
+        myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+        return;
+      }
+      aPoint[aPtPos++] = *anEntIter;
+    }
+    else if (anEnt.type == SLVS_E_LINE_SEGMENT) {
+      if (myType == SLVS_C_PT_LINE_DISTANCE) {
+        myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+        return;
+      }
+      aLine = *anEntIter;
+      myType = SLVS_C_PT_LINE_DISTANCE;
+    }
+  }
+
+  Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+      getType(), myGroup->getWorkplaneId(), aValue, aPoint[0], aPoint[1], aLine, SLVS_E_UNKNOWN);
+  aConstraint.h = myStorage->addConstraint(aConstraint);
+  mySlvsConstraints.push_back(aConstraint.h);
+  adjustConstraint();
+}
+
+void SketchSolver_ConstraintDistance::adjustConstraint()
+{
+  if (getType() != SLVS_C_PT_LINE_DISTANCE)
+    return;
+
+  // Get constraint parameters and check the sign of constraint value
+  std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
+  for (; aCIter != mySlvsConstraints.end(); aCIter++) {
+    Slvs_Constraint aConstraint = myStorage->getConstraint(*aCIter);
+    Slvs_Entity aLine = myStorage->getEntity(aConstraint.entityA);
+    // Obtain point and line coordinates
+    Slvs_hEntity aPointID[3] = {aConstraint.ptA, aLine.point[0], aLine.point[1]};
+    std::shared_ptr<GeomAPI_XY> aPoints[3];
+    for (int i = 0; i < 3; i++) {
+      Slvs_Entity aPoint = myStorage->getEntity(aPointID[i]);
+      Slvs_Param aParams[2] = {
+          myStorage->getParameter(aPoint.param[0]),
+          myStorage->getParameter(aPoint.param[1])};
+      aPoints[i] = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(aParams[0].val, aParams[1].val));
+    }
+    std::shared_ptr<GeomAPI_XY> aLineVec = aPoints[2]->decreased(aPoints[1]);
+    std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoints[0]->decreased(aPoints[1]);
+    if (aPtLineVec->cross(aLineVec) * aConstraint.valA < 0.0) {
+      aConstraint.valA *= -1.0;
+      myStorage->updateConstraint(aConstraint);
+    }
+  }
+}
+
diff --git a/src/SketchSolver/SketchSolver_ConstraintDistance.h b/src/SketchSolver/SketchSolver_ConstraintDistance.h
new file mode 100644 (file)
index 0000000..48cadbf
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    SketchSolver_ConstraintDistance.h
+// Created: 31 Mar 2015
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintDistance_H_
+#define SketchSolver_ConstraintDistance_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Constraint.h>
+
+/** \class   SketchSolver_ConstraintDistance
+ *  \ingroup Plugins
+ *  \brief   Convert distance constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintDistance : public SketchSolver_Constraint
+{
+public:
+  SketchSolver_ConstraintDistance(ConstraintPtr theConstraint) :
+      SketchSolver_Constraint(theConstraint), myType(SLVS_C_UNKNOWN)
+  {}
+
+  virtual int getType() const
+  {return myType; }
+
+protected:
+  /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+  virtual void process();
+
+  /// \brief Verifies the sign of the distance between line and point and change it if necessary
+  virtual void adjustConstraint();
+
+private:
+  int myType; ///< type of constraint (applicable: SLVS_C_PT_PT_DISTANCE, SLVS_C_PT_LINE_DISTANCE)
+};
+
+#endif
diff --git a/src/SketchSolver/SketchSolver_ConstraintLength.cpp b/src/SketchSolver/SketchSolver_ConstraintLength.cpp
new file mode 100644 (file)
index 0000000..3d1d1bf
--- /dev/null
@@ -0,0 +1,36 @@
+#include <SketchSolver_ConstraintLength.h>
+#include <SketchSolver_Group.h>
+#include <SketchSolver_Error.h>
+
+
+void SketchSolver_ConstraintLength::process()
+{
+  cleanErrorMsg();
+  if (!myBaseConstraint || !myStorage || myGroup == 0) {
+    /// TODO: Put error message here
+    return;
+  }
+  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+    update(myBaseConstraint);
+
+  double aValue;
+  std::vector<Slvs_hEntity> anEntities;
+  getAttributes(aValue, anEntities);
+  if (!myErrorMsg.empty())
+    return;
+
+  // Check the entity is a line
+  Slvs_Entity aLine = myStorage->getEntity(anEntities[2]);
+  if (aLine.type != SLVS_E_LINE_SEGMENT){
+    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+    return;
+  }
+
+  Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+      getType(), myGroup->getWorkplaneId(), aValue,
+      aLine.point[0], aLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+  aConstraint.h = myStorage->addConstraint(aConstraint);
+  mySlvsConstraints.push_back(aConstraint.h);
+  adjustConstraint();
+}
+
diff --git a/src/SketchSolver/SketchSolver_ConstraintLength.h b/src/SketchSolver/SketchSolver_ConstraintLength.h
new file mode 100644 (file)
index 0000000..176c694
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    SketchSolver_ConstraintLength.h
+// Created: 31 Mar 2015
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintLength_H_
+#define SketchSolver_ConstraintLength_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Constraint.h>
+
+/** \class   SketchSolver_ConstraintLength
+ *  \ingroup Plugins
+ *  \brief   Convert length constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintLength : public SketchSolver_Constraint
+{
+public:
+  SketchSolver_ConstraintLength(ConstraintPtr theConstraint) :
+      SketchSolver_Constraint(theConstraint)
+  {}
+
+  virtual int getType() const
+  { return SLVS_C_PT_PT_DISTANCE; }
+
+protected:
+  /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+  virtual void process();
+
+private:
+  int myType; ///< type of constraint (applicable: SLVS_C_PT_PT_DISTANCE, SLVS_C_PT_LINE_DISTANCE)
+};
+
+#endif
index 1e80079c96c2406ff039fb43bd82f1306ebdd3a2..2dbd6c57d6b03452c0586d47521531eca5e24022 100644 (file)
@@ -224,7 +224,8 @@ bool SketchSolver_ConstraintManager::changeConstraintOrEntity(
     for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
       if ((*aGroupIter)->getId() == aGroupId) {
         // If the group is empty, the feature is not added (the constraint only)
-////        if (!aConstraint && !(*aGroupIter)->isEmpty())
+        if (!aConstraint && !(*aGroupIter)->isEmpty())
+          return (*aGroupIter)->updateFeature(theFeature);
 ////          return (*aGroupIter)->changeEntityFeature(theFeature) != SLVS_E_UNKNOWN;
         return (*aGroupIter)->changeConstraint(aConstraint);
       }
@@ -261,6 +262,7 @@ bool SketchSolver_ConstraintManager::changeConstraintOrEntity(
 
     if (aConstraint)
       return (*aFirstGroupIter)->changeConstraint(aConstraint);
+    return (*aFirstGroupIter)->updateFeature(theFeature);
 ////    return (*aFirstGroupIter)->changeEntityFeature(theFeature) != SLVS_E_UNKNOWN;
   }
 
index 02ba819a85d89f6ed58d31db10daf17ad11f9a2f..12815acf314300a61a83ba916b62af4bf7efe1a6 100644 (file)
@@ -30,7 +30,13 @@ void SketchSolver_ConstraintRigid::process()
   bool isEmpty = aConstrIter == mySlvsConstraints.end();
   std::vector<Slvs_hEntity>::const_iterator anEntIter = anEntities.begin();
   for (; anEntIter != anEntities.end(); anEntIter++) {
-    if (isEmpty) { // create new constraint
+    if (*anEntIter == SLVS_E_UNKNOWN)
+      continue;
+    Slvs_hConstraint aConstrID = myStorage->isPointFixed(*anEntIter);
+    bool isForceUpdate = (aConstrID != SLVS_E_UNKNOWN && !myBaseConstraint);
+    if (isEmpty && !isForceUpdate) { // create new constraint
+      if (aConstrID != SLVS_E_UNKNOWN)
+        continue; // the coincident point is already fixed
       aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(),
           aValue, *anEntIter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
       aConstraint.h = myStorage->addConstraint(aConstraint);
@@ -38,11 +44,17 @@ void SketchSolver_ConstraintRigid::process()
       if (!myBaseConstraint)
         myStorage->addTemporaryConstraint(aConstraint.h);
     } else { // update already existent constraint
-      aConstraint = myStorage->getConstraint(*aConstrIter);
+      if (aConstrID == SLVS_E_UNKNOWN || myBaseConstraint)
+        aConstrID = *aConstrIter;
+      aConstraint = myStorage->getConstraint(aConstrID);
       aConstraint.ptA = *anEntIter;
       myStorage->addConstraint(aConstraint);
-      aConstrIter++;
-      isEmpty = aConstrIter == mySlvsConstraints.end();
+      if (!myBaseConstraint)
+        myStorage->addTemporaryConstraint(aConstraint.h);
+      if (!isEmpty) {
+        aConstrIter++;
+        isEmpty = aConstrIter == mySlvsConstraints.end();
+      }
     }
   }
 }
@@ -59,7 +71,7 @@ void SketchSolver_ConstraintRigid::getAttributes(
     // Get the attribute of constraint
     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
         myBaseConstraint->attribute(SketchPlugin_ConstraintRigid::ENTITY_A()));
-    if (!aRefAttr) {
+    if (!aRefAttr || !aRefAttr->isInitialized()) {
       myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
       return;
     }
index 0ef01476ea599d295237eae951417b9c2c01d783..dfae098bf8b1f14bda7fe20eac86ab4e8094deb3 100644 (file)
@@ -35,6 +35,12 @@ class SketchSolver_Error
     static const std::string MY_ERROR_VALUE("Attribute is not initialized");
     return MY_ERROR_VALUE;
   }
+  /// Constraint has wrong attributes
+  inline static const std::string& INCORRECT_ATTRIBUTE()
+  {
+    static const std::string MY_ERROR_VALUE("Incorrect attribute");
+    return MY_ERROR_VALUE;
+  }
 };
 
 #endif
index f5b0ee38707d2c4e95a68aa81f30ddbdc67e4f51..493fdbf37f36250b74a1a5e0f5d21e1048083548 100644 (file)
@@ -156,41 +156,6 @@ Slvs_hEntity SketchSolver_Group::getAttributeId(AttributePtr theAttribute) const
   return aCIter->second->getId(theAttribute);
 }
 
-
-////// ============================================================================
-//////  Function: checkConstraintConsistence
-//////  Class:    SketchSolver_Group
-//////  Purpose:  verifies and changes parameters of the constraint
-////// ============================================================================
-////void SketchSolver_Group::checkConstraintConsistence(Slvs_Constraint& theConstraint)
-////{
-////  if (theConstraint.type == SLVS_C_PT_LINE_DISTANCE) {
-////    // Get constraint parameters and check the sign of constraint value
-////
-////    // point coordinates
-////    int aPtPos = Search(theConstraint.ptA, myEntities);
-////    int aPtParamPos = Search(myEntities[aPtPos].param[0], myParams);
-////    std::shared_ptr<GeomAPI_XY> aPoint(
-////        new GeomAPI_XY(myParams[aPtParamPos].val, myParams[aPtParamPos + 1].val));
-////
-////    // line coordinates
-////    int aLnPos = Search(theConstraint.entityA, myEntities);
-////    aPtPos = Search(myEntities[aLnPos].point[0], myEntities);
-////    aPtParamPos = Search(myEntities[aPtPos].param[0], myParams);
-////    std::shared_ptr<GeomAPI_XY> aStart(
-////        new GeomAPI_XY(-myParams[aPtParamPos].val, -myParams[aPtParamPos + 1].val));
-////    aPtPos = Search(myEntities[aLnPos].point[1], myEntities);
-////    aPtParamPos = Search(myEntities[aPtPos].param[0], myParams);
-////    std::shared_ptr<GeomAPI_XY> aEnd(
-////        new GeomAPI_XY(myParams[aPtParamPos].val, myParams[aPtParamPos + 1].val));
-////
-////    aEnd = aEnd->added(aStart);
-////    aPoint = aPoint->added(aStart);
-////    if (aPoint->cross(aEnd) * theConstraint.valA < 0.0)
-////      theConstraint.valA *= -1.0;
-////  }
-////}
-
 // ============================================================================
 //  Function: changeConstraint
 //  Class:    SketchSolver_Group
@@ -453,15 +418,23 @@ bool SketchSolver_Group::changeConstraint(
   return true;
 }
 
-void SketchSolver_Group::moveFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
+
+bool SketchSolver_Group::updateFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
 {
   std::set<ConstraintPtr> aConstraints = myFeatureStorage->getConstraints(theFeature);
+  if (aConstraints.empty())
+    return false;
   std::set<ConstraintPtr>::iterator aCIter = aConstraints.begin();
   for (; aCIter != aConstraints.end(); aCIter++) {
     ConstraintConstraintMap::iterator aSolConIter = myConstraints.find(*aCIter);
     aSolConIter->second->update();
   }
+  return true;
+}
 
+void SketchSolver_Group::moveFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
+{
+  updateFeature(theFeature);
   // Temporary rigid constraint
   SolverConstraintPtr aConstraint =
       SketchSolver_Builder::getInstance()->createRigidConstraint(theFeature);
@@ -1417,46 +1390,24 @@ bool SketchSolver_Group::updateWorkplane()
 // ============================================================================
 bool SketchSolver_Group::resolveConstraints()
 {
-  if (!myStorage->isNeedToResolve() || isEmpty())
-    return false;
+  bool aResolved = false;
+  if (myStorage->isNeedToResolve() && !isEmpty()) {
+    myConstrSolver.setGroupID(myID);
+    myStorage->initializeSolver(myConstrSolver);
 
-  myConstrSolver.setGroupID(myID);
-  myStorage->initializeSolver(myConstrSolver);
-
-////  theSolver.setDraggedParameters(myTempPointWhereDragged);
-////
-  int aResult = myConstrSolver.solve();
-  if (aResult == SLVS_RESULT_OKAY) {  // solution succeeded, store results into correspondent attributes
-    ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin();
-    for (; aConstrIter != myConstraints.end(); aConstrIter++)
-      aConstrIter->second->refresh();
-
-////                                      // Obtain result into the same list of parameters
-////    if (!myConstrSolver.getResult(myParams))
-////      return true;
-////
-////    // We should go through the attributes map, because only attributes have valued parameters
-////    std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::iterator anEntIter =
-////        myEntityAttrMap.begin();
-////    for (; anEntIter != myEntityAttrMap.end(); anEntIter++) {
-////      if (anEntIter->first->owner().get() && anEntIter->first->owner()->data().get())
-////        anEntIter->first->owner()->data()->blockSendAttributeUpdated(true);
-////      if (updateAttribute(anEntIter->first, anEntIter->second))
-////        updateRelatedConstraints(anEntIter->first);
-////    }
-////    updateFilletConstraints();
-////    // unblock all features then
-////    for (anEntIter = myEntityAttrMap.begin(); anEntIter != myEntityAttrMap.end(); anEntIter++) {
-////      if (anEntIter->first->owner().get() && anEntIter->first->owner()->data().get())
-////        anEntIter->first->owner()->data()->blockSendAttributeUpdated(false);
-////    }
-  } else if (!myConstraints.empty())
-    Events_Error::send(SketchSolver_Error::CONSTRAINTS(), this);
+    int aResult = myConstrSolver.solve();
+    if (aResult == SLVS_RESULT_OKAY) {  // solution succeeded, store results into correspondent attributes
+      ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin();
+      for (; aConstrIter != myConstraints.end(); aConstrIter++)
+        aConstrIter->second->refresh();
+    } else if (!myConstraints.empty())
+      Events_Error::send(SketchSolver_Error::CONSTRAINTS(), this);
 
+    myStorage->setNeedToResolve(false);
+    aResolved = true;
+  }
   removeTemporaryConstraints();
-////  myNeedToSolve = false;
-  myStorage->setNeedToResolve(false);
-  return true;
+  return aResolved;
 }
 
 // ============================================================================
index 68317fd0a15db5819d55f311d595036ece11c737..6e53af522829e3cd5f19c5d541c075a0b114f46a 100644 (file)
@@ -91,6 +91,11 @@ class SketchSolver_Group
 ////   */
 ////  bool changeFilletConstraint(std::shared_ptr<SketchPlugin_Constraint> theConstraint);
 
+  /** \brief Updates the data corresponding the specified feature
+   *  \param[in] theFeature the feature to be updated
+   */
+  bool updateFeature(std::shared_ptr<SketchPlugin_Feature> theFeature);
+
   /** \brief Updates the data corresponding the specified feature moved in GUI.
    *         Additional Fixed constraints are created.
    *  \param[in] theFeature the feature to be updated
@@ -240,12 +245,6 @@ private:
 ////   */
 ////  bool addCoincidentPoints(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2);
 ////
-////  /** \brief Verifies and changes parameters of constriant, 
-////   *         e.g. sign of the distance between line and point
-////   *  \param[in,out] theConstraint SolveSpace constraint to be verified
-////   */
-////  void checkConstraintConsistence(Slvs_Constraint& theConstraint);
-////
 ////  /** \brief Change entities parameters to make them symmetric relating to the mirror line
 ////   *  \param[in] theBase        entity to be mirrored
 ////   *  \param[in] theMirror      a mirrored object
index 650e11c2d79b12c9a261e355c45500c1358acd5d..0e7b1761cc51e62b2aeeede9ce12c1c952d9f51c 100644 (file)
@@ -31,6 +31,8 @@ SketchSolver_Solver::SketchSolver_Solver()
 
 SketchSolver_Solver::~SketchSolver_Solver()
 {
+  if (myEquationsSystem.constraint)
+    delete[] myEquationsSystem.constraint;
   if (myEquationsSystem.failed)
     delete[] myEquationsSystem.failed;
 }
@@ -56,8 +58,16 @@ void SketchSolver_Solver::setEntities(Slvs_Entity* theEntities, int theSize)
 
 void SketchSolver_Solver::setConstraints(Slvs_Constraint* theConstraints, int theSize)
 {
-  myEquationsSystem.constraint = theConstraints;
-  myEquationsSystem.constraints = theSize;
+  if (!myEquationsSystem.constraint) {
+    myEquationsSystem.constraint = new Slvs_Constraint[theSize];
+    myEquationsSystem.constraints = theSize;
+  }
+  else if (myEquationsSystem.constraints != theSize) {
+    delete[] myEquationsSystem.constraint;
+    myEquationsSystem.constraint = new Slvs_Constraint[theSize];
+    myEquationsSystem.constraints = theSize;
+  }
+  memcpy(myEquationsSystem.constraint, theConstraints, theSize * sizeof(Slvs_Constraint));
 }
 
 
index d56d98d851b475a3792ee3e892624403a46ad222..687e6ea11854397a289c81333cc67af046c80152 100644 (file)
@@ -26,6 +26,7 @@ SketchSolver_Storage::SketchSolver_Storage()
   : myParamMaxID(SLVS_E_UNKNOWN),
     myEntityMaxID(SLVS_E_UNKNOWN),
     myConstrMaxID(SLVS_C_UNKNOWN),
+    myFixed(SLVS_E_UNKNOWN),
     myNeedToResolve(false)
 {
 }
@@ -78,6 +79,7 @@ bool SketchSolver_Storage::removeParameter(const Slvs_hParam& theParamID)
     }
     // Remove parameter
     myParameters.erase(myParameters.begin() + aPos);
+    myParamMaxID = myParameters.empty() ? SLVS_E_UNKNOWN : myParameters.back().h;
     myNeedToResolve = true;
     myRemovedParameters.insert(theParamID);
     return true;
@@ -159,6 +161,7 @@ bool SketchSolver_Storage::removeEntity(const Slvs_hEntity& theEntityID)
     // The entity is not used, remove it and its parameters
     Slvs_Entity anEntity = myEntities[aPos];
     myEntities.erase(myEntities.begin() + aPos);
+    myEntityMaxID = myEntities.empty() ? SLVS_E_UNKNOWN : myEntities.back().h;
     if (anEntity.distance != SLVS_E_UNKNOWN)
       aResult = aResult && removeParameter(anEntity.distance);
     for (int i = 0; i < 4; i++)
@@ -169,6 +172,8 @@ bool SketchSolver_Storage::removeEntity(const Slvs_hEntity& theEntityID)
         aResult = removeEntity(anEntity.point[i]) && aResult;
     myNeedToResolve = true;
     myRemovedEntities.insert(theEntityID);
+    if (anEntity.type == SLVS_E_POINT_IN_2D || anEntity.type == SLVS_E_POINT_IN_3D)
+      removeCoincidentPoint(theEntityID);
   }
   return aResult;
 }
@@ -185,6 +190,31 @@ const Slvs_Entity& SketchSolver_Storage::getEntity(const Slvs_hEntity& theEntity
   return aDummy;
 }
 
+Slvs_hConstraint SketchSolver_Storage::isPointFixed(const Slvs_hEntity& thePointID) const
+{
+  // Search the set of coincident points
+  std::vector< std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
+  for (; aCPIter != myCoincidentPoints.end(); aCPIter++)
+    if (aCPIter->find(thePointID) != aCPIter->end())
+      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;
+  return SLVS_E_UNKNOWN;
+}
+
 
 Slvs_hConstraint SketchSolver_Storage::addConstraint(const Slvs_Constraint& theConstraint)
 {
@@ -200,6 +230,8 @@ Slvs_hConstraint SketchSolver_Storage::addConstraint(const Slvs_Constraint& theC
     aConstraint.h = ++myConstrMaxID;
   myConstraints.push_back(aConstraint);
   myNeedToResolve = true;
+  if (aConstraint.type == SLVS_C_POINTS_COINCIDENT)
+    addCoincidentPoints(aConstraint.ptA, aConstraint.ptB);
   return aConstraint.h;
 }
 
@@ -211,6 +243,8 @@ Slvs_hConstraint SketchSolver_Storage::updateConstraint(const Slvs_Constraint& t
     if (aPos >= 0 && aPos < (int)myConstraints.size()) {
       myNeedToResolve = myNeedToResolve || IsNotEqual(myConstraints[aPos], theConstraint);
       myConstraints[aPos] = theConstraint;
+      if (theConstraint.type == SLVS_C_POINTS_COINCIDENT)
+        addCoincidentPoints(theConstraint.ptA, theConstraint.ptB);
       return theConstraint.h;
     }
   }
@@ -228,6 +262,7 @@ bool SketchSolver_Storage::removeConstraint(const Slvs_hConstraint& theConstrain
   if (aPos >= 0 && aPos < (int)myConstraints.size()) {
     Slvs_Constraint aConstraint = myConstraints[aPos];
     myConstraints.erase(myConstraints.begin() + aPos);
+    myConstrMaxID = myConstraints.empty() ? SLVS_E_UNKNOWN : myConstraints.back().h;
     myNeedToResolve = true;
     myRemovedConstraints.insert(theConstraintID);
     // Remove all entities
@@ -235,16 +270,11 @@ bool SketchSolver_Storage::removeConstraint(const Slvs_hConstraint& theConstrain
         aConstraint.entityA, aConstraint.entityB,
         aConstraint.entityC, aConstraint.entityD};
     for (int i = 0; i < 6; i++)
-      if (anEntities[i] != SLVS_E_UNKNOWN) {
+      if (anEntities[i] != SLVS_E_UNKNOWN)
         aResult = removeEntity(anEntities[i]) && aResult;
-        // remove temporary fixed points, if exists
-        std::vector<Slvs_hEntity>::iterator aFPIt = myFixedPoints.begin();
-        for (; aFPIt != myFixedPoints.end(); aFPIt++)
-          if (*aFPIt == anEntities[i]) {
-            myFixedPoints.erase(aFPIt);
-            break;
-          }
-      }
+    // remove temporary fixed point, if available
+    if (myFixed == theConstraintID)
+      myFixed = SLVS_E_UNKNOWN;
   }
   return aResult;
 }
@@ -263,8 +293,11 @@ const Slvs_Constraint& SketchSolver_Storage::getConstraint(const Slvs_hConstrain
 
 void SketchSolver_Storage::addTemporaryConstraint(const Slvs_hConstraint& theConstraintID)
 {
+  if (myFixed != SLVS_E_UNKNOWN)
+    return; // the point is already fixed
   int aPos = Search(theConstraintID, myConstraints);
-  myFixedPoints.push_back(myConstraints[aPos].ptA);
+  if (aPos >= 0 && aPos < (int)myConstraints.size())
+    myFixed = theConstraintID;
 }
 
 void SketchSolver_Storage::getRemoved(
@@ -285,15 +318,70 @@ void SketchSolver_Storage::initializeSolver(SketchSolver_Solver& theSolver)
 {
   theSolver.setParameters(myParameters.data(), (int)myParameters.size());
   theSolver.setEntities(myEntities.data(), (int)myEntities.size());
-  theSolver.setConstraints(myConstraints.data(), (int)myConstraints.size());
 
-  // initialize fixed points
-  if (!myFixedPoints.empty()) {
-    int aPos = Search(myFixedPoints.front(), myEntities);
+  // Copy constraints excluding the fixed one
+  std::vector<Slvs_Constraint> aConstraints = myConstraints;
+  if (myFixed != SLVS_E_UNKNOWN) {
+    Slvs_hEntity aFixedPoint = SLVS_E_UNKNOWN;
+    std::vector<Slvs_Constraint>::iterator anIt = aConstraints.begin();
+    for (; anIt != aConstraints.end(); anIt++)
+      if (anIt->h == myFixed) {
+        aFixedPoint = anIt->ptA;
+        aConstraints.erase(anIt);
+        break;
+      }
+    // set dragged parameters
+    int aPos = Search(aFixedPoint, myEntities);
     theSolver.setDraggedParameters(myEntities[aPos].param);
   }
+  theSolver.setConstraints(aConstraints.data(), (int)aConstraints.size());
 }
 
+void SketchSolver_Storage::addCoincidentPoints(
+    const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2)
+{
+  std::vector< std::set<Slvs_hEntity> >::iterator aCIter = myCoincidentPoints.begin();
+  std::vector< std::set<Slvs_hEntity> >::iterator aFoundIter = myCoincidentPoints.end(); // already found coincidence
+  bool isFound = false;
+  for (; aCIter != myCoincidentPoints.end(); aCIter++) {
+    bool isFirstFound = aCIter->find(thePoint1) != aCIter->end();
+    bool isSecondFound = aCIter->find(thePoint2) != aCIter->end();
+    isFound = isFound || isFirstFound || isSecondFound;
+    if (isFirstFound && isSecondFound)
+      break; // already coincident
+    else if (isFirstFound || isSecondFound) {
+      if (aFoundIter != myCoincidentPoints.end()) {
+        // merge two sets
+        aFoundIter->insert(aCIter->begin(), aCIter->end());
+        myCoincidentPoints.erase(aCIter);
+        break;
+      }
+      aCIter->insert(thePoint1);
+      aCIter->insert(thePoint2);
+    }
+  }
+  // coincident points not found
+  if (!isFound) {
+    std::set<Slvs_hEntity> aNewSet;
+    aNewSet.insert(thePoint1);
+    aNewSet.insert(thePoint2);
+    myCoincidentPoints.push_back(aNewSet);
+  }
+}
+
+void SketchSolver_Storage::removeCoincidentPoint(const Slvs_hEntity& thePoint)
+{
+  std::vector< std::set<Slvs_hEntity> >::iterator aCIter = myCoincidentPoints.begin();
+  for (; aCIter != myCoincidentPoints.end(); aCIter++)
+    if (aCIter->find(thePoint) != aCIter->end()) {
+      aCIter->erase(thePoint);
+      if (aCIter->size() <= 1)
+        myCoincidentPoints.erase(aCIter);
+      break;
+    }
+}
+
+
 
 // ========================================================
 // =========      Auxiliary functions       ===============
index 0317f930f3073ca4fc2c90575c390797a688b16c..fe206107e219ed588e09696a772240680d4b0b40 100644 (file)
@@ -60,8 +60,12 @@ public:
   /// \brief Returns the entity by its ID
   const Slvs_Entity& getEntity(const Slvs_hEntity& theEntityID) const;
 
+  /// \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;
+
   /** \brief Add new constraint to the current group
-   *  \param[in] theConstraint  SolveSpace constraint
+   *  \param[in] theConstraint   SolveSpace's constraint
    *  \return the ID of added constraint
    */
   Slvs_hConstraint addConstraint(const Slvs_Constraint& theConstraint);
@@ -99,15 +103,22 @@ public:
   /// \brief Initialize constraint solver by the entities collected by current storage
   void initializeSolver(SketchSolver_Solver& theSolver);
 
+private:
+  /// \brief Store coincident points
+  void addCoincidentPoints(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2);
+  /// \brief Remove point from lists of coincidence
+  void removeCoincidentPoint(const Slvs_hEntity& thePoint);
+
 private:
   Slvs_hParam myParamMaxID; ///< current parameter index (may differs with the number of parameters)
-  std::vector<Slvs_Param> myParameters; ///< list of parameters used in the current group of constraints
+  std::vector<Slvs_Param> myParameters; ///< list of parameters used in the current group of constraints (sorted by the identifier)
   Slvs_hEntity myEntityMaxID; ///< current entity index (may differs with the number of entities)
-  std::vector<Slvs_Entity> myEntities; ///< list of entities used in the current group of constraints
+  std::vector<Slvs_Entity> myEntities; ///< list of entities used in the current group of constraints (sorted by the identifier)
   Slvs_hConstraint myConstrMaxID; ///< current constraint index (may differs with the number of constraints)
-  std::vector<Slvs_Constraint> myConstraints; ///< list of constraints used in the current group
+  std::vector<Slvs_Constraint> myConstraints; ///< list of constraints used in the current group (sorted by the identifier)
 
-  std::vector<Slvs_hEntity> myFixedPoints; ///< identifiers of entities which relate to temporary constraints
+  std::vector< std::set<Slvs_hEntity> > myCoincidentPoints; ///< lists of coincident points
+  Slvs_hConstraint myFixed; ///< identifier of one of temporary constraints to fix separate point
 
   bool myNeedToResolve; ///< parameters are changed and group needs to be resolved