Salome HOME
Revert "First phase of SketchSolver refactoring"
authorazv <azv@opencascade.com>
Tue, 15 Dec 2015 08:48:27 +0000 (11:48 +0300)
committerazv <azv@opencascade.com>
Tue, 15 Dec 2015 08:48:27 +0000 (11:48 +0300)
This reverts commit 7beb3c7ae26709576c42b01255e2530fc866c1fa.

67 files changed:
src/Config/plugins.xml
src/SketchSolver/CMakeLists.txt
src/SketchSolver/SketchSolver.h
src/SketchSolver/SketchSolver_Builder.cpp
src/SketchSolver/SketchSolver_Builder.h
src/SketchSolver/SketchSolver_Constraint.cpp
src/SketchSolver/SketchSolver_Constraint.h
src/SketchSolver/SketchSolver_ConstraintAngle.cpp
src/SketchSolver/SketchSolver_ConstraintAngle.h
src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp
src/SketchSolver/SketchSolver_ConstraintCoincidence.h
src/SketchSolver/SketchSolver_ConstraintDistance.cpp
src/SketchSolver/SketchSolver_ConstraintDistance.h
src/SketchSolver/SketchSolver_ConstraintEqual.cpp
src/SketchSolver/SketchSolver_ConstraintEqual.h
src/SketchSolver/SketchSolver_ConstraintFillet.cpp [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintFillet.h [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintFixed.cpp [deleted file]
src/SketchSolver/SketchSolver_ConstraintFixed.h [deleted file]
src/SketchSolver/SketchSolver_ConstraintLength.cpp
src/SketchSolver/SketchSolver_ConstraintLength.h
src/SketchSolver/SketchSolver_ConstraintManager.cpp [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintManager.h [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintMirror.cpp
src/SketchSolver/SketchSolver_ConstraintMirror.h
src/SketchSolver/SketchSolver_ConstraintMovement.cpp
src/SketchSolver/SketchSolver_ConstraintMovement.h
src/SketchSolver/SketchSolver_ConstraintMulti.cpp
src/SketchSolver/SketchSolver_ConstraintMulti.h
src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp
src/SketchSolver/SketchSolver_ConstraintMultiRotation.h
src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp
src/SketchSolver/SketchSolver_ConstraintMultiTranslation.h
src/SketchSolver/SketchSolver_ConstraintParametric.cpp [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintParametric.h [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintRigid.cpp [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintRigid.h [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintTangent.cpp
src/SketchSolver/SketchSolver_ConstraintTangent.h
src/SketchSolver/SketchSolver_FeatureStorage.cpp [new file with mode: 0644]
src/SketchSolver/SketchSolver_FeatureStorage.h [new file with mode: 0644]
src/SketchSolver/SketchSolver_Group.cpp
src/SketchSolver/SketchSolver_Group.h
src/SketchSolver/SketchSolver_IConstraintWrapper.h [deleted file]
src/SketchSolver/SketchSolver_IEntityWrapper.h [deleted file]
src/SketchSolver/SketchSolver_IParameterWrapper.h [deleted file]
src/SketchSolver/SketchSolver_ISolver.h [deleted file]
src/SketchSolver/SketchSolver_Manager.cpp [deleted file]
src/SketchSolver/SketchSolver_Manager.h [deleted file]
src/SketchSolver/SketchSolver_Solver.cpp [new file with mode: 0644]
src/SketchSolver/SketchSolver_Solver.h [new file with mode: 0644]
src/SketchSolver/SketchSolver_Storage.cpp
src/SketchSolver/SketchSolver_Storage.h
src/SketchSolver/SolveSpaceSolver/CMakeLists.txt [deleted file]
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Builder.cpp [deleted file]
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Builder.h [deleted file]
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_ConstraintType.h [deleted file]
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_ConstraintWrapper.cpp [deleted file]
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_ConstraintWrapper.h [deleted file]
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_EntityWrapper.cpp [deleted file]
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_EntityWrapper.h [deleted file]
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_ParameterWrapper.cpp [deleted file]
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_ParameterWrapper.h [deleted file]
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.cpp [deleted file]
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.h [deleted file]
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp [deleted file]
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.h [deleted file]

index 45903311b7f071242080f25252c200b1d57d4171..a8b4b231557d5d2eb66c78a90d58e77ba0de63c9 100644 (file)
@@ -12,7 +12,7 @@
   <plugin script="addons_Features" configuration="addons_Features.xml"/>
   <plugin script="ConnectorPlugin" configuration="plugin-Connector.xml" dependency="Geometry"/>
   <plugin library="ParametersPlugin" configuration="plugin-Parameters.xml"/>
-  <plugin library="SolveSpaceSolver"/>
+  <plugin library="SketchSolver"/>
   <plugin library="GeomValidators"/>
   <plugin library="DFBrowser" internal="true"/>
 </plugins>
index 79094bf2fffddcfda68efc5bf9c9a5a508200431..126fb212e7c6cddf5886afbd8a885f0bf7fe2b93 100644 (file)
@@ -1,56 +1,60 @@
 ## Copyright (C) 2014-20xx CEA/DEN, EDF R&D
 
 INCLUDE(Common)
+FIND_PACKAGE(SolveSpace REQUIRED)
 
 SET(PROJECT_HEADERS
     SketchSolver.h
     SketchSolver_Error.h
+    SketchSolver_Solver.h
     SketchSolver_Constraint.h
     SketchSolver_ConstraintAngle.h
     SketchSolver_ConstraintCoincidence.h
     SketchSolver_ConstraintDistance.h
     SketchSolver_ConstraintEqual.h
+    SketchSolver_ConstraintFillet.h
     SketchSolver_ConstraintLength.h
     SketchSolver_ConstraintMirror.h
-    SketchSolver_ConstraintFixed.h
+    SketchSolver_ConstraintRigid.h
     SketchSolver_ConstraintTangent.h
     SketchSolver_ConstraintMulti.h
     SketchSolver_ConstraintMultiRotation.h
     SketchSolver_ConstraintMultiTranslation.h
     SketchSolver_ConstraintMovement.h
-#    SketchSolver_ConstraintParametric.h
-    SketchSolver_Group.h
+    SketchSolver_ConstraintParametric.h
     SketchSolver_Builder.h
-    SketchSolver_IConstraintWrapper.h
-    SketchSolver_IEntityWrapper.h
-    SketchSolver_IParameterWrapper.h
-    SketchSolver_ISolver.h
-    SketchSolver_Manager.h
+    SketchSolver_Group.h
+    SketchSolver_ConstraintManager.h
     SketchSolver_Storage.h
+    SketchSolver_FeatureStorage.h
 )
 
 SET(PROJECT_SOURCES
+    SketchSolver_Solver.cpp
     SketchSolver_Constraint.cpp
     SketchSolver_ConstraintAngle.cpp
     SketchSolver_ConstraintCoincidence.cpp
     SketchSolver_ConstraintDistance.cpp
     SketchSolver_ConstraintEqual.cpp
+    SketchSolver_ConstraintFillet.cpp
     SketchSolver_ConstraintLength.cpp
     SketchSolver_ConstraintMirror.cpp
-    SketchSolver_ConstraintFixed.cpp
+    SketchSolver_ConstraintRigid.cpp
     SketchSolver_ConstraintTangent.cpp
     SketchSolver_ConstraintMulti.cpp
     SketchSolver_ConstraintMultiRotation.cpp
     SketchSolver_ConstraintMultiTranslation.cpp
+    SketchSolver_ConstraintParametric.cpp
     SketchSolver_ConstraintMovement.cpp
-#    SketchSolver_ConstraintParametric.cpp
-    SketchSolver_Group.cpp
     SketchSolver_Builder.cpp
-    SketchSolver_Manager.cpp
+    SketchSolver_Group.cpp
+    SketchSolver_ConstraintManager.cpp
     SketchSolver_Storage.cpp
+    SketchSolver_FeatureStorage.cpp
 )
 
 SET(PROJECT_LIBRARIES
+    ${SOLVESPACE_LIBRARIES}
     Config
     Events
     ModelAPI
@@ -58,6 +62,7 @@ SET(PROJECT_LIBRARIES
 )
 
 INCLUDE_DIRECTORIES(
+    ${SOLVESPACE_INCLUDE_DIRS}
     ${PROJECT_SOURCE_DIR}/src/Config
     ${PROJECT_SOURCE_DIR}/src/SketchPlugin
     ${PROJECT_SOURCE_DIR}/src/ModelAPI
@@ -68,30 +73,10 @@ INCLUDE_DIRECTORIES(
 
 ADD_DEFINITIONS(-DSKETCHSOLVER_EXPORTS)
 
-ADD_LIBRARY(SketchSolver SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS}
+ADD_LIBRARY(SketchSolver MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS}
 )
 
 TARGET_LINK_LIBRARIES(SketchSolver ${PROJECT_LIBRARIES}
 )
 
 INSTALL(TARGETS SketchSolver DESTINATION plugins)
-
-
-# Include specific solvers
-FIND_FILE(SSPath "SolveSpaceSolver/CMakeLists.txt" PATHS "${CMAKE_CURRENT_SOURCE_DIR}")
-STRING(COMPARE NOTEQUAL ${SSPath} "SSPath-NOTFOUND" SSPath_FOUND)
-FIND_FILE(GCSPath "PlainGCSSolver/CMakeLists.txt" PATHS "${CMAKE_CURRENT_SOURCE_DIR}")
-STRING(COMPARE NOTEQUAL ${GCSPath} "GCSPath-NOTFOUND" GCSPath_FOUND)
-
-IF(${SSPath_FOUND} OR ${GCSPath_FOUND})
-  IF(${SSPath_FOUND})
-    MESSAGE(STATUS "SolveSpaceSolver plugin found in ${SSPath}")
-    ADD_SUBDIRECTORY(SolveSpaceSolver)
-  ENDIF()
-  IF(${GCSPath_FOUND})
-    MESSAGE(STATUS "PlainGCSSolver plugin found in ${GCSPath}")
-    ADD_SUBDIRECTORY(PlainGCSSolver)
-  ENDIF()
-ELSE()
-  MESSAGE(WARNING "No sketch solver plugin is found")
-ENDIF()
index 56fa1dba25eba093e0041f1de7595e83b29080ee..cc5013f6ed163cf32b89d7b19ac2f346652ab826 100644 (file)
@@ -3,8 +3,6 @@
 #ifndef SKETCHSOLVER_H
 #define SKETCHSOLVER_H
 
-#include <stdlib.h>
-
 #if defined SKETCHSOLVER_EXPORTS
 #if defined WIN32
 #define SKETCHSOLVER_EXPORT              __declspec( dllexport )
@@ -24,18 +22,4 @@ const double tolerance = 1.e-10;
 
 #define PI 3.1415926535897932
 
-// Types for data entities enumeration
-typedef size_t GroupID;
-typedef size_t ParameterID;
-typedef size_t EntityID;
-typedef size_t ConstraintID;
-
-// Predefined values for identifiers
-const GroupID       GID_UNKNOWN    = 0;
-const GroupID       GID_OUTOFGROUP = 1;
-
-const ParameterID   PID_UNKNOWN    = 0;
-const EntityID      EID_UNKNOWN    = 0;
-const ConstraintID  CID_UNKNOWN    = 0;
-
 #endif
index 323bdb056a0d809dace936f5a7cca62cc098fa68..78bfc59bb19eff477c4c13b367ec68f81425fe58 100644 (file)
@@ -5,53 +5,66 @@
 // Author:  Artem ZHIDKOV
 
 #include "SketchSolver_Builder.h"
-#include <SketchSolver_Constraint.h>
+#include <SketchPlugin_ConstraintAngle.h>
 #include <SketchSolver_ConstraintAngle.h>
 #include <SketchSolver_ConstraintCoincidence.h>
 #include <SketchSolver_ConstraintDistance.h>
 #include <SketchSolver_ConstraintEqual.h>
-#include <SketchSolver_ConstraintFixed.h>
+#include <SketchSolver_ConstraintFillet.h>
 #include <SketchSolver_ConstraintLength.h>
 #include <SketchSolver_ConstraintMirror.h>
+#include <SketchSolver_ConstraintRigid.h>
 #include <SketchSolver_ConstraintTangent.h>
 #include <SketchSolver_ConstraintMultiRotation.h>
 #include <SketchSolver_ConstraintMultiTranslation.h>
 #include <SketchSolver_ConstraintMovement.h>
-////#include <SketchSolver_ConstraintParametric.h>
+#include <SketchSolver_ConstraintParametric.h>
+#include <SketchSolver_Error.h>
 
-#ifdef _DEBUG
+#include <GeomAPI_Edge.h>
+#include <GeomDataAPI_Dir.h>
+#include <GeomDataAPI_Point.h>
+#include <GeomDataAPI_Point2D.h>
 #include <Events_Error.h>
+#include <ModelAPI_Attribute.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_AttributeRefList.h>
 #include <ModelAPI_ResultConstruction.h>
-#include <SketchSolver_Error.h>
-#endif
 
-////#include <GeomAPI_Edge.h>
-////#include <GeomDataAPI_Dir.h>
-////#include <GeomDataAPI_Point.h>
-////#include <GeomDataAPI_Point2D.h>
-////#include <ModelAPI_Attribute.h>
-////#include <ModelAPI_AttributeDouble.h>
-////#include <ModelAPI_AttributeRefAttr.h>
-////
-////#include <SketchPlugin_Arc.h>
-////#include <SketchPlugin_Circle.h>
-////#include <SketchPlugin_Line.h>
-////#include <SketchPlugin_Point.h>
-#include <SketchPlugin_ConstraintAngle.h>
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
 #include <SketchPlugin_ConstraintCoincidence.h>
 #include <SketchPlugin_ConstraintDistance.h>
 #include <SketchPlugin_ConstraintEqual.h>
+#include <SketchPlugin_ConstraintFillet.h>
+#include <SketchPlugin_ConstraintHorizontal.h>
 #include <SketchPlugin_ConstraintLength.h>
 #include <SketchPlugin_ConstraintMirror.h>
+#include <SketchPlugin_ConstraintParallel.h>
+#include <SketchPlugin_ConstraintPerpendicular.h>
+#include <SketchPlugin_ConstraintRadius.h>
 #include <SketchPlugin_ConstraintRigid.h>
 #include <SketchPlugin_ConstraintTangent.h>
+#include <SketchPlugin_ConstraintVertical.h>
 #include <SketchPlugin_MultiRotation.h>
 #include <SketchPlugin_MultiTranslation.h>
 
 #include <math.h>
 
-SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theConstraint) const
+// Initialization of constraint builder self pointer
+SketchSolver_Builder* SketchSolver_Builder::mySelf = 0;
+
+SketchSolver_Builder* SketchSolver_Builder::getInstance()
+{
+  if (!mySelf)
+    mySelf = new SketchSolver_Builder();
+  return mySelf;
+}
+
+SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theConstraint)
 {
   SolverConstraintPtr aResult;
   DataPtr aData = theConstraint->data();
@@ -93,14 +106,26 @@ SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theCons
     return SolverConstraintPtr(new SketchSolver_ConstraintDistance(theConstraint));
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintEqual::ID()) {
     return SolverConstraintPtr(new SketchSolver_ConstraintEqual(theConstraint));
+  } else if (theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) {
+    return SolverConstraintPtr(new SketchSolver_ConstraintFillet(theConstraint));
+  } 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));
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
     return SolverConstraintPtr(new SketchSolver_ConstraintMirror(theConstraint));
+  } else if (theConstraint->getKind() == SketchPlugin_ConstraintParallel::ID()) {
+    return SolverConstraintPtr(new SketchSolver_ConstraintParallel(theConstraint));
+  } else if (theConstraint->getKind() == SketchPlugin_ConstraintPerpendicular::ID()) {
+    return SolverConstraintPtr(new SketchSolver_ConstraintPerpendicular(theConstraint));
+  } else if (theConstraint->getKind() == SketchPlugin_ConstraintRadius::ID()) {
+    return SolverConstraintPtr(new SketchSolver_ConstraintRadius(theConstraint));
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintTangent::ID()) {
     return SolverConstraintPtr(new SketchSolver_ConstraintTangent(theConstraint));
+  } else if (theConstraint->getKind() == SketchPlugin_ConstraintVertical::ID()) {
+    return SolverConstraintPtr(new SketchSolver_ConstraintVertical(theConstraint));
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID()) {
-    return SolverConstraintPtr(new SketchSolver_ConstraintFixed(theConstraint));
+    return SolverConstraintPtr(new SketchSolver_ConstraintRigid(theConstraint));
   } else if (theConstraint->getKind() == SketchPlugin_MultiTranslation::ID()) {
     return SolverConstraintPtr(new SketchSolver_ConstraintMultiTranslation(theConstraint));
   } else if (theConstraint->getKind() == SketchPlugin_MultiRotation::ID()) {
@@ -108,19 +133,18 @@ SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theCons
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintAngle::ID()) {
     return SolverConstraintPtr(new SketchSolver_ConstraintAngle(theConstraint));
   }
-  // All other types of constraints
-  return SolverConstraintPtr(new SketchSolver_Constraint(theConstraint));
+  return aResult;
 }
 
-SolverConstraintPtr SketchSolver_Builder::createFixedConstraint(FeaturePtr theFixedFeature) const
+SolverConstraintPtr SketchSolver_Builder::createRigidConstraint(FeaturePtr theFixedFeature)
 {
   DataPtr aData = theFixedFeature->data();
   if (!aData || !aData->isValid())
     return SolverConstraintPtr();
-  return SolverConstraintPtr(new SketchSolver_ConstraintFixed(theFixedFeature));
+  return SolverConstraintPtr(new SketchSolver_ConstraintRigid(theFixedFeature));
 }
 
-SolverConstraintPtr SketchSolver_Builder::createMovementConstraint(FeaturePtr theFixedFeature) const
+SolverConstraintPtr SketchSolver_Builder::createMovementConstraint(FeaturePtr theFixedFeature)
 {
   DataPtr aData = theFixedFeature->data();
   if (!aData || !aData->isValid())
@@ -128,40 +152,185 @@ SolverConstraintPtr SketchSolver_Builder::createMovementConstraint(FeaturePtr th
   return SolverConstraintPtr(new SketchSolver_ConstraintMovement(theFixedFeature));
 }
 
-////SolverConstraintPtr SketchSolver_Builder::createParametricConstraint(AttributePtr theAttribute)
-////{
-////  return SolverConstraintPtr(new SketchSolver_ConstraintParametric(theAttribute));
-////}
+SolverConstraintPtr SketchSolver_Builder::createParametricConstraint(AttributePtr theAttribute)
+{
+  return SolverConstraintPtr(new SketchSolver_ConstraintParametric(theAttribute));
+}
+
+
+
+bool SketchSolver_Builder::createWorkplane(
+    CompositeFeaturePtr theSketch,
+    std::vector<Slvs_Entity>& theEntities,
+    std::vector<Slvs_Param>& theParameters)
+{
+  DataPtr aSketchData = theSketch->data();
+  if (!aSketchData || !aSketchData->isValid())
+    return false; // the sketch is incorrect
+
+  // Get parameters of workplane
+  std::shared_ptr<ModelAPI_Attribute> aDirX = aSketchData->attribute(
+      SketchPlugin_Sketch::DIRX_ID());
+  std::shared_ptr<ModelAPI_Attribute> aNorm = aSketchData->attribute(
+      SketchPlugin_Sketch::NORM_ID());
+  std::shared_ptr<ModelAPI_Attribute> anOrigin = aSketchData->attribute(
+      SketchPlugin_Sketch::ORIGIN_ID());
+  // Create SolveSpace entity corresponding to the sketch origin
+  if (!createEntity(anOrigin, theEntities, theParameters))
+    return false;
+  Slvs_hEntity anOriginID = theEntities.back().h;
+  // Create SolveSpace entity corresponding the the sketch normal
+  if (!createNormal(aNorm, aDirX, theEntities, theParameters))
+    return false;
+  Slvs_hEntity aNormalID = theEntities.back().h;
 
-std::shared_ptr<GeomAPI_Pnt2d> SketchSolver_Builder::point(EntityWrapperPtr theEntity) const
+  // Create workplane
+  Slvs_hEntity aWorkplaneID = theEntities.back().h + 1;
+  Slvs_Entity aWorkplane = Slvs_MakeWorkplane(aWorkplaneID, SLVS_G_UNKNOWN, anOriginID, aNormalID);
+  theEntities.push_back(aWorkplane);
+  return true;
+}
+
+bool SketchSolver_Builder::createEntity(
+    AttributePtr theAttribute,
+    std::vector<Slvs_Entity>& theEntities,
+    std::vector<Slvs_Param>& theParameters)
 {
-  if (theEntity->type() != ENTITY_POINT)
-    return std::shared_ptr<GeomAPI_Pnt2d>();
-
-  double aXY[2];
-  std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
-  std::list<ParameterWrapperPtr>::const_iterator anIt = aParams.begin();
-  for (int i = 0; i < 2 && anIt != aParams.end(); ++i, ++anIt)
-    aXY[i] = (*anIt)->value();
-  if (anIt != aParams.end())
-    return std::shared_ptr<GeomAPI_Pnt2d>();
-
-  return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aXY[0], aXY[1]));
+  Slvs_hEntity anEntID = theEntities.empty() ? 0 : theEntities.back().h;
+  Slvs_hParam aParamID = theParameters.empty() ? 0 : theParameters.back().h;
+
+  // Point in 3D
+  std::shared_ptr<GeomDataAPI_Point> aPoint =
+      std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
+  if (aPoint) {
+    theParameters.push_back(Slvs_MakeParam(++aParamID, SLVS_G_UNKNOWN, aPoint->x()));
+    theParameters.push_back(Slvs_MakeParam(++aParamID, SLVS_G_UNKNOWN, aPoint->y()));
+    theParameters.push_back(Slvs_MakeParam(++aParamID, SLVS_G_UNKNOWN, aPoint->z()));
+    theEntities.push_back(Slvs_MakePoint3d(++anEntID, SLVS_G_UNKNOWN,
+        aParamID-2, aParamID-1, aParamID));
+    return true;
+  }
+  // Point in 2D
+  std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+    std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
+  if (aPoint2D) {
+    theParameters.push_back(Slvs_MakeParam(++aParamID, SLVS_G_UNKNOWN, aPoint2D->x()));
+    theParameters.push_back(Slvs_MakeParam(++aParamID, SLVS_G_UNKNOWN, aPoint2D->y()));
+    theEntities.push_back(Slvs_MakePoint2d(++anEntID, SLVS_G_UNKNOWN, SLVS_E_UNKNOWN,
+      aParamID-1, aParamID));
+    return true;
+  }
+  // Scalar value (used for the distance entities)
+  AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
+  if (aScalar) {
+    theParameters.push_back(Slvs_MakeParam(++aParamID, SLVS_G_UNKNOWN, aScalar->value()));
+    theEntities.push_back(Slvs_MakeDistance(++anEntID, SLVS_G_UNKNOWN,
+      SLVS_E_UNKNOWN, aParamID));
+    return true;
+  }
+  // unknown attribute type
+  return false;
 }
 
-std::shared_ptr<GeomAPI_Lin2d> SketchSolver_Builder::line(EntityWrapperPtr theEntity) const
+bool SketchSolver_Builder::createEntity(
+    FeaturePtr theFeature,
+    std::vector<Slvs_Entity>& theEntities,
+    std::vector<Slvs_Param>& theParameters)
 {
-  if (theEntity->type() != ENTITY_LINE)
-    return std::shared_ptr<GeomAPI_Lin2d>();
-
-  std::shared_ptr<GeomAPI_Pnt2d> aPoints[2];
-  std::list<EntityWrapperPtr> aSubs = theEntity->subEntities();
-  std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
-  for (int i = 0; i < 2 && anIt != aSubs.end(); ++i, ++anIt)
-    aPoints[i] = point(*anIt);
-  if (anIt != aSubs.end())
-    return std::shared_ptr<GeomAPI_Lin2d>();
-
-  return std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[0], aPoints[1]));
+  if (!theFeature->data()->isValid())
+    return false;
+
+  // SketchPlugin features
+  std::shared_ptr<SketchPlugin_Feature> aFeature = std::dynamic_pointer_cast<
+      SketchPlugin_Feature>(theFeature);
+  if (!aFeature)
+    return false;
+
+  // Verify the feature by its kind
+  const std::string& aFeatureKind = aFeature->getKind();
+  DataPtr aData = aFeature->data();
+  // Line
+  if (aFeatureKind == SketchPlugin_Line::ID()) {
+    AttributePtr aStart = aData->attribute(SketchPlugin_Line::START_ID());
+    AttributePtr aEnd = aData->attribute(SketchPlugin_Line::END_ID());
+    if (!aStart->isInitialized() || !aEnd->isInitialized())
+      return false;
+    if (!createEntity(aStart, theEntities, theParameters) ||
+        !createEntity(aEnd, theEntities, theParameters))
+      return false;
+    Slvs_hEntity aLineID = theEntities.back().h + 1;
+    theEntities.push_back(Slvs_MakeLineSegment(aLineID, SLVS_G_UNKNOWN, SLVS_E_UNKNOWN,
+        aLineID-2, aLineID-1));
+  }
+  // Circle
+  else if (aFeatureKind == SketchPlugin_Circle::ID()) {
+    AttributePtr aCenter = aData->attribute(SketchPlugin_Circle::CENTER_ID());
+    AttributePtr aRadius = aData->attribute(SketchPlugin_Circle::RADIUS_ID());
+    if (!aCenter->isInitialized() || !aRadius->isInitialized())
+      return false;
+    if (!createEntity(aCenter, theEntities, theParameters) ||
+        !createEntity(aRadius, theEntities, theParameters))
+      return false;
+    Slvs_hEntity aCircID = theEntities.back().h;
+    theEntities.push_back(Slvs_MakeCircle(aCircID, SLVS_G_UNKNOWN, SLVS_E_UNKNOWN, aCircID-2,
+      SLVS_E_UNKNOWN, aCircID-1));
+  }
+  // Arc
+  else if (aFeatureKind == SketchPlugin_Arc::ID()) {
+    AttributePtr aCenter = aData->attribute(SketchPlugin_Arc::CENTER_ID());
+    AttributePtr aStart = aData->attribute(SketchPlugin_Arc::START_ID());
+    AttributePtr aEnd = aData->attribute(SketchPlugin_Arc::END_ID());
+    if (!aCenter->isInitialized() || !aStart->isInitialized() || !aEnd->isInitialized())
+      return false;
+    if (!createEntity(aCenter, theEntities, theParameters) ||
+        !createEntity(aStart, theEntities, theParameters) ||
+        !createEntity(aEnd, theEntities, theParameters))
+      return false;
+    Slvs_hEntity anArcID = theEntities.back().h;
+    theEntities.push_back(Slvs_MakeArcOfCircle(anArcID, SLVS_G_UNKNOWN, SLVS_E_UNKNOWN,
+        SLVS_E_UNKNOWN, anArcID-3, anArcID-2, anArcID-1));
+  }
+  // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
+  else if (aFeatureKind == SketchPlugin_Point::ID()) {
+    AttributePtr aPoint = aData->attribute(SketchPlugin_Point::COORD_ID());
+    if (!aPoint->isInitialized() ||
+        !createEntity(aPoint, theEntities, theParameters))
+      return false;
+    // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier.
+    // No need to add another entity.
+  }
+  return true;
 }
 
+bool SketchSolver_Builder::createNormal(
+    AttributePtr theNormal,
+    AttributePtr theDirX,
+    std::vector<Slvs_Entity>& theEntities,
+    std::vector<Slvs_Param>& theParameters)
+{
+  std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(theNormal);
+  std::shared_ptr<GeomDataAPI_Dir> aDirX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(theDirX);
+  if (!aDirX || (fabs(aDirX->x()) + fabs(aDirX->y()) + fabs(aDirX->z()) < tolerance) || 
+      !aNorm->isInitialized())
+    return false;
+  // calculate Y direction
+  std::shared_ptr<GeomAPI_Dir> aDirY(new GeomAPI_Dir(aNorm->dir()->cross(aDirX->dir())));
+
+  // quaternion parameters of normal vector
+  double qw, qx, qy, qz;
+  Slvs_MakeQuaternion(aDirX->x(), aDirX->y(), aDirX->z(), aDirY->x(), aDirY->y(), aDirY->z(), &qw,
+                      &qx, &qy, &qz);
+  double aNormCoord[4] = { qw, qx, qy, qz };
+
+  // Create parameters of the normal
+  Slvs_hParam aCurParam = theParameters.back().h;
+  for (int i = 0; i < 4; i++)
+    theParameters.push_back(Slvs_MakeParam(++aCurParam, SLVS_G_UNKNOWN, aNormCoord[i]));
+
+  // Create a normal
+  Slvs_hEntity aCurEntity = theEntities.back().h + 1;
+  Slvs_Entity aNormal = Slvs_MakeNormal3d(aCurEntity, SLVS_G_UNKNOWN,
+      aCurParam-3, aCurParam-2, aCurParam-1, aCurParam);
+  theEntities.push_back(aNormal);
+  return true;
+}
index ebac79ffdab636cb6934a62bd055035588dfad27..21beac3191fe136cf2f47f8a38d055f213b29ea3 100644 (file)
 #ifndef SketchSolver_Builder_H_
 #define SketchSolver_Builder_H_
 
+#include "SketchSolver.h"
 #include <SketchSolver_Constraint.h>
+
 #include <SketchPlugin_Constraint.h>
 
-#include <GeomAPI_Lin2d.h>
-#include <GeomAPI_Pnt2d.h>
+#include <ModelAPI_CompositeFeature.h>
 
 /** \class   SketchSolver_Builder
  *  \ingroup Plugins
- *  \brief   Abstract class for builders of solver's entities
+ *  \brief   Create bridges between SketchPlugin constraints and SolveSpace constraints
  */
 class SketchSolver_Builder
 {
+private:
+  /// Default constructor
+  SketchSolver_Builder() {}
+
 public:
-  /// \brief Creates a storage specific for used solver
-  virtual StoragePtr createStorage(const GroupID& theGroup) const = 0;
-  /// \brief Creates specific solver
-  virtual SolverPtr createSolver() const = 0;
+  /// \brief Returns single instance of builder
+  static SketchSolver_Builder* getInstance();
 
   /// \brief Creates a solver's constraint using given SketchPlugin constraint
   ///        or returns empty pointer if not all attributes are correct
-  SolverConstraintPtr createConstraint(ConstraintPtr theConstraint) const;
+  SolverConstraintPtr createConstraint(ConstraintPtr theConstraint);
 
   /// \brief Creates temporary constraint to fix the placement of the feature
-  SolverConstraintPtr createFixedConstraint(FeaturePtr theFixedFeature) const;
+  SolverConstraintPtr createRigidConstraint(FeaturePtr theFixedFeature);
 
   /// \brief Creates temporary constraint to fix the feature after movement
-  SolverConstraintPtr createMovementConstraint(FeaturePtr theFixedFeature) const;
-
-////  /// \brief Creates constraint for parametrically given attribute
-////  SolverConstraintPtr createParametricConstraint(AttributePtr theAttribute) const;
-
-  /// \brief Creates new constraint(s) using given parameters
-  /// \param theConstraint [in]  original constraint
-  /// \param theGroupID    [in]  group the constraint belongs to
-  /// \param theSketchID   [in]  sketch the constraint belongs to
-  /// \param theType       [in]  type of constraint
-  /// \param theValue      [in]  numeric characteristic of constraint (e.g. distance or radius) if applicable
-  /// \param theEntity1    [in]  first attribute of constraint
-  /// \param theEntity2    [in]  second attribute of constraint
-  /// \param theEntity3    [in]  third attribute of constraint
-  /// \param theEntity4    [in]  fourth attribute of constraint
-  /// \return Created list of wrappers of constraints applicable for specific solver.
-  ///         Most of constraint types lead to single constraint, but there are some kind of
-  ///         constraints (e.g. mirror), which may produce couple of constraints.
-  virtual std::list<ConstraintWrapperPtr>
-    createConstraint(ConstraintPtr theConstraint,
-                     const GroupID& theGroup,
-                     const EntityID& theSketchID,
-                     const SketchSolver_ConstraintType& theType,
-                     const double& theValue,
-                     const EntityWrapperPtr& theEntity1,
-                     const EntityWrapperPtr& theEntity2 = EntityWrapperPtr(),
-                     const EntityWrapperPtr& theEntity3 = EntityWrapperPtr(),
-                     const EntityWrapperPtr& theEntity4 = EntityWrapperPtr()) const = 0;
-
-  /// \brief Creates new multi-translation or multi-rotation constraint
-  /// \param theConstraint [in]  original constraint
-  /// \param theGroupID    [in]  group the constraint belongs to
-  /// \param theSketchID   [in]  sketch the constraint belongs to
-  /// \param theType       [in]  type of constraint
-  /// \param theValue      [in]  numeric characteristic of constraint (angle for multi-rotation) if applicable
-  /// \param thePoint1     [in]  center for multi-rotation or start point for multi-translation
-  /// \param thePoint2     [in]  end point for multi-translation (empty for multi-rotation)
-  /// \param theTrsfEnt    [in]  list of transformed entities
-  virtual std::list<ConstraintWrapperPtr>
-    createConstraint(ConstraintPtr theConstraint,
-                     const GroupID& theGroup,
-                     const EntityID& theSketchID,
-                     const SketchSolver_ConstraintType& theType,
-                     const double& theValue,
-                     const EntityWrapperPtr& thePoint1,
-                     const EntityWrapperPtr& thePoint2,
-                     const std::list<EntityWrapperPtr>& theTrsfEnt) const = 0;
-
-  /// \brief Update flags for several kinds of constraints
-  virtual void adjustConstraint(ConstraintWrapperPtr theConstraint) const = 0;
-
-  /// \brief Creates a feature using list of already created attributes
-  /// \param theFeature    [in]  feature to create
-  /// \param theAttributes [in]  attributes of the feature
-  /// \param theGroupID    [in]  group the feature belongs to
-  /// \param theSketchID   [in]  sketch the feature belongs to
-  /// \return Created wrapper of the feature applicable for specific solver
-  virtual EntityWrapperPtr createFeature(FeaturePtr theFeature,
-                                         const std::list<EntityWrapperPtr>& theAttributes,
-                                         const GroupID& theGroupID,
-                                         const EntityID& theSketchID = EID_UNKNOWN) const = 0;
-
-  /// \brief Creates an attribute
-  /// \param theAttribute [in]  attribute to create
-  /// \param theGroup     [in]  group the attribute belongs to
-  /// \param theSketchID  [in]  sketch the attribute belongs to
-  /// \return Created wrapper of the attribute applicable for specific solver
-  virtual EntityWrapperPtr createAttribute(AttributePtr theAttribute,
-                                           const GroupID& theGroup,
-                                           const EntityID& theSketchID = EID_UNKNOWN) const = 0;
-
-
-  /// \brief Convert entity to point
-  /// \return empty pointer if the entity is not a point
-  SKETCHSOLVER_EXPORT std::shared_ptr<GeomAPI_Pnt2d> point(EntityWrapperPtr theEntity) const;
-  /// \brief Convert entity to line
-  /// \return empty pointer if the entity is not a line
-  SKETCHSOLVER_EXPORT std::shared_ptr<GeomAPI_Lin2d> line(EntityWrapperPtr theEntity) const;
+  SolverConstraintPtr createMovementConstraint(FeaturePtr theFixedFeature);
+
+  /// \brief Creates constraint for parametrically given attribute
+  SolverConstraintPtr createParametricConstraint(AttributePtr theAttribute);
+
+  /// \brief Converts sketch parameters to the list of SolveSpace entities.
+  ///        Identifiers of entities and parameters are local. They should be changed while adding into storage.
+  ///        The sketch entity goes last.
+  /// \param[in]  theSketch     the element to be converted
+  /// \param[out] theEntities   created list of entities
+  /// \param[out] theParameters created list of parameters of the entities
+  /// \return \c true if workplane created
+  bool createWorkplane(CompositeFeaturePtr theSketch,
+                       std::vector<Slvs_Entity>& theEntities,
+                       std::vector<Slvs_Param>& theParameters);
+
+  /// \brief Converts attribute to the list of entities.
+  ///        Identifiers are local (see createWorkplane).
+  ///        The main entity goes last.
+  bool createEntity(AttributePtr theAttribute,
+                    std::vector<Slvs_Entity>& theEntities,
+                    std::vector<Slvs_Param>& theParameters);
+  /// \brief Converts feature to the list of entities.
+  ///        Identifiers are local (see createWorkplane).
+  ///        The main entity goes last.
+  bool createEntity(FeaturePtr theFeature,
+                    std::vector<Slvs_Entity>& theEntities,
+                    std::vector<Slvs_Param>& theParameters);
+
+  /// \brief Converts normal and OX direction to the list of entities representing a normal in SolveSpace.
+  ///        Identifiers are local (see createWorkplane).
+  ///        The main entity goes last.
+  bool createNormal(AttributePtr theNormal,
+                    AttributePtr theDirX,
+                    std::vector<Slvs_Entity>& theEntities,
+                    std::vector<Slvs_Param>& theParameters);
+
+private:
+  static SketchSolver_Builder* mySelf;
 };
 
-typedef std::shared_ptr<SketchSolver_Builder> BuilderPtr;
-
 #endif
index 4792c51ff2a48391dd7bb84efcdd8e6408a5b604..b4b888fa3b75607f333ce26e27e8779247068f31 100644 (file)
@@ -1,27 +1,12 @@
 #include <SketchSolver_Constraint.h>
 #include <SketchSolver_Group.h>
 #include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
 
 #include <SketchPlugin_Arc.h>
 #include <SketchPlugin_Circle.h>
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_Point.h>
 
-#include <SketchPlugin_ConstraintAngle.h>
-#include <SketchPlugin_ConstraintCoincidence.h>
-#include <SketchPlugin_ConstraintDistance.h>
-#include <SketchPlugin_ConstraintEqual.h>
-#include <SketchPlugin_ConstraintHorizontal.h>
-#include <SketchPlugin_ConstraintLength.h>
-#include <SketchPlugin_ConstraintMirror.h>
-#include <SketchPlugin_ConstraintParallel.h>
-#include <SketchPlugin_ConstraintPerpendicular.h>
-#include <SketchPlugin_ConstraintRadius.h>
-#include <SketchPlugin_ConstraintRigid.h>
-#include <SketchPlugin_ConstraintTangent.h>
-#include <SketchPlugin_ConstraintVertical.h>
-
 #include <GeomAPI_Dir2d.h>
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Point2D.h>
 SketchSolver_Constraint::SketchSolver_Constraint(
     ConstraintPtr  theConstraint)
   : myBaseConstraint(theConstraint),
-    myGroupID(GID_UNKNOWN),
-    myType(CONSTRAINT_UNKNOWN)
+    myGroup(0)
 {
 }
 
-void SketchSolver_Constraint::process(StoragePtr theStorage,
-                                      const GroupID& theGroupID,
-                                      const EntityID& theSketchID)
+SketchSolver_Constraint::~SketchSolver_Constraint()
+{
+  std::map<AttributePtr, Slvs_hParam>::const_iterator anIt1 = myValueMap.begin();
+  for (; anIt1 != myValueMap.end(); anIt1++)
+    myStorage->removeParameter(anIt1->second);
+  myValueMap.clear();
+
+  std::map<AttributePtr, Slvs_hEntity>::const_iterator anIt2 = myAttributeMap.begin();
+  for (; anIt2 != myAttributeMap.end(); anIt2++)
+    myStorage->removeEntity(anIt2->second);
+  myAttributeMap.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++)
+    myStorage->removeConstraint(*anIt4);
+  mySlvsConstraints.clear();
+}
+
+void SketchSolver_Constraint::setStorage(StoragePtr theStorage)
 {
   myStorage = theStorage;
-  myGroupID = theGroupID;
-  mySketchID = theSketchID;
-  // Process constraint according to its type
   process();
 }
 
+void SketchSolver_Constraint::setGroup(SketchSolver_Group* theGroup)
+{
+  myGroup = theGroup;
+  process();
+}
 
-SketchSolver_ConstraintType SketchSolver_Constraint::TYPE(ConstraintPtr theConstraint)
+void SketchSolver_Constraint::addFeature(FeaturePtr theFeature)
 {
-  const std::string& aType = theConstraint->getKind();
-  if (aType == SketchPlugin_ConstraintCoincidence::ID())
-    return CONSTRAINT_COINCIDENCE;
-  else if (aType == SketchPlugin_ConstraintRigid::ID())
-    return CONSTRAINT_FIXED;
-  else if (aType == SketchPlugin_ConstraintHorizontal::ID())
-    return CONSTRAINT_HORIZONTAL;
-  else if (aType == SketchPlugin_ConstraintVertical::ID())
-    return CONSTRAINT_VERTICAL;
-  else if (aType == SketchPlugin_ConstraintAngle::ID())
-    return CONSTRAINT_ANGLE;
-  else if (aType == SketchPlugin_ConstraintDistance::ID())
-    return CONSTRAINT_DISTANCE;
-  else if (aType == SketchPlugin_ConstraintEqual::ID())
-    return CONSTRAINT_EQUAL;
-  else if (aType == SketchPlugin_ConstraintLength::ID())
-    return CONSTRAINT_PT_PT_DISTANCE;
-  else if (aType == SketchPlugin_ConstraintMirror::ID())
-    return CONSTRAINT_SYMMETRIC;
-  else if (aType == SketchPlugin_ConstraintParallel::ID())
-    return CONSTRAINT_PARALLEL;
-  else if (aType == SketchPlugin_ConstraintPerpendicular::ID())
-    return CONSTRAINT_PERPENDICULAR;
-  else if (aType == SketchPlugin_ConstraintRadius::ID())
-    return CONSTRAINT_RADIUS;
-  else if (aType == SketchPlugin_ConstraintTangent::ID())
-    return CONSTRAINT_TANGENT;
-  return CONSTRAINT_UNKNOWN;
+  int aType;
+  changeEntity(theFeature, aType);
 }
 
+
 void SketchSolver_Constraint::process()
 {
   cleanErrorMsg();
-  if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
-    // Not enough parameters are assigned
+  if (!myBaseConstraint || !myStorage || myGroup == 0) {
+    /// TODO: Put error message here
     return;
   }
-////  if (!myConstraints.empty()) // some data is changed, update constraint
-////    update();
+  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+    update(myBaseConstraint);
 
-  SketchSolver_ConstraintType aConstrType = getType();
-  double aValue;
-  std::vector<EntityWrapperPtr> anAttributes;
+  int aConstrType = getType();
+  double aValue = 0.0;
+  std::vector<Slvs_hEntity> anAttributes;
   getAttributes(aValue, anAttributes);
   if (!myErrorMsg.empty())
     return;
-  if (anAttributes.empty()) {
-    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-    return;
-  }
-  if (aConstrType == CONSTRAINT_UNKNOWN)
+  if (aConstrType == SLVS_C_UNKNOWN)
     aConstrType = getType();
 
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-  std::list<ConstraintWrapperPtr> aNewConstraints = aBuilder->createConstraint(
-      myBaseConstraint, myGroupID, mySketchID, aConstrType,
-      aValue, anAttributes[0], anAttributes[1], anAttributes[2], anAttributes[3]);
-  myStorage->addConstraint(myBaseConstraint, aNewConstraints);
+  Slvs_hGroup aGroupID = myGroup->getId();
+  Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
+  Slvs_Constraint aConstraint;
+  if (mySlvsConstraints.empty())
+    aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, aGroupID, aConstrType, aWorkplaneID,
+        aValue, anAttributes[0], anAttributes[1], anAttributes[2], anAttributes[3]);
+  else {
+    aConstraint = myStorage->getConstraint(mySlvsConstraints[0]);
+    aConstraint.valA = aValue;
+    static const int aNbAttrs = 6;
+    Slvs_hEntity* aConstrAttrs[aNbAttrs] = {
+        &aConstraint.ptA, &aConstraint.ptB,
+        &aConstraint.entityA, &aConstraint.entityB,
+        &aConstraint.entityC, &aConstraint.entityD};
+    std::vector<Slvs_hEntity>::const_iterator anIter = anAttributes.begin();
+    for (int i = 0; i < aNbAttrs && anIter != anAttributes.end(); i++, anIter++)
+      *(aConstrAttrs[i]) = *anIter;
+  }
 
+  Slvs_hConstraint anID = myStorage->addConstraint(aConstraint);
+  if (mySlvsConstraints.empty())
+    mySlvsConstraints.push_back(anID);
+  else
+    mySlvsConstraints[0] = anID;
   adjustConstraint();
 }
 
-////bool SketchSolver_Constraint::checkAttributesChanged(ConstraintPtr theConstraint)
-////{
-////  std::set<Slvs_hEntity> aCurAttrs; // list of currently used attributes
-////  std::vector<Slvs_hConstraint>::const_iterator aConstrIter = mySlvsConstraints.begin();
-////  for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) {
-////    Slvs_Constraint aConstr = myStorage->getConstraint(*aConstrIter);
-////    if (aConstr.ptA != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.ptA);
-////    if (aConstr.ptB != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.ptB);
-////    if (aConstr.entityA != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityA);
-////    if (aConstr.entityB != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityB);
-////    if (aConstr.entityC != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityC);
-////    if (aConstr.entityD != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityD);
-////  }
-////  // Check the attrbutes of constraint are changed
-////  ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
-////  std::list<AttributePtr> anAttrList = aConstraint->data()->attributes(std::string());
-////  std::list<AttributePtr>::iterator anAttrIter = anAttrList.begin();
-////  for (; anAttrIter != anAttrList.end(); anAttrIter++) {
-////    AttributeRefAttrPtr aRefAttr =
-////        std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
-////    if (aRefAttr) {
-////      if (aRefAttr->isObject()) {
-////        FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
-////        std::map<FeaturePtr, Slvs_hEntity>::iterator aFIt = myFeatureMap.find(aFeature);
-////        if (aFeature) {
-////          if (aFIt == myFeatureMap.end())
-////            return true;
-////          // Additional check the points of entity
-////          if (aCurAttrs.find(aFIt->second) == aCurAttrs.end()) {
-////            Slvs_Entity anEntity = myStorage->getEntity(aFIt->second);
-////            bool isFound = false;
-////            for (int i = 0; i < 4 && !isFound; i++)
-////              if (anEntity.point[i] != SLVS_E_UNKNOWN && 
-////                  aCurAttrs.find(anEntity.point[i]) != aCurAttrs.end())
-////                isFound = true;
-////            if (!isFound)
-////              return true;
-////          }
-////        }
-////      } else if (aRefAttr->attr()) {
-////        std::map<AttributePtr, Slvs_hEntity>::iterator anAIt = myAttributeMap.find(aRefAttr->attr());
-////        if (anAIt == myAttributeMap.end() || aCurAttrs.find(anAIt->second) == aCurAttrs.end())
-////          return true;
-////      }
-////    }
-////    AttributeRefListPtr aRefList =
-////        std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIter);
-////    if (aRefList) {
-////      std::list<ObjectPtr> anItems = aRefList->list();
-////      std::list<ObjectPtr>::iterator anIt = anItems.begin();
-////      for (; anIt != anItems.end(); anIt++) {
-////        FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
-////        if (aFeature && myFeatureMap.find(aFeature) == myFeatureMap.end())
-////          return true;
-////      }
-////    }
-////  }
-////  return false;
-////}
-
-void SketchSolver_Constraint::update()
+bool SketchSolver_Constraint::checkAttributesChanged(ConstraintPtr theConstraint)
+{
+  std::set<Slvs_hEntity> aCurAttrs; // list of currently used attributes
+  std::vector<Slvs_hConstraint>::const_iterator aConstrIter = mySlvsConstraints.begin();
+  for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) {
+    Slvs_Constraint aConstr = myStorage->getConstraint(*aConstrIter);
+    if (aConstr.ptA != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.ptA);
+    if (aConstr.ptB != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.ptB);
+    if (aConstr.entityA != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityA);
+    if (aConstr.entityB != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityB);
+    if (aConstr.entityC != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityC);
+    if (aConstr.entityD != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityD);
+  }
+  // Check the attrbutes of constraint are changed
+  ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
+  std::list<AttributePtr> anAttrList = aConstraint->data()->attributes(std::string());
+  std::list<AttributePtr>::iterator anAttrIter = anAttrList.begin();
+  for (; anAttrIter != anAttrList.end(); anAttrIter++) {
+    AttributeRefAttrPtr aRefAttr =
+        std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
+    if (aRefAttr) {
+      if (aRefAttr->isObject()) {
+        FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+        std::map<FeaturePtr, Slvs_hEntity>::iterator aFIt = myFeatureMap.find(aFeature);
+        if (aFeature) {
+          if (aFIt == myFeatureMap.end())
+            return true;
+          // Additional check the points of entity
+          if (aCurAttrs.find(aFIt->second) == aCurAttrs.end()) {
+            Slvs_Entity anEntity = myStorage->getEntity(aFIt->second);
+            bool isFound = false;
+            for (int i = 0; i < 4 && !isFound; i++)
+              if (anEntity.point[i] != SLVS_E_UNKNOWN && 
+                  aCurAttrs.find(anEntity.point[i]) != aCurAttrs.end())
+                isFound = true;
+            if (!isFound)
+              return true;
+          }
+        }
+      } else if (aRefAttr->attr()) {
+        std::map<AttributePtr, Slvs_hEntity>::iterator anAIt = myAttributeMap.find(aRefAttr->attr());
+        if (anAIt == myAttributeMap.end() || aCurAttrs.find(anAIt->second) == aCurAttrs.end())
+          return true;
+      }
+    }
+    AttributeRefListPtr aRefList =
+        std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIter);
+    if (aRefList) {
+      std::list<ObjectPtr> anItems = aRefList->list();
+      std::list<ObjectPtr>::iterator anIt = anItems.begin();
+      for (; anIt != anItems.end(); anIt++) {
+        FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+        if (aFeature && myFeatureMap.find(aFeature) == myFeatureMap.end())
+          return true;
+      }
+    }
+  }
+  return false;
+}
+
+void SketchSolver_Constraint::update(ConstraintPtr theConstraint)
 {
   cleanErrorMsg();
+  bool needToRebuild = (theConstraint && theConstraint != myBaseConstraint);
+  if (!needToRebuild)
+    needToRebuild = checkAttributesChanged(theConstraint);
+  if (needToRebuild) {
+    if (theConstraint && theConstraint->getKind() != myBaseConstraint->getKind())
+      return;
+    remove(myBaseConstraint);
+    if (theConstraint)
+      myBaseConstraint = theConstraint;
+    process();
+    return;
+  }
 
-  std::list<ConstraintWrapperPtr> aWrapper = myStorage->constraint(myBaseConstraint);
-  AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
-      myBaseConstraint->attribute(SketchPlugin_Constraint::VALUE()));
-  if (aValueAttr) {
-    std::list<ConstraintWrapperPtr>::iterator aWIt = aWrapper.begin();
-    for (; aWIt != aWrapper.end(); ++aWIt)
-      (*aWIt)->setValue(aValueAttr->value());
+  // 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++) {
+    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++) {
+    Slvs_hEntity aPrevID = anAttrIter->second;
+    anAttrIter->second = changeEntity(anAttrIter->first, aType);
+    if (anAttrIter->second != aPrevID)
+      aRelocationMap[aPrevID] = anAttrIter->second;
   }
-  myStorage->addConstraint(myBaseConstraint, aWrapper);
 
+  // Value if exists
+  DataPtr aData = myBaseConstraint->data();
+  if (!aData) return;
+  AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+    myBaseConstraint->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);
+    if (aValueAttr) {
+      aConstraint.valA = aValue;
+      if (aConstraint.type == SLVS_C_DIAMETER)
+        aConstraint.valA *= 2.0;
+    }
+    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()
+bool SketchSolver_Constraint::remove(ConstraintPtr theConstraint)
 {
   cleanErrorMsg();
-  return myStorage->removeConstraint(myBaseConstraint);
+  if (theConstraint && theConstraint != myBaseConstraint)
+    return false;
+  if (mySlvsConstraints.empty())
+    return true;
+  bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints.front());
+  if (isFullyRemoved) {
+    myFeatureMap.clear();
+    myAttributeMap.clear();
+    myValueMap.clear();
+  } else
+    cleanRemovedEntities();
+  mySlvsConstraints.clear();
+  return true;
+}
+
+void SketchSolver_Constraint::cleanRemovedEntities()
+{
+  std::set<Slvs_hParam> aRemovedParams;
+  std::set<Slvs_hEntity> aRemovedEntities;
+  std::set<Slvs_hConstraint> aRemovedConstraints;
+  myStorage->getRemoved(aRemovedParams, aRemovedEntities, aRemovedConstraints);
+  std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
+  while (aFeatIt != myFeatureMap.end()) {
+    if (aRemovedEntities.find(aFeatIt->second) == aRemovedEntities.end()) {
+      aFeatIt++;
+      continue;
+    }
+    std::map<FeaturePtr, Slvs_hEntity>::iterator aTmpIter = aFeatIt++;
+    myFeatureMap.erase(aTmpIter);
+  }
+  std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIt = myAttributeMap.begin();
+  while (anAttrIt != myAttributeMap.end()) {
+    if (aRemovedEntities.find(anAttrIt->second) == aRemovedEntities.end()) {
+      anAttrIt++;
+      continue;
+    }
+    std::map<AttributePtr, Slvs_hEntity>::iterator aTmpIter = anAttrIt++;
+    myAttributeMap.erase(aTmpIter);
+  }
+  std::map<AttributePtr, Slvs_hParam>::iterator aValIt = myValueMap.begin();
+  while (aValIt != myValueMap.end()) {
+    if (aRemovedParams.find(aValIt->second) == aRemovedParams.end()) {
+      aValIt++;
+      continue;
+    }
+    std::map<AttributePtr, Slvs_hParam>::iterator aTmpIter = aValIt++;
+    myValueMap.erase(aTmpIter);
+  }
+  for (size_t i = 0; i < mySlvsConstraints.size(); i++)
+    if (aRemovedConstraints.find(mySlvsConstraints[i]) != aRemovedConstraints.end()) {
+      mySlvsConstraints.erase(mySlvsConstraints.begin() + i);
+      i--;
+    }
 }
 
 void SketchSolver_Constraint::getAttributes(
     double& theValue,
-    std::vector<EntityWrapperPtr>& theAttributes)
+    std::vector<Slvs_hEntity>& theAttributes)
 {
   static const int anInitNbOfAttr = 4;
-  theAttributes.assign(anInitNbOfAttr, EntityWrapperPtr());
+  theAttributes.assign(anInitNbOfAttr, SLVS_E_UNKNOWN);
 
   DataPtr aData = myBaseConstraint->data();
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
-  myType = TYPE(myBaseConstraint);
 
   AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
-      aData->attribute(SketchPlugin_Constraint::VALUE()));
+    aData->attribute(SketchPlugin_Constraint::VALUE()));
   theValue = aValueAttr ? aValueAttr->value() : 0.0;
 
   int aPtInd = 0; // index of first point in the list of attributes
-  int aEntInd = 2; // index of first entity in the list of attributes
+  int aEntInd = 2; // index of first antity in the list of attributes
   std::list<AttributePtr> aConstrAttrs = aData->attributes(ModelAPI_AttributeRefAttr::typeId());
   std::list<AttributePtr>::iterator anIter = aConstrAttrs.begin();
   for (; anIter != aConstrAttrs.end(); anIter++) {
@@ -225,13 +325,18 @@ void SketchSolver_Constraint::getAttributes(
       return;
     }
 
-    myStorage->update(*anIter, myGroupID);
-    EntityWrapperPtr anEntity = myStorage->entity(*anIter);
+    int aType = SLVS_E_UNKNOWN; // type of created entity
+    Slvs_hEntity anEntity = myGroup->getAttributeId(aRefAttr);
+    if (anEntity == SLVS_E_UNKNOWN)
+      anEntity = changeEntity(aRefAttr, aType);
+    else {
+      Slvs_Entity anEnt = myStorage->getEntity(anEntity);
+      aType = anEnt.type;
+    }
 
-    SketchSolver_EntityType aType = anEntity->type();
-    if (aType == ENTITY_UNKNOWN)
+    if (aType == SLVS_E_UNKNOWN)
       continue;
-    else if (aType == ENTITY_POINT)
+    else if (aType == SLVS_E_POINT_IN_2D || aType == SLVS_E_POINT_IN_3D)
       theAttributes[aPtInd++] = anEntity; // the point is created
     else { // another entity (not a point) is created
       if (aEntInd < anInitNbOfAttr)
@@ -243,415 +348,403 @@ void SketchSolver_Constraint::getAttributes(
   }
 }
 
-bool SketchSolver_Constraint::isUsed(FeaturePtr theFeature) const
+Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributeRefAttrPtr theAttribute, int& theType)
 {
-  const std::list<ConstraintWrapperPtr>& aCList = myStorage->constraint(myBaseConstraint);
-  std::list<ConstraintWrapperPtr>::const_iterator aCIt = aCList.begin();
-  for (; aCIt != aCList.end(); ++aCIt)
-    if ((*aCIt)->isUsed(theFeature))
-      return true;
-
-  std::list<AttributePtr> anAttrList = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
-  std::list<AttributePtr>::const_iterator anAttrIt = anAttrList.begin();
-  for (; anAttrIt != anAttrList.end(); ++ anAttrIt)
-    if (isUsed(*anAttrIt))
-      return true;
+  // Convert the object of the attribute to the feature
+  FeaturePtr aFeature;
+  if (theAttribute->isObject() && theAttribute->object()) {
+    ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+        theAttribute->object());
+    if (!aRC) {
+      myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+      return SLVS_E_UNKNOWN;
+    }
+    std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
+    aFeature = aDoc->feature(aRC);
 
-  return false;
+    return changeEntity(aFeature, theType);
+  }
+
+  return changeEntity(theAttribute->attr(), theType);
+}
+
+Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributePtr theEntity, int& theType)
+{
+  Slvs_hEntity aResult = SLVS_E_UNKNOWN;
+  if (!theEntity || !isInitialized(theEntity)) {
+    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+    return SLVS_E_UNKNOWN;
+  }
+
+  // If the entity is already in the group, try to find it
+  std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator anEntIter =
+      myAttributeMap.find(theEntity);
+  Slvs_Entity aCurrentEntity;
+  aCurrentEntity.h = SLVS_E_UNKNOWN;
+  if (anEntIter != myAttributeMap.end())
+    aCurrentEntity = myStorage->getEntity(anEntIter->second);
+  else {
+    aResult = myGroup->getAttributeId(theEntity);
+    if (aResult != SLVS_E_UNKNOWN) {
+      Slvs_Entity anEnt = myStorage->getEntity(aResult);
+      theType = anEnt.type;
+      myAttributeMap[theEntity] = aResult;
+      return aResult;
+    }
+  }
+
+  Slvs_hGroup aGroupID = myGroup->getId();
+  // do not update entity from another group
+  if (aCurrentEntity.h != SLVS_E_UNKNOWN && aGroupID != aCurrentEntity.group)
+    return aCurrentEntity.h;
+
+  // Point in 3D
+  std::shared_ptr<GeomDataAPI_Point> aPoint =
+      std::dynamic_pointer_cast<GeomDataAPI_Point>(theEntity);
+  if (aPoint) {
+    double aXYZ[3] = {aPoint->x(), aPoint->y(), aPoint->z()};
+    Slvs_hParam aParams[3];
+    for (int i = 0; i < 3; i++) {
+      Slvs_Param aPar = aCurrentEntity.h != SLVS_E_UNKNOWN ?
+          myStorage->getParameter(aCurrentEntity.param[i]) :
+          Slvs_MakeParam(SLVS_E_UNKNOWN, aGroupID, 0.0);
+      aPar.val = aXYZ[i];
+      aParams[i] = myStorage->addParameter(aPar);
+    }
+
+    if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
+      aCurrentEntity = Slvs_MakePoint3d(SLVS_E_UNKNOWN, aGroupID, aParams[0], aParams[1], aParams[2]);
+    else { // update entity data
+      for (int i = 0; i < 3; i++)
+        aCurrentEntity.param[i] = aParams[i];
+    }
+    aResult = myStorage->addEntity(aCurrentEntity);
+  } else {
+    // All entities except 3D points are created on workplane. So, if there is no workplane yet, then error
+    Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
+    if (aWorkplaneID == SLVS_E_UNKNOWN)
+      return SLVS_E_UNKNOWN;
+
+    // Point in 2D
+    std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEntity);
+    if (aPoint2D) {
+      double aXY[2] = {aPoint2D->x(), aPoint2D->y()};
+      Slvs_hParam aParams[2];
+      for (int i = 0; i < 2; i++) {
+        Slvs_Param aPar = aCurrentEntity.h != SLVS_E_UNKNOWN ?
+            myStorage->getParameter(aCurrentEntity.param[i]) :
+            Slvs_MakeParam(SLVS_E_UNKNOWN, aGroupID, 0.0);
+        aPar.val = aXY[i];
+        aParams[i] = myStorage->addParameter(aPar);
+      }
+
+      if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
+        aCurrentEntity = Slvs_MakePoint2d(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aParams[0], aParams[1]);
+      else { // update entity data
+        for (int i = 0; i < 2; i++)
+          aCurrentEntity.param[i] = aParams[i];
+      }
+      aResult = myStorage->addEntity(aCurrentEntity);
+    } else {
+      // Scalar value (used for the distance entities)
+      AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theEntity);
+      if (aScalar) {
+        Slvs_Param aParam = aCurrentEntity.h != SLVS_E_UNKNOWN ?
+            myStorage->getParameter(aCurrentEntity.param[0]) :
+            Slvs_MakeParam(SLVS_E_UNKNOWN, aGroupID, 0.0);
+        aParam.val = aScalar->value();
+        Slvs_hParam aValue = myStorage->addParameter(aParam);
+
+        if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
+          aCurrentEntity = Slvs_MakeDistance(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aValue);
+        else
+          aCurrentEntity.param[0] = aValue;
+        aResult = myStorage->addEntity(aCurrentEntity);
+      }
+    }
+  }
+
+  myAttributeMap[theEntity] = aResult;
+  theType = aCurrentEntity.type;
+  return aResult;
 }
 
-bool SketchSolver_Constraint::isUsed(AttributePtr theAttribute) const
+Slvs_hEntity SketchSolver_Constraint::changeEntity(FeaturePtr theEntity, int& theType)
 {
-  AttributePtr anAttribute = theAttribute;
-  AttributeRefAttrPtr aRefAttr =
-      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
-  if (aRefAttr) {
-    if (aRefAttr->isObject())
-      return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
-    else
-      anAttribute = aRefAttr->attr();
+  Slvs_hEntity aResult = SLVS_E_UNKNOWN;
+  if (!theEntity || !theEntity->data() || !theEntity->data()->isValid())
+    return SLVS_E_UNKNOWN;
+  // If the entity is already in the group, try to find it
+  std::map<FeaturePtr, Slvs_hEntity>::const_iterator anEntIter = myFeatureMap.find(theEntity);
+  Slvs_Entity aCurrentEntity;
+  aCurrentEntity.h = SLVS_E_UNKNOWN;
+  if (anEntIter != myFeatureMap.end())
+    aCurrentEntity = myStorage->getEntity(anEntIter->second);
+  else {
+    aResult = myGroup->getFeatureId(theEntity);
+    if (aResult != SLVS_E_UNKNOWN) {
+      Slvs_Entity anEnt = myStorage->getEntity(aResult);
+      theType = anEnt.type;
+      myFeatureMap[theEntity] = aResult;
+      return aResult;
+    }
+  }
+
+  Slvs_hGroup aGroupID = myGroup->getId();
+  // do not update entity from another group
+  if (aCurrentEntity.h != SLVS_E_UNKNOWN && aGroupID != aCurrentEntity.group)
+    return aCurrentEntity.h;
+
+  Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
+  DataPtr aData = theEntity->data();
+
+  // SketchPlugin features
+  const std::string& aFeatureKind = theEntity->getKind();
+  AttributePtr anAttribute;
+  int anAttrType;
+  // Line
+  if (aFeatureKind == SketchPlugin_Line::ID()) {
+    anAttribute = aData->attribute(SketchPlugin_Line::START_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
+
+    anAttribute = aData->attribute(SketchPlugin_Line::END_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType);
+
+    if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
+      aCurrentEntity = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aStart, aEnd);
+    else {
+      aCurrentEntity.point[0] = aStart;
+      aCurrentEntity.point[1] = aEnd;
+    }
+    aResult = myStorage->addEntity(aCurrentEntity);
+  }
+  // Circle
+  else if (aFeatureKind == SketchPlugin_Circle::ID()) {
+    anAttribute = aData->attribute(SketchPlugin_Circle::CENTER_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
+
+    anAttribute = aData->attribute(SketchPlugin_Circle::RADIUS_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    Slvs_hEntity aRadius = changeEntity(anAttribute, anAttrType);
+
+    if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity
+      Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID);
+      aCurrentEntity = Slvs_MakeCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID,
+                                        aCenter, aWorkplane.normal, aRadius);
+    } else {
+      aCurrentEntity.point[0] = aCenter;
+      aCurrentEntity.distance = aRadius;
+    }
+    aResult = myStorage->addEntity(aCurrentEntity);
+  }
+  // Arc
+  else if (aFeatureKind == SketchPlugin_Arc::ID()) {
+    anAttribute = aData->attribute(SketchPlugin_Arc::CENTER_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
+
+    anAttribute = aData->attribute(SketchPlugin_Arc::START_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
+
+    anAttribute = aData->attribute(SketchPlugin_Arc::END_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType);
+
+    if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity
+      Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID);
+      aCurrentEntity = Slvs_MakeArcOfCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID,
+                                            aWorkplane.normal, aCenter, aStart, aEnd);
+    } else {
+      aCurrentEntity.point[0] = aCenter;
+      aCurrentEntity.point[1] = aStart;
+      aCurrentEntity.point[2] = aEnd;
+    }
+    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 == SketchPlugin_Point::ID()) {
+    anAttribute = aData->attribute(SketchPlugin_Point::COORD_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier
+    aResult = changeEntity(anAttribute, anAttrType);
+    aCurrentEntity.type = SLVS_E_POINT_IN_3D;
+  }
+
+  if (aResult != SLVS_E_UNKNOWN) {
+    myFeatureMap[theEntity] = aResult;
+    theType = aCurrentEntity.type;
   }
+  return aResult;
+}
 
-  const std::list<ConstraintWrapperPtr>& aCList = myStorage->constraint(myBaseConstraint);
-  std::list<ConstraintWrapperPtr>::const_iterator aCIt = aCList.begin();
-  for (; aCIt != aCList.end(); ++aCIt)
-    if ((*aCIt)->isUsed(theAttribute))
-      return true;
+std::list<ConstraintPtr> SketchSolver_Constraint::constraints() const
+{
+  std::list<ConstraintPtr> aConstraints;
+  aConstraints.push_back(myBaseConstraint);
+  return aConstraints;
+}
+
+void SketchSolver_Constraint::refresh()
+{
+  cleanErrorMsg();
+  std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
+  while (anAttrIter != myAttributeMap.end()) {
+    std::shared_ptr<GeomDataAPI_Point> aPoint =
+        std::dynamic_pointer_cast<GeomDataAPI_Point>(anAttrIter->first);
+    Slvs_Entity anEntity = myStorage->getEntity(anAttrIter->second);
+    if (anEntity.h == SLVS_E_UNKNOWN) {
+      std::map<AttributePtr, Slvs_hEntity>::iterator aTmpIter = anAttrIter++;
+      myAttributeMap.erase(aTmpIter);
+      continue;
+    }
+    if (aPoint) {
+      double aXYZ[3];
+      for (int i = 0; i < 3; i++) {
+        Slvs_Param aPar = myStorage->getParameter(anEntity.param[i]);
+        aXYZ[i] = aPar.val;
+      }
+      if (fabs(aPoint->x() - aXYZ[0]) > tolerance ||
+          fabs(aPoint->y() - aXYZ[1]) > tolerance ||
+          fabs(aPoint->z() - aXYZ[2]) > tolerance)
+        aPoint->setValue(aXYZ[0], aXYZ[1], aXYZ[2]);
+    } else {
+      // Point in 2D
+      std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttrIter->first);
+      if (aPoint2D) {
+        double aXY[2];
+        for (int i = 0; i < 2; i++) {
+          Slvs_Param aPar = myStorage->getParameter(anEntity.param[i]);
+          aXY[i] = aPar.val;
+        }
+        if (fabs(aPoint2D->x() - aXY[0]) > tolerance ||
+            fabs(aPoint2D->y() - aXY[1]) > tolerance)
+          aPoint2D->setValue(aXY[0], aXY[1]);
+      } else {
+        // Scalar value (used for the distance entities)
+        AttributeDoublePtr aScalar =
+            std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttrIter->first);
+        if (aScalar) {
+          Slvs_Param aPar = myStorage->getParameter(anEntity.param[0]);
+          if (fabs(aScalar->value() - aPar.val) > tolerance)
+            aScalar->setValue(aPar.val);
+        }
+      }
+    }
+    anAttrIter++;
+  }
+
+  std::map<AttributePtr, Slvs_hParam>::iterator aValIter = myValueMap.begin();
+  for (; aValIter != myValueMap.end(); aValIter++) {
+    AttributeDoublePtr aScalar =
+        std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttrIter->first);
+    if (aScalar) {
+      Slvs_Param aPar = myStorage->getParameter(anAttrIter->second);
+      aScalar->setValue(aPar.val);
+    }
+  }
+}
+
+Slvs_hEntity SketchSolver_Constraint::getId(FeaturePtr theFeature) const
+{
+  std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFIter = myFeatureMap.find(theFeature);
+  if (aFIter == myFeatureMap.end())
+    return SLVS_E_UNKNOWN;
+  //// check the Feature is really in the storage
+  //Slvs_Entity anEntity = myStorage->getEntity(aFIter->second);
+  //if (anEntity.h == SLVS_E_UNKNOWN) {
+  //  // rebuild feature
+  //  int aType;
+  //  anEntity.h = const_cast<SketchSolver_Constraint*>(this)->changeEntity(aFIter->first, aType);
+  //  const_cast<SketchSolver_Constraint*>(this)->myFeatureMap[theFeature] = anEntity.h;
+  //}
+  //return anEntity.h;
+  return aFIter->second;
+}
+
+Slvs_hEntity SketchSolver_Constraint::getId(AttributePtr theAttribute) const
+{
+  std::map<AttributePtr, Slvs_hEntity>::const_iterator anAttrIter = myAttributeMap.find(theAttribute);
+  if (anAttrIter == myAttributeMap.end())
+    return SLVS_E_UNKNOWN;
+  return anAttrIter->second;
+}
+
+bool SketchSolver_Constraint::isInitialized(AttributePtr theAttribute)
+{
+  if (theAttribute->isInitialized())
+    return true;
+  myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
   return false;
 }
 
-////Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributeRefAttrPtr theAttribute, int& theType)
-////{
-////  // Convert the object of the attribute to the feature
-////  FeaturePtr aFeature;
-////  if (theAttribute->isObject() && theAttribute->object()) {
-////    ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
-////        theAttribute->object());
-////    if (!aRC) {
-////      myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
-////      return SLVS_E_UNKNOWN;
-////    }
-////    std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
-////    aFeature = aDoc->feature(aRC);
-////
-////    return changeEntity(aFeature, theType);
-////  }
-////
-////  return changeEntity(theAttribute->attr(), theType);
-////}
-////
-////Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributePtr theEntity, int& theType)
-////{
-////  Slvs_hEntity aResult = SLVS_E_UNKNOWN;
-////  if (!theEntity || !isInitialized(theEntity)) {
-////    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
-////    return SLVS_E_UNKNOWN;
-////  }
-////
-////  // If the entity is already in the group, try to find it
-////  std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator anEntIter =
-////      myAttributeMap.find(theEntity);
-////  Slvs_Entity aCurrentEntity;
-////  aCurrentEntity.h = SLVS_E_UNKNOWN;
-////  if (anEntIter != myAttributeMap.end())
-////    aCurrentEntity = myStorage->getEntity(anEntIter->second);
-////  else {
-////    aResult = myGroup->getAttributeId(theEntity);
-////    if (aResult != SLVS_E_UNKNOWN) {
-////      Slvs_Entity anEnt = myStorage->getEntity(aResult);
-////      theType = anEnt.type;
-////      myAttributeMap[theEntity] = aResult;
-////      return aResult;
-////    }
-////  }
-////
-////  Slvs_hGroup aGroupID = myGroup->getId();
-////  // do not update entity from another group
-////  if (aCurrentEntity.h != SLVS_E_UNKNOWN && aGroupID != aCurrentEntity.group)
-////    return aCurrentEntity.h;
-////
-////  // Point in 3D
-////  std::shared_ptr<GeomDataAPI_Point> aPoint =
-////      std::dynamic_pointer_cast<GeomDataAPI_Point>(theEntity);
-////  if (aPoint) {
-////    double aXYZ[3] = {aPoint->x(), aPoint->y(), aPoint->z()};
-////    Slvs_hParam aParams[3];
-////    for (int i = 0; i < 3; i++) {
-////      Slvs_Param aPar = aCurrentEntity.h != SLVS_E_UNKNOWN ?
-////          myStorage->getParameter(aCurrentEntity.param[i]) :
-////          Slvs_MakeParam(SLVS_E_UNKNOWN, aGroupID, 0.0);
-////      aPar.val = aXYZ[i];
-////      aParams[i] = myStorage->addParameter(aPar);
-////    }
-////
-////    if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
-////      aCurrentEntity = Slvs_MakePoint3d(SLVS_E_UNKNOWN, aGroupID, aParams[0], aParams[1], aParams[2]);
-////    else { // update entity data
-////      for (int i = 0; i < 3; i++)
-////        aCurrentEntity.param[i] = aParams[i];
-////    }
-////    aResult = myStorage->addEntity(aCurrentEntity);
-////  } else {
-////    // All entities except 3D points are created on workplane. So, if there is no workplane yet, then error
-////    Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
-////    if (aWorkplaneID == SLVS_E_UNKNOWN)
-////      return SLVS_E_UNKNOWN;
-////
-////    // Point in 2D
-////    std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
-////        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEntity);
-////    if (aPoint2D) {
-////      double aXY[2] = {aPoint2D->x(), aPoint2D->y()};
-////      Slvs_hParam aParams[2];
-////      for (int i = 0; i < 2; i++) {
-////        Slvs_Param aPar = aCurrentEntity.h != SLVS_E_UNKNOWN ?
-////            myStorage->getParameter(aCurrentEntity.param[i]) :
-////            Slvs_MakeParam(SLVS_E_UNKNOWN, aGroupID, 0.0);
-////        aPar.val = aXY[i];
-////        aParams[i] = myStorage->addParameter(aPar);
-////      }
-////
-////      if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
-////        aCurrentEntity = Slvs_MakePoint2d(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aParams[0], aParams[1]);
-////      else { // update entity data
-////        for (int i = 0; i < 2; i++)
-////          aCurrentEntity.param[i] = aParams[i];
-////      }
-////      aResult = myStorage->addEntity(aCurrentEntity);
-////    } else {
-////      // Scalar value (used for the distance entities)
-////      AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theEntity);
-////      if (aScalar) {
-////        Slvs_Param aParam = aCurrentEntity.h != SLVS_E_UNKNOWN ?
-////            myStorage->getParameter(aCurrentEntity.param[0]) :
-////            Slvs_MakeParam(SLVS_E_UNKNOWN, aGroupID, 0.0);
-////        aParam.val = aScalar->value();
-////        Slvs_hParam aValue = myStorage->addParameter(aParam);
-////
-////        if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
-////          aCurrentEntity = Slvs_MakeDistance(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aValue);
-////        else
-////          aCurrentEntity.param[0] = aValue;
-////        aResult = myStorage->addEntity(aCurrentEntity);
-////      }
-////    }
-////  }
-////
-////  myAttributeMap[theEntity] = aResult;
-////  theType = aCurrentEntity.type;
-////  return aResult;
-////}
-////
-////Slvs_hEntity SketchSolver_Constraint::changeEntity(FeaturePtr theEntity, int& theType)
-////{
-////  Slvs_hEntity aResult = SLVS_E_UNKNOWN;
-////  if (!theEntity || !theEntity->data() || !theEntity->data()->isValid())
-////    return SLVS_E_UNKNOWN;
-////  // If the entity is already in the group, try to find it
-////  std::map<FeaturePtr, Slvs_hEntity>::const_iterator anEntIter = myFeatureMap.find(theEntity);
-////  Slvs_Entity aCurrentEntity;
-////  aCurrentEntity.h = SLVS_E_UNKNOWN;
-////  if (anEntIter != myFeatureMap.end())
-////    aCurrentEntity = myStorage->getEntity(anEntIter->second);
-////  else {
-////    aResult = myGroup->getFeatureId(theEntity);
-////    if (aResult != SLVS_E_UNKNOWN) {
-////      Slvs_Entity anEnt = myStorage->getEntity(aResult);
-////      theType = anEnt.type;
-////      myFeatureMap[theEntity] = aResult;
-////      return aResult;
-////    }
-////  }
-////
-////  Slvs_hGroup aGroupID = myGroup->getId();
-////  // do not update entity from another group
-////  if (aCurrentEntity.h != SLVS_E_UNKNOWN && aGroupID != aCurrentEntity.group)
-////    return aCurrentEntity.h;
-////
-////  Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
-////  DataPtr aData = theEntity->data();
-////
-////  // SketchPlugin features
-////  const std::string& aFeatureKind = theEntity->getKind();
-////  AttributePtr anAttribute;
-////  int anAttrType;
-////  // Line
-////  if (aFeatureKind == SketchPlugin_Line::ID()) {
-////    anAttribute = aData->attribute(SketchPlugin_Line::START_ID());
-////    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-////    Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
-////
-////    anAttribute = aData->attribute(SketchPlugin_Line::END_ID());
-////    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-////    Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType);
-////
-////    if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
-////      aCurrentEntity = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aStart, aEnd);
-////    else {
-////      aCurrentEntity.point[0] = aStart;
-////      aCurrentEntity.point[1] = aEnd;
-////    }
-////    aResult = myStorage->addEntity(aCurrentEntity);
-////  }
-////  // Circle
-////  else if (aFeatureKind == SketchPlugin_Circle::ID()) {
-////    anAttribute = aData->attribute(SketchPlugin_Circle::CENTER_ID());
-////    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-////    Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
-////
-////    anAttribute = aData->attribute(SketchPlugin_Circle::RADIUS_ID());
-////    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-////    Slvs_hEntity aRadius = changeEntity(anAttribute, anAttrType);
-////
-////    if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity
-////      Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID);
-////      aCurrentEntity = Slvs_MakeCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID,
-////                                        aCenter, aWorkplane.normal, aRadius);
-////    } else {
-////      aCurrentEntity.point[0] = aCenter;
-////      aCurrentEntity.distance = aRadius;
-////    }
-////    aResult = myStorage->addEntity(aCurrentEntity);
-////  }
-////  // Arc
-////  else if (aFeatureKind == SketchPlugin_Arc::ID()) {
-////    anAttribute = aData->attribute(SketchPlugin_Arc::CENTER_ID());
-////    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-////    Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
-////
-////    anAttribute = aData->attribute(SketchPlugin_Arc::START_ID());
-////    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-////    Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
-////
-////    anAttribute = aData->attribute(SketchPlugin_Arc::END_ID());
-////    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-////    Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType);
-////
-////    if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity
-////      Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID);
-////      aCurrentEntity = Slvs_MakeArcOfCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID,
-////                                            aWorkplane.normal, aCenter, aStart, aEnd);
-////    } else {
-////      aCurrentEntity.point[0] = aCenter;
-////      aCurrentEntity.point[1] = aStart;
-////      aCurrentEntity.point[2] = aEnd;
-////    }
-////    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 == SketchPlugin_Point::ID()) {
-////    anAttribute = aData->attribute(SketchPlugin_Point::COORD_ID());
-////    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-////    // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier
-////    aResult = changeEntity(anAttribute, anAttrType);
-////    aCurrentEntity.type = SLVS_E_POINT_IN_3D;
-////  }
-////
-////  if (aResult != SLVS_E_UNKNOWN) {
-////    myFeatureMap[theEntity] = aResult;
-////    theType = aCurrentEntity.type;
-////  }
-////  return aResult;
-////}
-////
-////bool SketchSolver_Constraint::hasConstraint(ConstraintPtr theConstraint) const
-////{
-////  std::list<ConstraintPtr>::const_iterator anIt = myConstraints.begin();
-////  for (; anIt != myConstraints.end(); ++anIt)
-////    if (*anIt == theConstraint)
-////      return true;
-////  return false;
-////}
-////
-////void SketchSolver_Constraint::refresh()
-////{
-////  cleanErrorMsg();
-////  std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
-////  while (anAttrIter != myAttributeMap.end()) {
-////    std::shared_ptr<GeomDataAPI_Point> aPoint =
-////        std::dynamic_pointer_cast<GeomDataAPI_Point>(anAttrIter->first);
-////    Slvs_Entity anEntity = myStorage->getEntity(anAttrIter->second);
-////    if (anEntity.h == SLVS_E_UNKNOWN) {
-////      std::map<AttributePtr, Slvs_hEntity>::iterator aTmpIter = anAttrIter++;
-////      myAttributeMap.erase(aTmpIter);
-////      continue;
-////    }
-////    if (aPoint) {
-////      double aXYZ[3];
-////      for (int i = 0; i < 3; i++) {
-////        Slvs_Param aPar = myStorage->getParameter(anEntity.param[i]);
-////        aXYZ[i] = aPar.val;
-////      }
-////      if (fabs(aPoint->x() - aXYZ[0]) > tolerance ||
-////          fabs(aPoint->y() - aXYZ[1]) > tolerance ||
-////          fabs(aPoint->z() - aXYZ[2]) > tolerance)
-////        aPoint->setValue(aXYZ[0], aXYZ[1], aXYZ[2]);
-////    } else {
-////      // Point in 2D
-////      std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
-////          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttrIter->first);
-////      if (aPoint2D) {
-////        double aXY[2];
-////        for (int i = 0; i < 2; i++) {
-////          Slvs_Param aPar = myStorage->getParameter(anEntity.param[i]);
-////          aXY[i] = aPar.val;
-////        }
-////        if (fabs(aPoint2D->x() - aXY[0]) > tolerance ||
-////            fabs(aPoint2D->y() - aXY[1]) > tolerance)
-////          aPoint2D->setValue(aXY[0], aXY[1]);
-////      } else {
-////        // Scalar value (used for the distance entities)
-////        AttributeDoublePtr aScalar =
-////            std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttrIter->first);
-////        if (aScalar) {
-////          Slvs_Param aPar = myStorage->getParameter(anEntity.param[0]);
-////          if (fabs(aScalar->value() - aPar.val) > tolerance)
-////            aScalar->setValue(aPar.val);
-////        }
-////      }
-////    }
-////    anAttrIter++;
-////  }
-////
-////  std::map<AttributePtr, Slvs_hParam>::iterator aValIter = myValueMap.begin();
-////  for (; aValIter != myValueMap.end(); aValIter++) {
-////    AttributeDoublePtr aScalar =
-////        std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttrIter->first);
-////    if (aScalar) {
-////      Slvs_Param aPar = myStorage->getParameter(anAttrIter->second);
-////      aScalar->setValue(aPar.val);
-////    }
-////  }
-////}
-
-////bool SketchSolver_Constraint::isInitialized(AttributePtr theAttribute)
-////{
-////  if (theAttribute->isInitialized())
-////    return true;
-////  myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
-////  return false;
-////}
-////
-////
-////void SketchSolver_Constraint::calculateMiddlePoint(
-////    const Slvs_Entity& theEntity, double theCoeff, double& theX, double& theY) const
-////{
-////  if (theEntity.type == SLVS_E_LINE_SEGMENT) {
-////    double aStartEndXY[2][2];
-////    Slvs_Entity aPoint;
-////    for (int i = 0; i < 2; i++) {
-////      aPoint = myStorage->getEntity(theEntity.point[i]);
-////      for (int j = 0; j < 2; j++)
-////        aStartEndXY[i][j] = myStorage->getParameter(aPoint.param[j]).val;
-////    }
-////    theX = (1.0 - theCoeff) * aStartEndXY[0][0] + theCoeff * aStartEndXY[1][0];
-////    theY = (1.0 - theCoeff) * aStartEndXY[0][1] + theCoeff * aStartEndXY[1][1];
-////  } else if (theEntity.type == SLVS_E_ARC_OF_CIRCLE) {
-////    double anArcPoint[3][2];
-////    Slvs_Entity aPoint;
-////    for (int i = 0; i < 3; i++) {
-////      aPoint = myStorage->getEntity(theEntity.point[i]);
-////      for (int j = 0; j < 2; j++)
-////        anArcPoint[i][j] = myStorage->getParameter(aPoint.param[j]).val;
-////    }
-////    // project last point of arc on the arc
-////    double x = anArcPoint[1][0] - anArcPoint[0][0];
-////    double y = anArcPoint[1][1] - anArcPoint[0][1];
-////    double aRad = sqrt(x*x + y*y);
-////    x = anArcPoint[2][0] - anArcPoint[0][0];
-////    y = anArcPoint[2][1] - anArcPoint[0][1];
-////    double aNorm = sqrt(x*x + y*y);
-////    if (aNorm >= tolerance) {
-////      anArcPoint[2][0] = x * aRad / aNorm;
-////      anArcPoint[2][1] = y * aRad / aNorm;
-////    }
-////    anArcPoint[1][0] -= anArcPoint[0][0];
-////    anArcPoint[1][1] -= anArcPoint[0][1];
-////    if (theCoeff < tolerance) {
-////      theX = anArcPoint[0][0] + anArcPoint[1][0];
-////      theY = anArcPoint[0][1] + anArcPoint[1][1];
-////      return;
-////    } else if (1 - theCoeff < tolerance) {
-////      theX = anArcPoint[0][0] + anArcPoint[2][0];
-////      theY = anArcPoint[0][1] + anArcPoint[2][1];
-////      return;
-////    }
-////
-////    std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
-////    std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
-////    double anAngle = aStartDir->angle(aEndDir);
-////    if (anAngle < 0)
-////      anAngle += 2.0 * PI;
-////    anAngle *= theCoeff;
-////    double aCos = cos(anAngle);
-////    double aSin = sin(anAngle);
-////    theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
-////    theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
-////  }
-////}
+
+void SketchSolver_Constraint::calculateMiddlePoint(
+    const Slvs_Entity& theEntity, double theCoeff, double& theX, double& theY) const
+{
+  if (theEntity.type == SLVS_E_LINE_SEGMENT) {
+    double aStartEndXY[2][2];
+    Slvs_Entity aPoint;
+    for (int i = 0; i < 2; i++) {
+      aPoint = myStorage->getEntity(theEntity.point[i]);
+      for (int j = 0; j < 2; j++)
+        aStartEndXY[i][j] = myStorage->getParameter(aPoint.param[j]).val;
+    }
+    theX = (1.0 - theCoeff) * aStartEndXY[0][0] + theCoeff * aStartEndXY[1][0];
+    theY = (1.0 - theCoeff) * aStartEndXY[0][1] + theCoeff * aStartEndXY[1][1];
+  } else if (theEntity.type == SLVS_E_ARC_OF_CIRCLE) {
+    double anArcPoint[3][2];
+    Slvs_Entity aPoint;
+    for (int i = 0; i < 3; i++) {
+      aPoint = myStorage->getEntity(theEntity.point[i]);
+      for (int j = 0; j < 2; j++)
+        anArcPoint[i][j] = myStorage->getParameter(aPoint.param[j]).val;
+    }
+    // project last point of arc on the arc
+    double x = anArcPoint[1][0] - anArcPoint[0][0];
+    double y = anArcPoint[1][1] - anArcPoint[0][1];
+    double aRad = sqrt(x*x + y*y);
+    x = anArcPoint[2][0] - anArcPoint[0][0];
+    y = anArcPoint[2][1] - anArcPoint[0][1];
+    double aNorm = sqrt(x*x + y*y);
+    if (aNorm >= tolerance) {
+      anArcPoint[2][0] = x * aRad / aNorm;
+      anArcPoint[2][1] = y * aRad / aNorm;
+    }
+    anArcPoint[1][0] -= anArcPoint[0][0];
+    anArcPoint[1][1] -= anArcPoint[0][1];
+    if (theCoeff < tolerance) {
+      theX = anArcPoint[0][0] + anArcPoint[1][0];
+      theY = anArcPoint[0][1] + anArcPoint[1][1];
+      return;
+    } else if (1 - theCoeff < tolerance) {
+      theX = anArcPoint[0][0] + anArcPoint[2][0];
+      theY = anArcPoint[0][1] + anArcPoint[2][1];
+      return;
+    }
+
+    std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
+    std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
+    double anAngle = aStartDir->angle(aEndDir);
+    if (anAngle < 0)
+      anAngle += 2.0 * PI;
+    anAngle *= theCoeff;
+    double aCos = cos(anAngle);
+    double aSin = sin(anAngle);
+    theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
+    theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
+  }
+}
 
 void SketchSolver_Constraint::makeTemporary() const
 {
-  myStorage->setTemporary(myBaseConstraint);
+  std::vector<Slvs_hConstraint>::const_iterator anIt = mySlvsConstraints.begin();
+  for (; anIt != mySlvsConstraints.end(); anIt++)
+    myStorage->addTemporaryConstraint(*anIt);
 }
 
index d1ea3e1b55f788d843ac9a002ace028cab235e3a..974143246cff2f493fdf6547bc8941660265fd9f 100644 (file)
 #include <string>
 #include <vector>
 
+class SketchSolver_Group;
+
 /** \class   SketchSolver_Constraint
  *  \ingroup Plugins
- *  \brief   Converts SketchPlugin constraint to the constraint applicable for solver
+ *  \brief   Stores mapping between SketchPlugin and SolveSpace constraints data
  */
 class SketchSolver_Constraint
 {
 protected:
   /// Default constructor
-  SketchSolver_Constraint()
-    : myGroupID(GID_UNKNOWN),
-      myType(CONSTRAINT_UNKNOWN)
-  {}
-
-public:
+  SketchSolver_Constraint() {}
   /// Constructor based on SketchPlugin constraint
-  SKETCHSOLVER_EXPORT SketchSolver_Constraint(ConstraintPtr theConstraint);
+  SketchSolver_Constraint(ConstraintPtr theConstraint);
 
-  virtual ~SketchSolver_Constraint() {}
+public:
+  virtual ~SketchSolver_Constraint();
 
-  /// \brief Initializes parameters and start constraint creation
-  /// \param theStorage  [in]  storage where to place new constraint
-  /// \param theGroupID  [in]  group for constraint
-  /// \param theSketchID [in] sketch for constraint
-  void process(StoragePtr theStorage, const GroupID& theGroupID, const EntityID& theSketchID);
+  /// \brief Initializes the storage of SolveSpace constraints
+  void setStorage(StoragePtr theStorage);
+  /// \brief Initializes group ID for this constraint
+  void setGroup(SketchSolver_Group* theGroup);
 
   /// \brief Update constraint
-  SKETCHSOLVER_EXPORT virtual void update();
+  virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
 
   /// \brief Tries to remove constraint
   /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
-  SKETCHSOLVER_EXPORT virtual bool remove();
+  virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
 
-  /// \brief Obtain a type of SketchPlugin constraint
-  SKETCHSOLVER_EXPORT static SketchSolver_ConstraintType TYPE(ConstraintPtr theConstraint);
+  /// \brief Update SketchPlugin attributes using the data obtained from SolveSpace entities
+  virtual void refresh();
 
   /// \brief Returns the type of constraint
-////  virtual SketchSolver_ConstraintType getType() const = 0;
-  virtual SketchSolver_ConstraintType getType() const
-  { return myType; }
+  virtual int getType() const = 0;
 
   /// \brief The constraint is made temporary
   void makeTemporary() const;
 
-  /// \brief Verify the feature or any its attribute is used by constraint
-  bool isUsed(FeaturePtr theFeature) const;
-  /// \brief Verify the attribute is used by constraint
-  bool isUsed(AttributePtr theAttribute) const;
+  /// \brief Checks the constraint is used by current object
+  virtual bool hasConstraint(ConstraintPtr theConstraint) const
+  { return theConstraint == myBaseConstraint; }
+
+  /// \brief Return list of SketchPlugin constraints attached to this object
+  virtual std::list<ConstraintPtr> constraints() const;
 
-////  /// \brief Checks the constraint is used by current object
-////  SKETCHSOLVER_EXPORT virtual bool hasConstraint(ConstraintPtr theConstraint) const;
-////
-////  /// \brief Return list of SketchPlugin constraints attached to this object
-////  virtual const std::list<ConstraintPtr>& constraints() const
-////  { return myConstraints; }
+  /// \brief Return identifier of SolveSpace entity relating to the feature
+  Slvs_hEntity getId(FeaturePtr theFeature) const;
+  /// \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
+  virtual void addFeature(FeaturePtr theFeature);
 
   /// \brief Shows error message
   const std::string& error() const
   { return myErrorMsg; }
 
 protected:
-  /// \brief Converts SketchPlugin constraint to a list of solver's constraints
+  /// \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
+  /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
   /// \param[out] theValue      numerical characteristic of constraint (e.g. distance)
   /// \param[out] theAttributes list of attributes to be filled
-  virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+  virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
 
-////  /// \brief Verify the attributes of constraint are changed (and constraint need to rebuild)
-////  /// \param[in] theConstraint constraint, which attributes should be checked (if NULL, the myBaseConstraint is used)
-////  /// \return \c true if some attributes are changed
-////  virtual bool checkAttributesChanged(ConstraintPtr theConstraint);
+  /// \brief Verify the attributes of constraint are changed (and constraint need to rebuild)
+  /// \param[in] theConstraint constraint, which attributes should be checked (if NULL, the myBaseConstraint is used)
+  /// \return \c true if some attributes are changed
+  virtual bool checkAttributesChanged(ConstraintPtr theConstraint);
 
   /// \brief This method is used in derived objects to check consistency 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
+  /// \return identifier of created/updated entity
+  Slvs_hEntity changeEntity(AttributeRefAttrPtr theAttribute, int& theType);
+  /// \brief Create or change SlveSpace entity according to the given attribute
+  Slvs_hEntity changeEntity(AttributePtr theAttribute, int& theType);
+  /// \brief Create or change SlveSpace entity according to the given feature
+  Slvs_hEntity changeEntity(FeaturePtr theFeature, int& theType);
+
+  /// \brief Calculate middle point on the specified entity
+  /// \param[in]  theEntity  arc or line
+  /// \param[in]  theCoeff   is a value in [0.0, 1.0] which shows the position of the point on the entity (0.0 - start point, 1.0 - end point)
+  /// \param[out] theX       X coordinate of middle point
+  /// \param[out] theY       Y coordinate of middle point
+  void calculateMiddlePoint(const Slvs_Entity& theEntity, double theCoeff,
+                            double& theX, double& theY) const;
+
+  /// \brief Removes the links to unused entities
+  void cleanRemovedEntities();
+
   /// \brief Removes last error
   void cleanErrorMsg()
   { myErrorMsg.clear(); }
 
-protected:
-  GroupID       myGroupID;  ///< identifier of the group, the constraint belongs to
-  EntityID      mySketchID; ///< identifier of the sketch, the constraint belongs to
-  ConstraintPtr myBaseConstraint; ///< base SketchPlugin constraint
-  StoragePtr    myStorage; ///< storage, which contains all information about entities and constraints
-  SketchSolver_ConstraintType myType; ///< type of constraint
+private:
+  /// \brief Sets error, if the attribute is not initialized
+  bool isInitialized(AttributePtr theAttribute);
 
-  std::string   myErrorMsg; ///< error message
+protected:
+  SketchSolver_Group* myGroup; ///< the group which contains current constraint
+  ConstraintPtr myBaseConstraint; ///< SketchPlugin constraint
+  std::vector<Slvs_hConstraint> mySlvsConstraints; ///< list of indices of SolveSpace constraints, together which equivalent to SketchPlugin constraint
+  std::map<FeaturePtr, Slvs_hEntity> myFeatureMap; ///< map feature to the entity it represents
+  std::map<AttributePtr, Slvs_hEntity> myAttributeMap; ///< map attribute to the corresponding entity
+  std::map<AttributePtr, Slvs_hParam> myValueMap; ///< list of attributes, which represents single value (e.g. distance) used in constraint
+  StoragePtr myStorage; ///< storage, which contains all information about entities and constraints in current group
+
+  std::string myErrorMsg; ///< error message
 };
 
 typedef std::shared_ptr<SketchSolver_Constraint> SolverConstraintPtr;
 
 
 
-/////** \class   SketchSolver_ConstraintParallel
-//// *  \ingroup Plugins
-//// *  \brief   Convert Parallel constraint to SolveSpace structure
-//// */
-////class SketchSolver_ConstraintParallel : public SketchSolver_Constraint
-////{
-////public:
-////  /// Constructor based on SketchPlugin constraint
-////  SketchSolver_ConstraintParallel(ConstraintPtr theConstraint) :
-////      SketchSolver_Constraint(theConstraint)
-////  {}
-////
-////  virtual int getType() const
-////  { return SLVS_C_PARALLEL; }
-////};
-////
-////
-/////** \class   SketchSolver_ConstraintPerpendicular
-//// *  \ingroup Plugins
-//// *  \brief   Convert Perpendicular constraint to SolveSpace structure
-//// */
-////class SketchSolver_ConstraintPerpendicular : public SketchSolver_Constraint
-////{
-////public:
-////  /// Constructor based on SketchPlugin constraint
-////  SketchSolver_ConstraintPerpendicular(ConstraintPtr theConstraint) :
-////      SketchSolver_Constraint(theConstraint)
-////  {}
-////
-////  virtual int getType() const
-////  { return SLVS_C_PERPENDICULAR; }
-////};
-////
-////
-/////** \class   SketchSolver_ConstraintHorizontal
-//// *  \ingroup Plugins
-//// *  \brief   Convert Horizontal constraint to SolveSpace structure
-//// */
-////class SketchSolver_ConstraintHorizontal : public SketchSolver_Constraint
-////{
-////public:
-////  /// Constructor based on SketchPlugin constraint
-////  SketchSolver_ConstraintHorizontal(ConstraintPtr theConstraint) :
-////      SketchSolver_Constraint(theConstraint)
-////  {}
-////
-////  virtual int getType() const
-////  { return SLVS_C_HORIZONTAL; }
-////};
-////
-////
-/////** \class   SketchSolver_ConstraintVertical
-//// *  \ingroup Plugins
-//// *  \brief   Convert Vertical constraint to SolveSpace structure
-//// */
-////class SketchSolver_ConstraintVertical : public SketchSolver_Constraint
-////{
-////public:
-////  /// Constructor based on SketchPlugin constraint
-////  SketchSolver_ConstraintVertical(ConstraintPtr theConstraint) :
-////      SketchSolver_Constraint(theConstraint)
-////  {}
-////
-////  virtual int getType() const
-////  { return SLVS_C_VERTICAL; }
-////};
-////
-////
-/////** \class   SketchSolver_ConstraintRadius
-//// *  \ingroup Plugins
-//// *  \brief   Convert Radius constraint to SolveSpace structure
-//// */
-////class SketchSolver_ConstraintRadius : public SketchSolver_Constraint
-////{
-////public:
-////  /// Constructor based on SketchPlugin constraint
-////  SketchSolver_ConstraintRadius(ConstraintPtr theConstraint) :
-////      SketchSolver_Constraint(theConstraint)
-////  {}
-////
-////  virtual int getType() const
-////  { return SLVS_C_DIAMETER; }
-////
-////  virtual void adjustConstraint()
-////  {
-////    AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
-////        myBaseConstraint->attribute(SketchPlugin_Constraint::VALUE()));
-////    Slvs_Constraint aConstraint = myStorage->getConstraint(mySlvsConstraints.front());
-////    aConstraint.valA = 2.0 * aValueAttr->value();
-////    myStorage->updateConstraint(aConstraint);
-////  }
-////};
+/** \class   SketchSolver_ConstraintParallel
+ *  \ingroup Plugins
+ *  \brief   Convert Parallel constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintParallel : public SketchSolver_Constraint
+{
+public:
+  /// Constructor based on SketchPlugin constraint
+  SketchSolver_ConstraintParallel(ConstraintPtr theConstraint) :
+      SketchSolver_Constraint(theConstraint)
+  {}
+
+  virtual int getType() const
+  { return SLVS_C_PARALLEL; }
+};
+
+
+/** \class   SketchSolver_ConstraintPerpendicular
+ *  \ingroup Plugins
+ *  \brief   Convert Perpendicular constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintPerpendicular : public SketchSolver_Constraint
+{
+public:
+  /// Constructor based on SketchPlugin constraint
+  SketchSolver_ConstraintPerpendicular(ConstraintPtr theConstraint) :
+      SketchSolver_Constraint(theConstraint)
+  {}
+
+  virtual int getType() const
+  { return SLVS_C_PERPENDICULAR; }
+};
+
+
+/** \class   SketchSolver_ConstraintHorizontal
+ *  \ingroup Plugins
+ *  \brief   Convert Horizontal constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintHorizontal : public SketchSolver_Constraint
+{
+public:
+  /// Constructor based on SketchPlugin constraint
+  SketchSolver_ConstraintHorizontal(ConstraintPtr theConstraint) :
+      SketchSolver_Constraint(theConstraint)
+  {}
+
+  virtual int getType() const
+  { return SLVS_C_HORIZONTAL; }
+};
+
+
+/** \class   SketchSolver_ConstraintVertical
+ *  \ingroup Plugins
+ *  \brief   Convert Vertical constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintVertical : public SketchSolver_Constraint
+{
+public:
+  /// Constructor based on SketchPlugin constraint
+  SketchSolver_ConstraintVertical(ConstraintPtr theConstraint) :
+      SketchSolver_Constraint(theConstraint)
+  {}
+
+  virtual int getType() const
+  { return SLVS_C_VERTICAL; }
+};
+
+
+/** \class   SketchSolver_ConstraintRadius
+ *  \ingroup Plugins
+ *  \brief   Convert Radius constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintRadius : public SketchSolver_Constraint
+{
+public:
+  /// Constructor based on SketchPlugin constraint
+  SketchSolver_ConstraintRadius(ConstraintPtr theConstraint) :
+      SketchSolver_Constraint(theConstraint)
+  {}
+
+  virtual int getType() const
+  { return SLVS_C_DIAMETER; }
+
+  virtual void adjustConstraint()
+  {
+    AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+        myBaseConstraint->attribute(SketchPlugin_Constraint::VALUE()));
+    Slvs_Constraint aConstraint = myStorage->getConstraint(mySlvsConstraints.front());
+    aConstraint.valA = 2.0 * aValueAttr->value();
+    myStorage->updateConstraint(aConstraint);
+  }
+};
 
 #endif
index 903805060ad0e07df8fedd03075b271feee415a0..10dbae16549bc0ab16c9024acee89c9c0b085199 100644 (file)
@@ -1,5 +1,4 @@
 #include <SketchSolver_ConstraintAngle.h>
-#include <SketchSolver_Manager.h>
 
 #include <GeomAPI_Dir2d.h>
 #include <GeomAPI_Lin2d.h>
@@ -9,7 +8,7 @@
 #include <cmath>
 
 void SketchSolver_ConstraintAngle::getAttributes(
-    double& theValue, std::vector<EntityWrapperPtr>& theAttributes)
+    double& theValue, std::vector<Slvs_hEntity>& theAttributes)
 {
   SketchSolver_Constraint::getAttributes(theValue, theAttributes);
 
@@ -20,31 +19,25 @@ void SketchSolver_ConstraintAngle::getAttributes(
 void SketchSolver_ConstraintAngle::adjustConstraint()
 {
   static const double aTol = 1000. * tolerance;
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
-  ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
-  if (fabs(myAngle - aConstraint->value()) < aTol)
-    return;
-  myAngle = aConstraint->value();
-
-////  Slvs_Constraint aConstraint = myStorage->getConstraint(mySlvsConstraints.front());
+  Slvs_Constraint aConstraint = myStorage->getConstraint(mySlvsConstraints.front());
 
   bool isFixed[2][2];
   std::shared_ptr<GeomAPI_Pnt2d> aPoints[2][2]; // start and end points of lines
-  const std::list<EntityWrapperPtr>& aConstrLines = aConstraint->entities();
-  std::list<EntityWrapperPtr>::const_iterator aCLIt = aConstrLines.begin();
-  for (int i = 0; aCLIt != aConstrLines.end(); ++i, ++aCLIt) {
-    const std::list<EntityWrapperPtr>& aLinePoints = (*aCLIt)->subEntities();
-    std::list<EntityWrapperPtr>::const_iterator aLPIt = aLinePoints.begin();
-    for (int j = 0; aLPIt != aLinePoints.end(); ++j, ++aLPIt) {
-      isFixed[i][j] = ((*aLPIt)->group() != myGroupID);
-      aPoints[i][j] = aBuilder->point(*aLPIt);
+  Slvs_hConstraint aFixedConstraint;
+  Slvs_hEntity anEnt[2] = {aConstraint.entityA, aConstraint.entityB};
+  for (int i = 0; i < 2; i++) {
+    const Slvs_Entity& aLine = myStorage->getEntity(anEnt[i]);
+    double aCoef = -1.0;
+    for (int j = 0; j < 2; j++, aCoef += 2.0) {
+      const Slvs_Entity& aPoint = myStorage->getEntity(aLine.point[j]);
+      double aCoords[2];
+      for (int k = 0; k < 2; k++)
+        aCoords[k] = myStorage->getParameter(aPoint.param[k]).val;
+      isFixed[i][j] = myStorage->isPointFixed(aPoint.h, aFixedConstraint, true);
+      aPoints[i][j] = std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aCoords[0], aCoords[1]));
     }
   }
 
-  if (isFixed[0][0] && isFixed[0][1] && isFixed[1][0] && isFixed[1][1])
-    return; // both lines are fixed => no need to update them
-
   std::shared_ptr<GeomAPI_Lin2d> aLine[2] = {
     std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[0][0], aPoints[0][1])),
     std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[1][0], aPoints[1][1]))
@@ -82,17 +75,20 @@ void SketchSolver_ConstraintAngle::adjustConstraint()
       }
     }
 
-////  aConstraint.other = false;
-////  for (int i = 0; i < 2; i++)
-////    if (aLine[i]->direction()->dot(aDir[i]) < 0.0)
-////      aConstraint.other = !aConstraint.other;
-////  myStorage->updateConstraint(aConstraint);
-////
-////  bool isChanged = fabs(myAngle - aConstraint.valA) > aTol;
-////  // myAngle should be updated even if the angle of constraint is changed too little
-////  myAngle = aConstraint.valA;
-////  if (!isChanged)
-////    return; // the angle was not changed, no need to recalculate positions of lines
+  aConstraint.other = false;
+  for (int i = 0; i < 2; i++)
+    if (aLine[i]->direction()->dot(aDir[i]) < 0.0)
+      aConstraint.other = !aConstraint.other;
+  myStorage->updateConstraint(aConstraint);
+
+  bool isChanged = fabs(myAngle - aConstraint.valA) > aTol;
+  // myAngle should be updated even if the angle of constraint is changed too little
+  myAngle = aConstraint.valA;
+  if (!isChanged)
+    return; // the angle was not changed, no need to recalculate positions of lines
+
+  if (isFixed[0][0] && isFixed[0][1] && isFixed[1][0] && isFixed[1][1])
+    return; // both lines are fixed => no need to update them
 
   // Recalculate positions of lines to avoid conflicting constraints
   // while changing angle value several times
@@ -128,18 +124,15 @@ void SketchSolver_ConstraintAngle::adjustConstraint()
   }
 
   // Update positions of points
-  std::list<EntityWrapperPtr>::const_iterator anUpdLine = aConstrLines.begin();
-  if (aLineToUpd > 0) ++anUpdLine;
-  const std::list<EntityWrapperPtr>& anUpdPoints = (*anUpdLine)->subEntities();
-  std::list<EntityWrapperPtr>::const_iterator aPIt = anUpdPoints.begin();
-  for (int i = 0; aPIt != anUpdPoints.end(); ++aPIt, ++i) {
-    double aCoord[2] = {aNewPoints[i]->x(), aNewPoints[i]->y()};
-    const std::list<ParameterWrapperPtr>& aParams = (*aPIt)->parameters();
-    std::list<ParameterWrapperPtr>::const_iterator aParIt = aParams.begin();
-    for (int j = 0; aParIt != aParams.end(); ++j, ++aParIt)
-      (*aParIt)->setValue(aCoord[j]);
+  const Slvs_Entity& anUpdLine = myStorage->getEntity(anEnt[aLineToUpd]);
+  Slvs_Param aParam;
+  for (int i = 0; i < 2; i++) {
+    const Slvs_Entity& aPoint = myStorage->getEntity(anUpdLine.point[i]);
+    aParam = myStorage->getParameter(aPoint.param[0]);
+    aParam.val = aNewPoints[i]->x();
+    myStorage->updateParameter(aParam);
+    aParam = myStorage->getParameter(aPoint.param[1]);
+    aParam.val = aNewPoints[i]->y();
+    myStorage->updateParameter(aParam);
   }
-
-  aBuilder->adjustConstraint(aConstraint);
-  myStorage->addConstraint(myBaseConstraint, aConstraint);
 }
index 3e979aa6d0b05d2f2b60e700709e7660f9f66b62..4d91aced435e949b13f2f0a1c76ccd82c70e6eeb 100644 (file)
@@ -22,14 +22,17 @@ public:
       myAngle(0.0)
   {}
 
+  virtual int getType() const
+  { return SLVS_C_ANGLE; }
+
   /// \brief This method is used in derived objects to check consistence of constraint.
   virtual void adjustConstraint();
 
 protected:
-  /// \brief Generate list of attributes of constraint in order useful for constraints
+  /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
   /// \param[out] theValue      numerical characteristic of constraint (e.g. distance)
   /// \param[out] theAttributes list of attributes to be filled
-  virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+  virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
 
 private:
   double myAngle;
index d2bd86a991dbfc90e992955101d9b5284e30546d..e1242606ea82f1f6c216f3f46da63f628175c105 100644 (file)
@@ -1,36 +1,41 @@
 #include <SketchSolver_ConstraintCoincidence.h>
 #include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
+#include <SketchSolver_Group.h>
 
-////#include <SketchPlugin_Point.h>
-////#include <GeomDataAPI_Point2D.h>
-////
-////#include <map>
+#include <SketchPlugin_Point.h>
+#include <GeomDataAPI_Point2D.h>
+
+#include <map>
 
 void SketchSolver_ConstraintCoincidence::getAttributes(
     double& theValue,
-    std::vector<EntityWrapperPtr>& theAttributes)
+    std::vector<Slvs_hEntity>& theAttributes)
 {
   SketchSolver_Constraint::getAttributes(theValue, theAttributes);
-  if (!myErrorMsg.empty() || !theAttributes[0]) {
-    theAttributes.clear();
+  if (!myErrorMsg.empty() || theAttributes[0] == SLVS_E_UNKNOWN)
     return;
-  }
 
-  if (theAttributes[1]) {
-    myType = CONSTRAINT_PT_PT_COINCIDENT;
-    // Set the slave (second) point the same as master (first) point.
-    // This will allow to skip adding point-point coincidence to the set of constraints
-    // and give us speed-up in solving the set of equations
-    myStorage->addCoincidentPoints(theAttributes[0], theAttributes[1]);
+  if (theAttributes[1] != SLVS_E_UNKNOWN) {
+    myType = SLVS_C_POINTS_COINCIDENT;
+
+    // set coordinates of slave (second) point equal to the master (first) point
+    Slvs_Entity aFirst  = myStorage->getEntity(theAttributes[0]);
+    Slvs_Entity aSecond = myStorage->getEntity(theAttributes[1]);
+    for (int i = 0; i < 4; i++)
+      if (aFirst.param[i] != SLVS_E_UNKNOWN && aSecond.param[i] != SLVS_E_UNKNOWN) {
+        Slvs_Param aPar1 = myStorage->getParameter(aFirst.param[i]);
+        Slvs_Param aPar2 = myStorage->getParameter(aSecond.param[i]);
+        aPar2.val = aPar1.val;
+        myStorage->updateParameter(aPar2);
+      }
   }
-  else if (theAttributes[2]) {
+  else if (theAttributes[2] != SLVS_E_UNKNOWN) {
     // check the type of entity (line or circle)
-    SketchSolver_EntityType anEntType = theAttributes[2]->type();
-    if (anEntType == ENTITY_LINE)
-      myType = CONSTRAINT_PT_ON_LINE;
-    else if (anEntType == ENTITY_CIRCLE || anEntType == ENTITY_ARC)
-      myType = CONSTRAINT_PT_ON_CIRCLE;
+    Slvs_Entity anEnt = myStorage->getEntity(theAttributes[2]);
+    if (anEnt.type == SLVS_E_LINE_SEGMENT)
+      myType = SLVS_C_PT_ON_LINE;
+    else if (anEnt.type == SLVS_E_CIRCLE || anEnt.type == SLVS_E_ARC_OF_CIRCLE)
+      myType = SLVS_C_PT_ON_CIRCLE;
     else
       myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
   } else
@@ -38,364 +43,339 @@ void SketchSolver_ConstraintCoincidence::getAttributes(
 }
 
 
-static bool isBase(const std::list<ConstraintWrapperPtr>& theConstraints, AttributePtr theAttribute)
+bool SketchSolver_ConstraintCoincidence::hasConstraint(ConstraintPtr theConstraint) const
 {
-  AttributePtr anAttribute = theAttribute;
-  FeaturePtr aFeature;
-  AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
-  if (aRefAttr) {
-    if (aRefAttr->isObject())
-      aFeature = ModelAPI_Feature::feature(aRefAttr->object());
-    else
-      anAttribute = aRefAttr->attr();
+  if (myBaseConstraint == theConstraint)
+    return true;
+  return myExtraCoincidence.find(theConstraint) != myExtraCoincidence.end();
+}
+
+std::list<ConstraintPtr> SketchSolver_ConstraintCoincidence::constraints() const
+{
+  std::list<ConstraintPtr> aConstraints;
+  aConstraints.push_back(myBaseConstraint);
+  std::map<ConstraintPtr, Slvs_hConstraint>::const_iterator anIt = myExtraCoincidence.begin();
+  for (; anIt != myExtraCoincidence.end(); anIt++)
+    aConstraints.push_back(anIt->first);
+  return aConstraints;
+}
+
+bool SketchSolver_ConstraintCoincidence::isCoincide(
+    std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const
+{
+  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;
+}
+
+void SketchSolver_ConstraintCoincidence::attach(
+    std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint)
+{
+  cleanErrorMsg();
+  // Remove constraints from theConstraint
+  std::vector<Slvs_hConstraint>::iterator aCIter = theConstraint->mySlvsConstraints.begin();
+  for (; aCIter != theConstraint->mySlvsConstraints.end(); aCIter++)
+    theConstraint->myStorage->removeConstraint(*aCIter);
+
+  if (myStorage == theConstraint->myStorage) {
+    // Clean removed items
+    std::set<Slvs_hParam> aRemParams;
+    std::set<Slvs_hEntity> aRemEnts;
+    std::set<Slvs_hConstraint> aRemConstr;
+    theConstraint->myStorage->getRemoved(aRemParams, aRemEnts, aRemConstr);
+
+    if (!aRemEnts.empty()) {
+      std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = theConstraint->myFeatureMap.begin();
+      while (aFeatIt != theConstraint->myFeatureMap.end()) {
+        if (aRemEnts.find(aFeatIt->second) != aRemEnts.end()) {
+          // remove feature
+          std::map<FeaturePtr, Slvs_hEntity>::iterator aRemoveIt = aFeatIt++;
+          theConstraint->myFeatureMap.erase(aRemoveIt);
+        } else
+          ++aFeatIt;
+      }
+      std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIt = theConstraint->myAttributeMap.begin();
+      while (anAttrIt != theConstraint->myAttributeMap.end()) {
+        if (aRemEnts.find(anAttrIt->second) != aRemEnts.end()) {
+          // remove attribute
+          std::map<AttributePtr, Slvs_hEntity>::iterator aRemoveIt = anAttrIt++;
+          theConstraint->myAttributeMap.erase(aRemoveIt);
+        } else
+          ++anAttrIt;
+      }
+    }
   }
 
-  std::list<ConstraintWrapperPtr>::const_iterator aCIt = theConstraints.begin();
-  for (; aCIt != theConstraints.end(); ++aCIt) {
-    std::list<EntityWrapperPtr> aSubs = (*aCIt)->entities();
-    std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
-    for (; aSIt != aSubs.end(); ++aSIt)
-      if ((aFeature && (*aSIt)->isBase(aFeature)) ||
-         (!aFeature && (*aSIt)->isBase(anAttribute)))
-        return true;
+  // Copy data.
+  addConstraint(theConstraint->myBaseConstraint);
+  std::map<ConstraintPtr, Slvs_hConstraint>::iterator aConstrIter =
+      theConstraint->myExtraCoincidence.begin();
+  for (; aConstrIter != theConstraint->myExtraCoincidence.end(); aConstrIter++)
+    addConstraint(aConstrIter->first);
+  // Clear the lists to not remove the entities on destruction
+  theConstraint->mySlvsConstraints.clear();
+  theConstraint->myFeatureMap.clear();
+  theConstraint->myAttributeMap.clear();
+}
+
+Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint(
+    Slvs_hEntity thePoint1, Slvs_hEntity thePoint2)
+{
+  if (thePoint1 == thePoint2)
+    return SLVS_E_UNKNOWN;
+
+  bool hasDuplicated = myStorage->hasDuplicatedConstraint();
+  Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+      SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), 0.0, thePoint1, thePoint2, 
+      SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+  Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
+  if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) {
+    // the duplicated constraint appears
+    myStorage->removeConstraint(aNewID);
+    return SLVS_E_UNKNOWN;
+  }
+  mySlvsConstraints.push_back(aNewID);
+  return aNewID;
+}
+
+Slvs_hConstraint SketchSolver_ConstraintCoincidence::addPointOnEntity(
+    Slvs_hEntity thePoint, Slvs_hEntity theEntity)
+{
+  // Check the point is not coincident with boundaries of the entity
+  Slvs_Entity anEnt = myStorage->getEntity(theEntity);
+  int aPos = anEnt.type == SLVS_E_LINE_SEGMENT ? 0 : 1;
+  for (; anEnt.point[aPos] != SLVS_E_UNKNOWN; aPos++)
+    if (anEnt.point[aPos] == thePoint ||
+        myStorage->isCoincident(anEnt.point[aPos], thePoint))
+      return SLVS_E_UNKNOWN;
+
+  bool hasDuplicated = myStorage->hasDuplicatedConstraint();
+  Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
+  Slvs_hConstraint aType = anEnt.type == SLVS_E_LINE_SEGMENT ?
+      SLVS_C_PT_ON_LINE : SLVS_C_PT_ON_CIRCLE;
+  Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+      aType, myGroup->getWorkplaneId(), 0.0, aBaseCoincidence.ptA, SLVS_E_UNKNOWN,
+      theEntity, SLVS_E_UNKNOWN);
+  Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
+  if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) {
+    // the duplicated constraint appears
+    myStorage->removeConstraint(aNewID);
+    return SLVS_E_UNKNOWN;
+  }
+  mySlvsConstraints.push_back(aNewID);
+  return aNewID;
+}
+
+void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstraint)
+{
+  if (mySlvsConstraints.empty()) {
+    // This constraint is empty, rebuild it from scratch
+    myBaseConstraint = theConstraint;
+    process();
+    return;
+  }
+
+  std::list<AttributePtr> anAttrList =
+      theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
+  std::list<AttributePtr>::iterator anIter = anAttrList.begin();
+  std::vector<Slvs_hEntity> aPoints;
+  Slvs_hEntity anEntity = SLVS_E_UNKNOWN;
+  int anEntType;
+  for (; anIter != anAttrList.end(); anIter++) {
+    Slvs_hEntity aPointID = SLVS_E_UNKNOWN;
+    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+    if (!aRefAttr)
+      continue;
+
+    AttributePtr aPointAttr;
+    if (aRefAttr->isObject()) {
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+      std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFeatFound = 
+          myFeatureMap.find(aFeature);
+      if (aFeatFound != myFeatureMap.end())
+        anEntity = aFeatFound->second;
+      else {
+        anEntity = myGroup->getFeatureId(aFeature);
+        if (anEntity == SLVS_E_UNKNOWN)
+          anEntity = changeEntity(aFeature, anEntType);
+        else {
+          myFeatureMap[aFeature] = anEntity;
+          // Obtain relations between attributes of the feature and SolveSpace entities
+          std::list<AttributePtr> anAttrList =
+              aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+          std::list<AttributePtr>::iterator anIt = anAttrList.begin();
+          for (; anIt != anAttrList.end(); ++anIt) {
+            Slvs_hEntity anAttrID = myGroup->getAttributeId(*anIt);
+            if (anAttrID != SLVS_E_UNKNOWN)
+              myAttributeMap[*anIt] = anAttrID;
+          }
+        }
+      }
+      // If the feature is a point, add it to the list of coincident points
+      if (aFeature->getKind() == SketchPlugin_Point::ID()) {
+        aPointID = anEntity;
+        anEntity = SLVS_E_UNKNOWN;
+        aPointAttr = aFeature->attribute(SketchPlugin_Point::COORD_ID());
+      }
+    } else {
+      aPointAttr = aRefAttr->attr();
+      std::map<AttributePtr, Slvs_hEntity>::const_iterator anAttrFound =
+          myAttributeMap.find(aPointAttr);
+      if (anAttrFound != myAttributeMap.end())
+        aPointID = anAttrFound->second;
+      else {
+        aPointID = myGroup->getAttributeId(aPointAttr);
+        if (aPointID == SLVS_E_UNKNOWN)
+          aPointID = changeEntity(aPointAttr, anEntType);
+      }
+    }
+
+    if (aPointAttr) { // the point is found
+      aPoints.push_back(aPointID);
+      myCoincidentPoints.insert(aPointAttr);
+      myAttributeMap[aPointAttr] = aPointID;
+    }
+  }
+
+  Slvs_hConstraint aNewConstr = SLVS_E_UNKNOWN;
+  if (anEntity != SLVS_E_UNKNOWN)
+    aNewConstr = addPointOnEntity(aPoints.front(), anEntity);
+  else { // coincidence between two points
+    Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
+    std::vector<Slvs_hEntity>::const_iterator aPtIter = aPoints.begin();
+    for (; aPtIter != aPoints.end(); aPtIter++) {
+      Slvs_hConstraint aC = addConstraint(aBaseCoincidence.ptA, *aPtIter);
+      if (aC != SLVS_E_UNKNOWN)
+        aNewConstr = aC;
+    }
+  }
+  myExtraCoincidence[theConstraint] = aNewConstr;
+}
+
+void SketchSolver_ConstraintCoincidence::process()
+{
+  SketchSolver_Constraint::process();
+
+  // Fill the list of coincident points
+  std::list<AttributePtr> anAttrList =
+      myBaseConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
+  std::list<AttributePtr>::iterator anIt = anAttrList.begin();
+  for (; anIt != anAttrList.end(); anIt++) {
+    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIt);
+    if (!aRefAttr || aRefAttr->isObject())
+      continue;
+    myCoincidentPoints.insert(aRefAttr->attr());
   }
-  return false;
 }
 
-////bool SketchSolver_ConstraintCoincidence::isCoincide(
-////    std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const
-////{
-////  std::list<ConstraintPtr>::const_iterator anOtherCIt = theConstraint->myConstraints.begin();
-////  for (; anOtherCIt != theConstraint->myConstraints.end(); ++anOtherCIt) {
-////    std::list<ConstraintPtr>::const_iterator aCIt = myConstraints.begin();
-////    for (; aCIt != myConstraints.end(); ++aCIt) {
-////      std::list<ConstraintWrapperPtr> aWrappers = myStorage->constraint(*aCIt);
-////      if (isBase(aWrappers, (*anOtherCIt)->attribute(SketchPlugin_Constraint::ENTITY_A())) ||
-////         (isBase(aWrappers, (*anOtherCIt)->attribute(SketchPlugin_Constraint::ENTITY_B()))))
-////        return true;
-////    }
-////  }
-////  return false;
-////}
-////
-////void SketchSolver_ConstraintCoincidence::attach(
-////    std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint)
-////{
-////  cleanErrorMsg();
-////  ConstraintWrapperPtr aFirstConstraint = myStorage->constraint(myConstraints.front()).front();
-////  EntityWrapperPtr aMasterPoint = aFirstConstraint->entities().front();
-////
-////  // Set points from theConstraint equal to master point
-////  const std::list<ConstraintPtr>& anOtherConstraints = theConstraint->myConstraints;
-////  std::list<ConstraintPtr>::const_iterator anOtherCIt = anOtherConstraints.begin();
-////  bool isFirstUpd = false;
-////  for (; anOtherCIt != anOtherConstraints.end(); ++anOtherCIt) {
-////    std::list<ConstraintWrapperPtr> aSolverConstraints = myStorage->constraint(*anOtherCIt);
-////    std::list<ConstraintWrapperPtr>::iterator aSCIt = aSolverConstraints.begin();
-////    // First point in each constraint is the same (master point of theConstraint),
-////    // it should be updated only once.
-////    if (!isFirstUpd) {
-////      EntityWrapperPtr anOtherMasterPoint = (*aSCIt)->entities().front();
-////      myStorage->addCoincidentPoints(aMasterPoint, anOtherMasterPoint);
-////      isFirstUpd = true;
-////    }
-////    // Update all slave points
-////    for (; aSCIt != aSolverConstraints.end(); ++aSCIt) {
-////      std::list<EntityWrapperPtr> aSubs = (*aSCIt)->entities();
-////      std::list<EntityWrapperPtr>::iterator aSubIt = aSubs.begin();
-////      for (++aSubIt; aSubIt != aSubs.end(); ++aSubIt)
-////        myStorage->addCoincidentPoints(aMasterPoint, *aSubIt);
-////    }
-////    // add constraint to myConstraints
-////    myConstraints.push_back(*anOtherCIt);
-////  }
-////
-////  // Remove constraints from theConstraint
-////  std::vector<Slvs_hConstraint>::iterator aCIter = theConstraint->mySlvsConstraints.begin();
-////  for (; aCIter != theConstraint->mySlvsConstraints.end(); aCIter++)
-////    theConstraint->myStorage->removeConstraint(*aCIter);
-////
-////  if (myStorage == theConstraint->myStorage) {
-////    // Clean removed items
-////    std::set<Slvs_hParam> aRemParams;
-////    std::set<Slvs_hEntity> aRemEnts;
-////    std::set<Slvs_hConstraint> aRemConstr;
-////    theConstraint->myStorage->getRemoved(aRemParams, aRemEnts, aRemConstr);
-////
-////    if (!aRemEnts.empty()) {
-////      std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = theConstraint->myFeatureMap.begin();
-////      while (aFeatIt != theConstraint->myFeatureMap.end()) {
-////        if (aRemEnts.find(aFeatIt->second) != aRemEnts.end()) {
-////          // remove feature
-////          std::map<FeaturePtr, Slvs_hEntity>::iterator aRemoveIt = aFeatIt++;
-////          theConstraint->myFeatureMap.erase(aRemoveIt);
-////        } else
-////          ++aFeatIt;
-////      }
-////      std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIt = theConstraint->myAttributeMap.begin();
-////      while (anAttrIt != theConstraint->myAttributeMap.end()) {
-////        if (aRemEnts.find(anAttrIt->second) != aRemEnts.end()) {
-////          // remove attribute
-////          std::map<AttributePtr, Slvs_hEntity>::iterator aRemoveIt = anAttrIt++;
-////          theConstraint->myAttributeMap.erase(aRemoveIt);
-////        } else
-////          ++anAttrIt;
-////      }
-////    }
-////  }
-////
-////  // Copy data.
-////  addConstraint(theConstraint->myBaseConstraint);
-////  std::map<ConstraintPtr, Slvs_hConstraint>::iterator aConstrIter =
-////      theConstraint->myExtraCoincidence.begin();
-////  for (; aConstrIter != theConstraint->myExtraCoincidence.end(); aConstrIter++)
-////    addConstraint(aConstrIter->first);
-////  // Clear the lists to not remove the entities on destruction
-////  theConstraint->mySlvsConstraints.clear();
-////  theConstraint->myFeatureMap.clear();
-////  theConstraint->myAttributeMap.clear();
-////}
+bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
+{
+  cleanErrorMsg();
+  if (mySlvsConstraints.empty())
+    return true;
+  ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
+  int aPos = -1; // position of constraint in the list (-1 for base constraint)
+  std::map<ConstraintPtr, Slvs_hConstraint>::iterator anExtraIt;
+  if (aConstraint != myBaseConstraint) {
+    anExtraIt = myExtraCoincidence.find(aConstraint);
+    if (anExtraIt == myExtraCoincidence.end())
+      return false; // there is no constraint, which is specified to remove
+    else {
+      bool isEmpty = anExtraIt->second == SLVS_E_UNKNOWN;
+      if (!isEmpty) {
+        isEmpty = true;
+        for (aPos = 0; aPos < (int)mySlvsConstraints.size(); aPos++)
+          if (mySlvsConstraints[aPos] == anExtraIt->second) {
+            isEmpty = false;
+            break;
+          }
+        aPos -= 1;
+      }
+      myExtraCoincidence.erase(anExtraIt);
+      if (isEmpty)
+        return false;
+    }
+  }
 
-////Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint(
-////    Slvs_hEntity thePoint1, Slvs_hEntity thePoint2)
-////{
-////  if (thePoint1 == thePoint2)
-////    return SLVS_E_UNKNOWN;
-////
-////  bool hasDuplicated = myStorage->hasDuplicatedConstraint();
-////  Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
-////      SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), 0.0, thePoint1, thePoint2, 
-////      SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-////  Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
-////  if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) {
-////    // the duplicated constraint appears
-////    myStorage->removeConstraint(aNewID);
-////    return SLVS_E_UNKNOWN;
-////  }
-////  mySlvsConstraints.push_back(aNewID);
-////  return aNewID;
-////}
-////
-////Slvs_hConstraint SketchSolver_ConstraintCoincidence::addPointOnEntity(
-////    Slvs_hEntity thePoint, Slvs_hEntity theEntity)
-////{
-////  // Check the point is not coincident with boundaries of the entity
-////  Slvs_Entity anEnt = myStorage->getEntity(theEntity);
-////  int aPos = anEnt.type == SLVS_E_LINE_SEGMENT ? 0 : 1;
-////  for (; anEnt.point[aPos] != SLVS_E_UNKNOWN; aPos++)
-////    if (anEnt.point[aPos] == thePoint ||
-////        myStorage->isCoincident(anEnt.point[aPos], thePoint))
-////      return SLVS_E_UNKNOWN;
-////
-////  bool hasDuplicated = myStorage->hasDuplicatedConstraint();
-////  Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
-////  Slvs_hConstraint aType = anEnt.type == SLVS_E_LINE_SEGMENT ?
-////      SLVS_C_PT_ON_LINE : SLVS_C_PT_ON_CIRCLE;
-////  Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
-////      aType, myGroup->getWorkplaneId(), 0.0, aBaseCoincidence.ptA, SLVS_E_UNKNOWN,
-////      theEntity, SLVS_E_UNKNOWN);
-////  Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
-////  if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) {
-////    // the duplicated constraint appears
-////    myStorage->removeConstraint(aNewID);
-////    return SLVS_E_UNKNOWN;
-////  }
-////  mySlvsConstraints.push_back(aNewID);
-////  return aNewID;
-////}
-////
-////void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstraint)
-////{
-////  if (mySlvsConstraints.empty()) {
-////    // This constraint is empty, rebuild it from scratch
-////    myBaseConstraint = theConstraint;
-////    process();
-////    return;
-////  }
-////
-////  std::list<AttributePtr> anAttrList =
-////      theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
-////  std::list<AttributePtr>::iterator anIter = anAttrList.begin();
-////  std::vector<Slvs_hEntity> aPoints;
-////  Slvs_hEntity anEntity = SLVS_E_UNKNOWN;
-////  int anEntType;
-////  for (; anIter != anAttrList.end(); anIter++) {
-////    Slvs_hEntity aPointID = SLVS_E_UNKNOWN;
-////    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
-////    if (!aRefAttr)
-////      continue;
-////
-////    AttributePtr aPointAttr;
-////    if (aRefAttr->isObject()) {
-////      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
-////      std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFeatFound = 
-////          myFeatureMap.find(aFeature);
-////      if (aFeatFound != myFeatureMap.end())
-////        anEntity = aFeatFound->second;
-////      else {
-////        anEntity = myGroup->getFeatureId(aFeature);
-////        if (anEntity == SLVS_E_UNKNOWN)
-////          anEntity = changeEntity(aFeature, anEntType);
-////        else {
-////          myFeatureMap[aFeature] = anEntity;
-////          // Obtain relations between attributes of the feature and SolveSpace entities
-////          std::list<AttributePtr> anAttrList =
-////              aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
-////          std::list<AttributePtr>::iterator anIt = anAttrList.begin();
-////          for (; anIt != anAttrList.end(); ++anIt) {
-////            Slvs_hEntity anAttrID = myGroup->getAttributeId(*anIt);
-////            if (anAttrID != SLVS_E_UNKNOWN)
-////              myAttributeMap[*anIt] = anAttrID;
-////          }
-////        }
-////      }
-////      // If the feature is a point, add it to the list of coincident points
-////      if (aFeature->getKind() == SketchPlugin_Point::ID()) {
-////        aPointID = anEntity;
-////        anEntity = SLVS_E_UNKNOWN;
-////        aPointAttr = aFeature->attribute(SketchPlugin_Point::COORD_ID());
-////      }
-////    } else {
-////      aPointAttr = aRefAttr->attr();
-////      std::map<AttributePtr, Slvs_hEntity>::const_iterator anAttrFound =
-////          myAttributeMap.find(aPointAttr);
-////      if (anAttrFound != myAttributeMap.end())
-////        aPointID = anAttrFound->second;
-////      else {
-////        aPointID = myGroup->getAttributeId(aPointAttr);
-////        if (aPointID == SLVS_E_UNKNOWN)
-////          aPointID = changeEntity(aPointAttr, anEntType);
-////      }
-////    }
-////
-////    if (aPointAttr) { // the point is found
-////      aPoints.push_back(aPointID);
-////      myCoincidentPoints.insert(aPointAttr);
-////      myAttributeMap[aPointAttr] = aPointID;
-////    }
-////  }
-////
-////  Slvs_hConstraint aNewConstr = SLVS_E_UNKNOWN;
-////  if (anEntity != SLVS_E_UNKNOWN)
-////    aNewConstr = addPointOnEntity(aPoints.front(), anEntity);
-////  else { // coincidence between two points
-////    Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
-////    std::vector<Slvs_hEntity>::const_iterator aPtIter = aPoints.begin();
-////    for (; aPtIter != aPoints.end(); aPtIter++) {
-////      Slvs_hConstraint aC = addConstraint(aBaseCoincidence.ptA, *aPtIter);
-////      if (aC != SLVS_E_UNKNOWN)
-////        aNewConstr = aC;
-////    }
-////  }
-////  myExtraCoincidence[theConstraint] = aNewConstr;
-////}
+  bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints[aPos+1]);
+  mySlvsConstraints.erase(mySlvsConstraints.begin() + (1+aPos));
+  if (aPos < 0 && !myExtraCoincidence.empty()) {
+    anExtraIt = myExtraCoincidence.begin();
+    // Remove invalid constraints
+    while (anExtraIt != myExtraCoincidence.end()) {
+      if (!anExtraIt->first->data() || !anExtraIt->first->data()->isValid()) {
+        std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
+        if (aTempIt->first != SLVS_E_UNKNOWN) {
+          myStorage->removeConstraint(aTempIt->second);
+          std::vector<Slvs_hConstraint>::iterator anIt = mySlvsConstraints.begin();
+          for (; anIt != mySlvsConstraints.end(); anIt++)
+            if (*anIt == aTempIt->second) {
+              mySlvsConstraints.erase(anIt);
+              break;
+            }
+        }
+        myExtraCoincidence.erase(aTempIt);
+        continue;
+      }
+      anExtraIt++;
+    }
+    // Find first non-extra conststraint
+    anExtraIt = myExtraCoincidence.begin();
+    while (anExtraIt != myExtraCoincidence.end() && anExtraIt->second == SLVS_E_UNKNOWN)
+      anExtraIt++;
+    if (anExtraIt != myExtraCoincidence.end()) {
+      // Need to specify another base coincidence constraint
+      myBaseConstraint = anExtraIt->first;
+      myExtraCoincidence.erase(anExtraIt);
+      if (mySlvsConstraints.empty()) {
+        std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
+        Slvs_Constraint aBase = myStorage->getConstraint(*aCIter);
+        for (++aCIter; aCIter != mySlvsConstraints.end(); aCIter++) {
+          Slvs_Constraint aConstr = myStorage->getConstraint(*aCIter);
+          aConstr.ptA = aBase.ptA;
+          myStorage->updateConstraint(aConstr);
+        }
+      }
+    }
+  }
+  // Clear removed attributes
+  std::set<Slvs_hParam> aParamRemoved;
+  std::set<Slvs_hEntity> anEntRemoved;
+  std::set<Slvs_hConstraint> aConstrRemoved;
+  myStorage->getRemoved(aParamRemoved, anEntRemoved, aConstrRemoved);
+  std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
+  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;
+    }
+    anAttrIter++;
+  }
 
-////bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
-////{
-////  cleanErrorMsg();
-////  if (mySlvsConstraints.empty())
-////    return true;
-////  ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
-////  int aPos = -1; // position of constraint in the list (-1 for base constraint)
-////  std::map<ConstraintPtr, Slvs_hConstraint>::iterator anExtraIt;
-////  if (aConstraint != myBaseConstraint) {
-////    anExtraIt = myExtraCoincidence.find(aConstraint);
-////    if (anExtraIt == myExtraCoincidence.end())
-////      return false; // there is no constraint, which is specified to remove
-////    else {
-////      bool isEmpty = anExtraIt->second == SLVS_E_UNKNOWN;
-////      if (!isEmpty) {
-////        isEmpty = true;
-////        for (aPos = 0; aPos < (int)mySlvsConstraints.size(); aPos++)
-////          if (mySlvsConstraints[aPos] == anExtraIt->second) {
-////            isEmpty = false;
-////            break;
-////          }
-////        aPos -= 1;
-////      }
-////      myExtraCoincidence.erase(anExtraIt);
-////      if (isEmpty)
-////        return false;
-////    }
-////  }
-////
-////  bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints[aPos+1]);
-////  mySlvsConstraints.erase(mySlvsConstraints.begin() + (1+aPos));
-////  if (aPos < 0 && !myExtraCoincidence.empty()) {
-////    anExtraIt = myExtraCoincidence.begin();
-////    // Remove invalid constraints
-////    while (anExtraIt != myExtraCoincidence.end()) {
-////      if (!anExtraIt->first->data() || !anExtraIt->first->data()->isValid()) {
-////        std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
-////        if (aTempIt->first != SLVS_E_UNKNOWN) {
-////          myStorage->removeConstraint(aTempIt->second);
-////          std::vector<Slvs_hConstraint>::iterator anIt = mySlvsConstraints.begin();
-////          for (; anIt != mySlvsConstraints.end(); anIt++)
-////            if (*anIt == aTempIt->second) {
-////              mySlvsConstraints.erase(anIt);
-////              break;
-////            }
-////        }
-////        myExtraCoincidence.erase(aTempIt);
-////        continue;
-////      }
-////      anExtraIt++;
-////    }
-////    // Find first non-extra conststraint
-////    anExtraIt = myExtraCoincidence.begin();
-////    while (anExtraIt != myExtraCoincidence.end() && anExtraIt->second == SLVS_E_UNKNOWN)
-////      anExtraIt++;
-////    if (anExtraIt != myExtraCoincidence.end()) {
-////      // Need to specify another base coincidence constraint
-////      myBaseConstraint = anExtraIt->first;
-////      myExtraCoincidence.erase(anExtraIt);
-////      if (mySlvsConstraints.empty()) {
-////        std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
-////        Slvs_Constraint aBase = myStorage->getConstraint(*aCIter);
-////        for (++aCIter; aCIter != mySlvsConstraints.end(); aCIter++) {
-////          Slvs_Constraint aConstr = myStorage->getConstraint(*aCIter);
-////          aConstr.ptA = aBase.ptA;
-////          myStorage->updateConstraint(aConstr);
-////        }
-////      }
-////    }
-////  }
-////  // Clear removed attributes
-////  std::set<Slvs_hParam> aParamRemoved;
-////  std::set<Slvs_hEntity> anEntRemoved;
-////  std::set<Slvs_hConstraint> aConstrRemoved;
-////  myStorage->getRemoved(aParamRemoved, anEntRemoved, aConstrRemoved);
-////  std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
-////  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;
-////    }
-////    anAttrIter++;
-////  }
-////
-////  // Go through remaining extra coincidence and try to add or remove them
-////  anExtraIt = myExtraCoincidence.begin();
-////  while (anExtraIt != myExtraCoincidence.end()) {
-////    if (anExtraIt->first == SLVS_E_UNKNOWN) {
-////      if (!anExtraIt->first->data() || !anExtraIt->first->data()->isValid()) {
-////        std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
-////        myExtraCoincidence.erase(aTempIt);
-////        continue;
-////      }
-////      if (mySlvsConstraints.empty()) {
-////        myBaseConstraint = anExtraIt->first;
-////        std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
-////        myExtraCoincidence.erase(aTempIt);
-////        process();
-////        continue;
-////      } else
-////        addConstraint(anExtraIt->first);
-////    }
-////    anExtraIt++;
-////  }
-////  return mySlvsConstraints.empty();
-////}
+  // Go through remaining extra coincidence and try to add or remove them
+  anExtraIt = myExtraCoincidence.begin();
+  while (anExtraIt != myExtraCoincidence.end()) {
+    if (anExtraIt->first == SLVS_E_UNKNOWN) {
+      if (!anExtraIt->first->data() || !anExtraIt->first->data()->isValid()) {
+        std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
+        myExtraCoincidence.erase(aTempIt);
+        continue;
+      }
+      if (mySlvsConstraints.empty()) {
+        myBaseConstraint = anExtraIt->first;
+        std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
+        myExtraCoincidence.erase(aTempIt);
+        process();
+        continue;
+      } else
+        addConstraint(anExtraIt->first);
+    }
+    anExtraIt++;
+  }
+  return mySlvsConstraints.empty();
+}
 
index 5ff02a1b6a2b6b807f9dcc337f1ccd309a0eab45..efb01572d063fa923a1fff61237a4728eb014a65 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "SketchSolver.h"
 #include <SketchSolver_Constraint.h>
+#include <SketchSolver_Storage.h>
 
 /** \class   SketchSolver_ConstraintCoincidence
  *  \ingroup Plugins
@@ -18,54 +19,53 @@ class SketchSolver_ConstraintCoincidence : public SketchSolver_Constraint
 {
 public:
   /// Constructor based on SketchPlugin constraint
-  SKETCHSOLVER_EXPORT SketchSolver_ConstraintCoincidence(ConstraintPtr theConstraint) :
-      SketchSolver_Constraint(theConstraint)
+  SketchSolver_ConstraintCoincidence(ConstraintPtr theConstraint) :
+      SketchSolver_Constraint(theConstraint),
+      myType(SLVS_C_UNKNOWN)
   {}
 
-////  /// \brief Tries to remove constraint
-////  /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
-////  virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
-
-////  /// \brief Checks the constraint is used by current object
-////  virtual bool hasConstraint(ConstraintPtr theConstraint) const;
-////
-////  /// \brief Return list of SketchPlugin constraints attached to this object
-////  virtual std::list<ConstraintPtr> constraints() const;
-////
-////  /// \brief Verifies the two Coincidence constraints are intersects (have shared point)
-////  bool isCoincide(std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const;
-////
-////  /// \brief Append all data of coincidence constraint to the current
-////  void attach(std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint);
+  virtual int getType() const
+  { return myType; }
+
+  /// \brief Tries to remove constraint
+  /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+  virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+
+  /// \brief Checks the constraint is used by current object
+  virtual bool hasConstraint(ConstraintPtr theConstraint) const;
+
+  /// \brief Return list of SketchPlugin constraints attached to this object
+  virtual std::list<ConstraintPtr> constraints() const;
+
+  /// \brief Verifies the two Coincidence constraints are intersects (have shared point)
+  bool isCoincide(std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const;
+
+  /// \brief Append all data of coincidence constaint to the current
+  void attach(std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint);
 
 protected:
-////  /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
-////  virtual void process();
+  /// \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
+  /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
   /// \param[out] theValue      numerical characteristic of constraint (e.g. distance)
   /// \param[out] theAttributes list of attributes to be filled
-  virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
-
-////  /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
-////  /// \param[out] theValue      numerical characteristic of constraint (e.g. distance)
-////  /// \param[out] theAttributes list of attributes to be filled
-////  virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
-////
-////private:
-////  /// \brief Creates new coincidence constraint
-////  Slvs_hConstraint addConstraint(Slvs_hEntity thePoint1, Slvs_hEntity thePoint2);
-////
-////  /// \brief Create full SolveSpace structure according to given constraint
-////  void addConstraint(ConstraintPtr theConstraint);
-////
-////  /// \brief Create constraint of point coincident to the line or circle
-////  Slvs_hConstraint addPointOnEntity(Slvs_hEntity thePoint, Slvs_hEntity theEntity);
-////
-////private:
-////  int myType; ///< type of constraint (applicable SLVS_C_POINTS_COINCIDENT or SLVS_C_PT_ON_LINE or SLVS_C_PT_ON_CIRCLE)
-////  std::map<ConstraintPtr, Slvs_hConstraint> myExtraCoincidence; ///< multiple coincidence of points
-////  std::set<AttributePtr> myCoincidentPoints; ///< list of points under the Coincidence constraint
+  virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
+
+private:
+  /// \brief Creates new coincidence constraint
+  Slvs_hConstraint addConstraint(Slvs_hEntity thePoint1, Slvs_hEntity thePoint2);
+
+  /// \brief Create full SolveSpace structure according to given constraint
+  void addConstraint(ConstraintPtr theConstraint);
+
+  /// \brief Create constraint of point concident to the line or circle
+  Slvs_hConstraint addPointOnEntity(Slvs_hEntity thePoint, Slvs_hEntity theEntity);
+
+private:
+  int myType; ///< type of constraint (applicable SLVS_C_POINTS_COINCIDENT or SLVS_C_PT_ON_LINE or SLVS_C_PT_ON_CIRCLE)
+  std::map<ConstraintPtr, Slvs_hConstraint> myExtraCoincidence; ///< multiple coincidence of points
+  std::set<AttributePtr> myCoincidentPoints; ///< list of points under the Coincidence constraint
 };
 
 #endif
index e82568d3ef089f60cd569a3c5895a3bc565dab25..63bd0ae7ddbd2c3d2f8bffb7a278a8d245cda1bd 100644 (file)
 #include <SketchSolver_ConstraintDistance.h>
+#include <SketchSolver_Group.h>
 #include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
 
-#include <GeomAPI_Dir2d.h>
-#include <GeomAPI_Lin2d.h>
-#include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_XY.h>
 
 #include <math.h>
 
 
-void SketchSolver_ConstraintDistance::getAttributes(
-    double& theValue,
-    std::vector<EntityWrapperPtr>& theAttributes)
+void SketchSolver_ConstraintDistance::process()
 {
-  SketchSolver_Constraint::getAttributes(theValue, theAttributes);
-  if (!myErrorMsg.empty() || !theAttributes[0]) {
-    theAttributes.clear();
+  cleanErrorMsg();
+  if (!myBaseConstraint || !myStorage || myGroup == 0) {
+    /// TODO: Put error message here
     return;
   }
+  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+    update(myBaseConstraint);
 
-  if (theAttributes[1])
-    myType = CONSTRAINT_PT_PT_DISTANCE;
-  else if (theAttributes[2] && theAttributes[2]->type() == ENTITY_LINE)
-    myType = CONSTRAINT_PT_LINE_DISTANCE;
-  else
-    theAttributes.clear();
+  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);
 
   myPrevValue = 0.0;
+  adjustConstraint();
 }
 
 void SketchSolver_ConstraintDistance::adjustConstraint()
 {
   // Adjust point-line distance
-  if (getType() != CONSTRAINT_PT_LINE_DISTANCE)
+  if (getType() != SLVS_C_PT_LINE_DISTANCE)
     return;
 
   // Check the sign of distance is changed
-  ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
-  if (fabs(myPrevValue) == fabs(aConstraint->value())) {
-    aConstraint->setValue(myPrevValue);
-    myStorage->addConstraint(myBaseConstraint, aConstraint);
+  Slvs_Constraint aConstraint = myStorage->getConstraint(mySlvsConstraints.front());
+  if (fabs(myPrevValue) == fabs(aConstraint.valA)) {
+    aConstraint.valA = myPrevValue;
+    myStorage->updateConstraint(aConstraint);
     return;
   }
 
   // Get constraint parameters and check the sign of constraint value
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-  std::shared_ptr<GeomAPI_Pnt2d> aPoint;
-  std::shared_ptr<GeomAPI_Lin2d> aLine;
-  std::list<EntityWrapperPtr> aSubs = aConstraint->entities();
-  std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
-  for (; aSIt != aSubs.end(); ++aSIt) {
-    if ((*aSIt)->type() == ENTITY_POINT)
-      aPoint = aBuilder->point(*aSIt);
-    else if ((*aSIt)->type() == ENTITY_LINE)
-      aLine = aBuilder->line(*aSIt);
-  }
-
-  std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
-  std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
-  if (aPtLineVec->cross(aLineVec) * aConstraint->value() < 0.0 || myIsNegative) {
-    aConstraint->setValue(aConstraint->value() * (-1.0));
-    myStorage->addConstraint(myBaseConstraint, aConstraint);
-    myIsNegative = true;
+  std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
+  for (; aCIter != mySlvsConstraints.end(); aCIter++) {
+    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 || myIsNegative) {
+      aConstraint.valA *= -1.0;
+      myStorage->updateConstraint(aConstraint);
+      myIsNegative = true;
+    }
   }
 }
 
-void SketchSolver_ConstraintDistance::update()
+void SketchSolver_ConstraintDistance::update(ConstraintPtr theConstraint)
 {
-  ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
-  myPrevValue = aConstraint->value();
-
-  SketchSolver_Constraint::update();
+  Slvs_Constraint aConstraint = myStorage->getConstraint(mySlvsConstraints.front());
+  myPrevValue = aConstraint.valA;
+  SketchSolver_Constraint::update(theConstraint);
 }
index b11e0a8a55d730345d30c641502df30ecb52f0f7..5c1569f9a4f160f78b06f7ec81571f359dd36d47 100644 (file)
@@ -20,23 +20,26 @@ public:
   /// Constructor based on SketchPlugin constraint
   SketchSolver_ConstraintDistance(ConstraintPtr theConstraint) :
       SketchSolver_Constraint(theConstraint),
+      myType(SLVS_C_UNKNOWN),
       myIsNegative(false)
   {}
 
   /// \brief Update constraint
-  virtual void update();
+  virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
+
+  virtual int getType() const
+  {return myType; }
 
 protected:
-  /// \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(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+  /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+  virtual void process();
 
   /// \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();
 
 private:
+  int myType; ///< type of constraint (applicable: SLVS_C_PT_PT_DISTANCE, SLVS_C_PT_LINE_DISTANCE)
   double myPrevValue; ///< previous value of distance (for correct calculation of a distance sign)
   bool myIsNegative;  ///< \c true, if the point if placed rightside of line direction (SLVS_C_PT_LINE_DISTANCE only)
 };
index a6120533ecb1a46f21b0a1673071e8aa8b3a4410..e91ca2cf0f2a8d0f25db12649303f8e081ac013e 100644 (file)
@@ -1,54 +1,70 @@
 #include <SketchSolver_ConstraintEqual.h>
+#include <SketchSolver_Group.h>
 #include <SketchSolver_Error.h>
 
-void SketchSolver_ConstraintEqual::getAttributes(
-    double& theValue,
-    std::vector<EntityWrapperPtr>& theAttributes)
+
+void SketchSolver_ConstraintEqual::process()
 {
-  SketchSolver_Constraint::getAttributes(theValue, theAttributes);
-  if (!myErrorMsg.empty() || !theAttributes[2] || !theAttributes[3]) {
-    theAttributes.clear();
+  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 quantity of entities of each type
   int aNbLines = 0;
   int aNbArcs = 0;
   int aNbCircs = 0;
   bool isArcFirst = false; // in line-arc equivalence, the line should be first
-  std::vector<EntityWrapperPtr>::iterator anAttrIt = theAttributes.begin() + 2;
-  for (; anAttrIt != theAttributes.end(); ++anAttrIt) {
-    SketchSolver_EntityType aType = (*anAttrIt)->type();
-    if (aType == ENTITY_LINE)
-      ++aNbLines;
-    else if (aType == ENTITY_CIRCLE)
-      ++aNbCircs;
-    else if (aType == ENTITY_ARC) {
-      ++aNbArcs;
+  std::vector<Slvs_hEntity>::iterator anEntIter = anEntities.begin();
+  for (; anEntIter != anEntities.end(); anEntIter++) {
+    Slvs_Entity anEnt = myStorage->getEntity(*anEntIter);
+    if (anEnt.type == SLVS_E_LINE_SEGMENT)
+      aNbLines++;
+    else if (anEnt.type == SLVS_E_CIRCLE)
+      aNbCircs++;
+    else if (anEnt.type == SLVS_E_ARC_OF_CIRCLE) {
+      aNbArcs++;
       isArcFirst = (aNbLines == 0);
     }
   }
 
   if (aNbLines + aNbArcs + aNbCircs != 2 ||
-     (aNbLines == aNbCircs && aNbArcs == 0)) {
+      (aNbLines == aNbCircs && aNbArcs == 0)) {
     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
     return;
   }
 
   switch (aNbLines) {
   case 0:
-    myType = CONSTRAINT_EQUAL_RADIUS;
+    myType = SLVS_C_EQUAL_RADIUS;
     break;
   case 1:
-    myType = CONSTRAINT_EQUAL_LINE_ARC;
+    myType = SLVS_C_EQUAL_LINE_ARC_LEN;
     if (isArcFirst) { // change the order of arc and line
-      EntityWrapperPtr aTmp = theAttributes[2];
-      theAttributes[2] = theAttributes[3];
-      theAttributes[3] = aTmp;
+      Slvs_hEntity aTmp = anEntities[2];
+      anEntities[2] = anEntities[3];
+      anEntities[3] = aTmp;
     }
     break;
   default:
-    myType = CONSTRAINT_EQUAL_LINES;
+    myType = SLVS_C_EQUAL_LENGTH_LINES;
     break;
   }
+
+  Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+      getType(), myGroup->getWorkplaneId(), aValue,
+      anEntities[0], anEntities[1], anEntities[2], anEntities[3]);
+  aConstraint.h = myStorage->addConstraint(aConstraint);
+  mySlvsConstraints.push_back(aConstraint.h);
+  adjustConstraint();
 }
+
index 12e6a334e973650cc65b7c8c01699c1690d36df3..2aca9c850a265fca96d897296e4fcbdce4a86162 100644 (file)
@@ -22,11 +22,15 @@ public:
       SketchSolver_Constraint(theConstraint)
   {}
 
+  virtual int getType() const
+  { return myType; }
+
 protected:
-  /// \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(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+  /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+  virtual void process();
+
+private:
+  int myType; ///< type of constraint (applicable: SLVS_C_EQUAL_LENGTH_LINES, SLVS_C_EQUAL_RADIUS, SLVS_C_EQUAL_LINE_ARC_LEN)
 };
 
 #endif
diff --git a/src/SketchSolver/SketchSolver_ConstraintFillet.cpp b/src/SketchSolver/SketchSolver_ConstraintFillet.cpp
new file mode 100644 (file)
index 0000000..3d53b90
--- /dev/null
@@ -0,0 +1,208 @@
+#include <SketchSolver_ConstraintFillet.h>
+#include <SketchSolver_Group.h>
+#include <SketchSolver_Error.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_ResultConstruction.h>
+
+
+void SketchSolver_ConstraintFillet::getAttributes(
+    double& theValue, std::vector<Slvs_hEntity>& theAttributes)
+{
+  theAttributes.clear();
+
+  DataPtr aData = myBaseConstraint->data();
+  AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+    aData->attribute(SketchPlugin_Constraint::VALUE()));
+  theValue = aValueAttr ? aValueAttr->value() : 0.0;
+
+  std::list<AttributePtr> aBaseAttrs = aData->attributes(ModelAPI_AttributeRefAttr::typeId());
+  std::list<AttributePtr>::iterator anIter = aBaseAttrs.begin();
+  for (; anIter != aBaseAttrs.end(); anIter++) {
+    AttributeRefAttrPtr aRefAttr =
+        std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+    if (!aRefAttr || !aRefAttr->isInitialized()) {
+      myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+      return;
+    }
+
+    int aType = SLVS_E_UNKNOWN; // type of created entity
+    Slvs_hEntity anEntity = myGroup->getAttributeId(aRefAttr);
+    if (anEntity == SLVS_E_UNKNOWN)
+      anEntity = changeEntity(aRefAttr, aType);
+
+    if (aType == SLVS_E_UNKNOWN)
+      continue;
+    theAttributes.push_back(anEntity);
+  }
+
+  // Fillet objects
+  AttributeRefListPtr aFilletRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+    aData->attribute(SketchPlugin_Constraint::ENTITY_C()));
+  if (!aFilletRefList || !aFilletRefList->isInitialized()) {
+    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+    return;
+  }
+  std::list<ObjectPtr> aFilletList = aFilletRefList->list();
+  if (aFilletList.size() < theAttributes.size() + 1) {
+    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+    return;
+  }
+  FeaturePtr aFilletFeature;
+  ResultConstructionPtr aRC;
+  int aType;
+  std::list<ObjectPtr>::iterator aFilIter = aFilletList.begin();
+  for (int indEnt = 0; aFilIter != aFilletList.end(); aFilIter++, indEnt++) {
+    aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aFilIter);
+    aFilletFeature = aRC ? aRC->document()->feature(aRC) :
+        std::dynamic_pointer_cast<ModelAPI_Feature>(*aFilIter);
+    if (!aFilletFeature) {
+      myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+      return;
+    }
+    Slvs_hEntity anEntity = changeEntity(aFilletFeature, aType);
+    theAttributes.push_back(anEntity);
+  }
+}
+
+void SketchSolver_ConstraintFillet::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> anEntID;
+  getAttributes(aValue, anEntID);
+  if (!myErrorMsg.empty())
+    return;
+
+  // Obtain the entities itself:
+  // First two are base entities
+  // Second two are trimmed them
+  // Last one is a fillet arc
+  std::vector<Slvs_Entity> anEntities;
+  std::vector<Slvs_hEntity>::iterator anIt = anEntID.begin();
+  for (; anIt != anEntID.end(); anIt++)
+    anEntities.push_back(myStorage->getEntity(*anIt));
+
+  // Check the base entities have a coincident point
+  Slvs_hEntity aPointsToFind[4];
+  for (int i = 0; i < 2; i++) {
+    int aShift = anEntities[i].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
+    aPointsToFind[2*i]  = anEntities[i].point[aShift];
+    aPointsToFind[2*i+1]= anEntities[i].point[aShift+1];
+  }
+  // Search coincident points
+  int aCoincInd[2]; // indices of coincident points on each entity (0 - first, 1 - last)
+  bool isPointFound = false;
+  for (int i = 0; i < 2 && !isPointFound; i++)
+    for (int j = 2; j < 4 && !isPointFound; j++)
+      if (myStorage->isEqual(aPointsToFind[i], aPointsToFind[j])) {
+        aCoincInd[0] = i;
+        aCoincInd[1] = j - 2;
+        isPointFound = true;
+      }
+  if (!isPointFound) {
+    // There is no coincident points between tangential objects. Generate error message
+    myErrorMsg = SketchSolver_Error::NO_COINCIDENT_POINTS();
+    return;
+  }
+
+  // For correct result, move floating points of fillet on the middle points of base objects
+  Slvs_Entity aPoint;
+  Slvs_Param aParam;
+  double anArcPoints[3][2];
+  for (int i = 0; i < 2; i++) {
+    calculateMiddlePoint(anEntities[i], 0.1 + 0.8 * aCoincInd[i], anArcPoints[i+1][0], anArcPoints[i+1][1]);
+    aPoint = myStorage->getEntity(anEntities[i+2].point[aCoincInd[i]]);
+    for (int j = 0; j < 2; j++) {
+      aParam = myStorage->getParameter(aPoint.param[j]);
+      aParam.val = anArcPoints[i+1][j];
+      aPoint.param[j] = myStorage->updateParameter(aParam);
+    }
+  }
+  anArcPoints[0][0] = 0.5 * (anArcPoints[1][0] + anArcPoints[2][0]);
+  anArcPoints[0][1] = 0.5 * (anArcPoints[1][1] + anArcPoints[2][1]);
+  // Check the arc is need to be reversed
+  double aSharedPoint[2];
+  aPoint = myStorage->getEntity(aPointsToFind[aCoincInd[0]]);
+  for (int j = 0; j < 2; j++)
+    aSharedPoint[j] = myStorage->getParameter(aPoint.param[j]).val;
+  double aCross = (anArcPoints[1][0] - anArcPoints[0][0]) * (aSharedPoint[1] - anArcPoints[0][1]) -
+                  (anArcPoints[1][1] - anArcPoints[0][1]) * (aSharedPoint[0] - anArcPoints[0][0]);
+  if (aCross < 0.0) { // reverse fillet arc
+    double aTmp;
+    for (int j = 0; j < 2; j++) {
+      aTmp = anArcPoints[1][j];
+      anArcPoints[1][j] = anArcPoints[2][j];
+      anArcPoints[2][j] = aTmp;
+    }
+  }
+  // update fillet arc coordinates
+  for (int indArcPt = 0; indArcPt < 3; indArcPt++) {
+    aPoint = myStorage->getEntity(anEntities.back().point[indArcPt]);
+    for (int j = 0; j < 2; j++) {
+      aParam = myStorage->getParameter(aPoint.param[j]);
+      aParam.val = anArcPoints[indArcPt][j];
+      aPoint.param[j] = myStorage->updateParameter(aParam);
+    }
+  }
+
+  for (int indEnt = 0; indEnt < 2; indEnt++) {
+    int aShift = anEntities[indEnt].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
+    // one point of fillet object should be coincident with the point on base, non-coincident with another base object
+    Slvs_hEntity aBaseID = anEntities[indEnt].point[1 - aCoincInd[indEnt] + aShift];
+    Slvs_hEntity aFilletID = anEntities[2 + indEnt].point[1 - aCoincInd[indEnt] + aShift];
+    Slvs_Constraint aCoincConstr = Slvs_MakeConstraint(
+        SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(),
+        0.0, aBaseID, aFilletID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+    aCoincConstr.h = myStorage->addConstraint(aCoincConstr);
+    mySlvsConstraints.push_back(aCoincConstr.h);
+
+    // another point of fillet object should be placed on the base object
+    Slvs_Constraint aPonCurveConstr;
+    if (anEntities[indEnt].type == SLVS_E_ARC_OF_CIRCLE) {
+      // centers of arcs should be coincident
+      aBaseID = anEntities[indEnt].point[0];
+      aFilletID = anEntities[2 + indEnt].point[0];
+      aPonCurveConstr = Slvs_MakeConstraint(
+          SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(),
+          0.0, aBaseID, aFilletID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+    } else {
+      aFilletID = anEntities[2 + indEnt].point[aCoincInd[indEnt]];
+      aPonCurveConstr = Slvs_MakeConstraint(
+          SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_ON_LINE, myGroup->getWorkplaneId(),
+          0.0, aFilletID, SLVS_E_UNKNOWN, anEntities[indEnt].h, SLVS_E_UNKNOWN);
+    }
+    aPonCurveConstr.h = myStorage->addConstraint(aPonCurveConstr);
+    mySlvsConstraints.push_back(aPonCurveConstr.h);
+  }
+}
+
+bool SketchSolver_ConstraintFillet::remove(ConstraintPtr theConstraint)
+{
+  cleanErrorMsg();
+  if (theConstraint && theConstraint != myBaseConstraint)
+    return false;
+  bool isFullyRemoved = true;
+  std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
+  for (; aCIter != mySlvsConstraints.end(); aCIter++)
+   isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
+  mySlvsConstraints.clear();
+
+  if (isFullyRemoved) {
+    myFeatureMap.clear();
+    myAttributeMap.clear();
+    myValueMap.clear();
+  } else
+    cleanRemovedEntities();
+  return true;
+}
+
diff --git a/src/SketchSolver/SketchSolver_ConstraintFillet.h b/src/SketchSolver/SketchSolver_ConstraintFillet.h
new file mode 100644 (file)
index 0000000..44caaf0
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    SketchSolver_ConstraintFillet.h
+// Created: 1 Apr 2015
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintFillet_H_
+#define SketchSolver_ConstraintFillet_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Constraint.h>
+
+/** \class   SketchSolver_ConstraintFillet
+ *  \ingroup Plugins
+ *  \brief   Convert fillet constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintFillet : public SketchSolver_Constraint
+{
+public:
+  /// Constructor based on SketchPlugin constraint
+  SketchSolver_ConstraintFillet(ConstraintPtr theConstraint) :
+      SketchSolver_Constraint(theConstraint)
+  {}
+
+  virtual int getType() const
+  { return SLVS_C_FILLET; }
+
+  /// \brief Tries to remove constraint
+  /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+  virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+
+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 SolveSpace constraints
+  /// \param[out] theValue      numerical characteristic of constraint (e.g. distance)
+  /// \param[out] theAttributes list of attributes to be filled
+  ///
+  /// Parameter theAttributes contains 5 elements:
+  /// Two first entities in theAttributes list correspond to base features of fillet,
+  /// the next two entities represent trimmed base features and the last one is a fillet arc.
+  virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
+};
+
+#endif
diff --git a/src/SketchSolver/SketchSolver_ConstraintFixed.cpp b/src/SketchSolver/SketchSolver_ConstraintFixed.cpp
deleted file mode 100644 (file)
index 3e7a9f9..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-#include <SketchSolver_ConstraintFixed.h>
-#include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
-
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
-#include <SketchPlugin_ConstraintRigid.h>
-#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Point.h>
-
-#include <GeomAPI_Pnt2d.h>
-#include <GeomAPI_XY.h>
-#include <GeomDataAPI_Point2D.h>
-#include <ModelAPI_AttributeDouble.h>
-
-#include <math.h>
-
-SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(ConstraintPtr theConstraint)
-  : SketchSolver_Constraint()
-{
-  myBaseConstraint = theConstraint;
-  myType = CONSTRAINT_FIXED;
-  myFixedAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-      theConstraint->attribute(SketchPlugin_ConstraintRigid::ENTITY_A()));
-}
-
-SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(FeaturePtr theFeature)
-  : SketchSolver_Constraint(),
-    myBaseFeature(theFeature)
-{
-  myType = CONSTRAINT_FIXED;
-  process();
-}
-
-void SketchSolver_ConstraintFixed::process()
-{
-  cleanErrorMsg();
-  if ((!myBaseConstraint && !myBaseFeature) || !myStorage || myGroupID == GID_UNKNOWN) {
-    // Not enough parameters are assigned
-    return;
-  }
-////  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
-////    update(myBaseConstraint);
-
-  ParameterWrapperPtr aValue;
-  std::vector<EntityWrapperPtr> anEntities;
-  getAttributes(aValue, anEntities);
-  if (!myErrorMsg.empty() || anEntities.empty())
-    return;
-  fixFeature(anEntities.front());
-}
-
-////static void fixEntity(StoragePtr theStorage, const Slvs_hEntity& theEntID)
-////{
-////  Slvs_Entity anEntity = theStorage->getEntity(theEntID);
-////  anEntity.group = SLVS_G_OUTOFGROUP;
-////  theStorage->updateEntity(anEntity);
-////  // move out of group all sub-entities
-////  for (int i = 0; i < 4; ++i)
-////    if (anEntity.point[i] != SLVS_E_UNKNOWN)
-////      fixEntity(theStorage, anEntity.point[i]);
-////  // move out of group the radius of circle
-////  if (anEntity.distance != SLVS_E_UNKNOWN)
-////    fixEntity(theStorage, anEntity.distance);
-////  // move out of group parameters
-////  for (int i = 0; i < 4; ++i)
-////    if (anEntity.param[i] != SLVS_E_UNKNOWN) {
-////      Slvs_Param aParam = theStorage->getParameter(anEntity.param[i]);
-////      aParam.group = SLVS_G_OUTOFGROUP;
-////      theStorage->updateParameter(aParam);
-////    }
-////}
-
-void SketchSolver_ConstraintFixed::fixFeature(EntityWrapperPtr theFeature)
-{
-  // extract feature from the group
-  if (theFeature->baseAttribute())
-    myStorage->update(theFeature->baseAttribute(), GID_OUTOFGROUP);
-  else
-    myStorage->update(theFeature->baseFeature(), GID_OUTOFGROUP);
-}
-
-////Slvs_hEntity SketchSolver_ConstraintFixed::fixedEntity() const
-////{
-////  Slvs_hEntity anEntID = SLVS_E_UNKNOWN;
-////  if (myBaseConstraint) {
-////    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-////        myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
-////    if (aRefAttr->isObject()) {
-////      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
-////      std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFound = myFeatureMap.find(aFeature);
-////      if (aFound != myFeatureMap.end())
-////        anEntID = aFound->second;
-////    } else {
-////      std::map<AttributePtr, Slvs_hEntity>::const_iterator aFound = myAttributeMap.find(aRefAttr->attr());
-////      if (aFound != myAttributeMap.end())
-////        anEntID = aFound->second;
-////    }
-////  }
-////  else if (myBaseFeature) {
-////    std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFound = myFeatureMap.find(myBaseFeature);
-////    if (aFound != myFeatureMap.end())
-////      anEntID = aFound->second;
-////  }
-////  return anEntID;
-////}
-
-void SketchSolver_ConstraintFixed::getAttributes(
-    ParameterWrapperPtr& theValue,
-    std::vector<EntityWrapperPtr>& theAttributes)
-{
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
-  EntityWrapperPtr aSolverEntity;
-  if (myBaseFeature) {
-    // The feature is fixed.
-    myStorage->update(myBaseFeature, myGroupID);
-    aSolverEntity = myStorage->entity(myBaseFeature);
-  } else if (myBaseConstraint) {
-    // Constraint Fixed is added by user.
-    // Get the attribute of constraint (it should be alone in the list of constraints).
-    AttributePtr anAttr = myBaseConstraint->attribute(SketchPlugin_ConstraintRigid::ENTITY_A());
-    AttributeRefAttrPtr aRefAttr =
-        std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
-    if (!aRefAttr || !aRefAttr->isInitialized()) {
-      myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
-      return;
-    }
-
-    myStorage->update(anAttr, myGroupID);
-    aSolverEntity = myStorage->entity(anAttr);
-  } else
-    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
-
-  if (aSolverEntity)
-    theAttributes.push_back(aSolverEntity);
-}
-
-
-bool SketchSolver_ConstraintFixed::remove()
-{
-  cleanErrorMsg();
-  // Move fixed entities back to the current group
-  FeaturePtr aFeature = myBaseFeature;
-  if (myBaseConstraint && myFixedAttribute && myFixedAttribute->isObject())
-    aFeature = ModelAPI_Feature::feature(myFixedAttribute->object());
-  if (aFeature)
-    myStorage->update(aFeature, myGroupID);
-
-  // Remove constraint or base feature
-  if (myBaseConstraint) {
-    bool isRemoved = false;
-    if (aFeature)
-      isRemoved = myStorage->removeEntity(aFeature);
-    return SketchSolver_Constraint::remove() || isRemoved;
-  } else if (myBaseFeature)
-    myStorage->removeEntity(myBaseFeature);
-  return true;
-}
-
-////Slvs_hConstraint SketchSolver_ConstraintFixed::fixPoint(const Slvs_hEntity& thePointID)
-////{
-////  if (thePointID == SLVS_E_UNKNOWN)
-////    return SLVS_C_UNKNOWN;
-////
-////  Slvs_Constraint aConstraint;
-////  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 (isFixed) return aConstrID;
-////    aConstraint = Slvs_MakeConstraint(SLVS_C_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 (!isFixed || aConstrID == SLVS_C_UNKNOWN || myBaseConstraint)
-////      return SLVS_C_UNKNOWN;
-////    aConstraint = myStorage->getConstraint(aConstrID);
-////    aConstraint.ptA = thePointID;
-////    myStorage->addConstraint(aConstraint);
-////    if (!myBaseConstraint)
-////      myStorage->addConstraintWhereDragged(aConstraint.h);
-////  }
-////  return aConstraint.h;
-////}
-////
-////void SketchSolver_ConstraintFixed::fixLine(const Slvs_Entity& theLine)
-////{
-////  Slvs_Constraint anEqual;
-////  if (myStorage->isAxisParallel(theLine.h)) {
-////    // Fix one point and a line length
-////    Slvs_hConstraint aFixed;
-////    if (!myStorage->isPointFixed(theLine.point[0], aFixed, true) &&
-////        !myStorage->isPointFixed(theLine.point[1], aFixed, true))
-////      fixPoint(theLine.point[0]);
-////    if (!myStorage->isUsedInEqual(theLine.h, anEqual)) {
-////      // Check the distance is not set yet
-////      std::list<Slvs_Constraint> aDistConstr = myStorage->getConstraintsByType(SLVS_C_PT_PT_DISTANCE);
-////      std::list<Slvs_Constraint>::const_iterator aDIt = aDistConstr.begin();
-////      for (; aDIt != aDistConstr.end(); aDIt++)
-////        if ((aDIt->ptA == theLine.point[0] && aDIt->ptB == theLine.point[1]) ||
-////            (aDIt->ptA == theLine.point[1] && aDIt->ptB == theLine.point[0]))
-////          return;
-////      // Calculate distance between points on the line
-////      double aCoords[4];
-////      for (int i = 0; i < 2; i++) {
-////        Slvs_Entity aPnt = myStorage->getEntity(theLine.point[i]);
-////        for (int j = 0; j < 2; j++) {
-////          Slvs_Param aParam = myStorage->getParameter(aPnt.param[j]);
-////          aCoords[2*i+j] = aParam.val;
-////        }
-////      }
-////      double aLength = sqrt((aCoords[2] - aCoords[0]) * (aCoords[2] - aCoords[0]) + 
-////                            (aCoords[3] - aCoords[1]) * (aCoords[3] - aCoords[1]));
-////      // fix line length
-////      Slvs_Constraint aDistance = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
-////          SLVS_C_PT_PT_DISTANCE, myGroup->getWorkplaneId(), aLength,
-////          theLine.point[0], theLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-////      aDistance.h = myStorage->addConstraint(aDistance);
-////      mySlvsConstraints.push_back(aDistance.h);
-////    }
-////    return;
-////  }
-////  else if (myStorage->isUsedInEqual(theLine.h, anEqual)) {
-////    // Check another entity of Equal is already fixed
-////    Slvs_hEntity anOtherEntID = anEqual.entityA == theLine.h ? anEqual.entityB : anEqual.entityA;
-////    if (myStorage->isEntityFixed(anOtherEntID, true)) {
-////      // Fix start point of the line (if end point is not fixed yet) ...
-////      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];
-////      // 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, anEndFixedID);
-////          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_ConstraintFixed::fixCircle(const Slvs_Entity& theCircle)
-////{
-////  bool isFixRadius = true;
-////  // Verify the arc is under Equal constraint
-////  Slvs_Constraint anEqual;
-////  if (myStorage->isUsedInEqual(theCircle.h, anEqual)) {
-////    // Check another entity of Equal is already fixed
-////    Slvs_hEntity anOtherEntID = anEqual.entityA == theCircle.h ? anEqual.entityB : anEqual.entityA;
-////    if (myStorage->isEntityFixed(anOtherEntID, true))
-////      isFixRadius = false;
-////  }
-////
-////  fixPoint(theCircle.point[0]);
-////
-////  if (isFixRadius) {
-////    // Search the radius is already fixed
-////    std::list<Slvs_Constraint> aDiamConstr = myStorage->getConstraintsByType(SLVS_C_DIAMETER);
-////    std::list<Slvs_Constraint>::const_iterator aDiamIter = aDiamConstr.begin();
-////    for (; aDiamIter != aDiamConstr.end(); aDiamIter++)
-////      if (aDiamIter->entityA == theCircle.h)
-////        return;
-////
-////    // 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_ConstraintFixed::fixArc(const Slvs_Entity& theArc)
-////{
-////  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 (myStorage->isUsedInEqual(theArc.h, anEqual)) {
-////    // Check another entity of Equal is already fixed
-////    Slvs_hEntity anOtherEntID = anEqual.entityA == theArc.h ? anEqual.entityB : anEqual.entityA;
-////    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]);
-////      }
-////    }
-////  }
-////
-////  Slvs_hConstraint aConstrID;
-////  int aNbPointsToFix = 2; // number of fixed points for the arc
-////  if (myStorage->isPointFixed(theArc.point[0], aConstrID, true))
-////    aNbPointsToFix--;
-////
-////  // Radius of the arc
-////  FeaturePtr aFeature = myFeatureMap.begin()->first;
-////  std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-////    aFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
-////  std::shared_ptr<GeomAPI_Pnt2d> aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-////    aFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt();
-////  double aRadius = aCenter->distance(aStart);
-////
-////  // Update end point of the arc to be on a curve
-////  std::shared_ptr<GeomAPI_Pnt2d> anEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-////    aFeature->attribute(SketchPlugin_Arc::END_ID()))->pnt();
-////  double aDistance = anEnd->distance(aCenter);
-////  std::shared_ptr<GeomAPI_XY> aDir = anEnd->xy()->decreased(aCenter->xy());
-////  if (aDistance < tolerance)
-////    aDir = aStart->xy()->decreased(aCenter->xy())->multiplied(-1.0);
-////  else
-////    aDir = aDir->multiplied(aRadius / aDistance);
-////  double xy[2] = {aCenter->x() + aDir->x(), aCenter->y() + aDir->y()};
-////  Slvs_Entity aEndPoint = myStorage->getEntity(theArc.point[2]);
-////  for (int i = 0; i < 2; i++) {
-////    Slvs_Param aParam = myStorage->getParameter(aEndPoint.param[i]);
-////    aParam.val = xy[i];
-////    myStorage->updateParameter(aParam);
-////  }
-////
-////  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 == theArc.h)
-////        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);
-////    }
-////  }
-////}
diff --git a/src/SketchSolver/SketchSolver_ConstraintFixed.h b/src/SketchSolver/SketchSolver_ConstraintFixed.h
deleted file mode 100644 (file)
index 0c9f243..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SketchSolver_ConstraintFixed.h
-// Created: 30 Mar 2015
-// Author:  Artem ZHIDKOV
-
-#ifndef SketchSolver_ConstraintFixed_H_
-#define SketchSolver_ConstraintFixed_H_
-
-#include "SketchSolver.h"
-#include <SketchSolver_Constraint.h>
-
-/** \class   SketchSolver_ConstraintFixed
- *  \ingroup Plugins
- *  \brief   Stores data of the Fixed constraint
- *
- *  Fixed constraint may have NULL basic SketchPlugin constraint,
- *  because the Fixed constraint may be temporary for correct moving of objects.
- *
- *  Fixed constraint does not create a constraint, but builds the entities in separate group,
- *  so they will not be moved while resolving the set of constraints.
- */
-class SketchSolver_ConstraintFixed : public SketchSolver_Constraint
-{
-public:
-  /// Creates constraint to manage the given constraint from plugin
-  SketchSolver_ConstraintFixed(ConstraintPtr theConstraint);
-  /// Creates temporary constraint based on feature
-  SketchSolver_ConstraintFixed(FeaturePtr theFeature);
-
-  /// \brief Tries to remove constraint
-  /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
-  virtual bool remove();
-
-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(ParameterWrapperPtr& theValue, std::vector<EntityWrapperPtr>& theAttributes);
-
-  /// \brief Fixed feature basing on its type
-  /// \param theFeature [in]  feature, converted to solver specific format
-  virtual void fixFeature(EntityWrapperPtr theFeature);
-
-////  /// \brief Fix given point
-////  /// \return ID of the Fixed constraint
-////  Slvs_hConstraint fixPoint(const Slvs_hEntity& thePointID);
-////
-////  /// \brief Returns ID of fixed entity
-////  Slvs_hEntity fixedEntity() const;
-////
-////  /// \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);
-
-protected:
-  FeaturePtr myBaseFeature; ///< fixed feature (when it is set, myBaseConstraint should be NULL)
-
-private:
-  AttributeRefAttrPtr myFixedAttribute; ///< attribute of a fixed constraint (for correct remove)
-};
-
-#endif
index 5c3bbc088637187d5ee63c0cd3d746e27c89196f..06d854d175ba7a4724bf8ef920249746be45ceea 100644 (file)
@@ -1,26 +1,44 @@
 #include <SketchSolver_ConstraintLength.h>
+#include <SketchSolver_Group.h>
 #include <SketchSolver_Error.h>
 
 
-void SketchSolver_ConstraintLength::getAttributes(
-    double& theValue,
-    std::vector<EntityWrapperPtr>& theAttributes)
+void SketchSolver_ConstraintLength::process()
 {
-  SketchSolver_Constraint::getAttributes(theValue, theAttributes);
-  if (!myErrorMsg.empty() || !theAttributes[2] || 
-      theAttributes[2]->type() != ENTITY_LINE) {
-    theAttributes.clear();
+  cleanErrorMsg();
+  if (!myBaseConstraint || !myStorage || myGroup == 0) {
+    /// TODO: Put error message here
     return;
   }
+  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+    update(myBaseConstraint);
 
-  // Get boundary points of line segment and create point-point distance constraint
-  std::list<EntityWrapperPtr> aSubs = theAttributes[2]->subEntities();
-  theAttributes.assign(theAttributes.size(), EntityWrapperPtr());
-  std::vector<EntityWrapperPtr>::iterator anAttrIt = theAttributes.begin();
-  std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
-  for (; aSubIt != aSubs.end(); ++aSubIt, ++anAttrIt)
-    *anAttrIt = *aSubIt;
+  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;
+  }
 
-  myType = CONSTRAINT_PT_PT_DISTANCE;
+  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();
+}
+
+void SketchSolver_ConstraintLength::adjustConstraint()
+{
+  // No need to store the line, which length is constrained
+  // Upd: The line need to be stored to check that constraint
+  //      is changed/unchanged during modifications in GUI
+  //myFeatureMap.clear();
 }
 
index 0899d8b732419e138208af79263d0f7c56abc20c..f9c0da65ce54dd706629d07028d7447e50cf4c88 100644 (file)
@@ -22,11 +22,16 @@ public:
       SketchSolver_Constraint(theConstraint)
   {}
 
+  virtual int getType() const
+  { return SLVS_C_PT_PT_DISTANCE; }
+
 protected:
-  /// \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(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+  /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+  virtual void process();
+
+  /// \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();
 };
 
 #endif
diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.cpp b/src/SketchSolver/SketchSolver_ConstraintManager.cpp
new file mode 100644 (file)
index 0000000..682bbf2
--- /dev/null
@@ -0,0 +1,367 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    SketchSolver_ConstraintManager.cpp
+// Created: 08 May 2014
+// Author:  Artem ZHIDKOV
+
+#include "SketchSolver_ConstraintManager.h"
+
+#include <Events_Loop.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Events.h>
+#include <ModelAPI_Object.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Attribute.h>
+
+#include <SketchPlugin_Constraint.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
+#include <SketchPlugin_Sketch.h>
+#include <SketchPlugin_Feature.h>
+
+#include <list>
+#include <set>
+#include <memory>
+
+// Initialization of constraint manager self pointer
+SketchSolver_ConstraintManager* SketchSolver_ConstraintManager::_self = 0;
+
+/// Global constraint manager object
+SketchSolver_ConstraintManager* myManager = SketchSolver_ConstraintManager::Instance();
+
+
+// ========================================================
+// ========= SketchSolver_ConstraintManager ===============
+// ========================================================
+SketchSolver_ConstraintManager* SketchSolver_ConstraintManager::Instance()
+{
+  if (!_self)
+    _self = new SketchSolver_ConstraintManager();
+  return _self;
+}
+
+SketchSolver_ConstraintManager::SketchSolver_ConstraintManager()
+{
+  myGroups.clear();
+  myIsComputed = false;
+
+  // Register in event loop
+  Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
+  Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+  Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
+  Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_MOVED));
+}
+
+SketchSolver_ConstraintManager::~SketchSolver_ConstraintManager()
+{
+  myGroups.clear();
+}
+
+// ============================================================================
+//  Function: processEvent
+//  Class:    SketchSolver_Session
+//  Purpose:  listen the event loop and process the message
+// ============================================================================
+void SketchSolver_ConstraintManager::processEvent(
+  const std::shared_ptr<Events_Message>& theMessage)
+{
+  if (myIsComputed)
+    return;
+  if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)
+      || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)
+      || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) {
+    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
+        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
+    std::set<ObjectPtr> aFeatures = anUpdateMsg->objects();
+
+    // Shows the message has at least one feature applicable for solver
+    bool hasProperFeature = false;
+
+    bool isMovedEvt = theMessage->eventID()
+          == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED);
+    if (isMovedEvt) {
+      std::set<ObjectPtr>::iterator aFeatIter;
+      for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
+        std::shared_ptr<SketchPlugin_Feature> aSFeature = 
+            std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+        if (aSFeature) {
+          moveEntity(aSFeature);
+          hasProperFeature = true;
+        }
+      }
+    } else {
+      std::list<FeaturePtr> aSketchFeatures = SketchSolver_Group::selectApplicableFeatures(aFeatures);
+      std::list<FeaturePtr>::iterator aFeatIter = aSketchFeatures.begin();
+      for (; aFeatIter != aSketchFeatures.end(); ++aFeatIter) {
+        if ((*aFeatIter)->getKind() == SketchPlugin_Sketch::ID()) {
+          std::shared_ptr<ModelAPI_CompositeFeature> aSketch = 
+              std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aFeatIter);
+          hasProperFeature = changeWorkplane(aSketch) || hasProperFeature;
+          continue;
+        }
+        std::shared_ptr<SketchPlugin_Feature> aFeature = 
+            std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+        if (!aFeature)
+          continue;
+        hasProperFeature = changeConstraintOrEntity(aFeature) || hasProperFeature;
+      }
+    }
+
+    // Solve the set of constraints
+    if (hasProperFeature)
+      resolveConstraints(isMovedEvt); // send update for movement in any case
+  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
+    std::shared_ptr<ModelAPI_ObjectDeletedMessage> aDeleteMsg =
+      std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
+    const std::set<std::string>& aFeatureGroups = aDeleteMsg->groups();
+
+    // Find SketchPlugin_Sketch::ID() in groups. The constraint groups should be updated when an object removed from Sketch
+    std::set<std::string>::const_iterator aFGrIter;
+    for (aFGrIter = aFeatureGroups.begin(); aFGrIter != aFeatureGroups.end(); aFGrIter++)
+      if (aFGrIter->compare(ModelAPI_ResultConstruction::group()) == 0 ||
+        aFGrIter->compare(ModelAPI_Feature::group()) == 0)
+        break;
+
+    if (aFGrIter != aFeatureGroups.end()) {
+      std::vector<SketchSolver_Group*>::iterator aGroupIter = myGroups.begin();
+      std::vector<SketchSolver_Group*> aSeparatedGroups;
+      while (aGroupIter != myGroups.end()) {
+        if (!(*aGroupIter)->isWorkplaneValid()) {  // the group should be removed
+          delete *aGroupIter;
+          int aShift = aGroupIter - myGroups.begin();
+          myGroups.erase(aGroupIter);
+          aGroupIter = myGroups.begin() + aShift;
+          continue;
+        }
+        if (!(*aGroupIter)->isConsistent()) {  // some constraints were removed, try to split the group
+          (*aGroupIter)->splitGroup(aSeparatedGroups);
+        }
+        aGroupIter++;
+      }
+      if (aSeparatedGroups.size() > 0)
+        myGroups.insert(myGroups.end(), aSeparatedGroups.begin(), aSeparatedGroups.end());
+    }
+  }
+}
+
+// ============================================================================
+//  Function: changeWorkplane
+//  Class:    SketchSolver_Session
+//  Purpose:  update workplane by given parameters of the sketch
+// ============================================================================
+bool SketchSolver_ConstraintManager::changeWorkplane(CompositeFeaturePtr theSketch)
+{
+  bool aResult = true;  // changed when a workplane wrongly updated
+  bool isUpdated = false;
+  // Try to update specified workplane in all groups
+  std::vector<SketchSolver_Group*>::iterator aGroupIter;
+  for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
+    if ((*aGroupIter)->isBaseWorkplane(theSketch)) {
+      isUpdated = true;
+      if (!(*aGroupIter)->updateWorkplane())
+        aResult = false;
+    }
+  // If the workplane is not updated, so this is a new workplane
+  if (!isUpdated) {
+    SketchSolver_Group* aNewGroup = new SketchSolver_Group(theSketch);
+    // Verify that the group is created successfully
+    if (!aNewGroup->isBaseWorkplane(theSketch) || !aNewGroup->isWorkplaneValid()) {
+      delete aNewGroup;
+      return false;
+    }
+    myGroups.push_back(aNewGroup);
+  }
+  return aResult;
+}
+
+// ============================================================================
+//  Function: changeConstraintOrEntity
+//  Class:    SketchSolver_Session
+//  Purpose:  create/update the constraint or the feature and place it into appropriate group
+// ============================================================================
+bool SketchSolver_ConstraintManager::changeConstraintOrEntity(
+    std::shared_ptr<SketchPlugin_Feature> theFeature)
+{
+  // Search the groups which this feature touches
+  std::set<Slvs_hGroup> aGroups;
+  findGroups(theFeature, aGroups);
+
+  std::shared_ptr<SketchPlugin_Constraint> aConstraint = 
+      std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
+
+  // Process the groups list
+  if (aGroups.size() == 0) {
+    // There are no groups applicable for this constraint => create new one
+    // The group will be created only for constraints, not for features
+    if (!aConstraint) return false;
+    std::shared_ptr<ModelAPI_CompositeFeature> aWP = findWorkplane(aConstraint);
+    if (!aWP)
+      return false;
+    SketchSolver_Group* aGroup = new SketchSolver_Group(aWP);
+    if (!aGroup->changeConstraint(aConstraint)) {
+      delete aGroup;
+      return false;
+    }
+    myGroups.push_back(aGroup);
+    return true;
+  } else if (aGroups.size() == 1) {  // Only one group => add feature into it
+    Slvs_hGroup aGroupId = *(aGroups.begin());
+    std::vector<SketchSolver_Group*>::iterator aGroupIter;
+    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())
+          return (*aGroupIter)->updateFeature(theFeature);
+        return (*aGroupIter)->changeConstraint(aConstraint);
+      }
+  } else if (aGroups.size() > 1) {  // Several groups applicable for this feature => need to merge them
+    std::set<Slvs_hGroup>::const_iterator aGroupsIter = aGroups.begin();
+
+    // Search first group
+    std::vector<SketchSolver_Group*>::iterator aFirstGroupIter;
+    for (aFirstGroupIter = myGroups.begin(); aFirstGroupIter != myGroups.end(); aFirstGroupIter++)
+      if ((*aFirstGroupIter)->getId() == *aGroupsIter)
+        break;
+    if (aFirstGroupIter == myGroups.end())
+      return false;
+
+    // Append other groups to the first one
+    std::vector<SketchSolver_Group*>::iterator anOtherGroupIter = aFirstGroupIter + 1;
+    for (aGroupsIter++; aGroupsIter != aGroups.end(); aGroupsIter++) {
+      for (; anOtherGroupIter != myGroups.end(); anOtherGroupIter++)
+        if ((*anOtherGroupIter)->getId() == *aGroupsIter)
+          break;
+      if (anOtherGroupIter == myGroups.end()) {  // Group disappears
+        anOtherGroupIter = aFirstGroupIter + 1;
+        continue;
+      }
+
+      (*aFirstGroupIter)->mergeGroups(**anOtherGroupIter);
+      int aShiftFirst = aFirstGroupIter - myGroups.begin();
+      int aShiftOther = anOtherGroupIter - myGroups.begin();
+      delete *anOtherGroupIter;
+      myGroups.erase(anOtherGroupIter);
+      aFirstGroupIter = myGroups.begin() + aShiftFirst;
+      anOtherGroupIter = myGroups.begin() + aShiftOther;
+    }
+
+    if (aConstraint)
+      return (*aFirstGroupIter)->changeConstraint(aConstraint);
+    return (*aFirstGroupIter)->updateFeature(theFeature);
+  }
+
+  // Something goes wrong
+  return false;
+}
+
+// ============================================================================
+//  Function: moveEntity
+//  Class:    SketchSolver_Session
+//  Purpose:  update element moved on the sketch, which is used by constraints
+// ============================================================================
+void SketchSolver_ConstraintManager::moveEntity(
+    std::shared_ptr<SketchPlugin_Feature> theFeature)
+{
+  std::vector<SketchSolver_Group*>::iterator aGroupIt = myGroups.begin();
+  for (; aGroupIt != myGroups.end(); aGroupIt++)
+    if (!(*aGroupIt)->isEmpty() && (*aGroupIt)->isInteract(theFeature))
+      (*aGroupIt)->moveFeature(theFeature);
+}
+
+// ============================================================================
+//  Function: findGroups
+//  Class:    SketchSolver_Session
+//  Purpose:  search groups of entities interacting with given feature
+// ============================================================================
+void SketchSolver_ConstraintManager::findGroups(
+    std::shared_ptr<SketchPlugin_Feature> theFeature,
+    std::set<Slvs_hGroup>& theGroupIDs) const
+{
+  std::shared_ptr<ModelAPI_CompositeFeature> aWP = findWorkplane(theFeature);
+
+  SketchSolver_Group* anEmptyGroup = 0;  // appropriate empty group for specified constraint
+  std::vector<SketchSolver_Group*>::const_iterator aGroupIter;
+  for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
+    if (aWP == (*aGroupIter)->getWorkplane() && (*aGroupIter)->isInteract(theFeature)) {
+      if (!(*aGroupIter)->isEmpty())
+        theGroupIDs.insert((*aGroupIter)->getId());
+      else if (!anEmptyGroup)
+        anEmptyGroup = *aGroupIter;
+    }
+
+  // When only empty group is found, use it
+  if (anEmptyGroup && theGroupIDs.empty())
+    theGroupIDs.insert(anEmptyGroup->getId());
+}
+
+// ============================================================================
+//  Function: findWorkplane
+//  Class:    SketchSolver_Session
+//  Purpose:  search workplane containing given feature
+// ============================================================================
+std::shared_ptr<ModelAPI_CompositeFeature> SketchSolver_ConstraintManager
+::findWorkplane(std::shared_ptr<SketchPlugin_Feature> theFeature) const
+{
+  // Already verified workplanes
+  std::set<std::shared_ptr<ModelAPI_CompositeFeature> > aVerified;
+
+  std::vector<SketchSolver_Group*>::const_iterator aGroupIter;
+  for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) {
+    std::shared_ptr<ModelAPI_CompositeFeature> aWP = (*aGroupIter)->getWorkplane();
+    if (aVerified.find(aWP) != aVerified.end())
+      continue;
+
+    DataPtr aData = aWP->data();
+    if (aData->isValid()) {
+      std::shared_ptr<ModelAPI_AttributeRefList> aWPFeatures = std::dynamic_pointer_cast<
+          ModelAPI_AttributeRefList>(aData->attribute(SketchPlugin_Sketch::FEATURES_ID()));
+      std::list<ObjectPtr> aFeaturesList = aWPFeatures->list();
+      std::list<ObjectPtr>::const_iterator anIter;
+      for (anIter = aFeaturesList.begin(); anIter != aFeaturesList.end(); anIter++)
+        if (*anIter == theFeature)
+          return aWP;  // workplane is found
+    }
+    aVerified.insert(aWP);
+  }
+
+  return std::shared_ptr<ModelAPI_CompositeFeature>();
+}
+
+// ============================================================================
+//  Function: resolveConstraints
+//  Class:    SketchSolver_Session
+//  Purpose:  change entities according to available constraints
+// ============================================================================
+void SketchSolver_ConstraintManager::resolveConstraints(const bool theForceUpdate)
+{
+  myIsComputed = true;
+  bool needToUpdate = false;
+  static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+  // to avoid redisplay of each segment on update by solver one by one in the viewer
+  bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
+  if (isUpdateFlushed) {
+    Events_Loop::loop()->setFlushed(anUpdateEvent, false);
+  }
+
+  std::vector<SketchSolver_Group*>::iterator aGroupIter;
+  for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
+    if ((*aGroupIter)->resolveConstraints())
+      needToUpdate = true;
+
+  // Features may be updated => now send events, but for all changed at once
+  if (isUpdateFlushed) {
+    Events_Loop::loop()->setFlushed(anUpdateEvent, true);
+  }
+  // Must be before flush because on "Updated" flush the results may be produced
+  // and the creation event is appeared with many new objects. If myIsComputed these
+  // events are missed in processEvents and some elements are not added.
+  myIsComputed = false;
+  if (needToUpdate || theForceUpdate)
+    Events_Loop::loop()->flush(anUpdateEvent);
+}
+
diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.h b/src/SketchSolver/SketchSolver_ConstraintManager.h
new file mode 100644 (file)
index 0000000..a2d7ffa
--- /dev/null
@@ -0,0 +1,112 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    SketchSolver_ConstraintManager.h
+// Created: 08 May 2014
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintManager_H_
+#define SketchSolver_ConstraintManager_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Solver.h>
+#include <SketchSolver_Group.h>
+
+#include <Events_Listener.h>
+#include <SketchPlugin_Constraint.h>
+
+#include <string.h>
+#include <slvs.h>
+
+#include <list>
+#include <map>
+#include <vector>
+#include <set>
+
+/** \class   SketchSolver_ConstraintManager
+ *  \ingroup Plugins
+ *  \brief   Listens the changes of SketchPlugin features and transforms the Constraint
+ *           feature into the format understandable by SolveSpace library.
+ *
+ *  Constraints created for SolveSpace library are divided into the groups.
+ *  The division order based on connectedness of the features by the constraints.
+ *  The groups may be fused or separated according to the new constraints.
+ *
+ *  \remark This is a singleton.
+ */
+class SketchSolver_ConstraintManager : public Events_Listener
+{
+ public:
+  /** \brief Main method to create constraint manager
+   *  \return pointer to the singleton
+   */
+  static SketchSolver_ConstraintManager* Instance();
+
+  /** \brief Implementation of Event Listener method
+   *  \param[in] theMessage the data of the event
+   */
+  virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+ protected:
+  SketchSolver_ConstraintManager();
+  ~SketchSolver_ConstraintManager();
+
+  /** \brief Adds or updates a constraint or an entity in the suitable group
+   *  \param[in] theFeature sketch feature to be changed
+   *  \return \c true if the feature changed successfully
+   */
+  bool changeConstraintOrEntity(std::shared_ptr<SketchPlugin_Feature> theFeature);
+
+  /** \brief Removes a constraint from the manager
+   *  \param[in] theConstraint constraint to be removed
+   *  \return \c true if the constraint removed successfully
+   */
+  bool removeConstraint(std::shared_ptr<SketchPlugin_Constraint> theConstraint);
+
+  /** \brief Adds or updates a workplane in the manager
+   *  \param[in] theSketch the feature to create or update workplane
+   *  \return \c true if the workplane changed successfully
+   *  \remark Type of theSketch is not verified inside
+   */
+  bool changeWorkplane(CompositeFeaturePtr theSketch);
+
+  /** \brief Removes a workplane from the manager.
+   *         All groups based on such workplane will be removed too.
+   *  \param[in] theSketch the feature to be removed
+   *  \return \c true if the workplane removed successfully
+   */
+  bool removeWorkplane(std::shared_ptr<SketchPlugin_Sketch> theSketch);
+
+  /** \brief Updates entity which is moved in GUI
+   *  \param[in] theFeature entity to be updated
+   */
+  void moveEntity(std::shared_ptr<SketchPlugin_Feature> theFeature);
+
+  /** \brief Goes through the list of groups and solve the constraints
+   *  \param theForceUpdate flushes the update event in any case: something changed or not
+   */
+  void resolveConstraints(const bool theForceUpdate);
+
+ private:
+  /** \brief Searches list of groups which interact with specified feature
+   *  \param[in]  theFeature  object to be found
+   *  \param[out] theGroups   list of group indexes interacted with the feature
+   */
+  void findGroups(std::shared_ptr<SketchPlugin_Feature> theFeature,
+                  std::set<Slvs_hGroup>& theGroupIDs) const;
+
+  /** \brief Searches in the list of groups the workplane which constains specified feature
+   *  \param[in] theFeature object to be found
+   *  \return workplane containing the feature
+   */
+  std::shared_ptr<ModelAPI_CompositeFeature> findWorkplane(
+      std::shared_ptr<SketchPlugin_Feature> theFeature) const;
+
+ private:
+  static SketchSolver_ConstraintManager* _self;  ///< Self pointer to implement singleton functionality
+  std::vector<SketchSolver_Group*> myGroups;  ///< Groups of constraints
+  /// true if computation is performed and all "updates" are generated by this algo
+  /// and needs no recomputation
+  bool myIsComputed;
+};
+
+#endif
index be15c46a0970b0f1a73e091a11db56fa72acf99c..9d1477545f9d969234e7c7115d2fe04b16ab2d5f 100644 (file)
@@ -1,33 +1,34 @@
 #include <SketchSolver_ConstraintMirror.h>
+#include <SketchSolver_Group.h>
 #include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
 
-////#include <ModelAPI_AttributeDouble.h>
-////#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_AttributeRefList.h>
-////#include <ModelAPI_ResultConstruction.h>
-////
-////#include <GeomAPI_Dir2d.h>
-////#include <GeomAPI_XY.h>
-////
-////#include <cmath>
+#include <ModelAPI_ResultConstruction.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+
+#include <cmath>
 
 void SketchSolver_ConstraintMirror::getAttributes(
-    EntityWrapperPtr& theMirrorLine,
-    std::vector<EntityWrapperPtr>& theBaseEntities,
-    std::vector<EntityWrapperPtr>& theMirrorEntities)
+    Slvs_Entity& theMirrorLine,
+    std::vector<Slvs_Entity>& theBaseEntities,
+    std::vector<Slvs_Entity>& theMirrorEntities)
 {
-  AttributePtr aMirLineAttr = myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A());
-  AttributeRefAttrPtr aMirLineRefAttr =
-      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aMirLineAttr);
-  if (!aMirLineRefAttr || !aMirLineRefAttr->isInitialized() || !aMirLineRefAttr->isObject()) {
+  DataPtr aData = myBaseConstraint->data();
+  AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) {
     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
     return;
   }
-
-  myType = TYPE(myBaseConstraint);
-  myStorage->update(aMirLineAttr, myGroupID);
-  theMirrorLine = myStorage->entity(aMirLineAttr);
+  int aType = SLVS_E_UNKNOWN; // type of created entity
+  Slvs_hEntity anEntity = myGroup->getAttributeId(aMirLineAttr);
+  if (anEntity == SLVS_E_UNKNOWN)
+    anEntity = changeEntity(aMirLineAttr, aType);
+  theMirrorLine = myStorage->getEntity(anEntity);
 
   // Create SolveSpace entity for all features
   AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
@@ -44,25 +45,26 @@ void SketchSolver_ConstraintMirror::getAttributes(
   std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
 
   FeaturePtr aFeature;
+  ResultConstructionPtr aRC;
   for (int i = 0; i < 2; i++) {
     std::list<ObjectPtr>::iterator anIter = i == 0 ? aBaseList.begin() : aMirroredList.begin();
     std::list<ObjectPtr>::iterator aEndIter = i == 0 ? aBaseList.end() : aMirroredList.end();
-    std::vector<EntityWrapperPtr>* aList = i == 0 ? &theBaseEntities : & theMirrorEntities;
+    std::vector<Slvs_Entity>* aList = i == 0 ? &theBaseEntities : & theMirrorEntities;
     for ( ; anIter != aEndIter; anIter++) {
-      aFeature = ModelAPI_Feature::feature(*anIter);
+      aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIter);
+      aFeature = aRC ? aRC->document()->feature(aRC) :
+        std::dynamic_pointer_cast<ModelAPI_Feature>(*anIter);
       if (!aFeature)
         continue;
 
-////      anEntity = changeEntity(aFeature, aType);
-////      // Sort entities by their type
-////      std::vector<Slvs_Entity>::iterator anIt = aList->begin();
-////      for (; anIt != aList->end(); anIt++)
-////        if (aType < anIt->type)
-////          break;
-//////      aList->push_back(myStorage->getEntity(anEntity));
-////      aList->insert(anIt, myStorage->getEntity(anEntity));
-      myStorage->update(aFeature, myGroupID);
-      aList->push_back(myStorage->entity(aFeature));
+      anEntity = changeEntity(aFeature, aType);
+      // Sort entities by their type
+      std::vector<Slvs_Entity>::iterator anIt = aList->begin();
+      for (; anIt != aList->end(); anIt++)
+        if (aType < anIt->type)
+          break;
+//      aList->push_back(myStorage->getEntity(anEntity));
+      aList->insert(anIt, myStorage->getEntity(anEntity));
     }
   }
 
@@ -73,16 +75,16 @@ void SketchSolver_ConstraintMirror::getAttributes(
 void SketchSolver_ConstraintMirror::process()
 {
   cleanErrorMsg();
-  if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
-    // Not enough parameters are assigned
+  if (!myBaseConstraint || !myStorage || myGroup == 0) {
+    /// TODO: Put error message here
     return;
   }
-////  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
-////    update(myBaseConstraint);
+  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+    update(myBaseConstraint);
 
-  EntityWrapperPtr aMirrorLine;
-  std::vector<EntityWrapperPtr> aBaseList;
-  std::vector<EntityWrapperPtr> aMirrorList;
+  Slvs_Entity aMirrorLine;
+  std::vector<Slvs_Entity> aBaseList;
+  std::vector<Slvs_Entity> aMirrorList;
   getAttributes(aMirrorLine, aBaseList, aMirrorList);
   if (!myErrorMsg.empty())
     return;
@@ -92,328 +94,389 @@ void SketchSolver_ConstraintMirror::process()
     return;
   }
 
-  std::list<ConstraintWrapperPtr> aNewConstraints;
-  SketchSolver_ConstraintType aConstrType = getType();
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-  std::list<ConstraintWrapperPtr> aMirConstrList;
-
-  std::vector<EntityWrapperPtr>::iterator aBIt = aBaseList.begin();
-  std::vector<EntityWrapperPtr>::iterator aMIt = aMirrorList.begin();
-  for (; aBIt != aBaseList.end(); ++aBIt, ++aMIt) {
-    if ((*aBIt)->type() == ENTITY_ARC) {
-      // add new points on arcs and mirror them
-      EntityWrapperPtr aBasePnt = myStorage->calculateMiddlePoint(*aBIt, 0.5);
-      EntityWrapperPtr aMirrPnt = myStorage->calculateMiddlePoint(*aMIt, 0.5);
-      // point on base arc
-      aNewConstraints = aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID,
-          CONSTRAINT_PT_ON_CIRCLE, 0.0, aBasePnt, EntityWrapperPtr(), *aBIt);
-      aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
-      // point on mirrored arc
-      aNewConstraints = aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID,
-          CONSTRAINT_PT_ON_CIRCLE, 0.0, aMirrPnt, EntityWrapperPtr(), *aMIt);
-      aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
-      // mirror these points
-      aNewConstraints = aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID,
-          aConstrType, 0.0, aBasePnt, aMirrPnt, aMirrorLine);
-      aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
-    }
-    aNewConstraints = aBuilder->createConstraint(
-        myBaseConstraint, myGroupID, mySketchID, aConstrType,
-        0.0, *aBIt, *aMIt, aMirrorLine);
-    aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
+  Slvs_Constraint aConstraint;
+  // Get coordinates of mirror line points for speed up
+  double aStartEnd[4];
+  for (int i = 0; i < 2; i++) {
+    Slvs_Entity aPoint = myStorage->getEntity(aMirrorLine.point[i]);
+    for (int j = 0; j < 2; j++)
+      aStartEnd[2*i+j] = myStorage->getParameter(aPoint.param[j]).val;
   }
 
-  myStorage->addConstraint(myBaseConstraint, aMirConstrList);
+  std::vector<Slvs_Entity>::iterator aBaseIter = aBaseList.begin();
+  std::vector<Slvs_Entity>::iterator aMirrorIter = aMirrorList.begin();
+  for (; aBaseIter != aBaseList.end(); aBaseIter++, aMirrorIter++) {
+    // Make aMirrorEnt parameters to be symmetric with aBaseEnt
+    makeMirrorEntity(*aBaseIter, *aMirrorIter, aStartEnd);
+
+    if (aBaseIter->type == SLVS_E_POINT_IN_2D) {
+      aConstraint = Slvs_MakeConstraint(
+          SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(),
+          0.0, aBaseIter->h, aMirrorIter->h, aMirrorLine.h, SLVS_E_UNKNOWN);
+      aConstraint.h = myStorage->addConstraint(aConstraint);
+      mySlvsConstraints.push_back(aConstraint.h);
+    } else if (aBaseIter->type == SLVS_E_LINE_SEGMENT) {
+      for (int i = 0; i < 2; i++) {
+        aConstraint = Slvs_MakeConstraint(
+            SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), 0.0,
+            aBaseIter->point[i], aMirrorIter->point[i], aMirrorLine.h, SLVS_E_UNKNOWN);
+        aConstraint.h = myStorage->addConstraint(aConstraint);
+        mySlvsConstraints.push_back(aConstraint.h);
+      }
+    } else if (aBaseIter->type == SLVS_E_CIRCLE) {
+      aConstraint = Slvs_MakeConstraint(
+          SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), 0.0,
+          aBaseIter->point[0], aMirrorIter->point[0], aMirrorLine.h, SLVS_E_UNKNOWN);
+      aConstraint.h = myStorage->addConstraint(aConstraint);
+      mySlvsConstraints.push_back(aConstraint.h);
+      // Additional constraint for equal radii
+      Slvs_Constraint anEqRadConstr = Slvs_MakeConstraint(
+          SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_EQUAL_RADIUS, myGroup->getWorkplaneId(),
+          0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aBaseIter->h, aMirrorIter->h);
+      anEqRadConstr.h = myStorage->addConstraint(anEqRadConstr);
+      mySlvsConstraints.push_back(anEqRadConstr.h);
+    } else if (aBaseIter->type == SLVS_E_ARC_OF_CIRCLE) {
+      // Workaround to avoid problems in SolveSpace.
+      // The symmetry of two arcs will be done using symmetry of three points on these arcs:
+      // start point, end point, and any other point on the arc
+      Slvs_hEntity aBaseArcPoints[3] = {
+          aBaseIter->point[1],
+          aBaseIter->point[2],
+          SLVS_E_UNKNOWN};
+      Slvs_hEntity aMirrorArcPoints[3] = { // indices of points of arc, center corresponds center, first point corresponds last point
+          aMirrorIter->point[2],
+          aMirrorIter->point[1],
+          SLVS_E_UNKNOWN};
+
+      Slvs_Entity aBothArcs[2] = {*aBaseIter, *aMirrorIter};
+      Slvs_hEntity aBothMiddlePoints[2];
+      for (int i = 0; i < 2; i++) {
+        double x, y;
+        calculateMiddlePoint(aBothArcs[i], 0.5, x, y);
+        Slvs_Param aParamX = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), x);
+        Slvs_Param aParamY = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), y);
+        aParamX.h = myStorage->addParameter(aParamX);
+        aParamY.h = myStorage->addParameter(aParamY);
+        Slvs_Entity aPoint = Slvs_MakePoint2d(SLVS_E_UNKNOWN, myGroup->getId(),
+            myGroup->getWorkplaneId(), aParamX.h, aParamY.h);
+        aBothMiddlePoints[i] = myStorage->addEntity(aPoint);
+        // additional constraint point-on-curve
+        Slvs_Constraint aPonCircConstr = Slvs_MakeConstraint(
+            SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_ON_CIRCLE, myGroup->getWorkplaneId(),
+            0.0, aBothMiddlePoints[i], SLVS_E_UNKNOWN, aBothArcs[i].h, SLVS_E_UNKNOWN);
+        aPonCircConstr.h = myStorage->addConstraint(aPonCircConstr);
+        mySlvsConstraints.push_back(aPonCircConstr.h);
+        if (i == 0) {
+          // additional constraint for the point to be in the middle of a base arc
+          Slvs_Entity aLine1 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+              myGroup->getWorkplaneId(), aBothArcs[i].point[1], aBothMiddlePoints[i]);
+          aLine1.h = myStorage->addEntity(aLine1);
+          Slvs_Entity aLine2 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+              myGroup->getWorkplaneId(), aBothArcs[i].point[2], aBothMiddlePoints[i]);
+          aLine2.h = myStorage->addEntity(aLine2);
+          Slvs_Constraint aMiddleConstr = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+              SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(),
+              0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aLine1.h, aLine2.h);
+          aMiddleConstr.h = myStorage->addConstraint(aMiddleConstr);
+          mySlvsConstraints.push_back(aMiddleConstr.h);
+        }
+      }
+
+      aBaseArcPoints[2] = aBothMiddlePoints[0];
+      aMirrorArcPoints[2] = aBothMiddlePoints[1];
+      for (int ind = 0; ind < 3; ind++) {
+        Slvs_Constraint aConstraint = Slvs_MakeConstraint(
+            SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), 0.0,
+            aBaseArcPoints[ind], aMirrorArcPoints[ind], aMirrorLine.h, SLVS_E_UNKNOWN);
+        aConstraint.h = myStorage->addConstraint(aConstraint);
+        mySlvsConstraints.push_back(aConstraint.h);
+      }
+    }
+  }
 }
 
 
-void SketchSolver_ConstraintMirror::update()
+void SketchSolver_ConstraintMirror::update(ConstraintPtr theConstraint)
 {
   cleanErrorMsg();
-  AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-    myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C()));
-  if (aMirroredRefList->size() != myNumberOfObjects) {
-    remove();
-    process();
-    return;
+  if (!theConstraint || theConstraint == myBaseConstraint) {
+    AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+        myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C()));
+    if (aMirroredRefList->size() != myNumberOfObjects) {
+      remove(myBaseConstraint);
+      process();
+      return;
+    }
   }
   SketchSolver_Constraint::update();
 }
 
-////bool SketchSolver_ConstraintMirror::remove(ConstraintPtr theConstraint)
-////{
-////  cleanErrorMsg();
-////  if (theConstraint && theConstraint != myBaseConstraint)
-////    return false;
-////  bool isFullyRemoved = true;
-////  std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
-////  for (; aCIter != mySlvsConstraints.end(); aCIter++)
-////   isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
-////  mySlvsConstraints.clear();
-////
-////  std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
-////  for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
-////    myStorage->removeEntity(aFeatIt->second);
-////
-////  if (isFullyRemoved) {
-////    myFeatureMap.clear();
-////    myAttributeMap.clear();
-////    myValueMap.clear();
-////  } else
-////    cleanRemovedEntities();
-////  return true;
-////}
-////
-////bool SketchSolver_ConstraintMirror::checkAttributesChanged(ConstraintPtr theConstraint)
-////{
-////  // First of all, check the mirror line is changed.
-////  // It may be changed to one of mirrored lines, which is already in this constraint
-////  // (this case is not marked as attribute changing)
-////  ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
-////  AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-////      aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
-////  if (!aRefAttr || !aRefAttr->isObject() || !aRefAttr->object())
-////    return true;
-////  FeaturePtr aMirrorLine = ModelAPI_Feature::feature(aRefAttr->object());
-////  if (!aMirrorLine)
-////    return true;
-////
-////  std::map<FeaturePtr, Slvs_hEntity>::iterator aMirrorIter = myFeatureMap.find(aMirrorLine);
-////  if (aMirrorIter == myFeatureMap.end())
-////    return true;
-////
-////  // Check the entity is not used as mirror line
-////  std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
-////  for (; aCIter != mySlvsConstraints.end(); aCIter++) {
-////    Slvs_Constraint aMirrorConstr = myStorage->getConstraint(*aCIter);
-////    if (aMirrorConstr.type != SLVS_C_SYMMETRIC_LINE)
-////      continue;
-////    if (aMirrorConstr.entityA != aMirrorIter->second)
-////      return true;
-////    else break; // check just one symmetric constraint
-////  }
-////
-////  // Base verification
-////  return SketchSolver_Constraint::checkAttributesChanged(theConstraint);
-////}
-
-////void SketchSolver_ConstraintMirror::makeMirrorEntity(
-////    const Slvs_Entity& theBase,
-////    const Slvs_Entity& theMirror,
-////    const double theMirrorLine[]) const
-////{
-////  Slvs_hEntity aBasePoint[4];
-////  Slvs_hEntity aMirrorPoint[4];
-////  for (int i = 0; i < 4; i++) {
-////    aBasePoint[i] = theBase.point[i];
-////    aMirrorPoint[i] = theMirror.point[i];
-////  }
-////  if (theBase.type == SLVS_E_ARC_OF_CIRCLE) {
-////    Slvs_hEntity aTmp = aMirrorPoint[2];
-////    aMirrorPoint[2] = aMirrorPoint[1];
-////    aMirrorPoint[1] = aTmp;
-////    adjustArcPoints(theBase);
-////  }
-////  if (theBase.type == SLVS_E_POINT_IN_2D || theBase.type == SLVS_E_POINT_IN_3D) {
-////    aBasePoint[0] = theBase.h;
-////    aMirrorPoint[0] = theMirror.h;
-////  }
-////
-////  // Mirror line parameters
-////  std::shared_ptr<GeomAPI_XY> aLinePoints[2];
-////  for (int i = 0; i < 2; i++)
-////    aLinePoints[i] = std::shared_ptr<GeomAPI_XY>(
-////        new GeomAPI_XY(theMirrorLine[2*i], theMirrorLine[2*i+1]));
-////  // direction of a mirror line
-////  std::shared_ptr<GeomAPI_Dir2d> aDir = std::shared_ptr<GeomAPI_Dir2d>(
-////    new GeomAPI_Dir2d(aLinePoints[1]->added(aLinePoints[0]->multiplied(-1.0))));
-////  // orthogonal direction
-////  aDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aDir->y(), -aDir->x()));
-////
-////  Slvs_hConstraint aFixed; // transient variable
-////  for (int i = 0; i < 4; i++) {
-////    if (aBasePoint[i] == SLVS_E_UNKNOWN || aMirrorPoint[i] == SLVS_E_UNKNOWN)
-////      continue;
-////    // check the mirror point is not fixed
-////    if (myStorage->isPointFixed(aMirrorPoint[i], aFixed, true))
-////      continue;
-////
-////    Slvs_Entity aPointEnt = myStorage->getEntity(aBasePoint[i]);
-////    double aBaseX = myStorage->getParameter(aPointEnt.param[0]).val;
-////    double aBaseY = myStorage->getParameter(aPointEnt.param[1]).val;
-////    std::shared_ptr<GeomAPI_XY> aPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(aBaseX, aBaseY));
-////
-////    std::shared_ptr<GeomAPI_XY> aVec = std::shared_ptr<GeomAPI_XY>(
-////        new GeomAPI_XY(aPoint->x() - aLinePoints[0]->x(), aPoint->y() - aLinePoints[0]->y()));
-////    double aDist = aVec->dot(aDir->xy());
-////    aPoint = aPoint->added(aDir->xy()->multiplied(-2.0 * aDist));
-////
-////    Slvs_Entity aMirrorEnt = myStorage->getEntity(aMirrorPoint[i]);
-////    Slvs_Param aParam = Slvs_MakeParam(aMirrorEnt.param[0], myGroup->getId(), aPoint->x());
-////    myStorage->updateParameter(aParam);
-////    aParam = Slvs_MakeParam(aMirrorEnt.param[1], myGroup->getId(), aPoint->y());
-////    myStorage->updateParameter(aParam);
-////  }
-////}
-////
-////void SketchSolver_ConstraintMirror::adjustArcPoints(const Slvs_Entity& theArc) const
-////{
-////  Slvs_Param aParam;
-////  Slvs_Entity aPoint;
-////  double anArcParams[3][2];
-////  for (int i = 0; i < 3; i++) {
-////    aPoint = myStorage->getEntity(theArc.point[i]);
-////    for (int j = 0; j < 2; j++) {
-////      aParam = myStorage->getParameter(aPoint.param[j]);
-////      anArcParams[i][j] = aParam.val;
-////      if (i > 0)
-////        anArcParams[i][j] -= anArcParams[0][j];
-////    }
-////  }
-////  double aRad2 = anArcParams[1][0] * anArcParams[1][0] + anArcParams[1][1] * anArcParams[1][1];
-////  double aDist2 = anArcParams[2][0] * anArcParams[2][0] + anArcParams[2][1] * anArcParams[2][1];
-////  if (std::fabs(aRad2 - aDist2) < tolerance)
-////    return; // nothing to update (last point already on the arc)
-////  if (aDist2 < tolerance)
-////    return; // unable to update
-////  double aCoeff = std::sqrt(aRad2 / aDist2);
-////  anArcParams[2][0] *= aCoeff;
-////  anArcParams[2][1] *= aCoeff;
-////
-////  // Update last point
-////  aPoint = myStorage->getEntity(theArc.point[2]);
-////  for (int i = 0; i < 2; i++) {
-////    aParam = Slvs_MakeParam(aPoint.param[i], myGroup->getId(),
-////        anArcParams[0][i] + anArcParams[2][i]);
-////    myStorage->updateParameter(aParam);
-////  }
-////}
+bool SketchSolver_ConstraintMirror::remove(ConstraintPtr theConstraint)
+{
+  cleanErrorMsg();
+  if (theConstraint && theConstraint != myBaseConstraint)
+    return false;
+  bool isFullyRemoved = true;
+  std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
+  for (; aCIter != mySlvsConstraints.end(); aCIter++)
+   isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
+  mySlvsConstraints.clear();
+
+  std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
+  for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
+    myStorage->removeEntity(aFeatIt->second);
+
+  if (isFullyRemoved) {
+    myFeatureMap.clear();
+    myAttributeMap.clear();
+    myValueMap.clear();
+  } else
+    cleanRemovedEntities();
+  return true;
+}
+
+bool SketchSolver_ConstraintMirror::checkAttributesChanged(ConstraintPtr theConstraint)
+{
+  // First of all, check the mirror line is changed.
+  // It may be changed to one of mirrored lines, which is already in this constraint
+  // (this case is not marked as attribute changing)
+  ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
+  AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+      aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  if (!aRefAttr || !aRefAttr->isObject() || !aRefAttr->object())
+    return true;
+  FeaturePtr aMirrorLine = ModelAPI_Feature::feature(aRefAttr->object());
+  if (!aMirrorLine)
+    return true;
+
+  std::map<FeaturePtr, Slvs_hEntity>::iterator aMirrorIter = myFeatureMap.find(aMirrorLine);
+  if (aMirrorIter == myFeatureMap.end())
+    return true;
+
+  // Check the entity is not used as mirror line
+  std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
+  for (; aCIter != mySlvsConstraints.end(); aCIter++) {
+    Slvs_Constraint aMirrorConstr = myStorage->getConstraint(*aCIter);
+    if (aMirrorConstr.type != SLVS_C_SYMMETRIC_LINE)
+      continue;
+    if (aMirrorConstr.entityA != aMirrorIter->second)
+      return true;
+    else break; // check just one symmetric constraint
+  }
+
+  // Base verification
+  return SketchSolver_Constraint::checkAttributesChanged(theConstraint);
+}
+
+void SketchSolver_ConstraintMirror::makeMirrorEntity(
+    const Slvs_Entity& theBase,
+    const Slvs_Entity& theMirror,
+    const double theMirrorLine[]) const
+{
+  Slvs_hEntity aBasePoint[4];
+  Slvs_hEntity aMirrorPoint[4];
+  for (int i = 0; i < 4; i++) {
+    aBasePoint[i] = theBase.point[i];
+    aMirrorPoint[i] = theMirror.point[i];
+  }
+  if (theBase.type == SLVS_E_ARC_OF_CIRCLE) {
+    Slvs_hEntity aTmp = aMirrorPoint[2];
+    aMirrorPoint[2] = aMirrorPoint[1];
+    aMirrorPoint[1] = aTmp;
+    adjustArcPoints(theBase);
+  }
+  if (theBase.type == SLVS_E_POINT_IN_2D || theBase.type == SLVS_E_POINT_IN_3D) {
+    aBasePoint[0] = theBase.h;
+    aMirrorPoint[0] = theMirror.h;
+  }
+
+  // Mirror line parameters
+  std::shared_ptr<GeomAPI_XY> aLinePoints[2];
+  for (int i = 0; i < 2; i++)
+    aLinePoints[i] = std::shared_ptr<GeomAPI_XY>(
+        new GeomAPI_XY(theMirrorLine[2*i], theMirrorLine[2*i+1]));
+  // direction of a mirror line
+  std::shared_ptr<GeomAPI_Dir2d> aDir = std::shared_ptr<GeomAPI_Dir2d>(
+    new GeomAPI_Dir2d(aLinePoints[1]->added(aLinePoints[0]->multiplied(-1.0))));
+  // orthogonal direction
+  aDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aDir->y(), -aDir->x()));
+
+  Slvs_hConstraint aFixed; // transient variable
+  for (int i = 0; i < 4; i++) {
+    if (aBasePoint[i] == SLVS_E_UNKNOWN || aMirrorPoint[i] == SLVS_E_UNKNOWN)
+      continue;
+    // check the mirror point is not fixed
+    if (myStorage->isPointFixed(aMirrorPoint[i], aFixed, true))
+      continue;
+
+    Slvs_Entity aPointEnt = myStorage->getEntity(aBasePoint[i]);
+    double aBaseX = myStorage->getParameter(aPointEnt.param[0]).val;
+    double aBaseY = myStorage->getParameter(aPointEnt.param[1]).val;
+    std::shared_ptr<GeomAPI_XY> aPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(aBaseX, aBaseY));
+
+    std::shared_ptr<GeomAPI_XY> aVec = std::shared_ptr<GeomAPI_XY>(
+        new GeomAPI_XY(aPoint->x() - aLinePoints[0]->x(), aPoint->y() - aLinePoints[0]->y()));
+    double aDist = aVec->dot(aDir->xy());
+    aPoint = aPoint->added(aDir->xy()->multiplied(-2.0 * aDist));
+
+    Slvs_Entity aMirrorEnt = myStorage->getEntity(aMirrorPoint[i]);
+    Slvs_Param aParam = Slvs_MakeParam(aMirrorEnt.param[0], myGroup->getId(), aPoint->x());
+    myStorage->updateParameter(aParam);
+    aParam = Slvs_MakeParam(aMirrorEnt.param[1], myGroup->getId(), aPoint->y());
+    myStorage->updateParameter(aParam);
+  }
+}
+
+void SketchSolver_ConstraintMirror::adjustArcPoints(const Slvs_Entity& theArc) const
+{
+  Slvs_Param aParam;
+  Slvs_Entity aPoint;
+  double anArcParams[3][2];
+  for (int i = 0; i < 3; i++) {
+    aPoint = myStorage->getEntity(theArc.point[i]);
+    for (int j = 0; j < 2; j++) {
+      aParam = myStorage->getParameter(aPoint.param[j]);
+      anArcParams[i][j] = aParam.val;
+      if (i > 0)
+        anArcParams[i][j] -= anArcParams[0][j];
+    }
+  }
+  double aRad2 = anArcParams[1][0] * anArcParams[1][0] + anArcParams[1][1] * anArcParams[1][1];
+  double aDist2 = anArcParams[2][0] * anArcParams[2][0] + anArcParams[2][1] * anArcParams[2][1];
+  if (std::fabs(aRad2 - aDist2) < tolerance)
+    return; // nothing to update (last point already on the arc)
+  if (aDist2 < tolerance)
+    return; // unable to update
+  double aCoeff = std::sqrt(aRad2 / aDist2);
+  anArcParams[2][0] *= aCoeff;
+  anArcParams[2][1] *= aCoeff;
+
+  // Update last point
+  aPoint = myStorage->getEntity(theArc.point[2]);
+  for (int i = 0; i < 2; i++) {
+    aParam = Slvs_MakeParam(aPoint.param[i], myGroup->getId(),
+        anArcParams[0][i] + anArcParams[2][i]);
+    myStorage->updateParameter(aParam);
+  }
+}
 
 void SketchSolver_ConstraintMirror::adjustConstraint()
 {
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
-  const std::list<ConstraintWrapperPtr>& aConstraints = myStorage->constraint(myBaseConstraint);
-  std::list<ConstraintWrapperPtr>::const_iterator aCIt = aConstraints.begin();
-  for (; aCIt != aConstraints.end(); ++aCIt)
-    if ((*aCIt)->type() == CONSTRAINT_SYMMETRIC)
-      aBuilder->adjustConstraint(*aCIt);
-
-////  AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-////      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
-////  if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) {
-////    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
-////    return;
-////  }
-////  ResultConstructionPtr aRC =
-////      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aMirLineAttr->object());
-////  FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
-////    std::dynamic_pointer_cast<ModelAPI_Feature>(aMirLineAttr->object());
-////  std::map<FeaturePtr, Slvs_hEntity>::iterator aMirLineIter = myFeatureMap.find(aFeature);
-////  if (aMirLineIter == myFeatureMap.end())
-////    return;
-////  Slvs_Entity aMirrorLine = myStorage->getEntity(aMirLineIter->second);
-////
-////  Slvs_Constraint aMirror;
-////  double aStartEnd[4];
-////  for (int i = 0; i < 2; i++) {
-////    Slvs_Entity aPoint = myStorage->getEntity(aMirrorLine.point[i]);
-////    for (int j = 0; j < 2; j++)
-////      aStartEnd[2*i+j] = myStorage->getParameter(aPoint.param[j]).val;
-////  }
-////
-////  // Calculate length of the mirror line and create temporary constraint
-////  double aLength = sqrt((aStartEnd[2] - aStartEnd[0]) * (aStartEnd[2] - aStartEnd[0]) +
-////                        (aStartEnd[3] - aStartEnd[1]) * (aStartEnd[3] - aStartEnd[1]));
-////  if (aLength < tolerance) {
-////    if (myMirrorLineLength < 1.0)
-////      myMirrorLineLength = 1.0;
-////  } else
-////    myMirrorLineLength = aLength;
-////  std::list<Slvs_Constraint> aDist = myStorage->getConstraintsByType(SLVS_C_PT_PT_DISTANCE);
-////  std::list<Slvs_Constraint>::const_iterator aDIt = aDist.begin();
-////  for (; aDIt != aDist.end(); ++aDIt)
-////    if ((aDIt->ptA == aMirrorLine.point[0] && aDIt->ptB == aMirrorLine.point[1]) ||
-////        (aDIt->ptA == aMirrorLine.point[1] && aDIt->ptB == aMirrorLine.point[0]))
-////      break; // length of mirror line is already set
-////  if (aDIt == aDist.end()) {
-////    // check the points of mirror line is not fixed
-////    Slvs_hConstraint aFixed;
-////    if (!myStorage->isPointFixed(aMirrorLine.point[0], aFixed, true) ||
-////        !myStorage->isPointFixed(aMirrorLine.point[1], aFixed, true)) {
-////      // Add length constraint
-////      aMirror = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_PT_DISTANCE,
-////          myGroup->getWorkplaneId(), aLength, aMirrorLine.point[0], aMirrorLine.point[1],
-////          SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-////      aMirror.h = myStorage->addConstraint(aMirror);
-////      myStorage->addTemporaryConstraint(aMirror.h);
-////    }
-////  }
-////
-////  // Search mirror between middle points on the arcs and recompute their coordinates
-////  std::map<Slvs_hEntity, Slvs_hEntity> aPointsOnCircles;
-////  std::list<Slvs_Constraint> aMirrorPonCirc;
-////  std::list<Slvs_Constraint> aPonCirc = myStorage->getConstraintsByType(SLVS_C_PT_ON_CIRCLE);
-////  std::vector<Slvs_hConstraint>::iterator aConstrIter = mySlvsConstraints.begin();
-////  for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) {
-////    aMirror = myStorage->getConstraint(*aConstrIter);
-////    if (aMirror.type != SLVS_C_SYMMETRIC_LINE)
-////      continue;
-////    if (aMirror.entityA != aMirrorLine.h)
-////      continue; // don't update another Mirror constraints
-////    Slvs_Constraint aPonCircA, aPonCircB;
-////    aPonCircA.h = SLVS_E_UNKNOWN;
-////    aPonCircB.h = SLVS_E_UNKNOWN;
-////    std::list<Slvs_Constraint>::iterator aPtIter = aPonCirc.begin();
-////    for (; aPtIter != aPonCirc.end(); aPtIter++) {
-////      if (aMirror.ptA == aPtIter->ptA)
-////        aPonCircA = *aPtIter;
-////      if (aMirror.ptB == aPtIter->ptA)
-////        aPonCircB = *aPtIter;
-////    }
-////    if (aPonCircA.h == SLVS_E_UNKNOWN || aPonCircB.h == SLVS_E_UNKNOWN)
-////      continue;
-////    aMirrorPonCirc.push_back(aMirror);
-////    // Store point IDs to avoid their recalculation twice
-////    aPointsOnCircles[aPonCircA.ptA] = aPonCircA.entityA;
-////    aPointsOnCircles[aPonCircB.ptA] = aPonCircB.entityA;
-////  }
-////
-////  // Recalculate positions of mirroring points
-////  std::list<Slvs_Constraint> aMirrorList = myStorage->getConstraintsByType(SLVS_C_SYMMETRIC_LINE);
-////  std::list<Slvs_Constraint>::iterator aMirIter = aMirrorList.begin();
-////  for (; aMirIter != aMirrorList.end(); aMirIter++) {
-////    if (aMirIter->entityA != aMirrorLine.h)
-////      continue; // don't update another Mirror constraints
-////    if (aPointsOnCircles.find(aMirIter->ptA) != aPointsOnCircles.end())
-////      continue; // Avoid mirroring points on circles
-////    Slvs_Entity aBase = myStorage->getEntity(aMirIter->ptA);
-////    Slvs_Entity aMirror = myStorage->getEntity(aMirIter->ptB);
-////    makeMirrorEntity(aBase, aMirror, aStartEnd);
-////  }
-////
-////  bool aNeedToResolve = myStorage->isNeedToResolve();
-////  for (aMirIter = aMirrorPonCirc.begin(); aMirIter != aMirrorPonCirc.end(); aMirIter++) {
-////    // Make centers of arcs symmetric
-////    Slvs_Entity aBaseArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptA]);
-////    Slvs_Entity aBasePoint = myStorage->getEntity(aBaseArc.point[0]);
-////    Slvs_Entity aMirrorArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptB]);
-////    Slvs_Entity aMirrorPoint = myStorage->getEntity(aMirrorArc.point[0]);
-////    makeMirrorEntity(aBasePoint, aMirrorPoint, aStartEnd);
-////    // Calculate middle point for base arc and mirrored point on mirror arc
-////    aBasePoint = myStorage->getEntity(aMirIter->ptA);
-////    Slvs_Param aParamX = myStorage->getParameter(aBasePoint.param[0]);
-////    Slvs_Param aParamY = myStorage->getParameter(aBasePoint.param[1]);
-////    calculateMiddlePoint(aBaseArc, 0.5, aParamX.val, aParamY.val);
-////    myStorage->updateParameter(aParamX);
-////    myStorage->updateParameter(aParamY);
-////    aMirrorPoint = myStorage->getEntity(aMirIter->ptB);
-////    aParamX = myStorage->getParameter(aMirrorPoint.param[0]);
-////    aParamY = myStorage->getParameter(aMirrorPoint.param[1]);
-////    calculateMiddlePoint(aMirrorArc, 0.5, aParamX.val, aParamY.val);
-////    myStorage->updateParameter(aParamX);
-////    myStorage->updateParameter(aParamY);
-////  }
-////  // Restore previous value to avoid looped recalculations of sketch
-////  myStorage->setNeedToResolve(aNeedToResolve);
+  AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) {
+    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+    return;
+  }
+  ResultConstructionPtr aRC =
+      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aMirLineAttr->object());
+  FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
+    std::dynamic_pointer_cast<ModelAPI_Feature>(aMirLineAttr->object());
+  std::map<FeaturePtr, Slvs_hEntity>::iterator aMirLineIter = myFeatureMap.find(aFeature);
+  if (aMirLineIter == myFeatureMap.end())
+    return;
+  Slvs_Entity aMirrorLine = myStorage->getEntity(aMirLineIter->second);
+
+  Slvs_Constraint aMirror;
+  double aStartEnd[4];
+  for (int i = 0; i < 2; i++) {
+    Slvs_Entity aPoint = myStorage->getEntity(aMirrorLine.point[i]);
+    for (int j = 0; j < 2; j++)
+      aStartEnd[2*i+j] = myStorage->getParameter(aPoint.param[j]).val;
+  }
+
+  // Calculate length of the mirror line and create temporary constraint
+  double aLength = sqrt((aStartEnd[2] - aStartEnd[0]) * (aStartEnd[2] - aStartEnd[0]) +
+                        (aStartEnd[3] - aStartEnd[1]) * (aStartEnd[3] - aStartEnd[1]));
+  if (aLength < tolerance) {
+    if (myMirrorLineLength < 1.0)
+      myMirrorLineLength = 1.0;
+  } else
+    myMirrorLineLength = aLength;
+  std::list<Slvs_Constraint> aDist = myStorage->getConstraintsByType(SLVS_C_PT_PT_DISTANCE);
+  std::list<Slvs_Constraint>::const_iterator aDIt = aDist.begin();
+  for (; aDIt != aDist.end(); ++aDIt)
+    if ((aDIt->ptA == aMirrorLine.point[0] && aDIt->ptB == aMirrorLine.point[1]) ||
+        (aDIt->ptA == aMirrorLine.point[1] && aDIt->ptB == aMirrorLine.point[0]))
+      break; // length of mirror line is already set
+  if (aDIt == aDist.end()) {
+    // check the points of mirror line is not fixed
+    Slvs_hConstraint aFixed;
+    if (!myStorage->isPointFixed(aMirrorLine.point[0], aFixed, true) ||
+        !myStorage->isPointFixed(aMirrorLine.point[1], aFixed, true)) {
+      // Add length constraint
+      aMirror = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_PT_DISTANCE,
+          myGroup->getWorkplaneId(), aLength, aMirrorLine.point[0], aMirrorLine.point[1],
+          SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+      aMirror.h = myStorage->addConstraint(aMirror);
+      myStorage->addTemporaryConstraint(aMirror.h);
+    }
+  }
+
+  // Search mirror between middle points on the arcs and recompute their coordinates
+  std::map<Slvs_hEntity, Slvs_hEntity> aPointsOnCircles;
+  std::list<Slvs_Constraint> aMirrorPonCirc;
+  std::list<Slvs_Constraint> aPonCirc = myStorage->getConstraintsByType(SLVS_C_PT_ON_CIRCLE);
+  std::vector<Slvs_hConstraint>::iterator aConstrIter = mySlvsConstraints.begin();
+  for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) {
+    aMirror = myStorage->getConstraint(*aConstrIter);
+    if (aMirror.type != SLVS_C_SYMMETRIC_LINE)
+      continue;
+    if (aMirror.entityA != aMirrorLine.h)
+      continue; // don't update another Mirror constraints
+    Slvs_Constraint aPonCircA, aPonCircB;
+    aPonCircA.h = SLVS_E_UNKNOWN;
+    aPonCircB.h = SLVS_E_UNKNOWN;
+    std::list<Slvs_Constraint>::iterator aPtIter = aPonCirc.begin();
+    for (; aPtIter != aPonCirc.end(); aPtIter++) {
+      if (aMirror.ptA == aPtIter->ptA)
+        aPonCircA = *aPtIter;
+      if (aMirror.ptB == aPtIter->ptA)
+        aPonCircB = *aPtIter;
+    }
+    if (aPonCircA.h == SLVS_E_UNKNOWN || aPonCircB.h == SLVS_E_UNKNOWN)
+      continue;
+    aMirrorPonCirc.push_back(aMirror);
+    // Store point IDs to avoid their recalculation twice
+    aPointsOnCircles[aPonCircA.ptA] = aPonCircA.entityA;
+    aPointsOnCircles[aPonCircB.ptA] = aPonCircB.entityA;
+  }
+
+  // Recalculate positions of mirroring points
+  std::list<Slvs_Constraint> aMirrorList = myStorage->getConstraintsByType(SLVS_C_SYMMETRIC_LINE);
+  std::list<Slvs_Constraint>::iterator aMirIter = aMirrorList.begin();
+  for (; aMirIter != aMirrorList.end(); aMirIter++) {
+    if (aMirIter->entityA != aMirrorLine.h)
+      continue; // don't update another Mirror constraints
+    if (aPointsOnCircles.find(aMirIter->ptA) != aPointsOnCircles.end())
+      continue; // Avoid mirroring points on circles
+    Slvs_Entity aBase = myStorage->getEntity(aMirIter->ptA);
+    Slvs_Entity aMirror = myStorage->getEntity(aMirIter->ptB);
+    makeMirrorEntity(aBase, aMirror, aStartEnd);
+  }
+
+  bool aNeedToResolve = myStorage->isNeedToResolve();
+  for (aMirIter = aMirrorPonCirc.begin(); aMirIter != aMirrorPonCirc.end(); aMirIter++) {
+    // Make centers of arcs symmetric
+    Slvs_Entity aBaseArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptA]);
+    Slvs_Entity aBasePoint = myStorage->getEntity(aBaseArc.point[0]);
+    Slvs_Entity aMirrorArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptB]);
+    Slvs_Entity aMirrorPoint = myStorage->getEntity(aMirrorArc.point[0]);
+    makeMirrorEntity(aBasePoint, aMirrorPoint, aStartEnd);
+    // Calculate middle point for base arc and mirrored point on mirror arc
+    aBasePoint = myStorage->getEntity(aMirIter->ptA);
+    Slvs_Param aParamX = myStorage->getParameter(aBasePoint.param[0]);
+    Slvs_Param aParamY = myStorage->getParameter(aBasePoint.param[1]);
+    calculateMiddlePoint(aBaseArc, 0.5, aParamX.val, aParamY.val);
+    myStorage->updateParameter(aParamX);
+    myStorage->updateParameter(aParamY);
+    aMirrorPoint = myStorage->getEntity(aMirIter->ptB);
+    aParamX = myStorage->getParameter(aMirrorPoint.param[0]);
+    aParamY = myStorage->getParameter(aMirrorPoint.param[1]);
+    calculateMiddlePoint(aMirrorArc, 0.5, aParamX.val, aParamY.val);
+    myStorage->updateParameter(aParamX);
+    myStorage->updateParameter(aParamY);
+  }
+  // Restore previous value to avoid looped recalculations of sketch
+  myStorage->setNeedToResolve(aNeedToResolve);
 }
index 30d72e781bfa3084508cd1b5f084d9e1bfc94e15..f6aa365eb616810b736c30d501cd36644449a985 100644 (file)
@@ -20,57 +20,60 @@ public:
   /// Constructor based on SketchPlugin constraint
   SketchSolver_ConstraintMirror(ConstraintPtr theConstraint) :
       SketchSolver_Constraint(theConstraint),
-      myNumberOfObjects(0)////,
-////      myMirrorLineLength(0.0)
+      myNumberOfObjects(0),
+      myMirrorLineLength(0.0)
   {}
 
+  virtual int getType() const
+  { return SLVS_C_SYMMETRIC_LINE; }
+
   /// \brief Update constraint
-  virtual void update();
+  virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
 
-////  /// \brief Tries to remove constraint
-////  /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
-////  virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+  /// \brief Tries to remove constraint
+  /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+  virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
 
 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
+  /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
   /// \param[out] theValue      numerical characteristic of constraint (e.g. distance)
   /// \param[out] theAttributes list of attributes to be filled
-  virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes)
+  virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes)
   { /* do nothing here */ }
 
-////  /// \brief Verify the attributes of constraint are changed (and constraint need to rebuild)
-////  /// \param[in] theConstraint constraint, which attributes should be checked (if NULL, the myBaseConstraint is used)
-////  /// \return \c true if some attributes are changed
-////  virtual bool checkAttributesChanged(ConstraintPtr theConstraint);
+  /// \brief Verify the attributes of constraint are changed (and constraint need to rebuild)
+  /// \param[in] theConstraint constraint, which attributes should be checked (if NULL, the myBaseConstraint is used)
+  /// \return \c true if some attributes are changed
+  virtual bool checkAttributesChanged(ConstraintPtr theConstraint);
 
   /// \brief Generate list of entities of mirror constraint
   /// \param[out] theMirrorLine     entity corresponding to mirror line
   /// \param[out] theBaseEntities   list of entities to mirror
   /// \param[out] theMirrorEntities list of mirrored entities
-  void getAttributes(EntityWrapperPtr& theMirrorLine,
-                     std::vector<EntityWrapperPtr>& theBaseEntities,
-                     std::vector<EntityWrapperPtr>& theMirrorEntities);
+  void getAttributes(Slvs_Entity& theMirrorLine,
+                     std::vector<Slvs_Entity>& theBaseEntities,
+                     std::vector<Slvs_Entity>& theMirrorEntities);
 
   /// \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();
 
 private:
-////  /// \brief Change parameters of entities to be symmetric relative a line,
-////  ///        given by array of parameters (coordinates of first and last points)
-////  void makeMirrorEntity(const Slvs_Entity& theBase,
-////                        const Slvs_Entity& theMirror,
-////                        const double theMirrorLine[]) const;
-////
-////  /// \brief Precisely update last point to be on arc
-////  void adjustArcPoints(const Slvs_Entity& theArc) const;
+  /// \brief Change parameters of entities to be symmetric relative a line,
+  ///        given by array of parameters (coordinates of first and last points)
+  void makeMirrorEntity(const Slvs_Entity& theBase,
+                        const Slvs_Entity& theMirror,
+                        const double theMirrorLine[]) const;
+
+  /// \brief Precisely update last point to be on arc
+  void adjustArcPoints(const Slvs_Entity& theArc) const;
 
 private:
   size_t myNumberOfObjects;  ///< number of previously mirrored objects
-////  double myMirrorLineLength; ///< length of mirror line (should be always greater than 0)
+  double myMirrorLineLength; ///< length of mirror line (should be always greater than 0)
 };
 
 #endif
index 85542cb42c7cad8c36e86a18530dc18c8479da23..b97d1a754fde25fbc659b8bfa8e0e771e1502c48 100644 (file)
 #include <SketchSolver_ConstraintMovement.h>
 #include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
+#include <SketchSolver_Group.h>
 
 #include <SketchPlugin_Arc.h>
 #include <SketchPlugin_Circle.h>
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_Point.h>
 
-#include <GeomDataAPI_Point2D.h>
-
+SketchSolver_ConstraintMovement::SketchSolver_ConstraintMovement(FeaturePtr theFeature)
+  : SketchSolver_ConstraintRigid(theFeature)
+{
+  process();
+}
 
 void SketchSolver_ConstraintMovement::process()
 {
   cleanErrorMsg();
-  if (!myBaseFeature || !myStorage || myGroupID == GID_UNKNOWN) {
-    // Not enough parameters are initialized
+  if (!myBaseFeature || !myStorage || myGroup == 0) {
+    /// TODO: Put error message here
     return;
   }
+  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+    update(myBaseConstraint);
 
-  ParameterWrapperPtr aValue;
-  getAttributes(aValue, myMovedEntities);
-  if (!myErrorMsg.empty() || myMovedEntities.empty()) {
-    // Nothing to move, clear the feature to avoid changing its group
-    // after removing the Movement constraint.
-    myBaseFeature = FeaturePtr();
+  double aValue;
+  std::vector<Slvs_hEntity> anEntities;
+  bool isFullyMoved;
+  getAttributes(aValue, anEntities, isFullyMoved);
+  if (!myErrorMsg.empty() || (myFeatureMap.empty() && myAttributeMap.empty()))
     return;
-  }
 
-  std::vector<EntityWrapperPtr>::iterator anEntIt = myMovedEntities.begin();
-  for (; anEntIt != myMovedEntities.end(); ++anEntIt)
-    fixFeature(*anEntIt);
+  if (isFullyMoved)
+    fixFeature();
+  else {
+    std::vector<Slvs_hEntity>::iterator anEntIt = anEntities.begin();
+    for (; anEntIt != anEntities.end(); ++anEntIt)
+      fixPoint(*anEntIt);
+  }
 }
 
 
-static std::list<EntityWrapperPtr> movedEntities(
-    EntityWrapperPtr theOld, StoragePtr theOldStorage,
-    EntityWrapperPtr theNew, StoragePtr theNewStorage)
+void SketchSolver_ConstraintMovement::getAttributes(
+    double& theValue,
+    std::vector<Slvs_hEntity>& theAttributes,
+    bool& theIsFullyMoved)
 {
-  bool isFullyMoved = true;
-  std::list<EntityWrapperPtr> aMoved;
-  if (theOld->isEqual(theNew))
-    return aMoved;
-
-  std::list<EntityWrapperPtr> anOldSubs = theOld->subEntities();
-  std::list<EntityWrapperPtr> aNewSubs = theNew->subEntities();
-  std::list<EntityWrapperPtr>::const_iterator anOldIt = anOldSubs.begin();
-  std::list<EntityWrapperPtr>::const_iterator aNewIt = aNewSubs.begin();
-  for (; anOldIt != anOldSubs.end() && aNewIt != aNewSubs.end(); ++anOldIt, ++aNewIt) {
-    std::list<EntityWrapperPtr> aMovedSubs = movedEntities(
-        *anOldIt, theOldStorage, *aNewIt, theNewStorage);
-    if (aMovedSubs.size() != 1 || aMovedSubs.front() != *anOldIt)
-      isFullyMoved = false;
-    aMoved.insert(aMoved.end(), aMovedSubs.begin(), aMovedSubs.end());
+  bool isComplexFeature = false;
+  theValue = 0.0;
+  theIsFullyMoved = true;
+  int aType = SLVS_E_UNKNOWN; // type of created entity
+  Slvs_hEntity anEntityID = SLVS_E_UNKNOWN;
+  Slvs_hEntity anEntMaxID = myStorage->entityMaxID();
+  anEntityID = myGroup->getFeatureId(myBaseFeature);
+  if (anEntityID == SLVS_E_UNKNOWN) {
+    anEntityID = changeEntity(myBaseFeature, aType);
+    if (anEntityID == SLVS_E_UNKNOWN) {
+      myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+      return;
+    }
+
+    // Check the entity is complex
+    Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
+    if (anEntity.point[0] != SLVS_E_UNKNOWN)
+      isComplexFeature = true;
+    else // simple entity
+      theAttributes.push_back(anEntityID);
   }
-  if (isFullyMoved) {
-    aMoved.clear();
-    aMoved.push_back(theOld);
+  else {
+     myFeatureMap[myBaseFeature] = anEntityID;
+     isComplexFeature = true;
+  }
+
+  int aNbOutOfGroup = 0;
+  if (isComplexFeature) {
+     std::list<AttributePtr> aPoints =
+        myBaseFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+     std::list<AttributePtr>::iterator anIt = aPoints.begin();
+     for (; anIt != aPoints.end(); ++anIt) {
+       std::map<AttributePtr, Slvs_hEntity>::const_iterator aFound = myAttributeMap.find(*anIt);
+       Slvs_hEntity anAttr = aFound != myAttributeMap.end() ?
+                             aFound->second : myGroup->getAttributeId(*anIt);
+       Slvs_Entity anAttrEnt = myStorage->getEntity(anAttr);
+
+       // Check the attribute changes coordinates
+       std::shared_ptr<GeomDataAPI_Point2D> aPt =
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt);
+       // Check the entity is not lying in the current group or it is not moved
+       if (anAttr == SLVS_E_UNKNOWN || anAttrEnt.group != myGroup->getId() ||
+           (anAttr <= anEntMaxID && !isMoved(aPt, anAttrEnt))) {
+         if (anAttrEnt.group == SLVS_G_OUTOFGROUP)
+           ++aNbOutOfGroup;
+         theIsFullyMoved = false;
+       }
+       else {
+         theAttributes.push_back(anAttr);
+         // update point coordinates
+         Slvs_Entity anAttrEnt = myStorage->getEntity(anAttr);
+         double aNewPos[2] = {aPt->x(), aPt->y()};
+         for (int i = 0; i < 2; i++) {
+           Slvs_Param aParam = myStorage->getParameter(anAttrEnt.param[i]);
+           aParam.val = aNewPos[i];
+           myStorage->updateParameter(aParam);
+         }
+       }
+     }
+  }
+
+  // Additional checking, which leads to fix whole feature, if it has fixed points
+  if (!theIsFullyMoved) {
+    Slvs_Entity aFeature = myStorage->getEntity(anEntityID);
+    int aNbPoints = 4;
+    while (aNbPoints > 0 && aFeature.point[aNbPoints-1] == SLVS_E_UNKNOWN)
+      --aNbPoints;
+    if (aNbPoints == aNbOutOfGroup + (int)theAttributes.size()) {
+      theIsFullyMoved = true;
+      return;
+    }
+  }
+
+  // Leave only points which are used in constraints
+  if (myStorage->isUsedByConstraints(anEntityID))
+    return;
+  std::vector<Slvs_hEntity>::iterator anIt = theAttributes.begin();
+  while (anIt != theAttributes.end()) {
+    if (myStorage->isUsedByConstraints(*anIt))
+      ++anIt;
+    else {
+      int aShift = anIt - theAttributes.begin();
+      theAttributes.erase(anIt);
+      anIt = theAttributes.begin() + aShift;
+    }
   }
-  return aMoved;
 }
 
+bool SketchSolver_ConstraintMovement::isMoved(
+    std::shared_ptr<GeomDataAPI_Point2D> thePoint, const Slvs_Entity& theEntity)
+{
+  double aDeltaX = myStorage->getParameter(theEntity.param[0]).val;
+  double aDeltaY = myStorage->getParameter(theEntity.param[1]).val;
+  aDeltaX -= thePoint->x();
+  aDeltaY -= thePoint->y();
+  return aDeltaX * aDeltaX + aDeltaY * aDeltaY >= tolerance * tolerance;
+}
 
-void SketchSolver_ConstraintMovement::getAttributes(
-    ParameterWrapperPtr& theValue,
-    std::vector<EntityWrapperPtr>& theAttributes)
+void SketchSolver_ConstraintMovement::fixFeature()
 {
-  // There will be build entities, according to the fixed feature, in the separate storage
-  // to check whether any point is moved
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-  StoragePtr anOtherStorage = aBuilder->createStorage(myGroupID);
-  anOtherStorage->setSketch(myStorage->sketch());
-  if (!anOtherStorage->update(myBaseFeature, myGroupID))
-    return;
-  EntityWrapperPtr aNewEntity = anOtherStorage->entity(myBaseFeature);
-  EntityWrapperPtr anOldEntity = myStorage->entity(myBaseFeature);
+  Slvs_hEntity anEntID = fixedEntity();
 
-  std::list<EntityWrapperPtr> aMoved;
-  if (aNewEntity && anOldEntity)
-    aMoved = movedEntities(anOldEntity, myStorage, aNewEntity, anOtherStorage);
-  else {
-    // get attributes moved
-    std::list<AttributePtr> anAttrList =
-        myBaseFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
-    std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
-    for (; anIt != anAttrList.end(); ++anIt) {
-      aNewEntity = anOtherStorage->entity(*anIt);
-      anOldEntity = myStorage->entity(*anIt);
-      if (!aNewEntity || !anOldEntity)
-        continue;
-      std::list<EntityWrapperPtr> aMovedAttr = movedEntities(
-          anOldEntity, myStorage, aNewEntity, anOtherStorage);
-      aMoved.insert(aMoved.end(), aMovedAttr.begin(), aMovedAttr.end());
-    }
+  std::string aKind;
+  std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFIt = myFeatureMap.begin();
+  for (; aFIt != myFeatureMap.end() && aKind.empty(); ++aFIt)
+    if (aFIt->second == anEntID)
+      aKind = aFIt->first->getKind();
+  std::map<AttributePtr, Slvs_hEntity>::const_iterator anAtIt = myAttributeMap.begin();
+  for (; anAtIt != myAttributeMap.end() && aKind.empty(); ++anAtIt)
+    if (anAtIt->second == anEntID)
+      aKind = anAtIt->first->attributeType();
+
+  if (aKind == SketchPlugin_Line::ID()) {
+    Slvs_Entity aLine = myStorage->getEntity(anEntID);
+    fixLine(aLine);
+  }
+  else if (aKind == SketchPlugin_Arc::ID()) {
+    Slvs_Entity anArc = myStorage->getEntity(anEntID);
+    fixArc(anArc);
+  }
+  else if (aKind == SketchPlugin_Circle::ID()) {
+    Slvs_Entity aCirc = myStorage->getEntity(anEntID);
+    fixCircle(aCirc);
+  }
+  else if (aKind == SketchPlugin_Point::ID() || aKind == GeomDataAPI_Point2D::typeId()) {
+    fixPoint(anEntID);
   }
-  theAttributes.clear();
-  theAttributes.insert(theAttributes.begin(), aMoved.begin(), aMoved.end());
 }
+
index ba119beaadf2f6bc7cab53469949838d3b9a19c3..dbec1b020e25ea06bf4a910cb4431c84f5417e9d 100644 (file)
@@ -8,25 +8,25 @@
 #define SketchSolver_ConstraintMovement_H_
 
 #include "SketchSolver.h"
-#include <SketchSolver_ConstraintFixed.h>
+#include <SketchSolver_ConstraintRigid.h>
+
+#include <GeomDataAPI_Point2D.h>
 
 /** \class   SketchSolver_ConstraintMovement
  *  \ingroup Plugins
- *  \brief   Stores data to the Fixed constraint for the moved feature only
+ *  \brief   Stores data of Rigid (Fixed) constraint for the moved feature only
  */
-class SketchSolver_ConstraintMovement : public SketchSolver_ConstraintFixed
+class SketchSolver_ConstraintMovement : public SketchSolver_ConstraintRigid
 {
 private:
   /// Creates constraint to manage the given constraint from plugin
   SketchSolver_ConstraintMovement(ConstraintPtr theConstraint)
-    : SketchSolver_ConstraintFixed(theConstraint)
+    : SketchSolver_ConstraintRigid(theConstraint)
   {}
 
 public:
   /// Creates temporary constraint based on feature
-  SketchSolver_ConstraintMovement(FeaturePtr theFeature)
-    : SketchSolver_ConstraintFixed(theFeature)
-  {}
+  SketchSolver_ConstraintMovement(FeaturePtr theFeature);
 
 protected:
   /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
@@ -34,11 +34,16 @@ protected:
 
   /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
   /// \param[out] theValue        numerical characteristic of constraint (e.g. distance)
-  /// \param[out] theAttributes   list of attributes to be filled (list of moved entities or attributes)
-  virtual void getAttributes(ParameterWrapperPtr& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+  /// \param[out] theAttributes   list of attributes to be filled
+  /// \param[out] theIsFullyMoved shows that the feature is moved, in other case only one point of the feature is shifted
+  virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes, bool& theIsFullyMoved);
+
+  /// \brief Fixed feature basing on its type
+  virtual void fixFeature();
 
 private:
-  std::vector<EntityWrapperPtr> myMovedEntities; ///< list of entities that are moved
+  /// \brief Check the coordinates of point are differ than coordinates of correponding SolveSpace entity
+  bool isMoved(std::shared_ptr<GeomDataAPI_Point2D> thePoint, const Slvs_Entity& theEntity);
 };
 
 #endif
index 3c664be9c32fa8b3a09a5a47ff91dffd99db9df3..5be0d2fe596ce718db4c4217312f6c009b6d74f9 100644 (file)
 #include <SketchSolver_ConstraintMulti.h>
+#include <SketchSolver_Group.h>
 #include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
 
-////#include <SketchPlugin_Arc.h>
-////
-////#include <ModelAPI_AttributeDouble.h>
+#include <SketchPlugin_Arc.h>
+
+#include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_AttributeRefList.h>
-////#include <ModelAPI_ResultConstruction.h>
-////
-////#include <GeomAPI_Dir2d.h>
-////#include <GeomAPI_XY.h>
-////
-////#include <math.h>
-
-void SketchSolver_ConstraintMulti::getEntitiesAndCopies(
-    std::list< std::list<EntityWrapperPtr> >& theEntAndCopies)
+#include <ModelAPI_ResultConstruction.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+
+#include <math.h>
+
+void SketchSolver_ConstraintMulti::processEntities(const std::vector< std::vector<Slvs_hEntity> >& theEntAndCopies)
 {
-  DataPtr aData = myBaseConstraint->data();
-
-  // Lists of objects and number of copies
-  AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-      aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
-  myNumberOfObjects = anInitialRefList->size();
-  myNumberOfCopies = aData->integer(nameNbObjects())->value() - 1;
-  if (myNumberOfCopies <= 0)
-    return;
+  // Keep all objects unchanged (only initial object may be changed by user)
+  myCircsAndCopies.clear();
+  std::vector<std::vector<Slvs_hEntity> >::const_iterator anEntIt = theEntAndCopies.begin();
+  std::vector<Slvs_hEntity>::const_iterator aCpIt;
+  for (; anEntIt != theEntAndCopies.end(); ++anEntIt) {
+    std::vector<Slvs_hEntity> aCircs;
+    aCpIt = anEntIt->begin();
+    // Obtain initial points
+    Slvs_Entity anInitial = myStorage->getEntity(*aCpIt);
+    if (anInitial.type == SLVS_E_POINT_IN_2D || anInitial.type == SLVS_E_POINT_IN_3D)
+      myInitialPoints.insert(anInitial.h);
+    else {
+      for (int i = 0; i < 4 && anInitial.point[i] != SLVS_E_UNKNOWN; i++)
+        myInitialPoints.insert(anInitial.point[i]);
+    }
 
-  AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-      aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
-  if (!aRefList || aRefList->size() == 0) {
-    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-    return;
-  }
+    // Fix the copies
+    for (++aCpIt; aCpIt != anEntIt->end(); ++aCpIt) {
+      const Slvs_Entity& anEntity = myStorage->getEntity(*aCpIt);
+      std::vector<Slvs_hConstraint> aNewConstr;
+      if (anEntity.type == SLVS_E_CIRCLE) {
+        aCircs.push_back(anEntity.distance);
+        // for circles we fix only center
+        aNewConstr = myStorage->fixEntity(anEntity.point[0]);
+      } else
+        aNewConstr = myStorage->fixEntity(*aCpIt);
+      if (anEntity.type == SLVS_E_ARC_OF_CIRCLE)
+        aCircs.push_back(anEntity.h);
+      mySlvsConstraints.insert(mySlvsConstraints.end(), aNewConstr.begin(), aNewConstr.end());
+    }
 
-  FeaturePtr aFeature;
-  std::list<EntityWrapperPtr> anEntities; // list of transformed entities
-  std::list<ObjectPtr> anObjectList = aRefList->list();
-  std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
-  while (anObjIt != anObjectList.end()) {
-    anEntities.clear();
-    for (int i = 0; i <= myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
-      aFeature = ModelAPI_Feature::feature(*anObjIt);
-      if (!aFeature)
-        continue;
-
-      myStorage->update(aFeature);
-      anEntities.push_back(myStorage->entity(aFeature));
+    if (!aCircs.empty()) {
+      if (anInitial.type == SLVS_E_CIRCLE)
+        aCircs.insert(aCircs.begin(), anInitial.distance);
+      else
+        aCircs.insert(aCircs.begin(), anInitial.h);
+      myCircsAndCopies.push_back(aCircs);
     }
-    if (!anEntities.empty())
-      theEntAndCopies.push_back(anEntities);
   }
 }
 
-
-////void SketchSolver_ConstraintMulti::processEntities(const std::vector< std::vector<Slvs_hEntity> >& theEntAndCopies)
-////{
-////  // Keep all objects unchanged (only initial object may be changed by user)
-////  myCircsAndCopies.clear();
-////  std::vector<std::vector<Slvs_hEntity> >::const_iterator anEntIt = theEntAndCopies.begin();
-////  std::vector<Slvs_hEntity>::const_iterator aCpIt;
-////  for (; anEntIt != theEntAndCopies.end(); ++anEntIt) {
-////    std::vector<Slvs_hEntity> aCircs;
-////    aCpIt = anEntIt->begin();
-////    // Obtain initial points
-////    Slvs_Entity anInitial = myStorage->getEntity(*aCpIt);
-////    if (anInitial.type == SLVS_E_POINT_IN_2D || anInitial.type == SLVS_E_POINT_IN_3D)
-////      myInitialPoints.insert(anInitial.h);
-////    else {
-////      for (int i = 0; i < 4 && anInitial.point[i] != SLVS_E_UNKNOWN; i++)
-////        myInitialPoints.insert(anInitial.point[i]);
-////    }
-////
-////    // Fix the copies
-////    for (++aCpIt; aCpIt != anEntIt->end(); ++aCpIt) {
-////      const Slvs_Entity& anEntity = myStorage->getEntity(*aCpIt);
-////      std::vector<Slvs_hConstraint> aNewConstr;
-////      if (anEntity.type == SLVS_E_CIRCLE) {
-////        aCircs.push_back(anEntity.distance);
-////        // for circles we fix only center
-////        aNewConstr = myStorage->fixEntity(anEntity.point[0]);
-////      } else
-////        aNewConstr = myStorage->fixEntity(*aCpIt);
-////      if (anEntity.type == SLVS_E_ARC_OF_CIRCLE)
-////        aCircs.push_back(anEntity.h);
-////      mySlvsConstraints.insert(mySlvsConstraints.end(), aNewConstr.begin(), aNewConstr.end());
-////    }
-////
-////    if (!aCircs.empty()) {
-////      if (anInitial.type == SLVS_E_CIRCLE)
-////        aCircs.insert(aCircs.begin(), anInitial.distance);
-////      else
-////        aCircs.insert(aCircs.begin(), anInitial.h);
-////      myCircsAndCopies.push_back(aCircs);
-////    }
-////  }
-////}
-
-void SketchSolver_ConstraintMulti::update(bool isForce)
+void SketchSolver_ConstraintMulti::update(ConstraintPtr theConstraint)
 {
   cleanErrorMsg();
-  AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
-  AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
-  if (anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies) {
-    remove();
-    process();
-    return;
+  if (!theConstraint || theConstraint == myBaseConstraint) {
+    AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+        myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+    AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
+    if (anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies) {
+      remove(myBaseConstraint);
+      process();
+      return;
+    }
   }
 
-  // update derivative object
   updateLocal();
-  if (isForce)
-    myAdjusted = false;
-  // update parent object
   SketchSolver_Constraint::update();
 }
 
-////bool SketchSolver_ConstraintMulti::remove()
-////{
-////  cleanErrorMsg();
-////  if (theConstraint && theConstraint != myBaseConstraint)
-////    return false;
-////  bool isFullyRemoved = true;
-////  std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
-////  for (; aCIter != mySlvsConstraints.end(); aCIter++)
-////   isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
-////  mySlvsConstraints.clear();
-////
-////  std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
-////  for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
-////    myStorage->removeEntity(aFeatIt->second);
-////  myStorage->removeUnusedEntities();
-////
-////  std::map<FeaturePtr, Slvs_hEntity> aFeatureMapCopy = myFeatureMap;
-////
-////  if (isFullyRemoved) {
-////    myFeatureMap.clear();
-////    myAttributeMap.clear();
-////    myValueMap.clear();
-////  } else
-////    cleanRemovedEntities();
-////
-////  // Restore initial features
-////  std::map<FeaturePtr, Slvs_hEntity>::iterator aFIter = aFeatureMapCopy.begin();
-////  for (; aFIter != aFeatureMapCopy.end(); ++aFIter)
-////  {
-////    if (myFeatureMap.find(aFIter->first) != myFeatureMap.end())
-////      continue; // the feature was not removed
-////    Slvs_hEntity anEntity = myGroup->getFeatureId(aFIter->first);
-////    if (anEntity != SLVS_E_UNKNOWN)
-////      myFeatureMap[aFIter->first] = anEntity;
-////  }
-////
-////  // Clear list of rotated points
-////  myPointsAndCopies.clear();
-////  myInitialPoints.clear();
-////
-////  return true;
-////}
-
-////void SketchSolver_ConstraintMulti::addFeature(FeaturePtr theFeature)
-////{
-////  SketchSolver_Constraint::addFeature(theFeature);
-////
-////  std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.find(theFeature);
-////  if (aFeatIt == myFeatureMap.end())
-////    return;
-////
-////  // store list of points of the feature
-////  const Slvs_Entity& theEntity = myStorage->getEntity(aFeatIt->second);
-////  for (int i = 0; i < 4; i++)
-////    if (theEntity.point[i] != SLVS_E_UNKNOWN)
-////      myPointsJustUpdated.insert(theEntity.point[i]);
-////}
+bool SketchSolver_ConstraintMulti::remove(ConstraintPtr theConstraint)
+{
+  cleanErrorMsg();
+  if (theConstraint && theConstraint != myBaseConstraint)
+    return false;
+  bool isFullyRemoved = true;
+  std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
+  for (; aCIter != mySlvsConstraints.end(); aCIter++)
+   isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
+  mySlvsConstraints.clear();
+
+  std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
+  for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
+    myStorage->removeEntity(aFeatIt->second);
+  myStorage->removeUnusedEntities();
+
+  std::map<FeaturePtr, Slvs_hEntity> aFeatureMapCopy = myFeatureMap;
+
+  if (isFullyRemoved) {
+    myFeatureMap.clear();
+    myAttributeMap.clear();
+    myValueMap.clear();
+  } else
+    cleanRemovedEntities();
+
+  // Restore initial features
+  std::map<FeaturePtr, Slvs_hEntity>::iterator aFIter = aFeatureMapCopy.begin();
+  for (; aFIter != aFeatureMapCopy.end(); ++aFIter)
+  {
+    if (myFeatureMap.find(aFIter->first) != myFeatureMap.end())
+      continue; // the feature was not removed
+    Slvs_hEntity anEntity = myGroup->getFeatureId(aFIter->first);
+    if (anEntity != SLVS_E_UNKNOWN)
+      myFeatureMap[aFIter->first] = anEntity;
+  }
+
+  // Clear list of rotated points
+  myPointsAndCopies.clear();
+  myInitialPoints.clear();
+
+  return true;
+}
+
+void SketchSolver_ConstraintMulti::addFeature(FeaturePtr theFeature)
+{
+  SketchSolver_Constraint::addFeature(theFeature);
+
+  std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.find(theFeature);
+  if (aFeatIt == myFeatureMap.end())
+    return;
+
+  // store list of points of the feature
+  const Slvs_Entity& theEntity = myStorage->getEntity(aFeatIt->second);
+  for (int i = 0; i < 4; i++)
+    if (theEntity.point[i] != SLVS_E_UNKNOWN)
+      myPointsJustUpdated.insert(theEntity.point[i]);
+}
 
 void SketchSolver_ConstraintMulti::adjustConstraint()
 {
   if (myAdjusted)
     return; // constraint already adjusted, don't do it once again
 
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
-  const std::list<ConstraintWrapperPtr>& aConstraints = myStorage->constraint(myBaseConstraint);
-  std::list<ConstraintWrapperPtr>::const_iterator anIt = aConstraints.begin();
-  for (; anIt != aConstraints.end(); ++anIt)
-    aBuilder->adjustConstraint(*anIt);
-  myStorage->addConstraint(myBaseConstraint, aConstraints);
-
-////  double aRelCoord[2]  = {0.0, 0.0}; // relative coordinates of point
-////  double anAbsCoord[2] = {0.0, 0.0}; // absolute coordinates of point
-////
-////  std::list<Slvs_Constraint> aCoincident = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT);
-////  std::list<Slvs_Constraint>::const_iterator aCoIt;
-////
-////  // Update positions of all points to satisfy angles
-////  std::vector< std::vector<Slvs_hEntity> >::const_iterator aPointsIter = myPointsAndCopies.begin();
-////  std::vector<Slvs_hEntity>::const_iterator aCopyIter;
-////  for (; aPointsIter != myPointsAndCopies.end(); ++aPointsIter) {
-////    aCopyIter = aPointsIter->begin();
-////    const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter);
-////    for (int i = 0; i < 2; i++)
-////      anAbsCoord[i] = myStorage->getParameter(anInitial.param[i]).val;
-////    getRelative(anAbsCoord[0], anAbsCoord[1], aRelCoord[0], aRelCoord[1]);
-////
-////    // if the point is coincident with another one which is temporary fixed (moved by user),
-////    // we will update its position correspondingly
-////    Slvs_hConstraint aFixed;
-////    for (aCoIt = aCoincident.begin(); aCoIt != aCoincident.end(); ++aCoIt) {
-////      if ((aCoIt->ptA == anInitial.h && myInitialPoints.find(aCoIt->ptB) != myInitialPoints.end()) ||
-////          (aCoIt->ptB == anInitial.h && myInitialPoints.find(aCoIt->ptA) != myInitialPoints.end())) {
-////        Slvs_hEntity anOtherId = aCoIt->ptA == anInitial.h ? aCoIt->ptB : aCoIt->ptA;
-////        if (!myStorage->isTemporary(aFixed) &&
-////            myPointsJustUpdated.find(anOtherId) == myPointsJustUpdated.end())
-////          continue; // nothing to change
-////
-////        const Slvs_Entity& anOtherPnt = myStorage->getEntity(anOtherId);
-////        for (int i = 0; i < 2; i++) {
-////          Slvs_Param anInitParam = myStorage->getParameter(anInitial.param[i]);
-////          const Slvs_Param& anOtherParam = myStorage->getParameter(anOtherPnt.param[i]);
-////          anInitParam.val = anOtherParam.val;
-////          myStorage->updateParameter(anInitParam);
-////          anAbsCoord[i] = anOtherParam.val;
-////        }
-////        getRelative(anAbsCoord[0], anAbsCoord[1], aRelCoord[0], aRelCoord[1]);
-////      }
-////    }
-////
-////    // update copied points
-////    aCopyIter = aPointsIter->begin();
-////    for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) {
-////      // transform coordinates
-////      transformRelative(aRelCoord[0], aRelCoord[1]);
-////      getAbsolute(aRelCoord[0], aRelCoord[1], anAbsCoord[0], anAbsCoord[1]);
-////
-////      const Slvs_Entity& aTarget = myStorage->getEntity(*aCopyIter);
-////      for (int i = 0; i < 2; i++) {
-////        Slvs_Param aParam = myStorage->getParameter(aTarget.param[i]);
-////        aParam.val = anAbsCoord[i];
-////        myStorage->updateParameter(aParam);
-////      }
-////    }
-////  }
-////
-////  std::list<Slvs_Constraint> aDiamConstr;
-////  for (aPointsIter = myCircsAndCopies.begin(); aPointsIter != myCircsAndCopies.end(); ++aPointsIter) {
-////    aCopyIter = aPointsIter->begin();
-////    const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter);
-////    if (anInitial.type == SLVS_E_DISTANCE) {
-////      const Slvs_Param& anInitRad = myStorage->getParameter(anInitial.param[0]);
-////      for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) {
-////        const Slvs_Entity& aCopy = myStorage->getEntity(*aCopyIter);
-////        Slvs_Param aCopyRad = myStorage->getParameter(aCopy.param[0]);
-////        aCopyRad.val = anInitRad.val;
-////        myStorage->updateParameter(aCopyRad);
-////      }
-////    } else if (anInitial.type == SLVS_E_ARC_OF_CIRCLE) {
-////      const Slvs_Entity& aCenterEnt = myStorage->getEntity(anInitial.point[0]);
-////      const Slvs_Entity& aStartEnt = myStorage->getEntity(anInitial.point[1]);
-////
-////      if (aDiamConstr.empty())
-////        aDiamConstr = myStorage->getConstraintsByType(SLVS_C_DIAMETER);
-////      // Calculate diameter of initial arc
-////      double aDiam = 0.0;
-////      for (int i = 0; i < 2; i++) {
-////        double d = myStorage->getParameter(aStartEnt.param[i]).val -
-////                   myStorage->getParameter(aCenterEnt.param[i]).val;
-////        aDiam += d * d;
-////      }
-////      aDiam = sqrt(aDiam) * 2.0;
-////      // Update the Diameter constraints of copied arcs
-////      for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) {
-////        std::list<Slvs_Constraint>::iterator aDCIt = aDiamConstr.begin();
-////        for (; aDCIt != aDiamConstr.end(); ++aDCIt)
-////          if (aDCIt->entityA == *aCopyIter) {
-////            aDCIt->valA = aDiam;
-////            myStorage->updateConstraint(*aDCIt);
-////            aDiamConstr.erase(aDCIt);
-////            break;
-////          }
-////      }
-////    }
-////  }
-////
-////  myPointsJustUpdated.clear();
+  double aRelCoord[2]  = {0.0, 0.0}; // relative coordinates of point
+  double anAbsCoord[2] = {0.0, 0.0}; // absolute coordinates of point
+
+  std::list<Slvs_Constraint> aCoincident = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT);
+  std::list<Slvs_Constraint>::const_iterator aCoIt;
+
+  // Update positions of all points to satisfy angles
+  std::vector< std::vector<Slvs_hEntity> >::const_iterator aPointsIter = myPointsAndCopies.begin();
+  std::vector<Slvs_hEntity>::const_iterator aCopyIter;
+  for (; aPointsIter != myPointsAndCopies.end(); ++aPointsIter) {
+    aCopyIter = aPointsIter->begin();
+    const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter);
+    for (int i = 0; i < 2; i++)
+      anAbsCoord[i] = myStorage->getParameter(anInitial.param[i]).val;
+    getRelative(anAbsCoord[0], anAbsCoord[1], aRelCoord[0], aRelCoord[1]);
+
+    // if the point is coincident with another one which is temporary fixed (moved by user),
+    // we will update its position correspondingly
+    Slvs_hConstraint aFixed;
+    for (aCoIt = aCoincident.begin(); aCoIt != aCoincident.end(); ++aCoIt) {
+      if ((aCoIt->ptA == anInitial.h && myInitialPoints.find(aCoIt->ptB) != myInitialPoints.end()) ||
+          (aCoIt->ptB == anInitial.h && myInitialPoints.find(aCoIt->ptA) != myInitialPoints.end())) {
+        Slvs_hEntity anOtherId = aCoIt->ptA == anInitial.h ? aCoIt->ptB : aCoIt->ptA;
+        if (!myStorage->isTemporary(aFixed) &&
+            myPointsJustUpdated.find(anOtherId) == myPointsJustUpdated.end())
+          continue; // nothing to change
+
+        const Slvs_Entity& anOtherPnt = myStorage->getEntity(anOtherId);
+        for (int i = 0; i < 2; i++) {
+          Slvs_Param anInitParam = myStorage->getParameter(anInitial.param[i]);
+          const Slvs_Param& anOtherParam = myStorage->getParameter(anOtherPnt.param[i]);
+          anInitParam.val = anOtherParam.val;
+          myStorage->updateParameter(anInitParam);
+          anAbsCoord[i] = anOtherParam.val;
+        }
+        getRelative(anAbsCoord[0], anAbsCoord[1], aRelCoord[0], aRelCoord[1]);
+      }
+    }
+
+    // update copied points
+    aCopyIter = aPointsIter->begin();
+    for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) {
+      // transform coordinates
+      transformRelative(aRelCoord[0], aRelCoord[1]);
+      getAbsolute(aRelCoord[0], aRelCoord[1], anAbsCoord[0], anAbsCoord[1]);
+
+      const Slvs_Entity& aTarget = myStorage->getEntity(*aCopyIter);
+      for (int i = 0; i < 2; i++) {
+        Slvs_Param aParam = myStorage->getParameter(aTarget.param[i]);
+        aParam.val = anAbsCoord[i];
+        myStorage->updateParameter(aParam);
+      }
+    }
+  }
+
+  std::list<Slvs_Constraint> aDiamConstr;
+  for (aPointsIter = myCircsAndCopies.begin(); aPointsIter != myCircsAndCopies.end(); ++aPointsIter) {
+    aCopyIter = aPointsIter->begin();
+    const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter);
+    if (anInitial.type == SLVS_E_DISTANCE) {
+      const Slvs_Param& anInitRad = myStorage->getParameter(anInitial.param[0]);
+      for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) {
+        const Slvs_Entity& aCopy = myStorage->getEntity(*aCopyIter);
+        Slvs_Param aCopyRad = myStorage->getParameter(aCopy.param[0]);
+        aCopyRad.val = anInitRad.val;
+        myStorage->updateParameter(aCopyRad);
+      }
+    } else if (anInitial.type == SLVS_E_ARC_OF_CIRCLE) {
+      const Slvs_Entity& aCenterEnt = myStorage->getEntity(anInitial.point[0]);
+      const Slvs_Entity& aStartEnt = myStorage->getEntity(anInitial.point[1]);
+
+      if (aDiamConstr.empty())
+        aDiamConstr = myStorage->getConstraintsByType(SLVS_C_DIAMETER);
+      // Calculate diameter of initial arc
+      double aDiam = 0.0;
+      for (int i = 0; i < 2; i++) {
+        double d = myStorage->getParameter(aStartEnt.param[i]).val -
+                   myStorage->getParameter(aCenterEnt.param[i]).val;
+        aDiam += d * d;
+      }
+      aDiam = sqrt(aDiam) * 2.0;
+      // Update the Diameter constraints of copied arcs
+      for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) {
+        std::list<Slvs_Constraint>::iterator aDCIt = aDiamConstr.begin();
+        for (; aDCIt != aDiamConstr.end(); ++aDCIt)
+          if (aDCIt->entityA == *aCopyIter) {
+            aDCIt->valA = aDiam;
+            myStorage->updateConstraint(*aDCIt);
+            aDiamConstr.erase(aDCIt);
+            break;
+          }
+      }
+    }
+  }
+
+  myPointsJustUpdated.clear();
   myAdjusted = true;
 }
 
-////void SketchSolver_ConstraintMulti::checkCoincidence()
-////{
-////  std::vector< std::vector<Slvs_hEntity> > aFilteredPoints; // points are filtered by their positions
-////
-////  std::vector< std::vector<Slvs_hEntity> >::const_iterator aPCIt = myPointsAndCopies.begin();
-////  std::vector<Slvs_hEntity>::const_iterator aCIt;
-////  for (; aPCIt != myPointsAndCopies.end(); ++aPCIt) {
-////    aCIt = aPCIt->begin();
-////    // Skip first element, focus the copies only
-////    for (++aCIt; aCIt != aPCIt->end(); ++aCIt) {
-////      std::vector< std::vector<Slvs_hEntity> >::iterator aFilterIt = aFilteredPoints.begin();
-////      for (; aFilterIt != aFilteredPoints.end(); ++aFilterIt)
-////        if (myStorage->isEqual(*aCIt, aFilterIt->front())) {
-////          aFilterIt->push_back(*aCIt);
-////          break;
-////        }
-////      if (aFilterIt == aFilteredPoints.end()) {
-////        std::vector<Slvs_hEntity> aNewFilter(1, *aCIt);
-////        aFilteredPoints.push_back(aNewFilter);
-////      }
-////    }
-////  }
-////
-////  // Check the coicidence of filtered points and remove extra fixation.
-////  // Also check separated points which are not fixed.
-////  std::vector< std::vector<Slvs_hEntity> >::iterator aFPIt = aFilteredPoints.begin();
-////  for (; aFPIt != aFilteredPoints.end(); ++aFPIt) {
-////    if (aFPIt->size() <= 1)
-////      continue;
-////    std::vector<Slvs_hEntity>::iterator anIt1, anIt2;
-////    for (anIt1 = aFPIt->begin(); anIt1 != aFPIt->end(); ++anIt1) {
-////      for (anIt2 = anIt1 + 1; anIt2 != aFPIt->end(); ++anIt2) {
-////        Slvs_hConstraint aFixed1, aFixed2;
-////        bool isFixed1 = myStorage->isPointFixed(*anIt1, aFixed1);
-////        bool isFixed2 = myStorage->isPointFixed(*anIt2, aFixed2);
-////        if (myStorage->isCoincident(*anIt1, *anIt2)) {
-////          if (!isFixed1 && isFixed2) {
-////            Slvs_hEntity aTmp = *anIt1;
-////            *anIt1 = *anIt2;
-////            *anIt2 = aTmp;
-////          } else if (isFixed1 && isFixed2) {
-////            // remove fixing of the second point
-////            myStorage->removeConstraint(aFixed2);
-////            std::vector<Slvs_hConstraint>::iterator aRemoveIt = mySlvsConstraints.begin();
-////            for (; aRemoveIt != mySlvsConstraints.end(); ++aRemoveIt)
-////              if (*aRemoveIt == aFixed2) {
-////                mySlvsConstraints.erase(aRemoveIt);
-////                break;
-////              }
-////          }
-////        } else {
-////          bool isFixed[2] = {
-////              myStorage->isPointFixed(*anIt1, aFixed1, true),
-////              myStorage->isPointFixed(*anIt2, aFixed2, true)
-////          };
-////
-////          Slvs_hEntity aPoint[2] = {*anIt1, *anIt2};
-////          for (int i = 0; i < 2; i++)
-////            if (!isFixed[i]) {
-////              Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
-////                  SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
-////                  aPoint[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-////              aConstraint.h = myStorage->addConstraint(aConstraint);
-////              mySlvsConstraints.push_back(aConstraint.h);
-////            }
-////        }
-////      }
-////    }
-////  }
-////}
+void SketchSolver_ConstraintMulti::checkCoincidence()
+{
+  std::vector< std::vector<Slvs_hEntity> > aFilteredPoints; // points are filtered by their positions
+
+  std::vector< std::vector<Slvs_hEntity> >::const_iterator aPCIt = myPointsAndCopies.begin();
+  std::vector<Slvs_hEntity>::const_iterator aCIt;
+  for (; aPCIt != myPointsAndCopies.end(); ++aPCIt) {
+    aCIt = aPCIt->begin();
+    // Skip first element, focus the copies only
+    for (++aCIt; aCIt != aPCIt->end(); ++aCIt) {
+      std::vector< std::vector<Slvs_hEntity> >::iterator aFilterIt = aFilteredPoints.begin();
+      for (; aFilterIt != aFilteredPoints.end(); ++aFilterIt)
+        if (myStorage->isEqual(*aCIt, aFilterIt->front())) {
+          aFilterIt->push_back(*aCIt);
+          break;
+        }
+      if (aFilterIt == aFilteredPoints.end()) {
+        std::vector<Slvs_hEntity> aNewFilter(1, *aCIt);
+        aFilteredPoints.push_back(aNewFilter);
+      }
+    }
+  }
+
+  // Check the coicidence of filtered points and remove extra fixation.
+  // Also check separated points which are not fixed.
+  std::vector< std::vector<Slvs_hEntity> >::iterator aFPIt = aFilteredPoints.begin();
+  for (; aFPIt != aFilteredPoints.end(); ++aFPIt) {
+    if (aFPIt->size() <= 1)
+      continue;
+    std::vector<Slvs_hEntity>::iterator anIt1, anIt2;
+    for (anIt1 = aFPIt->begin(); anIt1 != aFPIt->end(); ++anIt1) {
+      for (anIt2 = anIt1 + 1; anIt2 != aFPIt->end(); ++anIt2) {
+        Slvs_hConstraint aFixed1, aFixed2;
+        bool isFixed1 = myStorage->isPointFixed(*anIt1, aFixed1);
+        bool isFixed2 = myStorage->isPointFixed(*anIt2, aFixed2);
+        if (myStorage->isCoincident(*anIt1, *anIt2)) {
+          if (!isFixed1 && isFixed2) {
+            Slvs_hEntity aTmp = *anIt1;
+            *anIt1 = *anIt2;
+            *anIt2 = aTmp;
+          } else if (isFixed1 && isFixed2) {
+            // remove fixing of the second point
+            myStorage->removeConstraint(aFixed2);
+            std::vector<Slvs_hConstraint>::iterator aRemoveIt = mySlvsConstraints.begin();
+            for (; aRemoveIt != mySlvsConstraints.end(); ++aRemoveIt)
+              if (*aRemoveIt == aFixed2) {
+                mySlvsConstraints.erase(aRemoveIt);
+                break;
+              }
+          }
+        } else {
+          bool isFixed[2] = {
+              myStorage->isPointFixed(*anIt1, aFixed1, true),
+              myStorage->isPointFixed(*anIt2, aFixed2, true)
+          };
+
+          Slvs_hEntity aPoint[2] = {*anIt1, *anIt2};
+          for (int i = 0; i < 2; i++)
+            if (!isFixed[i]) {
+              Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+                  SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
+                  aPoint[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+              aConstraint.h = myStorage->addConstraint(aConstraint);
+              mySlvsConstraints.push_back(aConstraint.h);
+            }
+        }
+      }
+    }
+  }
+}
index 9328b55f8c7c47abee6bc64ee10fe55cf7630cc2..4786ee430436040987a5dfe405366e9d8eff4892 100644 (file)
@@ -27,29 +27,29 @@ public:
       myAdjusted(false)
   {}
 
-////  virtual int getType() const
-////  { return SLVS_C_UNKNOWN; }
+  virtual int getType() const
+  { return SLVS_C_UNKNOWN; }
 
   /// \brief Update constraint
-  virtual void update(bool isForce = false);
-
-////  /// \brief Tries to remove constraint
-////  /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
-////  virtual bool remove();
-////
-////  /// \brief Adds a feature to constraint and create its analogue in SolveSpace
-////  virtual void addFeature(FeaturePtr theFeature);
-////
-////  /// \brief Update SketchPlugin attributes using the data obtained from SolveSpace entities
-////  virtual void refresh()
-////  {
-////    myAdjusted = false;
-////    SketchSolver_Constraint::refresh();
-////  }
-
-////  /// \brief Verifies, the coincidence between points of copied entities appears or disappears,
-////  ///        and removes or adds fixing of corresponding points.
-////  void checkCoincidence();
+  virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
+
+  /// \brief Tries to remove constraint
+  /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+  virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+
+  /// \brief Adds a feature to constraint and create its analogue in SolveSpace
+  virtual void addFeature(FeaturePtr theFeature);
+
+  /// \brief Update SketchPlugin attributes using the data obtained from SolveSpace entities
+  virtual void refresh()
+  {
+    myAdjusted = false;
+    SketchSolver_Constraint::refresh();
+  }
+
+  /// \brief Verifies, the coincidence between points of copied entities appears or disappears,
+  ///        and removes or adds fixing of corresponding points.
+  void checkCoincidence();
 
 protected:
   /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
@@ -57,12 +57,12 @@ protected:
   { /* do nothing here */ }
 
   /// \brief Collect entities and their copies, like circles and arcs
-  void getEntitiesAndCopies(std::list< std::list<EntityWrapperPtr> >& theEntAndCopies);
+  void processEntities(const std::vector< std::vector<Slvs_hEntity> >& theEntAndCopies);
 
   /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
   /// \param[out] theValue      numerical characteristic of constraint (e.g. distance)
   /// \param[out] theAttributes list of attributes to be filled
-  virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes)
+  virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes)
   { /* do nothing here */ }
 
   /// \brief This method is used in derived objects to check consistence of constraint.
@@ -73,24 +73,24 @@ protected:
 
   /// \brief Returns name of NUMBER_OF_COPIES parameter for corresponding feature
   virtual const std::string& nameNbObjects() = 0;
-
-////protected:
-////  /// \brief Convert absolute coordinates to relative coordinates
-////  virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY) = 0;
-////  /// \brief Convert relative coordinates to absolute coordinates
-////  virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY) = 0;
-////  /// \brief Apply transformation for relative coordinates
-////  virtual void transformRelative(double& theX, double& theY) = 0;
+  
+protected:
+  /// \brief Convert absolute coordinates to relative coordinates
+  virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY) = 0;
+  /// \brief Convert relative coordinates to absolute coordinates
+  virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY) = 0;
+  /// \brief Apply transformation for relative coordinates
+  virtual void transformRelative(double& theX, double& theY) = 0;
 
 protected:
-  int myNumberOfObjects; ///< number of previous initial objects
-  int myNumberOfCopies;  ///< number of previous copies of initial objects
-
-////  std::vector< std::vector<Slvs_hEntity> > myPointsAndCopies; ///< list of initial points and their copies
-////  std::vector< std::vector<Slvs_hEntity> > myCircsAndCopies;  ///< list of circles and their copies (to change their radii together)
-////
-////  std::set<Slvs_hEntity> myPointsJustUpdated; ///< list of points touched by user
-////  std::set<Slvs_hEntity> myInitialPoints;     ///< list of points containing initial objects
+  size_t myNumberOfObjects; ///< number of previous initial objects
+  size_t myNumberOfCopies;  ///< number of previous copies of initial objects
+
+  std::vector< std::vector<Slvs_hEntity> > myPointsAndCopies; ///< list of initial points and their copies
+  std::vector< std::vector<Slvs_hEntity> > myCircsAndCopies;  ///< list of circles and their copies (to change their radii together)
+
+  std::set<Slvs_hEntity> myPointsJustUpdated; ///< list of points touched by user
+  std::set<Slvs_hEntity> myInitialPoints;     ///< list of points containing initial objects
 
   bool myAdjusted; ///< the constraint is already adjusted (to not do it several times)
 };
index 91fd4bf40cfdf9d0d0909ad05af121d8096378e2..7608460c47d37f5bdcb2261f02843b2e92b8d08a 100644 (file)
@@ -1,24 +1,25 @@
 #include <SketchSolver_ConstraintMultiRotation.h>
+#include <SketchSolver_Group.h>
 #include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
 
-////#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Arc.h>
 #include <SketchPlugin_MultiRotation.h>
 
-////#include <ModelAPI_AttributeDouble.h>
-////#include <ModelAPI_AttributeInteger.h>
-////#include <ModelAPI_AttributeRefAttr.h>
-////#include <ModelAPI_AttributeRefList.h>
-////#include <ModelAPI_ResultConstruction.h>
-////
-////#include <GeomAPI_Dir2d.h>
-////#include <GeomAPI_XY.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_ResultConstruction.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
 
 #include <math.h>
 
 void SketchSolver_ConstraintMultiRotation::getAttributes(
-    EntityWrapperPtr& theCenter, double& theAngle,
-    std::list< std::list<EntityWrapperPtr> >& theEntities)
+    Slvs_hEntity& theCenter, double& theAngle,
+    std::vector< std::vector<Slvs_hEntity> >& thePoints,
+    std::vector< std::vector<Slvs_hEntity> >& theEntities)
 {
   DataPtr aData = myBaseConstraint->data();
   theAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
@@ -29,121 +30,106 @@ void SketchSolver_ConstraintMultiRotation::getAttributes(
     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
     return;
   }
+  int aType = SLVS_E_UNKNOWN; // type of created entity
+  Slvs_hEntity anEntityID = myGroup->getAttributeId(aCenterAttr);
+  if (anEntityID == SLVS_E_UNKNOWN)
+    anEntityID = changeEntity(aCenterAttr, aType);
+  theCenter = anEntityID;
+
+  // Lists of objects and number of copies
+  AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  myNumberOfObjects = anInitialRefList->size();
+  myNumberOfCopies = (size_t) aData->integer(SketchPlugin_MultiRotation::NUMBER_OF_OBJECTS_ID())->value() - 1;
+  if (myNumberOfCopies <= 0)
+    return;
+  AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+  if (!aRefList) {
+    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+    return;
+  }
 
-  myType = CONSTRAINT_MULTI_ROTATION;
-
-  myStorage->update(aCenterAttr, GID_OUTOFGROUP);
-  theCenter = myStorage->entity(aCenterAttr);
-
-  getEntitiesAndCopies(theEntities);
-
-////  // Lists of objects and number of copies
-////  AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-////      aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
-////  myNumberOfObjects = anInitialRefList->size();
-////  myNumberOfCopies = (size_t) aData->integer(SketchPlugin_MultiRotation::NUMBER_OF_OBJECTS_ID())->value() - 1;
-////  if (myNumberOfCopies <= 0)
-////    return;
-////  AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-////      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
-////  if (!aRefList) {
-////    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-////    return;
-////  }
-////
-////  // Obtain all points of initial features and store them into separate lists
-////  // containing their translated copies.
-////  // Also all circles and arc collected too, because they will be constrained by equal radii.
-////  FeaturePtr aFeature;
-////  ResultConstructionPtr aRC;
-////  static const size_t MAX_POINTS = 3;
-////  std::vector<Slvs_hEntity> aPoints[MAX_POINTS]; // lists of points of features
-////  std::vector<Slvs_hEntity> anEntities;
-////  std::list<ObjectPtr> anObjectList = aRefList->list();
-////  std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
-////  while (anObjectIter != anObjectList.end()) {
-////    for (size_t i = 0; i < MAX_POINTS; ++i)
-////      aPoints[i].clear();
-////    anEntities.clear();
-////
-////    for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
-////      aFeature = ModelAPI_Feature::feature(*anObjectIter);
-////      if (!aFeature)
-////        continue;
-////      anEntityID = changeEntity(aFeature, aType);
-////      anEntities.push_back(anEntityID);
-////      Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
-////      switch (aType) {
-////      case SLVS_E_POINT_IN_2D:
-////      case SLVS_E_POINT_IN_3D:
-////        aPoints[0].push_back(anEntityID);
-////        break;
-////      case SLVS_E_LINE_SEGMENT:
-////        aPoints[0].push_back(anEntity.point[0]); // start point of line
-////        aPoints[1].push_back(anEntity.point[1]); // end point of line
-////        break;
-////      case SLVS_E_CIRCLE:
-////        aPoints[0].push_back(anEntity.point[0]); // center of circle
-////        break;
-////      case SLVS_E_ARC_OF_CIRCLE:
-////        aPoints[0].push_back(anEntity.point[0]); // center of arc
-////        aPoints[1].push_back(anEntity.point[1]); // start point of arc
-////        aPoints[2].push_back(anEntity.point[2]); // end point of arc
-////        break;
-////      default:
-////        myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-////        return;
-////      }
-////    }
-////
-////    for (size_t i = 0; i < MAX_POINTS; ++i)
-////      if (!aPoints[i].empty())
-////        thePoints.push_back(aPoints[i]);
-////    if (!anEntities.empty())
-////      theEntities.push_back(anEntities);
-////  }
+  // Obtain all points of initial features and store them into separate lists
+  // containing their translated copies.
+  // Also all circles and arc collected too, because they will be constrained by equal radii.
+  FeaturePtr aFeature;
+  ResultConstructionPtr aRC;
+  static const size_t MAX_POINTS = 3;
+  std::vector<Slvs_hEntity> aPoints[MAX_POINTS]; // lists of points of features
+  std::vector<Slvs_hEntity> anEntities;
+  std::list<ObjectPtr> anObjectList = aRefList->list();
+  std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
+  while (anObjectIter != anObjectList.end()) {
+    for (size_t i = 0; i < MAX_POINTS; ++i)
+      aPoints[i].clear();
+    anEntities.clear();
+
+    for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
+      aFeature = ModelAPI_Feature::feature(*anObjectIter);
+      if (!aFeature)
+        continue;
+      anEntityID = changeEntity(aFeature, aType);
+      anEntities.push_back(anEntityID);
+      Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
+      switch (aType) {
+      case SLVS_E_POINT_IN_2D:
+      case SLVS_E_POINT_IN_3D:
+        aPoints[0].push_back(anEntityID);
+        break;
+      case SLVS_E_LINE_SEGMENT:
+        aPoints[0].push_back(anEntity.point[0]); // start point of line
+        aPoints[1].push_back(anEntity.point[1]); // end point of line
+        break;
+      case SLVS_E_CIRCLE:
+        aPoints[0].push_back(anEntity.point[0]); // center of circle
+        break;
+      case SLVS_E_ARC_OF_CIRCLE:
+        aPoints[0].push_back(anEntity.point[0]); // center of arc
+        aPoints[1].push_back(anEntity.point[1]); // start point of arc
+        aPoints[2].push_back(anEntity.point[2]); // end point of arc
+        break;
+      default:
+        myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+        return;
+      }
+    }
+
+    for (size_t i = 0; i < MAX_POINTS; ++i)
+      if (!aPoints[i].empty())
+        thePoints.push_back(aPoints[i]);
+    if (!anEntities.empty())
+      theEntities.push_back(anEntities);
+  }
 }
 
 void SketchSolver_ConstraintMultiRotation::process()
 {
   cleanErrorMsg();
-  if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
+  if (!myBaseConstraint || !myStorage || myGroup == 0) {
     /// TODO: Put error message here
     return;
   }
-////  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
-////    update(myBaseConstraint);
+  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+    update(myBaseConstraint);
 
-  EntityWrapperPtr aRotationCenter;
-  std::list<std::list<EntityWrapperPtr> > anEntitiesAndCopies;
-  getAttributes(aRotationCenter, myAngle, anEntitiesAndCopies);
+  std::vector<std::vector<Slvs_hEntity> > anEntitiesAndCopies;
+  getAttributes(myRotationCenter, myAngle, myPointsAndCopies, anEntitiesAndCopies);
   if (!myErrorMsg.empty())
     return;
 
-////  // Set the rotation center unchanged during constraint recalculation
-////  Slvs_Constraint aConstraint;
-////  if (!myStorage->isPointFixed(myRotationCenter, aConstraint.h, true)) {
-////    aConstraint = Slvs_MakeConstraint(
-////        SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
-////        myRotationCenter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-////    aConstraint.h = myStorage->addConstraint(aConstraint);
-////    mySlvsConstraints.push_back(aConstraint.h);
-////  }
-
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-  std::list<ConstraintWrapperPtr> aRotConstraints;
-
-  std::list< std::list<EntityWrapperPtr> >::iterator anEntIt = anEntitiesAndCopies.begin();
-  for (; anEntIt != anEntitiesAndCopies.end(); ++anEntIt) {
-    std::list<ConstraintWrapperPtr> aNewConstraints =
-        aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID, myType,
-        myAngle, aRotationCenter, EntityWrapperPtr(), *anEntIt);
-    aRotConstraints.insert(aRotConstraints.end(), aNewConstraints.begin(), aNewConstraints.end());
+  // Set the rotation center unchanged during constraint recalculation
+  Slvs_Constraint aConstraint;
+  if (!myStorage->isPointFixed(myRotationCenter, aConstraint.h, true)) {
+    aConstraint = Slvs_MakeConstraint(
+        SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
+        myRotationCenter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+    aConstraint.h = myStorage->addConstraint(aConstraint);
+    mySlvsConstraints.push_back(aConstraint.h);
   }
-  myStorage->addConstraint(myBaseConstraint, aRotConstraints);
 
   myAdjusted = false;
-////  processEntities(anEntitiesAndCopies);
+  processEntities(anEntitiesAndCopies);
   adjustConstraint();
 }
 
@@ -155,13 +141,6 @@ void SketchSolver_ConstraintMultiRotation::updateLocal()
     myAdjusted = false;
   // update angle value
   myAngle = aValue;
-
-  // update center
-  AttributePtr aCenterAttr = myBaseConstraint->attribute(SketchPlugin_MultiRotation::CENTER_ID());
-  if (myStorage->update(aCenterAttr, myGroupID)) {
-    myStorage->update(aCenterAttr, GID_UNKNOWN);
-    myAdjusted = false;
-  }
 }
 
 void SketchSolver_ConstraintMultiRotation::adjustConstraint()
@@ -170,69 +149,63 @@ void SketchSolver_ConstraintMultiRotation::adjustConstraint()
     myStorage->setNeedToResolve(false);
     return;
   }
-////  if (myAdjusted)
-////    return;
-////
-////  std::list<Slvs_Constraint> aCoincident = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT);
-////  std::list<Slvs_Constraint>::const_iterator aCoIt;
-////
-////  // Check overconstrained on rotation center (if it is coincident with other fixed point)
-////  Slvs_hConstraint aFixedCenter;
-////  if (myStorage->isPointFixed(myRotationCenter, aFixedCenter, false)) {
-////    Slvs_hConstraint aFixed;
-////    for (aCoIt = aCoincident.begin(); aCoIt != aCoincident.end(); ++aCoIt)
-////      if ((aCoIt->ptA == myRotationCenter && myStorage->isPointFixed(aCoIt->ptB, aFixed, true)) ||
-////          (aCoIt->ptB == myRotationCenter && myStorage->isPointFixed(aCoIt->ptA, aFixed, true))) {
-////        // Un-fix the center
-////        myStorage->removeConstraint(aFixedCenter);
-////        std::vector<Slvs_hConstraint>::iterator aSCIt = mySlvsConstraints.begin();
-////        for (; aSCIt != mySlvsConstraints.end(); ++aSCIt)
-////          if (*aSCIt == aFixedCenter) {
-////            mySlvsConstraints.erase(aSCIt);
-////            break;
-////          }
-////      }
-////  }
-////
-////  // Obtain coordinates of rotation center
-////  Slvs_Entity aRotCenter = myStorage->getEntity(myRotationCenter);
-////  myCenterCoord[0] = myStorage->getParameter(aRotCenter.param[0]).val;
-////  myCenterCoord[1] = myStorage->getParameter(aRotCenter.param[1]).val;
-////
-////  myRotationVal[0] = sin(myAngle * PI / 180.0);
-////  myRotationVal[1] = cos(myAngle * PI / 180.0);
-////
-
-  const std::list<ConstraintWrapperPtr>& aConstraints = myStorage->constraint(myBaseConstraint);
-  std::list<ConstraintWrapperPtr>::const_iterator aCIt = aConstraints.begin();
-  for (; aCIt != aConstraints.end(); ++aCIt)
-    (*aCIt)->setValue(myAngle);
+  if (myAdjusted)
+    return;
+
+  std::list<Slvs_Constraint> aCoincident = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT);
+  std::list<Slvs_Constraint>::const_iterator aCoIt;
+
+  // Check overconstrained on rotation center (if it is coincident with other fixed point)
+  Slvs_hConstraint aFixedCenter;
+  if (myStorage->isPointFixed(myRotationCenter, aFixedCenter, false)) {
+    Slvs_hConstraint aFixed;
+    for (aCoIt = aCoincident.begin(); aCoIt != aCoincident.end(); ++aCoIt)
+      if ((aCoIt->ptA == myRotationCenter && myStorage->isPointFixed(aCoIt->ptB, aFixed, true)) ||
+          (aCoIt->ptB == myRotationCenter && myStorage->isPointFixed(aCoIt->ptA, aFixed, true))) {
+        // Un-fix the center
+        myStorage->removeConstraint(aFixedCenter);
+        std::vector<Slvs_hConstraint>::iterator aSCIt = mySlvsConstraints.begin();
+        for (; aSCIt != mySlvsConstraints.end(); ++aSCIt)
+          if (*aSCIt == aFixedCenter) {
+            mySlvsConstraints.erase(aSCIt);
+            break;
+          }
+      }
+  }
+
+  // Obtain coordinates of rotation center
+  Slvs_Entity aRotCenter = myStorage->getEntity(myRotationCenter);
+  myCenterCoord[0] = myStorage->getParameter(aRotCenter.param[0]).val;
+  myCenterCoord[1] = myStorage->getParameter(aRotCenter.param[1]).val;
+
+  myRotationVal[0] = sin(myAngle * PI / 180.0);
+  myRotationVal[1] = cos(myAngle * PI / 180.0);
 
   SketchSolver_ConstraintMulti::adjustConstraint();
 }
 
-////void SketchSolver_ConstraintMultiRotation::getRelative(
-////    double theAbsX, double theAbsY, double& theRelX, double& theRelY)
-////{
-////  theRelX = theAbsX - myCenterCoord[0];
-////  theRelY = theAbsY - myCenterCoord[1];
-////}
-////
-////void SketchSolver_ConstraintMultiRotation::getAbsolute(
-////    double theRelX, double theRelY, double& theAbsX, double& theAbsY)
-////{
-////  theAbsX = theRelX + myCenterCoord[0];
-////  theAbsY = theRelY + myCenterCoord[1];
-////}
-////
-////void SketchSolver_ConstraintMultiRotation::transformRelative(double& theX, double& theY)
-////{
-////  // rotate direction
-////  // myRotationVal[0] = sinA, myRotationVal[1] = cosA
-////  double aTemp = theX * myRotationVal[1] - theY * myRotationVal[0];
-////  theY = theX * myRotationVal[0] + theY * myRotationVal[1];
-////  theX = aTemp;
-////}
+void SketchSolver_ConstraintMultiRotation::getRelative(
+    double theAbsX, double theAbsY, double& theRelX, double& theRelY)
+{
+  theRelX = theAbsX - myCenterCoord[0];
+  theRelY = theAbsY - myCenterCoord[1];
+}
+
+void SketchSolver_ConstraintMultiRotation::getAbsolute(
+    double theRelX, double theRelY, double& theAbsX, double& theAbsY)
+{
+  theAbsX = theRelX + myCenterCoord[0];
+  theAbsY = theRelY + myCenterCoord[1];
+}
+
+void SketchSolver_ConstraintMultiRotation::transformRelative(double& theX, double& theY)
+{
+  // rotate direction
+  // myRotationVal[0] = sinA, myRotationVal[1] = cosA
+  double aTemp = theX * myRotationVal[1] - theY * myRotationVal[0];
+  theY = theX * myRotationVal[0] + theY * myRotationVal[1];
+  theX = aTemp;
+}
 
 const std::string& SketchSolver_ConstraintMultiRotation::nameNbObjects()
 {
index 8ebda4584f969c6c978ce896694ccb4c32abb125..86966e522110d56d67cc83212aa824b9c77779be 100644 (file)
@@ -22,19 +22,21 @@ public:
       SketchSolver_ConstraintMulti(theConstraint)
   {}
 
-////  virtual int getType() const
-////  { return SLVS_C_MULTI_ROTATION; }
+  virtual int getType() const
+  { return SLVS_C_MULTI_ROTATION; }
 
 protected:
   /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
   virtual void process();
 
   /// \brief Generate list of rotated entities
-  /// \param[out] theCenter   central point of rotation
+  /// \param[out] theCenter   ID of central point of rotation
   /// \param[out] theAngle    rotation angle
-  /// \param[out] theEntities list of entities and their rotated copies
-  void getAttributes(EntityWrapperPtr& theCenter, double& theAngle,
-                     std::list< std::list<EntityWrapperPtr> >& theEntities);
+  /// \param[out] thePoints   list of IDs of initial points and their rotated copies
+  /// \param[out] theEntities list of IDs of entities and their rotated copies
+  void getAttributes(Slvs_hEntity& theCenter, double& theAngle,
+                     std::vector< std::vector<Slvs_hEntity> >& thePoints,
+                     std::vector< std::vector<Slvs_hEntity> >& theEntities);
 
   /// \brief This method is used in derived objects to check consistence of constraint.
   virtual void adjustConstraint();
@@ -42,24 +44,24 @@ protected:
   /// \brief Update parameters (called from base class)
   virtual void updateLocal();
 
-////private:
-////  /// \brief Convert absolute coordinates to relative coordinates
-////  virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY);
-////  /// \brief Convert relative coordinates to absolute coordinates
-////  virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY);
-////  /// \brief Apply transformation for relative coordinates
-////  virtual void transformRelative(double& theX, double& theY);
+private:
+  /// \brief Convert absolute coordinates to relative coordinates
+  virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY);
+  /// \brief Convert relative coordinates to absolute coordinates
+  virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY);
+  /// \brief Apply transformation for relative coordinates
+  virtual void transformRelative(double& theX, double& theY);
 
 private:
   /// \brief Returns name of NUMBER_OF_COPIES parameter for corresponding feature
   virtual const std::string& nameNbObjects();
 
-////private:
-////  Slvs_hEntity myRotationCenter; ///< ID of center of rotation
+private:
+  Slvs_hEntity myRotationCenter; ///< ID of center of rotation
   double       myAngle;           ///< angle of rotation
-////
-////  double myCenterCoord[2]; ///< coordinates of rotation center
-////  double myRotationVal[2]; ///< sinus and cosine of rotation angle
+
+  double myCenterCoord[2]; ///< coordinates of rotation center
+  double myRotationVal[2]; ///< sinus and cosinus of rotation angle
 };
 
 #endif
index 9b6a0840dd82c6a23bded315f2770fd12e2abd21..02b872c6e549527f2bbdd56cb85c4a87707b5e9a 100644 (file)
@@ -1,26 +1,27 @@
 #include <SketchSolver_ConstraintMultiTranslation.h>
+#include <SketchSolver_Group.h>
 #include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
 
-////#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Arc.h>
 #include <SketchPlugin_MultiTranslation.h>
-////
-////#include <ModelAPI_AttributeDouble.h>
-////#include <ModelAPI_AttributeInteger.h>
-////#include <ModelAPI_AttributeRefAttr.h>
-////#include <ModelAPI_AttributeRefList.h>
-////#include <ModelAPI_ResultConstruction.h>
-////#include <ModelAPI_Data.h>
-////
-////#include <GeomAPI_Dir2d.h>
-////#include <GeomAPI_XY.h>
-////
-////#include <math.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Data.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+
+#include <math.h>
 
 
 void SketchSolver_ConstraintMultiTranslation::getAttributes(
-    EntityWrapperPtr& theStartPoint, EntityWrapperPtr& theEndPoint,
-    std::list< std::list<EntityWrapperPtr> >& theEntities)
+    Slvs_hEntity& theStartPoint, Slvs_hEntity& theEndPoint,
+    std::vector< std::vector<Slvs_hEntity> >& thePoints,
+    std::vector< std::vector<Slvs_hEntity> >& theEntities)
 {
   DataPtr aData = myBaseConstraint->data();
   AttributePtr aStartPointAttr = aData->attribute(SketchPlugin_MultiTranslation::START_POINT_ID());
@@ -31,196 +32,175 @@ void SketchSolver_ConstraintMultiTranslation::getAttributes(
     return;
   }
 
-  myType = CONSTRAINT_MULTI_TRANSLATION;
-
-  myStorage->update(aStartPointAttr);
-  theStartPoint = myStorage->entity(aStartPointAttr);
-  myStorage->update(aEndPointAttr);
-  theEndPoint = myStorage->entity(aEndPointAttr);
-
-  getEntitiesAndCopies(theEntities);
-
-////  int aType = SLVS_E_UNKNOWN; // type of created entity
-////  Slvs_hEntity anEntityID = myGroup->getAttributeId(aStartPointAttr);
-////  if (anEntityID == SLVS_E_UNKNOWN)
-////    anEntityID = changeEntity(aStartPointAttr, aType);
-////  theStartPoint = anEntityID;
-////  anEntityID = myGroup->getAttributeId(aEndPointAttr);
-////  if (anEntityID == SLVS_E_UNKNOWN)
-////    anEntityID = changeEntity(aEndPointAttr, aType);
-////  theEndPoint = anEntityID;
-////
-////  // Lists of objects and number of copies
-////  AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-////      aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
-////  myNumberOfObjects = anInitialRefList->size();
-////  myNumberOfCopies = (size_t) aData->integer(SketchPlugin_MultiTranslation::NUMBER_OF_OBJECTS_ID())->value() - 1;
-////  if (myNumberOfCopies <= 0)
-////    return;
-////
-////  AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-////      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
-////  if (!aRefList) {
-////    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-////    return;
-////  }
-////
-////  // Obtain all points of initial features and store them into separate lists
-////  // containing their translated copies.
-////  // Also all circles and arc collected too, because they will be constrained by equal radii.
-////  FeaturePtr aFeature;
-////  ResultConstructionPtr aRC;
-////  static const size_t MAX_POINTS = 3;
-////  std::vector<Slvs_hEntity> aPoints[MAX_POINTS]; // lists of points of features
-////  std::vector<Slvs_hEntity> anEntities;          // list of translated entities
-////  std::list<ObjectPtr> anObjectList = aRefList->list();
-////  std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
-////  while (anObjectIter != anObjectList.end()) {
-////    for (size_t i = 0; i < MAX_POINTS; i++)
-////      aPoints[i].clear();
-////    anEntities.clear();
-////
-////    for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
-////      aFeature = ModelAPI_Feature::feature(*anObjectIter);
-////      if (!aFeature)
-////        continue;
-////      anEntityID = changeEntity(aFeature, aType);
-////      anEntities.push_back(anEntityID);
-////      Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
-////      switch (aType) {
-////      case SLVS_E_POINT_IN_2D:
-////      case SLVS_E_POINT_IN_3D:
-////        aPoints[0].push_back(anEntityID);
-////        break;
-////      case SLVS_E_LINE_SEGMENT:
-////        aPoints[0].push_back(anEntity.point[0]); // start point of line
-////        aPoints[1].push_back(anEntity.point[1]); // end point of line
-////        break;
-////      case SLVS_E_CIRCLE:
-////        aPoints[0].push_back(anEntity.point[0]); // center of circle
-////        break;
-////      case SLVS_E_ARC_OF_CIRCLE:
-////        aPoints[0].push_back(anEntity.point[0]); // center of arc
-////        aPoints[1].push_back(anEntity.point[1]); // start point of arc
-////        aPoints[2].push_back(anEntity.point[2]); // end point of arc
-////        break;
-////      default:
-////        myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-////        return;
-////      }
-////    }
-////
-////    for (size_t i = 0; i < MAX_POINTS; ++i)
-////      if (!aPoints[i].empty())
-////        thePoints.push_back(aPoints[i]);
-////    if (!anEntities.empty())
-////      theEntities.push_back(anEntities);
-////  }
+  int aType = SLVS_E_UNKNOWN; // type of created entity
+  Slvs_hEntity anEntityID = myGroup->getAttributeId(aStartPointAttr);
+  if (anEntityID == SLVS_E_UNKNOWN)
+    anEntityID = changeEntity(aStartPointAttr, aType);
+  theStartPoint = anEntityID;
+  anEntityID = myGroup->getAttributeId(aEndPointAttr);
+  if (anEntityID == SLVS_E_UNKNOWN)
+    anEntityID = changeEntity(aEndPointAttr, aType);
+  theEndPoint = anEntityID;
+
+  // Lists of objects and number of copies
+  AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  myNumberOfObjects = anInitialRefList->size();
+  myNumberOfCopies = (size_t) aData->integer(SketchPlugin_MultiTranslation::NUMBER_OF_OBJECTS_ID())->value() - 1;
+  if (myNumberOfCopies <= 0)
+    return;
+
+  AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+  if (!aRefList) {
+    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+    return;
+  }
+
+  // Obtain all points of initial features and store them into separate lists
+  // containing their translated copies.
+  // Also all circles and arc collected too, because they will be constrained by equal radii.
+  FeaturePtr aFeature;
+  ResultConstructionPtr aRC;
+  static const size_t MAX_POINTS = 3;
+  std::vector<Slvs_hEntity> aPoints[MAX_POINTS]; // lists of points of features
+  std::vector<Slvs_hEntity> anEntities;          // list of translated entities
+  std::list<ObjectPtr> anObjectList = aRefList->list();
+  std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
+  while (anObjectIter != anObjectList.end()) {
+    for (size_t i = 0; i < MAX_POINTS; i++)
+      aPoints[i].clear();
+    anEntities.clear();
+
+    for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
+      aFeature = ModelAPI_Feature::feature(*anObjectIter);
+      if (!aFeature)
+        continue;
+      anEntityID = changeEntity(aFeature, aType);
+      anEntities.push_back(anEntityID);
+      Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
+      switch (aType) {
+      case SLVS_E_POINT_IN_2D:
+      case SLVS_E_POINT_IN_3D:
+        aPoints[0].push_back(anEntityID);
+        break;
+      case SLVS_E_LINE_SEGMENT:
+        aPoints[0].push_back(anEntity.point[0]); // start point of line
+        aPoints[1].push_back(anEntity.point[1]); // end point of line
+        break;
+      case SLVS_E_CIRCLE:
+        aPoints[0].push_back(anEntity.point[0]); // center of circle
+        break;
+      case SLVS_E_ARC_OF_CIRCLE:
+        aPoints[0].push_back(anEntity.point[0]); // center of arc
+        aPoints[1].push_back(anEntity.point[1]); // start point of arc
+        aPoints[2].push_back(anEntity.point[2]); // end point of arc
+        break;
+      default:
+        myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+        return;
+      }
+    }
+
+    for (size_t i = 0; i < MAX_POINTS; ++i)
+      if (!aPoints[i].empty())
+        thePoints.push_back(aPoints[i]);
+    if (!anEntities.empty())
+      theEntities.push_back(anEntities);
+  }
 }
 
 void SketchSolver_ConstraintMultiTranslation::process()
 {
   cleanErrorMsg();
-  if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
+  if (!myBaseConstraint || !myStorage || myGroup == 0) {
     /// TODO: Put error message here
     return;
   }
-////  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
-////    update(myBaseConstraint);
+  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+    update(myBaseConstraint);
 
-  EntityWrapperPtr aStartPoint, aEndPoint;
-  std::list<std::list<EntityWrapperPtr> > anEntitiesAndCopies;
-  getAttributes(aStartPoint, aEndPoint, anEntitiesAndCopies);
+  Slvs_hEntity aStartPoint, aEndPoint;
+  std::vector<std::vector<Slvs_hEntity> > anEntitiesAndCopies;
+  getAttributes(aStartPoint, aEndPoint, myPointsAndCopies, anEntitiesAndCopies);
   if (!myErrorMsg.empty())
     return;
 
-////  // Create translation line
-////  if (myTranslationLine == SLVS_E_UNKNOWN) {
-////    Slvs_Entity aTranslationLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
-////        myGroup->getWorkplaneId(), aStartPoint, aEndPoint);
-////    aTranslationLine.h = myStorage->addEntity(aTranslationLine);
-////    myTranslationLine = aTranslationLine.h;
-////  } else {
-////    Slvs_Entity aTranslationLine = myStorage->getEntity(myTranslationLine);
-////    if (aTranslationLine.point[0] != aStartPoint || aTranslationLine.point[1] != aEndPoint) {
-////      aTranslationLine.point[0] = aStartPoint;
-////      aTranslationLine.point[1] = aEndPoint;
-////      myStorage->updateEntity(aTranslationLine);
-////    }
-////  }
-
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-  std::list<ConstraintWrapperPtr> aTransConstraints;
-
-  std::list< std::list<EntityWrapperPtr> >::iterator anEntIt = anEntitiesAndCopies.begin();
-  for (; anEntIt != anEntitiesAndCopies.end(); ++anEntIt) {
-    std::list<ConstraintWrapperPtr> aNewConstraints =
-        aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID, myType,
-        0.0, aStartPoint, aEndPoint, *anEntIt);
-    aTransConstraints.insert(aTransConstraints.end(), aNewConstraints.begin(), aNewConstraints.end());
+  // Create translation line
+  if (myTranslationLine == SLVS_E_UNKNOWN) {
+    Slvs_Entity aTranslationLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+        myGroup->getWorkplaneId(), aStartPoint, aEndPoint);
+    aTranslationLine.h = myStorage->addEntity(aTranslationLine);
+    myTranslationLine = aTranslationLine.h;
+  } else {
+    Slvs_Entity aTranslationLine = myStorage->getEntity(myTranslationLine);
+    if (aTranslationLine.point[0] != aStartPoint || aTranslationLine.point[1] != aEndPoint) {
+      aTranslationLine.point[0] = aStartPoint;
+      aTranslationLine.point[1] = aEndPoint;
+      myStorage->updateEntity(aTranslationLine);
+    }
   }
-  myStorage->addConstraint(myBaseConstraint, aTransConstraints);
 
   myAdjusted = false;
-////  processEntities(anEntitiesAndCopies);
+  processEntities(anEntitiesAndCopies);
   adjustConstraint();
 }
 
-////void SketchSolver_ConstraintMultiTranslation::adjustConstraint()
-////{
-////  if (myAdjusted)
-////    return;
-////
-////  Slvs_Entity aTranslationLine = myStorage->getEntity(myTranslationLine);
-////  Slvs_hConstraint aFixed; // temporary variable
-////  // Set the translation line unchanged during constraint recalculation
-////  for (int i = 0; i < 2; i++) {
-////    if (myStorage->isPointFixed(aTranslationLine.point[i], aFixed, true))
-////      continue;
-////    Slvs_Constraint aConstraint = Slvs_MakeConstraint(
-////        SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
-////        aTranslationLine.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-////    aConstraint.h = myStorage->addConstraint(aConstraint);
-////    myStorage->addTemporaryConstraint(aConstraint.h);
-////  }
-////
-////  // Check if the distance between point is 0, no need to resolve constraints (just wait another values)
-////  double aXY[4];
-////  for (int i = 0; i < 2; i++) {
-////    Slvs_Entity aPnt = myStorage->getEntity(aTranslationLine.point[i]);
-////    aXY[2*i] = myStorage->getParameter(aPnt.param[0]).val;
-////    aXY[2*i+1] = myStorage->getParameter(aPnt.param[1]).val;
-////  }
-////  myDelta[0] = aXY[2] - aXY[0];
-////  myDelta[1] = aXY[3] - aXY[1];
-////  if (fabs(myDelta[0]) + fabs(myDelta[1]) < tolerance) {
-////    myStorage->setNeedToResolve(false);
-////    return;
-////  }
-////
-////  SketchSolver_ConstraintMulti::adjustConstraint();
-////}
-////
-////void SketchSolver_ConstraintMultiTranslation::getRelative(
-////    double theAbsX, double theAbsY, double& theRelX, double& theRelY)
-////{
-////  theRelX = theAbsX;
-////  theRelY = theAbsY;
-////}
-////
-////void SketchSolver_ConstraintMultiTranslation::getAbsolute(
-////    double theRelX, double theRelY, double& theAbsX, double& theAbsY)
-////{
-////  theAbsX = theRelX;
-////  theAbsY = theRelY;
-////}
-////
-////void SketchSolver_ConstraintMultiTranslation::transformRelative(double& theX, double& theY)
-////{
-////  // translate coordinates
-////  theX += myDelta[0];
-////  theY += myDelta[1];
-////}
+void SketchSolver_ConstraintMultiTranslation::adjustConstraint()
+{
+  if (myAdjusted)
+    return;
+
+  Slvs_Entity aTranslationLine = myStorage->getEntity(myTranslationLine);
+  Slvs_hConstraint aFixed; // temporary variable
+  // Set the translation line unchanged during constraint recalculation
+  for (int i = 0; i < 2; i++) {
+    if (myStorage->isPointFixed(aTranslationLine.point[i], aFixed, true))
+      continue;
+    Slvs_Constraint aConstraint = Slvs_MakeConstraint(
+        SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
+        aTranslationLine.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+    aConstraint.h = myStorage->addConstraint(aConstraint);
+    myStorage->addTemporaryConstraint(aConstraint.h);
+  }
+
+  // Check if the distance between point is 0, no need to resolve constraints (just wait another values)
+  double aXY[4];
+  for (int i = 0; i < 2; i++) {
+    Slvs_Entity aPnt = myStorage->getEntity(aTranslationLine.point[i]);
+    aXY[2*i] = myStorage->getParameter(aPnt.param[0]).val;
+    aXY[2*i+1] = myStorage->getParameter(aPnt.param[1]).val;
+  }
+  myDelta[0] = aXY[2] - aXY[0];
+  myDelta[1] = aXY[3] - aXY[1];
+  if (fabs(myDelta[0]) + fabs(myDelta[1]) < tolerance) {
+    myStorage->setNeedToResolve(false);
+    return;
+  }
+
+  SketchSolver_ConstraintMulti::adjustConstraint();
+}
+
+void SketchSolver_ConstraintMultiTranslation::getRelative(
+    double theAbsX, double theAbsY, double& theRelX, double& theRelY)
+{
+  theRelX = theAbsX;
+  theRelY = theAbsY;
+}
+
+void SketchSolver_ConstraintMultiTranslation::getAbsolute(
+    double theRelX, double theRelY, double& theAbsX, double& theAbsY)
+{
+  theAbsX = theRelX;
+  theAbsY = theRelY;
+}
+
+void SketchSolver_ConstraintMultiTranslation::transformRelative(double& theX, double& theY)
+{
+  // translate coordinates
+  theX += myDelta[0];
+  theY += myDelta[1];
+}
 
 const std::string& SketchSolver_ConstraintMultiTranslation::nameNbObjects()
 {
index 3b3f0901886e81bc6392ed396e384732d709a236..c9f10147def434dcc90e67d1937686b2e1bcf17b 100644 (file)
@@ -19,47 +19,49 @@ class SketchSolver_ConstraintMultiTranslation : public SketchSolver_ConstraintMu
 public:
   /// Constructor based on SketchPlugin constraint
   SketchSolver_ConstraintMultiTranslation(ConstraintPtr theConstraint) :
-      SketchSolver_ConstraintMulti(theConstraint)////,
-////      myTranslationLine(SLVS_E_UNKNOWN)
+      SketchSolver_ConstraintMulti(theConstraint),
+      myTranslationLine(SLVS_E_UNKNOWN)
   {}
 
-////  virtual int getType() const
-////  { return SLVS_C_MULTI_TRANSLATION; }
+  virtual int getType() const
+  { return SLVS_C_MULTI_TRANSLATION; }
 
 protected:
   /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
   virtual void process();
 
   /// \brief Generate list of translated entities
-  /// \param[out] theStartPoint start point of translation
-  /// \param[out] theEndPoint   final point of translation
-  /// \param[out] theEntities   list of entities and their translated copies
-  void getAttributes(EntityWrapperPtr& theStartPoint, EntityWrapperPtr& theEndPoint,
-                     std::list< std::list<EntityWrapperPtr> >& theEntities);
+  /// \param[out] theStartPoint ID of start point of translation
+  /// \param[out] theEndPoint   ID of final point of translation
+  /// \param[out] thePoints     list of IDs of initial points and their translated copies
+  /// \param[out] theEntities   list of IDs of entities and their translated copies
+  void getAttributes(Slvs_hEntity& theStartPoint, Slvs_hEntity& theEndPoint,
+                     std::vector< std::vector<Slvs_hEntity> >& thePoints,
+                     std::vector< std::vector<Slvs_hEntity> >& theEntities);
 
-////  /// \brief This method is used in derived objects to check consistence of constraint.
-////  virtual void adjustConstraint();
+  /// \brief This method is used in derived objects to check consistence of constraint.
+  virtual void adjustConstraint();
 
   /// \brief Update parameters (called from base class)
   virtual void updateLocal()
   {}
 
-////private:
-////  /// \brief Convert absolute coordinates to relative coordinates
-////  virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY);
-////  /// \brief Convert relative coordinates to absolute coordinates
-////  virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY);
-////  /// \brief Apply transformation for relative coordinates
-////  virtual void transformRelative(double& theX, double& theY);
+private:
+  /// \brief Convert absolute coordinates to relative coordinates
+  virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY);
+  /// \brief Convert relative coordinates to absolute coordinates
+  virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY);
+  /// \brief Apply transformation for relative coordinates
+  virtual void transformRelative(double& theX, double& theY);
 
 private:
   /// \brief Returns name of NUMBER_OF_COPIES parameter for corresponding feature
   virtual const std::string& nameNbObjects();
 
-////private:
-////  Slvs_hEntity myTranslationLine; ///< ID of translation line
-////
-////  double myDelta[2]; ///< increment of translation
+private:
+  Slvs_hEntity myTranslationLine; ///< ID of translation line
+
+  double myDelta[2]; ///< increment of translation
 };
 
 #endif
diff --git a/src/SketchSolver/SketchSolver_ConstraintParametric.cpp b/src/SketchSolver/SketchSolver_ConstraintParametric.cpp
new file mode 100644 (file)
index 0000000..bd533ce
--- /dev/null
@@ -0,0 +1,171 @@
+#include <SketchSolver_ConstraintParametric.h>
+#include <SketchSolver_Error.h>
+#include <SketchSolver_Group.h>
+
+#include <GeomDataAPI_Point2D.h>
+
+SketchSolver_ConstraintParametric::SketchSolver_ConstraintParametric(AttributePtr theAttribute)
+  : SketchSolver_ConstraintRigid(ConstraintPtr()),
+    myBaseAttribute(theAttribute)
+{
+  process();
+}
+
+void SketchSolver_ConstraintParametric::process()
+{
+  cleanErrorMsg();
+  if (!myBaseAttribute || !myStorage || myGroup == 0) {
+    /// TODO: Put error message here
+    return;
+  }
+  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+    update(myBaseConstraint);
+
+  Slvs_hEntity anAttrID;
+  getAttributes(anAttrID);
+  if (!myErrorMsg.empty() || (myFeatureMap.empty() && myAttributeMap.empty()))
+    return;
+
+  myHorizLineID = SLVS_E_UNKNOWN;
+  myVertLineID = SLVS_E_UNKNOWN;
+
+  std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(myBaseAttribute);
+  if (!aPoint)
+    return;
+  if (!aPoint->textX().empty()) {
+    // Create vertical line with fixed boundary point
+    Slvs_Entity aLine = createLine(aPoint->x(), -100.0, aPoint->x(), 100.0);
+    // Place point on line
+    Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+        SLVS_C_PT_ON_LINE, myGroup->getWorkplaneId(), 0.0, anAttrID, SLVS_E_UNKNOWN,
+        aLine.h, SLVS_E_UNKNOWN);
+    aConstraint.h = myStorage->addConstraint(aConstraint);
+    mySlvsConstraints.push_back(aConstraint.h);
+    myVertLineID = aLine.h;
+    myX = aPoint->x();
+  }
+  if (!aPoint->textY().empty()) {
+    // Create horizontal line with fixed boundary points
+    Slvs_Entity aLine = createLine(-100.0, aPoint->y(), 100.0, aPoint->y());
+    // Place point on line
+    Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+        SLVS_C_PT_ON_LINE, myGroup->getWorkplaneId(), 0.0, anAttrID, SLVS_E_UNKNOWN,
+        aLine.h, SLVS_E_UNKNOWN);
+    aConstraint.h = myStorage->addConstraint(aConstraint);
+    mySlvsConstraints.push_back(aConstraint.h);
+    myHorizLineID = aLine.h;
+    myY = aPoint->y();
+  }
+}
+
+
+void SketchSolver_ConstraintParametric::getAttributes(Slvs_hEntity& theAttributeID)
+{
+  int aType = SLVS_E_UNKNOWN; // type of created entity
+  theAttributeID = SLVS_E_UNKNOWN;
+  theAttributeID = myGroup->getAttributeId(myBaseAttribute);
+  if (theAttributeID == SLVS_E_UNKNOWN) {
+    theAttributeID = changeEntity(myBaseAttribute, aType);
+    if (theAttributeID == SLVS_E_UNKNOWN) {
+      myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+      return;
+    }
+  }
+  else
+     myAttributeMap[myBaseAttribute] = theAttributeID;
+}
+
+
+void SketchSolver_ConstraintParametric::update(ConstraintPtr theConstraint)
+{
+  cleanErrorMsg();
+  if (!theConstraint || theConstraint == myBaseConstraint) {
+    std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(myBaseAttribute);
+    if (aPoint && ((!aPoint->textX().empty() && myVertLineID == SLVS_E_UNKNOWN) || 
+        (!aPoint->textY().empty() && myHorizLineID == SLVS_E_UNKNOWN))) {
+      remove();
+      process();
+      return;
+    }
+  }
+  adjustConstraint();
+}
+
+void SketchSolver_ConstraintParametric::refresh()
+{
+  Slvs_hEntity aBasePointID = myAttributeMap[myBaseAttribute];
+  const Slvs_Entity& aBasePoint = myStorage->getEntity(aBasePointID);
+  double aXY[2];
+  aXY[0] = myVertLineID  != SLVS_E_UNKNOWN ? myX : myStorage->getParameter(aBasePoint.param[0]).val;
+  aXY[1] = myHorizLineID != SLVS_E_UNKNOWN ? myY : myStorage->getParameter(aBasePoint.param[1]).val;
+
+  std::list<Slvs_Constraint> aCoincidence = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT);
+  std::list<Slvs_Constraint>::const_iterator aCIt = aCoincidence.begin();
+  for (; aCIt != aCoincidence.end(); ++aCIt) {
+    if (aCIt->ptA != aBasePointID && aCIt->ptB != aBasePointID)
+      continue;
+    Slvs_hEntity anOtherPointID = aCIt->ptA == aBasePointID ? aCIt->ptB : aCIt->ptA;
+    const Slvs_Entity& aPoint = myStorage->getEntity(anOtherPointID);
+    for (int i = 0; i < 2; i++) {
+      Slvs_Param aParam = myStorage->getParameter(aPoint.param[i]);
+      aParam.val = aXY[i];
+      myStorage->updateParameter(aParam);
+    }
+  }
+}
+
+void SketchSolver_ConstraintParametric::adjustConstraint()
+{
+  std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(myBaseAttribute);
+  if (!aPoint)
+    return;
+
+  if (!aPoint->textX().empty()) {
+    const Slvs_Entity& aLine = myStorage->getEntity(myVertLineID);
+    const Slvs_Entity& aStartPoint = myStorage->getEntity(aLine.point[0]);
+    Slvs_Param aParX = myStorage->getParameter(aStartPoint.param[0]);
+    aParX.val = aPoint->x();
+    myStorage->updateParameter(aParX);
+    myX = aParX.val;
+  }
+  if (!aPoint->textY().empty()) {
+    const Slvs_Entity& aLine = myStorage->getEntity(myHorizLineID);
+    const Slvs_Entity& aStartPoint = myStorage->getEntity(aLine.point[0]);
+    Slvs_Param aParY = myStorage->getParameter(aStartPoint.param[1]);
+    aParY.val = aPoint->y();
+    myStorage->updateParameter(aParY);
+    myY = aParY.val;
+  }
+}
+
+
+Slvs_Entity SketchSolver_ConstraintParametric::createLine(
+    double theStartX, double theStartY, double theEndX, double theEndY)
+{
+  // Start point
+  Slvs_Param aParX = Slvs_MakeParam(SLVS_E_UNKNOWN, SLVS_G_OUTOFGROUP, theStartX);
+  Slvs_Param aParY = Slvs_MakeParam(SLVS_E_UNKNOWN, SLVS_G_OUTOFGROUP, theStartY);
+  aParX.h = myStorage->addParameter(aParX);
+  aParY.h = myStorage->addParameter(aParY);
+  Slvs_Entity aStartPoint = Slvs_MakePoint2d(SLVS_E_UNKNOWN, SLVS_G_OUTOFGROUP,
+    myGroup->getWorkplaneId(), aParX.h, aParY.h);
+  aStartPoint.h = myStorage->addEntity(aStartPoint);
+
+  // End point
+  aParX = Slvs_MakeParam(SLVS_E_UNKNOWN, SLVS_G_OUTOFGROUP, theEndX);
+  aParY = Slvs_MakeParam(SLVS_E_UNKNOWN, SLVS_G_OUTOFGROUP, theEndY);
+  aParX.h = myStorage->addParameter(aParX);
+  aParY.h = myStorage->addParameter(aParY);
+  Slvs_Entity aEndPoint = Slvs_MakePoint2d(SLVS_E_UNKNOWN, SLVS_G_OUTOFGROUP,
+    myGroup->getWorkplaneId(), aParX.h, aParY.h);
+  aEndPoint.h = myStorage->addEntity(aEndPoint);
+
+  // Line
+  Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, SLVS_G_OUTOFGROUP,
+    myGroup->getWorkplaneId(), aStartPoint.h, aEndPoint.h);
+  aLine.h = myStorage->addEntity(aLine);
+  return aLine;
+}
diff --git a/src/SketchSolver/SketchSolver_ConstraintParametric.h b/src/SketchSolver/SketchSolver_ConstraintParametric.h
new file mode 100644 (file)
index 0000000..3a25d96
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    SketchSolver_ConstraintParametric.h
+// Created: 15 Jun 2015
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintParametric_H_
+#define SketchSolver_ConstraintParametric_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_ConstraintRigid.h>
+
+/** \class   SketchSolver_ConstraintParametric
+ *  \ingroup Plugins
+ *  \brief   Stores data of Rigid (Fixed) constraint for the attribute
+ *           which coordinates are given by parametric expression
+ */
+class SketchSolver_ConstraintParametric : public SketchSolver_ConstraintRigid
+{
+private:
+  /// Creates constraint to manage the given constraint from plugin
+  SketchSolver_ConstraintParametric()
+    : SketchSolver_ConstraintRigid(ConstraintPtr())
+  {}
+
+public:
+  /// Creates temporary constraint based on feature
+  SketchSolver_ConstraintParametric(AttributePtr theAttribute);
+
+  /// \brief Update constraint
+  virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
+
+  /// \brief Update points coincident with parametric one
+  virtual void refresh();
+
+protected:
+  /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+  virtual void process();
+
+  /// \brief Convert attribute to the entity
+  /// \param[out] theAttributeID   identifier of the entity related to the attribute
+  virtual void getAttributes(Slvs_hEntity& theAttributeID);
+
+  /// \brief This method is used in derived objects to check consistence of constraint.
+  virtual void adjustConstraint();
+
+private:
+  /// \brief Create SolveSpace line with given coordinates
+  /// \return created line
+  Slvs_Entity createLine(double theStartX, double theStartY, double theEndX, double theEndY);
+
+private:
+  AttributePtr myBaseAttribute; ///< attribute given by expression
+  Slvs_hEntity myHorizLineID;   ///< identifier of horizontal line, containing the point
+  Slvs_hEntity myVertLineID;    ///< identifier of vertical line, containing the point
+  double myX, myY;
+};
+
+#endif
diff --git a/src/SketchSolver/SketchSolver_ConstraintRigid.cpp b/src/SketchSolver/SketchSolver_ConstraintRigid.cpp
new file mode 100644 (file)
index 0000000..ed8ae37
--- /dev/null
@@ -0,0 +1,393 @@
+#include <SketchSolver_ConstraintRigid.h>
+#include <SketchSolver_Error.h>
+#include <SketchSolver_Group.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_ConstraintRigid.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
+
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_XY.h>
+#include <GeomDataAPI_Point2D.h>
+#include <ModelAPI_AttributeDouble.h>
+
+#include <math.h>
+
+SketchSolver_ConstraintRigid::SketchSolver_ConstraintRigid(FeaturePtr theFeature)
+  : SketchSolver_Constraint(),
+    myBaseFeature(theFeature)
+{
+  process();
+}
+
+void SketchSolver_ConstraintRigid::process()
+{
+  cleanErrorMsg();
+  if ((!myBaseConstraint && !myBaseFeature) || !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() || (myFeatureMap.empty() && myAttributeMap.empty()))
+    return;
+  fixFeature();
+}
+
+void SketchSolver_ConstraintRigid::update(ConstraintPtr theConstraint)
+{
+  cleanErrorMsg();
+  if (theConstraint && theConstraint == myBaseConstraint &&
+      theConstraint->getKind() == myBaseConstraint->getKind() &&
+      checkAttributesChanged(theConstraint)) {
+    // remove previous constraint and set the given one
+    remove(myBaseConstraint);
+    myBaseConstraint = theConstraint;
+    process();
+  }
+}
+
+static void fixEntity(StoragePtr theStorage, const Slvs_hEntity& theEntID)
+{
+  Slvs_Entity anEntity = theStorage->getEntity(theEntID);
+  anEntity.group = SLVS_G_OUTOFGROUP;
+  theStorage->updateEntity(anEntity);
+  // move out of group all sub-entities
+  for (int i = 0; i < 4; ++i)
+    if (anEntity.point[i] != SLVS_E_UNKNOWN)
+      fixEntity(theStorage, anEntity.point[i]);
+  // move out of group the radius of circle
+  if (anEntity.distance != SLVS_E_UNKNOWN)
+    fixEntity(theStorage, anEntity.distance);
+  // move out of group parameters
+  for (int i = 0; i < 4; ++i)
+    if (anEntity.param[i] != SLVS_E_UNKNOWN) {
+      Slvs_Param aParam = theStorage->getParameter(anEntity.param[i]);
+      aParam.group = SLVS_G_OUTOFGROUP;
+      theStorage->updateParameter(aParam);
+    }
+}
+
+void SketchSolver_ConstraintRigid::fixFeature()
+{
+  Slvs_hEntity anEntID = fixedEntity();
+  if (anEntID != SLVS_E_UNKNOWN)
+    fixEntity(myStorage, anEntID);
+}
+
+Slvs_hEntity SketchSolver_ConstraintRigid::fixedEntity() const
+{
+  Slvs_hEntity anEntID = SLVS_E_UNKNOWN;
+  if (myBaseConstraint) {
+    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+        myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+    if (aRefAttr->isObject()) {
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+      std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFound = myFeatureMap.find(aFeature);
+      if (aFound != myFeatureMap.end())
+        anEntID = aFound->second;
+    } else {
+      std::map<AttributePtr, Slvs_hEntity>::const_iterator aFound = myAttributeMap.find(aRefAttr->attr());
+      if (aFound != myAttributeMap.end())
+        anEntID = aFound->second;
+    }
+  }
+  else if (myBaseFeature) {
+    std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFound = myFeatureMap.find(myBaseFeature);
+    if (aFound != myFeatureMap.end())
+      anEntID = aFound->second;
+  }
+  return anEntID;
+}
+
+void SketchSolver_ConstraintRigid::getAttributes(
+    double& theValue,
+    std::vector<Slvs_hEntity>& theAttributes)
+{
+  theValue = 0.0;
+  int aType = SLVS_E_UNKNOWN; // type of created entity
+  Slvs_hEntity anEntityID = SLVS_E_UNKNOWN;
+  if (myBaseConstraint) {
+    // Get the attribute of constraint
+    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+        myBaseConstraint->attribute(SketchPlugin_ConstraintRigid::ENTITY_A()));
+    if (!aRefAttr || !aRefAttr->isInitialized()) {
+      myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+      return;
+    }
+    anEntityID = myGroup->getAttributeId(aRefAttr);
+    if (anEntityID == SLVS_E_UNKNOWN)
+      anEntityID = changeEntity(aRefAttr, aType);
+  } else {
+    anEntityID = myGroup->getFeatureId(myBaseFeature);
+    if (anEntityID == SLVS_E_UNKNOWN)
+      anEntityID = changeEntity(myBaseFeature, aType);
+    else
+      myFeatureMap[myBaseFeature] = anEntityID;
+  }
+
+  if (anEntityID == SLVS_E_UNKNOWN) {
+    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+    return;
+  }
+
+  // Check the entity is complex
+  Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
+  if (anEntity.point[0] != SLVS_E_UNKNOWN) {
+    for (int i = 0; i < 4 && anEntity.point[i]; i++)
+      theAttributes.push_back(anEntity.point[i]);
+  } else // simple entity
+    theAttributes.push_back(anEntityID);
+}
+
+
+bool SketchSolver_ConstraintRigid::remove(ConstraintPtr theConstraint)
+{
+  cleanErrorMsg();
+  if (theConstraint && theConstraint != myBaseConstraint)
+    return false;
+  bool isFullyRemoved = true;
+
+  std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
+  for (; aCIter != mySlvsConstraints.end(); ++aCIter)
+    isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
+
+  std::map<FeaturePtr, Slvs_hEntity>::iterator aFIter = myFeatureMap.begin();
+  for (; aFIter != myFeatureMap.end(); ++aFIter)
+    isFullyRemoved = myStorage->removeEntity(aFIter->second) && isFullyRemoved;
+
+  std::map<AttributePtr, Slvs_hEntity>::iterator anAtIter = myAttributeMap.begin();
+  for (; anAtIter != myAttributeMap.end(); ++anAtIter)
+    isFullyRemoved = myStorage->removeEntity(anAtIter->second) && isFullyRemoved;
+
+  if (isFullyRemoved) {
+    myFeatureMap.clear();
+    myAttributeMap.clear();
+    myValueMap.clear();
+    mySlvsConstraints.clear();
+  } else
+    cleanRemovedEntities();
+  return true;
+}
+
+Slvs_hConstraint SketchSolver_ConstraintRigid::fixPoint(const Slvs_hEntity& thePointID)
+{
+  if (thePointID == SLVS_E_UNKNOWN)
+    return SLVS_C_UNKNOWN;
+
+  Slvs_Constraint aConstraint;
+  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 (isFixed) return aConstrID;
+    aConstraint = Slvs_MakeConstraint(SLVS_C_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 (!isFixed || aConstrID == SLVS_C_UNKNOWN || myBaseConstraint)
+      return SLVS_C_UNKNOWN;
+    aConstraint = myStorage->getConstraint(aConstrID);
+    aConstraint.ptA = thePointID;
+    myStorage->addConstraint(aConstraint);
+    if (!myBaseConstraint)
+      myStorage->addConstraintWhereDragged(aConstraint.h);
+  }
+  return aConstraint.h;
+}
+
+void SketchSolver_ConstraintRigid::fixLine(const Slvs_Entity& theLine)
+{
+  Slvs_Constraint anEqual;
+  if (myStorage->isAxisParallel(theLine.h)) {
+    // Fix one point and a line length
+    Slvs_hConstraint aFixed;
+    if (!myStorage->isPointFixed(theLine.point[0], aFixed, true) &&
+        !myStorage->isPointFixed(theLine.point[1], aFixed, true))
+      fixPoint(theLine.point[0]);
+    if (!myStorage->isUsedInEqual(theLine.h, anEqual)) {
+      // Check the distance is not set yet
+      std::list<Slvs_Constraint> aDistConstr = myStorage->getConstraintsByType(SLVS_C_PT_PT_DISTANCE);
+      std::list<Slvs_Constraint>::const_iterator aDIt = aDistConstr.begin();
+      for (; aDIt != aDistConstr.end(); aDIt++)
+        if ((aDIt->ptA == theLine.point[0] && aDIt->ptB == theLine.point[1]) ||
+            (aDIt->ptA == theLine.point[1] && aDIt->ptB == theLine.point[0]))
+          return;
+      // Calculate distance between points on the line
+      double aCoords[4];
+      for (int i = 0; i < 2; i++) {
+        Slvs_Entity aPnt = myStorage->getEntity(theLine.point[i]);
+        for (int j = 0; j < 2; j++) {
+          Slvs_Param aParam = myStorage->getParameter(aPnt.param[j]);
+          aCoords[2*i+j] = aParam.val;
+        }
+      }
+      double aLength = sqrt((aCoords[2] - aCoords[0]) * (aCoords[2] - aCoords[0]) + 
+                            (aCoords[3] - aCoords[1]) * (aCoords[3] - aCoords[1]));
+      // fix line length
+      Slvs_Constraint aDistance = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+          SLVS_C_PT_PT_DISTANCE, myGroup->getWorkplaneId(), aLength,
+          theLine.point[0], theLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+      aDistance.h = myStorage->addConstraint(aDistance);
+      mySlvsConstraints.push_back(aDistance.h);
+    }
+    return;
+  }
+  else if (myStorage->isUsedInEqual(theLine.h, anEqual)) {
+    // Check another entity of Equal is already fixed
+    Slvs_hEntity anOtherEntID = anEqual.entityA == theLine.h ? anEqual.entityB : anEqual.entityA;
+    if (myStorage->isEntityFixed(anOtherEntID, true)) {
+      // Fix start point of the line (if end point is not fixed yet) ...
+      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];
+      // 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, anEndFixedID);
+          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 (myStorage->isUsedInEqual(theCircle.h, anEqual)) {
+    // Check another entity of Equal is already fixed
+    Slvs_hEntity anOtherEntID = anEqual.entityA == theCircle.h ? anEqual.entityB : anEqual.entityA;
+    if (myStorage->isEntityFixed(anOtherEntID, true))
+      isFixRadius = false;
+  }
+
+  fixPoint(theCircle.point[0]);
+
+  if (isFixRadius) {
+    // Search the radius is already fixed
+    std::list<Slvs_Constraint> aDiamConstr = myStorage->getConstraintsByType(SLVS_C_DIAMETER);
+    std::list<Slvs_Constraint>::const_iterator aDiamIter = aDiamConstr.begin();
+    for (; aDiamIter != aDiamConstr.end(); aDiamIter++)
+      if (aDiamIter->entityA == theCircle.h)
+        return;
+
+    // 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)
+{
+  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 (myStorage->isUsedInEqual(theArc.h, anEqual)) {
+    // Check another entity of Equal is already fixed
+    Slvs_hEntity anOtherEntID = anEqual.entityA == theArc.h ? anEqual.entityB : anEqual.entityA;
+    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]);
+      }
+    }
+  }
+
+  Slvs_hConstraint aConstrID;
+  int aNbPointsToFix = 2; // number of fixed points for the arc
+  if (myStorage->isPointFixed(theArc.point[0], aConstrID, true))
+    aNbPointsToFix--;
+
+  // Radius of the arc
+  FeaturePtr aFeature = myFeatureMap.begin()->first;
+  std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+    aFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
+  std::shared_ptr<GeomAPI_Pnt2d> aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+    aFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt();
+  double aRadius = aCenter->distance(aStart);
+
+  // Update end point of the arc to be on a curve
+  std::shared_ptr<GeomAPI_Pnt2d> anEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+    aFeature->attribute(SketchPlugin_Arc::END_ID()))->pnt();
+  double aDistance = anEnd->distance(aCenter);
+  std::shared_ptr<GeomAPI_XY> aDir = anEnd->xy()->decreased(aCenter->xy());
+  if (aDistance < tolerance)
+    aDir = aStart->xy()->decreased(aCenter->xy())->multiplied(-1.0);
+  else
+    aDir = aDir->multiplied(aRadius / aDistance);
+  double xy[2] = {aCenter->x() + aDir->x(), aCenter->y() + aDir->y()};
+  Slvs_Entity aEndPoint = myStorage->getEntity(theArc.point[2]);
+  for (int i = 0; i < 2; i++) {
+    Slvs_Param aParam = myStorage->getParameter(aEndPoint.param[i]);
+    aParam.val = xy[i];
+    myStorage->updateParameter(aParam);
+  }
+
+  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 == theArc.h)
+        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);
+    }
+  }
+}
diff --git a/src/SketchSolver/SketchSolver_ConstraintRigid.h b/src/SketchSolver/SketchSolver_ConstraintRigid.h
new file mode 100644 (file)
index 0000000..adac8c6
--- /dev/null
@@ -0,0 +1,76 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    SketchSolver_ConstraintRigid.h
+// Created: 30 Mar 2015
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintRigid_H_
+#define SketchSolver_ConstraintRigid_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Constraint.h>
+
+/** \class   SketchSolver_ConstraintRigid
+ *  \ingroup Plugins
+ *  \brief   Stores data of Rigid (Fixed) constraint
+ *
+ *  Rigid constraint may have NULL basic SketchPlugin constraint,
+ *  because the Rigid constraint may be temporary for correct moving of objects.
+ *
+ *  Rigid constraint does not create a constraint, but builds the entities in separate group,
+ *  so they will not be moved while resolving the set of constraints.
+ */
+class SketchSolver_ConstraintRigid : public SketchSolver_Constraint
+{
+public:
+  /// Creates constraint to manage the given constraint from plugin
+  SketchSolver_ConstraintRigid(ConstraintPtr theConstraint)
+    : SketchSolver_Constraint(theConstraint)
+  {}
+  /// Creates temporary constraint based on feature
+  SketchSolver_ConstraintRigid(FeaturePtr theFeature);
+
+  /// \brief Update constraint
+  virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
+
+  /// \brief Tries to remove constraint
+  /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+  virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+
+  /// \brief Returns the type of constraint
+  virtual int getType() const
+  { return SLVS_C_WHERE_DRAGGED; }
+
+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 SolveSpace constraints
+  /// \param[out] theValue      numerical characteristic of constraint (e.g. distance)
+  /// \param[out] theAttributes list of attributes to be filled
+  virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
+
+  /// \brief Fixed feature basing on its type
+  virtual void fixFeature();
+
+  /// \brief Fix given point
+  /// \return ID of the Fixed constraint
+  Slvs_hConstraint fixPoint(const Slvs_hEntity& thePointID);
+
+  /// \brief Returns ID of fixed entity
+  Slvs_hEntity fixedEntity() const;
+
+  /// \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);
+
+protected:
+  FeaturePtr myBaseFeature; ///< fixed feature (when it is set, myBaseConstraint should be NULL)
+};
+
+#endif
index 7ec41bc79c0ff66fa18a1d60abf10bcc70fd5774..865065411596d9e96ec503398675a63f43cf78a3 100644 (file)
 #include <SketchSolver_ConstraintTangent.h>
+#include <SketchSolver_Group.h>
 #include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
 
-#include <GeomAPI_Pnt2d.h>
 
-
-/// \brief Check whether the entities has only one shared point
-static bool hasSingleCoincidence(EntityWrapperPtr theEntity1, EntityWrapperPtr theEntity2)
+void SketchSolver_ConstraintTangent::process()
 {
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
-  const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
-  const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
-
-  std::list<EntityWrapperPtr>::const_iterator aStartIt1 = aPoints1.begin();
-  if (theEntity1->type() == ENTITY_ARC) ++aStartIt1; // skip center of arc
-  std::list<EntityWrapperPtr>::const_iterator aStartIt2 = aPoints2.begin();
-  if (theEntity2->type() == ENTITY_ARC) ++aStartIt2; // skip center of arc
-
-  int aNbCoinc = 0;
-  std::list<EntityWrapperPtr>::const_iterator anIt1, anIt2;
-  for (anIt1 = aStartIt1; anIt1 != aPoints1.end(); ++anIt1) {
-    std::shared_ptr<GeomAPI_Pnt2d> aPt1 = aBuilder->point(*anIt1);
-    for (anIt2 = aStartIt2; anIt2 != aPoints2.end(); ++anIt2) {
-      std::shared_ptr<GeomAPI_Pnt2d> aPt2 = aBuilder->point(*anIt2);
-      if (aPt1->distance(aPt2) < tolerance)
-        ++aNbCoinc;
-    }
-  }
-  return aNbCoinc == 1;
-}
-
-
-void SketchSolver_ConstraintTangent::getAttributes(
-    double& theValue,
-    std::vector<EntityWrapperPtr>& theAttributes)
-{
-  SketchSolver_Constraint::getAttributes(theValue, theAttributes);
-  if (!myErrorMsg.empty() || !theAttributes[2] || !theAttributes[3]) {
-    theAttributes.clear();
+  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> anEntID;
+  getAttributes(aValue, anEntID);
+  if (!myErrorMsg.empty())
+    return;
   // Check the quantity of entities of each type and their order (arcs first)
   int aNbLines = 0;
   int aNbArcs = 0;
-  bool isSwap = false; // whether need to swap arguments (arc goes before line)
-  std::vector<EntityWrapperPtr>::iterator anEntIt = theAttributes.begin() + 2;
-  for (; anEntIt != theAttributes.end(); ++anEntIt) {
-    if ((*anEntIt)->type() == ENTITY_LINE)
-      ++aNbLines;
-    else if ((*anEntIt)->type() == ENTITY_ARC) {
-      ++aNbArcs;
-      isSwap = aNbLines > 0;
+  Slvs_Entity anEntities[2];
+  myType = SLVS_C_CURVE_CURVE_TANGENT;
+  std::vector<Slvs_hEntity>::iterator anEntIter = anEntID.begin();
+  for (; anEntIter != anEntID.end(); anEntIter++) {
+    Slvs_Entity anEnt = myStorage->getEntity(*anEntIter);
+    if (anEnt.type == SLVS_E_LINE_SEGMENT) {
+      if (aNbLines == 0)
+        anEntities[1 + aNbLines] = anEnt;
+      aNbLines++;
+      myType = SLVS_C_ARC_LINE_TANGENT;
+    }
+    else if (anEnt.type == SLVS_E_ARC_OF_CIRCLE) {
+      if (aNbArcs < 2)
+        anEntities[aNbArcs] = anEnt;
+      aNbArcs++;
     }
   }
 
-  if (aNbArcs < 1) {
+  if (aNbLines + aNbArcs != 2) {
+    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+    return;
+  } else if (aNbArcs < 1) {
     myErrorMsg = SketchSolver_Error::INCORRECT_TANGENCY_ATTRIBUTE();
     return;
   }
-  if (aNbLines == 1 && aNbArcs == 1)
-    myType = CONSTRAINT_TANGENT_ARC_LINE;
-  else if (aNbArcs == 2)
-    myType = CONSTRAINT_TANGENT_ARC_ARC;
-  else {
-    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+
+  // It is necessary to identify which points of entities are coincident
+  int aSlvsOtherFlag = 0;
+  int aSlvsOther2Flag = 0;
+  // Obtain start and end points of entities
+  Slvs_hEntity aPointsToFind[4];
+  for (int i = 0; i < 2; i++) {
+    int aShift = anEntities[i].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
+    aPointsToFind[2*i]  = anEntities[i].point[aShift];
+    aPointsToFind[2*i+1]= anEntities[i].point[aShift+1];
+  }
+  // Search coincident points
+  bool isPointFound = false;
+  for (int i = 0; i < 2 && !isPointFound; i++)
+    for (int j = 2; j < 4 && !isPointFound; j++)
+      if (myStorage->isEqual(aPointsToFind[i], aPointsToFind[j])) {
+        aSlvsOtherFlag = i;
+        aSlvsOther2Flag = j - 2;
+        isPointFound = true;
+      }
+  if (!isPointFound) {
+    // There is no coincident points between tangential objects. Generate error message
+    myErrorMsg = SketchSolver_Error::NO_COINCIDENT_POINTS();
     return;
   }
 
-  if (!hasSingleCoincidence(theAttributes[2], theAttributes[3]))
-    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-
-  if (isSwap) {
-    EntityWrapperPtr aTemp = theAttributes[2];
-    theAttributes[2] = theAttributes[3];
-    theAttributes[3] = aTemp;
-  }
+  Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+      getType(), myGroup->getWorkplaneId(), aValue,
+      SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, anEntities[0].h, anEntities[1].h);
+  aConstraint.other = aSlvsOtherFlag;
+  aConstraint.other2 = aSlvsOther2Flag;
+  aConstraint.h = myStorage->addConstraint(aConstraint);
+  mySlvsConstraints.push_back(aConstraint.h);
+  adjustConstraint();
 }
 
-
-////void SketchSolver_ConstraintTangent::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> anEntID;
-////  getAttributes(aValue, anEntID);
-////  if (!myErrorMsg.empty())
-////    return;
-////  // Check the quantity of entities of each type and their order (arcs first)
-////  int aNbLines = 0;
-////  int aNbArcs = 0;
-////  Slvs_Entity anEntities[2];
-////  myType = SLVS_C_CURVE_CURVE_TANGENT;
-////  std::vector<Slvs_hEntity>::iterator anEntIter = anEntID.begin();
-////  for (; anEntIter != anEntID.end(); anEntIter++) {
-////    Slvs_Entity anEnt = myStorage->getEntity(*anEntIter);
-////    if (anEnt.type == SLVS_E_LINE_SEGMENT) {
-////      if (aNbLines == 0)
-////        anEntities[1 + aNbLines] = anEnt;
-////      aNbLines++;
-////      myType = SLVS_C_ARC_LINE_TANGENT;
-////    }
-////    else if (anEnt.type == SLVS_E_ARC_OF_CIRCLE) {
-////      if (aNbArcs < 2)
-////        anEntities[aNbArcs] = anEnt;
-////      aNbArcs++;
-////    }
-////  }
-////
-////  if (aNbLines + aNbArcs != 2) {
-////    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-////    return;
-////  } else if (aNbArcs < 1) {
-////    myErrorMsg = SketchSolver_Error::INCORRECT_TANGENCY_ATTRIBUTE();
-////    return;
-////  }
-////
-////  // It is necessary to identify which points of entities are coincident
-////  int aSlvsOtherFlag = 0;
-////  int aSlvsOther2Flag = 0;
-////  // Obtain start and end points of entities
-////  Slvs_hEntity aPointsToFind[4];
-////  for (int i = 0; i < 2; i++) {
-////    int aShift = anEntities[i].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
-////    aPointsToFind[2*i]  = anEntities[i].point[aShift];
-////    aPointsToFind[2*i+1]= anEntities[i].point[aShift+1];
-////  }
-////  // Search coincident points
-////  bool isPointFound = false;
-////  for (int i = 0; i < 2 && !isPointFound; i++)
-////    for (int j = 2; j < 4 && !isPointFound; j++)
-////      if (myStorage->isEqual(aPointsToFind[i], aPointsToFind[j])) {
-////        aSlvsOtherFlag = i;
-////        aSlvsOther2Flag = j - 2;
-////        isPointFound = true;
-////      }
-////  if (!isPointFound) {
-////    // There is no coincident points between tangential objects. Generate error message
-////    myErrorMsg = SketchSolver_Error::NO_COINCIDENT_POINTS();
-////    return;
-////  }
-////
-////  Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
-////      getType(), myGroup->getWorkplaneId(), aValue,
-////      SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, anEntities[0].h, anEntities[1].h);
-////  aConstraint.other = aSlvsOtherFlag;
-////  aConstraint.other2 = aSlvsOther2Flag;
-////  aConstraint.h = myStorage->addConstraint(aConstraint);
-////  mySlvsConstraints.push_back(aConstraint.h);
-////  adjustConstraint();
-////}
-
index e1716bf74b5c4c493d20ec4c6a298c101b684122..a6c744e44e7ff7718981433fa52674a6fbc17bb2 100644 (file)
@@ -22,11 +22,15 @@ public:
       SketchSolver_Constraint(theConstraint)
   {}
 
+  virtual int getType() const
+  { return myType; }
+
 protected:
-  /// \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(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+  /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+  virtual void process();
+
+private:
+  int myType; ///< type of constraint (applicable: SLVS_C_ARC_LINE_TANGENT, SLVS_C_CURVE_CURVE_TANGENT)
 };
 
 #endif
diff --git a/src/SketchSolver/SketchSolver_FeatureStorage.cpp b/src/SketchSolver/SketchSolver_FeatureStorage.cpp
new file mode 100644 (file)
index 0000000..34d07b2
--- /dev/null
@@ -0,0 +1,418 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    SketchSolver_FeatureStorage.cpp
+// Created: 23 Mar 2015
+// Author:  Artem ZHIDKOV
+
+#include <SketchSolver_FeatureStorage.h>
+
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <GeomDataAPI_Point2D.h>
+
+void SketchSolver_FeatureStorage::changeConstraint(ConstraintPtr theConstraint)
+{
+  std::list<AttributePtr> anAttributes = theConstraint->data()->attributes(std::string());
+  std::list<AttributePtr>::iterator anIter = anAttributes.begin();
+  for (; anIter != anAttributes.end(); anIter++) {
+    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+    if (aRefAttr) {
+      if (!aRefAttr->isObject()) {
+        changeAttribute(aRefAttr->attr(), theConstraint);
+        continue;
+      }
+      ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+          aRefAttr->object());
+      FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
+          std::dynamic_pointer_cast<ModelAPI_Feature>(aRefAttr->object());
+      if (aFeature)
+        changeFeature(aFeature, theConstraint);
+      continue;
+    }
+    AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anIter);
+    if (aRefList) {
+      std::list<ObjectPtr> aList = aRefList->list();
+      std::list<ObjectPtr>::iterator aListIter = aList.begin();
+      for (; aListIter != aList.end(); aListIter++) {
+        ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+            *aListIter);
+        FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
+            std::dynamic_pointer_cast<ModelAPI_Feature>(*aListIter);
+        if (aFeature)
+          changeFeature(aFeature, theConstraint);
+      }
+      continue;
+    }
+    changeAttribute(*anIter, theConstraint);
+  }
+  myConstraints.insert(theConstraint);
+}
+
+void SketchSolver_FeatureStorage::removeConstraint(ConstraintPtr theConstraint)
+{
+  DataPtr aData = theConstraint->data();
+  if (aData) { // Constraint has data. Iterate through its attributes and remove them
+    std::list<AttributePtr> anAttributes = aData->attributes(std::string());
+    std::list<AttributePtr>::iterator anIter = anAttributes.begin();
+    for (; anIter != anAttributes.end(); anIter++) {
+      AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+      if (aRefAttr) {
+        if (!aRefAttr->isObject()) {
+          removeAttribute(aRefAttr->attr(), theConstraint);
+          continue;
+        }
+        ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+            aRefAttr->object());
+        FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
+            std::dynamic_pointer_cast<ModelAPI_Feature>(aRefAttr->object());
+        if (aFeature)
+          removeFeature(aFeature, theConstraint);
+        continue;
+      }
+      AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anIter);
+      if (aRefList) {
+        std::list<ObjectPtr> aList = aRefList->list();
+        std::list<ObjectPtr>::iterator aListIter = aList.begin();
+        for (; aListIter != aList.end(); aListIter++) {
+          ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+              *aListIter);
+          FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
+              std::dynamic_pointer_cast<ModelAPI_Feature>(*aListIter);
+          if (aFeature)
+            removeFeature(aFeature, theConstraint);
+        }
+        continue;
+      }
+      removeAttribute(*anIter, theConstraint);
+    }
+  } else { // Constraint has no data. Search the links on it in the lists of back references for features and attributes
+    std::set<ConstraintPtr>::iterator aCIter;
+    MapFeatureConstraint::iterator aFeatIter = myFeatures.begin();
+    while (aFeatIter != myFeatures.end()) {
+      aCIter = aFeatIter->second.find(theConstraint);
+      if (aCIter != aFeatIter->second.end()) {
+        FeaturePtr aFeature = aFeatIter->first;
+        aFeatIter++;
+        removeFeature(aFeature, theConstraint);
+        continue;
+      }
+      aFeatIter++;
+    }
+    std::set<FeaturePtr>::iterator aFIter;
+    MapAttributeFeature::iterator anAttrIter = myAttributes.begin();
+    while (anAttrIter != myAttributes.end()) {
+      aFIter = anAttrIter->second.find(theConstraint);
+      if (aFIter != anAttrIter->second.end()) {
+        anAttrIter->second.erase(aFIter);
+        if (anAttrIter->second.empty()) {
+          MapAttributeFeature::iterator aTmpIter = anAttrIter; // stores iterator for the next element, while the current is deleting
+          aTmpIter++;
+          myAttributes.erase(anAttrIter);
+          anAttrIter = aTmpIter;
+          continue;
+        }
+      }
+      anAttrIter++;
+    }
+  }
+  myConstraints.erase(theConstraint);
+}
+
+bool SketchSolver_FeatureStorage::isInteract(ConstraintPtr theConstraint) const
+{
+  if (myConstraints.empty() || myConstraints.find(theConstraint) != myConstraints.end())
+    return true;
+
+  DataPtr aData = theConstraint->data();
+  if (!aData)
+    return false;
+
+  std::list<AttributePtr> anAttributes = aData->attributes(std::string());
+  std::list<AttributePtr>::iterator anIter = anAttributes.begin();
+  for (; anIter != anAttributes.end(); anIter++) {
+    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+    if (aRefAttr) {
+      if (!aRefAttr->isObject()) {
+        if (isInteract(aRefAttr->attr()))
+          return true;
+        continue;
+      }
+      ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+          aRefAttr->object());
+      FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
+          std::dynamic_pointer_cast<ModelAPI_Feature>(aRefAttr->object());
+      if (aFeature)
+        if (isInteract(aFeature))
+          return true;
+      continue;
+    }
+    AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anIter);
+    if (aRefList) {
+      std::list<ObjectPtr> aList = aRefList->list();
+      std::list<ObjectPtr>::iterator aListIter = aList.begin();
+      for (; aListIter != aList.end(); aListIter++) {
+        ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+            *aListIter);
+        FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
+            std::dynamic_pointer_cast<ModelAPI_Feature>(*aListIter);
+        if (aFeature)
+          if (isInteract(aFeature))
+            return true;
+      }
+      continue;
+    }
+    if (isInteract(*anIter))
+      return true;
+  }
+  return false;
+}
+
+
+void SketchSolver_FeatureStorage::changeFeature(FeaturePtr theFeature)
+{
+  std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
+  std::list<AttributePtr>::iterator anIter = anAttributes.begin();
+  for (; anIter != anAttributes.end(); anIter++) {
+    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+    if (aRefAttr) {
+      if (!aRefAttr->isObject())
+        changeAttribute(aRefAttr->attr(), theFeature);
+      continue;
+    }
+    changeAttribute(*anIter, theFeature);
+  }
+  if (myFeatures.find(theFeature) == myFeatures.end())
+    myFeatures[theFeature] = std::set<ConstraintPtr>();
+}
+
+void SketchSolver_FeatureStorage::changeFeature(FeaturePtr theFeature, ConstraintPtr theConstraint)
+{
+  // Change all attributes of the feature
+  changeFeature(theFeature);
+  // Add back reference feature to constraint
+  myFeatures[theFeature].insert(theConstraint);
+}
+
+void SketchSolver_FeatureStorage::removeFeature(FeaturePtr theFeature)
+{
+  MapFeatureConstraint::iterator aFeatIter = myFeatures.find(theFeature);
+  if (aFeatIter == myFeatures.end())
+    return; // no such feature
+
+  std::set<ConstraintPtr> aConstraints = aFeatIter->second;
+  std::set<ConstraintPtr>::iterator aCIter = aConstraints.begin();
+  for (; aCIter != aConstraints.end(); aCIter++)
+    removeFeature(theFeature, *aCIter);
+}
+
+void SketchSolver_FeatureStorage::removeFeature(FeaturePtr theFeature, ConstraintPtr theConstraint)
+{
+  MapFeatureConstraint::iterator aFeatIter = myFeatures.find(theFeature);
+  if (aFeatIter == myFeatures.end())
+    return; // no such feature
+
+  if (theFeature->data()) {
+    std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
+    std::list<AttributePtr>::iterator anIter = anAttributes.begin();
+    for (; anIter != anAttributes.end(); anIter++) {
+      AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+      if (aRefAttr) {
+        if (!aRefAttr->isObject())
+          removeAttribute(aRefAttr->attr(), theFeature);
+        continue;
+      }
+      removeAttribute(*anIter, theFeature);
+    }
+  } else {
+    // iterate on attributes to find items refered to theFeature
+    MapAttributeFeature::iterator anIter = myAttributes.begin();
+    while (anIter != myAttributes.end()) {
+      if (anIter->second.find(theFeature) != anIter->second.end()) {
+        anIter->second.erase(theFeature);
+        if (anIter->second.empty()) {
+          MapAttributeFeature::iterator aDeadIter = anIter++;
+          myAttributes.erase(aDeadIter);
+          continue;
+        }
+      }
+      anIter++;
+    }
+  }
+
+  aFeatIter->second.erase(theConstraint);
+  if (aFeatIter->second.empty())
+    myFeatures.erase(aFeatIter);
+}
+
+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();
+  for (; anIter != anAttributes.end(); anIter++) {
+    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+    if (aRefAttr) {
+      if (!aRefAttr->isObject())
+        if (isInteract(aRefAttr->attr()))
+          return true;
+      continue;
+    }
+    if (isInteract(*anIter))
+      return true;
+  }
+  return false;
+}
+
+
+void SketchSolver_FeatureStorage::changeAttribute(AttributePtr theAttribute)
+{
+  if (myAttributes.find(theAttribute) == myAttributes.end())
+    myAttributes[theAttribute] = std::set<FeaturePtr>();
+}
+
+void SketchSolver_FeatureStorage::changeAttribute(AttributePtr theAttribute, FeaturePtr theFeature)
+{
+  MapAttributeFeature::iterator anAttrIter = myAttributes.find(theAttribute);
+  if (anAttrIter == myAttributes.end()) {
+    std::set<FeaturePtr> aFeatures;
+    aFeatures.insert(theFeature);
+    myAttributes[theAttribute] = aFeatures;
+    return;
+  }
+  anAttrIter->second.insert(theFeature);
+}
+
+void SketchSolver_FeatureStorage::removeAttribute(AttributePtr theAttribute)
+{
+  MapAttributeFeature::iterator anAttrIter = myAttributes.find(theAttribute);
+  if (anAttrIter == myAttributes.end())
+    return;
+
+  std::set<FeaturePtr> aFeatures = anAttrIter->second;
+  std::set<FeaturePtr>::iterator aFeatIter = aFeatures.begin();
+  for (; aFeatIter != aFeatures.end(); aFeatIter++)
+    removeAttribute(theAttribute, *aFeatIter);
+}
+
+void SketchSolver_FeatureStorage::removeAttribute(AttributePtr theAttribute, FeaturePtr theFeature)
+{
+  MapAttributeFeature::iterator anAttrIter = myAttributes.find(theAttribute);
+  if (anAttrIter == myAttributes.end())
+    return; // no such attribute
+
+  anAttrIter->second.erase(theFeature);
+  if (!anAttrIter->second.empty())
+    return;
+
+  // Check there is no features containing such attribute
+  MapFeatureConstraint::iterator aFeatIter = myFeatures.begin();
+  for (; aFeatIter != myFeatures.end(); aFeatIter++) {
+    DataPtr aData = aFeatIter->first->data();
+    if (!aData || !aData->isValid())
+      continue;
+    std::list<AttributePtr> anAttrList = aData->attributes(GeomDataAPI_Point2D::typeId());
+    std::list<AttributePtr>::iterator anAtIt = anAttrList.begin();
+    for (; anAtIt != anAttrList.end(); anAtIt++) {
+      std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anAtIt);
+      if (aPoint == theAttribute)
+        anAttrIter->second.insert(aFeatIter->first);
+    }
+  }
+  if (anAttrIter->second.empty())
+    myAttributes.erase(anAttrIter);
+}
+
+bool SketchSolver_FeatureStorage::isInteract(AttributePtr theAttribute) const
+{
+  return myAttributes.find(theAttribute) != myAttributes.end();
+}
+
+
+bool SketchSolver_FeatureStorage::isConsistent() const
+{
+  // Check the constraints are valid
+  std::set<ConstraintPtr>::const_iterator aCIter = myConstraints.begin();
+  for (; aCIter != myConstraints.end(); aCIter++)
+    if (!(*aCIter)->data() || !(*aCIter)->data()->isValid())
+      return false;
+  // Check the features are valid
+  MapFeatureConstraint::const_iterator aFIter = myFeatures.begin();
+  for (; aFIter != myFeatures.end(); aFIter++)
+    if (!aFIter->first->data() || !aFIter->first->data()->isValid())
+      return false;
+  return true;
+}
+
+std::set<ConstraintPtr> SketchSolver_FeatureStorage::getConstraints(FeaturePtr theFeature) const
+{
+  std::set<ConstraintPtr> aResult;
+  MapFeatureConstraint::const_iterator aFeatIter = myFeatures.find(theFeature);
+  if (aFeatIter != myFeatures.end())
+    aResult.insert(aFeatIter->second.begin(), aFeatIter->second.end());
+
+  std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
+  std::list<AttributePtr>::const_iterator anAttrIter = anAttributes.begin();
+  for (; anAttrIter != anAttributes.end(); anAttrIter++) {
+    MapAttributeFeature::const_iterator anIt = myAttributes.find(*anAttrIter);
+    if (anIt == myAttributes.end())
+      continue;
+    std::set<FeaturePtr>::const_iterator aFIter = anIt->second.begin();
+    for (; aFIter != anIt->second.end(); aFIter++) {
+      aFeatIter = myFeatures.find(*aFIter);
+      if (aFeatIter != myFeatures.end())
+        aResult.insert(aFeatIter->second.begin(), aFeatIter->second.end());
+      else {
+        ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(*aFIter);
+        if (aConstraint)
+          aResult.insert(aConstraint);
+      }
+    }
+  }
+  return aResult;
+}
+
+std::set<ConstraintPtr> SketchSolver_FeatureStorage::getConstraints(AttributePtr theAttribute) const
+{
+  std::set<ConstraintPtr> aResult;
+  MapAttributeFeature::const_iterator anIt = myAttributes.find(theAttribute);
+  if (anIt == myAttributes.end())
+    return aResult;
+  std::set<FeaturePtr>::const_iterator aFIter = anIt->second.begin();
+  MapFeatureConstraint::const_iterator aFeatIter;
+  for (; aFIter != anIt->second.end(); aFIter++) {
+    aFeatIter = myFeatures.find(*aFIter);
+    if (aFeatIter != myFeatures.end())
+      aResult.insert(aFeatIter->second.begin(), aFeatIter->second.end());
+    else {
+      ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(*aFIter);
+      if (aConstraint)
+        aResult.insert(aConstraint);
+    }
+  }
+  return aResult;
+}
+
+void SketchSolver_FeatureStorage::blockEvents(bool isBlocked) const
+{
+  std::set<ConstraintPtr>::iterator aCIter = myConstraints.begin();
+  for (; aCIter != myConstraints.end(); aCIter++)
+    if ((*aCIter)->data() && (*aCIter)->data()->isValid())
+      (*aCIter)->data()->blockSendAttributeUpdated(isBlocked);
+
+  MapFeatureConstraint::const_iterator aFIter = myFeatures.begin();
+  for (; aFIter != myFeatures.end(); aFIter++)
+    if (aFIter->first->data() && aFIter->first->data()->isValid())
+      aFIter->first->data()->blockSendAttributeUpdated(isBlocked);
+
+  MapAttributeFeature::const_iterator anAtIter = myAttributes.begin();
+  for (; anAtIter != myAttributes.end(); anAtIter++)
+    if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
+        anAtIter->first->owner()->data()->isValid())
+      anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
+}
diff --git a/src/SketchSolver/SketchSolver_FeatureStorage.h b/src/SketchSolver/SketchSolver_FeatureStorage.h
new file mode 100644 (file)
index 0000000..2cb36ba
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    SketchSolver_FeatureStorage.h
+// Created: 23 Mar 2015
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchSolver_FeatureStorage_H_
+#define SketchSolver_FeatureStorage_H_
+
+#include <SketchSolver.h>
+#include <SketchPlugin_Feature.h>
+#include <SketchPlugin_Constraint.h>
+
+#include <set>
+#include <map>
+
+typedef std::map<FeaturePtr, std::set<ConstraintPtr> > MapFeatureConstraint;
+typedef std::map<AttributePtr, std::set<FeaturePtr> >  MapAttributeFeature;
+
+/** \class   SketchSolver_FeatureStorage
+ *  \ingroup Plugins
+ *  \brief   Collects information about SketchPlugin constraints used in specific group
+ */
+class SketchSolver_FeatureStorage
+{
+public:
+  SketchSolver_FeatureStorage() {}
+
+  /// \brief Adds or changes a constraint and all features it uses in the storage
+  void changeConstraint(ConstraintPtr theConstraint);
+  /// \brief Removes a constraint and all its features not used by other constraints
+  void removeConstraint(ConstraintPtr theConstraint);
+  /// \brief Verifies a constraint is used in the current storage
+  bool isInteract(ConstraintPtr theConstraint) const;
+
+  /// \brief Adds or changes a feature in the storage
+  void changeFeature(FeaturePtr theFeature);
+  /// \brief Adds or changes a feature in the storage. The feature is used in specified constraint
+  void changeFeature(FeaturePtr theFeature, ConstraintPtr theConstraint);
+  /// \brief Removes a feature
+  void removeFeature(FeaturePtr theFeature);
+  /// \brief Removes a feature according to a given constraint
+  void removeFeature(FeaturePtr theFeature, ConstraintPtr theConstraint);
+  /// \brief Verifies a feature is used in the current storage
+  bool isInteract(FeaturePtr theFeature) const;
+
+  /// \brief Adds or changes an attribute in the storage
+  void changeAttribute(AttributePtr theAttribute);
+  /// \brief Adds or changes a attribute in the storage.
+  ///        The attribute is used in specified feature or constraint (theFeature)
+  void changeAttribute(AttributePtr theAttribute, FeaturePtr theFeature);
+  /// \brief Removes an attribute
+  void removeAttribute(AttributePtr theAttribute);
+  /// \brief Removes an attribute according to a given feature
+  void removeAttribute(AttributePtr theAttribute, FeaturePtr theFeature);
+  /// \brief Verifies an attribute is used in the current storage
+  bool isInteract(AttributePtr theAttribute) const;
+
+  /// \brief Check the features is not removed
+  bool isConsistent() const;
+
+  /// \brief Prepares list of constraints, which using specified feature or its attributes
+  std::set<ConstraintPtr> getConstraints(FeaturePtr theFeature) const;
+  /// \brief Prepares list of constraints, which using specified attribute
+  std::set<ConstraintPtr> getConstraints(AttributePtr theAttribute) const;
+
+  /// \brief Block/unblock events of changing attributes of the features
+  void blockEvents(bool isBlocked) const;
+
+private:
+  std::set<ConstraintPtr> myConstraints; ///< list of SketchPlugin constraints used in the current group
+  MapFeatureConstraint myFeatures; ///< list of features used in the group and corresponding constraints which use the feature
+  MapAttributeFeature myAttributes; ///< list of attributes used in the group and corresponding features which are based on the attribute
+};
+
+typedef std::shared_ptr<SketchSolver_FeatureStorage> FeatureStoragePtr;
+
+#endif // SketchSolver_FeatureStorage_H_
index f4ba30c83ba97cd9ad720712f6be25c5eace4781..9ad17d7508f15014737c74e2dbe5357fffea7b1e 100644 (file)
@@ -6,30 +6,29 @@
 
 #include "SketchSolver_Group.h"
 
+#include <SketchSolver_Builder.h>
 #include <SketchSolver_Constraint.h>
 #include <SketchSolver_ConstraintCoincidence.h>
 #include <SketchSolver_ConstraintMulti.h>
 #include <SketchSolver_Error.h>
-////#include <SketchSolver_Builder.h>
-#include <SketchSolver_Manager.h>
 
 #include <Events_Error.h>
 #include <Events_Loop.h>
-////#include <GeomAPI_XY.h>
-////#include <GeomAPI_Dir2d.h>
-////#include <GeomAPI_Pnt2d.h>
-////#include <GeomDataAPI_Dir.h>
-////#include <GeomDataAPI_Point.h>
-////#include <GeomDataAPI_Point2D.h>
-////#include <ModelAPI_AttributeDouble.h>
+#include <GeomAPI_XY.h>
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomDataAPI_Dir.h>
+#include <GeomDataAPI_Point.h>
+#include <GeomDataAPI_Point2D.h>
+#include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeString.h>
-////#include <ModelAPI_Document.h>
+#include <ModelAPI_Document.h>
 #include <ModelAPI_Events.h>
-////#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
-////
-////#include <SketchPlugin_Constraint.h>
+
+#include <SketchPlugin_Constraint.h>
 #include <SketchPlugin_ConstraintAngle.h>
 #include <SketchPlugin_ConstraintCoincidence.h>
 #include <SketchPlugin_ConstraintDistance.h>
 #include <SketchPlugin_ConstraintRigid.h>
 #include <SketchPlugin_ConstraintTangent.h>
 #include <SketchPlugin_ConstraintVertical.h>
-////#include <SketchPlugin_Feature.h>
+#include <SketchPlugin_Feature.h>
 #include <SketchPlugin_MultiRotation.h>
 #include <SketchPlugin_MultiTranslation.h>
-////#include <SketchPlugin_Sketch.h>
-////
-////#include <SketchPlugin_Arc.h>
-////#include <SketchPlugin_Circle.h>
-////#include <SketchPlugin_Line.h>
-////#include <SketchPlugin_Point.h>
-////#include <SketchPlugin_Sketch.h>
+#include <SketchPlugin_Sketch.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
+#include <SketchPlugin_Sketch.h>
 
 #include <math.h>
 #include <assert.h>
@@ -64,9 +63,9 @@ class GroupIndexer
 {
 public:
   /// \brief Return vacant index
-  static GroupID NEW_GROUP() { return ++myGroupIndex; }
+  static Slvs_hGroup NEW_GROUP() { return ++myGroupIndex; }
   /// \brief Removes the index
-  static void REMOVE_GROUP(const GroupID& theIndex) {
+  static void REMOVE_GROUP(const Slvs_hGroup& theIndex) {
     if (myGroupIndex == theIndex)
       myGroupIndex--;
   }
@@ -74,10 +73,10 @@ public:
 private:
   GroupIndexer() {};
 
-  static GroupID myGroupIndex; ///< index of the group
+  static Slvs_hGroup myGroupIndex; ///< index of the group
 };
 
-GroupID GroupIndexer::myGroupIndex = GID_OUTOFGROUP;
+Slvs_hGroup GroupIndexer::myGroupIndex = SLVS_G_OUTOFGROUP;
 
 
 static void sendMessage(const char* theMessageName)
@@ -99,8 +98,12 @@ SketchSolver_Group::SketchSolver_Group(
       myPrevSolved(true)
 {
   // Initialize workplane
-  myWorkplaneID = EID_UNKNOWN;
+  myWorkplaneID = SLVS_E_UNKNOWN;
+#ifndef NDEBUG
+  assert(addWorkplane(theWorkplane));
+#else
   addWorkplane(theWorkplane);
+#endif
 }
 
 SketchSolver_Group::~SketchSolver_Group()
@@ -124,13 +127,85 @@ bool SketchSolver_Group::isBaseWorkplane(CompositeFeaturePtr theWorkplane) const
 //  Class:    SketchSolver_Group
 //  Purpose:  verify are there any entities in the group used by given constraint
 // ============================================================================
-bool SketchSolver_Group::isInteract(FeaturePtr theFeature) const
+bool SketchSolver_Group::isInteract(
+    std::shared_ptr<SketchPlugin_Feature> theFeature) const
 {
   // Empty group interacts with everything
-  if (isEmpty())
-    return true;
-  // Check interaction with the storage
-  return myStorage->isInteract(theFeature);
+  if (isEmpty()) return true;
+  ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
+  if (aConstraint)
+    return myFeatureStorage->isInteract(aConstraint);
+  return myFeatureStorage->isInteract(std::dynamic_pointer_cast<ModelAPI_Feature>(theFeature));
+}
+
+// check the entity is really exists
+static void checkEntity(StoragePtr theStorage, Slvs_hEntity& theEntity)
+{
+  if (theEntity == SLVS_E_UNKNOWN)
+    return;
+  Slvs_Entity anEnt = theStorage->getEntity(theEntity);
+  theEntity = anEnt.h;
+}
+
+// ============================================================================
+//  Function: getFeatureId
+//  Class:    SketchSolver_Group
+//  Purpose:  Find the identifier of the feature, if it already exists in the group
+// ============================================================================
+Slvs_hEntity SketchSolver_Group::getFeatureId(FeaturePtr theFeature) const
+{
+  Slvs_hEntity aResult = SLVS_E_UNKNOWN;
+  if (!myFeatureStorage)
+    return aResult;
+  // Obtain regular constraints interacting with the feature and find its ID
+  ConstraintConstraintMap::const_iterator aCIter = myConstraints.begin();
+  for (; aCIter != myConstraints.end(); ++aCIter) {
+    aResult = aCIter->second->getId(theFeature);
+    checkEntity(myStorage, aResult);
+    if (aResult != SLVS_E_UNKNOWN)
+      return aResult;
+  }
+  // The feature is not found, check it in the temporary constraints
+  std::set<SolverConstraintPtr>::iterator aTmpCIter = myTempConstraints.begin();
+  for (; aTmpCIter != myTempConstraints.end() && aResult == SLVS_E_UNKNOWN; ++aTmpCIter) {
+    aResult = (*aTmpCIter)->getId(theFeature);
+    checkEntity(myStorage, aResult);
+  }
+  return aResult;
+}
+
+// ============================================================================
+//  Function: getAttributeId
+//  Class:    SketchSolver_Group
+//  Purpose:  Find the identifier of the attribute, if it already exists in the group
+// ============================================================================
+Slvs_hEntity SketchSolver_Group::getAttributeId(AttributePtr theAttribute) const
+{
+  Slvs_hEntity aResult = SLVS_E_UNKNOWN;
+  if (!myFeatureStorage)
+    return aResult;
+  // Obtain regular constraints interacting with the attribute and find its ID
+  ConstraintConstraintMap::const_iterator aCIter = myConstraints.begin();
+  for (; aCIter != myConstraints.end(); ++aCIter) {
+    aResult = aCIter->second->getId(theAttribute);
+    checkEntity(myStorage, aResult);
+    if (aResult != SLVS_E_UNKNOWN)
+      return aResult;
+  }
+  // The attribute is not found, check it in the temporary constraints
+  std::set<SolverConstraintPtr>::const_iterator aTmpCIter = myTempConstraints.begin();
+  for (; aTmpCIter != myTempConstraints.end() && aResult == SLVS_E_UNKNOWN; ++aTmpCIter) {
+    aResult = (*aTmpCIter)->getId(theAttribute);
+    checkEntity(myStorage, aResult);
+  }
+  // Last chance to find attribute in parametric constraints
+  std::map<AttributePtr, SolverConstraintPtr>::const_iterator aParIter =
+      myParametricConstraints.find(theAttribute);
+  if (aParIter != myParametricConstraints.end()) {
+    aResult = aParIter->second->getId(theAttribute);
+    checkEntity(myStorage, aResult);
+  }
+  return aResult;
 }
 
 // ============================================================================
@@ -142,7 +217,7 @@ bool SketchSolver_Group::changeConstraint(
     std::shared_ptr<SketchPlugin_Constraint> theConstraint)
 {
   // There is no workplane yet, something wrong
-  if (myWorkplaneID == EID_UNKNOWN)
+  if (myWorkplaneID == SLVS_E_UNKNOWN)
     return false;
 
   if (!theConstraint || !theConstraint->data())
@@ -151,127 +226,130 @@ bool SketchSolver_Group::changeConstraint(
   if (!checkFeatureValidity(theConstraint))
     return false;
 
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
   bool isNewConstraint = myConstraints.find(theConstraint) == myConstraints.end();
   if (isNewConstraint) {
     // Add constraint to the current group
-    SolverConstraintPtr aConstraint = aBuilder->createConstraint(theConstraint);
+    SolverConstraintPtr aConstraint =
+        SketchSolver_Builder::getInstance()->createConstraint(theConstraint);
     if (!aConstraint)
       return false;
-    aConstraint->process(myStorage, getId(), getWorkplaneId());
+    aConstraint->setGroup(this);
+    aConstraint->setStorage(myStorage);
     if (!aConstraint->error().empty()) {
       if (aConstraint->error() == SketchSolver_Error::NOT_INITIALIZED())
         return false; // some attribute are not initialized yet, don't show message
       Events_Error::send(aConstraint->error(), this);
     }
 
-////    // Additional verification of coincidence of several points
-////    if (aConstraint->getType() == CONSTRAINT_PT_PT_COINCIDENT) {
-////      bool hasMultiCoincidence = false;
-////      std::shared_ptr<SketchSolver_ConstraintCoincidence> aCoincidence =
-////          std::dynamic_pointer_cast<SketchSolver_ConstraintCoincidence>(aConstraint);
-////
-////      ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
-////      for (; aCIter != myConstraints.end(); ++aCIter) {
-////        if (aCIter->second->getType() != CONSTRAINT_PT_PT_COINCIDENT)
-////          continue;
-////
-////        std::shared_ptr<SketchSolver_ConstraintCoincidence> aCurCoinc =
-////          std::dynamic_pointer_cast<SketchSolver_ConstraintCoincidence>(aCIter->second);
-////        if (aCoincidence != aCurCoinc && aCurCoinc->isCoincide(aCoincidence)) {
-////          aCoincidence->attach(aCurCoinc);
-////////          // update other coincidences
-////////          ConstraintConstraintMap::iterator anIt = aCIter;
-////////          for (++anIt; anIt != myConstraints.end(); ++anIt)
-////////            if (anIt->second == aCIter->second)
-////////              anIt->second = aCoincidence;
-////          aCIter->second = aCoincidence;
-////          hasMultiCoincidence = true;
-////        }
-////      }
-////
-////      if (hasMultiCoincidence)
-////        notifyMultiConstraints();
-////    }
+    // Additional verification of coincidence of several points
+    if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
+      bool hasMultiCoincidence = false;
+      ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
+      for (; aCIter != myConstraints.end(); ++aCIter) {
+        std::shared_ptr<SketchSolver_ConstraintCoincidence> aCoincidence =
+          std::dynamic_pointer_cast<SketchSolver_ConstraintCoincidence>(aCIter->second);
+        if (!aCoincidence)
+          continue;
+        std::shared_ptr<SketchSolver_ConstraintCoincidence> aCoinc2 =
+          std::dynamic_pointer_cast<SketchSolver_ConstraintCoincidence>(aConstraint);
+        if (aCoincidence != aCoinc2 && aCoincidence->isCoincide(aCoinc2)) {
+          aCoinc2->attach(aCoincidence);
+          // update other coincidences
+          ConstraintConstraintMap::iterator anIt = aCIter;
+          for (++anIt; anIt != myConstraints.end(); ++anIt)
+            if (anIt->second == aCIter->second)
+              anIt->second = aCoinc2;
+          aCIter->second = aCoinc2;
+          hasMultiCoincidence = true;
+        }
+      }
+
+      if (hasMultiCoincidence)
+        notifyMultiConstraints();
+    }
     myConstraints[theConstraint] = aConstraint;
   }
   else
     myConstraints[theConstraint]->update();
 
-////  // Fix base features for fillet
-////  if (isNewConstraint && theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) {
-////    std::list<AttributePtr> anAttrList =
-////        theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
-////    std::list<AttributePtr>::iterator anAttrIter = anAttrList.begin();
-////    for (; anAttrIter != anAttrList.end(); anAttrIter++) {
-////      AttributeRefAttrPtr aRefAttr =
-////          std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
-////      if (!aRefAttr || !aRefAttr->isObject())
-////        continue;
-////      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
-////      SolverConstraintPtr aConstraint = aBuilder->createRigidConstraint(aFeature);
-////      if (!aConstraint)
-////        continue;
-////      aConstraint->setGroup(this);
-////      aConstraint->setStorage(myStorage);
-////      setTemporary(aConstraint);
-////    }
-////  }
-
+  // Fix base features for fillet
+  if (isNewConstraint && theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) {
+    std::list<AttributePtr> anAttrList =
+        theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
+    std::list<AttributePtr>::iterator anAttrIter = anAttrList.begin();
+    for (; anAttrIter != anAttrList.end(); anAttrIter++) {
+      AttributeRefAttrPtr aRefAttr =
+          std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
+      if (!aRefAttr || !aRefAttr->isObject())
+        continue;
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+      SolverConstraintPtr aConstraint =
+          SketchSolver_Builder::getInstance()->createRigidConstraint(aFeature);
+      if (!aConstraint)
+        continue;
+      aConstraint->setGroup(this);
+      aConstraint->setStorage(myStorage);
+      setTemporary(aConstraint);
+    }
+  }
   // Fix mirror line
   if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
         theConstraint->attribute(SketchPlugin_ConstraintMirror::ENTITY_A()));
     if (aRefAttr && aRefAttr->isObject()) {
-      std::shared_ptr<SketchPlugin_Feature> aFeature =
-          std::dynamic_pointer_cast<SketchPlugin_Feature>(
-          ModelAPI_Feature::feature(aRefAttr->object()));
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
       if (aFeature) {
-        SolverConstraintPtr aConstraint = aBuilder->createFixedConstraint(aFeature);
+        SolverConstraintPtr aConstraint =
+            SketchSolver_Builder::getInstance()->createRigidConstraint(aFeature);
         if (aConstraint) {
-          aConstraint->process(myStorage, getId(), getWorkplaneId());
+          aConstraint->setGroup(this);
+          aConstraint->setStorage(myStorage);
           setTemporary(aConstraint);
         }
       }
     }
   }
 
-////  // Check the attributes of constraint are given by parametric expression
-////  std::list<AttributePtr> anAttributes =
-////      theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
-////  std::list<AttributePtr>::iterator anAttrIt = anAttributes.begin();
-////  for (; anAttrIt != anAttributes.end(); ++anAttrIt) {
-////    AttributeRefAttrPtr aRefAttr =
-////        std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIt);
-////    if (!aRefAttr)
-////      continue;
-////
-////    std::shared_ptr<GeomDataAPI_Point2D> aPoint;
-////    if (aRefAttr->isObject()) {
-////      FeaturePtr aFeat = ModelAPI_Feature::feature(aRefAttr->object());
-////      if (aFeat->getKind() != SketchPlugin_Point::ID())
-////        continue;
-////      aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-////          aFeat->attribute(SketchPlugin_Point::COORD_ID()));
-////    } else
-////      aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
-////
-////    if (!aPoint || (aPoint->textX().empty() && aPoint->textY().empty()))
-////      continue;
-////
-////    std::map<AttributePtr, SolverConstraintPtr>::iterator aFound =
-////        myParametricConstraints.find(aPoint);
-////    if (aFound == myParametricConstraints.end()) {
-////      SolverConstraintPtr aConstraint = aBuilder->createParametricConstraint(aPoint);
-////      if (!aConstraint)
-////        continue;
-////      aConstraint->setGroup(this);
-////      aConstraint->setStorage(myStorage);
-////      myParametricConstraints[aPoint] = aConstraint;
-////    } else
-////      aFound->second->update();
-////  }
+  if (!myFeatureStorage)
+    myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage);
+  myFeatureStorage->changeConstraint(theConstraint);
+
+  // Check the attributes of constraint are given by parametric expression
+  std::list<AttributePtr> anAttributes =
+      theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
+  std::list<AttributePtr>::iterator anAttrIt = anAttributes.begin();
+  for (; anAttrIt != anAttributes.end(); ++anAttrIt) {
+    AttributeRefAttrPtr aRefAttr =
+        std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIt);
+    if (!aRefAttr)
+      continue;
+
+    std::shared_ptr<GeomDataAPI_Point2D> aPoint;
+    if (aRefAttr->isObject()) {
+      FeaturePtr aFeat = ModelAPI_Feature::feature(aRefAttr->object());
+      if (aFeat->getKind() != SketchPlugin_Point::ID())
+        continue;
+      aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+          aFeat->attribute(SketchPlugin_Point::COORD_ID()));
+    } else
+      aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
+
+    if (!aPoint || (aPoint->textX().empty() && aPoint->textY().empty()))
+      continue;
+
+    std::map<AttributePtr, SolverConstraintPtr>::iterator aFound =
+        myParametricConstraints.find(aPoint);
+    if (aFound == myParametricConstraints.end()) {
+      SolverConstraintPtr aConstraint =
+          SketchSolver_Builder::getInstance()->createParametricConstraint(aPoint);
+      if (!aConstraint)
+        continue;
+      aConstraint->setGroup(this);
+      aConstraint->setStorage(myStorage);
+      myParametricConstraints[aPoint] = aConstraint;
+    } else
+      aFound->second->update();
+  }
 
   return true;
 }
@@ -300,63 +378,105 @@ void SketchSolver_Group::updateConstraints()
   myChangedConstraints.clear();
 }
 
-bool SketchSolver_Group::updateFeature(FeaturePtr theFeature)
+bool SketchSolver_Group::updateFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
 {
   if (!checkFeatureValidity(theFeature))
     return false;
 
-  bool isUpdated = myStorage->update(theFeature);
-
-////  // Search attributes of the feature in the set of parametric constraints and update them
-////  std::list<AttributePtr> anAttrList =
-////      theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
-////  std::list<AttributePtr>::iterator anAttrIt = anAttrList.begin();
-////  for (; anAttrIt != anAttrList.end(); ++anAttrIt) {
-////    std::map<AttributePtr, SolverConstraintPtr>::iterator aFound =
-////        myParametricConstraints.find(*anAttrIt);
-////    if (aFound != myParametricConstraints.end())
-////      aFound->second->update();
-////    else {
-////      std::shared_ptr<GeomDataAPI_Point2D> aPoint =
-////          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anAttrIt);
-////      if (aPoint && (!aPoint->textX().empty() || !aPoint->textY().empty())) {
-////        // Create new parametric constraint
-////        SolverConstraintPtr aConstraint =
-////            SketchSolver_Builder::getInstance()->createParametricConstraint(*anAttrIt);
-////        if (!aConstraint)
-////          continue;
-////        aConstraint->setGroup(this);
-////        aConstraint->setStorage(myStorage);
-////        myParametricConstraints[*anAttrIt] = aConstraint;
-////      }
-////    }
-////  }
-  return isUpdated;
-}
+  std::set<ConstraintPtr> aConstraints =
+      myFeatureStorage->getConstraints(std::dynamic_pointer_cast<ModelAPI_Feature>(theFeature));
+  if (aConstraints.empty())
+    return false;
+  std::set<ConstraintPtr>::iterator aCIter = aConstraints.begin();
+  for (; aCIter != aConstraints.end(); aCIter++) {
+    ConstraintConstraintMap::iterator aSolConIter = myConstraints.find(*aCIter);
+    if (aSolConIter == myConstraints.end() || !aSolConIter->first->data() ||
+        !aSolConIter->first->data()->isValid())
+      continue;
+    myFeatureStorage->changeFeature(theFeature, aSolConIter->first);
 
-void SketchSolver_Group::moveFeature(FeaturePtr theFeature)
-{
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
-  // Firstly, revert changes in the fixed entities
-  myStorage->refresh(true);
-
-  // Secondly, search attributes of the feature in the list of the Multi constraints and update them
-  ConstraintConstraintMap::iterator aCIt = myConstraints.begin();
-  for (; aCIt != myConstraints.end(); ++aCIt) {
-    if ((aCIt->second->getType() == CONSTRAINT_MULTI_ROTATION ||
-         aCIt->second->getType() == CONSTRAINT_MULTI_TRANSLATION)
-        && aCIt->second->isUsed(theFeature))
-      std::dynamic_pointer_cast<SketchSolver_ConstraintMulti>(aCIt->second)->update(true);
+    aSolConIter->second->addFeature(theFeature);
+    myChangedConstraints.insert(aSolConIter->first);
+  }
+
+  // Search attributes of the feature in the set of parametric constraints and update them
+  std::list<AttributePtr> anAttrList =
+      theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+  std::list<AttributePtr>::iterator anAttrIt = anAttrList.begin();
+  for (; anAttrIt != anAttrList.end(); ++anAttrIt) {
+    std::map<AttributePtr, SolverConstraintPtr>::iterator aFound =
+        myParametricConstraints.find(*anAttrIt);
+    if (aFound != myParametricConstraints.end())
+      aFound->second->update();
+    else {
+      std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anAttrIt);
+      if (aPoint && (!aPoint->textX().empty() || !aPoint->textY().empty())) {
+        // Create new parametric constraint
+        SolverConstraintPtr aConstraint =
+            SketchSolver_Builder::getInstance()->createParametricConstraint(*anAttrIt);
+        if (!aConstraint)
+          continue;
+        aConstraint->setGroup(this);
+        aConstraint->setStorage(myStorage);
+        myParametricConstraints[*anAttrIt] = aConstraint;
+      }
+    }
   }
+  return true;
+}
 
-  // Then, create temporary rigid constraint
-  SolverConstraintPtr aConstraint = aBuilder->createMovementConstraint(theFeature);
+void SketchSolver_Group::moveFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
+{
+  // Firstly, create temporary rigid constraint
+  SolverConstraintPtr aConstraint =
+      SketchSolver_Builder::getInstance()->createMovementConstraint(theFeature);
   if (!aConstraint)
     return;
-  aConstraint->process(myStorage, getId(), getWorkplaneId());
+  aConstraint->setGroup(this);
+  aConstraint->setStorage(myStorage);
   if (aConstraint->error().empty())
     setTemporary(aConstraint);
+  // Secondly, update the feature
+  updateFeature(theFeature);
+}
+
+// ============================================================================
+//  Function: fixFeaturesList
+//  Class:    SketchSolver_Group
+//  Purpose:  Apply temporary rigid constraints for the list of features
+// ============================================================================
+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(*aFeatIter);
+    if (!aConstraint)
+      continue;
+    aConstraint->setGroup(this);
+    aConstraint->setStorage(myStorage);
+    setTemporary(aConstraint);
+  }
 }
 
 // ============================================================================
@@ -366,14 +486,11 @@ void SketchSolver_Group::moveFeature(FeaturePtr theFeature)
 // ============================================================================
 bool SketchSolver_Group::addWorkplane(CompositeFeaturePtr theSketch)
 {
-  if (myWorkplaneID != EID_UNKNOWN || theSketch->getKind() != SketchPlugin_Sketch::ID())
+  if (myWorkplaneID != SLVS_E_UNKNOWN || theSketch->getKind() != SketchPlugin_Sketch::ID())
     return false;  // the workplane already exists or the function parameter is not Sketch
 
   mySketch = theSketch;
-  if (!updateWorkplane()) {
-    mySketch = CompositeFeaturePtr();
-    return false;
-  }
+  updateWorkplane();
   return true;
 }
 
@@ -384,17 +501,55 @@ bool SketchSolver_Group::addWorkplane(CompositeFeaturePtr theSketch)
 // ============================================================================
 bool SketchSolver_Group::updateWorkplane()
 {
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
   if (!myStorage) // Create storage if not exists
-    myStorage = aBuilder->createStorage(getId());
+    myStorage = StoragePtr(new SketchSolver_Storage);
+  SketchSolver_Builder* aBuilder = SketchSolver_Builder::getInstance();
 
-  // sketch should be unchanged, set it out of current group
-  bool isUpdated = myStorage->update(FeaturePtr(mySketch), GID_OUTOFGROUP);
-  if (isUpdated) {
-    EntityWrapperPtr anEntity = myStorage->entity(FeaturePtr(mySketch));
-    myWorkplaneID = anEntity->id();
+  std::vector<Slvs_Entity> anEntities;
+  std::vector<Slvs_Param> aParams;
+  if (!aBuilder->createWorkplane(mySketch, anEntities, aParams))
+    return false;
+
+  if (myWorkplaneID == SLVS_E_UNKNOWN) {
+    myWorkplaneID = anEntities.back().h;
+    // Add new workplane elements
+    std::vector<Slvs_Param>::iterator aParIter = aParams.begin();
+    for (; aParIter != aParams.end(); aParIter++) {
+      aParIter->h = SLVS_E_UNKNOWN; // the ID should be generated by storage
+      aParIter->group = SLVS_G_OUTOFGROUP;
+      aParIter->h = myStorage->addParameter(*aParIter);
+    }
+    std::vector<Slvs_Entity>::iterator anEntIter = anEntities.begin();
+    for (; anEntIter != anEntities.end(); anEntIter++) {
+      anEntIter->h = SLVS_E_UNKNOWN; // the ID should be generated by storage
+      anEntIter->group = SLVS_G_OUTOFGROUP;
+      anEntIter->wrkpl = myWorkplaneID;
+      for (int i = 0; i < 4; i++)
+        if (anEntIter->param[i] != SLVS_E_UNKNOWN)
+          anEntIter->param[i] = aParams[anEntIter->param[i]-1].h;
+      for (int i = 0; i < 4; i++)
+        if (anEntIter->point[i] != SLVS_E_UNKNOWN)
+          anEntIter->point[i] = anEntities[anEntIter->point[i]-1].h;
+      anEntIter->h = myStorage->addEntity(*anEntIter);
+    }
+  } else {
+    // Update existent workplane
+    const Slvs_Entity& aWP = myStorage->getEntity(myWorkplaneID);
+    const Slvs_Entity& anOrigin = myStorage->getEntity(aWP.point[0]);
+    const Slvs_Entity& aNormal = myStorage->getEntity(aWP.normal);
+    // Get parameters and update them
+    Slvs_hParam aWPParams[7] = {
+        anOrigin.param[0], anOrigin.param[1], anOrigin.param[2],
+        aNormal.param[0], aNormal.param[1], aNormal.param[2], aNormal.param[3]
+      };
+    std::vector<Slvs_Param>::iterator aParIter = aParams.begin();
+    for (int i = 0; aParIter != aParams.end(); aParIter++, i++) {
+      Slvs_Param aParam = myStorage->getParameter(aWPParams[i]);
+      aParam.val = aParIter->val;
+      myStorage->updateParameter(aParam);
+    }
   }
-  return isUpdated;
+  return myWorkplaneID > 0;
 }
 
 // ============================================================================
@@ -410,36 +565,33 @@ bool SketchSolver_Group::resolveConstraints()
   bool aResolved = false;
   bool isGroupEmpty = isEmpty();
   if (myStorage->isNeedToResolve() && !isGroupEmpty) {
-    if (!mySketchSolver)
-      mySketchSolver = SketchSolver_Manager::instance()->builder()->createSolver();
-
-    mySketchSolver->setGroup(myID);
-    mySketchSolver->calculateFailedConstraints(false);
-    myStorage->initializeSolver(mySketchSolver);
+    myConstrSolver.setGroupID(myID);
+    myConstrSolver.calculateFailedConstraints(false);
+    myStorage->initializeSolver(myConstrSolver);
 
-    SketchSolver_SolveStatus aResult = STATUS_OK;
+    int aResult = SLVS_RESULT_OKAY;
     try {
       if (myStorage->hasDuplicatedConstraint())
-        aResult = STATUS_INCONSISTENT;
+        aResult = SLVS_RESULT_INCONSISTENT;
       else {
         // To avoid overconstraint situation, we will remove temporary constraints one-by-one
         // and try to find the case without overconstraint
         bool isLastChance = false;
-        size_t aNbTemp = myStorage->nbTemporary();
+        int aNbTemp = myStorage->numberTemporary();
         while (true) {
-          aResult = mySketchSolver->solve();
-          if (aResult == STATUS_OK || aResult == STATUS_EMPTYSET || isLastChance)
+          aResult = myConstrSolver.solve();
+          if (aResult == SLVS_RESULT_OKAY || isLastChance)
             break;
-          if (aNbTemp == 0) {
+          if (aNbTemp <= 0) {
             // try to update parameters and resolve once again
             ConstraintConstraintMap::iterator aConstrIt = myConstraints.begin();
             for (; aConstrIt != myConstraints.end(); ++aConstrIt)
               aConstrIt->second->update();
             isLastChance = true;
           } else
-            aNbTemp = myStorage->removeTemporary();
-          mySketchSolver->calculateFailedConstraints(true); // something failed => need to find it
-          myStorage->initializeSolver(mySketchSolver);
+            aNbTemp = myStorage->deleteTemporaryConstraint();
+          myConstrSolver.calculateFailedConstraints(true); // something failed => need to find it
+          myStorage->initializeSolver(myConstrSolver);
         }
       }
     } catch (...) {
@@ -452,18 +604,17 @@ bool SketchSolver_Group::resolveConstraints()
       }
       return false;
     }
-    if (aResult == STATUS_OK || aResult == STATUS_EMPTYSET) {  // solution succeeded, store results into correspondent attributes
-      myStorage->refresh();
-////      myFeatureStorage->blockEvents(true);
-////      // First refresh parametric constraints to satisfy parameters
-////      std::map<AttributePtr, SolverConstraintPtr>::iterator aParIter = myParametricConstraints.begin();
-////      for (; aParIter != myParametricConstraints.end(); ++aParIter)
-////        aParIter->second->refresh();
-////      // Update all other constraints
-////      ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin();
-////      for (; aConstrIter != myConstraints.end(); ++aConstrIter)
-////        aConstrIter->second->refresh();
-////      myFeatureStorage->blockEvents(false);
+    if (aResult == SLVS_RESULT_OKAY) {  // solution succeeded, store results into correspondent attributes
+      myFeatureStorage->blockEvents(true);
+      // First refresh parametric constraints to satisfy parameters
+      std::map<AttributePtr, SolverConstraintPtr>::iterator aParIter = myParametricConstraints.begin();
+      for (; aParIter != myParametricConstraints.end(); ++aParIter)
+        aParIter->second->refresh();
+      // Update all other constraints
+      ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin();
+      for (; aConstrIter != myConstraints.end(); ++aConstrIter)
+        aConstrIter->second->refresh();
+      myFeatureStorage->blockEvents(false);
       if (!myPrevSolved) {
         getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue("");
         // the error message should be changed before sending the message
@@ -482,18 +633,15 @@ bool SketchSolver_Group::resolveConstraints()
 
     aResolved = true;
   } else if (!isGroupEmpty) {
-////    myFeatureStorage->blockEvents(true);
+    myFeatureStorage->blockEvents(true);
     // Check there are constraints Fixed. If they exist, update parameters by stored values
     ConstraintConstraintMap::iterator aCIt = myConstraints.begin();
     for (; aCIt != myConstraints.end(); ++aCIt)
       if (aCIt->first->getKind() == SketchPlugin_ConstraintRigid::ID()) {
-////        aCIt->second->refresh();
+        aCIt->second->refresh();
         aResolved = true;
-        break;
       }
-////     myFeatureStorage->blockEvents(false);
-    if (aCIt != myConstraints.end())
-      myStorage->refresh();
+     myFeatureStorage->blockEvents(false);
   }
   removeTemporaryConstraints();
   myStorage->setNeedToResolve(false);
@@ -510,6 +658,8 @@ void SketchSolver_Group::mergeGroups(const SketchSolver_Group& theGroup)
   // If specified group is empty, no need to merge
   if (theGroup.isEmpty())
     return;
+  if (!myFeatureStorage)
+    myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage);
 
   std::set<ObjectPtr> aConstraints;
   ConstraintConstraintMap::const_iterator aConstrIter = theGroup.myConstraints.begin();
@@ -531,27 +681,27 @@ void SketchSolver_Group::mergeGroups(const SketchSolver_Group& theGroup)
 //  Class:    SketchSolver_Group
 //  Purpose:  divide the group into several subgroups
 // ============================================================================
-void SketchSolver_Group::splitGroup(std::list<SketchSolver_Group*>& theCuts)
+void SketchSolver_Group::splitGroup(std::vector<SketchSolver_Group*>& theCuts)
 {
-  // New storage will be used in trimmed way to store the list of constraint interacted together.
-  StoragePtr aNewStorage = SketchSolver_Manager::instance()->builder()->createStorage(getId());
-  std::list<ConstraintWrapperPtr> aDummyVec; // empty vector to avoid creation of solver's constraints
-
   // Obtain constraints, which should be separated
-  std::list<ConstraintPtr> anUnusedConstraints;
+  FeatureStoragePtr aNewFeatStorage(new SketchSolver_FeatureStorage);
+  std::vector<ConstraintPtr> anUnusedConstraints;
   ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
   for ( ; aCIter != myConstraints.end(); aCIter++) {
-    if (aNewStorage->isInteract(FeaturePtr(aCIter->first)))
-      aNewStorage->addConstraint(aCIter->first, aDummyVec);
-    else
-      anUnusedConstraints.push_back(aCIter->first);
+    std::list<ConstraintPtr> aBaseConstraints = aCIter->second->constraints();
+    std::list<ConstraintPtr>::iterator anIter = aBaseConstraints.begin();
+    for (; anIter != aBaseConstraints.end(); anIter++)
+      if (aNewFeatStorage->isInteract(*anIter)) {
+        aNewFeatStorage->changeConstraint(*anIter);
+      } else
+        anUnusedConstraints.push_back(*anIter);
   }
 
   // Check the unused constraints once again, because they may become interacted with new storage since adding constraints
-  std::list<ConstraintPtr>::iterator aUnuseIt = anUnusedConstraints.begin();
+  std::vector<ConstraintPtr>::iterator aUnuseIt = anUnusedConstraints.begin();
   while (aUnuseIt != anUnusedConstraints.end()) {
-    if (aNewStorage->isInteract(FeaturePtr(*aUnuseIt))) {
-      aNewStorage->addConstraint(*aUnuseIt, aDummyVec);
+    if (aNewFeatStorage->isInteract(*aUnuseIt)) {
+      aNewFeatStorage->changeConstraint(*aUnuseIt);
       anUnusedConstraints.erase(aUnuseIt);
       aUnuseIt = anUnusedConstraints.begin();
       continue;
@@ -559,13 +709,13 @@ void SketchSolver_Group::splitGroup(std::list<SketchSolver_Group*>& theCuts)
     aUnuseIt++;
   }
 
-  std::list<SketchSolver_Group*>::iterator aCutsIter;
+  std::vector<SketchSolver_Group*>::iterator aCutsIter;
   aUnuseIt = anUnusedConstraints.begin();
-  for ( ; aUnuseIt != anUnusedConstraints.end(); ++aUnuseIt) {
+  for ( ; aUnuseIt != anUnusedConstraints.end(); aUnuseIt++) {
     // Remove unused constraints
     removeConstraint(*aUnuseIt);
     // Try to append constraint to already existent group
-    for (aCutsIter = theCuts.begin(); aCutsIter != theCuts.end(); ++aCutsIter)
+    for (aCutsIter = theCuts.begin(); aCutsIter != theCuts.end(); aCutsIter++)
       if ((*aCutsIter)->isInteract(*aUnuseIt)) {
         (*aCutsIter)->changeConstraint(*aUnuseIt);
         break;
@@ -575,17 +725,11 @@ void SketchSolver_Group::splitGroup(std::list<SketchSolver_Group*>& theCuts)
       SketchSolver_Group* aGroup = new SketchSolver_Group(mySketch);
       aGroup->changeConstraint(*aUnuseIt);
       theCuts.push_back(aGroup);
-    } else {
-      // Find other groups interacting with constraint
-      std::list<SketchSolver_Group*>::iterator aBaseGroupIt = aCutsIter;
-      for (++aCutsIter; aCutsIter != theCuts.end(); ++aCutsIter)
-        if ((*aCutsIter)->isInteract(*aUnuseIt)) {
-          (*aBaseGroupIt)->mergeGroups(**aCutsIter);
-          std::list<SketchSolver_Group*>::iterator aRemoveIt = aCutsIter--;
-          theCuts.erase(aRemoveIt);
-        }
     }
   }
+
+  // Update feature storage
+  myFeatureStorage = aNewFeatStorage;
 }
 
 // ============================================================================
@@ -595,24 +739,12 @@ void SketchSolver_Group::splitGroup(std::list<SketchSolver_Group*>& theCuts)
 // ============================================================================
 bool SketchSolver_Group::isConsistent()
 {
-  if (isEmpty()) // no one constraint is initialized yet
+  if (!myFeatureStorage) // no one constraint is initialized yet
     return true;
 
-  // Check the features and constraint is the storage are valid
-  bool aResult = myStorage->isConsistent();
-  if (aResult) {
-    // additional check of consistency of the Fixed constraint,
-    // because they are not added to the storage
-    ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
-    for (; aCIter != myConstraints.end(); ++aCIter)
-      if (aCIter->first->getKind() == SketchPlugin_ConstraintRigid::ID() &&
-         (!aCIter->first->data() || !aCIter->first->data()->isValid())) {
-        aResult = false;
-        break;
-      }
-  }
+  bool aResult = myFeatureStorage->isConsistent();
   if (!aResult) {
-    // remove invalid constraints
+    // remove invalid entities
     std::set<ConstraintPtr> anInvalidConstraints;
     ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
     for (; aCIter != myConstraints.end(); ++aCIter) {
@@ -622,8 +754,6 @@ bool SketchSolver_Group::isConsistent()
     std::set<ConstraintPtr>::const_iterator aRemoveIt = anInvalidConstraints.begin();
     for (; aRemoveIt != anInvalidConstraints.end(); ++aRemoveIt)
       removeConstraint(*aRemoveIt);
-    // remove invalid features
-    myStorage->removeInvalidEntities();
   }
   return aResult;
 }
@@ -639,20 +769,16 @@ void SketchSolver_Group::removeTemporaryConstraints()
   std::set<SolverConstraintPtr>::iterator aTmpIt = myTempConstraints.begin();
   for (; aTmpIt != myTempConstraints.end(); ++aTmpIt)
     (*aTmpIt)->remove();
+  myTempConstraints.clear();
 
-  size_t aNbTemp = myStorage->nbTemporary();
-  if (aNbTemp > 0)
-    myStorage->removeTemporary(aNbTemp);
-////  // Clean lists of removed entities in the storage
-////  std::set<Slvs_hParam> aRemPar;
-////  std::set<Slvs_hEntity> aRemEnt;
-////  std::set<Slvs_hConstraint> aRemCon;
-////  myStorage->getRemoved(aRemPar, aRemEnt, aRemCon);
-
-  if (!myTempConstraints.empty())
-    myStorage->verifyFixed();
+  while (myStorage->numberTemporary())
+    myStorage->deleteTemporaryConstraint();
+  // Clean lists of removed entities in the storage
+  std::set<Slvs_hParam> aRemPar;
+  std::set<Slvs_hEntity> aRemEnt;
+  std::set<Slvs_hConstraint> aRemCon;
+  myStorage->getRemoved(aRemPar, aRemEnt, aRemCon);
   myStorage->setNeedToResolve(false);
-  myTempConstraints.clear();
 }
 
 // ============================================================================
@@ -663,18 +789,19 @@ void SketchSolver_Group::removeTemporaryConstraints()
 void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint)
 {
   bool isFullyRemoved = true;
+  myFeatureStorage->removeConstraint(theConstraint);
   ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
   for (; aCIter != myConstraints.end(); aCIter++)
-    if (aCIter->first == theConstraint) {
-      if (!aCIter->second->remove()) // the constraint is not fully removed
+    if (aCIter->second->hasConstraint(theConstraint)) {
+      if (!aCIter->second->remove(theConstraint)) // the constraint is not fully removed
         isFullyRemoved = false;
       break;
     }
   if (aCIter == myConstraints.end())
     return;
 
-////  // Remove entities not used by constraints
-////  myStorage->removeUnusedEntities();
+  // Remove entities not used by constraints
+  myStorage->removeUnusedEntities();
 
   if (isFullyRemoved)
     myConstraints.erase(aCIter);
@@ -690,7 +817,7 @@ void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint)
       }
       if (aCIter->first != theConstraint)
         aMultiCoinc.push_back(aCIter->first);
-      aCIter->second->remove();
+      aCIter->second->remove(aCIter->first);
       ConstraintConstraintMap::iterator aRemoveIt = aCIter++;
       myConstraints.erase(aRemoveIt);
     }
@@ -718,7 +845,7 @@ bool SketchSolver_Group::isComplexConstraint(FeaturePtr theConstraint)
 // ============================================================================
 //  Function: setTemporary
 //  Class:    SketchSolver_Group
-//  Purpose:  append given constraint to the group of temporary constraints
+//  Purpose:  append given constraint to th group of temporary constraints
 // ============================================================================
 void SketchSolver_Group::setTemporary(SolverConstraintPtr theConstraint)
 {
@@ -749,15 +876,15 @@ bool SketchSolver_Group::checkFeatureValidity(FeaturePtr theFeature)
 // ============================================================================
 void SketchSolver_Group::notifyMultiConstraints()
 {
-////  ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
-////  for (; aCIter != myConstraints.end(); ++aCIter) {
-////    if (aCIter->first->getKind() == SketchPlugin_MultiRotation::ID() ||
-////        aCIter->first->getKind() == SketchPlugin_MultiTranslation::ID()) {
-////      std::shared_ptr<SketchSolver_ConstraintMulti> aMulti = 
-////          std::dynamic_pointer_cast<SketchSolver_ConstraintMulti>(aCIter->second);
-////      aMulti->checkCoincidence();
-////    }
-////  }
+  ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
+  for (; aCIter != myConstraints.end(); ++aCIter) {
+    if (aCIter->first->getKind() == SketchPlugin_MultiRotation::ID() ||
+        aCIter->first->getKind() == SketchPlugin_MultiTranslation::ID()) {
+      std::shared_ptr<SketchSolver_ConstraintMulti> aMulti = 
+          std::dynamic_pointer_cast<SketchSolver_ConstraintMulti>(aCIter->second);
+      aMulti->checkCoincidence();
+    }
+  }
 }
 
 
index a8c09c2ac88349621d9f0e7763abc3a1062a2f74..507386d03e9928b83b0c578333422b25ec10b097 100644 (file)
 #include "SketchSolver.h"
 #include <SketchSolver_Constraint.h>
 #include <SketchSolver_Storage.h>
-#include <SketchSolver_ISolver.h>
+#include <SketchSolver_FeatureStorage.h>
+#include <SketchSolver_Solver.h>
 
 #include <SketchPlugin_Constraint.h>
-////#include <ModelAPI_Data.h>
+#include <ModelAPI_Data.h>
 #include <ModelAPI_Feature.h>
-////#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_AttributeRefList.h>
 
 #include <memory>
 #include <list>
 #include <map>
+#include <vector>
 #include <set>
 
 typedef std::map<ConstraintPtr, SolverConstraintPtr> ConstraintConstraintMap;
@@ -40,17 +42,22 @@ class SketchSolver_Group
   ~SketchSolver_Group();
 
   /// \brief Returns group's unique identifier
-  inline const GroupID& getId() const
+  inline const Slvs_hGroup& getId() const
   {
     return myID;
   }
 
   /// \brief Returns identifier of the workplane
-  inline const EntityID& getWorkplaneId() const
+  inline const Slvs_hEntity& getWorkplaneId() const
   {
     return myWorkplaneID;
   }
 
+  /// \brief Find the identifier of the feature, if it already exists in the group
+  Slvs_hEntity getFeatureId(FeaturePtr theFeature) const;
+  /// \brief Find the identifier of the attribute, if it already exists in the group
+  Slvs_hEntity getAttributeId(AttributePtr theAttribute) const;
+
   /// \brief Returns true if the group has no constraints yet
   inline bool isEmpty() const
   {
@@ -75,19 +82,19 @@ class SketchSolver_Group
   /** \brief Updates the data corresponding the specified feature
    *  \param[in] theFeature the feature to be updated
    */
-  bool updateFeature(FeaturePtr theFeature);
+  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
    */
-  void moveFeature(FeaturePtr theFeature);
+  void moveFeature(std::shared_ptr<SketchPlugin_Feature> theFeature);
 
   /** \brief Verifies the feature attributes are used in this group
    *  \param[in] theFeature constraint or any other object for verification of interaction
    *  \return \c true if some of attributes are used in current group
    */
-  bool isInteract(FeaturePtr theFeature) const;
+  bool isInteract(std::shared_ptr<SketchPlugin_Feature> theFeature) const;
 
   /** \brief Verifies the specified feature is equal to the base workplane for this group
    *  \param[in] theWorkplane the feature to be compared with base workplane
@@ -119,7 +126,7 @@ class SketchSolver_Group
   /** \brief Cut from the group several subgroups, which are not connected to the current one by any constraint
    *  \param[out] theCuts enlarge this list by newly created groups
    */
-  void splitGroup(std::list<SketchSolver_Group*>& theCuts);
+  void splitGroup(std::vector<SketchSolver_Group*>& theCuts);
 
   /** \brief Start solution procedure if necessary and update attributes of features
    *  \return \c false when no need to solve constraints
@@ -148,7 +155,10 @@ private:
    */
   bool addWorkplane(CompositeFeaturePtr theSketch);
 
-  /// \brief Append given constraint to the group of temporary constraints
+  /// \brief Apply temporary rigid constraints for the list of features
+  void fixFeaturesList(AttributeRefListPtr theList);
+
+  /// \brief Append given constraint to th group of temporary constraints
   void setTemporary(SolverConstraintPtr theConstraint);
 
   /// \brief Verifies is the feature valid
@@ -161,8 +171,8 @@ private:
   void notifyMultiConstraints();
 
 private:
-  GroupID  myID; ///< Index of the group
-  EntityID myWorkplaneID; ///< Index of workplane, the group is based on
+  Slvs_hGroup myID; ///< Index of the group
+  Slvs_hEntity myWorkplaneID; ///< Index of workplane, the group is based on
   CompositeFeaturePtr mySketch; ///< Sketch is equivalent to workplane
   ConstraintConstraintMap myConstraints; ///< List of constraints
   std::set<SolverConstraintPtr> myTempConstraints; ///< List of temporary constraints
@@ -170,8 +180,9 @@ private:
   std::set<ConstraintPtr> myChangedConstraints; ///< List of just updated constraints
 
   StoragePtr myStorage; ///< Container for the set of SolveSpace constraints and their entities
+  FeatureStoragePtr myFeatureStorage; ///< Container for the set of SketchPlugin features and their dependencies
 
-  SolverPtr mySketchSolver;  ///< Solver for set of equations obtained by constraints
+  SketchSolver_Solver myConstrSolver;  ///< Solver for set of equations obtained by constraints
 
   bool myPrevSolved; ///< Indicates that previous solving was done correctly
 };
diff --git a/src/SketchSolver/SketchSolver_IConstraintWrapper.h b/src/SketchSolver/SketchSolver_IConstraintWrapper.h
deleted file mode 100644 (file)
index 3e43cae..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SketchSolver_IConstraintWrapper.h
-// Created: 30 Nov 2015
-// Author:  Artem ZHIDKOV
-
-#ifndef SketchSolver_IConstraintWrapper_H_
-#define SketchSolver_IConstraintWrapper_H_
-
-#include <SketchSolver_IEntityWrapper.h>
-
-#include <SketchPlugin_Constraint.h>
-
-#include <list>
-#include <memory>
-
-/// Types of constraints
-enum SketchSolver_ConstraintType {
-  CONSTRAINT_UNKNOWN = 0,
-  CONSTRAINT_COINCIDENCE,      // base coincidence if we don't know exact type yet
-  CONSTRAINT_PT_PT_COINCIDENT,
-  CONSTRAINT_PT_ON_LINE,
-  CONSTRAINT_PT_ON_CIRCLE,
-  CONSTRAINT_DISTANCE,         // base distance if we don't know the measured objects yet
-  CONSTRAINT_PT_PT_DISTANCE,
-  CONSTRAINT_PT_LINE_DISTANCE,
-  CONSTRAINT_RADIUS,
-  CONSTRAINT_ANGLE,
-  CONSTRAINT_FIXED,
-  CONSTRAINT_HORIZONTAL,
-  CONSTRAINT_VERTICAL,
-  CONSTRAINT_PARALLEL,
-  CONSTRAINT_PERPENDICULAR,
-  CONSTRAINT_SYMMETRIC,
-  CONSTRAINT_EQUAL,           // base equality if we don't know the measured objects yet
-  CONSTRAINT_EQUAL_LINES,
-  CONSTRAINT_EQUAL_LINE_ARC,
-  CONSTRAINT_EQUAL_RADIUS,
-  CONSTRAINT_TANGENT,         // base tangency if we don't know the measured objects yet
-  CONSTRAINT_TANGENT_ARC_LINE,
-  CONSTRAINT_TANGENT_ARC_ARC,
-  CONSTRAINT_MULTI_TRANSLATION,
-  CONSTRAINT_MULTI_ROTATION
-};
-
-/**
- *  Wrapper providing operations with constraints regardless the solver.
- */
-class SketchSolver_IConstraintWrapper
-{
-public:
-  virtual ~SketchSolver_IConstraintWrapper() {}
-
-  /// \brief Return base feature
-  const ConstraintPtr& baseConstraint() const
-  { return myBaseConstraint; }
-
-  /// \brief Return ID of current entity
-  virtual ConstraintID id() const = 0;
-
-  /// \brief Change group for the constraint
-  virtual void setGroup(const GroupID& theGroup) = 0;
-  /// \brief Return identifier of the group the constraint belongs to
-  virtual const GroupID& group() const = 0;
-
-  /// \brief Return type of current entity
-  virtual SketchSolver_ConstraintType type() const = 0;
-
-  /// \brief Assign list of constrained objects
-  void setEntities(const std::list<EntityWrapperPtr>& theEntities)
-  { myConstrained = theEntities; }
-  /// \brief Return list of constrained objects
-  const std::list<EntityWrapperPtr>& entities() const
-  { return myConstrained; }
-
-  /// \brief Assign numeric parameter of constraint
-  virtual void setValue(const double& theValue)
-  { myValue = theValue; }
-  /// \brief Return numeric parameter of constraint
-  const double& value() const
-  { return myValue; }
-
-  /// \brief Verify the feature is used in the constraint
-  virtual bool isUsed(FeaturePtr theFeature) const = 0;
-  /// \brief Verify the attribute is used in the constraint
-  virtual bool isUsed(AttributePtr theAttribute) const = 0;
-
-  /// \brief Compare current constraint with other
-  virtual bool isEqual(const std::shared_ptr<SketchSolver_IConstraintWrapper>& theOther) = 0;
-
-  /// \brief Update values of parameters of this constraint by the parameters of given one
-  /// \return \c true if some parameters change their values
-  virtual bool update(const std::shared_ptr<SketchSolver_IConstraintWrapper>& theOther) = 0;
-
-protected:
-  ConstraintPtr               myBaseConstraint;
-  std::list<EntityWrapperPtr> myConstrained;
-  double                      myValue;
-};
-
-typedef std::shared_ptr<SketchSolver_IConstraintWrapper> ConstraintWrapperPtr;
-
-#endif
diff --git a/src/SketchSolver/SketchSolver_IEntityWrapper.h b/src/SketchSolver/SketchSolver_IEntityWrapper.h
deleted file mode 100644 (file)
index a5ecae3..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SketchSolver_IEntityWrapper.h
-// Created: 30 Nov 2015
-// Author:  Artem ZHIDKOV
-
-#ifndef SketchSolver_IEntityWrapper_H_
-#define SketchSolver_IEntityWrapper_H_
-
-#include <SketchSolver.h>
-#include <SketchSolver_IParameterWrapper.h>
-
-#include <ModelAPI_Attribute.h>
-#include <ModelAPI_Feature.h>
-
-#include <list>
-#include <memory>
-
-/// Types of entities
-enum SketchSolver_EntityType {
-  ENTITY_UNKNOWN = 0,
-  ENTITY_SCALAR,
-  ENTITY_POINT,
-  ENTITY_NORMAL,
-  ENTITY_LINE,
-  ENTITY_CIRCLE,
-  ENTITY_ARC,
-  ENTITY_SKETCH
-};
-
-/**
- *  Wrapper providing operations with entities regardless the solver.
- */
-class SketchSolver_IEntityWrapper
-{
-public:
-  virtual ~SketchSolver_IEntityWrapper() {}
-
-  /// \brief Return base feature
-  const FeaturePtr& baseFeature() const
-  { return myBaseFeature; }
-  /// \brief Return base attribute
-  const AttributePtr& baseAttribute() const
-  { return myBaseAttribute; }
-
-  /// \brief Check the feature is basis for this wrapper
-  bool isBase(FeaturePtr theFeature) const
-  { return myBaseFeature && myBaseFeature == theFeature; }
-  /// \brief Check the attribute is basis for this wrapper
-  bool isBase(AttributePtr theAttribute) const
-  { return myBaseAttribute && myBaseAttribute == theAttribute; }
-
-  /// \brief Assign list of parameters for this entity
-  void setParameters(const std::list<ParameterWrapperPtr>& theParams)
-  { myParameters = theParams; }
-  /// \brief Return list of parameters
-  const std::list<ParameterWrapperPtr>& parameters() const
-  { return myParameters; }
-
-  /// \brief Assign list of sub-entities
-  void setSubEntities(const std::list<std::shared_ptr<SketchSolver_IEntityWrapper> >& theEntities)
-  { mySubEntities = theEntities; }
-  /// \brief Return list of sub-entities
-  const std::list<std::shared_ptr<SketchSolver_IEntityWrapper> >& subEntities() const
-  { return mySubEntities; }
-
-  /// \brief Return ID of current entity
-  virtual EntityID id() const = 0;
-
-  /// \brief Change group for the entity
-  virtual void setGroup(const GroupID& theGroup) = 0;
-  /// \brief Return identifier of the group the entity belongs to
-  virtual const GroupID& group() const = 0;
-
-  /// \brief Return type of current entity
-  virtual SketchSolver_EntityType type() const = 0;
-
-  /// \brief Verify the feature is used in the entity
-  virtual bool isUsed(FeaturePtr theFeature) const = 0;
-  /// \brief Verify the attribute is used in the entity
-  virtual bool isUsed(AttributePtr theAttribute) const = 0;
-
-  /// \brief Compare current entity with other
-  virtual bool isEqual(const std::shared_ptr<SketchSolver_IEntityWrapper>& theOther) = 0;
-
-  /// \brief Update values of parameters of this entity by the parameters of given one
-  /// \return \c true if some parameters change their values
-  virtual bool update(const std::shared_ptr<SketchSolver_IEntityWrapper>& theOther) = 0;
-
-protected:
-  FeaturePtr   myBaseFeature;
-  AttributePtr myBaseAttribute;
-
-  std::list<ParameterWrapperPtr>                            myParameters;
-  std::list<std::shared_ptr<SketchSolver_IEntityWrapper> >  mySubEntities;
-};
-
-typedef std::shared_ptr<SketchSolver_IEntityWrapper> EntityWrapperPtr;
-
-#endif
diff --git a/src/SketchSolver/SketchSolver_IParameterWrapper.h b/src/SketchSolver/SketchSolver_IParameterWrapper.h
deleted file mode 100644 (file)
index fbd8819..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SketchSolver_IParameterWrapper.h
-// Created: 1 Dec 2015
-// Author:  Artem ZHIDKOV
-
-#ifndef SketchSolver_IParameterWrapper_H_
-#define SketchSolver_IParameterWrapper_H_
-
-#include <SketchSolver.h>
-
-#include <memory>
-
-/**
- *  Wrapper providing operations with parameters regardless the solver.
- */
-class SketchSolver_IParameterWrapper
-{
-public:
-  virtual ~SketchSolver_IParameterWrapper() {}
-
-  /// \brief Return ID of current parameter
-  virtual ParameterID id() const = 0;
-
-  /// \brief Change group for the parameter
-  virtual void setGroup(const GroupID& theGroup) = 0;
-  /// \brief Return identifier of the group the parameter belongs to
-  virtual const GroupID& group() const = 0;
-
-  /// \brief Change value of parameter
-  virtual void setValue(double theValue) = 0;
-  /// \brief Return value of parameter
-  virtual double value() const = 0;
-
-  /// \brief Set or unset flag the parameter is given by expression
-  void setIsParametric(bool isParametric)
-  { myIsParametric = isParametric; }
-  /// \brief Show the parameter is an expression
-  bool isParametric() const
-  { return myIsParametric; }
-
-  /// \brief Compare current parameter with other
-  virtual bool isEqual(const std::shared_ptr<SketchSolver_IParameterWrapper>& theOther) = 0;
-
-  /// \brief Update value of parameter by the given one
-  /// \return \c true if the value of parameter is changed
-  virtual bool update(const std::shared_ptr<SketchSolver_IParameterWrapper>& theOther) = 0;
-
-protected:
-  bool myIsParametric; ///< indicate the parameter is given by parametric expression
-};
-
-typedef std::shared_ptr<SketchSolver_IParameterWrapper> ParameterWrapperPtr;
-
-#endif
diff --git a/src/SketchSolver/SketchSolver_ISolver.h b/src/SketchSolver/SketchSolver_ISolver.h
deleted file mode 100644 (file)
index 75ddbfd..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SketchSolver_ISolver.h
-// Created: 30 Nov 2015
-// Author:  Artem ZHIDKOV
-
-#ifndef SketchSolver_ISolver_H_
-#define SketchSolver_ISolver_H_
-
-#include <SketchSolver.h>
-
-#include <memory>
-
-/// The result of constraints solution
-enum SketchSolver_SolveStatus {
-  STATUS_OK,
-  STATUS_INCONSISTENT,
-  STATUS_EMPTYSET,
-  STATUS_FAILED // set if no one other status is applicable
-};
-
-
-/**
- *  Interface providing operations to solve sketches.
- */
-class SketchSolver_ISolver
-{
-public:
-  virtual ~SketchSolver_ISolver() {}
-
-  /// \brief Changes the ID of the group to solve
-  void setGroup(const GroupID& theGroupID)
-  { myGroup = theGroupID; }
-
-  /// \brief Set or unset the flag which allows to find all failed constraints
-  void calculateFailedConstraints(bool theSic)
-  { myFindFaileds = theSic; }
-
-  /// \brief Solve the set of equations
-  /// \return identifier whether solution succeeded
-  virtual SketchSolver_SolveStatus solve() = 0;
-
-protected:
-  GroupID myGroup;       ///< ID of the group to be solved
-  bool    myFindFaileds; ///< flag to find conflicting or inappropriate constraints
-};
-
-typedef std::shared_ptr<SketchSolver_ISolver> SolverPtr;
-
-#endif
diff --git a/src/SketchSolver/SketchSolver_Manager.cpp b/src/SketchSolver/SketchSolver_Manager.cpp
deleted file mode 100644 (file)
index 442cf15..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SketchSolver_Manager.cpp
-// Created: 08 May 2014
-// Author:  Artem ZHIDKOV
-
-#include "SketchSolver_Manager.h"
-
-#include <Events_Loop.h>
-#include <ModelAPI_AttributeDouble.h>
-#include <ModelAPI_AttributeRefList.h>
-#include <ModelAPI_Data.h>
-#include <ModelAPI_Events.h>
-#include <ModelAPI_Object.h>
-#include <ModelAPI_ResultConstruction.h>
-#include <ModelAPI_Attribute.h>
-
-#include <SketchPlugin_Constraint.h>
-
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
-#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Point.h>
-#include <SketchPlugin_Sketch.h>
-#include <SketchPlugin_Feature.h>
-
-#include <list>
-#include <set>
-#include <memory>
-
-// Initialization of constraint manager self pointer
-SketchSolver_Manager* SketchSolver_Manager::mySelf = 0;
-
-/// Global constraint manager object
-SketchSolver_Manager* myManager = SketchSolver_Manager::instance();
-
-
-// ========================================================
-// ========= SketchSolver_Manager ===============
-// ========================================================
-SketchSolver_Manager* SketchSolver_Manager::instance()
-{
-  if (!mySelf)
-    mySelf = new SketchSolver_Manager();
-  return mySelf;
-}
-
-SketchSolver_Manager::SketchSolver_Manager()
-{
-  myGroups.clear();
-  myIsComputed = false;
-
-  // Register in event loop
-  Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
-  Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
-  Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
-  Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_MOVED));
-}
-
-SketchSolver_Manager::~SketchSolver_Manager()
-{
-  myGroups.clear();
-}
-
-void SketchSolver_Manager::setBuilder(BuilderPtr theBuilder)
-{
-  myBuilder = theBuilder;
-}
-
-BuilderPtr SketchSolver_Manager::builder()
-{
-  return myBuilder;
-}
-
-// ============================================================================
-//  Function: processEvent
-//  Purpose:  listen the event loop and process the message
-// ============================================================================
-void SketchSolver_Manager::processEvent(
-  const std::shared_ptr<Events_Message>& theMessage)
-{
-  if (myIsComputed)
-    return;
-  if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)
-      || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)
-      || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) {
-    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
-    std::set<ObjectPtr> aFeatures = anUpdateMsg->objects();
-
-    // Shows the message has at least one feature applicable for solver
-    bool hasProperFeature = false;
-
-    bool isMovedEvt = theMessage->eventID()
-          == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED);
-    if (isMovedEvt) {
-      std::set<ObjectPtr>::iterator aFeatIter;
-      for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
-        std::shared_ptr<SketchPlugin_Feature> aSFeature = 
-            std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
-        if (aSFeature) {
-          moveEntity(aSFeature);
-          hasProperFeature = true;
-        }
-      }
-    } else {
-      std::list<FeaturePtr> aSketchFeatures = SketchSolver_Group::selectApplicableFeatures(aFeatures);
-      std::list<FeaturePtr>::iterator aFeatIter = aSketchFeatures.begin();
-      for (; aFeatIter != aSketchFeatures.end(); ++aFeatIter) {
-        if ((*aFeatIter)->getKind() == SketchPlugin_Sketch::ID()) {
-          std::shared_ptr<ModelAPI_CompositeFeature> aSketch = 
-              std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aFeatIter);
-          hasProperFeature = changeWorkplane(aSketch) || hasProperFeature;
-          continue;
-        }
-        std::shared_ptr<SketchPlugin_Feature> aFeature = 
-            std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
-        if (!aFeature)
-          continue;
-        hasProperFeature = changeFeature(aFeature) || hasProperFeature;
-      }
-    }
-
-    // Solve the set of constraints
-    if (hasProperFeature)
-      resolveConstraints(isMovedEvt); // send update for movement in any case
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
-    std::shared_ptr<ModelAPI_ObjectDeletedMessage> aDeleteMsg =
-      std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
-    const std::set<std::string>& aFeatureGroups = aDeleteMsg->groups();
-
-    // Find SketchPlugin_Sketch::ID() in groups. The constraint groups should be updated when an object removed from Sketch
-    std::set<std::string>::const_iterator aFGrIter;
-    for (aFGrIter = aFeatureGroups.begin(); aFGrIter != aFeatureGroups.end(); aFGrIter++)
-      if (aFGrIter->compare(ModelAPI_ResultConstruction::group()) == 0 ||
-        aFGrIter->compare(ModelAPI_Feature::group()) == 0)
-        break;
-
-    if (aFGrIter != aFeatureGroups.end()) {
-      std::vector<SketchSolver_Group*>::iterator aGroupIter = myGroups.begin();
-      std::list<SketchSolver_Group*> aSeparatedGroups;
-      while (aGroupIter != myGroups.end()) {
-        if (!(*aGroupIter)->isWorkplaneValid()) {  // the group should be removed
-          delete *aGroupIter;
-          int aShift = aGroupIter - myGroups.begin();
-          myGroups.erase(aGroupIter);
-          aGroupIter = myGroups.begin() + aShift;
-          continue;
-        }
-        if (!(*aGroupIter)->isConsistent()) {  // some constraints were removed, try to split the group
-          (*aGroupIter)->splitGroup(aSeparatedGroups);
-        }
-        aGroupIter++;
-      }
-      if (aSeparatedGroups.size() > 0)
-        myGroups.insert(myGroups.end(), aSeparatedGroups.begin(), aSeparatedGroups.end());
-    }
-  }
-}
-
-// ============================================================================
-//  Function: changeWorkplane
-//  Purpose:  update workplane by given parameters of the sketch
-// ============================================================================
-bool SketchSolver_Manager::changeWorkplane(CompositeFeaturePtr theSketch)
-{
-  bool aResult = true;  // changed when a workplane wrongly updated
-  bool isUpdated = false;
-  // Try to update specified workplane in all groups
-  std::vector<SketchSolver_Group*>::iterator aGroupIter;
-  for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
-    if ((*aGroupIter)->isBaseWorkplane(theSketch)) {
-      isUpdated = true;
-      aResult = false;
-    }
-  // If the workplane is not updated, so this is a new workplane
-  if (!isUpdated) {
-    SketchSolver_Group* aNewGroup = new SketchSolver_Group(theSketch);
-    // Verify that the group is created successfully
-    if (!aNewGroup->isBaseWorkplane(theSketch) || !aNewGroup->isWorkplaneValid()) {
-      delete aNewGroup;
-      return false;
-    }
-    myGroups.push_back(aNewGroup);
-  }
-  return aResult;
-}
-
-// ============================================================================
-//  Function: changeConstraintOrEntity
-//  Purpose:  create/update the constraint or the feature and place it into appropriate group
-// ============================================================================
-bool SketchSolver_Manager::changeFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
-{
-  // Search the groups which this feature touches
-  std::set<GroupID> aGroups;
-  findGroups(theFeature, aGroups);
-
-  std::shared_ptr<SketchPlugin_Constraint> aConstraint = 
-      std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
-
-  // Process the groups list
-  if (aGroups.size() == 0) {
-    // There are no groups applicable for this constraint => create new one
-    // The group will be created only for constraints, not for features
-    if (!aConstraint) return false;
-    std::shared_ptr<ModelAPI_CompositeFeature> aWP = findWorkplane(aConstraint);
-    if (!aWP)
-      return false;
-    SketchSolver_Group* aGroup = new SketchSolver_Group(aWP);
-    if (!aGroup->changeConstraint(aConstraint)) {
-      delete aGroup;
-      return false;
-    }
-    myGroups.push_back(aGroup);
-    return true;
-  } else if (aGroups.size() == 1) {  // Only one group => add feature into it
-    GroupID aGroupId = *(aGroups.begin());
-    std::vector<SketchSolver_Group*>::iterator aGroupIter;
-    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())
-          return (*aGroupIter)->updateFeature(theFeature);
-        return (*aGroupIter)->changeConstraint(aConstraint);
-      }
-  } else if (aGroups.size() > 1) {  // Several groups applicable for this feature => need to merge them
-    std::set<GroupID>::const_iterator aGroupsIter = aGroups.begin();
-
-    // Search first group
-    std::vector<SketchSolver_Group*>::iterator aFirstGroupIter;
-    for (aFirstGroupIter = myGroups.begin(); aFirstGroupIter != myGroups.end(); aFirstGroupIter++)
-      if ((*aFirstGroupIter)->getId() == *aGroupsIter)
-        break;
-    if (aFirstGroupIter == myGroups.end())
-      return false;
-
-    // Append other groups to the first one
-    std::vector<SketchSolver_Group*>::iterator anOtherGroupIter = aFirstGroupIter + 1;
-    for (aGroupsIter++; aGroupsIter != aGroups.end(); aGroupsIter++) {
-      for (; anOtherGroupIter != myGroups.end(); anOtherGroupIter++)
-        if ((*anOtherGroupIter)->getId() == *aGroupsIter)
-          break;
-      if (anOtherGroupIter == myGroups.end()) {  // Group disappears
-        anOtherGroupIter = aFirstGroupIter + 1;
-        continue;
-      }
-
-      (*aFirstGroupIter)->mergeGroups(**anOtherGroupIter);
-      int aShiftFirst = aFirstGroupIter - myGroups.begin();
-      int aShiftOther = anOtherGroupIter - myGroups.begin();
-      delete *anOtherGroupIter;
-      myGroups.erase(anOtherGroupIter);
-      aFirstGroupIter = myGroups.begin() + aShiftFirst;
-      anOtherGroupIter = myGroups.begin() + aShiftOther;
-    }
-
-    if (aConstraint)
-      return (*aFirstGroupIter)->changeConstraint(aConstraint);
-    return (*aFirstGroupIter)->updateFeature(theFeature);
-  }
-
-  // Something goes wrong
-  return false;
-}
-
-// ============================================================================
-//  Function: moveEntity
-//  Purpose:  update element moved on the sketch, which is used by constraints
-// ============================================================================
-void SketchSolver_Manager::moveEntity(std::shared_ptr<SketchPlugin_Feature> theFeature)
-{
-  std::vector<SketchSolver_Group*>::iterator aGroupIt = myGroups.begin();
-  for (; aGroupIt != myGroups.end(); aGroupIt++)
-    if (!(*aGroupIt)->isEmpty() && (*aGroupIt)->isInteract(theFeature))
-      (*aGroupIt)->moveFeature(theFeature);
-}
-
-// ============================================================================
-//  Function: findGroups
-//  Purpose:  search groups of entities interacting with given feature
-// ============================================================================
-void SketchSolver_Manager::findGroups(
-    std::shared_ptr<SketchPlugin_Feature> theFeature,
-    std::set<GroupID>& theGroupIDs) const
-{
-  std::shared_ptr<ModelAPI_CompositeFeature> aWP = findWorkplane(theFeature);
-
-  SketchSolver_Group* anEmptyGroup = 0;  // appropriate empty group for specified constraint
-  std::vector<SketchSolver_Group*>::const_iterator aGroupIter;
-  for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
-    if (aWP == (*aGroupIter)->getWorkplane() && (*aGroupIter)->isInteract(theFeature)) {
-      if (!(*aGroupIter)->isEmpty())
-        theGroupIDs.insert((*aGroupIter)->getId());
-      else if (!anEmptyGroup)
-        anEmptyGroup = *aGroupIter;
-    }
-
-  // When only empty group is found, use it
-  if (anEmptyGroup && theGroupIDs.empty())
-    theGroupIDs.insert(anEmptyGroup->getId());
-}
-
-// ============================================================================
-//  Function: findWorkplane
-//  Purpose:  search workplane containing given feature
-// ============================================================================
-std::shared_ptr<ModelAPI_CompositeFeature> SketchSolver_Manager
-::findWorkplane(std::shared_ptr<SketchPlugin_Feature> theFeature) const
-{
-  // Already verified workplanes
-  std::set<std::shared_ptr<ModelAPI_CompositeFeature> > aVerified;
-
-  std::vector<SketchSolver_Group*>::const_iterator aGroupIter;
-  for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) {
-    std::shared_ptr<ModelAPI_CompositeFeature> aWP = (*aGroupIter)->getWorkplane();
-    if (aVerified.find(aWP) != aVerified.end())
-      continue;
-
-    DataPtr aData = aWP->data();
-    if (aData->isValid()) {
-      std::shared_ptr<ModelAPI_AttributeRefList> aWPFeatures = std::dynamic_pointer_cast<
-          ModelAPI_AttributeRefList>(aData->attribute(SketchPlugin_Sketch::FEATURES_ID()));
-      std::list<ObjectPtr> aFeaturesList = aWPFeatures->list();
-      std::list<ObjectPtr>::const_iterator anIter;
-      for (anIter = aFeaturesList.begin(); anIter != aFeaturesList.end(); anIter++)
-        if (*anIter == theFeature)
-          return aWP;  // workplane is found
-    }
-    aVerified.insert(aWP);
-  }
-
-  return std::shared_ptr<ModelAPI_CompositeFeature>();
-}
-
-// ============================================================================
-//  Function: resolveConstraints
-//  Purpose:  change entities according to available constraints
-// ============================================================================
-void SketchSolver_Manager::resolveConstraints(const bool theForceUpdate)
-{
-  myIsComputed = true;
-  bool needToUpdate = false;
-  static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
-  // to avoid redisplay of each segment on update by solver one by one in the viewer
-  bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
-  if (isUpdateFlushed) {
-    Events_Loop::loop()->setFlushed(anUpdateEvent, false);
-  }
-
-  std::vector<SketchSolver_Group*>::iterator aGroupIter;
-  for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
-    if ((*aGroupIter)->resolveConstraints())
-      needToUpdate = true;
-
-  // Features may be updated => now send events, but for all changed at once
-  if (isUpdateFlushed) {
-    Events_Loop::loop()->setFlushed(anUpdateEvent, true);
-  }
-  // Must be before flush because on "Updated" flush the results may be produced
-  // and the creation event is appeared with many new objects. If myIsComputed these
-  // events are missed in processEvents and some elements are not added.
-  myIsComputed = false;
-  if (needToUpdate || theForceUpdate)
-    Events_Loop::loop()->flush(anUpdateEvent);
-}
diff --git a/src/SketchSolver/SketchSolver_Manager.h b/src/SketchSolver/SketchSolver_Manager.h
deleted file mode 100644 (file)
index 8ceddc7..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SketchSolver_Manager.h
-// Created: 08 May 2014
-// Author:  Artem ZHIDKOV
-
-#ifndef SketchSolver_Manager_H_
-#define SketchSolver_Manager_H_
-
-#include "SketchSolver.h"
-#include <SketchSolver_Group.h>
-#include <SketchSolver_Builder.h>
-
-#include <Events_Listener.h>
-#include <SketchPlugin_Constraint.h>
-
-#include <vector>
-#include <set>
-
-/** \class   SketchSolver_Manager
- *  \ingroup Plugins
- *  \brief   Listens the changes of SketchPlugin features and transforms the Constraint
- *           feature into the format understandable by SolveSpace library.
- *
- *  Constraints created for SolveSpace library are divided into the groups.
- *  The division order based on connectedness of the features by the constraints.
- *  The groups may be fused or separated according to the new constraints.
- *
- *  \remark This is a singleton.
- */
-class SketchSolver_Manager : public Events_Listener
-{
-public:
-  /** \brief Main method to create constraint manager
-   *  \return pointer to the singleton
-   */
-  SKETCHSOLVER_EXPORT static SketchSolver_Manager* instance();
-
-  /** \brief Implementation of Event Listener method
-   *  \param[in] theMessage the data of the event
-   */
-  virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
-
-  /// \brief Initialize builder for solver's data structure entities
-  /// \param theBuilder [in]  solver's specific builder
-  SKETCHSOLVER_EXPORT void setBuilder(BuilderPtr theBuilder);
-  /// \brief Returns the builder specific for the solver
-  BuilderPtr builder();
-
-protected:
-  SketchSolver_Manager();
-  ~SketchSolver_Manager();
-
-  /** \brief Adds or updates a constraint or an entity in the suitable group
-   *  \param[in] theFeature sketch feature to be changed
-   *  \return \c true if the feature changed successfully
-   */
-  bool changeFeature(std::shared_ptr<SketchPlugin_Feature> theFeature);
-
-  /** \brief Removes a constraint from the manager
-   *  \param[in] theConstraint constraint to be removed
-   *  \return \c true if the constraint removed successfully
-   */
-  bool removeConstraint(std::shared_ptr<SketchPlugin_Constraint> theConstraint);
-
-  /** \brief Adds or updates a workplane in the manager
-   *  \param[in] theSketch the feature to create or update workplane
-   *  \return \c true if the workplane changed successfully
-   *  \remark Type of theSketch is not verified inside
-   */
-  bool changeWorkplane(CompositeFeaturePtr theSketch);
-
-  /** \brief Removes a workplane from the manager.
-   *         All groups based on such workplane will be removed too.
-   *  \param[in] theSketch the feature to be removed
-   *  \return \c true if the workplane removed successfully
-   */
-  bool removeWorkplane(std::shared_ptr<SketchPlugin_Sketch> theSketch);
-
-  /** \brief Updates entity which is moved in GUI
-   *  \param[in] theFeature entity to be updated
-   */
-  void moveEntity(std::shared_ptr<SketchPlugin_Feature> theFeature);
-
-  /** \brief Goes through the list of groups and solve the constraints
-   *  \param theForceUpdate flushes the update event in any case: something changed or not
-   */
-  void resolveConstraints(const bool theForceUpdate);
-
-private:
-  /** \brief Searches list of groups which interact with specified feature
-   *  \param[in]  theFeature  object to be found
-   *  \param[out] theGroups   list of group indexes interacted with the feature
-   */
-  void findGroups(std::shared_ptr<SketchPlugin_Feature> theFeature,
-                  std::set<GroupID>& theGroupIDs) const;
-
-  /** \brief Searches in the list of groups the workplane which contains specified feature
-   *  \param[in] theFeature object to be found
-   *  \return workplane containing the feature
-   */
-  std::shared_ptr<ModelAPI_CompositeFeature> findWorkplane(
-      std::shared_ptr<SketchPlugin_Feature> theFeature) const;
-
-private:
-  static SketchSolver_Manager*     mySelf;    ///< Self pointer to implement singleton functionality
-  std::vector<SketchSolver_Group*> myGroups;  ///< Groups of constraints
-  BuilderPtr                       myBuilder; ///< Builder for solver's entities
-  /// true if computation is performed and all "updates" are generated by this algo
-  /// and needs no recomputation
-  bool myIsComputed;
-};
-
-#endif
diff --git a/src/SketchSolver/SketchSolver_Solver.cpp b/src/SketchSolver/SketchSolver_Solver.cpp
new file mode 100644 (file)
index 0000000..36979d7
--- /dev/null
@@ -0,0 +1,112 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    SketchSolver_Solver.cpp
+// Created: 07 May 2014
+// Author:  Artem ZHIDKOV
+
+#include "SketchSolver_Solver.h"
+#include <Events_LongOp.h>
+
+SketchSolver_Solver::SketchSolver_Solver()
+{
+  myGroupID = 0;
+  // Nullify all elements of the set of equations
+  myEquationsSystem.param = 0;
+  myEquationsSystem.params = 0;
+  myEquationsSystem.entity = 0;
+  myEquationsSystem.entities = 0;
+  myEquationsSystem.constraint = 0;
+  myEquationsSystem.constraints = 0;
+  myEquationsSystem.failed = 0;
+  myEquationsSystem.faileds = 0;
+
+  myEquationsSystem.dragged[0] = 0;
+  myEquationsSystem.dragged[1] = 0;
+  myEquationsSystem.dragged[2] = 0;
+  myEquationsSystem.dragged[3] = 0;
+
+  // If the set of constraints is inconsistent,
+  // the failed field will contain wrong constraints
+  myEquationsSystem.calculateFaileds = 0;
+}
+
+SketchSolver_Solver::~SketchSolver_Solver()
+{
+  if (myEquationsSystem.constraint)
+    delete[] myEquationsSystem.constraint;
+  myEquationsSystem.constraint = 0;
+  if (myEquationsSystem.failed)
+    delete[] myEquationsSystem.failed;
+  myEquationsSystem.failed = 0;
+}
+
+void SketchSolver_Solver::setParameters(Slvs_Param* theParameters, int theSize)
+{
+  myEquationsSystem.param = theParameters;
+  myEquationsSystem.params = theSize;
+}
+
+
+void SketchSolver_Solver::setDraggedParameters(const Slvs_hParam* theDragged)
+{
+  for (unsigned int i = 0; i < 4; i++)
+    myEquationsSystem.dragged[i] = theDragged[i];
+}
+
+void SketchSolver_Solver::setEntities(Slvs_Entity* theEntities, int theSize)
+{
+  myEquationsSystem.entity = theEntities;
+  myEquationsSystem.entities = theSize;
+}
+
+void SketchSolver_Solver::setConstraints(Slvs_Constraint* theConstraints, int theSize)
+{
+  if (!myEquationsSystem.constraint) {
+    myEquationsSystem.constraint = new Slvs_Constraint[theSize];
+    myEquationsSystem.constraints = theSize;
+    myEquationsSystem.failed = new Slvs_hConstraint[theSize];
+  }
+  else if (myEquationsSystem.constraints != theSize) {
+    if (theSize > myEquationsSystem.constraints) {
+      delete[] myEquationsSystem.constraint;
+      myEquationsSystem.constraint = new Slvs_Constraint[theSize];
+      if (myEquationsSystem.failed)
+        delete[] myEquationsSystem.failed;
+      myEquationsSystem.failed = new Slvs_hConstraint[theSize];
+    }
+    myEquationsSystem.constraints = theSize;
+  }
+  memcpy(myEquationsSystem.constraint, theConstraints, theSize * sizeof(Slvs_Constraint));
+  memset(myEquationsSystem.failed, SLVS_C_UNKNOWN, theSize * sizeof(Slvs_hConstraint));
+}
+
+
+int SketchSolver_Solver::solve()
+{
+  if (myEquationsSystem.constraints <= 0)
+    return SLVS_RESULT_EMPTY_SET;
+
+  Events_LongOp::start(this);
+  Slvs_Solve(&myEquationsSystem, myGroupID);
+  Events_LongOp::end(this);
+
+  return myEquationsSystem.result;
+}
+
+bool SketchSolver_Solver::getResult(std::vector<Slvs_Param>& theParameters)
+{
+  if (myEquationsSystem.result != SLVS_RESULT_OKAY)
+    return false;
+
+  if (theParameters.size() != myEquationsSystem.params)
+    return false;  // number of parameters is not the same
+
+  std::vector<Slvs_Param>::iterator aParamIter = theParameters.begin();
+  for (int i = 0; i < myEquationsSystem.params; i++, aParamIter++) {
+    if (myEquationsSystem.param[i].h != aParamIter->h)
+      return false;  // sequence of parameters was changed
+    aParamIter->val = myEquationsSystem.param[i].val;
+  }
+
+  return true;
+}
diff --git a/src/SketchSolver/SketchSolver_Solver.h b/src/SketchSolver/SketchSolver_Solver.h
new file mode 100644 (file)
index 0000000..52ac18f
--- /dev/null
@@ -0,0 +1,101 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    SketchSolver_Solver.h
+// Created: 07 May 2014
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchSolver_Solver_H_
+#define SketchSolver_Solver_H_
+
+#include "SketchSolver.h"
+
+// Need to be defined before including SolveSpace to avoid additional dependances on Windows platform
+#if defined(WIN32) && !defined(HAVE_C99_INTEGER_TYPES)
+typedef unsigned int UINT32;
+#else
+#include <stdint.h>
+#endif
+#include <string.h>
+#include <slvs.h>
+
+#include <vector>
+
+#define SLVS_RESULT_EMPTY_SET -1
+
+// Unknown constraint (for error reporting)
+#define SLVS_C_UNKNOWN 0
+// Fillet constraint identifier
+#define SLVS_C_FILLET            100100
+// Multi-rotation constraint identifier
+#define SLVS_C_MULTI_ROTATION    100101
+// Multi-translation constraint identifier
+#define SLVS_C_MULTI_TRANSLATION 100102
+// Unknown entity
+#define SLVS_E_UNKNOWN 0
+// Unknown group
+#define SLVS_G_UNKNOWN 0
+// Group ID to store external objects
+#define SLVS_G_OUTOFGROUP 1
+
+/**
+ * The main class that performs the high-level operations for connection to the SolveSpace.
+ */
+class SketchSolver_Solver
+{
+ public:
+  SketchSolver_Solver();
+  ~SketchSolver_Solver();
+
+  /** \brief Initialize the ID of the group
+   */
+  inline void setGroupID(Slvs_hGroup theGroupID)
+  {
+    myGroupID = theGroupID;
+  }
+
+  /** \brief Change array of parameters
+   *  \param[in] theParameters pointer to the array of parameters
+   *  \param[in] theSize       size of this array
+   */
+  void setParameters(Slvs_Param* theParameters, int theSize);
+
+  /** \brief Change array of entities
+   *  \param[in] theEntities pointer to the array of entities
+   *  \param[in] theSize     size of this array
+   */
+  void setEntities(Slvs_Entity* theEntities, int theSize);
+
+  /** \brief Change array of constraints
+   *  \param[in] theConstraints pointer to the array of constraints
+   *  \param[in] theSize        size of this array
+   */
+  void setConstraints(Slvs_Constraint* theConstraints, int theSize);
+
+  /** \brief Store the parameters of the point which was moved by user.
+   *         The solver will watch this items to be constant
+   *  \param[in] theDragged list of parameters (not more than 4) which should not be changed during solving
+   */
+  void setDraggedParameters(const Slvs_hParam* theDragged);
+
+  /** \brief Set or unset the flag which allows to find all failed constraints
+   */
+  void calculateFailedConstraints(bool theSic)
+  { myEquationsSystem.calculateFaileds = theSic ? 1 : 0; }
+
+  /** \brief Solve the set of equations
+   *  \return identifier whether solution succeeded
+   */
+  int solve();
+
+  /** \brief Updates the list of parameters by calculated values
+   *  \param[in,out] theParameters parameters to be updated
+   *  \return \c true if parameters are updated correctly
+   */
+  bool getResult(std::vector<Slvs_Param>& theParameters);
+
+ private:
+  Slvs_hGroup myGroupID;         ///< identifier of the group to be solved
+  Slvs_System myEquationsSystem;  ///< set of equations for solving in SolveSpace
+};
+
+#endif
index 9e38f92706ccd5ff2092e6c53a0d2638f315fbed..58cd67418755730d3f169b6bdde4c3f020c8db65 100644 (file)
 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
 
 // File:    SketchSolver_Storage.cpp
-// Created: 30 Nov 2015
+// Created: 18 Mar 2015
 // Author:  Artem ZHIDKOV
 
 #include <SketchSolver_Storage.h>
-#include <SketchSolver_Manager.h>
 
-#include <GeomDataAPI_Point2D.h>
-#include <ModelAPI_AttributeRefAttr.h>
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_XY.h>
+#include <math.h>
 
+/** \brief Search the entity/parameter with specified ID in the list of elements
+ *  \param[in] theEntityID unique ID of the element
+ *  \param[in] theEntities list of elements
+ *  \return position of the found element or -1 if the element is not found
+ */
+template<typename T>
+static int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities);
 
-/// \brief Verify two vectors of constraints are equal.
-///        Vectors differ by the order of elements are equal.
-static bool isEqual(const std::list<ConstraintWrapperPtr>& theCVec1,
-                    const std::list<ConstraintWrapperPtr>& theCVec2);
+/// \brief Compare two parameters to be different
+static bool IsNotEqual(const Slvs_Param& theParam1, const Slvs_Param& theParam2);
+/// \brief Compare two entities to be different
+static bool IsNotEqual(const Slvs_Entity& theEntity1, const Slvs_Entity& theEntity2);
+/// \brief Compare two constriants to be different
+static bool IsNotEqual(const Slvs_Constraint& theConstraint1, const Slvs_Constraint& theConstraint2);
 
 
-void SketchSolver_Storage::addConstraint(ConstraintPtr        theConstraint,
-                                         ConstraintWrapperPtr theSolverConstraint)
+SketchSolver_Storage::SketchSolver_Storage()
+  : myParamMaxID(SLVS_E_UNKNOWN),
+    myEntityMaxID(SLVS_E_UNKNOWN),
+    myConstrMaxID(SLVS_C_UNKNOWN),
+    myFixed(SLVS_E_UNKNOWN),
+    myNeedToResolve(false),
+    myDuplicatedConstraint(false)
 {
-  std::list<ConstraintWrapperPtr> aConstrList(1, theSolverConstraint);
-  addConstraint(theConstraint, aConstrList);
 }
 
-void SketchSolver_Storage::addConstraint(
-    ConstraintPtr                   theConstraint,
-    std::list<ConstraintWrapperPtr> theSolverConstraints)
+Slvs_hParam SketchSolver_Storage::addParameter(const Slvs_Param& theParam)
 {
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
-      aFound = myConstraintMap.find(theConstraint);
-  if (!isEqual(aFound->second, theSolverConstraints))
-    setNeedToResolve(true);
+  if (theParam.h > 0 && theParam.h <= myParamMaxID) {
+    // parameter is already used, rewrite it
+    return updateParameter(theParam);
+  }
+
+  Slvs_Param aParam = theParam;
+  if (aParam.h > myParamMaxID)
+    myParamMaxID = aParam.h;
+  else
+    aParam.h = ++myParamMaxID;
+  myParameters.push_back(aParam);
+  myNeedToResolve = true;
+  return aParam.h;
+}
+
+Slvs_hParam SketchSolver_Storage::updateParameter(const Slvs_Param& theParam)
+{
+  if (theParam.h > 0 && theParam.h <= myParamMaxID) {
+    // parameter already used, rewrite it
+    int aPos = Search(theParam.h, myParameters);
+    if (aPos >= 0 && aPos < (int)myParameters.size()) {
+      if (IsNotEqual(myParameters[aPos], theParam))
+        myUpdatedParameters.insert(theParam.h);
+      myParameters[aPos] = theParam;
+      return theParam.h;
+    }
+  }
+
+  // Parameter is not found, add new one
+  Slvs_Param aParam = theParam;
+  aParam.h = 0;
+  return addParameter(aParam);
+}
 
-  // Do not add point-point coincidence, because it is already made by setting
-  // the same parameters for both points
-  if (!theSolverConstraints.empty() &&
-      theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) {
-    std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
-    for (; aCIt != theSolverConstraints.end(); ++aCIt)
-      update(*aCIt);
+bool SketchSolver_Storage::removeParameter(const Slvs_hParam& theParamID)
+{
+  int aPos = Search(theParamID, myParameters);
+  if (aPos >= 0 && aPos < (int)myParameters.size()) {
+    // Firstly, search the parametes is not used elsewhere
+    std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
+    for (; anEntIter != myEntities.end(); anEntIter++) {
+      for (int i = 0; i < 4; i++)
+        if (anEntIter->param[i] == theParamID)
+          return false;
+    }
+    // Remove parameter
+    myParameters.erase(myParameters.begin() + aPos);
+    myParamMaxID = myParameters.empty() ? SLVS_E_UNKNOWN : myParameters.back().h;
+    myNeedToResolve = true;
+    myRemovedParameters.insert(theParamID);
+    return true;
   }
-  myConstraintMap[theConstraint] = theSolverConstraints;
+  return false;
 }
 
-void SketchSolver_Storage::addEntity(FeaturePtr       theFeature,
-                                     EntityWrapperPtr theSolverEntity)
+const Slvs_Param& SketchSolver_Storage::getParameter(const Slvs_hParam& theParamID) const
 {
-  std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
-  if (aFound == myFeatureMap.end() || !aFound->second->isEqual(theSolverEntity))
-    setNeedToResolve(true); // the entity is new or modified
+  int aPos = Search(theParamID, myParameters);
+  if (aPos >= 0 && aPos < (int)myParameters.size())
+    return myParameters[aPos];
 
-  myFeatureMap[theFeature] = theSolverEntity;
+  // Parameter is not found, return empty object
+  static Slvs_Param aDummy;
+  aDummy.h = 0;
+  return aDummy;
 }
 
-void SketchSolver_Storage::addEntity(AttributePtr     theAttribute,
-                                     EntityWrapperPtr theSolverEntity)
+
+Slvs_hEntity SketchSolver_Storage::addEntity(const Slvs_Entity& theEntity)
 {
-  std::map<AttributePtr, EntityWrapperPtr>::const_iterator aFound = myAttributeMap.find(theAttribute);
-  if (aFound == myAttributeMap.end() || !aFound->second->isEqual(theSolverEntity))
-    setNeedToResolve(true); // the entity is new or modified
+  if (theEntity.h > 0 && theEntity.h <= myEntityMaxID) {
+    // Entity is already used, rewrite it
+    return updateEntity(theEntity);
+  }
 
-  myAttributeMap[theAttribute] = theSolverEntity;
+  Slvs_Entity aEntity = theEntity;
+  if (aEntity.h > myEntityMaxID)
+    myEntityMaxID = aEntity.h;
+  else
+    aEntity.h = ++myEntityMaxID;
+  myEntities.push_back(aEntity);
+  myNeedToResolve = true;
+  return aEntity.h;
 }
 
+Slvs_hEntity SketchSolver_Storage::updateEntity(const Slvs_Entity& theEntity)
+{
+  if (theEntity.h > 0 && theEntity.h <= myEntityMaxID) {
+    // Entity already used, rewrite it
+    int aPos = Search(theEntity.h, myEntities);
+    if (aPos >= 0 && aPos < (int)myEntities.size()) {
+      myNeedToResolve = myNeedToResolve || IsNotEqual(myEntities[aPos], theEntity);
+      myEntities[aPos] = theEntity;
+      return theEntity.h;
+    }
+  }
+
+  // Entity is not found, add new one
+  Slvs_Entity aEntity = theEntity;
+  aEntity.h = 0;
+  return addEntity(aEntity);
+}
 
-bool SketchSolver_Storage::update(FeaturePtr theFeature, const GroupID& theGroup)
+bool SketchSolver_Storage::removeEntity(const Slvs_hEntity& theEntityID)
 {
-  bool isUpdated = false;
-  EntityWrapperPtr aRelated = entity(theFeature);
-  if (!aRelated) { // Feature is not exist, create it
-    std::list<EntityWrapperPtr> aSubs;
-    // Firstly, create/update its attributes
-    std::list<AttributePtr> anAttrs =
-        theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
-    std::list<AttributePtr>::const_iterator anIt = anAttrs.begin();
-    for (; anIt != anAttrs.end(); ++anIt) {
-      isUpdated = update(*anIt, theGroup) || isUpdated;
-      aSubs.push_back(entity(*anIt));
+  bool aResult = true;
+  int aPos = Search(theEntityID, myEntities);
+  if (aPos >= 0 && aPos < (int)myEntities.size()) {
+    // Firstly, check the entity and its attributes is not used elsewhere
+    std::set<Slvs_hEntity> anEntAndSubs;
+    anEntAndSubs.insert(theEntityID);
+    for (int i = 0; i < 4; i++)
+      if (myEntities[aPos].point[i] != SLVS_E_UNKNOWN)
+        anEntAndSubs.insert(myEntities[aPos].point[i]);
+
+    std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
+    for (; anEntIter != myEntities.end(); anEntIter++) {
+      for (int i = 0; i < 4; i++)
+        if (anEntAndSubs.find(anEntIter->point[i]) != anEntAndSubs.end())
+          return false;
+      if (anEntAndSubs.find(anEntIter->distance) != anEntAndSubs.end())
+        return false;
     }
-    // If the feature is a circle, add its radius as a sub
-    if (theFeature->getKind() == SketchPlugin_Circle::ID()) {
-      AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
-      isUpdated = update(aRadius, theGroup) || isUpdated;
-      aSubs.push_back(entity(aRadius));
+    std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
+    for (; aConstrIter != myConstraints.end(); aConstrIter++) {
+      Slvs_hEntity anEntIDs[6] = {aConstrIter->ptA, aConstrIter->ptB,
+          aConstrIter->entityA, aConstrIter->entityB,
+          aConstrIter->entityC, aConstrIter->entityD};
+      for (int i = 0; i < 6; i++)
+        if (anEntAndSubs.find(anEntIDs[i]) != anEntAndSubs.end())
+          return false;
+    }
+    // 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++)
+      if (anEntity.param[i] != SLVS_E_UNKNOWN)
+        aResult = removeParameter(anEntity.param[i]) && aResult;
+    for (int i = 0; i < 4; i++)
+      if (anEntity.point[i] != SLVS_E_UNKNOWN)
+        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;
+}
+
+void SketchSolver_Storage::removeUnusedEntities()
+{
+  std::set<Slvs_hEntity> anUnusedEntities;
+  std::vector<Slvs_Entity>::const_iterator aEIt = myEntities.begin();
+  for (; aEIt != myEntities.end(); ++aEIt) {
+    if (aEIt->h == aEIt->wrkpl) {
+      // don't remove workplane
+      anUnusedEntities.erase(aEIt->point[0]);
+      anUnusedEntities.erase(aEIt->normal);
+      continue;
     }
-    // If the feature if circle or arc, we need to add normal of the sketch to the list of subs
-    if (theFeature->getKind() == SketchPlugin_Arc::ID() ||
-        theFeature->getKind() == SketchPlugin_Circle::ID()) {
-      EntityWrapperPtr aNormal = getNormal();
-      if (aNormal) aSubs.push_back(aNormal);
+    anUnusedEntities.insert(aEIt->h);
+  }
+
+  std::vector<Slvs_Constraint>::const_iterator aCIt = myConstraints.begin();
+  for (; aCIt != myConstraints.end(); ++aCIt) {
+    Slvs_hEntity aSubs[6] = {
+        aCIt->entityA, aCIt->entityB,
+        aCIt->entityC, aCIt->entityD,
+        aCIt->ptA,     aCIt->ptB};
+    for (int i = 0; i < 6; i++) {
+      if (aSubs[i] != SLVS_E_UNKNOWN) {
+        anUnusedEntities.erase(aSubs[i]);
+        int aPos = Search(aSubs[i], myEntities);
+        if (aPos >= 0 && aPos < (int)myEntities.size()) {
+          for (int j = 0; j < 4; j++)
+            if (myEntities[aPos].point[j] != SLVS_E_UNKNOWN)
+              anUnusedEntities.erase(myEntities[aPos].point[j]);
+          if (myEntities[aPos].distance != SLVS_E_UNKNOWN)
+            anUnusedEntities.erase(myEntities[aPos].distance);
+        }
+      }
     }
-    // Secondly, convert feature
-    BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-    aRelated = aBuilder->createFeature(theFeature, aSubs, theGroup);
-    if (!aRelated)
-      return false;
-    addEntity(theFeature, aRelated);
-  } else if (theGroup != GID_UNKNOWN)
-    changeGroup(aRelated, theGroup);
-  return update(aRelated) || isUpdated;
+  }
+
+  std::set<Slvs_hEntity>::const_iterator anEntIt = anUnusedEntities.begin();
+  while (anEntIt != anUnusedEntities.end()) {
+    int aPos = Search(*anEntIt, myEntities);
+    if (aPos < 0 && aPos >= (int)myEntities.size())
+      continue;
+    Slvs_Entity anEntity = myEntities[aPos];
+    // Remove entity if and only if all its parameters unused
+    bool isUsed = false;
+    if (anEntity.distance != SLVS_E_UNKNOWN && 
+      anUnusedEntities.find(anEntity.distance) == anUnusedEntities.end())
+      isUsed = true;
+    for (int i = 0; i < 4 && !isUsed; i++)
+      if (anEntity.point[i] != SLVS_E_UNKNOWN &&
+          anUnusedEntities.find(anEntity.point[i]) == anUnusedEntities.end())
+        isUsed = true;
+    if (isUsed) {
+      anUnusedEntities.erase(anEntity.distance);
+      for (int i = 0; i < 4; i++)
+        if (anEntity.point[i] != SLVS_E_UNKNOWN)
+          anUnusedEntities.erase(anEntity.point[i]);
+      std::set<Slvs_hEntity>::iterator aRemoveIt = anEntIt++;
+      anUnusedEntities.erase(aRemoveIt);
+      continue;
+    }
+    ++anEntIt;
+  }
+
+  for (anEntIt = anUnusedEntities.begin(); anEntIt != anUnusedEntities.end(); ++anEntIt) {
+    int aPos = Search(*anEntIt, myEntities);
+    if (aPos >= 0 && aPos < (int)myEntities.size()) {
+      // Remove entity 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)
+        removeParameter(anEntity.distance);
+      for (int i = 0; i < 4; i++)
+        if (anEntity.param[i] != SLVS_E_UNKNOWN)
+          removeParameter(anEntity.param[i]);
+      for (int i = 0; i < 4; i++)
+        if (anEntity.point[i] != SLVS_E_UNKNOWN)
+          removeEntity(anEntity.point[i]);
+      myRemovedEntities.insert(*anEntIt);
+      if (anEntity.type == SLVS_E_POINT_IN_2D || anEntity.type == SLVS_E_POINT_IN_3D)
+        removeCoincidentPoint(*anEntIt);
+    }
+  }
+
+  if (!anUnusedEntities.empty())
+    myNeedToResolve = true;
+}
+
+bool SketchSolver_Storage::isUsedByConstraints(const Slvs_hEntity& theEntityID) const
+{
+  std::vector<Slvs_Constraint>::const_iterator aCIt = myConstraints.begin();
+  for (; aCIt != myConstraints.end(); ++aCIt) {
+    Slvs_hEntity aSubs[6] = {
+        aCIt->entityA, aCIt->entityB,
+        aCIt->entityC, aCIt->entityD,
+        aCIt->ptA,     aCIt->ptB};
+    for (int i = 0; i < 6; i++)
+      if (aSubs[i] != SLVS_E_UNKNOWN && aSubs[i] == theEntityID)
+        return true;
+  }
+  return false;
+}
+
+const Slvs_Entity& SketchSolver_Storage::getEntity(const Slvs_hEntity& theEntityID) const
+{
+  int aPos = Search(theEntityID, myEntities);
+  if (aPos >= 0 && aPos < (int)myEntities.size())
+    return myEntities[aPos];
+
+  // Entity is not found, return empty object
+  static Slvs_Entity aDummy;
+  aDummy.h = SLVS_E_UNKNOWN;
+  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++;
+    }
+  }
 }
 
-bool SketchSolver_Storage::update(AttributePtr theAttribute, const GroupID& theGroup)
+
+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()) {
+      aCoincident = *aCPIter;
+      break;
+    }
+
+  // Check whether one of coincident points is out-of-group
+  std::set<Slvs_hEntity>::const_iterator aCoincIt = aCoincident.begin();
+  for (; aCoincIt != aCoincident.end(); ++aCoincIt) {
+    Slvs_Entity aPoint = getEntity(*aCoincIt);
+    if (aPoint.group == SLVS_G_OUTOFGROUP)
+      return true;
+  }
+
+  // Search the Rigid constraint
+  theFixed = SLVS_C_UNKNOWN;
+  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()) {
+      theFixed = aConstrIter->h;
+      if (aConstrIter->ptA == thePointID)
+        return true;
+    }
+  if (theFixed != SLVS_C_UNKNOWN)
+    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
 {
-  AttributePtr anAttribute = theAttribute;
-  AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
-  if (aRefAttr) {
-    if (aRefAttr->isObject()) {
-      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
-      return update(aFeature, theGroup);
-    } else
-      anAttribute = aRefAttr->attr();
+  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++;
   }
 
-  EntityWrapperPtr aRelated = entity(anAttribute);
-  if (!aRelated) { // Attribute is not exist, create it
-    BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-    aRelated = aBuilder->createAttribute(anAttribute, theGroup);
-    if (!aRelated)
+  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/Vertical/Horizontal and Length constraints
+    aList = getConstraintsByType(SLVS_C_PARALLEL);
+    aList.splice(aList.end(), getConstraintsByType(SLVS_C_PERPENDICULAR));
+    aList.splice(aList.end(), getConstraintsByType(SLVS_C_VERTICAL));
+    aList.splice(aList.end(), getConstraintsByType(SLVS_C_HORIZONTAL));
+    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;
-    addEntity(anAttribute, aRelated);
-  } else if (theGroup != GID_UNKNOWN)
-    changeGroup(aRelated, theGroup);
-  return update(aRelated);
+    // 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)
+{
+  if (theConstraint.h > 0 && theConstraint.h <= myConstrMaxID) {
+    // Constraint is already used, rewrite it
+    return updateConstraint(theConstraint);
+  }
+
+  Slvs_Constraint aConstraint = theConstraint;
+
+  // Find a constraint with same type uses same arguments to show user overconstraint situation
+  std::vector<Slvs_Constraint>::iterator aCIt = myConstraints.begin();
+  for (; aCIt != myConstraints.end(); aCIt++) {
+    if (aConstraint.type != aCIt->type)
+      continue;
+    if (aConstraint.ptA == aCIt->ptA && aConstraint.ptB == aCIt->ptB &&
+        aConstraint.entityA == aCIt->entityA && aConstraint.entityB == aCIt->entityB &&
+        aConstraint.entityC == aCIt->entityC && aConstraint.entityD == aCIt->entityD)
+      myDuplicatedConstraint = true;
+  }
+
+  if (aConstraint.h > myConstrMaxID)
+    myConstrMaxID = aConstraint.h;
+  else
+    aConstraint.h = ++myConstrMaxID;
+  myConstraints.push_back(aConstraint);
+  myNeedToResolve = true;
+  if (aConstraint.type == SLVS_C_POINTS_COINCIDENT)
+    addCoincidentPoints(aConstraint.ptA, aConstraint.ptB);
+  return aConstraint.h;
+}
 
-const std::list<ConstraintWrapperPtr>& SketchSolver_Storage::constraint(
-    const ConstraintPtr& theConstraint) const
+Slvs_hConstraint SketchSolver_Storage::updateConstraint(const Slvs_Constraint& theConstraint)
 {
-  static std::list<ConstraintWrapperPtr> aDummy;
+  if (theConstraint.h > 0 && theConstraint.h <= myConstrMaxID) {
+    // Constraint already used, rewrite it
+    int aPos = Search(theConstraint.h, myConstraints);
+    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;
+    }
+  }
 
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr>>::const_iterator
-      aFound = myConstraintMap.find(theConstraint);
-  if (aFound != myConstraintMap.end())
-    return aFound->second;
-  return aDummy;
+  // Constraint is not found, add new one
+  Slvs_Constraint aConstraint = theConstraint;
+  aConstraint.h = 0;
+  return addConstraint(aConstraint);
+}
+
+bool SketchSolver_Storage::removeConstraint(const Slvs_hConstraint& theConstraintID)
+{
+  bool aResult = true;
+  int aPos = Search(theConstraintID, myConstraints);
+  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);
+    if (aConstraint.type == SLVS_C_POINTS_COINCIDENT)
+      removeCoincidence(aConstraint);
+
+    // Remove all entities
+    Slvs_hEntity anEntities[6] = {aConstraint.ptA, aConstraint.ptB,
+        aConstraint.entityA, aConstraint.entityB,
+        aConstraint.entityC, aConstraint.entityD};
+    for (int i = 0; i < 6; i++)
+      if (anEntities[i] != SLVS_E_UNKNOWN)
+        aResult = removeEntity(anEntities[i]) && aResult;
+    // remove temporary fixed point, if available
+    if (myFixed == theConstraintID)
+      myFixed = SLVS_E_UNKNOWN;
+    if (myDuplicatedConstraint) {
+      // Check the duplicated constraints are still available
+      myDuplicatedConstraint = false;
+      std::vector<Slvs_Constraint>::const_iterator anIt1 = myConstraints.begin();
+      std::vector<Slvs_Constraint>::const_iterator anIt2 = myConstraints.begin();
+      for (; anIt1 != myConstraints.end() && !myDuplicatedConstraint; anIt1++)
+        for (anIt2 = anIt1+1; anIt2 != myConstraints.end() && !myDuplicatedConstraint; anIt2++) {
+          if (anIt1->type != anIt2->type)
+            continue;
+          if (anIt1->ptA == anIt2->ptA && anIt1->ptB == anIt2->ptB &&
+              anIt1->entityA == anIt2->entityA && anIt1->entityB == anIt2->entityB &&
+              anIt1->entityC == anIt2->entityC && anIt1->entityD == anIt2->entityD)
+            myDuplicatedConstraint = true;
+        }
+    }
+  }
+  return aResult;
 }
 
-const EntityWrapperPtr& SketchSolver_Storage::entity(const FeaturePtr& theFeature) const
+const Slvs_Constraint& SketchSolver_Storage::getConstraint(const Slvs_hConstraint& theConstraintID) const
 {
-  static EntityWrapperPtr aDummy;
+  int aPos = Search(theConstraintID, myConstraints);
+  if (aPos >= 0 && aPos < (int)myConstraints.size())
+    return myConstraints[aPos];
 
-  std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
-  if (aFound != myFeatureMap.end())
-    return aFound->second;
+  // Constraint is not found, return empty object
+  static Slvs_Constraint aDummy;
+  aDummy.h = 0;
   return aDummy;
 }
 
-const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttribute) const
+std::list<Slvs_Constraint> SketchSolver_Storage::getConstraintsByType(int theConstraintType) const
+{
+  std::list<Slvs_Constraint> aResult;
+  std::vector<Slvs_Constraint>::const_iterator aCIter = myConstraints.begin();
+  for (; aCIter != myConstraints.end(); aCIter++)
+    if (aCIter->type == theConstraintType)
+      aResult.push_back(*aCIter);
+  return aResult;
+}
+
+
+void SketchSolver_Storage::addConstraintWhereDragged(const Slvs_hConstraint& theConstraintID)
+{
+  if (myFixed != SLVS_E_UNKNOWN)
+    return; // the point is already fixed
+  int aPos = Search(theConstraintID, myConstraints);
+  if (aPos >= 0 && aPos < (int)myConstraints.size())
+    myFixed = theConstraintID;
+}
+
+void SketchSolver_Storage::addTemporaryConstraint(const Slvs_hConstraint& theConstraintID)
 {
-  static EntityWrapperPtr aDummy;
+  myTemporaryConstraints.insert(theConstraintID);
+}
 
-  std::map<AttributePtr, EntityWrapperPtr>::const_iterator
-      aFound = myAttributeMap.find(theAttribute);
-  if (aFound != myAttributeMap.end())
-    return aFound->second;
+void SketchSolver_Storage::removeTemporaryConstraints()
+{
+  myTemporaryConstraints.clear();
+}
 
-  AttributeRefAttrPtr aRefAttr =
-      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
-  if (aRefAttr) {
-    if (aRefAttr->isObject()) {
-      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
-      return entity(aFeature);
-    } else
-      return entity(aRefAttr->attr());
+int SketchSolver_Storage::deleteTemporaryConstraint()
+{
+  if (myTemporaryConstraints.empty())
+    return 0;
+  // Search the point-on-line or a non-rigid constraint
+  std::set<Slvs_hConstraint>::iterator aCIt = myTemporaryConstraints.begin();
+  for (; aCIt != myTemporaryConstraints.end(); aCIt++) {
+    int aPos = Search(*aCIt, myConstraints);
+    if (aPos >= (int)myConstraints.size() || myConstraints[aPos].type != SLVS_C_WHERE_DRAGGED)
+      break;
+    std::vector<Slvs_Constraint>::iterator anIt = myConstraints.begin();
+    for (; anIt != myConstraints.end(); anIt++)
+      if (anIt->type == SLVS_C_PT_ON_LINE && anIt->ptA == myConstraints[aPos].ptA)
+        break;
+    if (anIt != myConstraints.end())
+      break;
   }
-  return aDummy;
+  if (aCIt == myTemporaryConstraints.end())
+    aCIt = myTemporaryConstraints.begin();
+  bool aNewFixed = (*aCIt == myFixed);
+  removeConstraint(*aCIt);
+  myTemporaryConstraints.erase(aCIt);
+  if (aNewFixed) {
+    for (aCIt = myTemporaryConstraints.begin(); aCIt != myTemporaryConstraints.end(); aCIt++) {
+      int aPos = Search(*aCIt, myConstraints);
+      if (myConstraints[aPos].type == SLVS_C_WHERE_DRAGGED) {
+        myFixed = *aCIt;
+        break;
+      }
+    }
+  }
+  return (int)myTemporaryConstraints.size();
 }
 
-////const ParameterWrapperPtr& SketchSolver_Storage::parameter(const AttributeDoublePtr& theAttribute) const
-////{
-////  static ParameterWrapperPtr aDummy;
-////
-////  std::map<AttributeDoublePtr, ParameterWrapperPtr>::const_iterator
-////      aFound = myParametersMap.find(theAttribute);
-////  if (aFound != myParametersMap.end())
-////    return aFound->second;
-////  return aDummy;
-////}
+bool SketchSolver_Storage::isTemporary(const Slvs_hConstraint& theConstraintID) const
+{
+  return myTemporaryConstraints.find(theConstraintID) != myTemporaryConstraints.end();
+}
 
 
-bool SketchSolver_Storage::isInteract(const FeaturePtr& theFeature) const
+void SketchSolver_Storage::getRemoved(
+    std::set<Slvs_hParam>& theParameters,
+    std::set<Slvs_hEntity>& theEntities,
+    std::set<Slvs_hConstraint>& theConstraints)
 {
-  if (!theFeature)
-    return false;
-  if (myConstraintMap.empty())
-    return true; // empty storage interacts with each feature
+  theParameters = myRemovedParameters;
+  theEntities = myRemovedEntities;
+  theConstraints = myRemovedConstraints;
+
+  myRemovedParameters.clear();
+  myRemovedEntities.clear();
+  myRemovedConstraints.clear();
+}
+
+void SketchSolver_Storage::initializeSolver(SketchSolver_Solver& theSolver)
+{
+  theSolver.setParameters(myParameters.data(), (int)myParameters.size());
+  theSolver.setEntities(myEntities.data(), (int)myEntities.size());
+
+  // 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;
+      } else
+        aFoundIter = aCIter;
+      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;
+    }
+}
 
-  ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
-  if (aConstraint) {
-    if (myConstraintMap.find(aConstraint) != myConstraintMap.end())
+void SketchSolver_Storage::removeCoincidence(const Slvs_Constraint& theCoincidence)
+{
+  // Find set of coincident points
+  std::vector< std::set<Slvs_hEntity> >::iterator aCIt = myCoincidentPoints.begin();
+  for (; aCIt != myCoincidentPoints.end(); ++aCIt)
+    if (aCIt->find(theCoincidence.ptA) != aCIt->end() ||
+        aCIt->find(theCoincidence.ptB) != aCIt->end())
+      break;
+  if (aCIt == myCoincidentPoints.end())
+    return;
+
+  // Leave only the points which are still coincident
+  std::set<Slvs_hEntity> aRemainCoincidence;
+  std::vector<Slvs_Constraint>::const_iterator aConstrIt = myConstraints.begin();
+  for (; aConstrIt != myConstraints.end(); ++aConstrIt) {
+    if (aConstrIt->type != SLVS_C_POINTS_COINCIDENT)
+      continue;
+    if (aCIt->find(aConstrIt->ptA) != aCIt->end() ||
+        aCIt->find(aConstrIt->ptB) != aCIt->end()) {
+      aRemainCoincidence.insert(aConstrIt->ptA);
+      aRemainCoincidence.insert(aConstrIt->ptB);
+    }
+  }
+  if (aRemainCoincidence.size() <= 1)
+    myCoincidentPoints.erase(aCIt);
+  else
+    aCIt->swap(aRemainCoincidence);
+}
+
+bool SketchSolver_Storage::isCoincident(
+    const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const
+{
+  std::vector< std::set<Slvs_hEntity> >::const_iterator aCIter = myCoincidentPoints.begin();
+  for (; aCIter != myCoincidentPoints.end(); aCIter++)
+    if (aCIter->find(thePoint1) != aCIter->end() && aCIter->find(thePoint2) != aCIter->end())
       return true;
-  } else if (myFeatureMap.find(theFeature) != myFeatureMap.end())
+  return false;
+}
+
+bool SketchSolver_Storage::isEqual(
+    const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const
+{
+  if (isCoincident(thePoint1, thePoint2))
     return true;
 
-  std::list<AttributePtr> anAttrList = theFeature->data()->attributes(std::string());
-  std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
-  for (; anIt != anAttrList.end(); ++anIt)
-    if (isInteract(*anIt))
+  // Precise checking of coincidence: verify that points have equal coordinates
+  int aEnt1Pos = Search(thePoint1, myEntities);
+  int aEnt2Pos = Search(thePoint2, myEntities);
+  if (aEnt1Pos >= 0 && aEnt1Pos < (int)myEntities.size() &&
+      aEnt2Pos >= 0 && aEnt2Pos < (int)myEntities.size()) {
+    double aDist[2];
+    int aParamPos;
+    for (int i = 0; i < 2; i++) {
+      aParamPos = Search(myEntities[aEnt1Pos].param[i], myParameters);
+      aDist[i] = myParameters[aParamPos].val;
+      aParamPos = Search(myEntities[aEnt2Pos].param[i], myParameters);
+      aDist[i] -= myParameters[aParamPos].val;
+    }
+    if (aDist[0] * aDist[0] + aDist[1] * aDist[1] < tolerance * tolerance)
       return true;
-
+  }
   return false;
 }
 
-bool SketchSolver_Storage::isInteract(const AttributePtr& theAttribute) const
+
+std::vector<Slvs_hConstraint> SketchSolver_Storage::fixEntity(const Slvs_hEntity& theEntity)
 {
-  if (!theAttribute)
-    return false;
+  std::vector<Slvs_hConstraint> aNewConstraints;
 
-  AttributeRefAttrPtr aRefAttr =
-      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
-  if (!aRefAttr)
-    return myAttributeMap.find(theAttribute) != myAttributeMap.end();
-  if (!aRefAttr->isObject())
-    return myAttributeMap.find(aRefAttr->attr()) != myAttributeMap.end();
+  int aPos = Search(theEntity, myEntities);
+  if (aPos >= 0 && aPos < (int)myEntities.size()) {
+    switch (myEntities[aPos].type) {
+    case SLVS_E_POINT_IN_2D:
+    case SLVS_E_POINT_IN_3D:
+      fixPoint(myEntities[aPos], aNewConstraints);
+      break;
+    case SLVS_E_LINE_SEGMENT:
+      fixLine(myEntities[aPos], aNewConstraints);
+      break;
+    case SLVS_E_CIRCLE:
+      fixCircle(myEntities[aPos], aNewConstraints);
+      break;
+    case SLVS_E_ARC_OF_CIRCLE:
+      fixArc(myEntities[aPos], aNewConstraints);
+      break;
+    default:
+      break;
+    }
+  }
 
-  FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
-  return isInteract(aFeature);
+  return aNewConstraints;
 }
 
-bool SketchSolver_Storage::isConsistent() const
+void SketchSolver_Storage::fixPoint(const Slvs_Entity& thePoint,
+    std::vector<Slvs_hConstraint>& theCreated)
 {
-  // Check the constraints are valid
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
-      aCIter = myConstraintMap.begin();
-  for (; aCIter != myConstraintMap.end(); ++aCIter)
-    if (!aCIter->first->data() || !aCIter->first->data()->isValid())
-      return false;
-  // Check the features are valid
-  std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
-  for (; aFIter != myFeatureMap.end(); aFIter++)
-    if (!aFIter->first->data() || !aFIter->first->data()->isValid())
-      return false;
-  return true;
-}
-
-void SketchSolver_Storage::removeInvalidEntities()
-{
-  // Remove invalid constraints
-  std::list<ConstraintPtr> anInvalidConstraints;
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
-      aCIter = myConstraintMap.begin();
-  for (; aCIter != myConstraintMap.end(); ++aCIter)
-    if (!aCIter->first->data() || !aCIter->first->data()->isValid())
-      anInvalidConstraints.push_back(aCIter->first);
-  std::list<ConstraintPtr>::const_iterator anInvCIt = anInvalidConstraints.begin();
-  for (; anInvCIt != anInvalidConstraints.end(); ++anInvCIt)
-    removeConstraint(*anInvCIt);
-  // Remove invalid features
-  std::list<FeaturePtr> anInvalidFeatures;
-  std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
-  for (; aFIter != myFeatureMap.end(); aFIter++)
-    if (!aFIter->first->data() || !aFIter->first->data()->isValid())
-      anInvalidFeatures.push_back(aFIter->first);
-  std::list<FeaturePtr>::const_iterator anInvFIt = anInvalidFeatures.begin();
-  for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt)
-    removeEntity(*anInvFIt);
-}
-
-EntityWrapperPtr SketchSolver_Storage::getNormal() const
-{
-  EntityWrapperPtr aSketch = sketch();
-  if (!aSketch)
-    return aSketch;
-
-  // Find normal entity
-  const std::list<EntityWrapperPtr>& aSketchSubs = aSketch->subEntities();
-  std::list<EntityWrapperPtr>::const_iterator aSIt = aSketchSubs.begin();
-  for (; aSIt != aSketchSubs.end(); ++aSIt)
-    if ((*aSIt)->type() == ENTITY_NORMAL)
-      return *aSIt;
-  return EntityWrapperPtr();
-}
-
-const EntityWrapperPtr& SketchSolver_Storage::sketch() const
-{
-  static EntityWrapperPtr aDummySketch;
-
-  std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
-  for (; aFIt != myFeatureMap.end(); ++aFIt)
-    if (aFIt->second->type() == ENTITY_SKETCH)
-      break;
-  if (aFIt == myFeatureMap.end())
-    return aDummySketch;
-  return aFIt->second;
+  Slvs_Constraint aConstraint;
+  Slvs_hConstraint aConstrID = SLVS_E_UNKNOWN;
+  bool isFixed = isPointFixed(thePoint.h, aConstrID, true);
+  bool isForceUpdate = (isFixed && isTemporary(aConstrID));
+  if (!isForceUpdate) { // create new constraint
+    if (isFixed) return;
+    aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, thePoint.group, SLVS_C_WHERE_DRAGGED, thePoint.wrkpl,
+        0.0, thePoint.h, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+    aConstraint.h = addConstraint(aConstraint);
+    theCreated.push_back(aConstraint.h);
+  } else { // update already existent constraint
+    if (!isFixed || aConstrID == SLVS_E_UNKNOWN)
+      return;
+    int aPos = Search(aConstrID, myConstraints);
+    if (aPos >= 0 && aPos < (int)myConstraints.size())
+      myConstraints[aPos].ptA = thePoint.h;
+  }
 }
 
-void SketchSolver_Storage::setSketch(const EntityWrapperPtr& theSketch)
+void SketchSolver_Storage::fixLine(const Slvs_Entity& theLine,
+    std::vector<Slvs_hConstraint>& theCreated)
 {
-  if (sketch())
+  Slvs_Entity aPoint[2] = {
+      getEntity(theLine.point[0]),
+      getEntity(theLine.point[1])
+  };
+
+  Slvs_Constraint anEqual;
+  if (isAxisParallel(theLine.h)) {
+    // Fix one point and a line length
+    Slvs_hConstraint aFixed;
+    if (!isPointFixed(theLine.point[0], aFixed, true) &&
+        !isPointFixed(theLine.point[1], aFixed, true))
+      fixPoint(aPoint[0], theCreated);
+    if (!isUsedInEqual(theLine.h, anEqual)) {
+      // Check the distance is not set yet
+      std::vector<Slvs_Constraint>::const_iterator aDistIt = myConstraints.begin();
+      for (; aDistIt != myConstraints.end(); ++aDistIt)
+        if ((aDistIt->type == SLVS_C_PT_PT_DISTANCE) &&
+           ((aDistIt->ptA == theLine.point[0] && aDistIt->ptB == theLine.point[1]) ||
+            (aDistIt->ptA == theLine.point[1] && aDistIt->ptB == theLine.point[0])))
+          return;
+      // Calculate distance between points on the line
+      double aCoords[4];
+      for (int i = 0; i < 2; i++)
+        for (int j = 0; j < 2; j++) {
+          Slvs_Param aParam = getParameter(aPoint[i].param[j]);
+          aCoords[2*i+j] = aParam.val;
+        }
+
+      double aLength = sqrt((aCoords[2] - aCoords[0]) * (aCoords[2] - aCoords[0]) + 
+                            (aCoords[3] - aCoords[1]) * (aCoords[3] - aCoords[1]));
+      // fix line length
+      Slvs_Constraint aDistance = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theLine.group,
+          SLVS_C_PT_PT_DISTANCE, theLine.wrkpl, aLength,
+          theLine.point[0], theLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+      aDistance.h = addConstraint(aDistance);
+      theCreated.push_back(aDistance.h);
+    }
     return;
-  addEntity(FeaturePtr(), theSketch);
+  }
+  else if (isUsedInEqual(theLine.h, anEqual)) {
+    // Check another entity of Equal is already fixed
+    Slvs_hEntity anOtherEntID = anEqual.entityA == theLine.h ? anEqual.entityB : anEqual.entityA;
+    if (isEntityFixed(anOtherEntID, true)) {
+      // Fix start point of the line (if end point is not fixed yet) ...
+      Slvs_hConstraint anEndFixedID = SLVS_E_UNKNOWN;
+      bool isFixed = isPointFixed(theLine.point[1], anEndFixedID, true);
+      if (isFixed == SLVS_E_UNKNOWN)
+        fixPoint(aPoint[0], theCreated);
+      // ...  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::vector<Slvs_Constraint>::const_iterator aPLIter = myConstraints.begin();
+      for (; aPLIter != myConstraints.end() && !isPonLineFixed; ++aPLIter)
+        if (aPLIter->type == SLVS_C_PT_ON_LINE && aPLIter->entityA == theLine.h) {
+          isPonLineFixed = isPointFixed(aPLIter->ptA, anEndFixedID);
+          aFixedPoint = aPLIter->ptA;
+        }
+
+      if (isPonLineFixed) { // update existent constraint
+        copyEntity(aPointToCopy, aFixedPoint);
+      } else { // create new constraint
+        Slvs_hEntity aCopied = copyEntity(aPointToCopy);
+        Slvs_Constraint aPonLine = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theLine.group, SLVS_C_PT_ON_LINE,
+            theLine.wrkpl, 0.0, aCopied, SLVS_E_UNKNOWN, theLine.h, SLVS_E_UNKNOWN);
+        aPonLine.h = addConstraint(aPonLine);
+        theCreated.push_back(aPonLine.h);
+        fixPoint(getEntity(aCopied), theCreated);
+      }
+      return;
+    }
+  }
+
+  // Fix both points
+  for (int i = 0; i < 2; i++)
+    fixPoint(aPoint[i], theCreated);
 }
 
-void SketchSolver_Storage::blockEvents(bool isBlocked) const
+void SketchSolver_Storage::fixCircle(const Slvs_Entity& theCircle,
+    std::vector<Slvs_hConstraint>& theCreated)
 {
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
-      aCIter = myConstraintMap.begin();
-  for (; aCIter != myConstraintMap.end(); aCIter++)
-    if (aCIter->first->data() && aCIter->first->data()->isValid())
-      aCIter->first->data()->blockSendAttributeUpdated(isBlocked);
+  bool isFixRadius = true;
+  // Verify the arc is under Equal constraint
+  Slvs_Constraint anEqual;
+  if (isUsedInEqual(theCircle.h, anEqual)) {
+    // Check another entity of Equal is already fixed
+    Slvs_hEntity anOtherEntID = anEqual.entityA == theCircle.h ? anEqual.entityB : anEqual.entityA;
+    if (isEntityFixed(anOtherEntID, true))
+      isFixRadius = false;
+  }
+
+  fixPoint(getEntity(theCircle.point[0]), theCreated);
 
-  std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
-  for (; aFIter != myFeatureMap.end(); aFIter++)
-    if (aFIter->first->data() && aFIter->first->data()->isValid())
-      aFIter->first->data()->blockSendAttributeUpdated(isBlocked);
+  if (isFixRadius) {
+    // Search the radius is already fixed
+    std::vector<Slvs_Constraint>::const_iterator aDiamIter = myConstraints.begin();
+    for (; aDiamIter != myConstraints.end(); ++aDiamIter)
+      if (aDiamIter->type == SLVS_C_DIAMETER && aDiamIter->entityA == theCircle.h)
+        return;
 
-  std::map<AttributePtr, EntityWrapperPtr>::const_iterator anAtIter = myAttributeMap.begin();
-  for (; anAtIter != myAttributeMap.end(); anAtIter++)
-    if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
-        anAtIter->first->owner()->data()->isValid())
-      anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
+    // Fix radius of a circle
+    const Slvs_Entity& aRadEnt = getEntity(theCircle.distance);
+    double aRadius = getParameter(aRadEnt.param[0]).val;
+    Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theCircle.group, SLVS_C_DIAMETER,
+        theCircle.wrkpl, aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, theCircle.h, SLVS_E_UNKNOWN);
+    aFixedR.h = addConstraint(aFixedR);
+    theCreated.push_back(aFixedR.h);
+  }
 }
 
+void SketchSolver_Storage::fixArc(const Slvs_Entity& theArc,
+    std::vector<Slvs_hConstraint>& theCreated)
+{
+  Slvs_Entity aPoint[3] = {
+      getEntity(theArc.point[0]),
+      getEntity(theArc.point[1]),
+      getEntity(theArc.point[2])
+  };
+
+  bool isFixRadius = true;
+  std::list<Slvs_Entity> aPointsToFix;
+  aPointsToFix.push_back(aPoint[1]);
+  aPointsToFix.push_back(aPoint[2]);
+
+  // Verify the arc is under Equal constraint
+  Slvs_Constraint anEqual;
+  if (isUsedInEqual(theArc.h, anEqual)) {
+    // Check another entity of Equal is already fixed
+    Slvs_hEntity anOtherEntID = anEqual.entityA == theArc.h ? anEqual.entityB : anEqual.entityA;
+    if (isEntityFixed(anOtherEntID, true)) {
+      isFixRadius = false;
+      Slvs_Entity anOtherEntity = getEntity(anOtherEntID);
+      if (anOtherEntity.type == SLVS_E_LINE_SEGMENT) {
+        aPointsToFix.pop_back();
+        aPointsToFix.push_back(aPoint[0]);
+      }
+    }
+  }
+
+  Slvs_hConstraint aConstrID;
+  int aNbPointsToFix = 2; // number of fixed points for the arc
+  if (isPointFixed(theArc.point[0], aConstrID, true))
+    aNbPointsToFix--;
 
+  double anArcPoints[3][2];
+  for (int i = 0; i < 3; i++) {
+    const Slvs_Entity& aPointOnArc = getEntity(theArc.point[i]);
+    for (int j = 0; j < 2; j++)
+      anArcPoints[i][j] = getParameter(aPointOnArc.param[j]).val;
+  }
+
+  // Radius of the arc
+  std::shared_ptr<GeomAPI_Pnt2d> aCenter(new GeomAPI_Pnt2d(anArcPoints[0][0], anArcPoints[0][1]));
+  std::shared_ptr<GeomAPI_Pnt2d> aStart(new GeomAPI_Pnt2d(anArcPoints[1][0], anArcPoints[1][1]));
+  double aRadius = aCenter->distance(aStart);
+
+  // Update end point of the arc to be on a curve
+  std::shared_ptr<GeomAPI_Pnt2d> anEnd(new GeomAPI_Pnt2d(anArcPoints[2][0], anArcPoints[2][1]));
+  double aDistance = anEnd->distance(aCenter);
+  std::shared_ptr<GeomAPI_XY> aDir = anEnd->xy()->decreased(aCenter->xy());
+  if (aDistance < tolerance)
+    aDir = aStart->xy()->decreased(aCenter->xy())->multiplied(-1.0);
+  else
+    aDir = aDir->multiplied(aRadius / aDistance);
+  double xy[2] = {aCenter->x() + aDir->x(), aCenter->y() + aDir->y()};
+  const Slvs_Entity& aEndPoint = getEntity(theArc.point[2]);
+  for (int i = 0; i < 2; i++) {
+    Slvs_Param aParam = getParameter(aEndPoint.param[i]);
+    aParam.val = xy[i];
+    updateParameter(aParam);
+  }
 
+  std::list<Slvs_Entity>::iterator aPtIt = aPointsToFix.begin();
+  for (; aNbPointsToFix > 0; aPtIt++, aNbPointsToFix--)
+    fixPoint(*aPtIt, theCreated);
+
+  if (isFixRadius) {
+    // Fix radius of the arc
+    bool isExists = false;
+    std::vector<Slvs_Constraint>::iterator anIt = myConstraints.begin();
+    for (; anIt != myConstraints.end() && !isExists; ++anIt)
+      if (anIt->type == SLVS_C_DIAMETER && anIt->entityA == theArc.h)
+        isExists = true;
+    if (!isExists) {
+      Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theArc.group, SLVS_C_DIAMETER,
+          theArc.wrkpl, aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, theArc.h, SLVS_E_UNKNOWN);
+      aFixedR.h = addConstraint(aFixedR);
+      theCreated.push_back(aFixedR.h);
+    }
+  }
+}
 
 
+bool SketchSolver_Storage::isAxisParallel(const Slvs_hEntity& theEntity) const
+{
+  std::vector<Slvs_Constraint>::const_iterator anIter = myConstraints.begin();
+  for (; anIter != myConstraints.end(); anIter++)
+    if ((anIter->type == SLVS_C_HORIZONTAL || anIter->type == SLVS_C_VERTICAL) && 
+        anIter->entityA == theEntity)
+      return true;
+  return false;
+}
 
-// ==============   Auxiliary functions   ====================================
-bool isEqual(const std::list<ConstraintWrapperPtr>& theCVec1,
-             const std::list<ConstraintWrapperPtr>& theCVec2)
+bool SketchSolver_Storage::isUsedInEqual(
+    const Slvs_hEntity& theEntity, Slvs_Constraint& theEqual) const
 {
-  if (theCVec1.size() != theCVec2.size())
+  // Check the entity is used in Equal constraint
+  std::vector<Slvs_Constraint>::const_iterator anEqIter = myConstraints.begin();
+  for (; anEqIter != myConstraints.end(); anEqIter++)
+    if ((anEqIter->type == SLVS_C_EQUAL_LENGTH_LINES ||
+         anEqIter->type == SLVS_C_EQUAL_LINE_ARC_LEN ||
+         anEqIter->type == SLVS_C_EQUAL_RADIUS) &&
+       (anEqIter->entityA == theEntity || anEqIter->entityB == theEntity)) {
+      theEqual = *anEqIter;
+      return true;
+    }
+  return false;
+}
+
+bool SketchSolver_Storage::isNeedToResolve()
+{
+  if (myConstraints.empty())
     return false;
 
-  std::list<bool> aChecked(theCVec2.size(), false);
-  std::list<ConstraintWrapperPtr>::const_iterator anIt1 = theCVec1.begin();
-  for (; anIt1 != theCVec1.end(); ++anIt1) {
-    std::list<ConstraintWrapperPtr>::const_iterator anIt2 = theCVec2.begin();
-    std::list<bool>::iterator aCheckIt = aChecked.begin();
-    while (aCheckIt != aChecked.end() && *aCheckIt) {
-      ++aCheckIt;
-      ++anIt2;
-    }
-    for (; anIt2 != theCVec2.end(); ++anIt2, ++aCheckIt)
-      if (!(*aCheckIt) && (*anIt1)->isEqual(*anIt2)) {
-        *aCheckIt = true;
-        break;
-      }
-    // the same constraint is not found
-    if (anIt2 == theCVec2.end())
-      return false;
+  if (!myNeedToResolve) {
+    // Verify the updated parameters are used in constraints
+    std::set<Slvs_hEntity> aPoints;
+    std::vector<Slvs_Entity>::const_iterator anEntIt = myEntities.begin();
+    for (; anEntIt != myEntities.end(); ++anEntIt) {
+      for (int i = 0; i < 4 && anEntIt->param[i] != SLVS_E_UNKNOWN; ++i)
+        if (myUpdatedParameters.find(anEntIt->param[i]) != myUpdatedParameters.end()) {
+          aPoints.insert(anEntIt->h);
+          break;
+        }
+    }
+    std::set<Slvs_hEntity> anEntities = aPoints;
+    for (anEntIt = myEntities.begin(); anEntIt != myEntities.end(); ++anEntIt) {
+      for (int i = 0; i < 4 && anEntIt->point[i] != SLVS_E_UNKNOWN; ++i)
+        if (aPoints.find(anEntIt->point[i]) != aPoints.end()) {
+          anEntities.insert(anEntIt->h);
+          break;
+        }
+    }
+
+    std::vector<Slvs_Constraint>::const_iterator aCIt = myConstraints.begin();
+    for (; aCIt != myConstraints.end() && !myNeedToResolve; ++aCIt) {
+      Slvs_hEntity anAttrs[6] =
+        {aCIt->ptA, aCIt->ptB, aCIt->entityA, aCIt->entityB, aCIt->entityC, aCIt->entityD};
+      for (int i = 0; i < 6; i++)
+        if (anAttrs[i] != SLVS_E_UNKNOWN && anEntities.find(anAttrs[i]) != anEntities.end()) {
+          myNeedToResolve = true;
+          break;
+        }
+    }
   }
-  return true;
+
+  myUpdatedParameters.clear();
+  return myNeedToResolve;
+}
+
+
+
+
+
+
+// ========================================================
+// =========      Auxiliary functions       ===============
+// ========================================================
+
+template<typename T>
+int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities)
+{
+  int aResIndex = theEntityID <= theEntities.size() ? theEntityID - 1 : 0;
+  int aVecSize = theEntities.size();
+  if (theEntities.empty())
+    return 1;
+  while (aResIndex >= 0 && theEntities[aResIndex].h > theEntityID)
+    aResIndex--;
+  while (aResIndex < aVecSize && aResIndex >= 0 && theEntities[aResIndex].h < theEntityID)
+    aResIndex++;
+  if (aResIndex == -1 || (aResIndex < aVecSize && theEntities[aResIndex].h != theEntityID))
+    aResIndex = aVecSize;
+  return aResIndex;
+}
+
+bool IsNotEqual(const Slvs_Param& theParam1, const Slvs_Param& theParam2)
+{
+  return fabs(theParam1.val - theParam2.val) > tolerance;
+}
+
+bool IsNotEqual(const Slvs_Entity& theEntity1, const Slvs_Entity& theEntity2)
+{
+  int i = 0;
+  for (; theEntity1.param[i] != 0 && i < 4; i++)
+    if (theEntity1.param[i] != theEntity2.param[i])
+      return true;
+  i = 0;
+  for (; theEntity1.point[i] != 0 && i < 4; i++)
+    if (theEntity1.point[i] != theEntity2.point[i])
+      return true;
+  return false;
+}
+
+bool IsNotEqual(const Slvs_Constraint& theConstraint1, const Slvs_Constraint& theConstraint2)
+{
+  return theConstraint1.ptA != theConstraint2.ptA ||
+         theConstraint1.ptB != theConstraint2.ptB ||
+         theConstraint1.entityA != theConstraint2.entityA ||
+         theConstraint1.entityB != theConstraint2.entityB ||
+         theConstraint1.entityC != theConstraint2.entityC ||
+         theConstraint1.entityD != theConstraint2.entityD ||
+         fabs(theConstraint1.valA - theConstraint2.valA) > tolerance;
 }
index a286f8a28027d84290acee987591d2052103287a..bb270d77d191a1083c0b9d53e6f03898a4b09ee9 100644 (file)
 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
 
 // File:    SketchSolver_Storage.h
-// Created: 30 Nov 2015
+// Created: 18 Mar 2015
 // Author:  Artem ZHIDKOV
 
 #ifndef SketchSolver_Storage_H_
 #define SketchSolver_Storage_H_
 
-#include <SketchSolver.h>
-#include <SketchSolver_IConstraintWrapper.h>
-#include <SketchSolver_IEntityWrapper.h>
-#include <SketchSolver_IParameterWrapper.h>
-#include <SketchSolver_ISolver.h>
+#include "SketchSolver.h"
+#include <SketchSolver_Solver.h>
 
-#include <ModelAPI_Attribute.h>
-#include <ModelAPI_AttributeDouble.h>
-#include <ModelAPI_Feature.h>
-#include <SketchPlugin_Constraint.h>
+#include <list>
+#include <memory>
+#include <set>
+#include <vector>
 
 /** \class   SketchSolver_Storage
  *  \ingroup Plugins
- *  \brief   Interface to map SketchPlugin features to the entities of corresponding solver.
+ *  \brief   Contains all necessary data in SolveSpace format to solve a single group of constraints
  */
 class SketchSolver_Storage
 {
-private:
+public:
   SketchSolver_Storage();
-  SketchSolver_Storage(const SketchSolver_Storage&);
-  SketchSolver_Storage& operator=(const SketchSolver_Storage&);
 
-public:
-  SketchSolver_Storage(const GroupID& theGroup)
-    : myGroupID(theGroup),
-      myNeedToResolve(false)
-  {}
-
-  /// \brief Change mapping between constraint from SketchPlugin and
-  ///        a constraint applicable for corresponding solver.
-  /// \param theConstraint       [in]   original SketchPlugin constraint
-  /// \param theSolverConstraint [in]   solver's constraints
-  SKETCHSOLVER_EXPORT void addConstraint(ConstraintPtr        theConstraint,
-                                         ConstraintWrapperPtr theSolverConstraints);
-  /// \brief Change mapping between constraint from SketchPlugin and
-  ///        the list of constraints applicable for corresponding solver.
-  /// \param theConstraint        [in]   original SketchPlugin constraint
-  /// \param theSolverConstraints [in]   list of solver's constraints
-  SKETCHSOLVER_EXPORT
-    void addConstraint(ConstraintPtr                   theConstraint,
-                       std::list<ConstraintWrapperPtr> theSolverConstraints);
-
-  /// \brief Convert feature to the form applicable for specific solver and map it
-  /// \param theFeature [in]  feature to convert
-  /// \param theGroup   [in]  id of the group where the feature should be placed
-  /// \return \c true if the feature has been created or updated
-  SKETCHSOLVER_EXPORT bool update(FeaturePtr theFeature, const GroupID& theGroup = GID_UNKNOWN);
-  /// \brief Convert attribute to the form applicable for specific solver and map it
-  /// \param theFeature [in]  feature to convert
-  /// \return \c true if the attribute has been created or updated
-  SKETCHSOLVER_EXPORT bool update(AttributePtr theAttribute, const GroupID& theGroup = GID_UNKNOWN);
-
-  /// \brief Returns constraint related to corresponding constraint
-  SKETCHSOLVER_EXPORT
-    const std::list<ConstraintWrapperPtr>& constraint(const ConstraintPtr& theConstraint) const;
-
-  /// \brief Returns entity related to corresponding feature
-  SKETCHSOLVER_EXPORT const EntityWrapperPtr& entity(const FeaturePtr& theFeature) const;
-  /// \brief Returns entity related to corresponding attribute
-  SKETCHSOLVER_EXPORT const EntityWrapperPtr& entity(const AttributePtr& theAttribute) const;
-
-////  /// \brief Returns parameter related to corresponding scalar attribute
-////  SKETCHSOLVER_EXPORT
-////    const ParameterWrapperPtr& parameter(const AttributeDoublePtr& theAttribute) const;
-
-  /// \brief Return parsed sketch entity
-  const EntityWrapperPtr& sketch() const;
-  /// \brief Set parsed sketch entity.
-  /// Be careful, this method does not update fields of the storage specific for the solver.
-  /// Does not update if the sketch already exists.
-  void setSketch(const EntityWrapperPtr& theSketch);
-
-  /// \brief Mark two points as coincident
-  virtual void addCoincidentPoints(EntityWrapperPtr theMaster, EntityWrapperPtr theSlave) = 0;
-
-  /// \brief Shows the storage has any constraint twice
-  virtual bool hasDuplicatedConstraint() const = 0;
-
-  /// \brief Removes constraint from the storage
-  /// \return \c true if the constraint and all its parameters are removed successfully
-  virtual bool removeConstraint(ConstraintPtr theConstraint) = 0;
-  /// \brief Removes feature from the storage
-  /// \return \c true if the feature and its attributes are removed successfully;
-  ///         \c false if the feature or any it attribute is used by remaining constraints.
-  virtual bool removeEntity(FeaturePtr theFeature) = 0;
-  /// \brief Removes attribute from the storage
-  /// \return \c true if the attribute is not used by remaining features and constraints
-  virtual bool removeEntity(AttributePtr theAttribute) = 0;
-
-  /// \brief Remove all features became invalid
-  SKETCHSOLVER_EXPORT void removeInvalidEntities();
-
-  /// \brief Mark specified constraint as temporary
-  virtual void setTemporary(ConstraintPtr theConstraint) = 0;
-  /// \brief Returns number of temporary constraints
-  virtual size_t nbTemporary() const = 0;
-  /// \brief Remove temporary constraints
-  /// \param theNbConstraints [in]  number of temporary constraints to be deleted
-  /// \return number of remaining temporary constraints
-  virtual size_t removeTemporary(size_t theNbConstraints = 1) = 0;
-
-  /// \brief Check whether the feature or its attributes are used by this storage
-  /// \param theFeature [in]  feature to be checked
-  /// \return \c true if the feature interacts with the storage
-  bool isInteract(const FeaturePtr& theFeature) const;
-  /// \brief Check whether the attribute is used by this storage
-  /// \param theAttribute [in]  attribute to be checked
-  /// \return \c true if the attribute interacts with the storage
-  bool isInteract(const AttributePtr& theAttribute) const;
-
-  /// \brief Check the features is not removed
-  bool isConsistent() const;
+  /** \brief Add new parameter to the current group
+   *  \param[in] theParam  SolveSpace parameter
+   *  \return the ID of added parameter
+   */
+  Slvs_hParam addParameter(const Slvs_Param& theParam);
+  /** \brief Updates parameter in the current group. If the ID of parameter is zero, the new item will be added
+   *  \param[in] theParam  SolveSpace parameter
+   *  \return the ID of updated/added parameter
+   */
+  Slvs_hParam updateParameter(const Slvs_Param& theParam);
+  /** \brief Removes the parameter by its ID
+   *  \param[in] theParamID  index of parameter to be removed
+   *  \return \c true if the parameter was successfully removed
+   */
+  bool removeParameter(const Slvs_hParam& theParamID);
+  /// \brief Returns the parameter by its ID
+  const Slvs_Param& getParameter(const Slvs_hParam& theParamID) const;
+
+  /** \brief Add new entity to the current group
+   *  \param[in] theEntity  SolveSpace entity
+   *  \return the ID of added entity
+   */
+  Slvs_hEntity addEntity(const Slvs_Entity& theEntity);
+  /** \brief Updates entity in the current group. If the ID of entity is zero, the new item will be added
+   *  \param[in] theEntity  SolveSpace entity
+   *  \return the ID of updated/added entity
+   */
+  Slvs_hEntity updateEntity(const Slvs_Entity& theEntity);
+  /** \brief Removes the entity by its ID. All parameters used in this entity,
+   *         and not used in other constraints, will be removed too.
+   *  \param[in] theEntityID  index of entity to be removed
+   *  \return \c true if the entity was successfully removed
+   */
+  bool removeEntity(const Slvs_hEntity& theEntityID);
+  /** \brief Remove all entities, which are not used in constraints
+   */
+  void removeUnusedEntities();
+  /// \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 Check the entity is used in constraints
+  bool isUsedByConstraints(const Slvs_hEntity& theEntityID) const;
+  /// \brief Returns maximal ID of entities in this storage
+  const Slvs_hEntity& entityMaxID() const
+  { return myEntityMaxID; }
+
+  /// \brief Verifies the current point or another coincident one is fixed
+  /// \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
+   *  \return the ID of added constraint
+   */
+  Slvs_hConstraint addConstraint(const Slvs_Constraint& theConstraint);
+  /** \brief Updates constraint in the current group.
+   *         If the ID of constraint is zero, the new item will be added
+   *  \param[in] theConstraint  SolveSpace constraint
+   *  \return the ID of updated/added constraint
+   */
+  Slvs_hConstraint updateConstraint(const Slvs_Constraint& theConstraint);
+  /** \brief Removes the constraint by its ID. All entities and parameters depending on this
+   *         constraint, which are not used in other constraints, will be removed too.
+   *  \param[in] theConstraintID  index of constraint to be removed
+   *  \return \c true if the constraint was successfully removed
+   */
+  bool removeConstraint(const Slvs_hConstraint& theConstraintID);
+  /// \brief Returns the constraint by its ID
+  const Slvs_Constraint& getConstraint(const Slvs_hConstraint& theConstraintID) const;
+  /// \brief Returns list of constraints of specified type
+  std::list<Slvs_Constraint> getConstraintsByType(int theConstraintType) const;
+  /// \brief Returns quantity of constraints in this storage
+  size_t nbConstraints() const
+  { return myConstraints.size(); }
+
+  /// \brief Attach constraint SLVS_C_WHERE_DRAGGED to this storage. It need to make precise calculations
+  void addConstraintWhereDragged(const Slvs_hConstraint& theConstraintID);
+
+  /// \brief Add transient constraint
+  void addTemporaryConstraint(const Slvs_hConstraint& theConstraintID);
+  /// \brief Remove all transient constraints
+  void removeTemporaryConstraints();
+  /// \brief Remove one temporary constraint. Preferable to remove the points under Point-on-Line constraint
+  /// \return Number of remaining temporary constraints
+  int deleteTemporaryConstraint();
+  /// \brief Checks the constraint is temporary
+  bool isTemporary(const Slvs_hConstraint& theConstraintID) const;
+  /// \brief Number of temporary constraints
+  int numberTemporary() const
+  { return (int)myTemporaryConstraints.size(); }
 
   /// \brief Shows the sketch should be resolved
-  virtual bool isNeedToResolve()
-  { return myNeedToResolve; }
+  bool isNeedToResolve();
+
+  /// \brief Shows the storage has the same constraint twice
+  bool hasDuplicatedConstraint() const
+  { return myDuplicatedConstraint; }
+
   /// \brief Changes the flag of group to be resolved
   void setNeedToResolve(bool theFlag)
   { myNeedToResolve = theFlag; }
 
-  /// \brief Initialize solver by constraints, entities and parameters
-  virtual void initializeSolver(SolverPtr theSolver) = 0;
-
-  /// \brief Update SketchPlugin features after resolving constraints
-  /// \param theFixedOnly [in]  if \c true the fixed points will be updated only
-  virtual void refresh(bool theFixedOnly = false) const = 0;
-
-  /// \brief Check if some parameters or entities are returned
-  ///        to the current group after removing temporary constraints
-  virtual void verifyFixed() = 0;
-
-  /// \brief Calculate point on theBase entity. Value theCoeff is in [0.0 .. 1.0] and
-  ///        shows the distance from the start point.
-  virtual EntityWrapperPtr calculateMiddlePoint(EntityWrapperPtr theBase,
-                                                double theCoeff) = 0;
-
-protected:
-  /// \brief Change mapping feature from SketchPlugin and
-  ///        the entity applicable for corresponding solver.
-  /// \param theFeature      [in]  original SketchPlugin feature
-  /// \param theSolverEntity [in]  solver's entity, created outside
-  SKETCHSOLVER_EXPORT
-    void addEntity(FeaturePtr       theFeature,
-                   EntityWrapperPtr theSolverEntity);
-
-  /// \brief Change mapping attribute of a feature and the entity applicable for corresponding solver.
-  /// \param theAttribute    [in]  original attribute
-  /// \param theSolverEntity [in]  solver's entity, created outside
-  SKETCHSOLVER_EXPORT
-    void addEntity(AttributePtr     theAttribute,
-                   EntityWrapperPtr theSolverEntity);
-
-////  /// \brief Change mapping scalar attribute and the parameter applicable for corresponding solver.
-////  /// \param theValue       [in]  original attribute
-////  /// \param theSolverParam [in]  solver's parameter, created outside
-////  SKETCHSOLVER_EXPORT
-////    void addParameter(AttributeDoublePtr  theValue,
-////                      ParameterWrapperPtr theSolverParam);
-
-  /// \brief Update constraint's data
-  /// \return \c true if any value is updated
-  virtual bool update(ConstraintWrapperPtr& theConstraint) = 0;
-  /// \brief Update entity's data
-  /// \return \c true if any value is updated
-  virtual bool update(EntityWrapperPtr& theEntity) = 0;
-  /// \brief Update parameter's data
-  /// \return \c true if the value of parameter is updated
-  virtual bool update(ParameterWrapperPtr& theParameter) = 0;
-
-  /// \brief Remove constraint
-  /// \return \c true if the constraint and all its parameters are removed successfully
-  virtual bool remove(ConstraintWrapperPtr theConstraint) = 0;
-  /// \brief Remove entity
-  /// \return \c true if the entity and all its parameters are removed successfully
-  virtual bool remove(EntityWrapperPtr theEntity) = 0;
-  /// \brief Remove parameter
-  /// \return \c true if the parameter has been removed
-  virtual bool remove(ParameterWrapperPtr theParameter) = 0;
-
-  /// \brief Update the group for the given entity, its sub-entities and parameters
-  virtual void changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup) = 0;
-  /// \brief Update the group for the given parameter
-  virtual void changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup) = 0;
-
-  /// \brief Block or unblock events when refreshing features
-  SKETCHSOLVER_EXPORT void blockEvents(bool isBlocked) const;
+  /// \brief Returns lists of removed elements
+  void getRemoved(std::set<Slvs_hParam>& theParameters,
+                  std::set<Slvs_hEntity>& theEntities,
+                  std::set<Slvs_hConstraint>& theConstraints);
+
+  /// \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);
+  /// \brief Remove point-point coincidence
+  void removeCoincidence(const Slvs_Constraint& theCoincidence);
+
+public:
+  /// \brief Check two points are coincident
+  bool isCoincident(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const;
+
+  /// \brief Check two points are coincident or have same coordinates
+  bool isEqual(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const;
+
+  /// \brief Check the entity is horizontal of vertical
+  bool isAxisParallel(const Slvs_hEntity& theEntity) const;
+
+  /// \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_hEntity& theEntity, Slvs_Constraint& theEqual) const;
+
+  /// \brief Fixes specified entity
+  /// \param theEntity  ID of the entity to be fixed
+  /// \return List of created constraints
+  std::vector<Slvs_hConstraint> fixEntity(const Slvs_hEntity& theEntity);
 
 private:
-  /// \brief Find the normal of the sketch
-  EntityWrapperPtr getNormal() const;
+  /// \brief Fixes specified point
+  /// \param [in]  thePoint    point to be fixed
+  /// \param [out] theCreated  list of the Fixed constraints created
+  void fixPoint(const Slvs_Entity& thePoint, std::vector<Slvs_hConstraint>& theCreated);
+  /// \brief Fixes specified line
+  /// \param [in]  theLine     line to be fixed
+  /// \param [out] theCreated  list of the Fixed constraints created
+  void fixLine(const Slvs_Entity& theLine, std::vector<Slvs_hConstraint>& theCreated);
+  /// \brief Fixes specified circle
+  /// \param [in]  theCircle   circle to be fixed
+  /// \param [out] theCreated  list of the Fixed constraints created
+  void fixCircle(const Slvs_Entity& theCircle, std::vector<Slvs_hConstraint>& theCreated);
+  /// \brief Fixes specified arc
+  /// \param [in]  theArc      arc to be fixed
+  /// \param [out] theCreated  list of the Fixed constraints created
+  void fixArc(const Slvs_Entity& theArc, std::vector<Slvs_hConstraint>& theCreated);
 
-protected:
-  GroupID myGroupID; ///< identifier of the group, this storage belongs to
+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 (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 (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 (sorted by the identifier)
 
-  /// map SketchPlugin constraint to a list of solver's constraints
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> > myConstraintMap;
-  /// map SketchPlugin feature to solver's entity
-  std::map<FeaturePtr, EntityWrapperPtr>                    myFeatureMap;
-  /// map attribute to solver's entity
-  std::map<AttributePtr, EntityWrapperPtr>                  myAttributeMap;
-////  /// map scalar attribute to solver's parameter
-////  std::map<AttributeDoublePtr, ParameterWrapperPtr>         myParametersMap;
+  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
+  bool myDuplicatedConstraint; ///< shows the storage has same constraint twice
+
+  std::set<Slvs_hConstraint> myTemporaryConstraints; ///< list of transient constraints
+  std::set<Slvs_hParam> myRemovedParameters; ///< list of just removed parameters (cleared when returning to applicant)
+  std::set<Slvs_hEntity> myRemovedEntities; ///< list of just removed entities (cleared when returning to applicant)
+  std::set<Slvs_hConstraint> myRemovedConstraints; ///< list of just removed constraints (cleared when returning to applicant)
+  std::set<Slvs_hParam> myUpdatedParameters; ///< list of just updated parameters (cleared when isNeedToResolve() called)
 };
 
 typedef std::shared_ptr<SketchSolver_Storage> StoragePtr;
diff --git a/src/SketchSolver/SolveSpaceSolver/CMakeLists.txt b/src/SketchSolver/SolveSpaceSolver/CMakeLists.txt
deleted file mode 100644 (file)
index cda6e3b..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-## Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-FIND_PACKAGE(SolveSpace REQUIRED)
-
-SET(PROJECT_HEADERS
-    SolveSpaceSolver_Solver.h
-    SolveSpaceSolver_Builder.h
-    SolveSpaceSolver_Storage.h
-    SolveSpaceSolver_EntityWrapper.h
-    SolveSpaceSolver_ParameterWrapper.h
-    SolveSpaceSolver_ConstraintWrapper.h
-    SolveSpaceSolver_ConstraintType.h
-)
-
-SET(PROJECT_SOURCES
-    SolveSpaceSolver_Solver.cpp
-    SolveSpaceSolver_Builder.cpp
-    SolveSpaceSolver_Storage.cpp
-    SolveSpaceSolver_EntityWrapper.cpp
-    SolveSpaceSolver_ParameterWrapper.cpp
-    SolveSpaceSolver_ConstraintWrapper.cpp
-)
-
-SET(PROJECT_LIBRARIES
-    ${SOLVESPACE_LIBRARIES}
-    SketchSolver
-    ModelAPI
-    GeomAPI
-)
-
-INCLUDE_DIRECTORIES(
-    ${SOLVESPACE_INCLUDE_DIRS}
-    ${PROJECT_SOURCE_DIR}/src/SketchSolver
-    ${PROJECT_SOURCE_DIR}/src/SketchPlugin
-    ${PROJECT_SOURCE_DIR}/src/ModelAPI
-    ${PROJECT_SOURCE_DIR}/src/GeomAPI
-    ${PROJECT_SOURCE_DIR}/src/GeomDataAPI
-)
-
-ADD_LIBRARY(SolveSpaceSolver MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS})
-TARGET_LINK_LIBRARIES(SolveSpaceSolver ${PROJECT_LIBRARIES})
-INSTALL(TARGETS SolveSpaceSolver DESTINATION plugins)
diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Builder.cpp b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Builder.cpp
deleted file mode 100644 (file)
index b74a8db..0000000
+++ /dev/null
@@ -1,879 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SolveSpaceSolver_Builder.cpp
-// Created: 25 Mar 2015
-// Author:  Artem ZHIDKOV
-
-#include <SolveSpaceSolver_Builder.h>
-#include <SolveSpaceSolver_Solver.h>
-#include <SolveSpaceSolver_Storage.h>
-#include <SolveSpaceSolver_ParameterWrapper.h>
-#include <SolveSpaceSolver_EntityWrapper.h>
-#include <SolveSpaceSolver_ConstraintWrapper.h>
-#include <SolveSpaceSolver_ConstraintType.h>
-
-#include <SketchSolver_Manager.h>
-
-#include <GeomAPI_Dir2d.h>
-#include <GeomAPI_Pnt2d.h>
-#include <GeomAPI_XY.h>
-#include <GeomDataAPI_Dir.h>
-#include <GeomDataAPI_Point.h>
-#include <GeomDataAPI_Point2D.h>
-#include <ModelAPI_Attribute.h>
-#include <ModelAPI_AttributeRefAttr.h>
-
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
-#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Point.h>
-
-#include <math.h>
-
-
-static EntityWrapperPtr createLine(FeaturePtr theFeature,
-                                   const std::list<EntityWrapperPtr>& theAttributes,
-                                   const GroupID& theGroupID,
-                                   const EntityID& theSketchID);
-static EntityWrapperPtr createCircle(FeaturePtr theFeature,
-                                     const std::list<EntityWrapperPtr>& theAttributes,
-                                     const GroupID& theGroupID,
-                                     const EntityID& theSketchID);
-static EntityWrapperPtr createArc(FeaturePtr theFeature,
-                                  const std::list<EntityWrapperPtr>& theAttributes,
-                                  const GroupID& theGroupID,
-                                  const EntityID& theSketchID);
-
-/// \brief Set flags of constraint to identify which points are coincident in the Tangency
-///        (for more information, see SolveSpace documentation)
-static void adjustTangency(ConstraintWrapperPtr theConstraint);
-/// \brief Set flags for angle constraint
-static void adjustAngle(ConstraintWrapperPtr theConstraint);
-/// \brief Update mirror points
-static void adjustMirror(ConstraintWrapperPtr theConstraint);
-/// \brief Update positions of rotated features
-static void adjustMultiRotation(ConstraintWrapperPtr theConstraint);
-/// \brief Update positions of translated features
-static void adjustMultiTranslation(ConstraintWrapperPtr theConstraint);
-
-/// \brief Transform points to be symmetric regarding to the mirror line
-static void makeMirrorPoints(EntityWrapperPtr theOriginal,
-                             EntityWrapperPtr theMirrored,
-                             EntityWrapperPtr theMirrorLine);
-
-
-
-// Initialization of constraint builder self pointer
-BuilderPtr SolveSpaceSolver_Builder::mySelf = SolveSpaceSolver_Builder::getInstance();
-
-BuilderPtr SolveSpaceSolver_Builder::getInstance()
-{
-  if (!mySelf) {
-    mySelf = BuilderPtr(new SolveSpaceSolver_Builder);
-    SketchSolver_Manager::instance()->setBuilder(mySelf);
-  }
-  return mySelf;
-}
-
-StoragePtr SolveSpaceSolver_Builder::createStorage(const GroupID& theGroup) const
-{
-  return StoragePtr(new SolveSpaceSolver_Storage(theGroup));
-}
-
-SolverPtr SolveSpaceSolver_Builder::createSolver() const
-{
-  return SolverPtr(new SolveSpaceSolver_Solver);
-}
-
-
-std::list<ConstraintWrapperPtr> SolveSpaceSolver_Builder::createConstraint(
-    ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
-    const EntityID& theSketchID,
-    const SketchSolver_ConstraintType& theType,
-    const double& theValue,
-    const EntityWrapperPtr& thePoint1,
-    const EntityWrapperPtr& thePoint2,
-    const EntityWrapperPtr& theEntity1,
-    const EntityWrapperPtr& theEntity2) const
-{
-  if (theType == CONSTRAINT_SYMMETRIC)
-    return createMirror(theConstraint, theGroupID, theSketchID,
-                        thePoint1, thePoint2, theEntity1);
-
-  int aType = ConstraintType::toSolveSpace(theType);
-  if (aType == SLVS_C_UNKNOWN)
-    return std::list<ConstraintWrapperPtr>();
-
-  Slvs_hEntity aSlvsEntities[4] = {SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN};
-  EntityWrapperPtr anOriginal[4] = {thePoint1, thePoint2, theEntity1, theEntity2};
-  std::list<EntityWrapperPtr> aConstrAttrList; // to be filled
-  for (int i = 0; i < 4; ++i) {
-    if (!anOriginal[i])
-      continue;
-    aSlvsEntities[i] = (Slvs_hEntity)anOriginal[i]->id();
-    if (aSlvsEntities[i] == SLVS_E_UNKNOWN)
-      return std::list<ConstraintWrapperPtr>(); // entity is not added into a storage, constraint can not be created
-    aConstrAttrList.push_back(anOriginal[i]);
-  }
-
-  Slvs_Constraint aConstraint = Slvs_MakeConstraint(
-      SLVS_C_UNKNOWN, (Slvs_hGroup)theGroupID, aType, (Slvs_hEntity)theSketchID,
-      theValue, aSlvsEntities[0], aSlvsEntities[1], aSlvsEntities[2], aSlvsEntities[3]);
-  ConstraintWrapperPtr aResult(new SolveSpaceSolver_ConstraintWrapper(theConstraint, aConstraint));
-  aResult->setValue(theValue);
-  aResult->setEntities(aConstrAttrList);
-  adjustConstraint(aResult);
-
-  return std::list<ConstraintWrapperPtr>(1, aResult);
-}
-
-std::list<ConstraintWrapperPtr> SolveSpaceSolver_Builder::createConstraint(
-    ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
-    const EntityID& theSketchID,
-    const SketchSolver_ConstraintType& theType,
-    const double& theValue,
-    const EntityWrapperPtr& thePoint1,
-    const EntityWrapperPtr& thePoint2,
-    const std::list<EntityWrapperPtr>& theTrsfEnt) const
-{
-  if (theType != CONSTRAINT_MULTI_ROTATION && theType != CONSTRAINT_MULTI_TRANSLATION)
-    return std::list<ConstraintWrapperPtr>();
-
-  int aType = ConstraintType::toSolveSpace(theType);
-  if (aType == SLVS_C_UNKNOWN)
-    return std::list<ConstraintWrapperPtr>();
-
-  Slvs_Constraint aConstraint =
-      Slvs_MakeConstraint(SLVS_C_UNKNOWN, (Slvs_hGroup)theGroupID, aType, (Slvs_hEntity)theSketchID,
-      theValue, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-
-  std::list<EntityWrapperPtr> aConstrAttrList = theTrsfEnt;
-  if (thePoint2)
-    aConstrAttrList.push_front(thePoint2);
-  aConstrAttrList.push_front(thePoint1);
-
-  ConstraintWrapperPtr aResult(new SolveSpaceSolver_ConstraintWrapper(theConstraint, aConstraint));
-  aResult->setValue(theValue);
-  aResult->setEntities(aConstrAttrList);
-  return std::list<ConstraintWrapperPtr>(1, aResult);
-}
-
-
-std::list<ConstraintWrapperPtr> SolveSpaceSolver_Builder::createMirror(
-    ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
-    const EntityID& theSketchID,
-    const EntityWrapperPtr& theEntity1,
-    const EntityWrapperPtr& theEntity2,
-    const EntityWrapperPtr& theMirrorLine) const
-{
-////  std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity1 =
-////      std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theEntity1);
-////  std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity2 =
-////      std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theEntity2);
-////
-////  // Make aMirrorEnt parameters to be symmetric with aBaseEnt
-////  makeMirrorEntity(theEntity1, theEntity2, theMirrorLine);
-
-  Slvs_Constraint aConstraint;
-  std::list<ConstraintWrapperPtr> aResult;
-  std::list<EntityWrapperPtr> aConstrAttrList;
-  if (theEntity1->type() == ENTITY_POINT) {
-    if (theEntity2->group() == theGroupID) // theEntity2 is not fixed
-      makeMirrorPoints(theEntity1, theEntity2, theMirrorLine);
-
-    aConstraint = Slvs_MakeConstraint(
-        SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID, SLVS_C_SYMMETRIC_LINE, (Slvs_hEntity)theSketchID,
-        0.0, (Slvs_hEntity)theEntity1->id(), (Slvs_hEntity)theEntity2->id(),
-        (Slvs_hEntity)theMirrorLine->id(), SLVS_E_UNKNOWN);
-
-    aConstrAttrList.push_back(theEntity1);
-    aConstrAttrList.push_back(theEntity2);
-    aConstrAttrList.push_back(theMirrorLine);
-
-    ConstraintWrapperPtr aWrapper(new SolveSpaceSolver_ConstraintWrapper(
-        theConstraint, aConstraint));
-    aWrapper->setEntities(aConstrAttrList);
-    aResult.push_back(aWrapper);
-  }
-  else if (theEntity1->type() == ENTITY_LINE) {
-    const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
-    const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
-    std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
-    std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
-    for (; anIt1 != aPoints1.end() && anIt2 != aPoints2.end(); ++anIt1, ++anIt2) {
-      std::list<ConstraintWrapperPtr> aMrrList =
-          createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
-      aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
-    }
-  }
-  else if (theEntity1->type() == ENTITY_CIRCLE) {
-    const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
-    std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
-    for (; anIt1 != aPoints1.end(); ++anIt1)
-      if ((*anIt1)->type() == ENTITY_POINT)
-        break;
-    const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
-    std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
-    for (; anIt2 != aPoints2.end(); ++anIt2)
-      if ((*anIt2)->type() == ENTITY_POINT)
-        break;
-
-    std::list<ConstraintWrapperPtr> aMrrList =
-        createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
-    aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
-
-    // Additional constraint for equal radii
-    aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
-        0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
-    aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
-  }
-  else if (theEntity1->type() == ENTITY_ARC) {
-    // Do not allow mirrored arc recalculate its position until coordinated of all points recalculated
-    FeaturePtr aMirrArc = theEntity2->baseFeature();
-    aMirrArc->data()->blockSendAttributeUpdated(true);
-
-    std::list<ConstraintWrapperPtr> aMrrList;
-    std::list<EntityWrapperPtr>::const_iterator anIt1 = theEntity1->subEntities().begin();
-    std::list<EntityWrapperPtr>::const_iterator anIt2 = theEntity2->subEntities().begin();
-    if ((*anIt2)->group() == theGroupID) // mirrored point is not fixed
-      makeMirrorPoints(theEntity1->subEntities().front(),
-          theEntity2->subEntities().front(), theMirrorLine);
-
-    // Workaround to avoid problems in SolveSpace.
-    // The symmetry of two arcs will be done using symmetry of three points on these arcs:
-    // start point, end point, and any other point on the arc
-    std::list<EntityWrapperPtr> aBaseArcPoints(++anIt1, theEntity1->subEntities().end());
-    std::list<EntityWrapperPtr> aMirrorArcPoints(++anIt2, theEntity2->subEntities().end());
-    // indices of points of arc, center corresponds center, first point corresponds last point
-    aMirrorArcPoints.reverse();
-
-////    EntityWrapperPtr aBothArcs[2] = {theEntity1, theEntity2};
-////    EntityWrapperPtr aBothMiddlePoints[2];
-////    for (int i = 0; i < 2; i++) {
-////      aBothMiddlePoints[i] = calculateMiddlePoint(aBothArcs[i], 0.5, theGroupID, theSketchID);
-////      // additional constraint point-on-curve
-////      aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_PT_ON_CIRCLE,
-////          0.0, aBothMiddlePoints[i], EntityWrapperPtr(), aBothArcs[i]);
-////      aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
-////////      if (i == 0) {
-////////        // additional constraint for the point to be in the middle of a base arc
-////////        Slvs_Entity aLine1 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
-////////            myGroup->getWorkplaneId(), aBothArcs[i].point[1], aBothMiddlePoints[i]);
-////////        aLine1.h = myStorage->addEntity(aLine1);
-////////        Slvs_Entity aLine2 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
-////////            myGroup->getWorkplaneId(), aBothArcs[i].point[2], aBothMiddlePoints[i]);
-////////        aLine2.h = myStorage->addEntity(aLine2);
-////////        Slvs_Constraint aMiddleConstr = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
-////////            SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(),
-////////            0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aLine1.h, aLine2.h);
-////////        aMiddleConstr.h = myStorage->addConstraint(aMiddleConstr);
-////////        mySlvsConstraints.push_back(aMiddleConstr.h);
-////////      }
-////    }
-////
-////    aBaseArcPoints.push_back(aBothMiddlePoints[0]);
-////    aMirrorArcPoints.push_back(aBothMiddlePoints[1]);
-    anIt1 = aBaseArcPoints.begin();
-    anIt2 = aMirrorArcPoints.begin();
-    for (; anIt1 != aBaseArcPoints.end(); ++anIt1, ++anIt2) {
-      aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
-      aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
-    }
-    // Restore event sending
-    aMirrArc->data()->blockSendAttributeUpdated(false);
-  }
-  return aResult;
-}
-
-void SolveSpaceSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstraint) const
-{
-  SketchSolver_ConstraintType aType = theConstraint->type();
-  // Update flags in constraints
-  if (aType == CONSTRAINT_TANGENT_ARC_ARC || aType == CONSTRAINT_TANGENT_ARC_LINE)
-    adjustTangency(theConstraint);
-  else if (aType == CONSTRAINT_ANGLE)
-    adjustAngle(theConstraint);
-  else if (aType == CONSTRAINT_SYMMETRIC)
-    adjustMirror(theConstraint);
-  else if (aType == CONSTRAINT_MULTI_ROTATION)
-    adjustMultiRotation(theConstraint);
-  else if (aType == CONSTRAINT_MULTI_TRANSLATION)
-    adjustMultiTranslation(theConstraint);
-}
-
-EntityWrapperPtr SolveSpaceSolver_Builder::createFeature(
-    FeaturePtr theFeature,
-    const std::list<EntityWrapperPtr>& theAttributes,
-    const GroupID& theGroupID,
-    const EntityID& theSketchID) const
-{
-  static EntityWrapperPtr aDummy;
-  if (!theFeature->data()->isValid())
-    return aDummy;
-
-  // Sketch
-  CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
-  if (aSketch)
-    return createSketchEntity(aSketch, theGroupID);
-
-  // SketchPlugin features
-  std::shared_ptr<SketchPlugin_Feature> aFeature =
-      std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
-  if (!aFeature)
-    return aDummy;
-
-  // Verify the feature by its kind
-  const std::string& aFeatureKind = aFeature->getKind();
-  // Line
-  if (aFeatureKind == SketchPlugin_Line::ID())
-    return createLine(theFeature, theAttributes, theGroupID, theSketchID);
-  // Circle
-  else if (aFeatureKind == SketchPlugin_Circle::ID())
-    return createCircle(theFeature, theAttributes,theGroupID, theSketchID);
-  // Arc
-  else if (aFeatureKind == SketchPlugin_Arc::ID())
-    return createArc(theFeature, theAttributes,theGroupID, theSketchID);
-  // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
-  else if (aFeatureKind == SketchPlugin_Point::ID()) {
-    AttributePtr aPoint = theFeature->attribute(SketchPlugin_Point::COORD_ID());
-    if (!aPoint->isInitialized())
-      return aDummy;
-    EntityWrapperPtr aSub = createAttribute(aPoint, theGroupID, theSketchID);
-    if (!aSub)
-      return aDummy;
-
-    const Slvs_Entity& aSubEnt =
-        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(aSub)->entity();
-    EntityWrapperPtr aNewEntity(new SolveSpaceSolver_EntityWrapper(theFeature, aSubEnt));
-    aNewEntity->setSubEntities(std::list<EntityWrapperPtr>(1, aSub));
-    return aNewEntity;
-  }
-
-  // wrong entity
-  return aDummy;
-}
-
-EntityWrapperPtr SolveSpaceSolver_Builder::createAttribute(
-    AttributePtr theAttribute,
-    const GroupID& theGroupID,
-    const EntityID& theSketchID) const
-{
-  AttributePtr anAttribute = theAttribute;
-  AttributeRefAttrPtr aRefAttr =
-      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
-  if (aRefAttr) {
-    if (aRefAttr->isObject()) {
-      // do not create features here
-      return EntityWrapperPtr();
-    } else
-      anAttribute = aRefAttr->attr();
-  }
-
-  std::list<ParameterWrapperPtr> aParameters;
-  Slvs_Entity anEntity;
-  anEntity.type = 0;
-
-  // Point in 3D
-  std::shared_ptr<GeomDataAPI_Point> aPoint =
-      std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
-  if (aPoint) {
-    aParameters.push_back(createParameter(theGroupID, aPoint->x(), !aPoint->textX().empty()));
-    aParameters.push_back(createParameter(theGroupID, aPoint->y(), !aPoint->textY().empty()));
-    aParameters.push_back(createParameter(theGroupID, aPoint->z(), !aPoint->textZ().empty()));
-    // Create entity (parameters are not filled)
-    anEntity = Slvs_MakePoint3d(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
-        SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-  } else {
-    // Point in 2D
-    std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
-      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
-    if (aPoint2D) {
-      aParameters.push_back(createParameter(theGroupID, aPoint2D->x(), !aPoint2D->textX().empty()));
-      aParameters.push_back(createParameter(theGroupID, aPoint2D->y(), !aPoint2D->textY().empty()));
-      // Create entity (parameters are not filled)
-      anEntity = Slvs_MakePoint2d(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
-          (Slvs_hEntity)theSketchID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-    } else {
-      // Scalar value (used for the distance entities)
-      AttributeDoublePtr aScalar =
-          std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
-      if (aScalar) {
-        aParameters.push_back(createParameter(theGroupID, aScalar->value(), !aScalar->text().empty()));
-        // Create entity (parameter is not filled)
-        anEntity = Slvs_MakeDistance(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
-          (Slvs_hEntity)theSketchID, SLVS_E_UNKNOWN);
-      }
-    }
-  }
-
-  if (anEntity.type == 0) {
-    // unknown attribute type
-    return EntityWrapperPtr();
-  }
-
-  EntityWrapperPtr aResult(new SolveSpaceSolver_EntityWrapper(theAttribute, anEntity));
-  aResult->setParameters(aParameters);
-  return aResult;
-}
-
-
-
-EntityWrapperPtr SolveSpaceSolver_Builder::createSketchEntity(
-    CompositeFeaturePtr theSketch,
-    const GroupID& theGroupID) const
-{
-  DataPtr aSketchData = theSketch->data();
-  if (!aSketchData || !aSketchData->isValid())
-    return EntityWrapperPtr(); // the sketch is incorrect
-
-  // Get parameters of workplane
-  AttributePtr aDirX    = aSketchData->attribute(SketchPlugin_Sketch::DIRX_ID());
-  AttributePtr aNorm    = aSketchData->attribute(SketchPlugin_Sketch::NORM_ID());
-  AttributePtr anOrigin = aSketchData->attribute(SketchPlugin_Sketch::ORIGIN_ID());
-  if (!anOrigin->isInitialized() || !aNorm->isInitialized() || !aDirX->isInitialized())
-    return EntityWrapperPtr();
-
-  EntityWrapperPtr aNewEnt;
-  std::list<EntityWrapperPtr> aSubs;
-
-  // Create SolveSpace entity corresponding to the sketch origin
-  aNewEnt = createAttribute(anOrigin, theGroupID);
-  if (!aNewEnt)
-    return EntityWrapperPtr();
-  aSubs.push_back(aNewEnt);
-
-  // Create SolveSpace entity corresponding the the sketch normal
-  aNewEnt = createNormal(aNorm, aDirX, theGroupID);
-  if (!aNewEnt)
-    return EntityWrapperPtr();
-  aSubs.push_back(aNewEnt);
-
-  // Create workplane
-  Slvs_Entity aWorkplane = Slvs_MakeWorkplane(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
-      SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-
-  aNewEnt = EntityWrapperPtr(
-      new SolveSpaceSolver_EntityWrapper(FeaturePtr(theSketch), aWorkplane));
-  aNewEnt->setSubEntities(aSubs);
-  return aNewEnt;
-}
-
-EntityWrapperPtr SolveSpaceSolver_Builder::createNormal(
-    AttributePtr theNormal,
-    AttributePtr theDirX,
-    const GroupID& theGroupID) const
-{
-  std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(theNormal);
-  std::shared_ptr<GeomDataAPI_Dir> aDirX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(theDirX);
-  if (!aDirX || !aNorm ||
-      (fabs(aDirX->x()) + fabs(aDirX->y()) + fabs(aDirX->z()) < tolerance) || 
-      !aNorm->isInitialized())
-    return EntityWrapperPtr();
-  // calculate Y direction
-  std::shared_ptr<GeomAPI_Dir> aDirY(new GeomAPI_Dir(aNorm->dir()->cross(aDirX->dir())));
-
-  // quaternion parameters of normal vector
-  double qw, qx, qy, qz;
-  Slvs_MakeQuaternion(aDirX->x(), aDirX->y(), aDirX->z(), aDirY->x(), aDirY->y(), aDirY->z(), &qw,
-                      &qx, &qy, &qz);
-  double aNormCoord[4] = { qw, qx, qy, qz };
-
-  // Create parameters of the normal
-  std::list<ParameterWrapperPtr> aParameters;
-  for (int i = 0; i < 4; i++)
-    aParameters.push_back(createParameter(theGroupID, aNormCoord[i]));
-
-  // Create a normal with empty parameters
-  Slvs_Entity aNormalEnt = Slvs_MakeNormal3d(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
-      SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-  EntityWrapperPtr aNormal(new SolveSpaceSolver_EntityWrapper(theNormal, aNormalEnt));
-  aNormal->setParameters(aParameters);
-  return aNormal;
-}
-
-ParameterWrapperPtr SolveSpaceSolver_Builder::createParameter(
-    const GroupID& theGroup, const double theValue, const bool theExpr) const
-{
-  Slvs_Param aParam = Slvs_MakeParam(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroup, theValue);
-  ParameterWrapperPtr aWrapper(new SolveSpaceSolver_ParameterWrapper(aParam));
-  aWrapper->setIsParametric(theExpr);
-  return aWrapper;
-}
-
-
-
-
-
-// ================   Auxiliary functions   ==========================
-EntityWrapperPtr createLine(FeaturePtr theFeature,
-                            const std::list<EntityWrapperPtr>& theAttributes,
-                            const GroupID& theGroupID,
-                            const EntityID& theSketchID)
-{
-  EntityWrapperPtr aNewEntity;
-  std::list<EntityWrapperPtr> aSubs;
-
-  AttributePtr aStart = theFeature->attribute(SketchPlugin_Line::START_ID());
-  AttributePtr aEnd = theFeature->attribute(SketchPlugin_Line::END_ID());
-  if (!aStart->isInitialized() || !aEnd->isInitialized())
-    return aNewEntity;
-
-  EntityWrapperPtr aStartEnt, aEndEnt;
-  std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
-  for (; anIt != theAttributes.end(); ++anIt) {
-    std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSlvsEntity = 
-        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anIt);
-    if (aSlvsEntity->isBase(aStart))
-      aStartEnt = aSlvsEntity;
-    else if (aSlvsEntity->isBase(aEnd))
-      aEndEnt = aSlvsEntity;
-  }
-  if (!aStartEnt || !aEndEnt)
-    return aNewEntity;
-
-  aSubs.push_back(aStartEnt);
-  aSubs.push_back(aEndEnt);
-  Slvs_Entity anEntity = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
-      (Slvs_hEntity)theSketchID, (Slvs_hEntity)aStartEnt->id(), (Slvs_hEntity)aEndEnt->id());
-
-  aNewEntity = EntityWrapperPtr(new SolveSpaceSolver_EntityWrapper(theFeature, anEntity));
-  aNewEntity->setSubEntities(aSubs);
-  return aNewEntity;
-}
-
-EntityWrapperPtr createCircle(FeaturePtr theFeature,
-                              const std::list<EntityWrapperPtr>& theAttributes,
-                              const GroupID& theGroupID,
-                              const EntityID& theSketchID)
-{
-  EntityWrapperPtr aNewEntity;
-  std::list<EntityWrapperPtr> aSubs;
-
-  AttributePtr aCenter = theFeature->attribute(SketchPlugin_Circle::CENTER_ID());
-  AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
-  if (!aCenter->isInitialized() || !aRadius->isInitialized())
-    return aNewEntity;
-
-  EntityWrapperPtr aCenterEnt, aRadiusEnt, aNormalEnt;
-  std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
-  for (; anIt != theAttributes.end(); ++anIt) {
-    std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSlvsEntity = 
-        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anIt);
-    if (aSlvsEntity->isBase(aCenter))
-      aCenterEnt = aSlvsEntity;
-    else if (aSlvsEntity->isBase(aRadius))
-      aRadiusEnt = aSlvsEntity;
-    else if (aSlvsEntity->type() == ENTITY_NORMAL)
-      aNormalEnt = aSlvsEntity;
-  }
-  if (!aCenterEnt || !aRadiusEnt || !aNormalEnt)
-    return aNewEntity;
-
-  aSubs.push_back(aCenterEnt);
-  aSubs.push_back(aRadiusEnt);
-  Slvs_Entity anEntity = Slvs_MakeCircle(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
-      (Slvs_hEntity)theSketchID, (Slvs_hEntity)aCenterEnt->id(),
-      (Slvs_hEntity)aNormalEnt->id(), (Slvs_hEntity)aRadiusEnt->id());
-
-  aNewEntity = EntityWrapperPtr(new SolveSpaceSolver_EntityWrapper(theFeature, anEntity));
-  aNewEntity->setSubEntities(aSubs);
-  return aNewEntity;
-}
-
-EntityWrapperPtr createArc(FeaturePtr theFeature,
-                           const std::list<EntityWrapperPtr>& theAttributes,
-                           const GroupID& theGroupID,
-                           const EntityID& theSketchID)
-{
-  EntityWrapperPtr aNewEntity;
-  std::list<EntityWrapperPtr> aSubs;
-
-  AttributePtr aCenter = theFeature->attribute(SketchPlugin_Arc::CENTER_ID());
-  AttributePtr aStart = theFeature->attribute(SketchPlugin_Arc::START_ID());
-  AttributePtr aEnd = theFeature->attribute(SketchPlugin_Arc::END_ID());
-  if (!aCenter->isInitialized() || !aStart->isInitialized() || !aEnd->isInitialized())
-    return aNewEntity;
-
-  EntityWrapperPtr aCenterEnt, aStartEnt, aEndEnt, aNormalEnt;
-  std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
-  for (; anIt != theAttributes.end(); ++anIt) {
-    std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSlvsEntity = 
-        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anIt);
-    if (aSlvsEntity->isBase(aCenter))
-      aCenterEnt = aSlvsEntity;
-    else if (aSlvsEntity->isBase(aStart))
-      aStartEnt = aSlvsEntity;
-    else if (aSlvsEntity->isBase(aEnd))
-      aEndEnt = aSlvsEntity;
-    else if (aSlvsEntity->type() == ENTITY_NORMAL)
-      aNormalEnt = aSlvsEntity;
-  }
-  if (!aCenterEnt || !aStartEnt || !aEndEnt || !aNormalEnt)
-    return aNewEntity;
-
-  aSubs.push_back(aCenterEnt);
-  aSubs.push_back(aStartEnt);
-  aSubs.push_back(aEndEnt);
-  Slvs_Entity anEntity = Slvs_MakeArcOfCircle(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
-      (Slvs_hEntity)theSketchID, (Slvs_hEntity)aNormalEnt->id(),
-      (Slvs_hEntity)aCenterEnt->id(), (Slvs_hEntity)aStartEnt->id(), (Slvs_hEntity)aEndEnt->id());
-
-  aNewEntity = EntityWrapperPtr(new SolveSpaceSolver_EntityWrapper(theFeature, anEntity));
-  aNewEntity->setSubEntities(aSubs);
-  return aNewEntity;
-}
-
-
-void adjustTangency(ConstraintWrapperPtr theConstraint)
-{
-  BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
-
-  std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
-    std::dynamic_pointer_cast<SolveSpaceSolver_ConstraintWrapper>(theConstraint);
-
-  // Collect start, end points of entities
-  std::shared_ptr<GeomAPI_Pnt2d> aStartEntPoints[2][2];
-  bool isCoinc[2][2] = {false};
-  const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
-  std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
-  for (int i = 0; aSIt != aSubs.end(); ++aSIt, ++i) {
-    const std::list<EntityWrapperPtr>& aPoints = (*aSIt)->subEntities();
-    std::list<EntityWrapperPtr>::const_iterator aPIt = aPoints.begin();
-    if ((*aSIt)->type() == ENTITY_ARC)
-      ++aPIt;
-    for (int j = 0; aPIt != aPoints.end(); ++aPIt, ++j) {
-      aStartEntPoints[i][j] = aBuilder->point(*aPIt);
-      if (i > 0) { // check coincidence
-        for (int k = 0; k < 2; ++k)
-          if (aStartEntPoints[i][j]->distance(aStartEntPoints[0][k]) < tolerance)
-            isCoinc[0][k] = isCoinc[i][j] = true;
-      }
-    }
-  }
-
-  Slvs_Constraint& aSlvsConstraint = aConstraint->changeConstraint();
-  if (isCoinc[0][0] == false && isCoinc[0][1] == true)
-    aSlvsConstraint.other = 1;
-  else aSlvsConstraint.other = 0;
-  if (isCoinc[1][0] == false && isCoinc[1][1] == true)
-    aSlvsConstraint.other2 = 1;
-  else aSlvsConstraint.other2 = 0;
-}
-
-void adjustAngle(ConstraintWrapperPtr theConstraint)
-{
-  BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
-
-  std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
-    std::dynamic_pointer_cast<SolveSpaceSolver_ConstraintWrapper>(theConstraint);
-
-  std::shared_ptr<GeomAPI_Pnt2d> aPoints[2][2]; // start and end points of lines
-  const std::list<EntityWrapperPtr>& aConstrLines = aConstraint->entities();
-  std::list<EntityWrapperPtr>::const_iterator aCLIt = aConstrLines.begin();
-  for (int i = 0; aCLIt != aConstrLines.end(); ++i, ++aCLIt) {
-    const std::list<EntityWrapperPtr>& aLinePoints = (*aCLIt)->subEntities();
-    std::list<EntityWrapperPtr>::const_iterator aLPIt = aLinePoints.begin();
-    for (int j = 0; aLPIt != aLinePoints.end(); ++j, ++aLPIt)
-      aPoints[i][j] = aBuilder->point(*aLPIt);
-  }
-
-  std::shared_ptr<GeomAPI_Lin2d> aLine[2] = {
-    std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[0][0], aPoints[0][1])),
-    std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[1][0], aPoints[1][1]))
-  };
-  std::shared_ptr<GeomAPI_Pnt2d> anIntersection = aLine[0]->intersect(aLine[1]);
-  if (!anIntersection)
-    return;
-  double aDist[2][2];
-  for (int i = 0; i < 2; i++) {
-    for (int j = 0; j < 2; j++) {
-      aDist[i][j] = anIntersection->distance(aPoints[i][j]);
-      if (fabs(aDist[i][j]) <= tolerance)
-        aDist[i][j] = 0.0;
-    }
-    if (aDist[i][0] > tolerance && aDist[i][1] > tolerance &&
-        aDist[i][0] + aDist[i][1] < aPoints[i][0]->distance(aPoints[i][1]) + 2.0 * tolerance) {
-      // the intersection point is an inner point of the line,
-      // we change the sign of distance till start point to calculate correct coordinates
-      // after rotation
-      aDist[i][0] *= -1.0;
-    }
-  }
-  std::shared_ptr<GeomAPI_Dir2d> aDir[2];
-  for (int i = 0; i < 2; i++) {
-    if (aDist[i][1] > fabs(aDist[i][0]))
-      aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
-          aPoints[i][1]->xy()->decreased(anIntersection->xy())));
-    else {
-      aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
-          aPoints[i][0]->xy()->decreased(anIntersection->xy())));
-      // main direction is opposite => change signs
-      if (aDist[i][0] < 0.0) {
-        aDist[i][0] *= -1.0;
-        aDist[i][1] *= -1.0;
-      }
-    }
-  }
-
-  Slvs_Constraint& aSlvsConstraint = aConstraint->changeConstraint();
-  aSlvsConstraint.other = false;
-  for (int i = 0; i < 2; i++)
-    if (aLine[i]->direction()->dot(aDir[i]) < 0.0)
-      aSlvsConstraint.other = !aSlvsConstraint.other;
-}
-
-void adjustMirror(ConstraintWrapperPtr theConstraint)
-{
-  std::vector<EntityWrapperPtr> aPoints;
-  EntityWrapperPtr aMirrorLine;
-
-  const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
-  std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
-  for (; anIt != aSubs.end(); ++anIt) {
-    if ((*anIt)->type() == ENTITY_POINT)
-      aPoints.push_back(*anIt);
-    else if ((*anIt)->type() == ENTITY_LINE)
-      aMirrorLine = *anIt;
-  }
-
-  makeMirrorPoints(aPoints[0], aPoints[1], aMirrorLine);
-}
-
-void makeMirrorPoints(EntityWrapperPtr theOriginal,
-                      EntityWrapperPtr theMirrored,
-                      EntityWrapperPtr theMirrorLine)
-{
-  BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
-
-  std::shared_ptr<GeomAPI_Lin2d> aMirrorLine = aBuilder->line(theMirrorLine);
-  std::shared_ptr<GeomAPI_Dir2d> aMLDir = aMirrorLine->direction();
-  // orthogonal direction
-  aMLDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aMLDir->y(), -aMLDir->x()));
-
-  std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(theOriginal);
-  std::shared_ptr<GeomAPI_XY> aVec = aPoint->xy()->decreased(aMirrorLine->location()->xy());
-  double aDist = aVec->dot(aMLDir->xy());
-  aVec = aPoint->xy()->added(aMLDir->xy()->multiplied(-2.0 * aDist));
-  double aCoord[2] = {aVec->x(), aVec->y()};
-  std::list<ParameterWrapperPtr>::const_iterator aMIt = theMirrored->parameters().begin();
-  for (int i = 0; aMIt != theMirrored->parameters().end(); ++aMIt, ++i)
-    (*aMIt)->setValue(aCoord[i]);
-
-  // update corresponding attribute
-  AttributePtr anAttr = std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theMirrored)->baseAttribute();
-  if (anAttr) {
-    std::shared_ptr<GeomDataAPI_Point2D> aMirroredPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
-    aMirroredPnt->setValue(aCoord[0], aCoord[1]);
-  }
-}
-
-static void rotate(EntityWrapperPtr theSource, EntityWrapperPtr theDest,
-                   std::shared_ptr<GeomAPI_Pnt2d> theCenter,
-                   double theSin, double theCos)
-{
-  std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSource =
-      std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theSource);
-  std::shared_ptr<SolveSpaceSolver_EntityWrapper> aDest =
-      std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theDest);
-
-  if (theSource->type() == ENTITY_POINT) {
-    // Rotate single point
-    std::shared_ptr<GeomDataAPI_Point2D> aSrcAttr =
-        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aSource->baseAttribute());
-    std::shared_ptr<GeomDataAPI_Point2D> aDstAttr =
-        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aDest->baseAttribute());
-    if (aSrcAttr && aDstAttr) {
-      std::shared_ptr<GeomAPI_XY> aVec = aSrcAttr->pnt()->xy()->decreased(theCenter->xy());
-      double aNewX = aVec->x() * theCos - aVec->y() * theSin;
-      double aNewY = aVec->x() * theSin + aVec->y() * theCos;
-      aDstAttr->setValue(theCenter->x() + aNewX, theCenter->y() + aNewY);
-    }
-    return;
-  }
-
-  FeaturePtr aDestFeature = aDest->baseFeature();
-  if (aDestFeature)
-    aDestFeature->data()->blockSendAttributeUpdated(true);
-
-  // Rotate points of the feature
-  const std::list<EntityWrapperPtr>& aSrcSubs = theSource->subEntities();
-  const std::list<EntityWrapperPtr>& aDstSubs = theDest->subEntities();
-  std::list<EntityWrapperPtr>::const_iterator aSrcIt, aDstIt;
-  for (aSrcIt = aSrcSubs.begin(), aDstIt = aDstSubs.begin();
-       aSrcIt != aSrcSubs.end() && aDstIt != aDstSubs.end(); ++aSrcIt, ++aDstIt)
-    rotate(*aSrcIt, *aDstIt, theCenter, theSin, theCos);
-
-  if (aDestFeature)
-    aDestFeature->data()->blockSendAttributeUpdated(false);
-}
-
-static void translate(EntityWrapperPtr theSource, EntityWrapperPtr theDest,
-                      std::shared_ptr<GeomAPI_XY> theDelta)
-{
-  std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSource =
-      std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theSource);
-  std::shared_ptr<SolveSpaceSolver_EntityWrapper> aDest =
-      std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theDest);
-
-  if (theSource->type() == ENTITY_POINT) {
-    // Translate single point
-    std::shared_ptr<GeomDataAPI_Point2D> aSrcAttr =
-        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aSource->baseAttribute());
-    std::shared_ptr<GeomDataAPI_Point2D> aDstAttr =
-        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aDest->baseAttribute());
-    if (aSrcAttr && aDstAttr)
-      aDstAttr->setValue(aSrcAttr->x() + theDelta->x(), aSrcAttr->y() + theDelta->y());
-    return;
-  }
-
-  FeaturePtr aDestFeature = aDest->baseFeature();
-  if (aDestFeature)
-    aDestFeature->data()->blockSendAttributeUpdated(true);
-
-  // Translate points of the feature
-  const std::list<EntityWrapperPtr>& aSrcSubs = theSource->subEntities();
-  const std::list<EntityWrapperPtr>& aDstSubs = theDest->subEntities();
-  std::list<EntityWrapperPtr>::const_iterator aSrcIt, aDstIt;
-  for (aSrcIt = aSrcSubs.begin(), aDstIt = aDstSubs.begin();
-       aSrcIt != aSrcSubs.end() && aDstIt != aDstSubs.end(); ++aSrcIt, ++aDstIt)
-    translate(*aSrcIt, *aDstIt, theDelta);
-
-  if (aDestFeature)
-    aDestFeature->data()->blockSendAttributeUpdated(false);
-}
-
-void adjustMultiRotation(ConstraintWrapperPtr theConstraint)
-{
-  BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
-
-  double anAngleRad = theConstraint->value() * PI / 180.0;
-  double aSin = sin(anAngleRad);
-  double aCos = cos(anAngleRad);
-
-  const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
-  std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
-
-  std::shared_ptr<GeomAPI_Pnt2d> aCenter = aBuilder->point(*aSIt++);
-  std::list<EntityWrapperPtr>::const_iterator aPrevIt = aSIt++;
-  for (; aSIt != aSubs.end(); ++aPrevIt, ++aSIt)
-    rotate(*aPrevIt, *aSIt, aCenter, aSin, aCos);
-}
-
-void adjustMultiTranslation(ConstraintWrapperPtr theConstraint)
-{
-  BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
-
-  const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
-  std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
-
-  std::shared_ptr<GeomAPI_Pnt2d> aStartPnt = aBuilder->point(*aSIt++);
-  std::shared_ptr<GeomAPI_Pnt2d> aEndPnt = aBuilder->point(*aSIt++);
-  std::shared_ptr<GeomAPI_XY> aDelta = aEndPnt->xy()->decreased(aStartPnt->xy());
-
-  std::list<EntityWrapperPtr>::const_iterator aPrevIt = aSIt++;
-  for (; aSIt != aSubs.end(); ++aPrevIt, ++aSIt)
-    translate(*aPrevIt, *aSIt, aDelta);
-}
diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Builder.h b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Builder.h
deleted file mode 100644 (file)
index f55330a..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SolveSpaceSolver_Builder.h
-// Created: 25 Mar 2015
-// Author:  Artem ZHIDKOV
-
-#ifndef SolveSpaceSolver_Builder_H_
-#define SolveSpaceSolver_Builder_H_
-
-#include <SketchSolver_Builder.h>
-#include <SketchSolver_Constraint.h>
-
-#include <SketchPlugin_Constraint.h>
-
-#include <ModelAPI_CompositeFeature.h>
-
-/** \class   SolveSpaceSolver_Builder
- *  \ingroup Plugins
- *  \brief   Create bridges between SketchPlugin constraints and SolveSpace constraints
- */
-class SolveSpaceSolver_Builder : public SketchSolver_Builder
-{
-private:
-  /// Default constructor
-  SolveSpaceSolver_Builder() {}
-
-public:
-  /// \brief Returns single instance of builder
-  static BuilderPtr getInstance();
-
-  /// \brief Creates a storage specific for used solver
-  virtual StoragePtr createStorage(const GroupID& theGroup) const;
-  /// \brief Creates specific solver
-  virtual SolverPtr createSolver() const;
-
-  /// \brief Creates new constraint(s) using given parameters
-  /// \param theConstraint [in]  original constraint
-  /// \param theGroupID    [in]  group the constraint belongs to
-  /// \param theSketchID   [in]  sketch the constraint belongs to
-  /// \param theType       [in]  type of constraint
-  /// \param theValue      [in]  numeric characteristic of constraint (e.g. distance or radius) if applicable
-  /// \param theEntity1    [in]  first attribute of constraint
-  /// \param theEntity2    [in]  second attribute of constraint
-  /// \param theEntity3    [in]  third attribute of constraint
-  /// \param theEntity4    [in]  fourth attribute of constraint
-  /// \return Created list of wrappers of constraints applicable for specific solver.
-  ///         Most of constraint types lead to single constraint, but there are some kind of
-  ///         constraints (e.g. mirror), which may produce couple of constraints.
-  virtual std::list<ConstraintWrapperPtr>
-    createConstraint(ConstraintPtr theConstraint,
-                     const GroupID& theGroupID,
-                     const EntityID& theSketchID,
-                     const SketchSolver_ConstraintType& theType,
-                     const double& theValue,
-                     const EntityWrapperPtr& theEntity1,
-                     const EntityWrapperPtr& theEntity2 = EntityWrapperPtr(),
-                     const EntityWrapperPtr& theEntity3 = EntityWrapperPtr(),
-                     const EntityWrapperPtr& theEntity4 = EntityWrapperPtr()) const;
-
-  /// \brief Creates new multi-translation or multi-rotation constraint
-  /// \param theConstraint [in]  original constraint
-  /// \param theGroupID    [in]  group the constraint belongs to
-  /// \param theSketchID   [in]  sketch the constraint belongs to
-  /// \param theType       [in]  type of constraint
-  /// \param theValue      [in]  numeric characteristic of constraint (angle for multi-rotation) if applicable
-  /// \param thePoint1     [in]  center for multi-rotation or start point for multi-translation
-  /// \param thePoint2     [in]  end point for multi-translation (empty for multi-rotation)
-  /// \param theTrsfEnt    [in]  list of transformed entities
-  virtual std::list<ConstraintWrapperPtr>
-    createConstraint(ConstraintPtr theConstraint,
-                     const GroupID& theGroupID,
-                     const EntityID& theSketchID,
-                     const SketchSolver_ConstraintType& theType,
-                     const double& theValue,
-                     const EntityWrapperPtr& thePoint1,
-                     const EntityWrapperPtr& thePoint2,
-                     const std::list<EntityWrapperPtr>& theTrsfEnt) const;
-
-  /// \brief Update flags for several kinds of constraints
-  virtual void adjustConstraint(ConstraintWrapperPtr theConstraint) const;
-
-  /// \brief Creates a feature using list of already created attributes
-  /// \param theFeature    [in]  feature to create
-  /// \param theAttributes [in]  attributes of the feature
-  /// \param theGroupID    [in]  group the feature belongs to
-  /// \param theSketchID   [in]  sketch the feature belongs to
-  /// \return Created wrapper of the feature applicable for specific solver
-  virtual EntityWrapperPtr createFeature(FeaturePtr theFeature,
-                                         const std::list<EntityWrapperPtr>& theAttributes,
-                                         const GroupID& theGroupID,
-                                         const EntityID& theSketchID = EID_UNKNOWN) const;
-
-  /// \brief Creates an attribute
-  /// \param theAttribute [in]  attribute to create
-  /// \param theGroup     [in]  group the attribute belongs to
-  /// \param theSketchID  [in]  sketch the attribute belongs to
-  /// \return Created wrapper of the attribute applicable for specific solver
-  virtual EntityWrapperPtr createAttribute(AttributePtr theAttribute,
-                                           const GroupID& theGroup,
-                                           const EntityID& theSketchID = EID_UNKNOWN) const;
-
-private:
-  /// \brief Create necessary constraints to make two object symmetric relatively a given line
-  std::list<ConstraintWrapperPtr> createMirror(ConstraintPtr theConstraint,
-                                               const GroupID& theGroupID,
-                                               const EntityID& theSketchID,
-                                               const EntityWrapperPtr& theEntity1,
-                                               const EntityWrapperPtr& theEntity2,
-                                               const EntityWrapperPtr& theMirrorLine) const;
-
-  /// \brief Converts sketch parameters to the entity applicable for the solver.
-  /// \param theSketch  [in]  the element to be converted
-  /// \param theGroupID [in]  group where the sketch should be created
-  /// \return Entity respective the sketch or empty pointer, it the sketch has incorrect attributes
-  EntityWrapperPtr createSketchEntity(CompositeFeaturePtr theSketch,
-                                      const GroupID& theGroupID) const;
-
-  /// \brief Converts two axes of sketch's trihedron to the normal entity
-  /// \param theNormal  [in]  direction of the normal of the sketch
-  /// \param theDirX    [in]  direction of the X axis of the sketch
-  /// \param theGroupID [in]  group, the normal belongs to
-  /// \return Created entity or empty pointer, if there are incorrect attributes
-  EntityWrapperPtr createNormal(AttributePtr theNormal,
-                                AttributePtr theDirX,
-                                const GroupID& theGroupID) const;
-
-  /// \brief Converts a value to SolveSpace parameter
-  /// \param theGroup [in]  group to store parameter
-  /// \param theValue [in]  value of parameter
-  /// \param theExpr  [in]  shows the parameter is given by expression
-  /// \return Created parameter's wrapper
-  ParameterWrapperPtr createParameter(const GroupID& theGroup,
-                                      const double theValue = 0.0,
-                                      const bool theExpr = false) const;
-
-private:
-  static BuilderPtr mySelf;
-};
-
-#endif
diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_ConstraintType.h b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_ConstraintType.h
deleted file mode 100644 (file)
index a38939b..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SolveSpaceSolver_ConstraintType.h
-// Created: 8 Dec 2015
-// Author:  Artem ZHIDKOV
-
-#ifndef SolveSpaceSolver_ConstraintType_H_
-#define SolveSpaceSolver_ConstraintType_H_
-
-#include <SketchSolver_IConstraintWrapper.h>
-#include <SolveSpaceSolver_Solver.h>
-
-namespace ConstraintType
-{
-  /// \brief Convert constraint type from SketchSolver to SolveSpace
-  static int toSolveSpace(SketchSolver_ConstraintType theType)
-  {
-    switch (theType) {
-    case CONSTRAINT_PT_PT_COINCIDENT:   return SLVS_C_POINTS_COINCIDENT;
-    case CONSTRAINT_PT_ON_LINE:         return SLVS_C_PT_ON_LINE;
-    case CONSTRAINT_PT_ON_CIRCLE:       return SLVS_C_PT_ON_CIRCLE;
-    case CONSTRAINT_PT_PT_DISTANCE:     return SLVS_C_PT_PT_DISTANCE;
-    case CONSTRAINT_PT_LINE_DISTANCE:   return SLVS_C_PT_LINE_DISTANCE;
-    case CONSTRAINT_ANGLE:              return SLVS_C_ANGLE;
-    case CONSTRAINT_RADIUS:             return SLVS_C_DIAMETER;
-    case CONSTRAINT_FIXED:              return SLVS_C_WHERE_DRAGGED;
-    case CONSTRAINT_HORIZONTAL:         return SLVS_C_HORIZONTAL;
-    case CONSTRAINT_VERTICAL:           return SLVS_C_VERTICAL;
-    case CONSTRAINT_PARALLEL:           return SLVS_C_PARALLEL;
-    case CONSTRAINT_PERPENDICULAR:      return SLVS_C_PERPENDICULAR;
-    case CONSTRAINT_SYMMETRIC:          return SLVS_C_SYMMETRIC_LINE;
-    case CONSTRAINT_EQUAL_LINES:        return SLVS_C_EQUAL_LENGTH_LINES;
-    case CONSTRAINT_EQUAL_LINE_ARC:     return SLVS_C_EQUAL_LINE_ARC_LEN;
-    case CONSTRAINT_EQUAL_RADIUS:       return SLVS_C_EQUAL_RADIUS;
-    case CONSTRAINT_TANGENT_ARC_LINE:   return SLVS_C_ARC_LINE_TANGENT;
-    case CONSTRAINT_TANGENT_ARC_ARC:    return SLVS_C_CURVE_CURVE_TANGENT;
-    case CONSTRAINT_MULTI_ROTATION:     return SLVS_C_MULTI_ROTATION;
-    case CONSTRAINT_MULTI_TRANSLATION:  return SLVS_C_MULTI_TRANSLATION;
-    default: break;
-    }
-    return SLVS_C_UNKNOWN;
-  }
-
-  /// \brief Convert constraint type from SolveSpace to SketchSolver
-  static SketchSolver_ConstraintType fromSolveSpace(int theType)
-  {
-    switch (theType) {
-    case SLVS_C_POINTS_COINCIDENT:    return CONSTRAINT_PT_PT_COINCIDENT;
-    case SLVS_C_PT_ON_LINE:           return CONSTRAINT_PT_ON_LINE;
-    case SLVS_C_PT_ON_CIRCLE:         return CONSTRAINT_PT_ON_CIRCLE;
-    case SLVS_C_PT_PT_DISTANCE:       return CONSTRAINT_PT_PT_DISTANCE;
-    case SLVS_C_PT_LINE_DISTANCE:     return CONSTRAINT_PT_LINE_DISTANCE;
-    case SLVS_C_EQUAL_LENGTH_LINES:   return CONSTRAINT_EQUAL_LINES;
-    case SLVS_C_EQUAL_LINE_ARC_LEN:   return CONSTRAINT_EQUAL_LINE_ARC;
-    case SLVS_C_SYMMETRIC_LINE:       return CONSTRAINT_SYMMETRIC;
-    case SLVS_C_HORIZONTAL:           return CONSTRAINT_HORIZONTAL;
-    case SLVS_C_VERTICAL:             return CONSTRAINT_VERTICAL;
-    case SLVS_C_DIAMETER:             return CONSTRAINT_RADIUS;
-    case SLVS_C_ANGLE:                return CONSTRAINT_ANGLE;
-    case SLVS_C_PARALLEL:             return CONSTRAINT_PARALLEL;
-    case SLVS_C_PERPENDICULAR:        return CONSTRAINT_PERPENDICULAR;
-    case SLVS_C_ARC_LINE_TANGENT:     return CONSTRAINT_TANGENT_ARC_LINE;
-    case SLVS_C_EQUAL_RADIUS:         return CONSTRAINT_EQUAL_RADIUS;
-    case SLVS_C_WHERE_DRAGGED:        return CONSTRAINT_FIXED;
-    case SLVS_C_CURVE_CURVE_TANGENT:  return CONSTRAINT_TANGENT_ARC_ARC;
-    case SLVS_C_MULTI_ROTATION:       return CONSTRAINT_MULTI_ROTATION;
-    case SLVS_C_MULTI_TRANSLATION:    return CONSTRAINT_MULTI_TRANSLATION;
-    default: break;
-    }
-    return CONSTRAINT_UNKNOWN;
-  }
-}
-
-
-#endif
diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_ConstraintWrapper.cpp b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_ConstraintWrapper.cpp
deleted file mode 100644 (file)
index 8419b9a..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SolveSpaceSolver_ConstraintWrapper.cpp
-// Created: 2 Dec 2015
-// Author:  Artem ZHIDKOV
-
-#include <SolveSpaceSolver_ConstraintWrapper.h>
-#include <SolveSpaceSolver_ConstraintType.h>
-#include <math.h>
-
-SolveSpaceSolver_ConstraintWrapper::SolveSpaceSolver_ConstraintWrapper(
-    const ConstraintPtr&    theOriginal,
-    const Slvs_Constraint& theConstraint)
-  : mySlvsConstraint(theConstraint)
-{
-  myBaseConstraint = theOriginal;
-  myValue = mySlvsConstraint.valA;
-}
-
-ConstraintID SolveSpaceSolver_ConstraintWrapper::id() const
-{
-  return (ConstraintID)mySlvsConstraint.h;
-}
-
-void SolveSpaceSolver_ConstraintWrapper::setGroup(const GroupID& theGroup)
-{
-  mySlvsConstraint.group = (Slvs_hGroup)theGroup;
-  std::list<EntityWrapperPtr>::iterator aSubsIt = myConstrained.begin();
-  for (; aSubsIt != myConstrained.end(); ++aSubsIt)
-    (*aSubsIt)->setGroup(theGroup);
-}
-
-SketchSolver_ConstraintType SolveSpaceSolver_ConstraintWrapper::type() const
-{
-  return ConstraintType::fromSolveSpace(mySlvsConstraint.type);
-}
-
-void SolveSpaceSolver_ConstraintWrapper::setValue(const double& theValue)
-{
-  double aValue = theValue;
-  if (type() == CONSTRAINT_RADIUS)
-    aValue *= 2.0; // NOTE: SolveSpace uses constraint DIAMETER
-
-  SketchSolver_IConstraintWrapper::setValue(aValue);
-}
-
-bool SolveSpaceSolver_ConstraintWrapper::isUsed(FeaturePtr theFeature) const
-{
-  std::list<EntityWrapperPtr>::const_iterator anIt = myConstrained.begin();
-  for (; anIt != myConstrained.end(); ++anIt)
-    if ((*anIt)->isUsed(theFeature))
-      return true;
-  return false;
-}
-
-bool SolveSpaceSolver_ConstraintWrapper::isUsed(AttributePtr theAttribute) const
-{
-  std::list<EntityWrapperPtr>::const_iterator anIt = myConstrained.begin();
-  for (; anIt != myConstrained.end(); ++anIt)
-    if ((*anIt)->isUsed(theAttribute))
-      return true;
-  return false;
-}
-
-bool SolveSpaceSolver_ConstraintWrapper::isEqual(const ConstraintWrapperPtr& theOther)
-{
-  const Slvs_Constraint anOtherConstraint = 
-    std::dynamic_pointer_cast<SolveSpaceSolver_ConstraintWrapper>(theOther)->constraint();
-  if (mySlvsConstraint.type != anOtherConstraint.type)
-    return false;
-
-  // Verify SolveSpace entities. If they are equal, no need additional checking of parameters.
-  if (mySlvsConstraint.group   == anOtherConstraint.group   &&
-      mySlvsConstraint.ptA     == anOtherConstraint.ptA     &&
-      mySlvsConstraint.ptB     == anOtherConstraint.ptB     &&
-      mySlvsConstraint.entityA == anOtherConstraint.entityA &&
-      mySlvsConstraint.entityB == anOtherConstraint.entityB &&
-      mySlvsConstraint.entityC == anOtherConstraint.entityC &&
-      mySlvsConstraint.entityD == anOtherConstraint.entityD &&
-      fabs(mySlvsConstraint.valA - anOtherConstraint.valA) < tolerance) {
-    return true;
-  }
-
-  // Verify equality of values
-  if (fabs(myValue - theOther->value()) > tolerance)
-    return false;
-
-  // Verify equality of entities
-  const std::list<EntityWrapperPtr>& anOtherSubs = theOther->entities();
-  if (myConstrained.size() != anOtherSubs.size())
-    return false;
-  std::list<EntityWrapperPtr>::const_iterator aMySubsIt = myConstrained.begin();
-  std::list<EntityWrapperPtr>::const_iterator anOtherSubsIt = anOtherSubs.begin();
-  for (; aMySubsIt != myConstrained.end(); ++aMySubsIt, ++anOtherSubsIt)
-    if (!(*aMySubsIt)->isEqual(*anOtherSubsIt))
-      return false;
-  return true;
-}
-
-bool SolveSpaceSolver_ConstraintWrapper::update(const ConstraintWrapperPtr& theOther)
-{
-  bool isUpdated = false;
-
-  std::list<EntityWrapperPtr> aMySubs = entities();
-  std::list<EntityWrapperPtr> anOtherSubs = theOther->entities();
-  std::list<EntityWrapperPtr>::const_iterator aMySubsIt = aMySubs.begin();
-  std::list<EntityWrapperPtr>::const_iterator anOtherSubsIt = anOtherSubs.begin();
-  for (; aMySubsIt != aMySubs.end() && anOtherSubsIt != anOtherSubs.end();
-       ++aMySubsIt, ++anOtherSubsIt)
-     isUpdated = (*aMySubsIt)->update(*anOtherSubsIt) || isUpdated;
-
-  if (fabs(value() - theOther->value()) > tolerance) {
-    myValue = theOther->value();
-    isUpdated = true;
-  }
-  return isUpdated;
-}
diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_ConstraintWrapper.h b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_ConstraintWrapper.h
deleted file mode 100644 (file)
index dd1bb1c..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SolveSpaceSolver_ConstraintWrapper.h
-// Created: 2 Dec 2015
-// Author:  Artem ZHIDKOV
-
-#ifndef SolveSpaceSolver_ConstraintWrapper_H_
-#define SolveSpaceSolver_ConstraintWrapper_H_
-
-#include <SketchSolver_IConstraintWrapper.h>
-#include <SolveSpaceSolver_Solver.h>
-
-
-/**
- *  Wrapper providing operations with SovleSpace constraints.
- */
-class SolveSpaceSolver_ConstraintWrapper : public SketchSolver_IConstraintWrapper
-{
-public:
-  SolveSpaceSolver_ConstraintWrapper(const ConstraintPtr&   theOriginal,
-                                     const Slvs_Constraint& theConstraint);
-
-  /// \brief Return SolveSpace constraint
-  const Slvs_Constraint& constraint() const
-  { return mySlvsConstraint; }
-  /// \brief Return SolveSpace constraint to change
-  Slvs_Constraint& changeConstraint()
-  { return mySlvsConstraint; }
-
-  /// \brief Return ID of current entity
-  virtual ConstraintID id() const;
-
-  /// \brief Change group for the constraint
-  virtual void setGroup(const GroupID& theGroup);
-  /// \brief Return identifier of the group the constraint belongs to
-  virtual const GroupID& group() const
-  { return (GroupID)mySlvsConstraint.group; }
-
-  /// \brief Return type of current entity
-  virtual SketchSolver_ConstraintType type() const;
-
-  /// \brief Assign numeric parameter of constraint
-  virtual void setValue(const double& theValue);
-
-  /// \brief Verify the feature is used in the constraint
-  virtual bool isUsed(FeaturePtr theFeature) const;
-  /// \brief Verify the attribute is used in the constraint
-  virtual bool isUsed(AttributePtr theAttribute) const;
-
-  /// \brief Compare current constraint with other
-  virtual bool isEqual(const ConstraintWrapperPtr& theOther);
-
-  /// \brief Update values of parameters of this constraint by the parameters of given one
-  /// \return \c true if some parameters change their values
-  virtual bool update(const std::shared_ptr<SketchSolver_IConstraintWrapper>& theOther);
-
-private:
-  Slvs_Constraint mySlvsConstraint;
-};
-
-#endif
diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_EntityWrapper.cpp b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_EntityWrapper.cpp
deleted file mode 100644 (file)
index 1cb8115..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SolveSpaceSolver_EntityWrapper.cpp
-// Created: 2 Dec 2015
-// Author:  Artem ZHIDKOV
-
-#include <SolveSpaceSolver_EntityWrapper.h>
-
-SolveSpaceSolver_EntityWrapper::SolveSpaceSolver_EntityWrapper(
-    const FeaturePtr theFeature, const Slvs_Entity& theEntity)
-  : myEntity(theEntity)
-{
-  myBaseFeature = theFeature;
-}
-
-SolveSpaceSolver_EntityWrapper::SolveSpaceSolver_EntityWrapper(
-    const AttributePtr theAttribute, const Slvs_Entity& theEntity)
-  : myEntity(theEntity)
-{
-  myBaseAttribute = theAttribute;
-}
-
-EntityID SolveSpaceSolver_EntityWrapper::id() const
-{
-  return (EntityID)myEntity.h;
-}
-
-void SolveSpaceSolver_EntityWrapper::setGroup(const GroupID& theGroup)
-{
-  myEntity.group = (Slvs_hGroup)theGroup;
-  std::list<EntityWrapperPtr>::iterator aSubsIt = mySubEntities.begin();
-  for (; aSubsIt != mySubEntities.end(); ++aSubsIt)
-    (*aSubsIt)->setGroup(theGroup);
-  std::list<ParameterWrapperPtr>::iterator aPIt = myParameters.begin();
-  for (; aPIt != myParameters.end(); ++aPIt)
-    (*aPIt)->setGroup(theGroup);
-}
-
-SketchSolver_EntityType SolveSpaceSolver_EntityWrapper::type() const
-{
-  switch (myEntity.type) {
-  case SLVS_E_POINT_IN_3D:
-  case SLVS_E_POINT_IN_2D:    return ENTITY_POINT;
-  case SLVS_E_LINE_SEGMENT:   return ENTITY_LINE;
-  case SLVS_E_CIRCLE:         return ENTITY_CIRCLE;
-  case SLVS_E_ARC_OF_CIRCLE:  return ENTITY_ARC;
-  case SLVS_E_NORMAL_IN_3D:
-  case SLVS_E_NORMAL_IN_2D:   return ENTITY_NORMAL;
-  case SLVS_E_DISTANCE:       return ENTITY_SCALAR;
-  case SLVS_E_WORKPLANE:      return ENTITY_SKETCH;
-  default: break;
-  }
-  return ENTITY_UNKNOWN;
-}
-
-bool SolveSpaceSolver_EntityWrapper::isUsed(FeaturePtr theFeature) const
-{
-  if (isBase(theFeature))
-    return true;
-
-  std::list<EntityWrapperPtr>::const_iterator anIt = mySubEntities.begin();
-  for (; anIt != mySubEntities.end(); ++anIt)
-    if ((*anIt)->isUsed(theFeature))
-      return true;
-  return false;
-}
-
-bool SolveSpaceSolver_EntityWrapper::isUsed(AttributePtr theAttribute) const
-{
-  if (isBase(theAttribute))
-    return true;
-
-  std::list<EntityWrapperPtr>::const_iterator anIt = mySubEntities.begin();
-  for (; anIt != mySubEntities.end(); ++anIt)
-    if ((*anIt)->isUsed(theAttribute))
-      return true;
-  return false;
-}
-
-bool SolveSpaceSolver_EntityWrapper::isEqual(const EntityWrapperPtr& theOther)
-{
-  if (type() != theOther->type())
-    return false;
-
-  // Verify Equality of sub-entities
-  const std::list<EntityWrapperPtr>& anOtherSubs = theOther->subEntities();
-  if (mySubEntities.size() != anOtherSubs.size())
-    return false;
-  std::list<EntityWrapperPtr>::const_iterator aMySubsIt = mySubEntities.begin();
-  std::list<EntityWrapperPtr>::const_iterator anOtherSubsIt = anOtherSubs.begin();
-  for (; aMySubsIt != mySubEntities.end(); ++aMySubsIt, ++anOtherSubsIt)
-    if (!(*aMySubsIt)->isEqual(*anOtherSubsIt))
-      return false;
-
-  // Verify equality of parameters
-  const std::list<ParameterWrapperPtr>& anOtherParams = theOther->parameters();
-  if (myParameters.size() != anOtherParams.size())
-    return false;
-  std::list<ParameterWrapperPtr>::const_iterator aMyIt = myParameters.begin();
-  std::list<ParameterWrapperPtr>::const_iterator anOtherIt = anOtherParams.begin();
-  for (; aMyIt != myParameters.end(); ++aMyIt, ++anOtherIt)
-    if (!(*aMyIt)->isEqual(*anOtherIt))
-      return false;
-  return true;
-}
-
-bool SolveSpaceSolver_EntityWrapper::update(const EntityWrapperPtr& theOther)
-{
-  bool isUpdated = false;
-
-  std::list<EntityWrapperPtr> aMySubs = subEntities();
-  std::list<EntityWrapperPtr> anOtherSubs = theOther->subEntities();
-  std::list<EntityWrapperPtr>::const_iterator aMySubsIt = aMySubs.begin();
-  std::list<EntityWrapperPtr>::const_iterator anOtherSubsIt = anOtherSubs.begin();
-  for (; aMySubsIt != aMySubs.end() && anOtherSubsIt != anOtherSubs.end();
-       ++aMySubsIt, ++anOtherSubsIt)
-     isUpdated = (*aMySubsIt)->update(*anOtherSubsIt) || isUpdated;
-
-  std::list<ParameterWrapperPtr> aMyParams = parameters();
-  std::list<ParameterWrapperPtr> anOtherParams = theOther->parameters();
-  std::list<ParameterWrapperPtr>::const_iterator aMyParIt = aMyParams.begin();
-  std::list<ParameterWrapperPtr>::const_iterator anOtherParIt = anOtherParams.begin();
-  for (; aMyParIt != aMyParams.end() && anOtherParIt != anOtherParams.end();
-      ++aMyParIt, ++anOtherParIt)
-    isUpdated = (*aMyParIt)->update(*anOtherParIt);
-  return isUpdated;
-}
diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_EntityWrapper.h b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_EntityWrapper.h
deleted file mode 100644 (file)
index 4f74823..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SolveSpaceSolver_EntityWrapper.h
-// Created: 2 Dec 2015
-// Author:  Artem ZHIDKOV
-
-#ifndef SolveSpaceSolver_EntityWrapper_H_
-#define SolveSpaceSolver_EntityWrapper_H_
-
-#include <SketchSolver_IEntityWrapper.h>
-#include <SolveSpaceSolver_Solver.h>
-
-/**
- *  Wrapper providing operations with SolveSpace entities.
- */
-class SolveSpaceSolver_EntityWrapper : public SketchSolver_IEntityWrapper
-{
-public:
-  SolveSpaceSolver_EntityWrapper(const FeaturePtr theFeature, const Slvs_Entity& theEntity);
-  SolveSpaceSolver_EntityWrapper(const AttributePtr theAttribute, const Slvs_Entity& theEntity);
-
-  /// \brief Return SolveSpace entity
-  const Slvs_Entity& entity() const
-  { return myEntity; }
-  /// \brief Return SolveSpace entity to change
-  Slvs_Entity& changeEntity()
-  { return myEntity; }
-
-  /// \brief Return ID of current entity
-  virtual EntityID id() const;
-
-  /// \brief Change group for the entity
-  virtual void setGroup(const GroupID& theGroup);
-  /// \brief Return identifier of the group the entity belongs to
-  virtual const GroupID& group() const
-  { return (GroupID)myEntity.group; }
-
-  /// \brief Return type of current entity
-  virtual SketchSolver_EntityType type() const;
-
-  /// \brief Verify the feature is used in the entity
-  virtual bool isUsed(FeaturePtr theFeature) const;
-  /// \brief Verify the attribute is used in the entity
-  virtual bool isUsed(AttributePtr theAttribute) const;
-
-  /// \brief Compare current entity with other
-  virtual bool isEqual(const EntityWrapperPtr& theOther);
-
-  /// \brief Update values of parameters of this entity by the parameters of given one
-  /// \return \c true if some parameters change their values
-  virtual bool update(const std::shared_ptr<SketchSolver_IEntityWrapper>& theOther);
-
-private:
-  Slvs_Entity  myEntity;
-};
-
-#endif
diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_ParameterWrapper.cpp b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_ParameterWrapper.cpp
deleted file mode 100644 (file)
index 1f2c7d4..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SolveSpaceSolver_ParameterWrapper.cpp
-// Created: 2 Dec 2015
-// Author:  Artem ZHIDKOV
-
-#include <SolveSpaceSolver_ParameterWrapper.h>
-
-#include <math.h>
-
-SolveSpaceSolver_ParameterWrapper::SolveSpaceSolver_ParameterWrapper(const Slvs_Param& theParam)
-  : myParameter(theParam)
-{
-}
-
-ParameterID SolveSpaceSolver_ParameterWrapper::id() const
-{
-  return (ParameterID)myParameter.h;
-}
-
-void SolveSpaceSolver_ParameterWrapper::setValue(double theValue)
-{
-  myParameter.val = theValue;
-}
-
-double SolveSpaceSolver_ParameterWrapper::value() const
-{
-  return myParameter.val;
-}
-
-bool SolveSpaceSolver_ParameterWrapper::isEqual(const ParameterWrapperPtr& theOther)
-{
-  std::shared_ptr<SolveSpaceSolver_ParameterWrapper> anOtherParam = 
-      std::dynamic_pointer_cast<SolveSpaceSolver_ParameterWrapper>(theOther);
-  return anOtherParam && fabs(value() - anOtherParam->value()) < tolerance;
-}
-
-bool SolveSpaceSolver_ParameterWrapper::update(const ParameterWrapperPtr& theOther)
-{
-  std::shared_ptr<SolveSpaceSolver_ParameterWrapper> anOther =
-      std::dynamic_pointer_cast<SolveSpaceSolver_ParameterWrapper>(theOther);
-  if (fabs(value() - anOther->value()) < tolerance)
-    return false;
-  myParameter.val = anOther->value();
-  myIsParametric = theOther->isParametric();
-  return true;
-}
diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_ParameterWrapper.h b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_ParameterWrapper.h
deleted file mode 100644 (file)
index 35609f5..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SolveSpaceSolver_ParameterWrapper.h
-// Created: 2 Dec 2015
-// Author:  Artem ZHIDKOV
-
-#ifndef SolveSpaceSolver_ParameterWrapper_H_
-#define SolveSpaceSolver_ParameterWrapper_H_
-
-#include <SketchSolver_IParameterWrapper.h>
-#include <SolveSpaceSolver_Solver.h>
-
-/**
- *  Wrapper providing operations with parameters in SolveSpace.
- */
-class SolveSpaceSolver_ParameterWrapper : public SketchSolver_IParameterWrapper
-{
-public:
-  SolveSpaceSolver_ParameterWrapper(const Slvs_Param& theParam);
-
-  /// \brief Return SolveSpace parameter
-  const Slvs_Param& parameter() const
-  { return myParameter; }
-  /// \brief Return SolveSpace parameter to change
-  Slvs_Param& changeParameter()
-  { return myParameter; }
-
-  /// \brief Return ID of current parameter
-  virtual ParameterID id() const;
-
-  /// \brief Change group for the parameter
-  virtual void setGroup(const GroupID& theGroup)
-  { myParameter.group = (Slvs_hGroup)theGroup; }
-
-  /// \brief Return identifier of the group the parameter belongs to
-  virtual const GroupID& group() const
-  { return (GroupID)myParameter.group; }
-
-  /// \brief Change value of parameter
-  virtual void setValue(double theValue);
-  /// \brief Return value of parameter
-  virtual double value() const;
-
-  /// \brief Compare current parameter with other
-  virtual bool isEqual(const ParameterWrapperPtr& theOther);
-
-  /// \brief Update value of parameter by the given one
-  /// \return \c true if the value of parameter is changed
-  virtual bool update(const std::shared_ptr<SketchSolver_IParameterWrapper>& theOther);
-
-private:
-  Slvs_Param myParameter;
-};
-
-#endif
diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.cpp b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.cpp
deleted file mode 100644 (file)
index de1cc3e..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SolveSpaceSolver_Solver.cpp
-// Created: 07 May 2014
-// Author:  Artem ZHIDKOV
-
-#include "SolveSpaceSolver_Solver.h"
-#include <Events_LongOp.h>
-
-SolveSpaceSolver_Solver::SolveSpaceSolver_Solver()
-{
-  // Nullify all elements of the set of equations
-  myEquationsSystem.param = 0;
-  myEquationsSystem.params = 0;
-  myEquationsSystem.entity = 0;
-  myEquationsSystem.entities = 0;
-  myEquationsSystem.constraint = 0;
-  myEquationsSystem.constraints = 0;
-  myEquationsSystem.failed = 0;
-  myEquationsSystem.faileds = 0;
-
-  myEquationsSystem.dragged[0] = 0;
-  myEquationsSystem.dragged[1] = 0;
-  myEquationsSystem.dragged[2] = 0;
-  myEquationsSystem.dragged[3] = 0;
-
-  // If the set of constraints is inconsistent,
-  // the failed field will contain wrong constraints
-  myEquationsSystem.calculateFaileds = 0;
-}
-
-SolveSpaceSolver_Solver::~SolveSpaceSolver_Solver()
-{
-  if (myEquationsSystem.constraint)
-    delete[] myEquationsSystem.constraint;
-  myEquationsSystem.constraint = 0;
-  if (myEquationsSystem.failed)
-    delete[] myEquationsSystem.failed;
-  myEquationsSystem.failed = 0;
-}
-
-void SolveSpaceSolver_Solver::setParameters(Slvs_Param* theParameters, int theSize)
-{
-  myEquationsSystem.param = theParameters;
-  myEquationsSystem.params = theSize;
-}
-
-
-void SolveSpaceSolver_Solver::setDraggedParameters(const Slvs_hParam* theDragged)
-{
-  for (unsigned int i = 0; i < 4; i++)
-    myEquationsSystem.dragged[i] = theDragged[i];
-}
-
-void SolveSpaceSolver_Solver::setEntities(Slvs_Entity* theEntities, int theSize)
-{
-  myEquationsSystem.entity = theEntities;
-  myEquationsSystem.entities = theSize;
-}
-
-void SolveSpaceSolver_Solver::setConstraints(Slvs_Constraint* theConstraints, int theSize)
-{
-  if (!myEquationsSystem.constraint) {
-    myEquationsSystem.constraint = new Slvs_Constraint[theSize];
-    myEquationsSystem.constraints = theSize;
-    myEquationsSystem.failed = new Slvs_hConstraint[theSize];
-  }
-  else if (myEquationsSystem.constraints != theSize) {
-    if (theSize > myEquationsSystem.constraints) {
-      delete[] myEquationsSystem.constraint;
-      myEquationsSystem.constraint = new Slvs_Constraint[theSize];
-      if (myEquationsSystem.failed)
-        delete[] myEquationsSystem.failed;
-      myEquationsSystem.failed = new Slvs_hConstraint[theSize];
-    }
-    myEquationsSystem.constraints = theSize;
-  }
-  memcpy(myEquationsSystem.constraint, theConstraints, theSize * sizeof(Slvs_Constraint));
-  memset(myEquationsSystem.failed, SLVS_C_UNKNOWN, theSize * sizeof(Slvs_hConstraint));
-}
-
-
-SketchSolver_SolveStatus SolveSpaceSolver_Solver::solve()
-{
-  if (myEquationsSystem.constraints <= 0)
-    return STATUS_EMPTYSET;
-
-  myEquationsSystem.calculateFaileds = myFindFaileds ? 1 : 0;
-
-  Events_LongOp::start(this);
-  Slvs_Solve(&myEquationsSystem, myGroup);
-  Events_LongOp::end(this);
-
-  SketchSolver_SolveStatus aStatus;
-  switch (myEquationsSystem.result) {
-  case SLVS_RESULT_OKAY:
-    aStatus = STATUS_OK;
-    break;
-  case SLVS_RESULT_INCONSISTENT:
-  case SLVS_RESULT_DIDNT_CONVERGE:
-  case SLVS_RESULT_TOO_MANY_UNKNOWNS:
-    aStatus = STATUS_INCONSISTENT;
-    break;
-  default:
-    aStatus = STATUS_FAILED;
-  }
-  return aStatus;
-}
diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.h b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.h
deleted file mode 100644 (file)
index c853970..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SolveSpaceSolver_Solver.h
-// Created: 07 May 2014
-// Author:  Artem ZHIDKOV
-
-#ifndef SolveSpaceSolver_Solver_H_
-#define SolveSpaceSolver_Solver_H_
-
-#include <SketchSolver_ISolver.h>
-
-// Need to be defined before including SolveSpace to avoid additional dependences on Windows platform
-#if defined(WIN32) && !defined(HAVE_C99_INTEGER_TYPES)
-typedef unsigned int UINT32;
-#else
-#include <stdint.h>
-#endif
-#include <string.h>
-#include <slvs.h>
-
-#include <vector>
-
-// Unknown constraint (for error reporting)
-#define SLVS_C_UNKNOWN 0
-// Fillet constraint identifier
-#define SLVS_C_FILLET            100100
-// Multi-rotation constraint identifier
-#define SLVS_C_MULTI_ROTATION    100101
-// Multi-translation constraint identifier
-#define SLVS_C_MULTI_TRANSLATION 100102
-// Unknown entity
-#define SLVS_E_UNKNOWN 0
-// Unknown group
-#define SLVS_G_UNKNOWN 0
-// Group ID to store external objects
-#define SLVS_G_OUTOFGROUP 1
-
-/** \class SolveSpaceSolver_Solver
- *  \ingroup Plugins
- *  \brief Performs high-level operations to solve sketch in SolveSpace.
- */
-class SolveSpaceSolver_Solver : public SketchSolver_ISolver
-{
- public:
-  SolveSpaceSolver_Solver();
-  virtual ~SolveSpaceSolver_Solver();
-
-  /** \brief Change array of parameters
-   *  \param[in] theParameters pointer to the array of parameters
-   *  \param[in] theSize       size of this array
-   */
-  void setParameters(Slvs_Param* theParameters, int theSize);
-
-  /** \brief Change array of entities
-   *  \param[in] theEntities pointer to the array of entities
-   *  \param[in] theSize     size of this array
-   */
-  void setEntities(Slvs_Entity* theEntities, int theSize);
-
-  /** \brief Change array of constraints
-   *  \param[in] theConstraints pointer to the array of constraints
-   *  \param[in] theSize        size of this array
-   */
-  void setConstraints(Slvs_Constraint* theConstraints, int theSize);
-
-  /** \brief Store the parameters of the point which was moved by user.
-   *         The solver will watch this items to be constant
-   *  \param[in] theDragged list of parameters (not more than 4) which should not be changed during solving
-   */
-  void setDraggedParameters(const Slvs_hParam* theDragged);
-
-  /** \brief Solve the set of equations
-   *  \return identifier whether solution succeeded
-   */
-  virtual SketchSolver_SolveStatus solve();
-
- private:
-  Slvs_System myEquationsSystem; ///< set of equations for solving in SolveSpace
-};
-
-#endif
diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp
deleted file mode 100644 (file)
index 7843cd8..0000000
+++ /dev/null
@@ -1,2044 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SolveSpaceSolver_Storage.cpp
-// Created: 18 Mar 2015
-// Author:  Artem ZHIDKOV
-
-#include <SolveSpaceSolver_Storage.h>
-#include <SolveSpaceSolver_ConstraintWrapper.h>
-#include <SolveSpaceSolver_EntityWrapper.h>
-#include <SolveSpaceSolver_ParameterWrapper.h>
-#include <SolveSpaceSolver_Builder.h>
-
-#include <GeomAPI_Dir2d.h>
-#include <GeomAPI_Pnt2d.h>
-#include <GeomAPI_XY.h>
-#include <math.h>
-#include <assert.h>
-
-#include <GeomDataAPI_Point.h>
-#include <GeomDataAPI_Point2D.h>
-#include <ModelAPI_AttributeDouble.h>
-
-/** \brief Search the entity/parameter with specified ID in the list of elements
- *  \param[in] theEntityID unique ID of the element
- *  \param[in] theEntities list of elements
- *  \return position of the found element or -1 if the element is not found
- */
-template<typename T>
-static int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities);
-
-/// \brief Compare two parameters to be different
-static bool IsNotEqual(const Slvs_Param& theParam1, const Slvs_Param& theParam2);
-/// \brief Compare two entities to be different
-static bool IsNotEqual(const Slvs_Entity& theEntity1, const Slvs_Entity& theEntity2);
-/// \brief Compare two constraints to be different
-static bool IsNotEqual(const Slvs_Constraint& theConstraint1, const Slvs_Constraint& theConstraint2);
-
-
-SolveSpaceSolver_Storage::SolveSpaceSolver_Storage(const GroupID& theGroup)
-  : SketchSolver_Storage(theGroup),
-    myWorkplaneID(SLVS_E_UNKNOWN),
-    myParamMaxID(SLVS_E_UNKNOWN),
-    myEntityMaxID(SLVS_E_UNKNOWN),
-    myConstrMaxID(SLVS_C_UNKNOWN),
-    myFixed(SLVS_E_UNKNOWN),
-    myDuplicatedConstraint(false)
-{
-}
-
-bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr& theConstraint)
-{
-  bool isUpdated = false;
-  std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
-      std::dynamic_pointer_cast<SolveSpaceSolver_ConstraintWrapper>(theConstraint);
-  Slvs_Constraint aSlvsConstr = getConstraint((Slvs_hConstraint)aConstraint->id());
-  if (aSlvsConstr.h == SLVS_C_UNKNOWN)
-    aSlvsConstr = aConstraint->constraint();
-
-  // update value of constraint if exist
-  if (fabs(aSlvsConstr.valA - theConstraint->value()) > tolerance) {
-    aSlvsConstr.valA = theConstraint->value();
-    isUpdated = true;
-  }
-
-  // update constrained entities
-  Slvs_hEntity* aPnts[2] = {&aSlvsConstr.ptA, &aSlvsConstr.ptB};
-  Slvs_hEntity* anEnts[4] = {&aSlvsConstr.entityA, &aSlvsConstr.entityB,
-                             &aSlvsConstr.entityC, &aSlvsConstr.entityD};
-  int aPtInd = 0;
-  int aEntInd = 0;
-
-  std::list<EntityWrapperPtr> anEntities = theConstraint->entities();
-  std::list<EntityWrapperPtr>::iterator anIt = anEntities.begin();
-  for (; anIt != anEntities.end(); ++anIt) {
-    isUpdated = update(*anIt) || isUpdated;
-
-    Slvs_hEntity anID = (Slvs_hEntity)(*anIt)->id();
-    if ((*anIt)->type() == ENTITY_POINT) {
-      if (*(aPnts[aPtInd]) != anID) {
-        *(aPnts[aPtInd]) = anID;
-        isUpdated = true;
-      }
-      ++aPtInd;
-    } else {
-      if (*(anEnts[aEntInd]) != anID) {
-        *(anEnts[aEntInd]) = anID;
-        isUpdated = true;
-      }
-      ++aEntInd;
-    }
-  }
-
-  // update constraint itself (do not update constraints Multi)
-  if (aSlvsConstr.type != SLVS_C_MULTI_ROTATION && aSlvsConstr.type != SLVS_C_MULTI_TRANSLATION) {
-    if (aSlvsConstr.wrkpl == SLVS_E_UNKNOWN && myWorkplaneID != SLVS_E_UNKNOWN)
-      aSlvsConstr.wrkpl = myWorkplaneID;
-    if (aSlvsConstr.group == SLVS_G_UNKNOWN)
-      aSlvsConstr.group = (Slvs_hGroup)myGroupID;
-    Slvs_hConstraint aConstrID = updateConstraint(aSlvsConstr);
-    if (aSlvsConstr.h == SLVS_C_UNKNOWN) {
-      aConstraint->changeConstraint() = getConstraint(aConstrID);
-      isUpdated = true;
-    }
-  }
-  return isUpdated;
-}
-
-bool SolveSpaceSolver_Storage::update(EntityWrapperPtr& theEntity)
-{
-  bool isUpdated = false;
-  std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity = 
-      std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theEntity);
-  Slvs_Entity aSlvsEnt = getEntity((Slvs_hEntity)anEntity->id());
-  if (aSlvsEnt.h == SLVS_E_UNKNOWN)
-    aSlvsEnt = anEntity->entity();
-
-  std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
-  std::list<ParameterWrapperPtr>::iterator aPIt;
-  // if the entity is an attribute, need to update its coordinates
-  if (anEntity->baseAttribute()) {
-    BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
-    EntityWrapperPtr anUpdAttr = aBuilder->createAttribute(anEntity->baseAttribute(), GID_UNKNOWN);
-    if (anUpdAttr) {
-      std::list<ParameterWrapperPtr> anUpdParams = anUpdAttr->parameters();
-      std::list<ParameterWrapperPtr>::iterator anUpdIt = anUpdParams.begin();
-      for (aPIt = aParams.begin(); aPIt != aParams.end() && anUpdIt != anUpdParams.end();
-          ++aPIt, ++anUpdIt) {
-        (*aPIt)->update(*anUpdIt);
-      }
-    }
-  }
-
-  // update parameters
-  int anInd = 0;
-  for (aPIt = aParams.begin(); aPIt != aParams.end(); ++aPIt, ++anInd) {
-    assert(anInd < 4);
-    isUpdated = update(*aPIt) || isUpdated;
-    if (aSlvsEnt.param[anInd] != (Slvs_hEntity)(*aPIt)->id()) {
-      isUpdated = true;
-      aSlvsEnt.param[anInd] = (Slvs_hEntity)(*aPIt)->id();
-    }
-  }
-
-  // update sub-entities
-  std::list<EntityWrapperPtr> aSubEntities = theEntity->subEntities();
-  std::list<EntityWrapperPtr>::iterator aSIt = aSubEntities.begin();
-  for (anInd = 0; aSIt != aSubEntities.end(); ++aSIt, ++anInd) {
-    assert(anInd < 4);
-    isUpdated = update(*aSIt) || isUpdated;
-
-    Slvs_hEntity anID = Slvs_hEntity((*aSIt)->id());
-    if ((*aSIt)->type() == ENTITY_NORMAL)
-      aSlvsEnt.normal = anID;
-    else if ((*aSIt)->type() == ENTITY_SCALAR)
-      aSlvsEnt.distance = anID;
-    else if (aSlvsEnt.point[anInd] != anID) {
-      aSlvsEnt.point[anInd] = anID;
-      isUpdated = true;
-    }
-  }
-
-  // update entity itself
-  if (aSlvsEnt.wrkpl == SLVS_E_UNKNOWN && myWorkplaneID != SLVS_E_UNKNOWN)
-    aSlvsEnt.wrkpl = myWorkplaneID;
-  if (aSlvsEnt.group == SLVS_G_UNKNOWN)
-    aSlvsEnt.group = (Slvs_hGroup)myGroupID;
-  Slvs_hEntity anEntID = updateEntity(aSlvsEnt);
-  if (aSlvsEnt.h == SLVS_E_UNKNOWN) {
-    anEntity->changeEntity() = getEntity(anEntID);
-    isUpdated = true;
-
-    if (anEntity->type() == ENTITY_SKETCH)
-      storeWorkplane(anEntity);
-  }
-  return isUpdated;
-}
-
-bool SolveSpaceSolver_Storage::update(ParameterWrapperPtr& theParameter)
-{
-  std::shared_ptr<SolveSpaceSolver_ParameterWrapper> aParameter = 
-      std::dynamic_pointer_cast<SolveSpaceSolver_ParameterWrapper>(theParameter);
-  const Slvs_Param& aParam = getParameter((Slvs_hParam)aParameter->id());
-  if (aParam.h != SLVS_E_UNKNOWN && fabs(aParam.val - aParameter->value()) < tolerance)
-    return false;
-  Slvs_Param aParamToUpd = aParameter->parameter();
-  if (aParamToUpd.group == SLVS_G_UNKNOWN)
-    aParamToUpd.group = aParameter->isParametric() ? (Slvs_hGroup)GID_OUTOFGROUP : (Slvs_hGroup)myGroupID;
-////  else if (aParameter->isParametric() && aParamToUpd.group != (Slvs_hGroup)GID_OUTOFGROUP)
-////    aParameter->setGroup(GID_OUTOFGROUP);
-  Slvs_hParam anID = updateParameter(aParamToUpd);
-  if (aParam.h == SLVS_E_UNKNOWN) // new parameter
-    aParameter->changeParameter() = getParameter(anID);
-  return true;
-}
-
-void SolveSpaceSolver_Storage::storeWorkplane(EntityWrapperPtr theSketch)
-{
-  myWorkplaneID = (Slvs_hEntity)theSketch->id();
-
-  // Update sub-entities of the sketch
-  std::list<EntityWrapperPtr> aSubEntities = theSketch->subEntities();
-  std::list<EntityWrapperPtr>::iterator aSIt = aSubEntities.begin();
-  for (; aSIt != aSubEntities.end(); ++aSIt) {
-    std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSub =
-        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*aSIt);
-    aSub->changeEntity().wrkpl = myWorkplaneID;
-  }
-
-  // Update all stored entities
-  std::vector<Slvs_Entity>::iterator anIt = myEntities.begin();
-  for (; anIt != myEntities.end(); ++anIt)
-    anIt->wrkpl = myWorkplaneID;
-}
-
-void SolveSpaceSolver_Storage::changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup)
-{
-  std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
-  std::list<ParameterWrapperPtr>::iterator aPIt = aParams.begin();
-  for (; aPIt != aParams.end(); ++aPIt)
-    changeGroup(*aPIt, theGroup);
-
-  std::list<EntityWrapperPtr> aSubs = theEntity->subEntities();
-  std::list<EntityWrapperPtr>::iterator aSIt = aSubs.begin();
-  for (; aSIt != aSubs.end(); ++aSIt)
-    changeGroup(*aSIt, theGroup);
-
-  if (theEntity->group() != theGroup) {
-    theEntity->setGroup(theGroup);
-    int aPos = Search((Slvs_hEntity)theEntity->id(), myEntities);
-    if (aPos >= 0 && aPos < (int)myEntities.size()) {
-      myEntities[aPos].group = (Slvs_hGroup)theGroup;
-      setNeedToResolve(true);
-    }
-  }
-}
-
-void SolveSpaceSolver_Storage::changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup)
-{
-  GroupID aGroup = theGroup;
-  if (theParam->isParametric())
-    aGroup = GID_OUTOFGROUP;
-  if (theParam->group() == aGroup)
-    return;
-
-  theParam->setGroup(aGroup);
-  int aPos = Search((Slvs_hParam)theParam->id(), myParameters);
-  if (aPos >= 0 && aPos < (int)myParameters.size()) {
-    myParameters[aPos].group = (Slvs_hGroup)aGroup;
-    setNeedToResolve(true);
-  }
-}
-
-void SolveSpaceSolver_Storage::addCoincidentPoints(
-    EntityWrapperPtr theMaster, EntityWrapperPtr theSlave)
-{
-  if (theMaster->type() != ENTITY_POINT || theSlave->type() != ENTITY_POINT)
-    return;
-
-  // Search available coincidence
-  CoincidentPointsMap::iterator aMasterFound = myCoincidentPoints.find(theMaster);
-  CoincidentPointsMap::iterator aSlaveFound = myCoincidentPoints.find(theSlave);
-  if (aMasterFound == myCoincidentPoints.end() &&  aSlaveFound == myCoincidentPoints.end()) {
-    // try to find master and slave points in the lists of slaves of already existent coincidences
-    CoincidentPointsMap::iterator anIt = myCoincidentPoints.begin();
-    for (; anIt != myCoincidentPoints.end(); ++anIt) {
-      if (anIt->second.find(theMaster) != anIt->second.end())
-        aMasterFound = anIt;
-      else if (anIt->second.find(theSlave) != anIt->second.end())
-        aSlaveFound = anIt;
-
-      if (aMasterFound != myCoincidentPoints.end() &&  aSlaveFound != myCoincidentPoints.end())
-        break;
-    }
-  }
-
-  if (aMasterFound == myCoincidentPoints.end()) {
-    // create new group
-    myCoincidentPoints[theMaster] = std::set<EntityWrapperPtr>();
-    aMasterFound = myCoincidentPoints.find(theMaster);
-  } else if (aMasterFound == aSlaveFound)
-    return; // already coincident
-
-  if (aSlaveFound != myCoincidentPoints.end()) {
-    // A slave has been found, we need to attach all points coincident with it to the new master
-    std::set<EntityWrapperPtr> aNewSlaves = aSlaveFound->second;
-    aNewSlaves.insert(aSlaveFound->first);
-    myCoincidentPoints.erase(aSlaveFound);
-
-    std::set<EntityWrapperPtr>::const_iterator aSlIt = aNewSlaves.begin();
-    for (; aSlIt != aNewSlaves.end(); ++aSlIt)
-      addCoincidentPoints(theMaster, *aSlIt);
-  } else {
-    // Update the slave if it was used in constraints and features
-    replaceInFeatures(theSlave, theMaster);
-    replaceInConstraints(theSlave, theMaster);
-
-    // Remove slave entity
-    removeEntity((Slvs_hEntity)theSlave->id());
-
-    std::shared_ptr<SolveSpaceSolver_EntityWrapper> aPointMaster = 
-        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theMaster);
-    std::shared_ptr<SolveSpaceSolver_EntityWrapper> aPointSlave = 
-        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theSlave);
-    aPointSlave->changeEntity() = aPointMaster->entity();
-    aPointSlave->setParameters(aPointMaster->parameters());
-
-    aMasterFound->second.insert(theSlave);
-  }
-}
-
-void SolveSpaceSolver_Storage::replaceInFeatures(
-    EntityWrapperPtr theSource, EntityWrapperPtr theDest)
-{
-  std::map<FeaturePtr, EntityWrapperPtr>::const_iterator anIt = myFeatureMap.begin();
-  for (; anIt != myFeatureMap.end(); ++anIt) {
-    bool isUpdated = false;
-    std::list<EntityWrapperPtr> aSubs = anIt->second->subEntities();
-    std::list<EntityWrapperPtr>::iterator aSubIt = aSubs.begin();
-    for (; aSubIt != aSubs.end(); ++aSubIt)
-      if ((*aSubIt)->id() == theSource->id()) {
-        (*aSubIt)->update(theDest);
-        isUpdated = true;
-      }
-
-    if (!isUpdated)
-      continue;
-
-    std::shared_ptr<SolveSpaceSolver_EntityWrapper> aWrapper =
-        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(anIt->second);
-    // update SolveSpace entity
-    Slvs_Entity anEnt = aWrapper->entity();
-    for (int i = 0; i < 4; ++i)
-      if (anEnt.point[i] == (Slvs_hEntity)theSource->id())
-        anEnt.point[i] = (Slvs_hEntity)theDest->id();
-    anEnt.h = updateEntity(anEnt);
-    aWrapper->changeEntity() = anEnt;
-
-    // update sub-entities
-    aWrapper->setSubEntities(aSubs);
-  }
-}
-
-void SolveSpaceSolver_Storage::replaceInConstraints(
-    EntityWrapperPtr theSource, EntityWrapperPtr theDest)
-{
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
-      anIt = myConstraintMap.begin();
-  std::list<ConstraintWrapperPtr>::const_iterator aCIt;
-  for (; anIt != myConstraintMap.end(); ++anIt)
-    for (aCIt = anIt->second.begin(); aCIt != anIt->second.end(); ++aCIt) {
-      // Do not process coincidence between points
-      // (these constraints are stored to keep the structure of constraints).
-      if ((*aCIt)->type() == CONSTRAINT_PT_PT_COINCIDENT)
-        continue;
-
-      bool isUpdated = false;
-      std::list<EntityWrapperPtr> aSubs = (*aCIt)->entities();
-      std::list<EntityWrapperPtr>::iterator aSubIt = aSubs.begin();
-      for (; aSubIt != aSubs.end(); ++aSubIt)
-        if ((*aSubIt)->id() == theSource->id()) {
-          (*aSubIt)->update(theDest);
-          isUpdated = true;
-        }
-
-      if (!isUpdated)
-        continue;
-
-      std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aWrapper =
-          std::dynamic_pointer_cast<SolveSpaceSolver_ConstraintWrapper>(*aCIt);
-      // change constraint entities
-      Slvs_Constraint aConstr = aWrapper->constraint();
-      if (aConstr.ptA == (Slvs_hEntity)theSource->id())
-        aConstr.ptA = (Slvs_hEntity)theDest->id();
-      if (aConstr.ptB == (Slvs_hEntity)theSource->id())
-        aConstr.ptB = (Slvs_hEntity)theDest->id();
-
-      // check the constraint is duplicated
-      std::vector<Slvs_Constraint>::const_iterator aSlvsCIt = myConstraints.begin();
-      for (; aSlvsCIt != myConstraints.end(); ++aSlvsCIt)
-        if (aConstr.h != aSlvsCIt->h &&
-            aConstr.type == aSlvsCIt->type &&
-            aConstr.ptA == aSlvsCIt->ptA && aConstr.ptB == aSlvsCIt->ptB &&
-            aConstr.entityA == aSlvsCIt->entityA && aConstr.entityB == aSlvsCIt->entityB &&
-            aConstr.entityC == aSlvsCIt->entityC && aConstr.entityD == aSlvsCIt->entityD) {
-          removeConstraint(aConstr.h);
-          aConstr = *aSlvsCIt;
-          break;
-        }
-
-      if (aSlvsCIt != myConstraints.end()) {
-        // constraint is duplicated, search its wrapper to add the mapping
-        std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
-            anIt2 = myConstraintMap.begin();
-        std::list<ConstraintWrapperPtr>::const_iterator aCIt2;
-        for (; anIt2 != myConstraintMap.end(); ++anIt2)
-          for (aCIt2 = anIt2->second.begin(); aCIt2 != anIt2->second.end(); ++aCIt2)
-            if ((Slvs_hConstraint)(*aCIt2)->id() == aConstr.h) {
-              addSameConstraints(*aCIt2, aWrapper);
-              break;
-            }
-      } else 
-        aConstr.h = updateConstraint(aConstr);
-      aWrapper->changeConstraint() = aConstr;
-
-      // update sub-entities
-      aWrapper->setEntities(aSubs);
-    }
-}
-
-void SolveSpaceSolver_Storage::addSameConstraints(ConstraintWrapperPtr theConstraint1,
-                                                  ConstraintWrapperPtr theConstraint2)
-{
-  SameConstraintMap::iterator anIt = myEqualConstraints.begin();
-  for (; anIt != myEqualConstraints.end(); ++anIt) {
-    if (anIt->find(theConstraint1) != anIt->end()) {
-      anIt->insert(theConstraint2);
-      return;
-    }
-    else if (anIt->find(theConstraint2) != anIt->end()) {
-      anIt->insert(theConstraint1);
-      return;
-    }
-  }
-  // group not found => create new one
-  std::set<ConstraintWrapperPtr> aNewGroup;
-  aNewGroup.insert(theConstraint1);
-  aNewGroup.insert(theConstraint2);
-  myEqualConstraints.push_back(aNewGroup);
-}
-
-
-EntityWrapperPtr SolveSpaceSolver_Storage::calculateMiddlePoint(
-    EntityWrapperPtr theBase, double theCoeff)
-{
-  BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
-
-  std::shared_ptr<GeomAPI_XY> aMidPoint;
-  if (theBase->type() == ENTITY_LINE) {
-    std::shared_ptr<GeomAPI_Pnt2d> aPoints[2];
-    const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
-    std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
-    for (int i = 0; i < 2; ++i, ++anIt)
-      aPoints[i] = aBuilder->point(*anIt);
-    aMidPoint = aPoints[0]->xy()->multiplied(1.0 - theCoeff)->added(
-        aPoints[1]->xy()->multiplied(theCoeff));
-  }
-  else if (theBase->type() == ENTITY_ARC) {
-    double theX, theY;
-    double anArcPoint[3][2];
-    const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
-    std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
-    for (int i = 0; i < 3; ++i, ++anIt) {
-      std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(*anIt);
-      anArcPoint[i][0] = aPoint->x();
-      anArcPoint[i][1] = aPoint->y();
-    }
-    // project last point of arc on the arc
-    double x = anArcPoint[1][0] - anArcPoint[0][0];
-    double y = anArcPoint[1][1] - anArcPoint[0][1];
-    double aRad = sqrt(x*x + y*y);
-    x = anArcPoint[2][0] - anArcPoint[0][0];
-    y = anArcPoint[2][1] - anArcPoint[0][1];
-    double aNorm = sqrt(x*x + y*y);
-    if (aNorm >= tolerance) {
-      anArcPoint[2][0] = x * aRad / aNorm;
-      anArcPoint[2][1] = y * aRad / aNorm;
-    }
-    anArcPoint[1][0] -= anArcPoint[0][0];
-    anArcPoint[1][1] -= anArcPoint[0][1];
-    if (theCoeff < tolerance) {
-      theX = anArcPoint[0][0] + anArcPoint[1][0];
-      theY = anArcPoint[0][1] + anArcPoint[1][1];
-    } else if (1 - theCoeff < tolerance) {
-      theX = anArcPoint[0][0] + anArcPoint[2][0];
-      theY = anArcPoint[0][1] + anArcPoint[2][1];
-    } else {
-      std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
-      std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
-      double anAngle = aStartDir->angle(aEndDir);
-      if (anAngle < 0)
-        anAngle += 2.0 * PI;
-      anAngle *= theCoeff;
-      double aCos = cos(anAngle);
-      double aSin = sin(anAngle);
-      theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
-      theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
-    }
-    aMidPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(theX, theY));
-  }
-
-  if (!aMidPoint)
-    return EntityWrapperPtr();
-
-  std::list<ParameterWrapperPtr> aParameters;
-  Slvs_Param aParam1 = Slvs_MakeParam(SLVS_E_UNKNOWN, (Slvs_hGroup)myGroupID, aMidPoint->x());
-  aParam1.h = addParameter(aParam1);
-  aParameters.push_back(ParameterWrapperPtr(new SolveSpaceSolver_ParameterWrapper(aParam1)));
-  Slvs_Param aParam2 = Slvs_MakeParam(SLVS_E_UNKNOWN, (Slvs_hGroup)myGroupID, aMidPoint->y());
-  aParam2.h = addParameter(aParam2);
-  aParameters.push_back(ParameterWrapperPtr(new SolveSpaceSolver_ParameterWrapper(aParam2)));
-  // Create entity (parameters are not filled)
-  Slvs_Entity anEntity = Slvs_MakePoint2d(SLVS_E_UNKNOWN, (Slvs_hGroup)myGroupID,
-      (Slvs_hEntity)myWorkplaneID, aParam1.h, aParam2.h);
-  anEntity.h = addEntity(anEntity);
-
-  EntityWrapperPtr aResult(new SolveSpaceSolver_EntityWrapper(AttributePtr(), anEntity));
-  aResult->setParameters(aParameters);
-  return aResult;
-}
-
-
-
-
-
-
-Slvs_hParam SolveSpaceSolver_Storage::addParameter(const Slvs_Param& theParam)
-{
-  if (theParam.h > 0 && theParam.h <= myParamMaxID) {
-    // parameter is already used, rewrite it
-    return updateParameter(theParam);
-  }
-
-  Slvs_Param aParam = theParam;
-  if (aParam.h > myParamMaxID)
-    myParamMaxID = aParam.h;
-  else
-    aParam.h = ++myParamMaxID;
-  myParameters.push_back(aParam);
-  myNeedToResolve = true;
-  return aParam.h;
-}
-
-Slvs_hParam SolveSpaceSolver_Storage::updateParameter(const Slvs_Param& theParam)
-{
-  if (theParam.h > 0 && theParam.h <= myParamMaxID) {
-    // parameter already used, rewrite it
-    int aPos = Search(theParam.h, myParameters);
-    if (aPos >= 0 && aPos < (int)myParameters.size()) {
-      if (IsNotEqual(myParameters[aPos], theParam))
-        myUpdatedParameters.insert(theParam.h);
-      myParameters[aPos] = theParam;
-      return theParam.h;
-    }
-  }
-
-  // Parameter is not found, add new one
-  Slvs_Param aParam = theParam;
-  aParam.h = 0;
-  return addParameter(aParam);
-}
-
-bool SolveSpaceSolver_Storage::removeParameter(const Slvs_hParam& theParamID)
-{
-  int aPos = Search(theParamID, myParameters);
-  if (aPos >= 0 && aPos < (int)myParameters.size()) {
-    // Firstly, search the parameter is not used elsewhere
-    std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
-    for (; anEntIter != myEntities.end(); anEntIter++) {
-      for (int i = 0; i < 4; i++)
-        if (anEntIter->param[i] == theParamID)
-          return false;
-    }
-    // Remove parameter
-    myParameters.erase(myParameters.begin() + aPos);
-    myParamMaxID = myParameters.empty() ? SLVS_E_UNKNOWN : myParameters.back().h;
-    myNeedToResolve = true;
-////    myRemovedParameters.insert(theParamID);
-    return true;
-  }
-////  else if (myRemovedParameters.find(theParamID) != myRemovedParameters.end())
-////    return true;
-  return true;
-}
-
-const Slvs_Param& SolveSpaceSolver_Storage::getParameter(const Slvs_hParam& theParamID) const
-{
-  int aPos = Search(theParamID, myParameters);
-  if (aPos >= 0 && aPos < (int)myParameters.size())
-    return myParameters[aPos];
-
-  // Parameter is not found, return empty object
-  static Slvs_Param aDummy;
-  aDummy.h = 0;
-  return aDummy;
-}
-
-
-Slvs_hEntity SolveSpaceSolver_Storage::addEntity(const Slvs_Entity& theEntity)
-{
-  if (theEntity.h > 0 && theEntity.h <= myEntityMaxID) {
-    // Entity is already used, rewrite it
-    return updateEntity(theEntity);
-  }
-
-  Slvs_Entity aEntity = theEntity;
-  if (aEntity.h > myEntityMaxID)
-    myEntityMaxID = aEntity.h;
-  else
-    aEntity.h = ++myEntityMaxID;
-  myEntities.push_back(aEntity);
-  myNeedToResolve = true;
-  return aEntity.h;
-}
-
-Slvs_hEntity SolveSpaceSolver_Storage::updateEntity(const Slvs_Entity& theEntity)
-{
-  if (theEntity.h > 0 && theEntity.h <= myEntityMaxID) {
-    // Entity already used, rewrite it
-    int aPos = Search(theEntity.h, myEntities);
-    if (aPos >= 0 && aPos < (int)myEntities.size()) {
-      myNeedToResolve = myNeedToResolve || IsNotEqual(myEntities[aPos], theEntity);
-      myEntities[aPos] = theEntity;
-      return theEntity.h;
-    }
-  }
-
-  // Entity is not found, add new one
-  Slvs_Entity aEntity = theEntity;
-  aEntity.h = 0;
-  return addEntity(aEntity);
-}
-
-bool SolveSpaceSolver_Storage::removeEntity(const Slvs_hEntity& theEntityID)
-{
-  bool aResult = true;
-  int aPos = Search(theEntityID, myEntities);
-  if (aPos >= 0 && aPos < (int)myEntities.size()) {
-    // Firstly, check the entity and its attributes is not used elsewhere
-    std::set<Slvs_hEntity> anEntAndSubs;
-    anEntAndSubs.insert(theEntityID);
-    for (int i = 0; i < 4; i++)
-      if (myEntities[aPos].point[i] != SLVS_E_UNKNOWN)
-        anEntAndSubs.insert(myEntities[aPos].point[i]);
-
-    std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
-    for (; anEntIter != myEntities.end(); anEntIter++) {
-      if (anEntAndSubs.find(anEntIter->h) != anEntAndSubs.end())
-        continue;
-      for (int i = 0; i < 4; i++)
-        if (anEntAndSubs.find(anEntIter->point[i]) != anEntAndSubs.end())
-          return false;
-      if (anEntAndSubs.find(anEntIter->distance) != anEntAndSubs.end())
-        return false;
-    }
-    std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
-    for (; aConstrIter != myConstraints.end(); aConstrIter++) {
-      Slvs_hEntity anEntIDs[6] = {aConstrIter->ptA, aConstrIter->ptB,
-          aConstrIter->entityA, aConstrIter->entityB,
-          aConstrIter->entityC, aConstrIter->entityD};
-      for (int i = 0; i < 6; i++)
-        if (anEntAndSubs.find(anEntIDs[i]) != anEntAndSubs.end())
-          return false;
-    }
-    // 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++)
-      if (anEntity.param[i] != SLVS_E_UNKNOWN)
-        aResult = removeParameter(anEntity.param[i]) && aResult;
-    for (int i = 0; i < 4; i++)
-      if (anEntity.point[i] != SLVS_E_UNKNOWN)
-        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);
-  }
-////  else if (myRemovedEntities.find(theEntityID) != myRemovedEntities.end())
-////    return true;
-  return aResult;
-}
-
-void SolveSpaceSolver_Storage::removeUnusedEntities()
-{
-  std::set<Slvs_hEntity> anUnusedEntities;
-  std::vector<Slvs_Entity>::const_iterator aEIt = myEntities.begin();
-  for (; aEIt != myEntities.end(); ++aEIt) {
-    if (aEIt->h == aEIt->wrkpl) {
-      // don't remove workplane
-      anUnusedEntities.erase(aEIt->point[0]);
-      anUnusedEntities.erase(aEIt->normal);
-      continue;
-    }
-    anUnusedEntities.insert(aEIt->h);
-  }
-
-  std::vector<Slvs_Constraint>::const_iterator aCIt = myConstraints.begin();
-  for (; aCIt != myConstraints.end(); ++aCIt) {
-    Slvs_hEntity aSubs[6] = {
-        aCIt->entityA, aCIt->entityB,
-        aCIt->entityC, aCIt->entityD,
-        aCIt->ptA,     aCIt->ptB};
-    for (int i = 0; i < 6; i++) {
-      if (aSubs[i] != SLVS_E_UNKNOWN) {
-        anUnusedEntities.erase(aSubs[i]);
-        int aPos = Search(aSubs[i], myEntities);
-        if (aPos >= 0 && aPos < (int)myEntities.size()) {
-          for (int j = 0; j < 4; j++)
-            if (myEntities[aPos].point[j] != SLVS_E_UNKNOWN)
-              anUnusedEntities.erase(myEntities[aPos].point[j]);
-          if (myEntities[aPos].distance != SLVS_E_UNKNOWN)
-            anUnusedEntities.erase(myEntities[aPos].distance);
-        }
-      }
-    }
-  }
-
-  std::set<Slvs_hEntity>::const_iterator anEntIt = anUnusedEntities.begin();
-  while (anEntIt != anUnusedEntities.end()) {
-    int aPos = Search(*anEntIt, myEntities);
-    if (aPos < 0 && aPos >= (int)myEntities.size())
-      continue;
-    Slvs_Entity anEntity = myEntities[aPos];
-    // Remove entity if and only if all its parameters unused
-    bool isUsed = false;
-    if (anEntity.distance != SLVS_E_UNKNOWN && 
-      anUnusedEntities.find(anEntity.distance) == anUnusedEntities.end())
-      isUsed = true;
-    for (int i = 0; i < 4 && !isUsed; i++)
-      if (anEntity.point[i] != SLVS_E_UNKNOWN &&
-          anUnusedEntities.find(anEntity.point[i]) == anUnusedEntities.end())
-        isUsed = true;
-    if (isUsed) {
-      anUnusedEntities.erase(anEntity.distance);
-      for (int i = 0; i < 4; i++)
-        if (anEntity.point[i] != SLVS_E_UNKNOWN)
-          anUnusedEntities.erase(anEntity.point[i]);
-      std::set<Slvs_hEntity>::iterator aRemoveIt = anEntIt++;
-      anUnusedEntities.erase(aRemoveIt);
-      continue;
-    }
-    ++anEntIt;
-  }
-
-  for (anEntIt = anUnusedEntities.begin(); anEntIt != anUnusedEntities.end(); ++anEntIt) {
-    int aPos = Search(*anEntIt, myEntities);
-    if (aPos >= 0 && aPos < (int)myEntities.size()) {
-      // Remove entity 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)
-        removeParameter(anEntity.distance);
-      for (int i = 0; i < 4; i++)
-        if (anEntity.param[i] != SLVS_E_UNKNOWN)
-          removeParameter(anEntity.param[i]);
-      for (int i = 0; i < 4; i++)
-        if (anEntity.point[i] != SLVS_E_UNKNOWN)
-          removeEntity(anEntity.point[i]);
-////      myRemovedEntities.insert(*anEntIt);
-////      if (anEntity.type == SLVS_E_POINT_IN_2D || anEntity.type == SLVS_E_POINT_IN_3D)
-////        removeCoincidentPoint(*anEntIt);
-    }
-  }
-
-  if (!anUnusedEntities.empty())
-    myNeedToResolve = true;
-}
-
-bool SolveSpaceSolver_Storage::isUsedByConstraints(const Slvs_hEntity& theEntityID) const
-{
-  std::vector<Slvs_Constraint>::const_iterator aCIt = myConstraints.begin();
-  for (; aCIt != myConstraints.end(); ++aCIt) {
-    Slvs_hEntity aSubs[6] = {
-        aCIt->entityA, aCIt->entityB,
-        aCIt->entityC, aCIt->entityD,
-        aCIt->ptA,     aCIt->ptB};
-    for (int i = 0; i < 6; i++)
-      if (aSubs[i] != SLVS_E_UNKNOWN && aSubs[i] == theEntityID)
-        return true;
-  }
-  return false;
-}
-
-const Slvs_Entity& SolveSpaceSolver_Storage::getEntity(const Slvs_hEntity& theEntityID) const
-{
-  int aPos = Search(theEntityID, myEntities);
-  if (aPos >= 0 && aPos < (int)myEntities.size())
-    return myEntities[aPos];
-
-  // Entity is not found, return empty object
-  static Slvs_Entity aDummy;
-  aDummy.h = SLVS_E_UNKNOWN;
-  return aDummy;
-}
-
-Slvs_hEntity SolveSpaceSolver_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 SolveSpaceSolver_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++;
-    }
-  }
-}
-
-
-bool SolveSpaceSolver_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()) {
-////      aCoincident = *aCPIter;
-////      break;
-////    }
-
-  // Check whether one of coincident points is out-of-group
-  std::set<Slvs_hEntity>::const_iterator aCoincIt = aCoincident.begin();
-  for (; aCoincIt != aCoincident.end(); ++aCoincIt) {
-    Slvs_Entity aPoint = getEntity(*aCoincIt);
-    if (aPoint.group == SLVS_G_OUTOFGROUP)
-      return true;
-  }
-
-  // Search the Rigid constraint
-  theFixed = SLVS_C_UNKNOWN;
-  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()) {
-      theFixed = aConstrIter->h;
-      if (aConstrIter->ptA == thePointID)
-        return true;
-    }
-  if (theFixed != SLVS_C_UNKNOWN)
-    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 SolveSpaceSolver_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/Vertical/Horizontal and Length constraints
-    aList = getConstraintsByType(SLVS_C_PARALLEL);
-    aList.splice(aList.end(), getConstraintsByType(SLVS_C_PERPENDICULAR));
-    aList.splice(aList.end(), getConstraintsByType(SLVS_C_VERTICAL));
-    aList.splice(aList.end(), getConstraintsByType(SLVS_C_HORIZONTAL));
-    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 SolveSpaceSolver_Storage::addConstraint(const Slvs_Constraint& theConstraint)
-{
-  if (theConstraint.h > 0 && theConstraint.h <= myConstrMaxID) {
-    // Constraint is already used, rewrite it
-    return updateConstraint(theConstraint);
-  }
-
-  Slvs_Constraint aConstraint = theConstraint;
-
-  // Find a constraint with same type uses same arguments to show user overconstraint situation
-  std::vector<Slvs_Constraint>::iterator aCIt = myConstraints.begin();
-  for (; aCIt != myConstraints.end(); aCIt++) {
-    if (aConstraint.type != aCIt->type)
-      continue;
-    if (aConstraint.ptA == aCIt->ptA && aConstraint.ptB == aCIt->ptB &&
-        aConstraint.entityA == aCIt->entityA && aConstraint.entityB == aCIt->entityB &&
-        aConstraint.entityC == aCIt->entityC && aConstraint.entityD == aCIt->entityD)
-      myDuplicatedConstraint = true;
-  }
-
-  if (aConstraint.h > myConstrMaxID)
-    myConstrMaxID = aConstraint.h;
-  else
-    aConstraint.h = ++myConstrMaxID;
-  myConstraints.push_back(aConstraint);
-  myNeedToResolve = true;
-////  if (aConstraint.type == SLVS_C_POINTS_COINCIDENT)
-////    addCoincidentPoints(aConstraint.ptA, aConstraint.ptB);
-  return aConstraint.h;
-}
-
-Slvs_hConstraint SolveSpaceSolver_Storage::updateConstraint(const Slvs_Constraint& theConstraint)
-{
-  if (theConstraint.h > 0 && theConstraint.h <= myConstrMaxID) {
-    // Constraint already used, rewrite it
-    int aPos = Search(theConstraint.h, myConstraints);
-    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;
-    }
-  }
-
-  // Constraint is not found, add new one
-  Slvs_Constraint aConstraint = theConstraint;
-  aConstraint.h = 0;
-  return addConstraint(aConstraint);
-}
-
-bool SolveSpaceSolver_Storage::removeConstraint(const Slvs_hConstraint& theConstraintID)
-{
-  bool aResult = true;
-  int aPos = Search(theConstraintID, myConstraints);
-  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);
-////    if (aConstraint.type == SLVS_C_POINTS_COINCIDENT)
-////      removeCoincidence(aConstraint);
-
-    // Remove all entities
-    Slvs_hEntity anEntities[6] = {aConstraint.ptA, aConstraint.ptB,
-        aConstraint.entityA, aConstraint.entityB,
-        aConstraint.entityC, aConstraint.entityD};
-    for (int i = 0; i < 6; i++)
-      if (anEntities[i] != SLVS_E_UNKNOWN)
-        aResult = removeEntity(anEntities[i]) && aResult;
-    // remove temporary fixed point, if available
-    if (myFixed == theConstraintID)
-      myFixed = SLVS_E_UNKNOWN;
-    if (myDuplicatedConstraint) {
-      // Check the duplicated constraints are still available
-      myDuplicatedConstraint = false;
-      std::vector<Slvs_Constraint>::const_iterator anIt1 = myConstraints.begin();
-      std::vector<Slvs_Constraint>::const_iterator anIt2 = myConstraints.begin();
-      for (; anIt1 != myConstraints.end() && !myDuplicatedConstraint; anIt1++)
-        for (anIt2 = anIt1+1; anIt2 != myConstraints.end() && !myDuplicatedConstraint; anIt2++) {
-          if (anIt1->type != anIt2->type)
-            continue;
-          if (anIt1->ptA == anIt2->ptA && anIt1->ptB == anIt2->ptB &&
-              anIt1->entityA == anIt2->entityA && anIt1->entityB == anIt2->entityB &&
-              anIt1->entityC == anIt2->entityC && anIt1->entityD == anIt2->entityD)
-            myDuplicatedConstraint = true;
-        }
-    }
-  }
-////  else if (myRemovedConstraints.find(theConstraintID) != myRemovedConstraints.end())
-////    return true;
-  return aResult;
-}
-
-const Slvs_Constraint& SolveSpaceSolver_Storage::getConstraint(const Slvs_hConstraint& theConstraintID) const
-{
-  int aPos = Search(theConstraintID, myConstraints);
-  if (aPos >= 0 && aPos < (int)myConstraints.size())
-    return myConstraints[aPos];
-
-  // Constraint is not found, return empty object
-  static Slvs_Constraint aDummy;
-  aDummy.h = 0;
-  return aDummy;
-}
-
-std::list<Slvs_Constraint> SolveSpaceSolver_Storage::getConstraintsByType(int theConstraintType) const
-{
-  std::list<Slvs_Constraint> aResult;
-  std::vector<Slvs_Constraint>::const_iterator aCIter = myConstraints.begin();
-  for (; aCIter != myConstraints.end(); aCIter++)
-    if (aCIter->type == theConstraintType)
-      aResult.push_back(*aCIter);
-  return aResult;
-}
-
-
-void SolveSpaceSolver_Storage::addConstraintWhereDragged(const Slvs_hConstraint& theConstraintID)
-{
-  if (myFixed != SLVS_E_UNKNOWN)
-    return; // the point is already fixed
-  int aPos = Search(theConstraintID, myConstraints);
-  if (aPos >= 0 && aPos < (int)myConstraints.size())
-    myFixed = theConstraintID;
-}
-
-void SolveSpaceSolver_Storage::addTemporaryConstraint(const Slvs_hConstraint& theConstraintID)
-{
-  myTemporaryConstraints.insert(theConstraintID);
-}
-
-void SolveSpaceSolver_Storage::removeAllTemporary()
-{
-  myTemporaryConstraints.clear();
-}
-
-size_t SolveSpaceSolver_Storage::removeTemporary(size_t theNbConstraints)
-{
-  if (myTemporaryConstraints.empty())
-    return 0;
-  // Search the point-on-line or a non-rigid constraint
-  std::set<Slvs_hConstraint>::iterator aCIt = myTemporaryConstraints.begin();
-  for (; aCIt != myTemporaryConstraints.end(); aCIt++) {
-    int aPos = Search(*aCIt, myConstraints);
-    if (aPos >= (int)myConstraints.size() || myConstraints[aPos].type != SLVS_C_WHERE_DRAGGED)
-      break;
-    std::vector<Slvs_Constraint>::iterator anIt = myConstraints.begin();
-    for (; anIt != myConstraints.end(); anIt++)
-      if (anIt->type == SLVS_C_PT_ON_LINE && anIt->ptA == myConstraints[aPos].ptA)
-        break;
-    if (anIt != myConstraints.end())
-      break;
-  }
-  if (aCIt == myTemporaryConstraints.end())
-    aCIt = myTemporaryConstraints.begin();
-  bool aNewFixed = false;
-
-  size_t aNbRemain = theNbConstraints;
-  while (aNbRemain > 0 && aCIt != myTemporaryConstraints.end()) {
-    aNewFixed = aNewFixed || (*aCIt == myFixed);
-    --aNbRemain;
-
-    std::set<Slvs_hConstraint>::iterator aRemoveIt = aCIt++;
-    removeConstraint(*aRemoveIt);
-    myTemporaryConstraints.erase(aRemoveIt);
-    if (aCIt == myTemporaryConstraints.end())
-      aCIt = myTemporaryConstraints.begin();
-  }
-
-  if (aNewFixed) {
-    for (aCIt = myTemporaryConstraints.begin(); aCIt != myTemporaryConstraints.end(); aCIt++) {
-      int aPos = Search(*aCIt, myConstraints);
-      if (myConstraints[aPos].type == SLVS_C_WHERE_DRAGGED) {
-        myFixed = *aCIt;
-        break;
-      }
-    }
-  }
-  return myTemporaryConstraints.size();
-}
-
-bool SolveSpaceSolver_Storage::isTemporary(const Slvs_hConstraint& theConstraintID) const
-{
-  return myTemporaryConstraints.find(theConstraintID) != myTemporaryConstraints.end();
-}
-
-
-////void SolveSpaceSolver_Storage::getRemoved(
-////    std::set<Slvs_hParam>& theParameters,
-////    std::set<Slvs_hEntity>& theEntities,
-////    std::set<Slvs_hConstraint>& theConstraints)
-////{
-////  theParameters = myRemovedParameters;
-////  theEntities = myRemovedEntities;
-////  theConstraints = myRemovedConstraints;
-////
-////  myRemovedParameters.clear();
-////  myRemovedEntities.clear();
-////  myRemovedConstraints.clear();
-////}
-
-void SolveSpaceSolver_Storage::initializeSolver(SolverPtr theSolver)
-{
-  std::shared_ptr<SolveSpaceSolver_Solver> aSolver =
-      std::dynamic_pointer_cast<SolveSpaceSolver_Solver>(theSolver);
-  if (!aSolver)
-    return;
-
-  if (myConstraints.empty()) {
-    // Adjust all arc to place their points correctly
-    std::vector<Slvs_Entity>::const_iterator anEntIt = myEntities.begin();
-    for (; anEntIt != myEntities.end(); ++anEntIt)
-      if (anEntIt->type == SLVS_E_ARC_OF_CIRCLE)
-        adjustArc(*anEntIt);
-  }
-
-  aSolver->setParameters(myParameters.data(), (int)myParameters.size());
-  aSolver->setEntities(myEntities.data(), (int)myEntities.size());
-
-  // 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);
-    aSolver->setDraggedParameters(myEntities[aPos].param);
-  }
-  aSolver->setConstraints(aConstraints.data(), (int)aConstraints.size());
-}
-
-////void SolveSpaceSolver_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;
-////      } else
-////        aFoundIter = aCIter;
-////      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 SolveSpaceSolver_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;
-////    }
-////}
-////
-////void SolveSpaceSolver_Storage::removeCoincidence(const Slvs_Constraint& theCoincidence)
-////{
-////  // Find set of coincident points
-////  std::vector< std::set<Slvs_hEntity> >::iterator aCIt = myCoincidentPoints.begin();
-////  for (; aCIt != myCoincidentPoints.end(); ++aCIt)
-////    if (aCIt->find(theCoincidence.ptA) != aCIt->end() ||
-////        aCIt->find(theCoincidence.ptB) != aCIt->end())
-////      break;
-////  if (aCIt == myCoincidentPoints.end())
-////    return;
-////
-////  // Leave only the points which are still coincident
-////  std::set<Slvs_hEntity> aRemainCoincidence;
-////  std::vector<Slvs_Constraint>::const_iterator aConstrIt = myConstraints.begin();
-////  for (; aConstrIt != myConstraints.end(); ++aConstrIt) {
-////    if (aConstrIt->type != SLVS_C_POINTS_COINCIDENT)
-////      continue;
-////    if (aCIt->find(aConstrIt->ptA) != aCIt->end() ||
-////        aCIt->find(aConstrIt->ptB) != aCIt->end()) {
-////      aRemainCoincidence.insert(aConstrIt->ptA);
-////      aRemainCoincidence.insert(aConstrIt->ptB);
-////    }
-////  }
-////  if (aRemainCoincidence.size() <= 1)
-////    myCoincidentPoints.erase(aCIt);
-////  else
-////    aCIt->swap(aRemainCoincidence);
-////}
-////
-////bool SolveSpaceSolver_Storage::isCoincident(
-////    const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const
-////{
-////  std::vector< std::set<Slvs_hEntity> >::const_iterator aCIter = myCoincidentPoints.begin();
-////  for (; aCIter != myCoincidentPoints.end(); aCIter++)
-////    if (aCIter->find(thePoint1) != aCIter->end() && aCIter->find(thePoint2) != aCIter->end())
-////      return true;
-////  return false;
-////}
-
-bool SolveSpaceSolver_Storage::isEqual(
-    const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const
-{
-////  if (isCoincident(thePoint1, thePoint2))
-////    return true;
-
-  // Precise checking of coincidence: verify that points have equal coordinates
-  int aEnt1Pos = Search(thePoint1, myEntities);
-  int aEnt2Pos = Search(thePoint2, myEntities);
-  if (aEnt1Pos >= 0 && aEnt1Pos < (int)myEntities.size() &&
-      aEnt2Pos >= 0 && aEnt2Pos < (int)myEntities.size()) {
-    double aDist[2];
-    int aParamPos;
-    for (int i = 0; i < 2; i++) {
-      aParamPos = Search(myEntities[aEnt1Pos].param[i], myParameters);
-      aDist[i] = myParameters[aParamPos].val;
-      aParamPos = Search(myEntities[aEnt2Pos].param[i], myParameters);
-      aDist[i] -= myParameters[aParamPos].val;
-    }
-    if (aDist[0] * aDist[0] + aDist[1] * aDist[1] < tolerance * tolerance)
-      return true;
-  }
-  return false;
-}
-
-
-std::vector<Slvs_hConstraint> SolveSpaceSolver_Storage::fixEntity(const Slvs_hEntity& theEntity)
-{
-  std::vector<Slvs_hConstraint> aNewConstraints;
-
-  int aPos = Search(theEntity, myEntities);
-  if (aPos >= 0 && aPos < (int)myEntities.size()) {
-    switch (myEntities[aPos].type) {
-    case SLVS_E_POINT_IN_2D:
-    case SLVS_E_POINT_IN_3D:
-      fixPoint(myEntities[aPos], aNewConstraints);
-      break;
-    case SLVS_E_LINE_SEGMENT:
-      fixLine(myEntities[aPos], aNewConstraints);
-      break;
-    case SLVS_E_CIRCLE:
-      fixCircle(myEntities[aPos], aNewConstraints);
-      break;
-    case SLVS_E_ARC_OF_CIRCLE:
-      fixArc(myEntities[aPos], aNewConstraints);
-      break;
-    default:
-      break;
-    }
-  }
-
-  return aNewConstraints;
-}
-
-void SolveSpaceSolver_Storage::fixPoint(const Slvs_Entity& thePoint,
-    std::vector<Slvs_hConstraint>& theCreated)
-{
-  Slvs_Constraint aConstraint;
-  Slvs_hConstraint aConstrID = SLVS_E_UNKNOWN;
-  bool isFixed = isPointFixed(thePoint.h, aConstrID, true);
-  bool isForceUpdate = (isFixed && isTemporary(aConstrID));
-  if (!isForceUpdate) { // create new constraint
-    if (isFixed) return;
-    aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, thePoint.group, SLVS_C_WHERE_DRAGGED, thePoint.wrkpl,
-        0.0, thePoint.h, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-    aConstraint.h = addConstraint(aConstraint);
-    theCreated.push_back(aConstraint.h);
-  } else { // update already existent constraint
-    if (!isFixed || aConstrID == SLVS_E_UNKNOWN)
-      return;
-    int aPos = Search(aConstrID, myConstraints);
-    if (aPos >= 0 && aPos < (int)myConstraints.size())
-      myConstraints[aPos].ptA = thePoint.h;
-  }
-}
-
-void SolveSpaceSolver_Storage::fixLine(const Slvs_Entity& theLine,
-    std::vector<Slvs_hConstraint>& theCreated)
-{
-  Slvs_Entity aPoint[2] = {
-      getEntity(theLine.point[0]),
-      getEntity(theLine.point[1])
-  };
-
-  Slvs_Constraint anEqual;
-  if (isAxisParallel(theLine.h)) {
-    // Fix one point and a line length
-    Slvs_hConstraint aFixed;
-    if (!isPointFixed(theLine.point[0], aFixed, true) &&
-        !isPointFixed(theLine.point[1], aFixed, true))
-      fixPoint(aPoint[0], theCreated);
-    if (!isUsedInEqual(theLine.h, anEqual)) {
-      // Check the distance is not set yet
-      std::vector<Slvs_Constraint>::const_iterator aDistIt = myConstraints.begin();
-      for (; aDistIt != myConstraints.end(); ++aDistIt)
-        if ((aDistIt->type == SLVS_C_PT_PT_DISTANCE) &&
-           ((aDistIt->ptA == theLine.point[0] && aDistIt->ptB == theLine.point[1]) ||
-            (aDistIt->ptA == theLine.point[1] && aDistIt->ptB == theLine.point[0])))
-          return;
-      // Calculate distance between points on the line
-      double aCoords[4];
-      for (int i = 0; i < 2; i++)
-        for (int j = 0; j < 2; j++) {
-          Slvs_Param aParam = getParameter(aPoint[i].param[j]);
-          aCoords[2*i+j] = aParam.val;
-        }
-
-      double aLength = sqrt((aCoords[2] - aCoords[0]) * (aCoords[2] - aCoords[0]) + 
-                            (aCoords[3] - aCoords[1]) * (aCoords[3] - aCoords[1]));
-      // fix line length
-      Slvs_Constraint aDistance = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theLine.group,
-          SLVS_C_PT_PT_DISTANCE, theLine.wrkpl, aLength,
-          theLine.point[0], theLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-      aDistance.h = addConstraint(aDistance);
-      theCreated.push_back(aDistance.h);
-    }
-    return;
-  }
-  else if (isUsedInEqual(theLine.h, anEqual)) {
-    // Check another entity of Equal is already fixed
-    Slvs_hEntity anOtherEntID = anEqual.entityA == theLine.h ? anEqual.entityB : anEqual.entityA;
-    if (isEntityFixed(anOtherEntID, true)) {
-      // Fix start point of the line (if end point is not fixed yet) ...
-      Slvs_hConstraint anEndFixedID = SLVS_E_UNKNOWN;
-      bool isFixed = isPointFixed(theLine.point[1], anEndFixedID, true);
-      if (isFixed == SLVS_E_UNKNOWN)
-        fixPoint(aPoint[0], theCreated);
-      // ...  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::vector<Slvs_Constraint>::const_iterator aPLIter = myConstraints.begin();
-      for (; aPLIter != myConstraints.end() && !isPonLineFixed; ++aPLIter)
-        if (aPLIter->type == SLVS_C_PT_ON_LINE && aPLIter->entityA == theLine.h) {
-          isPonLineFixed = isPointFixed(aPLIter->ptA, anEndFixedID);
-          aFixedPoint = aPLIter->ptA;
-        }
-
-      if (isPonLineFixed) { // update existent constraint
-        copyEntity(aPointToCopy, aFixedPoint);
-      } else { // create new constraint
-        Slvs_hEntity aCopied = copyEntity(aPointToCopy);
-        Slvs_Constraint aPonLine = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theLine.group, SLVS_C_PT_ON_LINE,
-            theLine.wrkpl, 0.0, aCopied, SLVS_E_UNKNOWN, theLine.h, SLVS_E_UNKNOWN);
-        aPonLine.h = addConstraint(aPonLine);
-        theCreated.push_back(aPonLine.h);
-        fixPoint(getEntity(aCopied), theCreated);
-      }
-      return;
-    }
-  }
-
-  // Fix both points
-  for (int i = 0; i < 2; i++)
-    fixPoint(aPoint[i], theCreated);
-}
-
-void SolveSpaceSolver_Storage::fixCircle(const Slvs_Entity& theCircle,
-    std::vector<Slvs_hConstraint>& theCreated)
-{
-  bool isFixRadius = true;
-  // Verify the arc is under Equal constraint
-  Slvs_Constraint anEqual;
-  if (isUsedInEqual(theCircle.h, anEqual)) {
-    // Check another entity of Equal is already fixed
-    Slvs_hEntity anOtherEntID = anEqual.entityA == theCircle.h ? anEqual.entityB : anEqual.entityA;
-    if (isEntityFixed(anOtherEntID, true))
-      isFixRadius = false;
-  }
-
-  fixPoint(getEntity(theCircle.point[0]), theCreated);
-
-  if (isFixRadius) {
-    // Search the radius is already fixed
-    std::vector<Slvs_Constraint>::const_iterator aDiamIter = myConstraints.begin();
-    for (; aDiamIter != myConstraints.end(); ++aDiamIter)
-      if (aDiamIter->type == SLVS_C_DIAMETER && aDiamIter->entityA == theCircle.h)
-        return;
-
-    // Fix radius of a circle
-    const Slvs_Entity& aRadEnt = getEntity(theCircle.distance);
-    double aRadius = getParameter(aRadEnt.param[0]).val;
-    Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theCircle.group, SLVS_C_DIAMETER,
-        theCircle.wrkpl, aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, theCircle.h, SLVS_E_UNKNOWN);
-    aFixedR.h = addConstraint(aFixedR);
-    theCreated.push_back(aFixedR.h);
-  }
-}
-
-void SolveSpaceSolver_Storage::fixArc(const Slvs_Entity& theArc,
-    std::vector<Slvs_hConstraint>& theCreated)
-{
-  Slvs_Entity aPoint[3] = {
-      getEntity(theArc.point[0]),
-      getEntity(theArc.point[1]),
-      getEntity(theArc.point[2])
-  };
-
-  bool isFixRadius = true;
-  std::list<Slvs_Entity> aPointsToFix;
-  aPointsToFix.push_back(aPoint[1]);
-  aPointsToFix.push_back(aPoint[2]);
-
-  // Verify the arc is under Equal constraint
-  Slvs_Constraint anEqual;
-  if (isUsedInEqual(theArc.h, anEqual)) {
-    // Check another entity of Equal is already fixed
-    Slvs_hEntity anOtherEntID = anEqual.entityA == theArc.h ? anEqual.entityB : anEqual.entityA;
-    if (isEntityFixed(anOtherEntID, true)) {
-      isFixRadius = false;
-      Slvs_Entity anOtherEntity = getEntity(anOtherEntID);
-      if (anOtherEntity.type == SLVS_E_LINE_SEGMENT) {
-        aPointsToFix.pop_back();
-        aPointsToFix.push_back(aPoint[0]);
-      }
-    }
-  }
-
-  Slvs_hConstraint aConstrID;
-  int aNbPointsToFix = 2; // number of fixed points for the arc
-  if (isPointFixed(theArc.point[0], aConstrID, true))
-    aNbPointsToFix--;
-
-  double anArcPoints[3][2];
-  for (int i = 0; i < 3; i++) {
-    const Slvs_Entity& aPointOnArc = getEntity(theArc.point[i]);
-    for (int j = 0; j < 2; j++)
-      anArcPoints[i][j] = getParameter(aPointOnArc.param[j]).val;
-  }
-
-  // Radius of the arc
-  std::shared_ptr<GeomAPI_Pnt2d> aCenter(new GeomAPI_Pnt2d(anArcPoints[0][0], anArcPoints[0][1]));
-  std::shared_ptr<GeomAPI_Pnt2d> aStart(new GeomAPI_Pnt2d(anArcPoints[1][0], anArcPoints[1][1]));
-  double aRadius = aCenter->distance(aStart);
-
-  // Update end point of the arc to be on a curve
-  std::shared_ptr<GeomAPI_Pnt2d> anEnd(new GeomAPI_Pnt2d(anArcPoints[2][0], anArcPoints[2][1]));
-  double aDistance = anEnd->distance(aCenter);
-  std::shared_ptr<GeomAPI_XY> aDir = anEnd->xy()->decreased(aCenter->xy());
-  if (aDistance < tolerance)
-    aDir = aStart->xy()->decreased(aCenter->xy())->multiplied(-1.0);
-  else
-    aDir = aDir->multiplied(aRadius / aDistance);
-  double xy[2] = {aCenter->x() + aDir->x(), aCenter->y() + aDir->y()};
-  const Slvs_Entity& aEndPoint = getEntity(theArc.point[2]);
-  for (int i = 0; i < 2; i++) {
-    Slvs_Param aParam = getParameter(aEndPoint.param[i]);
-    aParam.val = xy[i];
-    updateParameter(aParam);
-  }
-
-  std::list<Slvs_Entity>::iterator aPtIt = aPointsToFix.begin();
-  for (; aNbPointsToFix > 0; aPtIt++, aNbPointsToFix--)
-    fixPoint(*aPtIt, theCreated);
-
-  if (isFixRadius) {
-    // Fix radius of the arc
-    bool isExists = false;
-    std::vector<Slvs_Constraint>::iterator anIt = myConstraints.begin();
-    for (; anIt != myConstraints.end() && !isExists; ++anIt)
-      if (anIt->type == SLVS_C_DIAMETER && anIt->entityA == theArc.h)
-        isExists = true;
-    if (!isExists) {
-      Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theArc.group, SLVS_C_DIAMETER,
-          theArc.wrkpl, aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, theArc.h, SLVS_E_UNKNOWN);
-      aFixedR.h = addConstraint(aFixedR);
-      theCreated.push_back(aFixedR.h);
-    }
-  }
-}
-
-
-bool SolveSpaceSolver_Storage::isAxisParallel(const Slvs_hEntity& theEntity) const
-{
-  std::vector<Slvs_Constraint>::const_iterator anIter = myConstraints.begin();
-  for (; anIter != myConstraints.end(); anIter++)
-    if ((anIter->type == SLVS_C_HORIZONTAL || anIter->type == SLVS_C_VERTICAL) && 
-        anIter->entityA == theEntity)
-      return true;
-  return false;
-}
-
-bool SolveSpaceSolver_Storage::isUsedInEqual(
-    const Slvs_hEntity& theEntity, Slvs_Constraint& theEqual) const
-{
-  // Check the entity is used in Equal constraint
-  std::vector<Slvs_Constraint>::const_iterator anEqIter = myConstraints.begin();
-  for (; anEqIter != myConstraints.end(); anEqIter++)
-    if ((anEqIter->type == SLVS_C_EQUAL_LENGTH_LINES ||
-         anEqIter->type == SLVS_C_EQUAL_LINE_ARC_LEN ||
-         anEqIter->type == SLVS_C_EQUAL_RADIUS) &&
-       (anEqIter->entityA == theEntity || anEqIter->entityB == theEntity)) {
-      theEqual = *anEqIter;
-      return true;
-    }
-  return false;
-}
-
-////bool SolveSpaceSolver_Storage::isNeedToResolve()
-////{
-////  if (myConstraints.empty())
-////    return false;
-////
-////  if (!myNeedToResolve) {
-////    // Verify the updated parameters are used in constraints
-////    std::set<Slvs_hEntity> aPoints;
-////    std::vector<Slvs_Entity>::const_iterator anEntIt = myEntities.begin();
-////    for (; anEntIt != myEntities.end(); ++anEntIt) {
-////      for (int i = 0; i < 4 && anEntIt->param[i] != SLVS_E_UNKNOWN; ++i)
-////        if (myUpdatedParameters.find(anEntIt->param[i]) != myUpdatedParameters.end()) {
-////          aPoints.insert(anEntIt->h);
-////          break;
-////        }
-////    }
-////    std::set<Slvs_hEntity> anEntities = aPoints;
-////    for (anEntIt = myEntities.begin(); anEntIt != myEntities.end(); ++anEntIt) {
-////      for (int i = 0; i < 4 && anEntIt->point[i] != SLVS_E_UNKNOWN; ++i)
-////        if (aPoints.find(anEntIt->point[i]) != aPoints.end()) {
-////          anEntities.insert(anEntIt->h);
-////          break;
-////        }
-////    }
-////
-////    std::vector<Slvs_Constraint>::const_iterator aCIt = myConstraints.begin();
-////    for (; aCIt != myConstraints.end() && !myNeedToResolve; ++aCIt) {
-////      Slvs_hEntity anAttrs[6] =
-////        {aCIt->ptA, aCIt->ptB, aCIt->entityA, aCIt->entityB, aCIt->entityC, aCIt->entityD};
-////      for (int i = 0; i < 6; i++)
-////        if (anAttrs[i] != SLVS_E_UNKNOWN && anEntities.find(anAttrs[i]) != anEntities.end()) {
-////          myNeedToResolve = true;
-////          break;
-////        }
-////    }
-////  }
-////
-////  myUpdatedParameters.clear();
-////  return myNeedToResolve;
-////}
-
-void SolveSpaceSolver_Storage::setTemporary(ConstraintPtr theConstraint)
-{
-  // TODO
-}
-
-bool SolveSpaceSolver_Storage::removeConstraint(ConstraintPtr theConstraint)
-{
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
-      aFound = myConstraintMap.find(theConstraint);
-  if (aFound == myConstraintMap.end())
-    return true; // no constraint, already deleted
-
-  // Remove constraint
-  std::list<ConstraintWrapperPtr> aConstrList = aFound->second;
-  myConstraintMap.erase(aFound);
-  // Remove SolveSpace constraints
-  bool isFullyRemoved = true;
-  std::list<ConstraintWrapperPtr>::iterator anIt = aConstrList.begin();
-  while (anIt != aConstrList.end()) {
-    if (remove(*anIt)) {
-      std::list<ConstraintWrapperPtr>::iterator aRemoveIt = anIt++;
-      aConstrList.erase(aRemoveIt);
-    } else {
-      isFullyRemoved = false;
-      ++anIt;
-    }
-  }
-  if (!isFullyRemoved)
-    myConstraintMap[theConstraint] = aConstrList;
-  return isFullyRemoved;
-}
-
-template <class ENT_TYPE>
-static bool isUsed(ConstraintWrapperPtr theConstraint, ENT_TYPE theEntity)
-{
-  std::list<EntityWrapperPtr>::const_iterator anEntIt = theConstraint->entities().begin();
-  for (; anEntIt != theConstraint->entities().end(); ++anEntIt)
-    if (std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anEntIt)->isBase(theEntity))
-      return true;
-  return false;
-}
-
-static bool isUsed(EntityWrapperPtr theFeature, AttributePtr theSubEntity)
-{
-  std::list<EntityWrapperPtr>::const_iterator aSubIt = theFeature->subEntities().begin();
-  for (; aSubIt != theFeature->subEntities().end(); ++aSubIt)
-    if (std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*aSubIt)->isBase(theSubEntity))
-      return true;
-  return false;
-}
-
-bool SolveSpaceSolver_Storage::isUsed(FeaturePtr theFeature) const
-{
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
-      aCIt = myConstraintMap.begin();
-  std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
-  for (; aCIt != myConstraintMap.end(); ++aCIt)
-    for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
-      if (::isUsed(*aCWIt, theFeature))
-        return true;
-  // check attributes
-  std::list<AttributePtr> anAttrList = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
-  std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
-  for (; anIt != anAttrList.end(); ++anIt)
-    if (isUsed(*anIt))
-      return true;
-  return false;
-}
-
-bool SolveSpaceSolver_Storage::isUsed(AttributePtr theAttribute) const
-{
-  AttributePtr anAttribute = theAttribute;
-  AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
-  if (aRefAttr) {
-    if (aRefAttr->isObject())
-      return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
-    else
-      anAttribute = aRefAttr->attr();
-  }
-
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
-      aCIt = myConstraintMap.begin();
-  std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
-  for (; aCIt != myConstraintMap.end(); ++aCIt)
-    for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
-      if (::isUsed(*aCWIt, anAttribute))
-        return true;
-  return false;
-}
-
-
-bool SolveSpaceSolver_Storage::removeEntity(FeaturePtr theFeature)
-{
-  std::map<FeaturePtr, EntityWrapperPtr>::iterator aFound = myFeatureMap.find(theFeature);
-  if (aFound == myFeatureMap.end())
-    return false; // feature not found, nothing to delete
-
-  // Check the feature is not used by constraints
-  if (isUsed(theFeature))
-    return false; // the feature is used, don't remove it
-
-  // Remove feature
-  EntityWrapperPtr anEntity = aFound->second;
-  myFeatureMap.erase(aFound);
-  if (remove(anEntity))
-    return true;
-  // feature is not removed, revert operation
-  myFeatureMap[theFeature] = anEntity;
-  return false;
-}
-
-bool SolveSpaceSolver_Storage::removeEntity(AttributePtr theAttribute)
-{
-  std::map<AttributePtr, EntityWrapperPtr>::iterator aFound = myAttributeMap.find(theAttribute);
-  if (aFound == myAttributeMap.end())
-    return false; // attribute not found, nothing to delete
-
-  // Check the attribute is not used by constraints
-  if (isUsed(theAttribute))
-    return false; // the attribute is used, don't remove it
-  // Check the attribute is not used by other features
-  std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
-  for (; aFIt != myFeatureMap.end(); ++aFIt)
-    if (::isUsed(aFIt->second, theAttribute)) // the attribute is used, don't remove it
-      return false;
-
-  // Remove attribute
-  EntityWrapperPtr anEntity = aFound->second;
-  myAttributeMap.erase(aFound);
-  if (remove(anEntity))
-    return true;
-  // attribute is not removed, revert operation
-  myAttributeMap[theAttribute] = anEntity;
-  return false;
-}
-
-
-bool SolveSpaceSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
-{
-  std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
-      std::dynamic_pointer_cast<SolveSpaceSolver_ConstraintWrapper>(theConstraint);
-
-  // verify whether the constraint has duplicated
-  SameConstraintMap::iterator anEqIt = myEqualConstraints.begin();
-  for (; anEqIt != myEqualConstraints.end(); ++anEqIt)
-    if (anEqIt->find(aConstraint) != anEqIt->end()) {
-      anEqIt->erase(aConstraint);
-      break;
-    }
-  if (anEqIt != myEqualConstraints.end())
-    return true;
-
-  bool isFullyRemoved = removeConstraint((Slvs_hConstraint)aConstraint->id());
-
-  std::list<EntityWrapperPtr>::const_iterator anIt = aConstraint->entities().begin();
-  for (; anIt != aConstraint->entities().end(); ++anIt) {
-    std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity = 
-        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anIt);
-    FeaturePtr aBaseFeature = anEntity->baseFeature();
-    if (aBaseFeature)
-      isFullyRemoved = removeEntity(aBaseFeature) && isFullyRemoved;
-    else
-      isFullyRemoved = removeEntity(anEntity->baseAttribute()) && isFullyRemoved;
-  }
-
-  return isFullyRemoved;
-}
-
-bool SolveSpaceSolver_Storage::remove(EntityWrapperPtr theEntity)
-{
-  std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity = 
-        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theEntity);
-  bool isFullyRemoved = removeEntity((Slvs_hEntity)anEntity->id());
-
-  std::list<EntityWrapperPtr>::const_iterator anEntIt = anEntity->subEntities().begin();
-  for (; anEntIt != anEntity->subEntities().end(); ++anEntIt) {
-    std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSubEntity = 
-        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anEntIt);
-    FeaturePtr aBaseFeature = aSubEntity->baseFeature();
-    if (aBaseFeature)
-      isFullyRemoved = removeEntity(aBaseFeature) && isFullyRemoved;
-    else
-      isFullyRemoved = removeEntity(aSubEntity->baseAttribute()) && isFullyRemoved;
-  }
-
-  std::list<ParameterWrapperPtr>::const_iterator aParIt = anEntity->parameters().begin();
-  for (; aParIt != anEntity->parameters().end(); ++aParIt)
-    isFullyRemoved = remove(*aParIt) && isFullyRemoved;
-  return isFullyRemoved;
-}
-
-bool SolveSpaceSolver_Storage::remove(ParameterWrapperPtr theParameter)
-{
-  return removeParameter((Slvs_hParam)theParameter->id());
-}
-
-
-void SolveSpaceSolver_Storage::refresh(bool theFixedOnly) const
-{
-  blockEvents(true);
-
-  std::map<AttributePtr, EntityWrapperPtr>::const_iterator anIt = myAttributeMap.begin();
-  std::list<ParameterWrapperPtr> aParams;
-  std::list<ParameterWrapperPtr>::const_iterator aParIt;
-  for (; anIt != myAttributeMap.end(); ++anIt) {
-    // update parameter wrappers and obtain values of attributes
-    aParams = anIt->second->parameters();
-    double aCoords[3];
-    bool isUpd[3] = {false};
-    int i = 0;
-    for (aParIt = aParams.begin(); i < 3 && aParIt != aParams.end(); ++aParIt, ++i) {
-      std::shared_ptr<SolveSpaceSolver_ParameterWrapper> aWrapper = 
-          std::dynamic_pointer_cast<SolveSpaceSolver_ParameterWrapper>(*aParIt);
-      if (!theFixedOnly || aWrapper->group() == GID_OUTOFGROUP || aWrapper->isParametric()) {
-        aWrapper->changeParameter().val = getParameter((Slvs_hParam)aWrapper->id()).val;
-        aCoords[i] = aWrapper->value();
-        isUpd[i] = true;
-      }
-    }
-    if (!isUpd[0] && !isUpd[1] && !isUpd[2])
-      continue; // nothing is updated
-
-    std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
-        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anIt->first);
-    if (aPoint2D) {
-      if ((isUpd[0] && fabs(aPoint2D->x() - aCoords[0]) > tolerance) ||
-          (isUpd[1] && fabs(aPoint2D->y() - aCoords[1]) > tolerance)) {
-        if (!isUpd[0]) aCoords[0] = aPoint2D->x();
-        if (!isUpd[1]) aCoords[1] = aPoint2D->y();
-        aPoint2D->setValue(aCoords[0], aCoords[1]);
-      }
-      continue;
-    }
-    AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anIt->first);
-    if (aScalar) {
-      if (isUpd[0] && fabs(aScalar->value() - aCoords[0]) > tolerance)
-        aScalar->setValue(aCoords[0]);
-      continue;
-    }
-    std::shared_ptr<GeomDataAPI_Point> aPoint =
-        std::dynamic_pointer_cast<GeomDataAPI_Point>(anIt->first);
-    if (aPoint) {
-      if ((isUpd[0] && fabs(aPoint->x() - aCoords[0]) > tolerance) ||
-          (isUpd[1] && fabs(aPoint->y() - aCoords[1]) > tolerance) ||
-          (isUpd[2] && fabs(aPoint->z() - aCoords[2]) > tolerance))
-        if (!isUpd[0]) aCoords[0] = aPoint->x();
-        if (!isUpd[1]) aCoords[1] = aPoint->y();
-        if (!isUpd[2]) aCoords[2] = aPoint->z();
-        aPoint->setValue(aCoords[0], aCoords[1], aCoords[2]);
-      continue;
-    }
-  }
-
-  blockEvents(false);
-}
-
-void SolveSpaceSolver_Storage::verifyFixed()
-{
-  std::map<AttributePtr, EntityWrapperPtr>::iterator anAttrIt = myAttributeMap.begin();
-  for (; anAttrIt != myAttributeMap.end(); ++anAttrIt) {
-    const std::list<ParameterWrapperPtr>& aParameters = anAttrIt->second->parameters();
-    std::list<ParameterWrapperPtr>::const_iterator aParIt = aParameters.begin();
-    for (; aParIt != aParameters.end(); ++aParIt)
-      if ((*aParIt)->group() == GID_OUTOFGROUP) {
-        Slvs_Param aParam = getParameter((Slvs_hParam)(*aParIt)->id());
-        if (aParam.group != (Slvs_hParam)GID_OUTOFGROUP) {
-          aParam.group = (Slvs_hParam)GID_OUTOFGROUP;
-          updateParameter(aParam);
-        }
-      }
-  }
-}
-
-
-void SolveSpaceSolver_Storage::adjustArc(const Slvs_Entity& theArc)
-{
-  double anArcPoints[3][2];
-  double aDist[3] = {0.0};
-  bool isFixed[3] = {false};
-  for (int i = 0; i < 3; ++i) {
-    Slvs_Entity aPoint = getEntity(theArc.point[i]);
-    isFixed[i] = (aPoint.group != (Slvs_hGroup)myGroupID);
-    anArcPoints[i][0] = getParameter(aPoint.param[0]).val;
-    anArcPoints[i][1] = getParameter(aPoint.param[1]).val;
-    if (i > 0) {
-      anArcPoints[i][0] -= anArcPoints[0][0];
-      anArcPoints[i][1] -= anArcPoints[0][1];
-      aDist[i] = sqrt(anArcPoints[i][0] * anArcPoints[i][0] + 
-                      anArcPoints[i][1] * anArcPoints[i][1]);
-    }
-  }
-
-  if (fabs(aDist[1] - aDist[2]) < tolerance)
-    return;
-
-  int anInd = 2;
-  while (anInd > 0 && isFixed[anInd])
-    --anInd;
-  if (anInd < 1)
-    return; // adjust only start or end point of the arc
-
-  anArcPoints[anInd][0] /= aDist[anInd];
-  anArcPoints[anInd][1] /= aDist[anInd];
-
-  Slvs_Entity aPoint = getEntity(theArc.point[anInd]);
-  for (int i = 0; i < 2; ++i) {
-    Slvs_Param aParam = getParameter(aPoint.param[i]);
-    aParam.val = anArcPoints[0][i] + aDist[3-anInd] * anArcPoints[anInd][i];
-    updateParameter(aParam);
-  }
-}
-
-
-
-
-
-
-
-// ========================================================
-// =========      Auxiliary functions       ===============
-// ========================================================
-
-template<typename T>
-int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities)
-{
-  int aResIndex = theEntityID <= theEntities.size() ? theEntityID - 1 : 0;
-  int aVecSize = theEntities.size();
-  if (theEntities.empty())
-    return 1;
-  while (aResIndex >= 0 && theEntities[aResIndex].h > theEntityID)
-    aResIndex--;
-  while (aResIndex < aVecSize && aResIndex >= 0 && theEntities[aResIndex].h < theEntityID)
-    aResIndex++;
-  if (aResIndex == -1 || (aResIndex < aVecSize && theEntities[aResIndex].h != theEntityID))
-    aResIndex = aVecSize;
-  return aResIndex;
-}
-
-bool IsNotEqual(const Slvs_Param& theParam1, const Slvs_Param& theParam2)
-{
-  return fabs(theParam1.val - theParam2.val) > tolerance;
-}
-
-bool IsNotEqual(const Slvs_Entity& theEntity1, const Slvs_Entity& theEntity2)
-{
-  int i = 0;
-  for (; theEntity1.param[i] != 0 && i < 4; i++)
-    if (theEntity1.param[i] != theEntity2.param[i])
-      return true;
-  i = 0;
-  for (; theEntity1.point[i] != 0 && i < 4; i++)
-    if (theEntity1.point[i] != theEntity2.point[i])
-      return true;
-  return false;
-}
-
-bool IsNotEqual(const Slvs_Constraint& theConstraint1, const Slvs_Constraint& theConstraint2)
-{
-  return theConstraint1.ptA != theConstraint2.ptA ||
-         theConstraint1.ptB != theConstraint2.ptB ||
-         theConstraint1.entityA != theConstraint2.entityA ||
-         theConstraint1.entityB != theConstraint2.entityB ||
-         theConstraint1.entityC != theConstraint2.entityC ||
-         theConstraint1.entityD != theConstraint2.entityD ||
-         fabs(theConstraint1.valA - theConstraint2.valA) > tolerance;
-}
diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.h b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.h
deleted file mode 100644 (file)
index 015ada9..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SolveSpaceSolver_Storage.h
-// Created: 18 Mar 2015
-// Author:  Artem ZHIDKOV
-
-#ifndef SolveSpaceSolver_Storage_H_
-#define SolveSpaceSolver_Storage_H_
-
-#include <SketchSolver_Storage.h>
-#include <SolveSpaceSolver_Solver.h>
-
-#include <list>
-#include <memory>
-#include <set>
-#include <vector>
-
-typedef std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> > CoincidentPointsMap;
-typedef std::list< std::set<ConstraintWrapperPtr> >             SameConstraintMap;
-
-/** \class   SolveSpaceSolver_Storage
- *  \ingroup Plugins
- *  \brief   Contains all necessary data in SolveSpace format to solve a single group of constraints
- */
-class SolveSpaceSolver_Storage : public SketchSolver_Storage
-{
-public:
-  SolveSpaceSolver_Storage(const GroupID& theGroup);
-
-// =============   Inherited from SketchSolver_Storage   =============
-
-  /// \brief Update constraint's data
-  /// \return \c true if any value is updated
-  virtual bool update(ConstraintWrapperPtr& theConstraint);
-  /// \brief Update entity's data
-  /// \return \c true if any value is updated
-  virtual bool update(EntityWrapperPtr& theEntity);
-  /// \brief Update parameter's data
-  /// \return \c true if the value of parameter is updated
-  virtual bool update(ParameterWrapperPtr& theParameter);
-
-  /// \brief Removes constraint from the storage
-  /// \return \c true if the constraint and all its parameters are remove successfully
-  virtual bool removeConstraint(ConstraintPtr theConstraint);
-  /// \brief Removes feature from the storage
-  /// \return \c true if the feature and its attributes are removed successfully;
-  ///         \c false if the feature or any it attribute is used by remaining constraints.
-  virtual bool removeEntity(FeaturePtr theFeature);
-  /// \brief Removes attribute from the storage
-  /// \return \c true if the attribute is not used by remaining features and constraints
-  virtual bool removeEntity(AttributePtr theAttribute);
-
-  /// \brief Update SketchPlugin features after resolving constraints
-  /// \param theFixedOnly [in]  if \c true the fixed points will be updated only
-  virtual void refresh(bool theFixedOnly = false) const;
-
-  /// \brief Check if some parameters or entities are returned
-  ///        to the current group after removing temporary constraints
-  virtual void verifyFixed();
-
-  /// \brief Mark two points as coincident
-  virtual void addCoincidentPoints(EntityWrapperPtr theMaster, EntityWrapperPtr theSlave);
-
-  /// \brief Calculate point on theBase entity. Value theCoeff is in [0.0 .. 1.0] and
-  ///        shows the distance from the start point.
-  virtual EntityWrapperPtr calculateMiddlePoint(EntityWrapperPtr theBase, double theCoeff);
-
-protected:
-  /// \brief Remove constraint
-  /// \return \c true if the constraint and all its parameters are removed successfully
-  virtual bool remove(ConstraintWrapperPtr theConstraint);
-  /// \brief Remove entity
-  /// \return \c true if the entity and all its parameters are removed successfully
-  virtual bool remove(EntityWrapperPtr theEntity);
-  /// \brief Remove parameter
-  /// \return \c true if the parameter has been removed
-  virtual bool remove(ParameterWrapperPtr theParameter);
-
-  /// \brief Update the group for the given entity, its sub-entities and parameters
-  virtual void changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup);
-  /// \brief Update the group for the given parameter
-  virtual void changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup);
-
-
-// =============   Own methods   =============
-public:
-  /// \brief Obtain and store identifier of sketch
-  void storeWorkplane(EntityWrapperPtr theSketch);
-
-  /** \brief Add new parameter to the current group
-   *  \param[in] theParam  SolveSpace parameter
-   *  \return the ID of added parameter
-   */
-  Slvs_hParam addParameter(const Slvs_Param& theParam);
-  /** \brief Updates parameter in the current group. If the ID of parameter is zero, the new item will be added
-   *  \param[in] theParam  SolveSpace parameter
-   *  \return the ID of updated/added parameter
-   */
-  Slvs_hParam updateParameter(const Slvs_Param& theParam);
-  /** \brief Removes the parameter by its ID
-   *  \param[in] theParamID  index of parameter to be removed
-   *  \return \c true if the parameter was successfully removed
-   */
-  bool removeParameter(const Slvs_hParam& theParamID);
-  /// \brief Returns the parameter by its ID
-  const Slvs_Param& getParameter(const Slvs_hParam& theParamID) const;
-
-  /** \brief Add new entity to the current group
-   *  \param[in] theEntity  SolveSpace entity
-   *  \return the ID of added entity
-   */
-  Slvs_hEntity addEntity(const Slvs_Entity& theEntity);
-  /** \brief Updates entity in the current group. If the ID of entity is zero, the new item will be added
-   *  \param[in] theEntity  SolveSpace entity
-   *  \return the ID of updated/added entity
-   */
-  Slvs_hEntity updateEntity(const Slvs_Entity& theEntity);
-  /** \brief Removes the entity by its ID. All parameters used in this entity,
-   *         and not used in other constraints, will be removed too.
-   *  \param[in] theEntityID  index of entity to be removed
-   *  \return \c true if the entity was successfully removed
-   */
-  bool removeEntity(const Slvs_hEntity& theEntityID);
-  /** \brief Remove all entities, which are not used in constraints
-   */
-  void removeUnusedEntities();
-  /// \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 Check the entity is used in constraints
-  bool isUsedByConstraints(const Slvs_hEntity& theEntityID) const;
-  /// \brief Returns maximal ID of entities in this storage
-  const Slvs_hEntity& entityMaxID() const
-  { return myEntityMaxID; }
-
-  /// \brief Verifies the current point or another coincident one is fixed
-  /// \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
-   *  \return the ID of added constraint
-   */
-  Slvs_hConstraint addConstraint(const Slvs_Constraint& theConstraint);
-  /** \brief Updates constraint in the current group.
-   *         If the ID of constraint is zero, the new item will be added
-   *  \param[in] theConstraint  SolveSpace constraint
-   *  \return the ID of updated/added constraint
-   */
-  Slvs_hConstraint updateConstraint(const Slvs_Constraint& theConstraint);
-  /** \brief Removes the constraint by its ID. All entities and parameters depending on this
-   *         constraint, which are not used in other constraints, will be removed too.
-   *  \param[in] theConstraintID  index of constraint to be removed
-   *  \return \c true if the constraint was successfully removed
-   */
-  bool removeConstraint(const Slvs_hConstraint& theConstraintID);
-  /// \brief Returns the constraint by its ID
-  const Slvs_Constraint& getConstraint(const Slvs_hConstraint& theConstraintID) const;
-  /// \brief Returns list of constraints of specified type
-  std::list<Slvs_Constraint> getConstraintsByType(int theConstraintType) const;
-  /// \brief Returns quantity of constraints in this storage
-  size_t nbConstraints() const
-  { return myConstraints.size(); }
-
-  /// \brief Attach constraint SLVS_C_WHERE_DRAGGED to this storage. It need to make precise calculations
-  void addConstraintWhereDragged(const Slvs_hConstraint& theConstraintID);
-
-  /// \brief Add transient constraint
-  void addTemporaryConstraint(const Slvs_hConstraint& theConstraintID);
-  /// \brief Mark specified constraint as temporary
-  virtual void setTemporary(ConstraintPtr theConstraint);
-  /// \brief Remove all transient constraints
-  void removeAllTemporary();
-  /// \brief Remove temporary constraint s. Preferable to remove the points under Point-on-Line constraint
-  /// \param theNbConstraints [in]  number of temporary constraints to be deleted
-  /// \return Number of remaining temporary constraints
-  virtual size_t removeTemporary(size_t theNbConstraints);
-  /// \brief Checks the constraint is temporary
-  bool isTemporary(const Slvs_hConstraint& theConstraintID) const;
-  /// \brief Number of temporary constraints
-  virtual size_t nbTemporary() const
-  { return myTemporaryConstraints.size(); }
-
-  /// \brief Shows the storage has the same constraint twice
-  virtual bool hasDuplicatedConstraint() const
-  { return myDuplicatedConstraint; }
-
-////  /// \brief Returns lists of removed elements
-////  void getRemoved(std::set<Slvs_hParam>& theParameters,
-////                  std::set<Slvs_hEntity>& theEntities,
-////                  std::set<Slvs_hConstraint>& theConstraints);
-
-////  /// \brief Shows the sketch should be resolved
-////  virtual bool isNeedToResolve();
-
-  /// \brief Initialize constraint solver by the entities collected by current storage
-  virtual void initializeSolver(SolverPtr 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);
-////  /// \brief Remove point-point coincidence
-////  void removeCoincidence(const Slvs_Constraint& theCoincidence);
-
-public:
-////  /// \brief Check two points are coincident
-////  bool isCoincident(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const;
-
-  /// \brief Check two points are coincident or have same coordinates
-  bool isEqual(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const;
-
-  /// \brief Check the entity is horizontal of vertical
-  bool isAxisParallel(const Slvs_hEntity& theEntity) const;
-
-  /// \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_hEntity& theEntity, Slvs_Constraint& theEqual) const;
-
-  /// \brief Fixes specified entity
-  /// \param theEntity  ID of the entity to be fixed
-  /// \return List of created constraints
-  std::vector<Slvs_hConstraint> fixEntity(const Slvs_hEntity& theEntity);
-
-private:
-  /// \brief Fixes specified point
-  /// \param [in]  thePoint    point to be fixed
-  /// \param [out] theCreated  list of the Fixed constraints created
-  void fixPoint(const Slvs_Entity& thePoint, std::vector<Slvs_hConstraint>& theCreated);
-  /// \brief Fixes specified line
-  /// \param [in]  theLine     line to be fixed
-  /// \param [out] theCreated  list of the Fixed constraints created
-  void fixLine(const Slvs_Entity& theLine, std::vector<Slvs_hConstraint>& theCreated);
-  /// \brief Fixes specified circle
-  /// \param [in]  theCircle   circle to be fixed
-  /// \param [out] theCreated  list of the Fixed constraints created
-  void fixCircle(const Slvs_Entity& theCircle, std::vector<Slvs_hConstraint>& theCreated);
-  /// \brief Fixes specified arc
-  /// \param [in]  theArc      arc to be fixed
-  /// \param [out] theCreated  list of the Fixed constraints created
-  void fixArc(const Slvs_Entity& theArc, std::vector<Slvs_hConstraint>& theCreated);
-
-  /// \brief Update arc points to be on circle sharp.
-  void adjustArc(const Slvs_Entity& theArc);
-
-  /// \brief Verify the feature or any its attribute is used by constraint
-  bool isUsed(FeaturePtr theFeature) const;
-  /// \brief Verify the attribute is used by constraint
-  bool isUsed(AttributePtr theAttirubute) const;
-
-  /// \brief Replace sub-entity theSource in all features by theDest
-  void replaceInFeatures(EntityWrapperPtr theSource, EntityWrapperPtr theDest);
-  /// \brief Replace constrained entity theSource by theDest in all constraints;
-  void replaceInConstraints(EntityWrapperPtr theSource, EntityWrapperPtr theDest);
-
-  /// \brief Add pair of constraints which have same representation in SolveSpace notation.
-  ///
-  ///        These constraints may be different and become the same after the substitution
-  ///        of point coincidence.
-  void addSameConstraints(ConstraintWrapperPtr theConstraint1, ConstraintWrapperPtr theConstraint2);
-
-private:
-  Slvs_hEntity myWorkplaneID; ///< identifier of workplane
-
-  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 (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 (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 (sorted by the identifier)
-
-  CoincidentPointsMap myCoincidentPoints; ///< lists of coincident points (first is a master point, second is a set of slaves)
-  Slvs_hConstraint myFixed; ///< identifier of one of temporary constraints to fix separate point
-
-  bool myDuplicatedConstraint; ///< shows the storage has same constraint twice
-
-  std::set<Slvs_hConstraint> myTemporaryConstraints; ///< list of transient constraints
-////  std::set<Slvs_hParam> myRemovedParameters; ///< list of just removed parameters (cleared when returning to applicant)
-////  std::set<Slvs_hEntity> myRemovedEntities; ///< list of just removed entities (cleared when returning to applicant)
-////  std::set<Slvs_hConstraint> myRemovedConstraints; ///< list of just removed constraints (cleared when returning to applicant)
-  std::set<Slvs_hParam> myUpdatedParameters; ///< list of just updated parameters (cleared when isNeedToResolve() called)
-
-  SameConstraintMap myEqualConstraints; ///< list of groups of equal constraints
-};
-
-#endif