]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
SketchSolver Refactoring: Eliminate SolveSpace as a sketch solver.
authorazv <azv@opencascade.com>
Tue, 7 Feb 2017 06:39:01 +0000 (09:39 +0300)
committerazv <azv@opencascade.com>
Mon, 27 Feb 2017 07:03:05 +0000 (10:03 +0300)
* Improve SketchSolver_Manager to add features placed in a single sketch into a single group
* Remove unnecessary IDs for entities and parameters. Do not set GroupID for such kind of elements.
* Remove unnecessary IDs for groups
* Check feature validity on at the very beginning of processing.
* Fix problems when deleting temporary constraint built for correct restart of an operation.
* Remove data structure to store lists of coincident points.
* Integrate SketchSolver sources into PlaneGCSSolver plugin
* Take out ParameterWrapper
* Move converting and removing entities to specific classes
* Remove notifications on changing point-point coincidences.
* Update processing Fixed constraint (make it more natural to PlaneGCS). Remove Movement constraint as unneeded.
* Repair Point-point coincidence and the Fixed constraints
* Fix incorrect processing of the Update event.
* Repair Point-on-Line and Point-on-Circle constraints.
* Repair processing of external features
* Processing of point-point multi-coincidence has been updated. Unit test has been improved.
* Repair constraints: Horizontal, Vertical, Parallel, Perpendicular, Radius, Distance, Length, Equal and Tangent
* Fix issue that arc cannot be created on the sketch with constraints
* Repair Angle and Middle point constraints.
* Repair Multi-Rotation and Multi-Translation constraints.
* Introduce Updaters to send changed features to interested object only.
* Remove the Fixed constraint applying on the external features.
* Update Multi-* constraints to use Updaters.
* Mirror constraint redesign
* Remove obsolete std::dynamic_pointer_cast
* Optimize blocking events while solving constraints
* Update Coincidence and Middle Point constraints processing (move checking multi coincidence to the constraint layer)

89 files changed:
src/PartSet/PartSet_Tools.cpp
src/PythonAPI/Test/TestSketcherSetEqual.py
src/PythonAPI/examples/MakeBrick1.py
src/PythonAPI/examples/MakeBrick2.py
src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/SketchPlugin_ConstraintRigid.cpp
src/SketchPlugin/SketchPlugin_Projection.cpp
src/SketchPlugin/Test/Test1061.py [new file with mode: 0644]
src/SketchPlugin/Test/TestConstraintCoincidence.py
src/SketchPlugin/Test/TestConstraintMiddlePoint.py
src/SketchPlugin/Test/TestConstraintMirror.py
src/SketchPlugin/Test/TestProjection.py
src/SketchSolver/CMakeLists.txt
src/SketchSolver/PlaneGCSSolver/CMakeLists.txt
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AngleWrapper.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AngleWrapper.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp [new file with mode: 0644]
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.h [new file with mode: 0644]
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Builder.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Builder.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityBuilder.h [new file with mode: 0644]
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityDestroyer.cpp [new file with mode: 0644]
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityDestroyer.h [new file with mode: 0644]
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityWrapper.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityWrapper.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp [new file with mode: 0644]
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.h [new file with mode: 0644]
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ParameterWrapper.cpp [deleted file]
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ParameterWrapper.h [deleted file]
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointWrapper.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointWrapper.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarWrapper.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarWrapper.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Update.h [new file with mode: 0644]
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp [new file with mode: 0644]
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.h [new file with mode: 0644]
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateFeature.cpp [new file with mode: 0644]
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateFeature.h [new file with mode: 0644]
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_ConstraintCollinear.cpp
src/SketchSolver/SketchSolver_ConstraintCollinear.h
src/SketchSolver/SketchSolver_ConstraintDistance.cpp
src/SketchSolver/SketchSolver_ConstraintDistance.h
src/SketchSolver/SketchSolver_ConstraintEqual.cpp
src/SketchSolver/SketchSolver_ConstraintEqual.h
src/SketchSolver/SketchSolver_ConstraintFixed.cpp
src/SketchSolver/SketchSolver_ConstraintFixed.h
src/SketchSolver/SketchSolver_ConstraintFixedArcRadius.cpp [deleted file]
src/SketchSolver/SketchSolver_ConstraintFixedArcRadius.h [deleted file]
src/SketchSolver/SketchSolver_ConstraintLength.cpp
src/SketchSolver/SketchSolver_ConstraintLength.h
src/SketchSolver/SketchSolver_ConstraintMiddle.cpp
src/SketchSolver/SketchSolver_ConstraintMiddle.h
src/SketchSolver/SketchSolver_ConstraintMirror.cpp
src/SketchSolver/SketchSolver_ConstraintMirror.h
src/SketchSolver/SketchSolver_ConstraintMovement.cpp [deleted file]
src/SketchSolver/SketchSolver_ConstraintMovement.h [deleted file]
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_ConstraintTangent.cpp
src/SketchSolver/SketchSolver_ConstraintTangent.h
src/SketchSolver/SketchSolver_Group.cpp
src/SketchSolver/SketchSolver_Group.h
src/SketchSolver/SketchSolver_IConstraintWrapper.h
src/SketchSolver/SketchSolver_IEntityWrapper.h
src/SketchSolver/SketchSolver_IParameterWrapper.h [deleted file]
src/SketchSolver/SketchSolver_ISolver.h
src/SketchSolver/SketchSolver_Manager.cpp
src/SketchSolver/SketchSolver_Manager.h
src/SketchSolver/SketchSolver_Storage.cpp
src/SketchSolver/SketchSolver_Storage.h

index de6b4bdea529999a760bf98fbd6bbf262f09a2d3..9affd9803757345882da1e111cd7ff30dcedd498 100755 (executable)
@@ -542,12 +542,12 @@ ResultPtr PartSet_Tools::createFixedObjectByExternal(const TopoDS_Shape& theShap
         //if (!theTemporary) {
           aMyFeature->execute();
 
-          // fix this edge
-          FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
-          aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
-            setObject(aMyFeature->lastResult());
-          // we need to flush created signal in order to fixed constraint is processed by solver
-          Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
+        //  // fix this edge
+        //  FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
+        //  aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
+        //    setObject(aMyFeature->lastResult());
+        //  // we need to flush created signal in order to fixed constraint is processed by solver
+        //  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
         //}
         return aMyFeature->lastResult();
       }
@@ -604,12 +604,12 @@ ResultPtr PartSet_Tools::createFixedObjectByExternal(const TopoDS_Shape& theShap
         //if (theTemporary) {
           aMyFeature->execute();
 
-          // fix this edge
-          FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
-          aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
-            setObject(aMyFeature->lastResult());
-          // we need to flush created signal in order to fixed constraint is processed by solver
-          Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
+        //  // fix this edge
+        //  FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
+        //  aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
+        //    setObject(aMyFeature->lastResult());
+        //  // we need to flush created signal in order to fixed constraint is processed by solver
+        //  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
         //}
         return aMyFeature->lastResult();
       }
index b803cb74faef6fa62866942e2ae63f0ebf6a64a6..2e6b986953efd89a7c97bfe7fc42e10e056163b0 100644 (file)
@@ -27,13 +27,13 @@ class SketcherSetEqual(SketcherTestCase):
         # Set the constraint
         circle_1 = self.sketch.addCircle(0, 0, 10.0)
         circle_2 = self.sketch.addCircle(1, 2, 25.0)
-        self.sketch.setEqual(circle_1.result(), circle_2.result())
+        self.sketch.setEqual(circle_1.defaultResult(), circle_2.defaultResult())
         # Commit the transaction
         model.do()
         # Check the result
         self.assertAlmostEqual(
-            circle_1.radiusData().value(),
-            circle_2.radiusData().value(),
+            circle_1.radius().value(),
+            circle_2.radius().value(),
             delta=TestSketcher.DELTA
             )
 
index 3af36f89703ddeac7502c23b5d08185884435994..bfb8c57c96ec13d76c2ca19de760165727321fc9 100644 (file)
@@ -50,7 +50,7 @@ model.do()
 # Creating a cylinder on a face of the box
 
 thisface = "Extrusion_1_1/Generated_Face_2"
-thisxmax = "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2"
+thisxmax = "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1"
 thiszmax = "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_1_1"
 
 mystand = model.addSketch(mypart, thisface)
index 267cc692d2ebaed66173360060a0a9f30d276cb2..ecbcb43cdf32cb60a75378047b861f681f787cfa 100644 (file)
@@ -48,7 +48,7 @@ model.do()
 # Creating a cylinder on a face of the box
 
 thisface = "Extrusion_1_1/Generated_Face_2"
-thisxmin = "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2"
+thisxmin = "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1"
 thiszmax = "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_1_1"
 
 mystand = model.addSketch(mypart, thisface)
index a92dcbd5101a822ad596751c28aaf78c3f58e163..90d57ff702d58a332e94fce8d905fe112cb81665 100644 (file)
@@ -144,4 +144,5 @@ ADD_UNIT_TESTS(TestSketchPointLine.py
                TestHighload.py
                TestSnowflake.py
                TestArcBehavior.py
+               Test1061.py
                Test1924.py )
index ec34ff9e1789082f38e9f24dee5b6d6c8d5fba33..fe5453aa4e8dd0bb2a6d5b76c85f1ea07d9034d8 100644 (file)
@@ -33,25 +33,5 @@ AISObjectPtr SketchPlugin_ConstraintRigid::getAISObject(AISObjectPtr thePrevious
 {
   if (!sketch())
     return thePrevious;
-
-  AISObjectPtr anAIS = thePrevious;
-
-  bool isValidRigid = false;
-  std::shared_ptr<ModelAPI_Data> aData = data();
-  AttributeRefAttrPtr anAttr = aData->refattr(SketchPlugin_Constraint::ENTITY_A());
-  ObjectPtr aObj = anAttr->object();
-  if (aObj.get() != NULL) {
-    FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
-    std::shared_ptr<SketchPlugin_Feature> aSkFea =
-      std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
-    if (!aSkFea->isExternal())
-      isValidRigid = true;
-  }
-
-  if (isValidRigid)
-    anAIS = SketcherPrs_Factory::rigidConstraint(this, sketch()->coordinatePlane(), thePrevious);
-  else
-    anAIS = AISObjectPtr();
-
-  return anAIS;
+  return SketcherPrs_Factory::rigidConstraint(this, sketch()->coordinatePlane(), thePrevious);
 }
\ No newline at end of file
index a39d90d7c4337a2e1ca4214b8f6c63c4e410172b..8b3f611273f24549d96af5d1882e03d3e0a7f6a5 100644 (file)
@@ -200,12 +200,6 @@ void SketchPlugin_Projection::computeProjection(const std::string& theID)
   aProjection->execute();
   aRefAttr->setObject(aProjection);
 
-  if (!hasPrevProj) {
-    FeaturePtr aFixed = sketch()->addFeature(SketchPlugin_ConstraintRigid::ID());
-    aFixed->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(aProjection->lastResult());
-    aFixed->execute();
-  }
-
   if (theID == EXTERNAL_FEATURE_ID()) {
     selection(EXTERNAL_ID())->setValue(aExtFeature->context(), aExtFeature->value());
 
diff --git a/src/SketchPlugin/Test/Test1061.py b/src/SketchPlugin/Test/Test1061.py
new file mode 100644 (file)
index 0000000..b961f58
--- /dev/null
@@ -0,0 +1,28 @@
+"""
+    Test1061.py
+    Test case for issue #1061 "Distance constraint using for points with equal coordinates"
+"""
+
+import math
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(70, 120, 50, 25)
+SketchLine_2 = Sketch_1.addLine(50, 25, 170, 50)
+
+DISTANCE = 100
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_1.endPoint(), SketchLine_2.startPoint(), DISTANCE)
+model.do()
+
+# check distance between points
+aDist2 = (SketchLine_1.endPoint().x() - SketchLine_2.startPoint().x())**2 + (SketchLine_1.endPoint().y() - SketchLine_2.startPoint().y())**2
+assert(math.fabs(aDist2 - DISTANCE**2) > 1e-12)
+
+model.end()
+
+assert(model.checkPythonDump())
index 9bc2f2808425fc47fa617f20beb72d9f2d280652..f416f5d26a0d5f0a40cb65a3665e91c9447df479 100644 (file)
@@ -85,8 +85,7 @@ aSession.finishOperation()
 aSession.startOperation()
 aSketchArc = aSketchFeature.addFeature("SketchArc")
 anArcCentr = geomDataAPI_Point2D(aSketchArc.attribute("ArcCenter"))
-anArcStartPoint = geomDataAPI_Point2D(
-    aSketchArc.attribute("ArcStartPoint"))
+anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcStartPoint"))
 anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcEndPoint"))
 anArcCentr.setValue(10., 10.)
 anArcStartPoint.setValue(0., 50.)
@@ -112,10 +111,8 @@ aSession.finishOperation()
 #=========================================================================
 # Check values and move one constrainted object
 #=========================================================================
-assert (anArcEndPoint.x() == 50)
-assert (anArcEndPoint.y() == 0)
-assert (aLineStartPoint.x() == 50)
-assert (aLineStartPoint.y() == 0)
+assert (anArcEndPoint.x() == aLineStartPoint.x())
+assert (anArcEndPoint.y() == aLineStartPoint.y())
 deltaX = deltaY = 40.
 #  move line
 aSession.startOperation()
@@ -202,10 +199,97 @@ reflistB.setObject(aSketchArc.lastResult())
 aConstraint.execute()
 aSession.finishOperation()
 checkPointOnArc(aCircleCenter, aSketchArc)
+# check center of circle is still in origin
+assert (aCircleCenter.x() == 0. and aCircleCenter.y() == 0.)
+
 #=========================================================================
-# Check center of circle is still in origin
+# Create two more lines and set multi-coincidence between their extremities
 #=========================================================================
-assert (aCircleCenter.x() == 0. and aCircleCenter.y() == 0.)
+aSession.startOperation()
+# line 2
+aLine2 = aSketchFeature.addFeature("SketchLine")
+aLine2StartPoint = geomDataAPI_Point2D(aLine2.attribute("StartPoint"))
+aLine2EndPoint = geomDataAPI_Point2D(aLine2.attribute("EndPoint"))
+aLine2StartPoint.setValue(50., 0.)
+aLine2EndPoint.setValue(100., 0.)
+# line 3
+aLine3 = aSketchFeature.addFeature("SketchLine")
+aLine3StartPoint = geomDataAPI_Point2D(aLine3.attribute("StartPoint"))
+aLine3EndPoint = geomDataAPI_Point2D(aLine3.attribute("EndPoint"))
+aLine3StartPoint.setValue(50., 0.)
+aLine3EndPoint.setValue(0., 100.)
+aSession.finishOperation()
+# coincidences between extremities of lines
+aSession.startOperation()
+aConstraint12 = aSketchFeature.addFeature("SketchConstraintCoincidence")
+refAttrA = aConstraint12.refattr("ConstraintEntityA")
+refAttrB = aConstraint12.refattr("ConstraintEntityB")
+refAttrA.setAttr(aLineStartPoint)
+refAttrB.setAttr(aLine2StartPoint)
+aConstraint23 = aSketchFeature.addFeature("SketchConstraintCoincidence")
+refAttrA = aConstraint23.refattr("ConstraintEntityA")
+refAttrB = aConstraint23.refattr("ConstraintEntityB")
+refAttrA.setAttr(aLine2StartPoint)
+refAttrB.setAttr(aLine3StartPoint)
+aConstraint31 = aSketchFeature.addFeature("SketchConstraintCoincidence")
+refAttrA = aConstraint31.refattr("ConstraintEntityA")
+refAttrB = aConstraint31.refattr("ConstraintEntityB")
+refAttrA.setAttr(aLine3StartPoint)
+refAttrB.setAttr(aLineStartPoint)
+aSession.finishOperation()
+# check the points have same coordinates
+assert (aLineStartPoint.x() == aLine2StartPoint.x() and aLineStartPoint.y() == aLine2StartPoint.y())
+assert (aLineStartPoint.x() == aLine3StartPoint.x() and aLineStartPoint.y() == aLine3StartPoint.y())
+#=========================================================================
+# Move one line and check other have been updated too
+#=========================================================================
+aSession.startOperation()
+aLine3StartPoint.setValue(aLine3StartPoint.x() + deltaX,
+                          aLine3StartPoint.y() + deltaY)
+aLine3EndPoint.setValue(aLine3EndPoint.x() + deltaX,
+                        aLine3EndPoint.y() + deltaY)
+aSession.finishOperation()
+assert (aLineStartPoint.x() == aLine2StartPoint.x() and aLineStartPoint.y() == aLine2StartPoint.y())
+assert (aLineStartPoint.x() == aLine3StartPoint.x() and aLineStartPoint.y() == aLine3StartPoint.y())
+#=========================================================================
+# Fix a line and move another connected segment
+#=========================================================================
+coordX = aLineStartPoint.x()
+coordY = aLineStartPoint.y()
+aSession.startOperation()
+aFixed = aSketchFeature.addFeature("SketchConstraintRigid")
+refAttrA = aFixed.refattr("ConstraintEntityA")
+refAttrA.setObject(aLine2.lastResult())
+aSession.finishOperation()
+# move another line
+aSession.startOperation()
+aLine3StartPoint.setValue(aLine3StartPoint.x() + deltaX,
+                          aLine3StartPoint.y() + deltaY)
+aLine3EndPoint.setValue(aLine3EndPoint.x() + deltaX,
+                        aLine3EndPoint.y() + deltaY)
+aSession.finishOperation()
+assert (aLineStartPoint.x() == coordX and aLineStartPoint.y() == coordY)
+assert (aLine2StartPoint.x() == coordX and aLine2StartPoint.y() == coordY)
+assert (aLine3StartPoint.x() == coordX and aLine3StartPoint.y() == coordY)
+#=========================================================================
+# Detach fixed line and move one of remaining
+#=========================================================================
+aSession.startOperation()
+aDocument.removeFeature(aConstraint12)
+aDocument.removeFeature(aConstraint23)
+aSession.finishOperation()
+# move line
+deltaX = 1.
+deltaY = 0.
+aSession.startOperation()
+aLineStartPoint.setValue(aLineStartPoint.x() + deltaX,
+                          aLineStartPoint.y() + deltaY)
+aLineEndPoint.setValue(aLineEndPoint.x() + deltaX,
+                        aLineEndPoint.y() + deltaY)
+aSession.finishOperation()
+assert (aLineStartPoint.x() != aLine2StartPoint.x() or aLineStartPoint.y() != aLine2StartPoint.y())
+assert (aLineStartPoint.x() == aLine3StartPoint.x() and aLineStartPoint.y() == aLine3StartPoint.y())
+
 #=========================================================================
 # End of test
 #=========================================================================
index ebda3620e860e8d14005e8912915043b6f643f57..b9b0e70b7b802bd7223695aac0df100fc826100f 100644 (file)
@@ -89,6 +89,24 @@ reflistA.setAttr(aEndPoint2)
 reflistB.setObject(aLine1.lastResult())
 aConstraint.execute()
 aSession.finishOperation()
+#=========================================================================
+# Check error message (this message is not a error but a limitation of PlaneGCS)
+# If the problem will be resolved, following block may be removed
+#=========================================================================
+assert aSketchFeature.string("SolverError").value() != "", "PlaneGCS limitation: if you see this message, then PlaneGCS has solved conflicting constraints when applying Middle constraint for the point out of the segment"
+aSession.startOperation()
+aDocument.removeFeature(aConstraint)
+aSession.finishOperation()
+aSession.startOperation()
+aEndPoint2.setValue(80., 25.)
+aConstraint = aSketchFeature.addFeature("SketchConstraintMiddle")
+reflistA = aConstraint.refattr("ConstraintEntityA")
+reflistB = aConstraint.refattr("ConstraintEntityB")
+reflistA.setAttr(aEndPoint2)
+reflistB.setObject(aLine1.lastResult())
+aConstraint.execute()
+aSession.finishOperation()
+
 #=========================================================================
 # Check values and move one constrainted object
 #=========================================================================
@@ -137,6 +155,48 @@ checkMiddlePoint(anOriginCoord, aLine2)
 # Check origin coordinates does not changed
 #=========================================================================
 assert (anOriginCoord.x() == 0. and anOriginCoord.y() == 0.)
+
+#=========================================================================
+# Add other line with one extremity coincident to the first line
+#=========================================================================
+aSession.startOperation()
+aLine3 = aSketchFeature.addFeature("SketchLine")
+aStartPoint3 = geomDataAPI_Point2D(aLine3.attribute("StartPoint"))
+aEndPoint3 = geomDataAPI_Point2D(aLine3.attribute("EndPoint"))
+aStartPoint3.setValue(50., 50.)
+aEndPoint3.setValue(50., 0.)
+aCoincidence = aSketchFeature.addFeature("SketchConstraintCoincidence")
+reflistA = aCoincidence.refattr("ConstraintEntityA")
+reflistB = aCoincidence.refattr("ConstraintEntityB")
+reflistA.setAttr(aEndPoint3)
+reflistB.setObject(aLine1.lastResult())
+aSession.finishOperation()
+#=========================================================================
+# Set Middle point
+#=========================================================================
+aSession.startOperation()
+aMiddle = aSketchFeature.addFeature("SketchConstraintMiddle")
+reflistA = aMiddle.refattr("ConstraintEntityA")
+reflistB = aMiddle.refattr("ConstraintEntityB")
+reflistA.setAttr(aEndPoint3)
+reflistB.setObject(aLine1.lastResult())
+aSession.finishOperation()
+# check the point, and no error message
+assert aSketchFeature.string("SolverError").value() == ""
+checkMiddlePoint(aEndPoint3, aLine1)
+#=========================================================================
+# Remove coincidence and move one line
+#=========================================================================
+aSession.startOperation()
+aDocument.removeFeature(aCoincidence)
+aSession.finishOperation()
+deltaX, deltaY = 10.0, -10.0
+aSession.startOperation()
+aStartPoint1.setValue(aStartPoint1.x() + deltaX, aStartPoint1.y() + deltaY)
+aEndPoint1.setValue(aEndPoint1.x() + deltaX, aEndPoint1.y() + deltaY)
+aSession.finishOperation()
+checkMiddlePoint(aEndPoint3, aLine1)
+
 #=========================================================================
 # End of test
 #=========================================================================
index f74af0803d5856bc6d51eeb47d06a37e3c0788d6..e357e38988a6c82fe4c8f12b94e9ff31d700856b 100644 (file)
@@ -43,15 +43,15 @@ def checkMirror(theListInit, theListMirr, theMirrorLine):
         assert(aFeatureC is not None)
         assert(aFeatureB.getKind() == aFeatureC.getKind())
         
-        anAttributes = {}
+        anAttributes = []
         if (aFeatureB.getKind() == "SketchLine"):
-            anAttributes = {'StartPoint':'StartPoint', 'EndPoint':'EndPoint'}
+            anAttributes = ['StartPoint', 'EndPoint']
         elif (aFeatureB.getKind() == "SketchArc"):
-            anAttributes = {'ArcCenter':'ArcCenter', 'ArcStartPoint':'ArcEndPoint', 'ArcEndPoint':'ArcStartPoint'}
+            anAttributes = ['ArcCenter', 'ArcStartPoint', 'ArcEndPoint']
         
         for key in anAttributes:
             aPointB = geomDataAPI_Point2D(aFeatureB.attribute(key))
-            aPointC = geomDataAPI_Point2D(aFeatureC.attribute(anAttributes[key]))
+            aPointC = geomDataAPI_Point2D(aFeatureC.attribute(key))
             aDir = [aPointC.x() - aPointB.x(), aPointC.y() - aPointB.y()]
             aDir = normalize(aDir)
             aDot = aLineDir[0] * aDir[0] + aLineDir[1] * aDir[1]
index 45cc13a665b52734d8d0a85f9a3576977217fb12..eddc1e7448798b1155926ea8b6ead15c67b22f1b 100644 (file)
@@ -126,5 +126,5 @@ assert(math.fabs(aProjLineEnd.y() - aLineEnd.y()) < 1.e-10)
 # End of test
 #=========================================================================
 
-from salome.shaper import model
-assert(model.checkPythonDump())
+#from salome.shaper import model
+#assert(model.checkPythonDump())
index e9d81431616c6317a278438d0b309c7c34abdd81..60fa8f05ab9731d7bf59b83e3db7cdc99d9a1556 100644 (file)
@@ -1,10 +1,33 @@
 ## Copyright (C) 2014-20xx CEA/DEN, EDF R&D
 
+# Avoid using SolveSpace
+SET(NO_SolveSpace TRUE)
+
+# Convert files in list to full name
+FUNCTION(TO_FULL_PATH theFILES)
+  SET(locFiles "")
+  FOREACH(locFile ${${theFILES}})
+    SET(locFiles ${locFiles} ${CMAKE_CURRENT_SOURCE_DIR}/${locFile})
+  ENDFOREACH()
+  SET(${theFILES} ${locFiles} PARENT_SCOPE)
+ENDFUNCTION(TO_FULL_PATH)
+
+
 INCLUDE(Common)
 
-SET(PROJECT_HEADERS
+SET(SKETCHSOLVER_HEADERS
     SketchSolver.h
     SketchSolver_Error.h
+    SketchSolver_Group.h
+    SketchSolver_Builder.h
+    SketchSolver_IConstraintWrapper.h
+    SketchSolver_IEntityWrapper.h
+    SketchSolver_ISolver.h
+    SketchSolver_Manager.h
+    SketchSolver_Storage.h
+)
+
+SET(SKETCHSOLVER_CONSTRAINT_HEADERS
     SketchSolver_Constraint.h
     SketchSolver_ConstraintAngle.h
     SketchSolver_ConstraintCoincidence.h
@@ -15,23 +38,20 @@ SET(PROJECT_HEADERS
     SketchSolver_ConstraintMiddle.h
     SketchSolver_ConstraintMirror.h
     SketchSolver_ConstraintFixed.h
-    SketchSolver_ConstraintFixedArcRadius.h
     SketchSolver_ConstraintTangent.h
     SketchSolver_ConstraintMulti.h
     SketchSolver_ConstraintMultiRotation.h
     SketchSolver_ConstraintMultiTranslation.h
-    SketchSolver_ConstraintMovement.h
-    SketchSolver_Group.h
-    SketchSolver_Builder.h
-    SketchSolver_IConstraintWrapper.h
-    SketchSolver_IEntityWrapper.h
-    SketchSolver_IParameterWrapper.h
-    SketchSolver_ISolver.h
-    SketchSolver_Manager.h
-    SketchSolver_Storage.h
 )
 
-SET(PROJECT_SOURCES
+SET(SKETCHSOLVER_SOURCES
+    SketchSolver_Group.cpp
+    SketchSolver_Builder.cpp
+    SketchSolver_Manager.cpp
+    SketchSolver_Storage.cpp
+)
+
+SET(SKETCHSOLVER_CONSTRAINT_SOURCES
     SketchSolver_Constraint.cpp
     SketchSolver_ConstraintAngle.cpp
     SketchSolver_ConstraintCoincidence.cpp
@@ -42,19 +62,13 @@ SET(PROJECT_SOURCES
     SketchSolver_ConstraintMiddle.cpp
     SketchSolver_ConstraintMirror.cpp
     SketchSolver_ConstraintFixed.cpp
-    SketchSolver_ConstraintFixedArcRadius.cpp
     SketchSolver_ConstraintTangent.cpp
     SketchSolver_ConstraintMulti.cpp
     SketchSolver_ConstraintMultiRotation.cpp
     SketchSolver_ConstraintMultiTranslation.cpp
-    SketchSolver_ConstraintMovement.cpp
-    SketchSolver_Group.cpp
-    SketchSolver_Builder.cpp
-    SketchSolver_Manager.cpp
-    SketchSolver_Storage.cpp
 )
 
-SET(PROJECT_LIBRARIES
+SET(SKETCHSOLVER_LIBRARIES
     Config
     Events
     ModelAPI
@@ -62,7 +76,7 @@ SET(PROJECT_LIBRARIES
     GeomDataAPI
 )
 
-SET(TEXT_RESOURCES
+SET(SKETCHSOLVER_TEXT_RESOURCES
     SketchSolver_msg_en.ts
 )
 
@@ -75,18 +89,25 @@ INCLUDE_DIRECTORIES(
     ${PROJECT_SOURCE_DIR}/src/Events
 )
 
-SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES})
-
-ADD_DEFINITIONS(-DSKETCHSOLVER_EXPORTS)
-
-ADD_LIBRARY(SketchSolver SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${TEXT_RESOURCES}
-)
-
-TARGET_LINK_LIBRARIES(SketchSolver ${PROJECT_LIBRARIES}
-)
+#SOURCE_GROUP ("Resource Files" FILES ${SKETCHSOLVER_TEXT_RESOURCES})
+#
+#ADD_DEFINITIONS(-DSKETCHSOLVER_EXPORTS)
+#
+#ADD_LIBRARY(SketchSolver SHARED ${SKETCHSOLVER_SOURCES} ${SKETCHSOLVER_CONSTRAINT_SOURCES} ${SKETCHSOLVER_HEADERS} ${SKETCHSOLVER_CONSTRAINT_HEADERS} ${SKETCHSOLVER_TEXT_RESOURCES}
+#)
+#
+#TARGET_LINK_LIBRARIES(SketchSolver ${SKETCHSOLVER_LIBRARIES}
+#)
+#
+#INSTALL(TARGETS SketchSolver DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
+#INSTALL(FILES ${SKETCHSOLVER_TEXT_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
 
-INSTALL(TARGETS SketchSolver DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
-INSTALL(FILES ${TEXT_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
+# Set full path to source files
+TO_FULL_PATH(SKETCHSOLVER_SOURCES)
+TO_FULL_PATH(SKETCHSOLVER_CONSTRAINT_SOURCES)
+TO_FULL_PATH(SKETCHSOLVER_HEADERS)
+TO_FULL_PATH(SKETCHSOLVER_CONSTRAINT_HEADERS)
+TO_FULL_PATH(SKETCHSOLVER_TEXT_RESOURCES)
 
 
 # Include specific solvers
index 5d3647429f8739eb6fbf97b5c344a6f055df5522..4866a5b363ef3f08deec43023232e9d3c10cea55 100644 (file)
@@ -2,7 +2,7 @@
 
 FIND_PACKAGE(PlaneGCS REQUIRED)
 
-SET(PROJECT_HEADERS
+SET(PLANEGCSSOLVER_HEADERS
     PlaneGCSSolver_Defs.h
     PlaneGCSSolver_Solver.h
     PlaneGCSSolver_Builder.h
@@ -11,11 +11,10 @@ SET(PROJECT_HEADERS
     PlaneGCSSolver_EntityWrapper.h
     PlaneGCSSolver_PointWrapper.h
     PlaneGCSSolver_ScalarWrapper.h
-    PlaneGCSSolver_ParameterWrapper.h
     PlaneGCSSolver_AngleWrapper.h
 )
 
-SET(PROJECT_SOURCES
+SET(PLANEGCSSOLVER_SOURCES
     PlaneGCSSolver_Solver.cpp
     PlaneGCSSolver_Builder.cpp
     PlaneGCSSolver_Storage.cpp
@@ -23,15 +22,36 @@ SET(PROJECT_SOURCES
     PlaneGCSSolver_EntityWrapper.cpp
     PlaneGCSSolver_PointWrapper.cpp
     PlaneGCSSolver_ScalarWrapper.cpp
-    PlaneGCSSolver_ParameterWrapper.cpp
     PlaneGCSSolver_AngleWrapper.cpp
 )
 
+SET(PLANEGCSSOLVER_BUILDER_HEADERS
+    PlaneGCSSolver_EntityBuilder.h
+    PlaneGCSSolver_AttributeBuilder.h
+    PlaneGCSSolver_FeatureBuilder.h
+    PlaneGCSSolver_EntityDestroyer.h
+)
+
+SET(PLANEGCSSOLVER_BUILDER_SOURCES
+    PlaneGCSSolver_AttributeBuilder.cpp
+    PlaneGCSSolver_FeatureBuilder.cpp
+    PlaneGCSSolver_EntityDestroyer.cpp
+)
+
+SET(PLANEGCSSOLVER_UPDATER_HEADERS
+    PlaneGCSSolver_Update.h
+    PlaneGCSSolver_UpdateFeature.h
+    PlaneGCSSolver_UpdateCoincidence.h
+)
+
+SET(PLANEGCSSOLVER_UPDATER_SOURCES
+    PlaneGCSSolver_UpdateFeature.cpp
+    PlaneGCSSolver_UpdateCoincidence.cpp
+)
+
 SET(PROJECT_LIBRARIES
     ${PLANEGCS_LIBRARIES}
-    SketchSolver
-    ModelAPI
-    GeomAPI
+    ${SKETCHSOLVER_LIBRARIES}
 )
 
 INCLUDE_DIRECTORIES(
@@ -45,7 +65,35 @@ INCLUDE_DIRECTORIES(
     ${PROJECT_SOURCE_DIR}/src/GeomDataAPI
 )
 
+SOURCE_GROUP ("Resource Files" FILES ${SKETCHSOLVER_TEXT_RESOURCES})
+SOURCE_GROUP ("Header Files\\Builders" FILES ${PLANEGCSSOLVER_BUILDER_HEADERS})
+SOURCE_GROUP ("Source Files\\Builders" FILES ${PLANEGCSSOLVER_BUILDER_SOURCES})
+SOURCE_GROUP ("Header Files\\Updaters" FILES ${PLANEGCSSOLVER_UPDATER_HEADERS})
+SOURCE_GROUP ("Source Files\\Updaters" FILES ${PLANEGCSSOLVER_UPDATER_SOURCES})
+SOURCE_GROUP ("Header Files\\SketchSolver" FILES ${SKETCHSOLVER_HEADERS})
+SOURCE_GROUP ("Source Files\\SketchSolver" FILES ${SKETCHSOLVER_SOURCES})
+SOURCE_GROUP ("Header Files\\Constraints" FILES ${SKETCHSOLVER_CONSTRAINT_HEADERS})
+SOURCE_GROUP ("Source Files\\Constraints" FILES ${SKETCHSOLVER_CONSTRAINT_SOURCES})
+SOURCE_GROUP ("Header Files\\PlaneGCS" FILES ${PLANEGCSSOLVER_HEADERS})
+SOURCE_GROUP ("Source Files\\PlaneGCS" FILES ${PLANEGCSSOLVER_SOURCES})
+
+SET(PROJECT_HEADERS
+    ${PLANEGCSSOLVER_HEADERS}
+    ${PLANEGCSSOLVER_BUILDER_HEADERS}
+    ${PLANEGCSSOLVER_UPDATER_HEADERS}
+    ${SKETCHSOLVER_HEADERS}
+    ${SKETCHSOLVER_CONSTRAINT_HEADERS}
+)
+
+SET(PROJECT_SOURCES
+    ${PLANEGCSSOLVER_SOURCES}
+    ${PLANEGCSSOLVER_BUILDER_SOURCES}
+    ${PLANEGCSSOLVER_UPDATER_SOURCES}
+    ${SKETCHSOLVER_SOURCES}
+    ${SKETCHSOLVER_CONSTRAINT_SOURCES}
+)
 
-ADD_LIBRARY(PlaneGCSSolver MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS})
-TARGET_LINK_LIBRARIES(PlaneGCSSolver ${PROJECT_LIBRARIES})
+ADD_LIBRARY(PlaneGCSSolver MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${SKETCHSOLVER_TEXT_RESOURCES})
+TARGET_LINK_LIBRARIES(PlaneGCSSolver ${PROJECT_LIBRARIES} ${SKETCHSOLVER_LIBRARIES})
 INSTALL(TARGETS PlaneGCSSolver DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
+INSTALL(FILES ${SKETCHSOLVER_TEXT_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
index 2bcf426597838c76b46ff37039e625378a2153c8..0706391bc1144696fb8e701be30ad03048f55130 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <PlaneGCSSolver_AngleWrapper.h>
 
-#include <math.h>
+#include <cmath>
 
 static double deg2rad(double theDegrees)
 {
@@ -19,9 +19,9 @@ static double rad2deg(double theRadians)
 }
 
 PlaneGCSSolver_AngleWrapper::PlaneGCSSolver_AngleWrapper(double *const theParam)
-  : PlaneGCSSolver_ParameterWrapper(theParam)
+  : PlaneGCSSolver_ScalarWrapper(theParam)
 {
-  setValue(*myValue);
+  setValue(*theParam);
 }
 
 void PlaneGCSSolver_AngleWrapper::setValue(double theValue)
index 0eb1f6c509315ad5427ae4e8478d4d374a94a574..189e391a9af0abb4e3ccbd4e9bba203ab1f43f56 100644 (file)
@@ -7,12 +7,13 @@
 #ifndef PlaneGCSSolver_AngleWrapper_H_
 #define PlaneGCSSolver_AngleWrapper_H_
 
-#include <PlaneGCSSolver_ParameterWrapper.h>
+#include <PlaneGCSSolver_ScalarWrapper.h>
 
 /**
  *  Wrapper providing operations with angular parameters in PlaneGCS.
+ *  Provides automatic conversion from degrees to radians and vice versa.
  */
-class PlaneGCSSolver_AngleWrapper : public PlaneGCSSolver_ParameterWrapper
+class PlaneGCSSolver_AngleWrapper : public PlaneGCSSolver_ScalarWrapper
 {
 public:
   PlaneGCSSolver_AngleWrapper(double *const theParam);
diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp
new file mode 100644 (file)
index 0000000..1cae520
--- /dev/null
@@ -0,0 +1,95 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    PlaneGCSSolver_AttributeBuilder.cpp
+// Created: 10 Feb 2017
+// Author:  Artem ZHIDKOV
+
+#include <PlaneGCSSolver_AngleWrapper.h>
+#include <PlaneGCSSolver_AttributeBuilder.h>
+#include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_ScalarWrapper.h>
+
+#include <GeomDataAPI_Point2D.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <SketchPlugin_ConstraintAngle.h>
+#include <SketchPlugin_MultiRotation.h>
+
+PlaneGCSSolver_AttributeBuilder::PlaneGCSSolver_AttributeBuilder(
+    PlaneGCSSolver_Storage* theStorage)
+  : PlaneGCSSolver_EntityBuilder(theStorage)
+{
+}
+
+PlaneGCSSolver_AttributeBuilder::PlaneGCSSolver_AttributeBuilder(const StoragePtr& theStorage)
+  : PlaneGCSSolver_EntityBuilder(
+        std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(theStorage).get())
+{
+}
+
+static double* createParameter(PlaneGCSSolver_Storage* theStorage)
+{
+  return theStorage ? theStorage->createParameter() : (new double(0));
+}
+
+static EntityWrapperPtr createScalar(const AttributePtr&     theAttribute,
+                                     PlaneGCSSolver_Storage* theStorage)
+{
+  AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
+  if (!aScalar)
+    return EntityWrapperPtr();
+
+  ScalarWrapperPtr aWrapper;
+  // following attributes should be converted from degrees to radians
+  //  - value of the Angle constraint
+  //  - angle of the Multi-Rotation constraint
+  FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
+  if ((theAttribute->id() == SketchPlugin_Constraint::VALUE() &&
+      anOwner->getKind() == SketchPlugin_ConstraintAngle::ID()) ||
+     (theAttribute->id() == SketchPlugin_MultiRotation::ANGLE_ID() &&
+      anOwner->getKind() == SketchPlugin_MultiRotation::ID()))
+    aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_AngleWrapper(createParameter(theStorage)));
+  else
+    aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(theStorage)));
+
+  aWrapper->setValue(aScalar->value());
+  return aWrapper;
+}
+
+static EntityWrapperPtr createPoint(const AttributePtr&     theAttribute,
+                                    PlaneGCSSolver_Storage* theStorage)
+{
+  std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
+  if (!aPoint2D)
+    return EntityWrapperPtr();
+
+  GCSPointPtr aNewPoint(new GCS::Point);
+
+  aNewPoint->x = createParameter(theStorage);
+  *(aNewPoint->x) = aPoint2D->x();
+  aNewPoint->y = createParameter(theStorage);
+  *(aNewPoint->y) = aPoint2D->y();
+
+  return EntityWrapperPtr(new PlaneGCSSolver_PointWrapper(aNewPoint));
+}
+
+EntityWrapperPtr PlaneGCSSolver_AttributeBuilder::createAttribute(
+    AttributePtr theAttribute)
+{
+  EntityWrapperPtr aResult;
+  if (myStorage)
+    aResult = myStorage->entity(theAttribute);
+  if (!aResult)
+    aResult = createPoint(theAttribute, myStorage);
+  if (!aResult)
+    aResult = createScalar(theAttribute, myStorage);
+  if (aResult && !myStorage)
+    aResult->setExternal(true);
+  return aResult;
+}
+
+const std::list<GCSConstraintPtr>& PlaneGCSSolver_AttributeBuilder::constraints() const
+{
+  static std::list<GCSConstraintPtr> aList;
+  return aList;
+}
diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.h
new file mode 100644 (file)
index 0000000..cdf586b
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File:    PlaneGCSSolver_AttributeBuilder.h
+// Created: 10 Feb 2017
+// Author:  Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_AttributeBuilder_H_
+#define PlaneGCSSolver_AttributeBuilder_H_
+
+#include <PlaneGCSSolver_EntityBuilder.h>
+
+/** \class   PlaneGCSSolver_AttributeBuilder
+ *  \ingroup Plugins
+ *  \brief   Converts ModelAPI_Attribute to the entity applicable for PlaneGCS solver
+ */
+class PlaneGCSSolver_AttributeBuilder : public PlaneGCSSolver_EntityBuilder
+{
+public:
+  PlaneGCSSolver_AttributeBuilder(PlaneGCSSolver_Storage* theStorage = 0);
+  PlaneGCSSolver_AttributeBuilder(const StoragePtr& theStorage);
+
+  /// \brief Converts an attribute to the solver's entity.
+  ///        Double attributes and 2D points are supported only.
+  /// \param theAttribute [in]  attribute to create
+  /// \return Created wrapper of the attribute applicable for specific solver
+  virtual EntityWrapperPtr createAttribute(AttributePtr theAttribute) override;
+
+  /// \brief Blank. To be defined in derived class.
+  virtual EntityWrapperPtr createFeature(FeaturePtr) override
+  { return EntityWrapperPtr(); }
+
+  /// \brief Blank. To be defined in derived class.
+  virtual const std::list<GCSConstraintPtr>& constraints() const override;
+};
+
+#endif
index 743d843e41554359e908b15d195fe52e85155983..fb81a64a2d8208fd06673b02dafdb19029213aa1 100644 (file)
@@ -5,10 +5,7 @@
 // Author:  Artem ZHIDKOV
 
 #include <PlaneGCSSolver_Builder.h>
-#include <PlaneGCSSolver_Solver.h>
 #include <PlaneGCSSolver_Storage.h>
-#include <PlaneGCSSolver_ParameterWrapper.h>
-#include <PlaneGCSSolver_AngleWrapper.h>
 #include <PlaneGCSSolver_EntityWrapper.h>
 #include <PlaneGCSSolver_PointWrapper.h>
 #include <PlaneGCSSolver_ScalarWrapper.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 <SketchPlugin_IntersectionPoint.h>
 #include <SketchPlugin_ConstraintAngle.h>
 
-#include <math.h>
+#include <cmath>
 
 
 #define GCS_ENTITY_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(x)
-#define GCS_POINT_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(x)
-#define GCS_PARAMETER_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(x)
-
-
-/// \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
-static ParameterWrapperPtr createParameter(const GroupID& theGroup,
-                                           const double theValue = 0.0,
-                                           const bool theExpr = false);
-
-static ParameterWrapperPtr createParamAngle(const GroupID& theGroup,
-                                            const double& theValue = 0.0);
-
-static std::shared_ptr<PlaneGCSSolver_ScalarWrapper>
-    createScalar(const GroupID& theGroupID,
-                 AttributeDoublePtr theDoubleAttr = AttributeDoublePtr());
+#define GCS_POINT_WRAPPER(x)  std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(x)
+#define GCS_SCALAR_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(x)
 
-static EntityWrapperPtr createLine(FeaturePtr theFeature,
-                                   const std::list<EntityWrapperPtr>& theAttributes,
-                                   const GroupID& theGroupID);
-static EntityWrapperPtr createCircle(FeaturePtr theFeature,
-                                     const std::list<EntityWrapperPtr>& theAttributes,
-                                     const GroupID& theGroupID);
-static EntityWrapperPtr createArc(FeaturePtr theFeature,
-                                  const std::list<EntityWrapperPtr>& theAttributes,
-                                  const GroupID& theGroupID);
 
 
 static ConstraintWrapperPtr
-  createConstraintCoincidence(ConstraintPtr theConstraint,
-                              const GroupID& theGroupID,
-                              std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
+  createConstraintCoincidence(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
                               std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
 static ConstraintWrapperPtr
-  createConstraintPointOnEntity(ConstraintPtr theConstraint,
-                                const GroupID& theGroupID,
-                                const SketchSolver_ConstraintType& theType,
+  createConstraintPointOnEntity(const SketchSolver_ConstraintType& theType,
                                 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
                                 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
 static ConstraintWrapperPtr
-  createConstraintDistancePointPoint(ConstraintPtr theConstraint,
-                                     const GroupID& theGroupID,
-                                     std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+  createConstraintDistancePointPoint(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
                                      std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
                                      std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
 static ConstraintWrapperPtr
-  createConstraintDistancePointLine(ConstraintPtr theConstraint,
-                                    const GroupID& theGroupID,
-                                    std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
-                                    std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
+  createConstraintDistancePointLine(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
+                                    std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint,
                                     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
 static ConstraintWrapperPtr
-  createConstraintRadius(ConstraintPtr theConstraint,
-                         const GroupID& theGroupID,
-                         std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+  createConstraintRadius(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
                          std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
 static ConstraintWrapperPtr
   createConstraintAngle(ConstraintPtr theConstraint,
-                        const GroupID& theGroupID,
-                        std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+                        std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
                         std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
                         std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
 static ConstraintWrapperPtr
-  createConstraintHorizVert(ConstraintPtr theConstraint,
-                            const GroupID& theGroupID,
-                            const SketchSolver_ConstraintType& theType,
+  createConstraintHorizVert(const SketchSolver_ConstraintType& theType,
                             std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
 static ConstraintWrapperPtr
-  createConstraintParallel(ConstraintPtr theConstraint,
-                           const GroupID& theGroupID,
-                           std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
+  createConstraintParallel(std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
                            std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
 static ConstraintWrapperPtr
-  createConstraintPerpendicular(ConstraintPtr theConstraint,
-                                const GroupID& theGroupID,
-                                std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
+  createConstraintPerpendicular(std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
                                 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
 static ConstraintWrapperPtr
-  createConstraintEqual(ConstraintPtr theConstraint,
-                        const GroupID& theGroupID,
-                        const SketchSolver_ConstraintType& theType,
+  createConstraintEqual(const SketchSolver_ConstraintType& theType,
                         std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
                         std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
-                        std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed);
+                        std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theIntermed);
 static ConstraintWrapperPtr
-  createConstraintTangent(ConstraintPtr theConstraint,
-                          const GroupID& theGroupID,
-                          const SketchSolver_ConstraintType& theType,
+  createConstraintTangent(const SketchSolver_ConstraintType& theType,
                           std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
                           std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
 static ConstraintWrapperPtr
   createConstraintCollinear(ConstraintPtr theConstraint,
-                           const GroupID& theGroupID,
                            std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
                            std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
 static ConstraintWrapperPtr
-  createConstraintMiddlePoint(ConstraintPtr theConstraint,
-                              const GroupID& theGroupID,
-                              std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
+  createConstraintMiddlePoint(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
                               std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
 
 
 
-/// \brief Update mirror points
-static void adjustMirror(ConstraintWrapperPtr theConstraint);
-/// \brief Update a sign of the point-line distance constraint
-static void adjustPtLineDistance(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 PlaneGCSSolver_Builder::mySelf = PlaneGCSSolver_Builder::getInstance();
+// Initialization of pointer to builder
+static BuilderPtr gBuilder = PlaneGCSSolver_Builder::getInstance();
 
 BuilderPtr PlaneGCSSolver_Builder::getInstance()
 {
+  static BuilderPtr mySelf;
   if (!mySelf) {
     mySelf = BuilderPtr(new PlaneGCSSolver_Builder);
     SketchSolver_Manager::instance()->setBuilder(mySelf);
@@ -166,9 +90,9 @@ BuilderPtr PlaneGCSSolver_Builder::getInstance()
   return mySelf;
 }
 
-StoragePtr PlaneGCSSolver_Builder::createStorage(const GroupID& theGroup) const
+StoragePtr PlaneGCSSolver_Builder::createStorage(const SolverPtr& theSolver) const
 {
-  return StoragePtr(new PlaneGCSSolver_Storage(theGroup));
+  return StoragePtr(new PlaneGCSSolver_Storage(theSolver));
 }
 
 SolverPtr PlaneGCSSolver_Builder::createSolver() const
@@ -177,422 +101,155 @@ SolverPtr PlaneGCSSolver_Builder::createSolver() const
 }
 
 
-std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
+ConstraintWrapperPtr PlaneGCSSolver_Builder::createConstraint(
     ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
-    const EntityID& theSketchID,
     const SketchSolver_ConstraintType& theType,
-    const double& theValue,
+    const EntityWrapperPtr& theValue,
     const EntityWrapperPtr& thePoint1,
     const EntityWrapperPtr& thePoint2,
     const EntityWrapperPtr& theEntity1,
     const EntityWrapperPtr& theEntity2) const
 {
   ConstraintWrapperPtr aResult;
-  ParameterWrapperPtr anIntermediate;
+  ScalarWrapperPtr anIntermediate;
 
   std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(thePoint1);
-  if (!aPoint1 && thePoint1 && thePoint1->type() == ENTITY_POINT)
-    aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint1)->subEntities().front() );
   std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(thePoint2);
-  if (!aPoint2 && thePoint2 && thePoint2->type() == ENTITY_POINT)
-    aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint2)->subEntities().front() );
 
   switch (theType) {
   case CONSTRAINT_PT_PT_COINCIDENT:
-    aResult = createConstraintCoincidence(theConstraint, theGroupID, aPoint1, aPoint2);
+    aResult = createConstraintCoincidence(aPoint1, aPoint2);
     break;
   case CONSTRAINT_PT_ON_LINE:
   case CONSTRAINT_PT_ON_CIRCLE:
-    aResult = createConstraintPointOnEntity(theConstraint, theGroupID, theType,
-                  aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
+    aResult = createConstraintPointOnEntity(theType, aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
     break;
   case CONSTRAINT_MIDDLE_POINT:
-    aResult = createConstraintMiddlePoint(theConstraint, theGroupID,
-                  aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
+    aResult = createConstraintMiddlePoint(aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
     break;
   case CONSTRAINT_PT_PT_DISTANCE:
-    aResult = createConstraintDistancePointPoint(theConstraint, theGroupID,
-                  GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
-                  aPoint1, aPoint2);
+    aResult = createConstraintDistancePointPoint(GCS_SCALAR_WRAPPER(theValue), aPoint1, aPoint2);
     break;
   case CONSTRAINT_PT_LINE_DISTANCE:
-    aResult = createConstraintDistancePointLine(theConstraint, theGroupID,
-                  GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
-                  aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
+    aResult = createConstraintDistancePointLine(GCS_SCALAR_WRAPPER(theValue),
+                                                aPoint1,
+                                                GCS_ENTITY_WRAPPER(theEntity1));
     break;
   case CONSTRAINT_RADIUS:
-    aResult = createConstraintRadius(theConstraint, theGroupID,
-                  GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
-                  GCS_ENTITY_WRAPPER(theEntity1));
+    aResult = createConstraintRadius(GCS_SCALAR_WRAPPER(theValue),
+                                     GCS_ENTITY_WRAPPER(theEntity1));
     break;
   case CONSTRAINT_ANGLE:
-    aResult = createConstraintAngle(theConstraint, theGroupID,
-                  GCS_PARAMETER_WRAPPER(createParamAngle(GID_OUTOFGROUP, theValue)),
+    aResult = createConstraintAngle(theConstraint,
+                  GCS_SCALAR_WRAPPER(theValue),
                   GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
     break;
   case CONSTRAINT_FIXED:
     break;
   case CONSTRAINT_HORIZONTAL:
   case CONSTRAINT_VERTICAL:
-    aResult = createConstraintHorizVert(theConstraint, theGroupID, theType,
-                  GCS_ENTITY_WRAPPER(theEntity1));
+    aResult = createConstraintHorizVert(theType, GCS_ENTITY_WRAPPER(theEntity1));
     break;
   case CONSTRAINT_PARALLEL:
-    aResult = createConstraintParallel(theConstraint, theGroupID,
-                  GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
+    aResult = createConstraintParallel(GCS_ENTITY_WRAPPER(theEntity1),
+                                       GCS_ENTITY_WRAPPER(theEntity2));
     break;
   case CONSTRAINT_PERPENDICULAR:
-    aResult = createConstraintPerpendicular(theConstraint, theGroupID,
-                  GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
+    aResult = createConstraintPerpendicular(GCS_ENTITY_WRAPPER(theEntity1),
+                                            GCS_ENTITY_WRAPPER(theEntity2));
     break;
   case CONSTRAINT_EQUAL_LINES:
-    anIntermediate = createParameter(theGroupID);
+    anIntermediate = GCS_SCALAR_WRAPPER(theValue); // parameter is used to store length of lines
   case CONSTRAINT_EQUAL_LINE_ARC:
   case CONSTRAINT_EQUAL_RADIUS:
-    aResult = createConstraintEqual(theConstraint, theGroupID, theType,
-                  GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2),
-                  GCS_PARAMETER_WRAPPER(anIntermediate));
+    aResult = createConstraintEqual(theType,
+                                    GCS_ENTITY_WRAPPER(theEntity1),
+                                    GCS_ENTITY_WRAPPER(theEntity2),
+                                    anIntermediate);
     break;
   case CONSTRAINT_TANGENT_ARC_LINE:
   case CONSTRAINT_TANGENT_CIRCLE_LINE:
   case CONSTRAINT_TANGENT_ARC_ARC:
-    aResult = createConstraintTangent(theConstraint, theGroupID, theType,
-                  GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
+    aResult = createConstraintTangent(theType,
+                                      GCS_ENTITY_WRAPPER(theEntity1),
+                                      GCS_ENTITY_WRAPPER(theEntity2));
     break;
   case CONSTRAINT_COLLINEAR:
-    aResult = createConstraintCollinear(theConstraint, theGroupID,
+    aResult = createConstraintCollinear(theConstraint,
                   GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
     break;
   case CONSTRAINT_MULTI_TRANSLATION:
   case CONSTRAINT_MULTI_ROTATION:
-    break;
   case CONSTRAINT_SYMMETRIC:
-    return createMirror(theConstraint, theGroupID, theSketchID,
-                        thePoint1, thePoint2, theEntity1);
   default:
     break;
   }
 
-  if (!aResult)
-    return std::list<ConstraintWrapperPtr>();
-  adjustConstraint(aResult);
-  return std::list<ConstraintWrapperPtr>(1, aResult);
+  return aResult;
 }
 
-std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
+ConstraintWrapperPtr PlaneGCSSolver_Builder::createConstraint(
     ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
-    const EntityID& theSketchID,
     const SketchSolver_ConstraintType& theType,
-    const double& theValue,
+    const EntityWrapperPtr& theValue,
     const bool theFullValue,
     const EntityWrapperPtr& thePoint1,
     const EntityWrapperPtr& thePoint2,
     const std::list<EntityWrapperPtr>& theTrsfEnt) const
 {
-  ParameterWrapperPtr anAngleParam;
-  if (theType == CONSTRAINT_MULTI_ROTATION)
-    anAngleParam = createParamAngle(theGroupID, theValue);
-  else if (theType != CONSTRAINT_MULTI_TRANSLATION)
-    return std::list<ConstraintWrapperPtr>();
+  if (theType != CONSTRAINT_MULTI_ROTATION && theType != CONSTRAINT_MULTI_TRANSLATION)
+    return ConstraintWrapperPtr();
 
   std::list<EntityWrapperPtr> aConstrAttrList = theTrsfEnt;
   if (thePoint2)
     aConstrAttrList.push_front(thePoint2);
   aConstrAttrList.push_front(thePoint1);
 
+  ScalarWrapperPtr aValue = GCS_SCALAR_WRAPPER(theValue);
+
   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
-      new PlaneGCSSolver_ConstraintWrapper(theConstraint, std::list<GCSConstraintPtr>(), theType));
-  aResult->setGroup(theGroupID);
+      new PlaneGCSSolver_ConstraintWrapper(std::list<GCSConstraintPtr>(), theType));
   aResult->setEntities(aConstrAttrList);
-  if (anAngleParam)
-    aResult->setValueParameter(anAngleParam);
+  if (aValue)
+    aResult->setValueParameter(aValue);
   aResult->setIsFullValue(theFullValue);
-  return std::list<ConstraintWrapperPtr>(1, aResult);
-}
-
-
-std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createMirror(
-    ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
-    const EntityID& theSketchID,
-    const EntityWrapperPtr& theEntity1,
-    const EntityWrapperPtr& theEntity2,
-    const EntityWrapperPtr& theMirrorLine) const
-{
-  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);
-
-    std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(theEntity1);
-    if (!aPoint1 && theEntity1->type() == ENTITY_POINT)
-      aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity1)->subEntities().front() );
-    std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(theEntity2);
-    if (!aPoint2 && theEntity2->type() == ENTITY_POINT)
-      aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity2)->subEntities().front() );
-
-    std::shared_ptr<PlaneGCSSolver_EntityWrapper> aMirrorLine =
-        std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMirrorLine);
-    std::shared_ptr<GCS::Line> aLine =
-        std::dynamic_pointer_cast<GCS::Line>(aMirrorLine->entity());
-
-    std::list<GCSConstraintPtr> aConstrList;
-    aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintMidpointOnLine(
-        *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
-    aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
-        *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
-
-    ConstraintWrapperPtr aSubResult(new PlaneGCSSolver_ConstraintWrapper(
-        theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
-    aSubResult->setGroup(theGroupID);
-    std::list<EntityWrapperPtr> aSubs(1, theEntity1);
-    aSubs.push_back(theEntity2);
-    aSubs.push_back(theMirrorLine);
-    aSubResult->setEntities(aSubs);
-    aResult.push_back(aSubResult);
-  }
-  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();
-    bool aWasBlocked = aMirrArc->data()->blockSendAttributeUpdated(true);
-
-    // Make mirror for center and start point of original arc
-    std::list<ConstraintWrapperPtr> aMrrList;
-    std::list<EntityWrapperPtr>::const_iterator anIt1 = theEntity1->subEntities().begin();
-    std::list<EntityWrapperPtr>::const_iterator anIt2 = theEntity2->subEntities().begin();
-    aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
-    aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
-
-    ++anIt1;
-    ++anIt2; ++anIt2;
-    aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
-    aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
-
-    // make symmetric last point of original arc and first point of
-    // mirrored arc without additional constraint
-    ++anIt1;
-    --anIt2;
-    makeMirrorPoints(*anIt1, *anIt2, theMirrorLine);
-
-    // Additionally, make equal radii...
-    aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
-        0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
-    aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
-    // ... and make parametric length of arcs the same
-    std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt1 =
-        std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity1);
-    std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt2 =
-        std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity2);
-    std::shared_ptr<GCS::Arc> anArc1 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt1->entity());
-    std::shared_ptr<GCS::Arc> anArc2 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt2->entity());
-    std::shared_ptr<PlaneGCSSolver_ParameterWrapper> anIntermed =
-        std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(
-        createParameter(theGroupID, *(anArc1->endAngle) - *(anArc1->startAngle)));
-    // By the way, recalculate start and end angles of mirrored arc
-    std::shared_ptr<GeomAPI_Dir2d> anOX(new GeomAPI_Dir2d(1.0, 0.0));
-    std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(
-        *(anArc2->start.x) - *(anArc2->center.x), *(anArc2->start.y) - *(anArc2->center.y)));
-    std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(
-        *(anArc2->end.x) - *(anArc2->center.x), *(anArc2->end.y) - *(anArc2->center.y)));
-    *anArc2->startAngle = anOX->angle(aStartDir);
-    *anArc2->endAngle = anOX->angle(aEndDir);
-
-    std::list<GCSConstraintPtr> aConstrList;
-    aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
-        anArc1->endAngle, anArc1->startAngle, anIntermed->parameter())));
-    aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
-        anArc2->endAngle, anArc2->startAngle, anIntermed->parameter())));
-
-    std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aSubResult(
-        new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
-    aSubResult->setGroup(theGroupID);
-    std::list<EntityWrapperPtr> aSubs(1, theEntity1);
-    aSubs.push_back(theEntity2);
-    aSubs.push_back(theMirrorLine);
-    aSubResult->setEntities(aSubs);
-    aSubResult->setValueParameter(anIntermed);
-    aResult.push_back(aSubResult);
-
-    // Restore event sending
-    aMirrArc->data()->blockSendAttributeUpdated(aWasBlocked);
-  }
   return aResult;
 }
 
-void PlaneGCSSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstraint) const
+std::shared_ptr<GeomAPI_Pnt2d> PlaneGCSSolver_Builder::point(EntityWrapperPtr theEntity) const
 {
-  SketchSolver_ConstraintType aType = theConstraint->type();
-  // Update flags and parameters in constraints
-  if (aType == CONSTRAINT_PT_LINE_DISTANCE)
-    adjustPtLineDistance(theConstraint);
-  else if (aType == CONSTRAINT_SYMMETRIC)
-    adjustMirror(theConstraint);
-}
+  if (theEntity->type() != ENTITY_POINT)
+    return std::shared_ptr<GeomAPI_Pnt2d>();
 
-EntityWrapperPtr PlaneGCSSolver_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);
-  // Circle
-  else if (aFeatureKind == SketchPlugin_Circle::ID())
-    return createCircle(theFeature, theAttributes, theGroupID);
-  // Arc
-  else if (aFeatureKind == SketchPlugin_Arc::ID())
-    return createArc(theFeature, theAttributes, theGroupID);
-  // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
-  else if (aFeatureKind == SketchPlugin_Point::ID() ||
-           aFeatureKind == SketchPlugin_IntersectionPoint::ID()) {
-    EntityWrapperPtr aSub;
-    if (theAttributes.size() == 1)
-      aSub = theAttributes.front();
-    else {
-      AttributePtr aPoint = theFeature->attribute(SketchPlugin_Point::COORD_ID());
-      if (aPoint->isInitialized())
-        aSub = createAttribute(aPoint, theGroupID);
-    }
-    if (!aSub)
-      return aDummy;
-
-    GCSPointPtr aSubEnt =
-        std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aSub)->point();
-    EntityWrapperPtr aNewEntity(new PlaneGCSSolver_EntityWrapper(theFeature));
-    aNewEntity->setSubEntities(std::list<EntityWrapperPtr>(1, aSub));
-    return aNewEntity;
-  }
-
-  // wrong entity
-  return aDummy;
+  std::shared_ptr<PlaneGCSSolver_PointWrapper> aPointWrapper =
+      std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
+  const GCSPointPtr& aPoint = aPointWrapper->point();
+  return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(*aPoint->x, *aPoint->y));
 }
 
-EntityWrapperPtr PlaneGCSSolver_Builder::createAttribute(
-    AttributePtr theAttribute,
-    const GroupID& theGroupID,
-    const EntityID& theSketchID) const
+std::shared_ptr<GeomAPI_Lin2d> PlaneGCSSolver_Builder::line(EntityWrapperPtr theEntity) 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;
-  EntityWrapperPtr aResult;
-
-  // 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()));
-    GCSPointPtr aGCSPoint(new GCS::Point);
-    aGCSPoint->x = std::dynamic_pointer_cast<
-      PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
-    aGCSPoint->y = std::dynamic_pointer_cast<
-      PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
-    // Create entity (parameters are not filled)
-    aResult = EntityWrapperPtr(new PlaneGCSSolver_PointWrapper(theAttribute, aGCSPoint));
-  } else {
-    // Scalar value (used for the distance entities)
-    AttributeDoublePtr aScalar =
-      std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
-    if (aScalar)
-      return createScalar(theGroupID, aScalar);
-  }
-
-  if (!aResult) {
-    // unknown attribute type
-    return EntityWrapperPtr();
-  }
+  if (theEntity->type() != ENTITY_LINE)
+    return std::shared_ptr<GeomAPI_Lin2d>();
 
-  aResult->setGroup(theGroupID);
-  aResult->setParameters(aParameters);
-  return aResult;
+  std::shared_ptr<PlaneGCSSolver_EntityWrapper> anEntity =
+      std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity);
+  std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
+  return std::shared_ptr<GeomAPI_Lin2d>(
+      new GeomAPI_Lin2d(*(aLine->p1.x), *(aLine->p1.y), *(aLine->p2.x), *(aLine->p2.y)));
 }
 
-ParameterWrapperPtr PlaneGCSSolver_Builder::createParameter(
-    const GroupID& theGroupID, double theValue) const
+std::shared_ptr<GeomAPI_Lin2d> PlaneGCSSolver_Builder::line(FeaturePtr theFeature) const
 {
-  return ::createParameter(theGroupID, theValue);
-}
+  if (theFeature->getKind() != SketchPlugin_Line::ID())
+    return std::shared_ptr<GeomAPI_Lin2d>();
 
+  AttributePoint2DPtr aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->attribute(SketchPlugin_Line::START_ID()));
+  AttributePoint2DPtr aEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->attribute(SketchPlugin_Line::END_ID()));
 
-EntityWrapperPtr PlaneGCSSolver_Builder::createSketchEntity(
-    CompositeFeaturePtr theSketch,
-    const GroupID& theGroupID) const
-{
-  DataPtr aSketchData = theSketch->data();
-  if (!aSketchData || !aSketchData->isValid())
-    return EntityWrapperPtr(); // the sketch is incorrect
-
-  // Create dummy wrapper representing workplane
-  std::shared_ptr<PlaneGCSSolver_EntityWrapper> aSketchEnt(
-      new PlaneGCSSolver_EntityWrapper(FeaturePtr(theSketch)));
-  aSketchEnt->setGroup(theGroupID);
-  aSketchEnt->setId(EID_SKETCH);
-  return aSketchEnt;
+  return std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aStart->pnt(), aEnd->pnt()));
 }
 
 
@@ -600,205 +257,25 @@ EntityWrapperPtr PlaneGCSSolver_Builder::createSketchEntity(
 
 
 // ================   Auxiliary functions   ==========================
-ParameterWrapperPtr createParameter(
-    const GroupID& theGroup, const double theValue, const bool theExpr)
-{
-  double* aParam = new double(theValue);
-  ParameterWrapperPtr aWrapper(new PlaneGCSSolver_ParameterWrapper(aParam));
-  aWrapper->setGroup(theGroup);
-  aWrapper->setIsParametric(theExpr);
-  return aWrapper;
-}
-
-ParameterWrapperPtr createParamAngle(const GroupID& theGroup, const double& theValue)
-{
-  double* aParam = new double(theValue);
-  ParameterWrapperPtr aWrapper(new PlaneGCSSolver_AngleWrapper(aParam));
-  aWrapper->setGroup(theGroup);
-  return aWrapper;
-}
-
-std::shared_ptr<PlaneGCSSolver_ScalarWrapper> createScalar(
-    const GroupID& theGroupID,
-    AttributeDoublePtr theDoubleAttr)
-{
-  ParameterWrapperPtr aParam =
-    createParameter(theGroupID, theDoubleAttr ? theDoubleAttr->value() : 0.0);
-  return std::shared_ptr<PlaneGCSSolver_ScalarWrapper>(
-      new PlaneGCSSolver_ScalarWrapper(theDoubleAttr, aParam));
-}
-
-EntityWrapperPtr createLine(FeaturePtr theFeature,
-                            const std::list<EntityWrapperPtr>& theAttributes,
-                            const GroupID& theGroupID)
-{
-  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;
-
-  std::shared_ptr<PlaneGCSSolver_PointWrapper> aStartEnt, aEndEnt;
-  std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
-  for (; anIt != theAttributes.end(); ++anIt) {
-    std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
-        std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
-    if (!aWrapper)
-      continue;
-    if (aWrapper->isBase(aStart))
-      aStartEnt = aWrapper;
-    else if (aWrapper->isBase(aEnd))
-      aEndEnt = aWrapper;
-  }
-  if (!aStartEnt || !aEndEnt)
-    return aNewEntity;
-
-  aSubs.push_back(aStartEnt);
-  aSubs.push_back(aEndEnt);
-
-  std::shared_ptr<GCS::Line> aLine(new GCS::Line);
-  aLine->p1 = *(aStartEnt->point());
-  aLine->p2 = *(aEndEnt->point());
-
-  aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aLine));
-  // sub-entities should not change their groups, therefore they are added later
-  aNewEntity->setGroup(theGroupID);
-  aNewEntity->setSubEntities(aSubs);
-  return aNewEntity;
-}
-
-EntityWrapperPtr createCircle(FeaturePtr theFeature,
-                              const std::list<EntityWrapperPtr>& theAttributes,
-                              const GroupID& theGroupID)
-{
-  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;
-
-  std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt;
-  std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aRadiusEnt;
-  std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
-  for (; anIt != theAttributes.end(); ++anIt) {
-    if ((*anIt)->isBase(aCenter))
-      aCenterEnt = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
-    else if ((*anIt)->isBase(aRadius))
-      aRadiusEnt = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*anIt);
-  }
-  if (!aCenterEnt || !aRadiusEnt)
-    return aNewEntity;
-
-  aSubs.push_back(aCenterEnt);
-  aSubs.push_back(aRadiusEnt);
-
-  std::shared_ptr<GCS::Circle> aCircle(new GCS::Circle);
-  aCircle->center = *(aCenterEnt->point());
-  aCircle->rad = aRadiusEnt->scalar();
-
-  aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aCircle));
-  // sub-entities should not change their groups, therefore they are added later
-  aNewEntity->setGroup(theGroupID);
-  aNewEntity->setSubEntities(aSubs);
-  return aNewEntity;
-}
-
-EntityWrapperPtr createArc(FeaturePtr theFeature,
-                           const std::list<EntityWrapperPtr>& theAttributes,
-                           const GroupID& theGroupID)
-{
-  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;
-
-  std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt, aStartEnt, aEndEnt;
-  std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
-  for (; anIt != theAttributes.end(); ++anIt) {
-    std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
-        std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
-    if (!aWrapper)
-      continue;
-    if (aWrapper->isBase(aCenter))
-      aCenterEnt = aWrapper;
-    else if (aWrapper->isBase(aStart))
-      aStartEnt = aWrapper;
-    else if (aWrapper->isBase(aEnd))
-      aEndEnt = aWrapper;
-  }
-  if (!aCenterEnt || !aStartEnt || !aEndEnt)
-    return aNewEntity;
-
-  std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aStartAng, aEndAng, aRadius;
-  aStartAng = createScalar(theGroupID);
-  aEndAng   = createScalar(theGroupID);
-  aRadius   = createScalar(theGroupID);
-
-  aSubs.push_back(aCenterEnt);
-  aSubs.push_back(aStartEnt);
-  aSubs.push_back(aEndEnt);
-  aSubs.push_back(aStartAng);
-  aSubs.push_back(aEndAng);
-  aSubs.push_back(aRadius);
-
-  std::shared_ptr<GCS::Arc> anArc(new GCS::Arc);
-  anArc->center     = *(aCenterEnt->point());
-  anArc->start      = *(aStartEnt->point());
-  anArc->end        = *(aEndEnt->point());
-  anArc->startAngle = aStartAng->scalar();
-  anArc->endAngle   = aEndAng->scalar();
-  anArc->rad        = aRadius->scalar();
-
-  aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, anArc));
-  // sub-entities should not change their groups, therefore they are added later
-  aNewEntity->setGroup(theGroupID);
-  aNewEntity->setSubEntities(aSubs);
-  return aNewEntity;
-}
-
-
-
 ConstraintWrapperPtr createConstraintCoincidence(
-    ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
 {
+  GCSPointPtr aPoint1 = thePoint1->point();
+  GCSPointPtr aPoint2 = thePoint2->point();
+
   // Create equality constraint for corresponding attributes of the points
   std::list<GCSConstraintPtr> aConstrList;
-  std::list<ParameterWrapperPtr>::const_iterator anIt1 = thePoint1->parameters().begin();
-  std::list<ParameterWrapperPtr>::const_iterator anIt2 = thePoint2->parameters().begin();
-  for (; anIt1 != thePoint1->parameters().end(); ++anIt1, ++anIt2) {
-    if (*anIt1 == *anIt2)
-      continue; // points use same parameters, no need additional constraints
-    std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam1 =
-        std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt1);
-    std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam2 =
-        std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt2);
-    aConstrList.push_back(
-        GCSConstraintPtr(new GCS::ConstraintEqual(aParam1->parameter(), aParam2->parameter())));
-  }
+  aConstrList.push_back(
+      GCSConstraintPtr(new GCS::ConstraintEqual(aPoint1->x, aPoint2->x)));
+  aConstrList.push_back(
+      GCSConstraintPtr(new GCS::ConstraintEqual(aPoint1->y, aPoint2->y)));
 
-  ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
-      theConstraint, aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
-  aResult->setGroup(theGroupID);
-  std::list<EntityWrapperPtr> aSubs(1, thePoint1);
-  aSubs.push_back(thePoint2);
-  aResult->setEntities(aSubs);
-  return aResult;
+  return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(
+      aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
 }
 
 ConstraintWrapperPtr createConstraintPointOnEntity(
-    ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
     const SketchSolver_ConstraintType& theType,
     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
@@ -823,34 +300,10 @@ ConstraintWrapperPtr createConstraintPointOnEntity(
     return ConstraintWrapperPtr();
   }
 
-  ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
-      theConstraint, aNewConstr, theType));
-  aResult->setGroup(theGroupID);
-  std::list<EntityWrapperPtr> aSubs(1, thePoint);
-  aSubs.push_back(theEntity);
-  aResult->setEntities(aSubs);
-  return aResult;
-}
-
-// calculate length of the line
-static inline double lineLength(const GCS::Line& theLine)
-{
-  double aDir[2] = {*(theLine.p2.x) - *(theLine.p1.x), *(theLine.p2.y) - *(theLine.p1.y)};
-  return sqrt(aDir[0] * aDir[0] + aDir[1] * aDir[1]);
-}
-
-// check the point is on the line
-static inline bool isPointOnLine(const GCS::Point& thePoint, const GCS::Line& theLine)
-{
-  double aDir[2] = {*(theLine.p2.x) - *(theLine.p1.x), *(theLine.p2.y) - *(theLine.p1.y)};
-  double aVec[2] = {*(thePoint.x) - *(theLine.p1.x), *(thePoint.y) - *(theLine.p1.y)};
-  double aCross = aVec[0] * aDir[1] - aVec[1] * aDir[0];
-  return fabs(aCross) < tolerance;
+  return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
 }
 
 ConstraintWrapperPtr createConstraintMiddlePoint(
-    ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
 {
@@ -860,102 +313,58 @@ ConstraintWrapperPtr createConstraintMiddlePoint(
     return ConstraintWrapperPtr();
 
   std::list<GCSConstraintPtr> aConstrList;
+  aConstrList.push_back(
+      GCSConstraintPtr(new GCS::ConstraintPointOnPerpBisector(*aPoint, aLine->p1, aLine->p2)));
   aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPointOnLine(*aPoint, *aLine)));
-  double aDist = lineLength(*aLine);
-  std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aDistance =
-      std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(
-      createParameter(theGroupID, aDist * 0.5));
-  aConstrList.push_back(GCSConstraintPtr(
-      new GCS::ConstraintP2PDistance(*aPoint, aLine->p1, aDistance->parameter())));
-  aConstrList.push_back(GCSConstraintPtr(
-      new GCS::ConstraintP2PDistance(*aPoint, aLine->p2, aDistance->parameter())));
-
-  // Workaround to avoid conflicting constraints when the point is already placed on line
-  if (thePoint->group() != GID_UNKNOWN && isPointOnLine(*aPoint, *aLine)) {
-    std::shared_ptr<GeomDataAPI_Point2D> aCoord =
-        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(thePoint->baseAttribute());
-    if (aCoord) {
-      *(aPoint->x) = (*(aLine->p1.x) + *(aLine->p2.x)) * 0.5;
-      *(aPoint->y) = (*(aLine->p1.y) + *(aLine->p2.y)) * 0.5;
-      aCoord->setValue(*(aPoint->x), *(aPoint->y));
-    }
-  }
 
-  std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(new PlaneGCSSolver_ConstraintWrapper(
-      theConstraint, aConstrList, CONSTRAINT_MIDDLE_POINT));
-  aResult->setGroup(theGroupID);
-  std::list<EntityWrapperPtr> aSubs(1, thePoint);
-  aSubs.push_back(theEntity);
-  aResult->setEntities(aSubs);
-  aResult->setValueParameter(aDistance);
-  return aResult;
+  return ConstraintWrapperPtr(
+      new PlaneGCSSolver_ConstraintWrapper(aConstrList, CONSTRAINT_MIDDLE_POINT));
 }
 
 
 ConstraintWrapperPtr createConstraintDistancePointPoint(
-    ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
-    std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
-    std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
-    std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
+    std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
+    std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint1,
+    std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint2)
 {
   GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
-      *(thePoint1->point()), *(thePoint2->point()), theValue->parameter()));
-
+      *(thePoint1->point()), *(thePoint2->point()), theValue->scalar()));
   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
-      new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
-  aResult->setGroup(theGroupID);
-  std::list<EntityWrapperPtr> aSubs(1, thePoint1);
-  aSubs.push_back(thePoint2);
-  aResult->setEntities(aSubs);
+      new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
   aResult->setValueParameter(theValue);
   return aResult;
 }
 
 ConstraintWrapperPtr createConstraintDistancePointLine(
-    ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
-    std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
-    std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
+    std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
+    std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
 {
   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
   GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
-      *(thePoint->point()), *(aLine), theValue->parameter()));
-
+      *(thePoint->point()), *(aLine), theValue->scalar()));
   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
-      new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
-  aResult->setGroup(theGroupID);
-  std::list<EntityWrapperPtr> aSubs(1, thePoint);
-  aSubs.push_back(theEntity);
-  aResult->setEntities(aSubs);
+      new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
   aResult->setValueParameter(theValue);
   return aResult;
 }
 
 ConstraintWrapperPtr createConstraintRadius(
-    ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
-    std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+    std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
 {
   std::shared_ptr<GCS::Circle> aCircle =
     std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
-  GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->parameter()));
-
+  GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->scalar()));
   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
-      new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_RADIUS));
-  aResult->setGroup(theGroupID);
-  std::list<EntityWrapperPtr> aSubs(1, theEntity);
-  aResult->setEntities(aSubs);
+      new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_RADIUS));
   aResult->setValueParameter(theValue);
   return aResult;
 }
 
 ConstraintWrapperPtr createConstraintAngle(
     ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
-    std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+    std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
 {
@@ -972,21 +381,15 @@ ConstraintWrapperPtr createConstraintAngle(
   GCS::Point aLine2Pt2 = isLine2Rev ? aLine2->p1 : aLine2->p2;
 
   GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
-      aLine1Pt1, aLine1Pt2, aLine2Pt1, aLine2Pt2, theValue->parameter()));
+      aLine1Pt1, aLine1Pt2, aLine2Pt1, aLine2Pt2, theValue->scalar()));
 
   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
-      new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_ANGLE));
-  aResult->setGroup(theGroupID);
-  std::list<EntityWrapperPtr> aSubs(1, theEntity1);
-  aSubs.push_back(theEntity2);
-  aResult->setEntities(aSubs);
+      new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_ANGLE));
   aResult->setValueParameter(theValue);
   return aResult;
 }
 
 ConstraintWrapperPtr createConstraintHorizVert(
-    ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
     const SketchSolver_ConstraintType& theType,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
 {
@@ -997,17 +400,11 @@ ConstraintWrapperPtr createConstraintHorizVert(
   else
     aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
 
-  ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
-      theConstraint, aNewConstr, theType));
-  aResult->setGroup(theGroupID);
-  std::list<EntityWrapperPtr> aSubs(1, theEntity);
-  aResult->setEntities(aSubs);
-  return aResult;
+  return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
 }
 
 ConstraintWrapperPtr createConstraintCollinear(
     ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
 {
@@ -1019,18 +416,11 @@ ConstraintWrapperPtr createConstraintCollinear(
   aConstrList.push_back( GCSConstraintPtr(new GCS::ConstraintPointOnLine(aLine2->p1, *aLine1)) );
   aConstrList.push_back( GCSConstraintPtr(new GCS::ConstraintPointOnLine(aLine2->p2, *aLine1)) );
 
-  ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
-      theConstraint, aConstrList, CONSTRAINT_COLLINEAR));
-  aResult->setGroup(theGroupID);
-  std::list<EntityWrapperPtr> aSubs(1, theEntity1);
-  aSubs.push_back(theEntity2);
-  aResult->setEntities(aSubs);
-  return aResult;
+  return ConstraintWrapperPtr(
+      new PlaneGCSSolver_ConstraintWrapper(aConstrList, CONSTRAINT_COLLINEAR));
 }
 
 ConstraintWrapperPtr createConstraintParallel(
-    ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
 {
@@ -1038,18 +428,11 @@ ConstraintWrapperPtr createConstraintParallel(
   std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
   GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
 
-  std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
-      new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PARALLEL));
-  aResult->setGroup(theGroupID);
-  std::list<EntityWrapperPtr> aSubs(1, theEntity1);
-  aSubs.push_back(theEntity2);
-  aResult->setEntities(aSubs);
-  return aResult;
+  return ConstraintWrapperPtr(
+      new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PARALLEL));
 }
 
 ConstraintWrapperPtr createConstraintPerpendicular(
-    ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
 {
@@ -1057,22 +440,15 @@ ConstraintWrapperPtr createConstraintPerpendicular(
   std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
   GCSConstraintPtr aNewConstr(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
 
-  std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
-      new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PERPENDICULAR));
-  aResult->setGroup(theGroupID);
-  std::list<EntityWrapperPtr> aSubs(1, theEntity1);
-  aSubs.push_back(theEntity2);
-  aResult->setEntities(aSubs);
-  return aResult;
+  return ConstraintWrapperPtr(
+      new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PERPENDICULAR));
 }
 
 ConstraintWrapperPtr createConstraintEqual(
-    ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
     const SketchSolver_ConstraintType& theType,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
-    std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed)
+    std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theIntermed)
 {
   if (theType == CONSTRAINT_EQUAL_LINE_ARC)
     return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
@@ -1083,9 +459,9 @@ ConstraintWrapperPtr createConstraintEqual(
     std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
 
     aConstrList.push_back(GCSConstraintPtr(
-        new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->parameter())));
+        new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->scalar())));
     aConstrList.push_back(GCSConstraintPtr(
-        new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->parameter())));
+        new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->scalar())));
     // update value of intermediate parameter
     double x = *aLine1->p1.x - *aLine1->p2.x;
     double y = *aLine1->p1.y - *aLine1->p2.y;
@@ -1101,19 +477,13 @@ ConstraintWrapperPtr createConstraintEqual(
   }
 
   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
-      new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, theType));
-  aResult->setGroup(theGroupID);
-  std::list<EntityWrapperPtr> aSubs(1, theEntity1);
-  aSubs.push_back(theEntity2);
-  aResult->setEntities(aSubs);
+      new PlaneGCSSolver_ConstraintWrapper(aConstrList, theType));
   if (theIntermed)
     aResult->setValueParameter(theIntermed);
   return aResult;
 }
 
 ConstraintWrapperPtr createConstraintTangent(
-    ConstraintPtr theConstraint,
-    const GroupID& theGroupID,
     const SketchSolver_ConstraintType& theType,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
@@ -1140,93 +510,7 @@ ConstraintWrapperPtr createConstraintTangent(
         aCirc1->rad, aCirc2->rad, (aDist < *(aCirc1->rad) || aDist < *(aCirc2->rad))));
   }
 
-  std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
-      new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, theType));
-  aResult->setGroup(theGroupID);
-  std::list<EntityWrapperPtr> aSubs(1, theEntity1);
-  aSubs.push_back(theEntity2);
-  aResult->setEntities(aSubs);
-  return aResult;
-}
-
-
-
-
-
-void makeMirrorPoints(EntityWrapperPtr theOriginal,
-                      EntityWrapperPtr theMirrored,
-                      EntityWrapperPtr theMirrorLine)
-{
-  BuilderPtr aBuilder = PlaneGCSSolver_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<PlaneGCSSolver_PointWrapper>(theMirrored)->baseAttribute();
-  if (anAttr) {
-    std::shared_ptr<GeomDataAPI_Point2D> aMirroredPnt =
-      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
-    aMirroredPnt->setValue(aCoord[0], aCoord[1]);
-  }
-}
-
-void adjustPtLineDistance(ConstraintWrapperPtr theConstraint)
-{
-  BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
-
-  std::shared_ptr<GeomAPI_Pnt2d> aPoint;
-  std::shared_ptr<GeomAPI_Lin2d> aLine;
-  std::list<EntityWrapperPtr> aSubs = theConstraint->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) * theConstraint->value() < 0.0)
-    theConstraint->setValue(theConstraint->value() * (-1.0));
-}
-
-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;
-  }
-
-  if (aPoints.size() == 2)
-    makeMirrorPoints(aPoints[0], aPoints[1], aMirrorLine);
-
-  // update scales of constraints
-  std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aGCSConstraint =
-      std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
-  std::list<GCSConstraintPtr>::const_iterator aCIt = aGCSConstraint->constraints().begin();
-  for (; aCIt != aGCSConstraint->constraints().end(); ++aCIt)
-    (*aCIt)->rescale();
+  return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
 }
 
 bool PlaneGCSSolver_Builder::isArcArcTangencyInternal(
@@ -1246,4 +530,3 @@ bool PlaneGCSSolver_Builder::isArcArcTangencyInternal(
 
   return (aDist < *(aCirc1->rad) || aDist < *(aCirc2->rad));
 }
-
index ea9042a6fcf3aa7b9d82ea358bd99fefba6832a1..62b9ff3270b135c8cdf5240348e40663b6e222a7 100644 (file)
@@ -22,7 +22,6 @@
  */
 class PlaneGCSSolver_Builder : public SketchSolver_Builder
 {
-private:
   /// Default constructor
   PlaneGCSSolver_Builder() {}
 
@@ -31,14 +30,12 @@ public:
   static BuilderPtr getInstance();
 
   /// \brief Creates a storage specific for used solver
-  virtual StoragePtr createStorage(const GroupID& theGroup) const;
+  virtual StoragePtr createStorage(const SolverPtr& theSolver) const override;
   /// \brief Creates specific solver
-  virtual SolverPtr createSolver() const;
+  virtual SolverPtr createSolver() const override;
 
-  /// \brief Creates new constraint(s) using given parameters
+  /// \brief Creates new constraint 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
@@ -46,24 +43,18 @@ public:
   /// \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>
+  /// \return Created wrapper of constraints applicable for specific solver.
+  virtual ConstraintWrapperPtr
     createConstraint(ConstraintPtr theConstraint,
-                     const GroupID& theGroupID,
-                     const EntityID& theSketchID,
                      const SketchSolver_ConstraintType& theType,
-                     const double& theValue,
+                     const EntityWrapperPtr& theValue,
                      const EntityWrapperPtr& theEntity1,
                      const EntityWrapperPtr& theEntity2 = EntityWrapperPtr(),
                      const EntityWrapperPtr& theEntity3 = EntityWrapperPtr(),
-                     const EntityWrapperPtr& theEntity4 = EntityWrapperPtr()) const;
+                     const EntityWrapperPtr& theEntity4 = EntityWrapperPtr()) const override;
 
   /// \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
@@ -72,68 +63,30 @@ public:
   /// \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>
+  virtual ConstraintWrapperPtr
     createConstraint(ConstraintPtr theConstraint,
-                     const GroupID& theGroupID,
-                     const EntityID& theSketchID,
                      const SketchSolver_ConstraintType& theType,
-                     const double& theValue,
+                     const EntityWrapperPtr& theValue,
                      const bool theFullValue,
                      const EntityWrapperPtr& thePoint1,
                      const EntityWrapperPtr& thePoint2,
-                     const std::list<EntityWrapperPtr>& theTrsfEnt) const;
+                     const std::list<EntityWrapperPtr>& theTrsfEnt) const override;
 
-  /// \brief Update flags for several kinds of constraints
-  virtual void adjustConstraint(ConstraintWrapperPtr theConstraint) const;
+  /// \brief Convert entity to point
+  /// \return empty pointer if the entity is not a point
+  virtual std::shared_ptr<GeomAPI_Pnt2d> point(EntityWrapperPtr theEntity) const override;
+  /// \brief Convert entity to line
+  /// \return empty pointer if the entity is not a line
+  virtual std::shared_ptr<GeomAPI_Lin2d> line(EntityWrapperPtr theEntity) const override;
 
-  /// \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;
-
-  /// \brief Create a parameter
-  /// \param theGroupID [in]  group the parameter belongs to
-  /// \param theValue   [in]  value of the parameter
-  /// \return Created wrapper for parameter
-  ParameterWrapperPtr createParameter(const GroupID& theGroupID, double theValue = 0.0) const;
+  /// \brief Convert entity to line
+  /// \return empty pointer if the entity is not a line
+  virtual std::shared_ptr<GeomAPI_Lin2d> line(FeaturePtr theFeature) const override;
 
   /// \brief Check if two connected arcs have centers
   ///        in same direction relatively to connection point
-  virtual bool isArcArcTangencyInternal(EntityWrapperPtr theArc1, EntityWrapperPtr theArc2) 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;
-
-private:
-  static BuilderPtr mySelf;
+  virtual bool isArcArcTangencyInternal(EntityWrapperPtr theArc1,
+                                        EntityWrapperPtr theArc2) const override;
 };
 
 #endif
index a2be38efe0ea444771532bb37d0e1069005be4e9..a9924a77343c99319d5956e31f59eab17ec38eb5 100644 (file)
@@ -6,30 +6,22 @@
 
 #include <PlaneGCSSolver_ConstraintWrapper.h>
 
-#include <math.h>
-
 PlaneGCSSolver_ConstraintWrapper::PlaneGCSSolver_ConstraintWrapper(
-    const ConstraintPtr& theOriginal,
     const GCSConstraintPtr& theConstraint,
     const SketchSolver_ConstraintType& theType)
   : myGCSConstraints(1, theConstraint),
-    myType(theType),
-    myID(CID_UNKNOWN)
+    myType(theType)
 {
-  myBaseConstraint = theOriginal;
-  myValue = 0.0;
+  myID = CID_UNKNOWN;
 }
 
 PlaneGCSSolver_ConstraintWrapper::PlaneGCSSolver_ConstraintWrapper(
-    const ConstraintPtr& theOriginal,
     const std::list<GCSConstraintPtr>& theConstraints,
     const SketchSolver_ConstraintType& theType)
   : myGCSConstraints(theConstraints),
-    myType(theType),
-    myID(CID_UNKNOWN)
+    myType(theType)
 {
-  myBaseConstraint = theOriginal;
-  myValue = 0.0;
+  myID = CID_UNKNOWN;
 }
 
 void PlaneGCSSolver_ConstraintWrapper::setId(const ConstraintID& theID)
@@ -40,81 +32,17 @@ void PlaneGCSSolver_ConstraintWrapper::setId(const ConstraintID& theID)
     (*anIt)->setTag((int)theID);
 }
 
-void PlaneGCSSolver_ConstraintWrapper::setValueParameter(const ParameterWrapperPtr& theValue)
+void PlaneGCSSolver_ConstraintWrapper::setValueParameter(const ScalarWrapperPtr& theValue)
 {
   myValueParam = theValue;
-  myValue = myValueParam->value();
 }
 
 void PlaneGCSSolver_ConstraintWrapper::setValue(const double& theValue)
 {
-  myValue = theValue;
   myValueParam->setValue(theValue);
 }
 
-
-void PlaneGCSSolver_ConstraintWrapper::setGroup(const GroupID& theGroup)
-{
-  myGroup = theGroup;
-  std::list<EntityWrapperPtr>::iterator aSubsIt = myConstrained.begin();
-  for (; aSubsIt != myConstrained.end(); ++aSubsIt)
-    (*aSubsIt)->setGroup(theGroup);
-}
-
-bool PlaneGCSSolver_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 PlaneGCSSolver_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 PlaneGCSSolver_ConstraintWrapper::isEqual(const ConstraintWrapperPtr& theOther)
+double PlaneGCSSolver_ConstraintWrapper::value() const
 {
-  if (type() != theOther->type())
-    return false;
-
-  // 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 PlaneGCSSolver_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;
+  return myValueParam->value();
 }
index ebf65ea657852ec52b2db754b28f020f6f030fde..216905155dd2e30354da5f05b6b3b77983dd2896 100644 (file)
@@ -9,20 +9,19 @@
 
 #include <PlaneGCSSolver_Defs.h>
 #include <PlaneGCSSolver_Solver.h>
+#include <PlaneGCSSolver_ScalarWrapper.h>
 #include <SketchSolver_IConstraintWrapper.h>
 
 
 /**
- *  Wrapper providing operations with SovleSpace constraints.
+ *  Wrapper providing operations with PlaneGCS constraints.
  */
 class PlaneGCSSolver_ConstraintWrapper : public SketchSolver_IConstraintWrapper
 {
 public:
-  PlaneGCSSolver_ConstraintWrapper(const ConstraintPtr& theOriginal,
-                                   const GCSConstraintPtr& theConstraint,
+  PlaneGCSSolver_ConstraintWrapper(const GCSConstraintPtr&            theConstraint,
                                    const SketchSolver_ConstraintType& theType);
-  PlaneGCSSolver_ConstraintWrapper(const ConstraintPtr& theOriginal,
-                                   const std::list<GCSConstraintPtr>& theConstraints,
+  PlaneGCSSolver_ConstraintWrapper(const std::list<GCSConstraintPtr>& theConstraints,
                                    const SketchSolver_ConstraintType& theType);
 
   /// \brief Return list of constraints
@@ -32,17 +31,8 @@ public:
   void setConstraints(const std::list<GCSConstraintPtr>& theConstraints)
   { myGCSConstraints = theConstraints; }
 
-  /// \brief Return ID of current entity
-  virtual ConstraintID id() const
-  { return myID; }
   /// \brief Change constraint ID
-  void setId( const ConstraintID& theID);
-
-  /// \brief Change group for the constraint
-  virtual void setGroup(const GroupID& theGroup);
-  /// \brief Return identifier of the group the constraint belongs to
-  virtual GroupID group() const
-  { return myGroup; }
+  virtual void setId(const ConstraintID& theID);
 
   /// \brief Return type of current entity
   virtual SketchSolver_ConstraintType type() const
@@ -50,30 +40,18 @@ public:
 
   /// \brief Assign numeric parameter of constraint
   virtual void setValue(const double& theValue);
+  /// \brief Return numeric parameter of constraint
+  virtual double value() const;
 
   /// \brief Change parameter representing the value of constraint
-  void setValueParameter(const ParameterWrapperPtr& theValue);
+  void setValueParameter(const ScalarWrapperPtr& theValue);
   /// \brief Return parametric representation of constraint value
-  const ParameterWrapperPtr& valueParameter() const
+  const ScalarWrapperPtr& valueParameter() const
   { return myValueParam; }
 
-  /// \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:
-  ConstraintID     myID;
-  GroupID          myGroup;
   SketchSolver_ConstraintType myType;
-  ParameterWrapperPtr myValueParam;
+  ScalarWrapperPtr            myValueParam;
   std::list<GCSConstraintPtr> myGCSConstraints;
 };
 
diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityBuilder.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityBuilder.h
new file mode 100644 (file)
index 0000000..d4eb9d9
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File:    PlaneGCSSolver_EntityBuilder.h
+// Created: 14 Feb 2017
+// Author:  Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_EntityBuilder_H_
+#define PlaneGCSSolver_EntityBuilder_H_
+
+#include <PlaneGCSSolver_Defs.h>
+#include <PlaneGCSSolver_Storage.h>
+
+/** \class   PlaneGCSSolver_EntityBuilder
+ *  \ingroup Plugins
+ *  \brief   API to convert data model entity to the entity applicable for PlaneGCS solver
+ */
+class PlaneGCSSolver_EntityBuilder
+{
+public:
+  /// \brief Create entity in the given storage.
+  ///        If the storage is empty, the entity should not be changed
+  ///         while constraint solving. So, it is created out of the storage.
+  PlaneGCSSolver_EntityBuilder(PlaneGCSSolver_Storage* theStorage = 0)
+    : myStorage(theStorage)
+  {}
+
+  virtual ~PlaneGCSSolver_EntityBuilder() {}
+
+  /// \brief Converts an attribute to the solver's entity.
+  ///        Double attributes and 2D points are supported only.
+  /// \param theAttribute [in]  attribute to create
+  /// \return Created wrapper of the attribute applicable for specific solver
+  virtual EntityWrapperPtr createAttribute(AttributePtr theAttribute) = 0;
+
+  /// \brief Converts SketchPlugin's feature to the solver's entity.
+  ///        Result if based on the list of already converted attributes.
+  /// \param theFeature [in]  feature to create
+  virtual EntityWrapperPtr createFeature(FeaturePtr) = 0;
+
+  /// \brief Return list of constraints necessary to fix feature's extra DoF
+  virtual const std::list<GCSConstraintPtr>& constraints() const = 0;
+
+protected:
+  PlaneGCSSolver_Storage* myStorage;
+};
+
+#endif
diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityDestroyer.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityDestroyer.cpp
new file mode 100644 (file)
index 0000000..697d2db
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    PlaneGCSSolver_EntityDestroyer.cpp
+// Created: 10 Feb 2017
+// Author:  Artem ZHIDKOV
+
+#include <PlaneGCSSolver_EntityDestroyer.h>
+
+#include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_ScalarWrapper.h>
+#include <PlaneGCSSolver_EntityWrapper.h>
+
+static void destroyScalar(const EntityWrapperPtr& theEntity, GCS::SET_pD& theParams)
+{
+  ScalarWrapperPtr aScalar = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(theEntity);
+  theParams.insert(aScalar->scalar());
+}
+
+static void destroyPoint(const EntityWrapperPtr& theEntity, GCS::SET_pD& theParams)
+{
+  std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+      std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
+  theParams.insert(aPoint->point()->x);
+  theParams.insert(aPoint->point()->y);
+}
+
+static void destroyLine(const EntityWrapperPtr& theEntity, GCS::SET_pD& theParams)
+{
+  std::shared_ptr<PlaneGCSSolver_EntityWrapper> anEntity =
+      std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity);
+  std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
+  theParams.insert(aLine->p1.x);
+  theParams.insert(aLine->p1.y);
+  theParams.insert(aLine->p2.x);
+  theParams.insert(aLine->p2.y);
+}
+
+static void destroyCircle(const EntityWrapperPtr& theEntity, GCS::SET_pD& theParams)
+{
+  std::shared_ptr<PlaneGCSSolver_EntityWrapper> anEntity =
+      std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity);
+  std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(anEntity->entity());
+  theParams.insert(aCirc->center.x);
+  theParams.insert(aCirc->center.y);
+  theParams.insert(aCirc->rad);
+}
+
+static void destroyArc(const EntityWrapperPtr& theEntity, GCS::SET_pD& theParams)
+{
+  std::shared_ptr<PlaneGCSSolver_EntityWrapper> anEntity =
+      std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity);
+  std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEntity->entity());
+  theParams.insert(anArc->center.x);
+  theParams.insert(anArc->center.y);
+  theParams.insert(anArc->start.x);
+  theParams.insert(anArc->start.y);
+  theParams.insert(anArc->end.x);
+  theParams.insert(anArc->end.y);
+  theParams.insert(anArc->startAngle);
+  theParams.insert(anArc->endAngle);
+  theParams.insert(anArc->rad);
+}
+
+void PlaneGCSSolver_EntityDestroyer::remove(const EntityWrapperPtr& theEntity)
+{
+  GCS::SET_pD& aParamSet = theEntity->isExternal() ? myParamsOutOfStorage : myParams;
+
+  switch (theEntity->type()) {
+  case ENTITY_SCALAR:
+  case ENTITY_ANGLE:
+    destroyScalar(theEntity, aParamSet);
+    break;
+  case ENTITY_POINT:
+    destroyPoint(theEntity, aParamSet);
+    break;
+  case ENTITY_LINE:
+    destroyLine(theEntity, aParamSet);
+    break;
+  case ENTITY_CIRCLE:
+    destroyCircle(theEntity, aParamSet);
+    break;
+  case ENTITY_ARC:
+    destroyArc(theEntity, aParamSet);
+    break;
+  default: break;
+  }
+}
diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityDestroyer.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityDestroyer.h
new file mode 100644 (file)
index 0000000..043797f
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File:    PlaneGCSSolver_EntityDestroyer.h
+// Created: 10 Feb 2017
+// Author:  Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_EntityDestroyer_H_
+#define PlaneGCSSolver_EntityDestroyer_H_
+
+#include <PlaneGCSSolver_Defs.h>
+#include <PlaneGCSSolver_Storage.h>
+
+/** \class   PlaneGCSSolver_EntityDestroyer
+ *  \ingroup Plugins
+ *  \brief   Collect entities of PlaneGCS solver which should be removed
+ */
+class PlaneGCSSolver_EntityDestroyer
+{
+public:
+  PlaneGCSSolver_EntityDestroyer() {}
+
+  /// \brief Add entity to remove. Its parameters are stored for further remove from the storage.
+  void remove(const EntityWrapperPtr& theEntity);
+
+  /// \brief Return parameters to remove
+  const GCS::SET_pD& parametersToRemove()
+  { return myParams; }
+
+private:
+  GCS::SET_pD myParams; ///< set of parameters to be removed
+  GCS::SET_pD myParamsOutOfStorage; ///< set of parameters not kept in the storage
+};
+
+#endif
index e1dbad9be4327832cf53dfdd7b060e54268f8241..907ca61675d8392bd4a0f169134344ecd5ff9511 100644 (file)
@@ -5,17 +5,10 @@
 // Author:  Artem ZHIDKOV
 
 #include <PlaneGCSSolver_EntityWrapper.h>
-#include <SketchPlugin_Point.h>
-#include <SketchPlugin_IntersectionPoint.h>
-#include <SketchPlugin_Sketch.h>
 
-PlaneGCSSolver_EntityWrapper::PlaneGCSSolver_EntityWrapper(
-    const FeaturePtr theFeature, const GCSCurvePtr theEntity)
-  : myEntity(theEntity),
-    myID(EID_UNKNOWN)
+PlaneGCSSolver_EntityWrapper::PlaneGCSSolver_EntityWrapper(const GCSCurvePtr theEntity)
+  : myEntity(theEntity)
 {
-  myBaseFeature = theFeature;
-
   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(myEntity);
   if (aLine) myType = ENTITY_LINE;
   else {
@@ -26,95 +19,4 @@ PlaneGCSSolver_EntityWrapper::PlaneGCSSolver_EntityWrapper(
       if (aCircle) myType = ENTITY_CIRCLE;
     }
   }
-
-  // empty entity, probably this is a SketchPlugin_Point or SketchPlugin_Sketch
-  if (theFeature->getKind() == SketchPlugin_Point::ID() ||
-      theFeature->getKind() == SketchPlugin_IntersectionPoint::ID())
-    myType = ENTITY_POINT;
-  else if (theFeature->getKind() == SketchPlugin_Sketch::ID())
-    myType = ENTITY_SKETCH;
-}
-
-void PlaneGCSSolver_EntityWrapper::setGroup(const GroupID& theGroup)
-{
-  myGroup = 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);
-}
-
-bool PlaneGCSSolver_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 PlaneGCSSolver_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 PlaneGCSSolver_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 PlaneGCSSolver_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;
 }
index 5fb99ddb40d29096543dc133c3c8dfd98ba08037..38c92198a494a3d8d08476be9bc18a5db407cd5f 100644 (file)
 #include <SketchSolver_IEntityWrapper.h>
 
 /**
- *  Wrapper providing operations with PlaneGCS entities.
+ *  Wrapper providing operations with PlaneGCS entities (lines, circles and arcs).
  */
 class PlaneGCSSolver_EntityWrapper : public SketchSolver_IEntityWrapper
 {
 public:
-  PlaneGCSSolver_EntityWrapper(const FeaturePtr theFeature,
-                               const GCSCurvePtr theEntity = GCSCurvePtr());
+  PlaneGCSSolver_EntityWrapper(const GCSCurvePtr theEntity);
 
   /// \brief Return PlaneGCS geometric entity
   const GCSCurvePtr& entity() const
@@ -26,38 +25,11 @@ public:
   GCSCurvePtr& changeEntity()
   { return myEntity; }
 
-  /// \brief Return ID of current entity
-  virtual EntityID id() const
-  { return myID; }
-  /// \brief Change ID of the entity
-  void setId(EntityID theID)
-  { myID = theID; }
-
-  /// \brief Change group for the entity
-  virtual void setGroup(const GroupID& theGroup);
-  /// \brief Return identifier of the group the entity belongs to
-  virtual GroupID group() const
-  { return myGroup; }
-
   /// \brief Return type of current entity
   virtual SketchSolver_EntityType type() const
   { return myType; }
 
-  /// \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 EntityWrapperPtr& theOther);
-
 private:
-  EntityID    myID;
-  GroupID     myGroup;
   SketchSolver_EntityType myType;
   GCSCurvePtr myEntity;
 };
diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp
new file mode 100644 (file)
index 0000000..fdcc98b
--- /dev/null
@@ -0,0 +1,201 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    PlaneGCSSolver_AttributeBuilder.cpp
+// Created: 10 Feb 2017
+// Author:  Artem ZHIDKOV
+
+#include <PlaneGCSSolver_FeatureBuilder.h>
+#include <PlaneGCSSolver_EntityWrapper.h>
+#include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_ScalarWrapper.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_IntersectionPoint.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_XY.h>
+
+static EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes);
+static EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes);
+static EntityWrapperPtr createArc(const AttributeEntityMap&    theAttributes,
+                                  PlaneGCSSolver_Storage*      theStorage,
+                                  std::list<GCSConstraintPtr>& theArcConstraints);
+
+
+PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(
+    PlaneGCSSolver_Storage* theStorage)
+  : PlaneGCSSolver_AttributeBuilder(theStorage)
+{
+}
+
+PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(const StoragePtr& theStorage)
+  : PlaneGCSSolver_AttributeBuilder(theStorage)
+{
+}
+
+EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createAttribute(
+    AttributePtr theAttribute)
+{
+  EntityWrapperPtr anAttr = PlaneGCSSolver_AttributeBuilder::createAttribute(theAttribute);
+  if (anAttr)
+    myAttributes[theAttribute] = anAttr;
+  return anAttr;
+}
+
+EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createFeature(FeaturePtr theFeature)
+{
+  EntityWrapperPtr aResult;
+  if (myStorage)
+    aResult = myStorage->entity(theFeature);
+  if (aResult)
+    return aResult;
+
+  // Process SketchPlugin features only
+  std::shared_ptr<SketchPlugin_Feature> aFeature =
+      std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
+  if (!aFeature)
+    return aResult;
+
+  // Verify the feature by its kind
+  const std::string& aFeatureKind = aFeature->getKind();
+  // Line
+  if (aFeatureKind == SketchPlugin_Line::ID())
+    aResult = createLine(myAttributes);
+  // Circle
+  else if (aFeatureKind == SketchPlugin_Circle::ID())
+    aResult = createCircle(myAttributes);
+  // Arc
+  else if (aFeatureKind == SketchPlugin_Arc::ID())
+    aResult = createArc(myAttributes, myStorage, myFeatureConstraints);
+  // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
+  else if (aFeatureKind == SketchPlugin_Point::ID() ||
+           aFeatureKind == SketchPlugin_IntersectionPoint::ID()) {
+    AttributeEntityMap::const_iterator anIt = myAttributes.begin();
+    for (; anIt != myAttributes.end(); ++anIt)
+      if (anIt->first->id() == SketchPlugin_Point::COORD_ID()) {
+        aResult = anIt->second;
+        break;
+      }
+  }
+
+  if (aResult && !myStorage)
+    aResult->setExternal(true);
+
+  myAttributes.clear();
+  return aResult;
+}
+
+
+
+
+
+// ==============   Auxiliary functions   =====================================
+EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes)
+{
+  std::shared_ptr<GCS::Line> aNewLine(new GCS::Line);
+
+  AttributeEntityMap::const_iterator anIt = theAttributes.begin();
+  for (; anIt != theAttributes.end(); ++anIt) {
+    std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+        std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+    if (!aPoint)
+      continue;
+
+    if (anIt->first->id() == SketchPlugin_Line::START_ID())
+      aNewLine->p1 = *(aPoint->point());
+    else if (anIt->first->id() == SketchPlugin_Line::END_ID())
+      aNewLine->p2 = *(aPoint->point());
+  }
+
+  return EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(aNewLine));
+}
+
+EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes)
+{
+  std::shared_ptr<GCS::Circle> aNewCircle(new GCS::Circle);
+
+  AttributeEntityMap::const_iterator anIt = theAttributes.begin();
+  for (; anIt != theAttributes.end(); ++anIt) {
+    if (anIt->first->id() == SketchPlugin_Circle::CENTER_ID()) {
+      std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+          std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+      aNewCircle->center = *(aPoint->point());
+    }
+    else if(anIt->first->id() == SketchPlugin_Circle::RADIUS_ID()) {
+      ScalarWrapperPtr aScalar =
+          std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
+      aNewCircle->rad = aScalar->scalar();
+    }
+  }
+
+  return EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(aNewCircle));
+}
+
+static double* createParameter(PlaneGCSSolver_Storage* theStorage)
+{
+  return theStorage ? theStorage->createParameter() : (new double(0));
+}
+
+EntityWrapperPtr createArc(const AttributeEntityMap&    theAttributes,
+                           PlaneGCSSolver_Storage*      theStorage,
+                           std::list<GCSConstraintPtr>& theArcConstraints)
+{
+  std::shared_ptr<GCS::Arc> aNewArc(new GCS::Arc);
+
+  // Base attributes of arc (center, start and end points)
+  AttributeEntityMap::const_iterator anIt = theAttributes.begin();
+  for (; anIt != theAttributes.end(); ++anIt) {
+    std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+        std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+    if (!aPoint)
+      continue;
+
+    if (anIt->first->id() == SketchPlugin_Arc::CENTER_ID())
+      aNewArc->center = *(aPoint->point());
+    else if (anIt->first->id() == SketchPlugin_Arc::START_ID())
+      aNewArc->start = *(aPoint->point());
+    else if (anIt->first->id() == SketchPlugin_Arc::END_ID())
+      aNewArc->end = *(aPoint->point());
+  }
+
+  // Additional atrtributes of arc necessary for PlaneGCS solver
+  // (start and end angles, radius)
+  aNewArc->startAngle = createParameter(theStorage);
+  aNewArc->endAngle   = createParameter(theStorage);
+  aNewArc->rad        = createParameter(theStorage);
+
+  static std::shared_ptr<GeomAPI_Dir2d> OX(new GeomAPI_Dir2d(1.0, 0.0));
+  std::shared_ptr<GeomAPI_Pnt2d> aCenter(
+      new GeomAPI_Pnt2d(*aNewArc->center.x, *aNewArc->center.y));
+  std::shared_ptr<GeomAPI_Pnt2d> aStart(
+      new GeomAPI_Pnt2d(*aNewArc->start.x, *aNewArc->start.y));
+
+  *aNewArc->rad = aStart->distance(aCenter);
+
+  std::shared_ptr<GeomAPI_Dir2d> aDir(new GeomAPI_Dir2d(aStart->xy()->decreased(aCenter->xy())));
+  *aNewArc->startAngle = OX->angle(aDir);
+
+  aDir = std::shared_ptr<GeomAPI_Dir2d>(
+      new GeomAPI_Dir2d((*aNewArc->end.x) - aCenter->x(), (*aNewArc->end.y) - aCenter->y()));
+  *aNewArc->endAngle = OX->angle(aDir);
+
+  if (theStorage) {
+    // Additional constaints to fix arc's extra DoF (if the arc is not external):
+    // 1. distances from center till start and end points are equal to radius
+    theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
+        aNewArc->center, aNewArc->start, aNewArc->rad)));
+    theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
+        aNewArc->center, aNewArc->end, aNewArc->rad)));
+    // 2. angles of start and end points should be equal to the arc angles
+    theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
+        aNewArc->center, aNewArc->start, aNewArc->startAngle)));
+    theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
+        aNewArc->center, aNewArc->end, aNewArc->endAngle)));
+  }
+
+  return EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(aNewArc));
+}
diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.h
new file mode 100644 (file)
index 0000000..d08d5ab
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File:    PlaneGCSSolver_FeatureBuilder.h
+// Created: 10 Feb 2017
+// Author:  Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_FeatureBuilder_H_
+#define PlaneGCSSolver_FeatureBuilder_H_
+
+#include <PlaneGCSSolver_AttributeBuilder.h>
+
+typedef std::map<AttributePtr, EntityWrapperPtr> AttributeEntityMap;
+
+/** \class   PlaneGCSSolver_FeatureBuilder
+ *  \ingroup Plugins
+ *  \brief   Converts SketchPlugin_Feature to the entity applicable for PlaneGCS solver
+ */
+class PlaneGCSSolver_FeatureBuilder : public PlaneGCSSolver_AttributeBuilder
+{
+public:
+  PlaneGCSSolver_FeatureBuilder(PlaneGCSSolver_Storage* theStorage = 0);
+  PlaneGCSSolver_FeatureBuilder(const StoragePtr& theStorage);
+
+  /// \brief Converts an attribute to the solver's entity and stores it for further processing.
+  ///        Double attributes and 2D points are supported only.
+  /// \param theAttribute [in]  attribute to create
+  /// \return Created wrapper of the attribute applicable for specific solver
+  virtual EntityWrapperPtr createAttribute(AttributePtr theAttribute) override;
+
+  /// \brief Converts SketchPlugin's feature to the solver's entity.
+  ///        Result if based on the list of already converted attributes.
+  /// \param theFeature [in]  feature to create
+  virtual EntityWrapperPtr createFeature(FeaturePtr theFeature) override;
+
+  /// \brief Return list of constraints necessary to fix feature's extra DoF
+  virtual const std::list<GCSConstraintPtr>& constraints() const override
+  { return myFeatureConstraints; }
+
+private:
+  /// list of converted attributes (will be cleared when the feature is created)
+  AttributeEntityMap myAttributes;
+
+  /// constraints for the feature
+  /// (primarily used for constrain arcs, which have 9 parameters but 5 DoF)
+  std::list<GCSConstraintPtr> myFeatureConstraints;
+};
+
+#endif
diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ParameterWrapper.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ParameterWrapper.cpp
deleted file mode 100644 (file)
index 9c0dfde..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    PlaneGCSSolver_ParameterWrapper.cpp
-// Created: 14 Dec 2015
-// Author:  Artem ZHIDKOV
-
-#include <PlaneGCSSolver_ParameterWrapper.h>
-
-#include <math.h>
-
-PlaneGCSSolver_ParameterWrapper::PlaneGCSSolver_ParameterWrapper(double *const theParam)
-  : myValue(theParam),
-    myProcessing(false)
-{
-}
-
-PlaneGCSSolver_ParameterWrapper::~PlaneGCSSolver_ParameterWrapper()
-{
-  if (!myProcessing)
-    delete myValue;
-}
-
-void PlaneGCSSolver_ParameterWrapper::setValue(double theValue)
-{
-  *(myValue) = theValue;
-}
-
-double PlaneGCSSolver_ParameterWrapper::value() const
-{
-  return *(myValue);
-}
-
-bool PlaneGCSSolver_ParameterWrapper::isEqual(const ParameterWrapperPtr& theOther)
-{
-  return fabs(value() - theOther->value()) < tolerance;
-}
-
-bool PlaneGCSSolver_ParameterWrapper::update(const ParameterWrapperPtr& theOther)
-{
-  if (fabs(value() - theOther->value()) < tolerance)
-    return false;
-  setValue(theOther->value());
-  myIsParametric = theOther->isParametric();
-  return true;
-}
diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ParameterWrapper.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ParameterWrapper.h
deleted file mode 100644 (file)
index 757728e..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    PlaneGCSSolver_ParameterWrapper.h
-// Created: 14 Dec 2015
-// Author:  Artem ZHIDKOV
-
-#ifndef PlaneGCSSolver_ParameterWrapper_H_
-#define PlaneGCSSolver_ParameterWrapper_H_
-
-#include <PlaneGCSSolver_Defs.h>
-#include <SketchSolver_IParameterWrapper.h>
-
-/**
- *  Wrapper providing operations with parameters in PlaneGCS.
- */
-class PlaneGCSSolver_ParameterWrapper : public SketchSolver_IParameterWrapper
-{
-public:
-  PlaneGCSSolver_ParameterWrapper(double *const theParam);
-  virtual ~PlaneGCSSolver_ParameterWrapper();
-
-  /// \brief Return ID of current parameter
-  virtual ParameterID id() const
-  { return myID; }
-
-  double* parameter() const
-  { return myValue; }
-
-  /// \brief Change group for the parameter
-  virtual void setGroup(const GroupID& theGroup)
-  { myGroup = theGroup; }
-
-  /// \brief Return identifier of the group the parameter belongs to
-  virtual GroupID group() const
-  { return myGroup; }
-
-  /// \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 ParameterWrapperPtr& theOther);
-
-  /// \brief Shows the parameter is added to full list of parameters
-  bool isProcessed() const
-  { return myProcessing; }
-  /// \brief Set the flag that parameter is under processing
-  void setProcessed(bool isProc)
-  { myProcessing = isProc; }
-
-protected:
-  ParameterID myID;
-  GroupID     myGroup;
-  double*     myValue;
-  bool        myProcessing; ///< identify that the parameter is already in the list of parameters
-};
-
-#endif
index a1e66e5871c1e58650a0f87a9b3a7cbc9918023d..31426d0178a69f57441bc73578edf20861b2b00f 100644 (file)
@@ -6,56 +6,7 @@
 
 #include <PlaneGCSSolver_PointWrapper.h>
 
-PlaneGCSSolver_PointWrapper::PlaneGCSSolver_PointWrapper(
-    const AttributePtr theAttribute, const GCSPointPtr thePoint)
-  : myPoint(thePoint),
-    myID(EID_UNKNOWN)
+PlaneGCSSolver_PointWrapper::PlaneGCSSolver_PointWrapper(const GCSPointPtr thePoint)
+  : myPoint(thePoint)
 {
-  myBaseAttribute = theAttribute;
-}
-
-void PlaneGCSSolver_PointWrapper::setGroup(const GroupID& theGroup)
-{
-  myGroup = 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);
-}
-
-bool PlaneGCSSolver_PointWrapper::isUsed(AttributePtr theAttribute) const
-{
-  return isBase(theAttribute);
-}
-
-bool PlaneGCSSolver_PointWrapper::isEqual(const EntityWrapperPtr& theOther)
-{
-  if (type() != theOther->type())
-    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 PlaneGCSSolver_PointWrapper::update(const EntityWrapperPtr& theOther)
-{
-  bool isUpdated = false;
-  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;
 }
index dc276d4b2e273599f7ff28e280120165495adbda..6bb2ade7a7c17fdcdb0c67c334628c4af04392ad 100644 (file)
@@ -16,7 +16,7 @@
 class PlaneGCSSolver_PointWrapper : public SketchSolver_IEntityWrapper
 {
 public:
-  PlaneGCSSolver_PointWrapper(const AttributePtr theAttribute, const GCSPointPtr thePoint);
+  PlaneGCSSolver_PointWrapper(const GCSPointPtr thePoint);
 
   /// \brief Return PlaneGCS point
   const GCSPointPtr& point() const
@@ -25,39 +25,11 @@ public:
   GCSPointPtr& changeEntity()
   { return myPoint; }
 
-  /// \brief Return ID of current entity
-  virtual EntityID id() const
-  { return myID; }
-  /// \brief Change ID of the entity
-  void setId(EntityID theID)
-  { myID = theID; }
-
-  /// \brief Change group for the entity
-  virtual void setGroup(const GroupID& theGroup);
-  /// \brief Return identifier of the group the entity belongs to
-  virtual GroupID group() const
-  { return myGroup; }
-
   /// \brief Return type of current entity
   virtual SketchSolver_EntityType type() const
   { return ENTITY_POINT; }
 
-  /// \brief Verify the feature is used in the entity
-  virtual bool isUsed(FeaturePtr theFeature) const
-  { return false; }
-  /// \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 EntityWrapperPtr& theOther);
-
 private:
-  EntityID    myID;
-  GroupID     myGroup;
   GCSPointPtr myPoint;
 };
 
index 2811988469d4093c44e0b2957c60dfe579ef764f..92cd4c95d1a2371de50030b1f0bf052f958c3872 100644 (file)
@@ -5,62 +5,20 @@
 // Author:  Artem ZHIDKOV
 
 #include <PlaneGCSSolver_ScalarWrapper.h>
-#include <PlaneGCSSolver_ParameterWrapper.h>
 
+#include <cmath>
 
-
-PlaneGCSSolver_ScalarWrapper::PlaneGCSSolver_ScalarWrapper(
-    const AttributePtr              theAttribute,
-    const ParameterWrapperPtr       theParam)
-{
-  myBaseAttribute = theAttribute;
-  myParameters.assign(1, theParam);
-}
-
-void PlaneGCSSolver_ScalarWrapper::setGroup(const GroupID& theGroup)
+PlaneGCSSolver_ScalarWrapper::PlaneGCSSolver_ScalarWrapper(double *const theParam)
+  : myValue(theParam)
 {
-  myGroup = theGroup;
-  myParameters.front()->setGroup(theGroup);
 }
 
-double* PlaneGCSSolver_ScalarWrapper::scalar() const
+void PlaneGCSSolver_ScalarWrapper::setValue(double theValue)
 {
-  std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
-      std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(myParameters.front());
-  return aParam->parameter();
-}
-
-bool PlaneGCSSolver_ScalarWrapper::isUsed(AttributePtr theAttribute) const
-{
-  return isBase(theAttribute);
-}
-
-bool PlaneGCSSolver_ScalarWrapper::isEqual(const EntityWrapperPtr& theOther)
-{
-  if (type() != theOther->type())
-    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;
+  *myValue = theValue;
 }
 
-bool PlaneGCSSolver_ScalarWrapper::update(const EntityWrapperPtr& theOther)
+double PlaneGCSSolver_ScalarWrapper::value() const
 {
-  bool isUpdated = false;
-  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;
+  return *myValue;
 }
index 89e389da2ae30c4c62883317fcd1f9a9e23c022a..f0907a5882f7909347bb3f696bc901d535638a05 100644 (file)
 class PlaneGCSSolver_ScalarWrapper : public SketchSolver_IEntityWrapper
 {
 public:
-  PlaneGCSSolver_ScalarWrapper(const AttributePtr theAttribute, const ParameterWrapperPtr theParam);
+  PlaneGCSSolver_ScalarWrapper(double *const theParam);
 
   /// \brief Return PlaneGCS parameter
-  double* scalar() const;
+  double* scalar() const
+  { return myValue; }
 
-  /// \brief Return ID of current entity
-  virtual EntityID id() const
-  { return myID; }
-  /// \brief Change ID of the entity
-  void setId(EntityID theID)
-  { myID = theID; }
-
-  /// \brief Change group for the entity
-  virtual void setGroup(const GroupID& theGroup);
-  /// \brief Return identifier of the group the entity belongs to
-  virtual GroupID group() const
-  { return myGroup; }
+  /// \brief Change value of parameter
+  virtual void setValue(double theValue);
+  /// \brief Return value of parameter
+  virtual double value() const;
 
   /// \brief Return type of current entity
   virtual SketchSolver_EntityType type() const
   { return ENTITY_SCALAR; }
 
-  /// \brief Verify the feature is used in the entity
-  virtual bool isUsed(FeaturePtr theFeature) const
-  { return false; }
-  /// \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 EntityWrapperPtr& theOther);
-
-private:
-  EntityID                myID;
-  GroupID                 myGroup;
+protected:
+  double* myValue; ///< pointer to value provided by the storage
 };
 
+typedef std::shared_ptr<PlaneGCSSolver_ScalarWrapper> ScalarWrapperPtr;
+
 #endif
index a16a3bbde75b2a93983f6cc735c36db1543f846c..9181f43dd1abd9ec92f5c31e627d80dab1da4347 100644 (file)
@@ -7,28 +7,10 @@
 #include "PlaneGCSSolver_Solver.h"
 #include <Events_LongOp.h>
 
-#include <cmath>
-
-// remove indices of all point-point coincidences from the vector
-static void removePtPtCoincidences(const ConstraintMap& theConstraints, GCS::VEC_I& theVecToClear)
-{
-  ConstraintMap::const_iterator aCIt = theConstraints.begin();
-  for (; aCIt != theConstraints.end(); ++aCIt) {
-    if (aCIt->second != CONSTRAINT_PT_PT_COINCIDENT)
-      continue;
-    GCS::VEC_I::iterator aRIt = theVecToClear.begin();
-    for (; aRIt != theVecToClear.end(); ++aRIt)
-      if (aCIt->first->getTag() == *aRIt) {
-        theVecToClear.erase(aRIt);
-        break;
-      }
-  }
-}
-
 
 PlaneGCSSolver_Solver::PlaneGCSSolver_Solver()
   : myEquationSystem(new GCS::System),
-  myConfCollected(false)
+    myConfCollected(false)
 {
 }
 
@@ -40,34 +22,19 @@ PlaneGCSSolver_Solver::~PlaneGCSSolver_Solver()
 void PlaneGCSSolver_Solver::clear()
 {
   myEquationSystem->clear();
-  myConstraints.clear();
   myParameters.clear();
+  myEqualConstraints.clear();
+  myEqualParameters.clear();
 }
 
-void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint,
-    const SketchSolver_ConstraintType theType)
+void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint)
 {
-  GCS::Constraint* aConstraint = theConstraint.get();
-  if (myConstraints.find(aConstraint) != myConstraints.end())
-    return; // constraint already exists, no need to add it again
-
-  myEquationSystem->addConstraint(aConstraint);
-  myConstraints[aConstraint] = theType;
+  myEquationSystem->addConstraint(theConstraint.get());
 }
 
-void PlaneGCSSolver_Solver::removeConstraint(GCSConstraintPtr theConstraint)
+void PlaneGCSSolver_Solver::removeConstraint(ConstraintID theID)
 {
-  GCS::Constraint* aConstraint = theConstraint.get();
-  removeConstraint(aConstraint);
-}
-
-void PlaneGCSSolver_Solver::removeConstraint(GCS::Constraint* theConstraint)
-{
-  if (myConstraints.find(theConstraint) == myConstraints.end())
-    return; // no constraint, no need to remove it
-
-  myEquationSystem->removeConstraint(theConstraint);
-  myConstraints.erase(theConstraint);
+  myEquationSystem->clearByTag(theID);
 }
 
 SketchSolver_SolveStatus PlaneGCSSolver_Solver::solve()
@@ -78,79 +45,12 @@ SketchSolver_SolveStatus PlaneGCSSolver_Solver::solve()
     myConfCollected = false;
   }
 
-  if (myConstraints.empty())
-    return STATUS_EMPTYSET;
   if (myParameters.empty())
     return STATUS_INCONSISTENT;
 
   Events_LongOp::start(this);
-  GCS::SolveStatus aResult = GCS::Success;
-  // if there is a constraint with all attributes constant, set fail status
-  GCS::SET_pD aParameters;
-  aParameters.insert(myParameters.begin(), myParameters.end());
-  ConstraintMap::const_iterator aConstrIt = myConstraints.begin();
-  for (; aConstrIt != myConstraints.end(); ++aConstrIt) {
-    GCS::VEC_pD aParams = aConstrIt->first->params();
-    GCS::VEC_pD::const_iterator aPIt = aParams.begin();
-    for (; aPIt != aParams.end(); ++aPIt)
-      if (aParameters.find(*aPIt) != aParameters.end())
-        break;
-    if (aPIt == aParams.end() && aConstrIt->first->getTag() > 0) {
-      myConflictingIDs.insert(aConstrIt->first->getTag());
-      myConfCollected = true;
-      aResult = GCS::Failed;
-    }
-  }
   // solve equations
-  if (aResult == GCS::Success)
-    aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
-
-  GCS::VEC_I aRedundantID;
-
-  // Workaround: the system with tangent constraint
-  // may fail if the tangent entities are connected smoothly.
-  // Investigate this situation and move constraints to redundant list
-  if (aResult == GCS::Failed && !myTangent.empty()) {
-    GCS::VEC_I aConflictingID;
-    myEquationSystem->getConflicting(aConflictingID);
-    GCS::VEC_I::iterator aCIt = aConflictingID.begin();
-    for (; aCIt != aConflictingID.end(); ++ aCIt) {
-      if (myTangent.find(*aCIt) == myTangent.end())
-        continue;
-      if (isTangentTruth(*aCIt))
-        aRedundantID.push_back(*aCIt);
-    }
-
-    if (!aRedundantID.empty())
-      aResult = GCS::Success; // check redundant constraints
-  }
-
-  // Additionally check redundant constraints
-  if (aResult == GCS::Success || aResult == GCS::Converged) {
-    bool isSolveWithoutTangent = !aRedundantID.empty();
-    GCS::VEC_I aRedundantLocal;
-    myEquationSystem->getRedundant(aRedundantLocal);
-    aRedundantID.insert(aRedundantID.end(), aRedundantLocal.begin(), aRedundantLocal.end());
-    // Workaround: remove all point-point coincidences from list of redundant
-    if (!aRedundantID.empty())
-      removePtPtCoincidences(myConstraints, aRedundantID);
-    // The system with tangent constraints may show redundant constraints
-    // if the entities are coupled smoothly.
-    // Sometimes tangent constraints are fall to both conflicting and redundant constraints.
-    // Need to check if there are redundant constraints without these tangencies.
-    if (!aRedundantID.empty() && !isSolveWithoutTangent) {
-      GCS::VEC_I::iterator aCIt = aRedundantID.begin();
-      for (; aCIt != aRedundantID.end(); ++ aCIt)
-        if (myTangent.find(*aCIt) != myTangent.end()) {
-          isSolveWithoutTangent = true;
-          break;
-        }
-    }
-    if (isSolveWithoutTangent)
-      aResult = myTangent.empty() ? GCS::Failed : solveWithoutTangent();
-    else
-      aResult = GCS::Success;
-  }
+  GCS::SolveStatus aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
   Events_LongOp::end(this);
 
   SketchSolver_SolveStatus aStatus;
@@ -163,119 +63,6 @@ SketchSolver_SolveStatus PlaneGCSSolver_Solver::solve()
   return aStatus;
 }
 
-GCS::SolveStatus PlaneGCSSolver_Solver::solveWithoutTangent()
-{
-  std::shared_ptr<GCS::System> aSystemWithoutTangent(new GCS::System);
-
-  // Remove tangency which leads to redundant or conflicting constraints
-  GCS::VEC_I aConflicting, aRedundant;
-  myEquationSystem->getRedundant(aRedundant);
-  size_t aNbRemove = myTangent.size(); // number of tangent constraints which can be removed
-  myEquationSystem->getConflicting(aConflicting);
-  aRedundant.insert(aRedundant.end(), aConflicting.begin(), aConflicting.end());
-
-  GCS::SET_I aTangentToRemove;
-  GCS::VEC_I::iterator aCIt = aRedundant.begin();
-  for (; aCIt != aRedundant.end() && aNbRemove > 0; ++aCIt)
-    if (myTangent.find(*aCIt) != myTangent.end()) {
-      aTangentToRemove.insert(*aCIt);
-      --aNbRemove;
-    }
-
-  std::set<GCS::Constraint*> aRemovedTangent;
-  ConstraintMap::const_iterator aConstrIt = myConstraints.begin();
-  while (aConstrIt != myConstraints.end()) {
-    GCS::Constraint* aConstraint = aConstrIt->first;
-    int anID = aConstraint->getTag();
-    ++aConstrIt;
-    if (aTangentToRemove.find(anID) == aTangentToRemove.end())
-      aSystemWithoutTangent->addConstraint(aConstraint);
-    else
-      aRemovedTangent.insert(aConstraint);
-  }
-
-  myTangent.clear();
-  GCS::SolveStatus aResult = (GCS::SolveStatus)aSystemWithoutTangent->solve(myParameters);
-  if (aResult == GCS::Success) {
-    GCS::VEC_I aRedundant;
-    aSystemWithoutTangent->getRedundant(aRedundant);
-    if (!aRedundant.empty()) {
-      removePtPtCoincidences(myConstraints, aRedundant);
-      if (!aRedundant.empty())
-        aResult = GCS::Failed;
-    }
-  }
-
-  // additional check that removed constraints are still correct
-  if (aResult == GCS::Success) {
-    aSystemWithoutTangent->applySolution();
-    std::set<GCS::Constraint*>::const_iterator aRemIt = aRemovedTangent.begin();
-    for (; aRemIt != aRemovedTangent.end(); ++aRemIt)
-      if (!isTangentTruth(*aRemIt))
-        break;
-    if (aRemIt != aRemovedTangent.end()) {
-      aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
-      if (aResult != GCS::Failed) {
-        aSystemWithoutTangent = myEquationSystem;
-        aResult = GCS::Success;
-      }
-    }
-  }
-
-  if (aResult == GCS::Success)
-      myEquationSystem = aSystemWithoutTangent;
-  else {
-    // Add IDs of removed tangent to the list of conflicting constraints
-    std::set<GCS::Constraint*>::const_iterator aRemIt = aRemovedTangent.begin();
-    for (; aRemIt != aRemovedTangent.end(); ++aRemIt)
-      myConflictingIDs.insert((*aRemIt)->getTag());
-  }
-
-  return aResult;
-}
-
-bool PlaneGCSSolver_Solver::isTangentTruth(GCS::Constraint* theTangent) const
-{
-  if (theTangent->getTypeId() == GCS::TangentCircumf) {
-    static const double aTol = 1e-4;
-    GCS::VEC_pD aParams = theTangent->params();
-    double dx = *(aParams[2]) - *(aParams[0]);
-    double dy = *(aParams[3]) - *(aParams[1]);
-    double aDist2 = dx * dx + dy * dy;
-    double aRadSum  = *(aParams[4]) + *(aParams[5]);
-    double aRadDiff = *(aParams[4]) - *(aParams[5]);
-    double aTol2 = aTol * aRadSum;
-    aTol2 *= aTol2;
-    return fabs(aDist2 - aRadSum * aRadSum) <= aTol2 ||
-           fabs(aDist2 - aRadDiff * aRadDiff) <= aTol2;
-  }
-  if (theTangent->getTypeId() == GCS::P2LDistance) {
-    static const double aTol2 = 1e-10;
-    GCS::VEC_pD aParams = theTangent->params();
-    double aDist2 = *(aParams[6]) * *(aParams[6]);
-    // orthogonal line direction
-    double aDirX = *(aParams[5]) - *(aParams[3]);
-    double aDirY = *(aParams[2]) - *(aParams[4]);
-    double aLen2 = aDirX * aDirX + aDirY * aDirY;
-    // vector from line's start to point
-    double aVecX = *(aParams[0]) - *(aParams[2]);
-    double aVecY = *(aParams[1]) - *(aParams[3]);
-
-    double aDot = aVecX * aDirX + aVecY * aDirY;
-    return fabs(aDot * aDot - aDist2 * aLen2) <= aTol2 * aLen2;
-  }
-  return false;
-}
-
-bool PlaneGCSSolver_Solver::isTangentTruth(int theTagID) const
-{
-  ConstraintMap::const_iterator anIt = myConstraints.begin();
-  for (; anIt != myConstraints.end(); ++anIt)
-    if (anIt->first->getTag() == theTagID)
-      return isTangentTruth(anIt->first);
-  return false;
-}
-
 void PlaneGCSSolver_Solver::undo()
 {
   myEquationSystem->undoSolution();
index c32d2daf6b55ebc9480067a3d8b6d8cb231f0a94..051f73cadbd8af76a74829021b9d12c5dcd69ce9 100644 (file)
 
 #include <GCS.h>
 
-typedef std::map<GCS::Constraint*, SketchSolver_ConstraintType> ConstraintMap;
-
-/**
- * The main class that performs the high-level operations for connection to the PlaneGCS.
- */
+/// \brief The main class that performs the high-level operations for connection to the PlaneGCS.
 class PlaneGCSSolver_Solver : public SketchSolver_ISolver
 {
 public:
@@ -28,60 +24,37 @@ public:
   void clear();
 
   /// \brief Add constraint to the system of equations
-  void addConstraint(GCSConstraintPtr theConstraint,
-                     const SketchSolver_ConstraintType theType);
+  void addConstraint(GCSConstraintPtr theConstraint);
 
   /// \brief Remove constraint from the system of equations
-  void removeConstraint(GCSConstraintPtr theConstraint);
+  void removeConstraint(ConstraintID theID);
 
   /// \brief Initialize list of unknowns
   void setParameters(const GCS::VEC_pD& theParams)
   { myParameters = theParams; }
 
-  /// \brief Set list of IDs of tangent constraints
-  ///
-  /// Workaround to avoid incorrect report about redundant constraints
-  /// if an arc is already smoothly connected to a line.
-  void setTangent(const GCS::SET_I& theTangentIDs)
-  { myTangent = theTangentIDs; }
-
-  /** \brief Solve the set of equations
-   *  \return identifier whether solution succeeded
-   */
-  virtual SketchSolver_SolveStatus solve();
+  /// \brief Solve the set of equations
+  /// \return identifier whether solution succeeded
+  virtual SketchSolver_SolveStatus solve() override;
 
   /// \brief Prepare for solving. Store initial values of parameters for undo
-  virtual void prepare()
+  virtual void prepare() override
   { /* do nothing */ }
 
   /// \brief Revert solution to initial values
-  virtual void undo();
+  virtual void undo() override;
 
   /// \brief Check the constraint is conflicted with others
-  virtual bool isConflicting(const ConstraintID& theConstraint) const;
+  virtual bool isConflicting(const ConstraintID& theConstraint) const override;
 
   /// \brief Degrees of freedom
-  virtual int dof() const;
+  virtual int dof() const override;
 
 private:
   void collectConflicting();
 
-  /// \brief Remove constraint from the system of equations
-  void removeConstraint(GCS::Constraint* theConstraint);
-
-  /// \brief Remove redundant tangent constraints and try to solve the system again
-  GCS::SolveStatus solveWithoutTangent();
-
-  /// \brief Check the entities under the tangent constraint are smoothly connected
-  bool isTangentTruth(int theTagID) const;
-  /// \brief Check the entities under the tangent constraint are smoothly connected
-  bool isTangentTruth(GCS::Constraint* theTangent) const;
-
 private:
   GCS::VEC_pD                  myParameters;     ///< list of unknowns
-
-  /// list of constraints already processed by the system
-  ConstraintMap                myConstraints;
   std::shared_ptr<GCS::System> myEquationSystem; ///< set of equations for solving in FreeGCS
 
   GCS::SET_I                   myConflictingIDs; ///< list of IDs of conflicting constraints
@@ -89,8 +62,10 @@ private:
   /// specifies the conflicting constraints are already collected
   bool                         myConfCollected;
 
-  /// list of tangent IDs to check incorrect redundant constraints
-  GCS::SET_I                   myTangent;
+  /// lists of parameters used in the Equal constraints (to avoid multiple equalities)
+  std::list<GCS::SET_pD>       myEqualParameters;
+  /// lists of the Equal constraints
+  std::map<ConstraintID, std::set<GCSConstraintPtr> > myEqualConstraints;
 };
 
 #endif
index 37086e22f611bf895b92ac3723742635ed96c59f..89c5bd29fa13184f322e4c2668a6fcef87ee75e6 100644 (file)
 #include <PlaneGCSSolver_ConstraintWrapper.h>
 #include <PlaneGCSSolver_EntityWrapper.h>
 #include <PlaneGCSSolver_PointWrapper.h>
-#include <PlaneGCSSolver_ScalarWrapper.h>
-#include <PlaneGCSSolver_ParameterWrapper.h>
 
-#include <GeomAPI_Edge.h>
+#include <PlaneGCSSolver_AttributeBuilder.h>
+#include <PlaneGCSSolver_FeatureBuilder.h>
+#include <PlaneGCSSolver_EntityDestroyer.h>
+
 #include <GeomAPI_Dir2d.h>
 #include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_XY.h>
 #include <GeomDataAPI_Point2D.h>
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_ConstraintTangent.h>
+#include <SketchPlugin_Projection.h>
 
 #include <cmath>
 
 
-PlaneGCSSolver_Storage::PlaneGCSSolver_Storage(const GroupID& theGroup)
-  : SketchSolver_Storage(theGroup),
-    myEntityLastID(EID_SKETCH),
+static void constraintsToSolver(const ConstraintWrapperPtr& theConstraint,
+                                const SolverPtr& theSolver)
+{
+  std::shared_ptr<PlaneGCSSolver_Solver> aSolver =
+      std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(theSolver);
+  if (!aSolver)
+    return;
+
+  const std::list<GCSConstraintPtr>& aConstraints =
+      std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint)->constraints();
+  std::list<GCSConstraintPtr>::const_iterator anIt = aConstraints.begin();
+  for (; anIt != aConstraints.end(); ++anIt)
+    aSolver->addConstraint(*anIt);
+}
+
+
+PlaneGCSSolver_Storage::PlaneGCSSolver_Storage(const SolverPtr& theSolver)
+  : SketchSolver_Storage(theSolver),
     myConstraintLastID(CID_UNKNOWN)
 {
 }
 
 void PlaneGCSSolver_Storage::addConstraint(
-    ConstraintPtr                   theConstraint,
-    std::list<ConstraintWrapperPtr> theSolverConstraints)
+    ConstraintPtr        theConstraint,
+    ConstraintWrapperPtr theSolverConstraint)
 {
-  SketchSolver_Storage::addConstraint(theConstraint, theSolverConstraints);
-
-  // update point-point coincidence
-  if (!theSolverConstraints.empty() &&
-      theSolverConstraints.front()->type() == CONSTRAINT_PT_PT_COINCIDENT) {
-    std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
-    for (; aCIt != theSolverConstraints.end(); ++aCIt)
-      update(*aCIt);
-  }
+  SketchSolver_Storage::addConstraint(theConstraint, theSolverConstraint);
+
+  theSolverConstraint->setId(++myConstraintLastID);
+  constraintsToSolver(theSolverConstraint, mySketchSolver);
+}
+
+void PlaneGCSSolver_Storage::addTemporaryConstraint(
+    const ConstraintWrapperPtr& theSolverConstraint)
+{
+  if (myConstraintMap.empty())
+    return; // no need to process temporary constraints if there is no active constraint
+
+  theSolverConstraint->setId(CID_MOVEMENT);
+  constraintsToSolver(theSolverConstraint, mySketchSolver);
 }
 
 
-bool PlaneGCSSolver_Storage::update(ConstraintWrapperPtr theConstraint)
+EntityWrapperPtr PlaneGCSSolver_Storage::createFeature(
+    const FeaturePtr&             theFeature,
+    PlaneGCSSolver_EntityBuilder* theBuilder)
 {
-  bool isUpdated = false;
-  std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
-      std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
-
-  // point-Line distance should be positive
-  if (aConstraint->type() == CONSTRAINT_PT_LINE_DISTANCE && aConstraint->value() < 0.0)
-    aConstraint->setValue(-aConstraint->value());
-
-  // make value of constraint unchangeable
-  ParameterWrapperPtr aValue = aConstraint->valueParameter();
-  if (aValue)
-    isUpdated = update(aValue) || isUpdated;
-
-  // update constrained entities
-  std::list<EntityWrapperPtr> anEntities = theConstraint->entities();
-  std::list<EntityWrapperPtr>::iterator anIt = anEntities.begin();
-  for (; anIt != anEntities.end(); ++anIt)
-    isUpdated = update(*anIt) || isUpdated;
-
-  if (aConstraint->id() == CID_UNKNOWN) {
-    const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
-    // check middle-point constraint conflicts with point-on-line
-    if (aConstraint->type() == CONSTRAINT_MIDDLE_POINT) {
-      std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
-          anIt = myConstraintMap.begin();
-      for (; anIt != myConstraintMap.end(); ++anIt) {
-        EntityWrapperPtr aPoint, aLine;
-        if (anIt->second.empty())
-          continue;
-        ConstraintWrapperPtr aCurrentConstr = anIt->second.front();
-        if (aCurrentConstr->type() != CONSTRAINT_PT_ON_LINE)
-          continue;
-        const std::list<EntityWrapperPtr>& aCurSubs = aCurrentConstr->entities();
-        std::list<EntityWrapperPtr>::const_iterator aSIt1, aSIt2;
-        for (aSIt1 = aSubs.begin(); aSIt1 != aSubs.end(); ++aSIt1) {
-          if ((*aSIt1)->type() == ENTITY_POINT)
-            aPoint = *aSIt1;
-          else if((*aSIt1)->type() == ENTITY_LINE)
-            aLine = *aSIt1;
-          else
-            continue;
-          for (aSIt2 = aCurSubs.begin(); aSIt2 != aCurSubs.end(); ++aSIt2)
-            if ((*aSIt1)->id() == (*aSIt2)->id())
-              break;
-          if (aSIt2 == aCurSubs.end())
-            break;
-        }
-        // point-on-line found, change it to bisector
-        if (aSIt1 == aSubs.end()) {
-          std::list<GCSConstraintPtr> aConstrList = aConstraint->constraints();
-          aConstrList.pop_front();
-          aConstraint->setConstraints(aConstrList);
-          break;
-        }
-      }
-    }
+  std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
+  std::list<AttributePtr>::const_iterator anIt = anAttributes.begin();
+  for (; anIt != anAttributes.end(); ++anIt)
+    createAttribute(*anIt, theBuilder);
+
+  EntityWrapperPtr aResult = theBuilder->createFeature(theFeature);
+  if (aResult)
+    addEntity(theFeature, aResult);
+  return aResult;
+}
 
-    // Change ID of constraints
-    aConstraint->setId(++myConstraintLastID);
-  }
+EntityWrapperPtr PlaneGCSSolver_Storage::createAttribute(
+    const AttributePtr&           theAttribute,
+    PlaneGCSSolver_EntityBuilder* theBuilder)
+{
+  EntityWrapperPtr aResult = theBuilder->createAttribute(theAttribute);
+  if (aResult)
+    addEntity(theAttribute, aResult);
+  return aResult;
+}
 
+/// \brief Update value
+static bool updateValue(const double& theSource, double& theDest)
+{
+  static const double aTol = 1000. * tolerance;
+  bool isUpdated = fabs(theSource - theDest) > aTol;
+  if (isUpdated)
+    theDest = theSource;
   return isUpdated;
 }
 
 /// \brief Update coordinates of the point or scalar using its base attribute
-static bool updateValues(EntityWrapperPtr& theEntity)
+static bool updateValues(AttributePtr& theAttribute, EntityWrapperPtr& theEntity)
 {
-  const double aTol = 1000. * tolerance;
   bool isUpdated = false;
-  AttributePtr anAttr = theEntity->baseAttribute();
-  const std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
-
-  double aCoord[2];
 
   std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
-      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
   if (aPoint2D) {
-    aCoord[0] = aPoint2D->x();
-    aCoord[1] = aPoint2D->y();
+    const GCSPointPtr& aGCSPoint =
+        std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity)->point();
+    isUpdated = updateValue(aPoint2D->x(), *(aGCSPoint->x)) || isUpdated;
+    isUpdated = updateValue(aPoint2D->y(), *(aGCSPoint->y)) || isUpdated;
   } else {
-    AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttr);
-    if (aScalar)
-      aCoord[0] = aScalar->value();
-  }
-
-  std::list<ParameterWrapperPtr>::const_iterator anIt = aParams.begin();
-  for (int i = 0; anIt != aParams.end(); ++anIt, ++i)
-    if (fabs((*anIt)->value() - aCoord[i]) > aTol) {
-      (*anIt)->setValue(aCoord[i]);
-      isUpdated = true;
-    }
-  return isUpdated;
-}
-
-bool PlaneGCSSolver_Storage::update(EntityWrapperPtr theEntity)
-{
-  if (theEntity->type() == ENTITY_SKETCH)
-    return true; // sketch is not necessary for PlaneGCS, so it is always says true
-
-  bool isUpdated = false;
-
-  if (theEntity->baseAttribute()) {
-    isUpdated = updateValues(theEntity);
-    if (isUpdated) {
-      setNeedToResolve(true);
-      if (theEntity->type() == ENTITY_POINT && theEntity->group() != myGroupID)
-        updateCoincident(theEntity);
-    }
-  }
-
-  // update parameters
-  std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
-  std::list<ParameterWrapperPtr>::iterator aPIt = aParams.begin();
-  for (; aPIt != aParams.end(); ++aPIt)
-    isUpdated = update(*aPIt) || isUpdated;
-
-  // update sub-entities
-  std::list<EntityWrapperPtr> aSubEntities = theEntity->subEntities();
-  std::list<EntityWrapperPtr>::iterator aSIt = aSubEntities.begin();
-  for (; aSIt != aSubEntities.end(); ++aSIt)
-    isUpdated = update(*aSIt) || isUpdated;
-
-  // additional constraints for the arc processing
-  if (theEntity->type() == ENTITY_ARC)
-    processArc(theEntity);
-
-  // Change entity's ID, if necessary
-  if (theEntity->id() == EID_UNKNOWN) {
-    if (theEntity->type() == ENTITY_POINT) {
-      std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
-          std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
-      if (!aPoint) {
-        aPoint = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
-            theEntity->subEntities().front());
-      }
-      aPoint->setId(++myEntityLastID);
-    } else if (theEntity->type() == ENTITY_SCALAR) {
-      std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aScalar =
+    AttributeDoublePtr aScalar =
+        std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
+    if (aScalar) {
+      ScalarWrapperPtr aWrapper =
           std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(theEntity);
-      aScalar->setId(++myEntityLastID);
-    } else {
-      std::shared_ptr<PlaneGCSSolver_EntityWrapper> aGCSEnt =
-          std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity);
-      aGCSEnt->setId(++myEntityLastID);
+      // There is possible angular value, which is converted between degrees and radians.
+      // So, we use its value instead of using direct pointer to value.
+      double aValue = aWrapper->value();
+      isUpdated = updateValue(aScalar->value(), aValue);
+      if (isUpdated)
+        aWrapper->setValue(aValue);
     }
   }
-  return isUpdated;
-}
-
-bool PlaneGCSSolver_Storage::update(ParameterWrapperPtr theParameter)
-{
-  std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
-      std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(theParameter);
-  if (aParam->isProcessed())
-    return false;
-  if (theParameter->group() != myGroupID || theParameter->isParametric())
-    myConst.push_back(aParam->parameter());
-  else
-    myParameters.push_back(aParam->parameter());
-  aParam->setProcessed(true);
-  return true;
-}
-
 
-bool PlaneGCSSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
-{
-  std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
-    std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
-
-  bool isFullyRemoved = true;
-  // remove point-point coincidence
-  if (aConstraint->type() == CONSTRAINT_PT_PT_COINCIDENT)
-    isFullyRemoved = removeCoincidence(theConstraint) && isFullyRemoved;
-  // remove sub-entities
-  const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
-  std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
-  for (; aSIt != aSubs.end(); ++ aSIt)
-    isFullyRemoved = remove(*aSIt) && isFullyRemoved;
-
-  if (aConstraint->valueParameter())
-    isFullyRemoved = remove(aConstraint->valueParameter()) && isFullyRemoved;
-  if (!isFullyRemoved && aConstraint->baseConstraint() &&
-     (!aConstraint->baseConstraint()->data() || !aConstraint->baseConstraint()->data()->isValid()))
-    isFullyRemoved = true;
-  setNeedToResolve(true);
-  myRemovedConstraints.insert(myRemovedConstraints.end(),
-      aConstraint->constraints().begin(), aConstraint->constraints().end());
-
-  if (isFullyRemoved && theConstraint->id() == myConstraintLastID)
-    --myConstraintLastID;
-
-  return isFullyRemoved;
+  return isUpdated;
 }
 
-bool PlaneGCSSolver_Storage::remove(EntityWrapperPtr theEntity)
+static bool isCopyInMulti(std::shared_ptr<SketchPlugin_Feature> theFeature)
 {
-  // do not remove entity, if it is used by constraints or other entities
-  if ((theEntity->baseFeature() && isUsed(theEntity->baseFeature())) ||
-      (theEntity->baseAttribute() && isUsed(theEntity->baseAttribute())))
+  if (!theFeature)
     return false;
 
-  bool isFullyRemoved = SketchSolver_Storage::remove(theEntity);
-  if (isFullyRemoved) {
-    if (theEntity->type() == ENTITY_ARC) {
-      // remove arc additional constraints
-      std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::iterator
-          aFound = myArcConstraintMap.find(theEntity);
-      if (aFound != myArcConstraintMap.end()) {
-        myRemovedConstraints.insert(myRemovedConstraints.end(),
-            aFound->second.begin(), aFound->second.end());
-        myArcConstraintMap.erase(aFound);
-      }
+  bool aResult = theFeature->isCopy();
+  if (aResult) {
+    const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
+    for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
+         aRefIt != aRefs.end() && aResult; ++aRefIt) {
+      FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
+      if (anOwner->getKind() == SketchPlugin_Projection::ID())
+        aResult = false;
     }
-    if (theEntity->id() == myEntityLastID)
-      --myEntityLastID;
   }
-  return isFullyRemoved;
+  return aResult;
 }
 
-bool PlaneGCSSolver_Storage::remove(ParameterWrapperPtr theParameter)
+bool PlaneGCSSolver_Storage::update(FeaturePtr theFeature, bool theForce)
 {
-  std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
-      std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(theParameter);
-  if (aParam->isProcessed()) {
-    double* aValPtr = aParam->parameter();
-    GCS::VEC_pD::iterator anIt =  myParameters.begin();
-    for (; anIt != myParameters.end(); ++anIt)
-      if (*anIt == aValPtr)
-        break;
-    if (anIt != myParameters.end()) {
-      myParameters.erase(anIt);
-      setNeedToResolve(true);
-      aParam->setProcessed(false);
-    }
-    else {
-      for (anIt = myConst.begin(); anIt != myConst.end(); ++anIt)
-        if (*anIt == aValPtr)
-          break;
-      if (anIt != myConst.end()) {
-        myConst.erase(anIt);
-        setNeedToResolve(true);
-        aParam->setProcessed(false);
-      }
+  bool isUpdated = false;
+  EntityWrapperPtr aRelated = entity(theFeature);
+  if (aRelated) // send signal to subscribers
+    notify(theFeature);
+  else { // Feature is not exist, create it
+    std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+        std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
+    bool isCopy = isCopyInMulti(aSketchFeature);
+    // the feature is a copy in "Multi" constraint and does not used in other constraints
+    if (!theForce && isCopy && myFeatureMap.find(theFeature) == myFeatureMap.end())
+      return false;
+
+    // external feature processing
+    bool isExternal = (aSketchFeature && (aSketchFeature->isExternal() || isCopy));
+
+    PlaneGCSSolver_FeatureBuilder aBuilder(isExternal ? 0 : this);
+
+    // Reserve the feature in the map of features
+    // (do not want to add several copies of it while adding attributes)
+    aRelated = createFeature(theFeature, &aBuilder);
+    myFeatureMap[theFeature] = aRelated;
+
+    const std::list<GCSConstraintPtr>& aConstraints = aBuilder.constraints();
+    if (!aConstraints.empty()) { // the feature is arc
+      /// TODO: avoid this workaround
+      ConstraintWrapperPtr aWrapper(
+          new PlaneGCSSolver_ConstraintWrapper(aConstraints, CONSTRAINT_UNKNOWN));
+      aWrapper->setId(++myConstraintLastID);
+      constraintsToSolver(aWrapper, mySketchSolver);
+
+      myArcConstraintMap[myFeatureMap[theFeature]] = aWrapper;
     }
+    isUpdated = true;
   }
-  return true;
-}
 
+  std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
+  std::list<AttributePtr>::iterator anAttrIt = anAttributes.begin();
+  for (; anAttrIt != anAttributes.end(); ++anAttrIt)
+    if ((*anAttrIt)->attributeType() == GeomDataAPI_Point2D::typeId() ||
+        (*anAttrIt)->attributeType() == ModelAPI_AttributeDouble::typeId())
+      isUpdated = update(*anAttrIt) || isUpdated;
 
-void PlaneGCSSolver_Storage::addCoincidentPoints(
-    EntityWrapperPtr theMaster, EntityWrapperPtr theSlave)
-{
-  if (theMaster->type() != ENTITY_POINT || theSlave->type() != ENTITY_POINT)
-    return;
-
-  std::shared_ptr<PlaneGCSSolver_PointWrapper> aMaster =
-      std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theMaster);
-  if (!aMaster)
-    aMaster = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
-      std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMaster)->subEntities().front());
-  std::shared_ptr<PlaneGCSSolver_PointWrapper> aSlave =
-      std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theSlave);
-  if (!aSlave)
-    aSlave = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
-      std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theSlave)->subEntities().front());
-
-  // Search available coincidence
-  CoincidentPointsMap::iterator aMasterFound = myCoincidentPoints.find(aMaster);
-  CoincidentPointsMap::iterator aSlaveFound = myCoincidentPoints.find(aSlave);
-  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(aMaster) != anIt->second.end())
-        aMasterFound = anIt;
-      else if (anIt->second.find(aSlave) != anIt->second.end())
-        aSlaveFound = anIt;
-
-      if (aMasterFound != myCoincidentPoints.end() &&  aSlaveFound != myCoincidentPoints.end())
-        break;
-    }
-  }
+  // update arc
+  if (aRelated && aRelated->type() == ENTITY_ARC) {
+    /// TODO: this code should be shared with FeatureBuilder somehow
 
-  if (aMasterFound == myCoincidentPoints.end()) {
-    // create new group
-    myCoincidentPoints[aMaster] = std::set<EntityWrapperPtr>();
-    aMasterFound = myCoincidentPoints.find(aMaster);
-  } 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(aMaster, *aSlIt);
-  } else {
-    //std::list<ParameterWrapperPtr> aSlaveParams = aSlave->parameters();
-    //aSlave->setParameters(aMaster->parameters());
+    std::shared_ptr<PlaneGCSSolver_EntityWrapper> anEntity =
+        std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(aRelated);
+    std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEntity->entity());
 
-    //// Remove slave's parameters
-    //std::list<ParameterWrapperPtr>::iterator aParIt = aSlaveParams.begin();
-    //for (; aParIt != aSlaveParams.end(); ++aParIt)
-    //  remove(*aParIt);
+    static std::shared_ptr<GeomAPI_Dir2d> OX(new GeomAPI_Dir2d(1.0, 0.0));
+    std::shared_ptr<GeomAPI_Pnt2d> aCenter(
+        new GeomAPI_Pnt2d(*anArc->center.x, *anArc->center.y));
+    std::shared_ptr<GeomAPI_Pnt2d> aStart(
+        new GeomAPI_Pnt2d(*anArc->start.x, *anArc->start.y));
 
-    aMasterFound->second.insert(aSlave);
-  }
-}
+    *anArc->rad = aStart->distance(aCenter);
 
+    std::shared_ptr<GeomAPI_Dir2d> aDir(new GeomAPI_Dir2d(aStart->xy()->decreased(aCenter->xy())));
+    *anArc->startAngle = OX->angle(aDir);
 
-void PlaneGCSSolver_Storage::changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup)
-{
-  theEntity->setGroup(theGroup);
-  if (theGroup == myGroupID)
-    makeVariable(theEntity);
-  else {
-    if (theEntity->type() == ENTITY_POINT)
-      update(theEntity);
-    makeConstant(theEntity);
+    aDir = std::shared_ptr<GeomAPI_Dir2d>(
+        new GeomAPI_Dir2d((*anArc->end.x) - aCenter->x(), (*anArc->end.y) - aCenter->y()));
+    *anArc->endAngle = OX->angle(aDir);
   }
-}
 
-void PlaneGCSSolver_Storage::changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup)
-{
-  // TODO
+  return isUpdated;
 }
 
-void PlaneGCSSolver_Storage::verifyFixed()
+bool PlaneGCSSolver_Storage::update(AttributePtr theAttribute, bool theForce)
 {
-  // TODO
-}
+  if (!theAttribute->isInitialized())
+    return false;
 
-void PlaneGCSSolver_Storage::processArc(const EntityWrapperPtr& theArc)
-{
-  // Calculate additional parameters necessary for PlaneGCS
-  const std::list<EntityWrapperPtr>& aSubs = theArc->subEntities();
-  std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
-  bool isFixed[3] = {false, false, false};
-  for (int i = 0; (*aSubIt)->type() == ENTITY_POINT; ++i) { // search scalar entities
-    isFixed[i] = (*aSubIt)->group() == GID_OUTOFGROUP;
-    ++aSubIt;
+  AttributePtr anAttribute = theAttribute;
+  AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
+  if (aRefAttr) {
+    if (aRefAttr->isObject()) {
+      FeaturePtr aFeature;
+      /// TODO: Check resultToFeatureOrAttribute() precisely.
+      resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute);
+      if (aFeature)
+        return update(aFeature, theForce);
+    } else
+      anAttribute = aRefAttr->attr();
   }
-  double* aStartAngle =
-    std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
-  double* aEndAngle =
-    std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
-  double* aRadius = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt)->scalar();
-
-  std::shared_ptr<SketchPlugin_Feature> anArcFeature =
-      std::dynamic_pointer_cast<SketchPlugin_Feature>(theArc->baseFeature());
-  std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
-  std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      anArcFeature->attribute(SketchPlugin_Arc::START_ID()));
-  std::shared_ptr<GeomDataAPI_Point2D> aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      anArcFeature->attribute(SketchPlugin_Arc::END_ID()));
-  if (!aCenterAttr || !aStartAttr || !aEndAttr)
-    return;
-  std::shared_ptr<GeomAPI_Pnt2d> aCenterPnt = aCenterAttr->pnt();
-  std::shared_ptr<GeomAPI_Pnt2d> aStartPnt  = aStartAttr->pnt();
-  std::shared_ptr<GeomAPI_Pnt2d> aEndPnt    = aEndAttr->pnt();
-
-  if (isFixed[2] && !isFixed[1])
-    *aRadius = aCenterPnt->distance(aEndPnt);
-  else
-    *aRadius = aCenterPnt->distance(aStartPnt);
-  if (!anArcFeature->lastResult())
-    return;
-  static std::shared_ptr<GeomAPI_Dir2d> OX(new GeomAPI_Dir2d(1.0, 0.0));
-  std::shared_ptr<GeomAPI_Dir2d> aDir(new GeomAPI_Dir2d(
-      aStartPnt->xy()->decreased(aCenterPnt->xy())));
-  *aStartAngle = OX->angle(aDir);
-  aDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
-      aEndPnt->xy()->decreased(aCenterPnt->xy())));
-  *aEndAngle = OX->angle(aDir);
-
-  // no need to constraint a fixed or a copied arc
-  if (theArc->group() == GID_OUTOFGROUP || anArcFeature->isCopy())
-    return;
-  // No need to add constraints if they are already exist
-  std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
-      aFound = myArcConstraintMap.find(theArc);
-//  if (aFound != myArcConstraintMap.end())
-//    return;
-
-  // Prepare additional constraints to produce the arc
-  std::vector<GCSConstraintPtr> anArcConstraints;
-  std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt =
-      std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theArc);
-  std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt->entity());
-  // Distances from center till start and end points are equal to radius
-  GCSConstraintPtr aNew = GCSConstraintPtr(new GCS::ConstraintP2PDistance(
-      anArc->center, anArc->start, anArc->rad));
-//  aNew->setTag((int)(++myConstraintLastID));
-  anArcConstraints.push_back(aNew);
-  aNew = GCSConstraintPtr(new GCS::ConstraintP2PDistance(
-      anArc->center, anArc->end, anArc->rad));
-//  aNew->setTag((int)myConstraintLastID);
-  anArcConstraints.push_back(aNew);
-  // Angles of start and end points should be equal to given angles
-  aNew = GCSConstraintPtr(new GCS::ConstraintP2PAngle(
-      anArc->center, anArc->start, anArc->startAngle));
-//  aNew->setTag((int)myConstraintLastID);
-  anArcConstraints.push_back(aNew);
-  aNew = GCSConstraintPtr(new GCS::ConstraintP2PAngle(
-      anArc->center, anArc->end, anArc->endAngle));
-//  aNew->setTag((int)myConstraintLastID);
-  anArcConstraints.push_back(aNew);
-
-  myArcConstraintMap[theArc] = anArcConstraints;
-}
 
+  EntityWrapperPtr aRelated = entity(anAttribute);
+  if (!aRelated) { // Attribute does not exist, create it.
+    // First of all check if the parent feature exists. If not, add it.
+    FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
+    if (aFeature && myFeatureMap.find(aFeature) == myFeatureMap.end())
+      return update(aFeature, theForce); // theAttribute has been processed while adding feature
 
-void PlaneGCSSolver_Storage::makeConstant(const EntityWrapperPtr& theEntity)
-{
-  toggleEntity(theEntity, myParameters, myConst);
-  if (theEntity->type() == ENTITY_POINT)
-    updateCoincident(theEntity);
+    PlaneGCSSolver_AttributeBuilder aBuilder(this);
+    aRelated = createAttribute(anAttribute, &aBuilder);
+    return aRelated.get() != 0;
+  }
+
+  bool isUpdated = updateValues(anAttribute, aRelated);
+  if (isUpdated)
+    setNeedToResolve(true);
+  return isUpdated;
 }
 
-void PlaneGCSSolver_Storage::makeVariable(const EntityWrapperPtr& theEntity)
+
+
+bool PlaneGCSSolver_Storage::removeConstraint(ConstraintPtr theConstraint)
 {
-  toggleEntity(theEntity, myConst, myParameters);
+  std::map<ConstraintPtr, ConstraintWrapperPtr>::iterator
+      aFound = myConstraintMap.find(theConstraint);
+  if (aFound != myConstraintMap.end()) {
+    ConstraintID anID = aFound->second->id();
+    // Remove solver's constraints
+    std::shared_ptr<PlaneGCSSolver_Solver> aSolver =
+        std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(mySketchSolver);
+    aSolver->removeConstraint(anID);
+    // Remove constraint
+    myConstraintMap.erase(aFound);
+
+    // notify subscibers
+    notify(theConstraint);
+  }
+  return true;
 }
 
-static void getParametersToMove(const EntityWrapperPtr& theEntity, std::set<double*>& theParamList)
+void PlaneGCSSolver_Storage::removeInvalidEntities()
 {
-  const std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
-  std::list<ParameterWrapperPtr>::const_iterator aPIt = aParams.begin();
-  for (; aPIt != aParams.end(); ++aPIt)
-    theParamList.insert(
-        std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*aPIt)->parameter());
-
-  const std::list<EntityWrapperPtr> aSubs = theEntity->subEntities();
-  std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
-
-  if (theEntity->type() == ENTITY_ARC) {
-    // workaround for the arc processing, because the arc is fixed by a set of constraints,
-    // which will conflict with all parameters fixed:
-    // 1. take center
-    getParametersToMove(*aSIt++, theParamList);
-    // 2. skip start and end points
-    ++aSIt;
-    // 3. take radius, start angle and end angle parameters
-    getParametersToMove(*(++aSIt), theParamList);
-    getParametersToMove(*(++aSIt), theParamList);
-    getParametersToMove(*(++aSIt), theParamList);
-  } else {
-    for (; aSIt != aSubs.end(); ++aSIt)
-      getParametersToMove(*aSIt, theParamList);
+  PlaneGCSSolver_EntityDestroyer aDestroyer;
+
+  // Remove invalid constraints
+  std::list<ConstraintPtr> anInvalidConstraints;
+  std::map<ConstraintPtr, 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);
+      aDestroyer.remove(aFIter->second);
+
+      // remove invalid arc
+      std::map<EntityWrapperPtr, ConstraintWrapperPtr>::iterator
+          aFound = myArcConstraintMap.find(aFIter->second);
+      if (aFound != myArcConstraintMap.end()) {
+        std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(
+            mySketchSolver)->removeConstraint(aFound->second->id());
+        myArcConstraintMap.erase(aFound);
+      }
+    }
+  std::list<FeaturePtr>::const_iterator anInvFIt = anInvalidFeatures.begin();
+  for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt)
+    removeFeature(*anInvFIt);
+
+  // Remove invalid attributes
+  std::list<AttributePtr> anInvalidAttributes;
+  std::map<AttributePtr, EntityWrapperPtr>::const_iterator anAttrIt = myAttributeMap.begin();
+  for (; anAttrIt != myAttributeMap.end(); ++anAttrIt) {
+    FeaturePtr anOwner = ModelAPI_Feature::feature(anAttrIt->first->owner());
+    if (!anOwner || !anOwner->data() || !anOwner->data()->isValid()) {
+      anInvalidAttributes.push_back(anAttrIt->first);
+      aDestroyer.remove(anAttrIt->second);
+    }
   }
+  std::list<AttributePtr>::const_iterator anInvAtIt = anInvalidAttributes.begin();
+  for (; anInvAtIt != anInvalidAttributes.end(); ++anInvAtIt)
+    removeAttribute(*anInvAtIt);
+
+  // free memory occupied by parameters
+  removeParameters(aDestroyer.parametersToRemove());
+
+  /// TODO: Think on optimization of checking invalid features and attributes
 }
 
-void PlaneGCSSolver_Storage::toggleEntity(
-    const EntityWrapperPtr& theEntity, GCS::VEC_pD& theFrom, GCS::VEC_pD& theTo)
-{
-  std::set<double*> aParamsToMove;
-  getParametersToMove(theEntity, aParamsToMove);
 
-  GCS::VEC_pD::iterator anIt = theFrom.begin();
-  while (anIt != theFrom.end()) {
-    if (aParamsToMove.find(*anIt) == aParamsToMove.end()) {
-      ++anIt;
-      continue;
-    }
 
-    theTo.push_back(*anIt);
-    int aShift = int(anIt - theFrom.begin());
-    theFrom.erase(anIt);
-    anIt = theFrom.begin() + aShift;
-  }
+double* PlaneGCSSolver_Storage::createParameter()
+{
+  double* aResult = new double(0);
+  myParameters.push_back(aResult);
+  return aResult;
 }
 
-void PlaneGCSSolver_Storage::updateCoincident(const EntityWrapperPtr& thePoint)
+void PlaneGCSSolver_Storage::removeParameters(const GCS::SET_pD& theParams)
 {
-  CoincidentPointsMap::iterator anIt = myCoincidentPoints.begin();
-  for (; anIt != myCoincidentPoints.end(); ++anIt) {
-    if (anIt->first == thePoint || anIt->second.find(thePoint) != anIt->second.end()) {
-      std::set<EntityWrapperPtr> aCoincident = anIt->second;
-      aCoincident.insert(anIt->first);
-
-      const std::list<ParameterWrapperPtr>& aBaseParams = thePoint->parameters();
-      std::list<ParameterWrapperPtr> aParams;
-      std::list<ParameterWrapperPtr>::const_iterator aBaseIt, anUpdIt;
-
-      std::set<EntityWrapperPtr>::const_iterator aCoincIt = aCoincident.begin();
-      for (; aCoincIt != aCoincident.end(); ++aCoincIt)
-        if (*aCoincIt != thePoint && (*aCoincIt)->group() != GID_OUTOFGROUP) {
-          aParams = (*aCoincIt)->parameters();
-          aBaseIt = aBaseParams.begin();
-          for (anUpdIt = aParams.begin(); anUpdIt != aParams.end(); ++anUpdIt, ++aBaseIt)
-            (*anUpdIt)->setValue((*aBaseIt)->value());
-        }
-
-      break;
-    }
-  }
+  for (int i = (int)myParameters.size() - 1; i >= 0; --i)
+    if (theParams.find(myParameters[i]) != theParams.end())
+      myParameters.erase(myParameters.begin() + i);
 }
 
 
@@ -605,54 +404,12 @@ bool PlaneGCSSolver_Storage::isRedundant(
   return false;
 }
 
-void PlaneGCSSolver_Storage::initializeSolver(SolverPtr theSolver)
+void PlaneGCSSolver_Storage::initializeSolver()
 {
   std::shared_ptr<PlaneGCSSolver_Solver> aSolver =
-      std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(theSolver);
-  if (!aSolver)
-    return;
-  aSolver->clear();
-
-  if (myExistArc)
-    processArcs();
-
-  // initialize constraints
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
-      aCIt = myConstraintMap.begin();
-  GCS::SET_I aTangentIDs;
-  std::list<std::set<double*> > aCoincidentPoints;
-  for (; aCIt != myConstraintMap.end(); ++aCIt) {
-    std::list<ConstraintWrapperPtr>::const_iterator aCWIt = aCIt->second.begin();
-    for (; aCWIt != aCIt->second.end(); ++ aCWIt) {
-      std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aGCS =
-          std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(*aCWIt);
-      std::list<GCSConstraintPtr>::const_iterator anIt = aGCS->constraints().begin();
-      for (; anIt != aGCS->constraints().end(); ++anIt)
-        if (!isRedundant(*anIt, aGCS, aCoincidentPoints))
-          aSolver->addConstraint(*anIt, aGCS->type());
-    }
-    // store IDs of tangent constraints to avoid incorrect report of redundant constraints
-    if (aCIt->first && aCIt->first->getKind() == SketchPlugin_ConstraintTangent::ID())
-      for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++ aCWIt)
-        aTangentIDs.insert((int)(*aCWIt)->id());
-  }
-  // additional constraints for arcs
-  std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
-      anArcIt = myArcConstraintMap.begin();
-  for (; anArcIt != myArcConstraintMap.end(); ++anArcIt) {
-    std::vector<GCSConstraintPtr>::const_iterator anIt = anArcIt->second.begin();
-    for (; anIt != anArcIt->second.end(); ++anIt)
-      aSolver->addConstraint(*anIt, CONSTRAINT_UNKNOWN);
-  }
-  // removed waste constraints
-  std::list<GCSConstraintPtr>::const_iterator aRemIt = myRemovedConstraints.begin();
-  for (; aRemIt != myRemovedConstraints.end(); ++aRemIt)
-    aSolver->removeConstraint(*aRemIt);
-  myRemovedConstraints.clear();
-  // set list of tangent constraints
-  aSolver->setTangent(aTangentIDs);
-  // initialize unknowns
-  aSolver->setParameters(myParameters);
+      std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(mySketchSolver);
+  if (aSolver)
+    aSolver->setParameters(myParameters);
 }
 
 // indicates attribute containing in the external feature
@@ -665,157 +422,35 @@ bool isExternalAttribute(const AttributePtr& theAttribute)
   return aSketchFeature.get() && aSketchFeature->isExternal();
 }
 
-void PlaneGCSSolver_Storage::refresh(bool theFixedOnly) const
+void PlaneGCSSolver_Storage::refresh() const
 {
-  //blockEvents(true);
-
   const double aTol = 1000. * tolerance; // tolerance to prevent frequent updates
 
   std::map<AttributePtr, EntityWrapperPtr>::const_iterator anIt = myAttributeMap.begin();
-  std::list<ParameterWrapperPtr> aParams;
-  std::list<ParameterWrapperPtr>::const_iterator aParIt;
   for (; anIt != myAttributeMap.end(); ++anIt) {
     // the external feature always should keep the up to date values, so,
     // refresh from the solver is never needed
-    bool isExternal = isExternalAttribute(anIt->first);
-
-    // 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) {
-      if (!theFixedOnly || isExternal ||
-          (*aParIt)->group() == GID_OUTOFGROUP || (*aParIt)->isParametric()) {
-        aCoords[i] = (*aParIt)->value();
-        isUpd[i] = true;
-      }
-    }
-    if (!isUpd[0] && !isUpd[1] && !isUpd[2])
-      continue; // nothing is updated
+    if (isExternalAttribute(anIt->first))
+      continue;
 
     std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anIt->first);
     if (aPoint2D) {
-      if ((isUpd[0] && fabs(aPoint2D->x() - aCoords[0]) > aTol) ||
-          (isUpd[1] && fabs(aPoint2D->y() - aCoords[1]) > aTol) || isExternal) {
-        // Find points coincident with this one (probably not in GID_OUTOFGROUP)
-        CoincidentPointsMap::const_iterator aCoincIt = myCoincidentPoints.begin();
-        for (; aCoincIt != myCoincidentPoints.end(); ++aCoincIt)
-          if (aCoincIt->first == anIt->second ||
-              aCoincIt->second.find(anIt->second) != aCoincIt->second.end())
-            break;
-        // get coordinates of "master"-point
-        std::shared_ptr<GeomDataAPI_Point2D> aMaster = aCoincIt != myCoincidentPoints.end() ?
-            std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aCoincIt->first->baseAttribute()) :
-            aPoint2D;
-        if (!isUpd[0] || isExternal) aCoords[0] = aMaster->x();
-        if (!isUpd[1] || isExternal) aCoords[1] = aMaster->y();
-        if (!isExternal)
-          aPoint2D->setValue(aCoords[0], aCoords[1]);
-        if (aCoincIt != myCoincidentPoints.end()) {
-          if (aMaster && !isExternalAttribute(aMaster))
-            aMaster->setValue(aCoords[0], aCoords[1]);
-          std::set<EntityWrapperPtr>::const_iterator aSlaveIt = aCoincIt->second.begin();
-          for (; aSlaveIt != aCoincIt->second.end(); ++aSlaveIt) {
-            aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>((*aSlaveIt)->baseAttribute());
-            if (aPoint2D && !isExternalAttribute(aPoint2D))
-              aPoint2D->setValue(aCoords[0], aCoords[1]);
-          }
-        }
-      }
+      std::shared_ptr<PlaneGCSSolver_PointWrapper> aPointWrapper =
+          std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+      GCSPointPtr aGCSPoint = aPointWrapper->point();
+      if (fabs(aPoint2D->x() - (*aGCSPoint->x)) > aTol ||
+          fabs(aPoint2D->y() - (*aGCSPoint->y)) > aTol)
+        aPoint2D->setValue(*aGCSPoint->x, *aGCSPoint->y);
       continue;
     }
     AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anIt->first);
-    if (aScalar && !isExternal) {
-      if (isUpd[0] && fabs(aScalar->value() - aCoords[0]) > aTol)
-        aScalar->setValue(aCoords[0]);
+    if (aScalar) {
+      ScalarWrapperPtr aScalarWrapper =
+          std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
+      if (fabs(aScalar->value() - aScalarWrapper->value()) > aTol)
+        aScalar->setValue(aScalarWrapper->value());
       continue;
     }
   }
-
-  //blockEvents(false);
-}
-
-EntityWrapperPtr PlaneGCSSolver_Storage::calculateMiddlePoint(
-    EntityWrapperPtr theBase, double theCoeff)
-{
-  std::shared_ptr<PlaneGCSSolver_Builder> aBuilder =
-      std::dynamic_pointer_cast<PlaneGCSSolver_Builder>(PlaneGCSSolver_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;
-  aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->x()));
-  aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->y()));
-  // Create entity (parameters are not filled)
-  GCSPointPtr aPnt(new GCS::Point);
-  aPnt->x =
-    std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
-  aPnt->y =
-    std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
-
-  EntityWrapperPtr aResult(new PlaneGCSSolver_PointWrapper(AttributePtr(), aPnt));
-  aResult->setGroup(myGroupID);
-  aResult->setParameters(aParameters);
-
-  update(aResult);
-  return aResult;
 }
index ccf318aef52130d938a635c43c272a0cbdd61a58..4af3f4e19b4a5642debde4e0dc58a1406bea3e73 100644 (file)
@@ -13,6 +13,8 @@
 #include <SketchSolver_Storage.h>
 #include <SketchSolver_ISolver.h>
 
+class PlaneGCSSolver_EntityBuilder;
+
 /** \class   PlaneGCSSolver_Storage
  *  \ingroup Plugins
  *  \brief   Contains all necessary data in PlaneGCS format to solve a single group of constraints
 class PlaneGCSSolver_Storage : public SketchSolver_Storage
 {
 public:
-  PlaneGCSSolver_Storage(const GroupID& theGroup);
+  PlaneGCSSolver_Storage(const SolverPtr& theSolver);
 
 // =============   Inherited from SketchSolver_Storage   =============
 
   /// \brief Change mapping between constraint from SketchPlugin and
-  ///        the list of constraints applicable for corresponding solver.
-  ///        Derived here to update point-point coincidence.
-  /// \param theConstraint        [in]   original SketchPlugin constraint
-  /// \param theSolverConstraints [in]   list of solver's constraints
-  virtual void addConstraint(ConstraintPtr                   theConstraint,
-                             std::list<ConstraintWrapperPtr> theSolverConstraints);
-
-  /// \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 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;
+  ///        a constraint applicable for corresponding solver.
+  /// \param theConstraint       [in]   original SketchPlugin constraint
+  /// \param theSolverConstraint [in]   solver's constraint
+  virtual void addConstraint(ConstraintPtr        theConstraint,
+                             ConstraintWrapperPtr theSolverConstraint) override;
 
-  /// \brief Check if some parameters or entities are returned
-  ///        to the current group after removing temporary constraints
-  virtual void verifyFixed();
+  /// \brief Add list of temporary constraints which will be destroyed
+  ///        after the next solving of the set of constraints.
+  /// \param theSolverConstraint [in]  solver's constraint
+  virtual void addTemporaryConstraint(const ConstraintWrapperPtr& theSolverConstraint) override;
 
-  /// \brief Mark two points as coincident
-  virtual void addCoincidentPoints(EntityWrapperPtr theMaster, EntityWrapperPtr theSlave);
 
-  /// \brief Shows the storage has the same constraint twice
-  virtual bool hasDuplicatedConstraint() const
-  { return false; }
+  /// \brief Convert feature to the form applicable for specific solver and map it
+  /// \param theFeature [in]  feature to convert
+  /// \param theForce   [in]  forced feature creation
+  /// \return \c true if the feature has been created or updated
+  virtual bool update(FeaturePtr theFeature, bool theForce = false) override;
 
-  /// \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);
+  /// \brief Convert attribute to the form applicable for specific solver and map it
+  /// \param theAttribute [in]  attribute to convert
+  /// \param theForce     [in]  forced feature creation
+  /// \return \c true if the attribute has been created or updated
+  virtual bool update(AttributePtr theAttribute, bool theForce = false) override;
 
-  /// \brief Initialize solver by constraints, entities and parameters
-  virtual void initializeSolver(SolverPtr theSolver);
 
-protected:
-  /// \brief Remove constraint
+  /// \brief Removes constraint from the storage
   /// \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);
+  virtual bool removeConstraint(ConstraintPtr theConstraint) override;
 
-  /// \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);
+  /// \brief Update SketchPlugin features after resolving constraints
+  virtual void refresh() const override;
 
+  /// \brief Initialize solver by constraints, entities and parameters
+  virtual void initializeSolver();
 
-// =============   Own methods   =============
+  /// \brief Initialize memory for new solver's parameter
+  double* createParameter();
+  /// \brief Release memory occupied by parameters
+  void removeParameters(const GCS::SET_pD& theParams);
 
-  /// \brief Move parameters of the entity to the constants
-  void makeConstant(const EntityWrapperPtr& theEntity);
-  /// \brief Move parameters of the entity to the variables
-  void makeVariable(const EntityWrapperPtr& theEntity);
+  /// \brief Remove all features became invalid
+  virtual void removeInvalidEntities() override;
 
 private:
-  /// \brief Move parameters of the entity from the list of variables to the list of constants
-  ///        and vice versa
-  /// \param theEntity [in]  entity to be changed
-  /// \param theFrom   [out] source list
-  /// \param theTo     [out] destination list
-  void toggleEntity(const EntityWrapperPtr& theEntity, GCS::VEC_pD& theFrom, GCS::VEC_pD& theTo);
-
-  /// \brief Create additional constraints for correct processing of arcs
-  /// \param theArc [in]  updated arc
-  void processArc(const EntityWrapperPtr& theArc);
-
-  /// \brief Adjust parameters of points coincident with the given
-  void updateCoincident(const EntityWrapperPtr& thePoint);
-
   /// \brief Verifies the constraint should not be added into the solver
   ///
   /// This is a workaround method to avoid some kinds of conflicting constraints:
@@ -111,18 +79,23 @@ private:
                    ConstraintWrapperPtr theParentConstraint,
                    std::list<std::set<double*> >& theCoincidentPoints) const;
 
+  /// \brief Convert feature using specified builder.
+  EntityWrapperPtr createFeature(const FeaturePtr&             theFeature,
+                                 PlaneGCSSolver_EntityBuilder* theBuilder);
+
+  /// \brief Convert attribute using specified builder.
+  EntityWrapperPtr createAttribute(const AttributePtr&           theAttribute,
+                                   PlaneGCSSolver_EntityBuilder* theBuilder);
+
 private:
-  GCS::VEC_pD                      myParameters;         ///< list of parameters
-  GCS::VEC_pD                      myConst;              ///< list of constants
-  EntityID                         myEntityLastID;       ///< identifier of last added entity
-  ConstraintID                     myConstraintLastID;   ///< identifier of last added constraint
+  GCS::VEC_pD  myParameters;         ///< list of parameters
+  ConstraintID myConstraintLastID;   ///< identifier of last added constraint
 
   /// additional constraints for correct processing of the arcs
-  std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >
-                                   myArcConstraintMap;
+  std::map<EntityWrapperPtr, ConstraintWrapperPtr> myArcConstraintMap;
 
   /// list of removed constraints to notify solver
-  std::list<GCSConstraintPtr>      myRemovedConstraints;
+  std::list<GCSConstraintPtr> myRemovedConstraints;
 };
 
 #endif
diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Update.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Update.h
new file mode 100644 (file)
index 0000000..2f1fddb
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File:    PlaneGCSSolver_Update.h
+// Created: 17 Feb 2017
+// Author:  Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_Update_H_
+#define PlaneGCSSolver_Update_H_
+
+#include <ModelAPI_Feature.h>
+
+#include <list>
+#include <memory>
+#include <string>
+
+class SketchSolver_Constraint;
+class PlaneGCSSolver_Update;
+typedef std::shared_ptr<PlaneGCSSolver_Update> UpdaterPtr;
+
+/** \class   PlaneGCSSolver_Update
+ *  \ingroup Plugins
+ *  \brief   Send events to listeners about changing a feature
+ */
+class PlaneGCSSolver_Update
+{
+public:
+  PlaneGCSSolver_Update(UpdaterPtr theNext = UpdaterPtr())
+    : myNext(theNext)
+  {}
+
+  virtual ~PlaneGCSSolver_Update() {}
+
+  /// \brief Attach listener
+  /// \param theObserver [in]  object which want to receive notifications
+  /// \param theType     [in]  receive notifications about changing objects
+  ///                          of theType and their derivatives
+  virtual void attach(SketchSolver_Constraint* theObserver, const std::string& theType) = 0;
+
+  /// \brief Detach listener
+  void detach(SketchSolver_Constraint* theObserver) {
+    std::list<SketchSolver_Constraint*>::iterator anIt = myObservers.begin();
+    for (; anIt != myObservers.end(); ++anIt)
+      if (*anIt == theObserver) {
+        myObservers.erase(anIt);
+        break;
+      }
+    // detach listener from all senders
+    if (myNext)
+      myNext->detach(theObserver);
+  }
+
+  /// \brief Send notification about update of the feature to all interested
+  virtual void update(const FeaturePtr& theFeature) = 0;
+
+protected:
+  UpdaterPtr myNext; ///< next updater, access if current one unable to process request
+  std::list<SketchSolver_Constraint*> myObservers; ///< list of observers
+};
+
+#endif
diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp
new file mode 100644 (file)
index 0000000..2051952
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    PlaneGCSSolver_UpdateCoincidence.cpp
+// Created: 17 Feb 2017
+// Author:  Artem ZHIDKOV
+
+#include <PlaneGCSSolver_UpdateCoincidence.h>
+#include <SketchSolver_Constraint.h>
+
+#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintMiddle.h>
+
+void PlaneGCSSolver_UpdateCoincidence::attach(SketchSolver_Constraint* theObserver, const std::string& theType)
+{
+  if (theType == GROUP()) {
+    std::list<SketchSolver_Constraint*>::iterator aPlaceToAdd = myObservers.end();
+    // point-point coincidence is placed first
+    if (theObserver->getType() == CONSTRAINT_PT_PT_COINCIDENT) {
+      for (aPlaceToAdd = myObservers.begin(); aPlaceToAdd != myObservers.end(); ++aPlaceToAdd)
+        if ((*aPlaceToAdd)->getType() != CONSTRAINT_PT_PT_COINCIDENT)
+          break;
+    }
+    myObservers.insert(aPlaceToAdd, theObserver);
+  } else
+    myNext->attach(theObserver, theType);
+}
+
+void PlaneGCSSolver_UpdateCoincidence::update(const FeaturePtr& theFeature)
+{
+  if (theFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
+      theFeature->getKind() == SketchPlugin_ConstraintMiddle::ID()) {
+    myCoincident.clear();
+    // notify listeners and stop procesing
+    std::list<SketchSolver_Constraint*>::iterator anIt = myObservers.begin();
+    for (; anIt != myObservers.end(); ++anIt)
+      (*anIt)->notify(theFeature, this);
+  } else
+    myNext->update(theFeature);
+}
+
+bool PlaneGCSSolver_UpdateCoincidence::checkCoincidence(
+    const EntityWrapperPtr& theEntity1,
+    const EntityWrapperPtr& theEntity2)
+{
+  bool isAccepted = true;
+
+  std::list<std::set<EntityWrapperPtr> >::iterator anIt = myCoincident.begin();
+  std::list<std::set<EntityWrapperPtr> >::iterator aFound1 = myCoincident.end();
+  std::list<std::set<EntityWrapperPtr> >::iterator aFound2 = myCoincident.end();
+  for (; anIt != myCoincident.end(); ++anIt) {
+    if (aFound1 == myCoincident.end() && anIt->find(theEntity1) != anIt->end())
+      aFound1 = anIt;
+    if (aFound2 == myCoincident.end() && anIt->find(theEntity2) != anIt->end())
+      aFound2 = anIt;
+    if (aFound1 != myCoincident.end() && aFound2 != myCoincident.end())
+      break;
+  }
+
+  if (aFound1 == myCoincident.end() && aFound2 == myCoincident.end()) {
+    // new group of coincidence
+    std::set<EntityWrapperPtr> aNewCoinc;
+    aNewCoinc.insert(theEntity1);
+    aNewCoinc.insert(theEntity2);
+    myCoincident.push_back(aNewCoinc);
+  } else if (aFound1 == aFound2) // same group => already coincident
+    isAccepted = false;
+  else if (aFound1 == myCoincident.end())
+    aFound2->insert(theEntity1);
+  else if (aFound2 == myCoincident.end())
+    aFound1->insert(theEntity2);
+  else { // merge two groups
+    aFound1->insert(aFound2->begin(), aFound2->end());
+    myCoincident.erase(aFound2);
+  }
+
+  return isAccepted;
+}
diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.h
new file mode 100644 (file)
index 0000000..d6320f6
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File:    PlaneGCSSolver_UpdateCoincidence.h
+// Created: 17 Feb 2017
+// Author:  Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_UpdateCoincidence_H_
+#define PlaneGCSSolver_UpdateCoincidence_H_
+
+#include <PlaneGCSSolver_Update.h>
+#include <SketchSolver_IEntityWrapper.h>
+
+/** \class   PlaneGCSSolver_UpdateCoincidence
+ *  \ingroup Plugins
+ *  \brief   Send events to listeners about changing a constraint
+ */
+class PlaneGCSSolver_UpdateCoincidence : public PlaneGCSSolver_Update
+{
+public:
+  PlaneGCSSolver_UpdateCoincidence(UpdaterPtr theNext = UpdaterPtr())
+    : PlaneGCSSolver_Update(theNext)
+  {}
+
+  virtual ~PlaneGCSSolver_UpdateCoincidence() {}
+
+  /// \brief Group of entities, processed by this kind of updater
+  static const std::string& GROUP()
+  {
+    static const std::string TYPE("Coincidence");
+    return TYPE;
+  }
+
+  /// \brief Attach listener
+  /// \param theObserver [in]  object which want to receive notifications
+  /// \param theType     [in]  receive notifications about changing objects
+  ///                          of theType and their derivatives
+  virtual void attach(SketchSolver_Constraint* theObserver, const std::string& theType) override;
+
+  /// \brief Send notification about update of the feature to all interested
+  virtual void update(const FeaturePtr& theFeature) override;
+
+  /// \brief Verifies the entities are not coincident yet
+  /// \return \c true if the entities does not coincident
+  bool checkCoincidence(const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2);
+
+private:
+  std::list<std::set<EntityWrapperPtr> > myCoincident; ///< list of coincidences
+};
+
+#endif
diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateFeature.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateFeature.cpp
new file mode 100644 (file)
index 0000000..5ff77f8
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    PlaneGCSSolver_UpdateFeature.cpp
+// Created: 17 Feb 2017
+// Author:  Artem ZHIDKOV
+
+#include <PlaneGCSSolver_UpdateFeature.h>
+#include <SketchSolver_Constraint.h>
+
+void PlaneGCSSolver_UpdateFeature::attach(SketchSolver_Constraint* theObserver, const std::string& theType)
+{
+  if (theType == GROUP())
+    myObservers.push_back(theObserver);
+  else
+    myNext->attach(theObserver, theType);
+}
+
+void PlaneGCSSolver_UpdateFeature::update(const FeaturePtr& theFeature)
+{
+  std::list<SketchSolver_Constraint*>::iterator anIt = myObservers.begin();
+  for (; anIt != myObservers.end(); ++anIt)
+    (*anIt)->notify(theFeature, this);
+}
diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateFeature.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateFeature.h
new file mode 100644 (file)
index 0000000..9da1a6e
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File:    PlaneGCSSolver_UpdateFeature.h
+// Created: 17 Feb 2017
+// Author:  Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_UpdateFeature_H_
+#define PlaneGCSSolver_UpdateFeature_H_
+
+#include <PlaneGCSSolver_Update.h>
+
+/** \class   PlaneGCSSolver_UpdateFeature
+ *  \ingroup Plugins
+ *  \brief   Send events to listeners about changing a feature
+ */
+class PlaneGCSSolver_UpdateFeature : public PlaneGCSSolver_Update
+{
+public:
+  PlaneGCSSolver_UpdateFeature(UpdaterPtr theNext = UpdaterPtr())
+    : PlaneGCSSolver_Update(theNext)
+  {}
+
+  /// \brief Group of entities, processed by this kind of updater
+  static const std::string& GROUP()
+  {
+    static const std::string TYPE("Feature");
+    return TYPE;
+  }
+
+  /// \brief Attach listener
+  /// \param theObserver [in]  object which want to receive notifications
+  /// \param theType     [in]  receive notifications about changing objects
+  ///                          of theType and their derivatives
+  virtual void attach(SketchSolver_Constraint* theObserver, const std::string& theType) override;
+
+  /// \brief Send notification about update of the feature to all interested
+  virtual void update(const FeaturePtr& theFeature) override;
+};
+
+#endif
index 8beb83a984e5e8d150ab38abe46a4b2a70c852aa..775702389fbfe343d8f59bb3769288550fe0492e 100644 (file)
@@ -5,38 +5,16 @@
 
 #include <stdlib.h>
 
-#if defined SKETCHSOLVER_EXPORTS
-#if defined WIN32
-#define SKETCHSOLVER_EXPORT              __declspec( dllexport )
-#else
-#define SKETCHSOLVER_EXPORT
-#endif
-#else
-#if defined WIN32
-#define SKETCHSOLVER_EXPORT              __declspec( dllimport )
-#else
-#define SKETCHSOLVER_EXPORT
-#endif
-#endif
-
 /// Tolerance for value of parameters
 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;
+typedef int 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 EntityID      EID_SKETCH     = 1;
-const ConstraintID  CID_UNKNOWN    = 0;
+const ConstraintID CID_UNKNOWN  =  0;
+const ConstraintID CID_MOVEMENT = -1;
 
 #endif
index 718ea18cacc6bdb7ccc6d2ef6f50f170faea00ef..d5bf71dc933c20fa04ddc156239278d11d1d1e75 100644 (file)
 #include <SketchSolver_ConstraintDistance.h>
 #include <SketchSolver_ConstraintEqual.h>
 #include <SketchSolver_ConstraintFixed.h>
-#include <SketchSolver_ConstraintFixedArcRadius.h>
 #include <SketchSolver_ConstraintLength.h>
 #include <SketchSolver_ConstraintMiddle.h>
 #include <SketchSolver_ConstraintMirror.h>
 #include <SketchSolver_ConstraintTangent.h>
 #include <SketchSolver_ConstraintMultiRotation.h>
 #include <SketchSolver_ConstraintMultiTranslation.h>
-#include <SketchSolver_ConstraintMovement.h>
 
 #ifdef _DEBUG
 #include <Events_InfoMessage.h>
 #include <SketchPlugin_MultiRotation.h>
 #include <SketchPlugin_MultiTranslation.h>
 
-#include <math.h>
+#include <cmath>
 
 SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theConstraint) const
 {
   SolverConstraintPtr aResult;
   DataPtr aData = theConstraint->data();
-  if (!aData || !aData->isValid())
-    return aResult;
 
 #ifdef _DEBUG
   // Verify attributes of constraint and generate errors
@@ -110,61 +106,7 @@ SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theCons
   return SolverConstraintPtr(new SketchSolver_Constraint(theConstraint));
 }
 
-SolverConstraintPtr SketchSolver_Builder::createFixedConstraint(FeaturePtr theFixedFeature) const
+SolverConstraintPtr SketchSolver_Builder::createMovementConstraint(FeaturePtr theMovedFeature) const
 {
-  DataPtr aData = theFixedFeature->data();
-  if (!aData || !aData->isValid())
-    return SolverConstraintPtr();
-  return SolverConstraintPtr(new SketchSolver_ConstraintFixed(theFixedFeature));
+  return SolverConstraintPtr(new SketchSolver_ConstraintFixed(theMovedFeature));
 }
-
-SolverConstraintPtr SketchSolver_Builder::createFixedArcRadiusConstraint(FeaturePtr theArc) const
-{
-  DataPtr aData = theArc->data();
-  if (!aData || !aData->isValid())
-    return SolverConstraintPtr();
-  return SolverConstraintPtr(new SketchSolver_ConstraintFixedArcRadius(theArc));
-}
-
-SolverConstraintPtr SketchSolver_Builder::createMovementConstraint(FeaturePtr theFixedFeature) const
-{
-  DataPtr aData = theFixedFeature->data();
-  if (!aData || !aData->isValid())
-    return SolverConstraintPtr();
-  return SolverConstraintPtr(new SketchSolver_ConstraintMovement(theFixedFeature));
-}
-
-std::shared_ptr<GeomAPI_Pnt2d> SketchSolver_Builder::point(EntityWrapperPtr theEntity) const
-{
-  if (theEntity->type() != ENTITY_POINT)
-    return std::shared_ptr<GeomAPI_Pnt2d>();
-  if (theEntity->subEntities().size() == 1) // SketchPlugin_Point wrapper
-    return point(theEntity->subEntities().front());
-
-  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]));
-}
-
-std::shared_ptr<GeomAPI_Lin2d> SketchSolver_Builder::line(EntityWrapperPtr theEntity) const
-{
-  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]));
-}
-
index a2d67beb84f2e47bdde2b39f9596575eba5daa42..10677a712efb7f42bdf93f79054fe19c98be0898 100644 (file)
@@ -21,7 +21,7 @@ class SketchSolver_Builder
 {
 public:
   /// \brief Creates a storage specific for used solver
-  virtual StoragePtr createStorage(const GroupID& theGroup) const = 0;
+  virtual StoragePtr createStorage(const SolverPtr&) const = 0;
   /// \brief Creates specific solver
   virtual SolverPtr createSolver() const = 0;
 
@@ -29,35 +29,23 @@ public:
   ///        or returns empty pointer if not all attributes are correct
   SolverConstraintPtr createConstraint(ConstraintPtr theConstraint) const;
 
-  /// \brief Creates temporary constraint to fix the placement of the feature
-  SolverConstraintPtr createFixedConstraint(FeaturePtr theFixedFeature) const;
-
-  /// \brief Creates temporary constraint to fix radius of the arc
-  SolverConstraintPtr createFixedArcRadiusConstraint(FeaturePtr theArc) const;
-
   /// \brief Creates temporary constraint to fix the feature after movement
-  SolverConstraintPtr createMovementConstraint(FeaturePtr theFixedFeature) const;
+  SolverConstraintPtr createMovementConstraint(FeaturePtr theMovedFeature) const;
 
-  /// \brief Creates new constraint(s) using given parameters
+  /// \brief Creates new constraint 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
+  ///                            (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>
+  /// \return Created wrapper of constraints applicable for specific solver.
+  virtual ConstraintWrapperPtr
     createConstraint(ConstraintPtr theConstraint,
-                     const GroupID& theGroup,
-                     const EntityID& theSketchID,
                      const SketchSolver_ConstraintType& theType,
-                     const double& theValue,
+                     const EntityWrapperPtr& theValue,
                      const EntityWrapperPtr& theEntity1,
                      const EntityWrapperPtr& theEntity2 = EntityWrapperPtr(),
                      const EntityWrapperPtr& theEntity3 = EntityWrapperPtr(),
@@ -65,62 +53,39 @@ public:
 
   /// \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 theFullValue  [in]  indicates theValue shows full translation delta/rotation angle or
-  ///  delta/angle between neighbor entities
+  ///                            delta/angle between neighbor entities
   /// \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>
+  virtual ConstraintWrapperPtr
     createConstraint(ConstraintPtr theConstraint,
-                     const GroupID& theGroup,
-                     const EntityID& theSketchID,
                      const SketchSolver_ConstraintType& theType,
-                     const double& theValue,
+                     const EntityWrapperPtr& theValue,
                      const bool theFullValue,
                      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;
+  virtual std::shared_ptr<GeomAPI_Pnt2d> point(EntityWrapperPtr theEntity) const = 0;
+  /// \brief Convert entity to line
+  /// \return empty pointer if the entity is not a line
+  virtual std::shared_ptr<GeomAPI_Lin2d> line(EntityWrapperPtr theEntity) const = 0;
+
   /// \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;
+  virtual std::shared_ptr<GeomAPI_Lin2d> line(FeaturePtr theFeature) const = 0;
 
   /// \brief Check if two connected arcs have centers
   ///        in same direction relatively to connection point
-  SKETCHSOLVER_EXPORT virtual bool isArcArcTangencyInternal(EntityWrapperPtr theArc1,
-    EntityWrapperPtr theArc2) const { return false; }
+  virtual bool isArcArcTangencyInternal(EntityWrapperPtr theArc1,
+                                        EntityWrapperPtr theArc2) const = 0;
 };
 
 typedef std::shared_ptr<SketchSolver_Builder> BuilderPtr;
index bbf00518aa95c1e1f57ec7f12aaa4f7c65e23612..1ac6bc83b10da26e4985ae164160a6258446b5c1 100644 (file)
@@ -5,6 +5,8 @@
 #include <SketchSolver_Error.h>
 #include <SketchSolver_Manager.h>
 
+#include <PlaneGCSSolver_AttributeBuilder.h>
+
 #include <SketchPlugin_Arc.h>
 #include <SketchPlugin_Circle.h>
 #include <SketchPlugin_Line.h>
 SketchSolver_Constraint::SketchSolver_Constraint(
     ConstraintPtr  theConstraint)
   : myBaseConstraint(theConstraint),
-    myGroupID(GID_UNKNOWN),
     myType(CONSTRAINT_UNKNOWN)
 {
 }
 
-void SketchSolver_Constraint::process(StoragePtr theStorage,
-                                      const GroupID& theGroupID,
-                                      const EntityID& theSketchID)
+void SketchSolver_Constraint::process(StoragePtr theStorage, bool theEvensBlocked)
 {
   myStorage = theStorage;
-  myGroupID = theGroupID;
-  mySketchID = theSketchID;
+  blockEvents(theEvensBlocked);
   // Process constraint according to its type
   process();
 }
 
+void SketchSolver_Constraint::blockEvents(bool isBlocked)
+{
+  myBaseConstraint->data()->blockSendAttributeUpdated(isBlocked);
+}
+
 
 SketchSolver_ConstraintType SketchSolver_Constraint::TYPE(ConstraintPtr theConstraint)
 {
@@ -93,13 +96,13 @@ SketchSolver_ConstraintType SketchSolver_Constraint::TYPE(ConstraintPtr theConst
 void SketchSolver_Constraint::process()
 {
   cleanErrorMsg();
-  if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
+  if (!myBaseConstraint || !myStorage) {
     // Not enough parameters are assigned
     return;
   }
 
   SketchSolver_ConstraintType aConstrType = getType();
-  double aValue;
+  EntityWrapperPtr aValue;
   std::vector<EntityWrapperPtr> anAttributes;
   getAttributes(aValue, anAttributes);
   if (!myErrorMsg.empty())
@@ -112,10 +115,10 @@ void SketchSolver_Constraint::process()
     aConstrType = getType();
 
   BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-  std::list<ConstraintWrapperPtr> aNewConstraints = aBuilder->createConstraint(
-      myBaseConstraint, myGroupID, mySketchID, aConstrType,
+  ConstraintWrapperPtr aNewConstraint = aBuilder->createConstraint(
+      myBaseConstraint, aConstrType,
       aValue, anAttributes[0], anAttributes[1], anAttributes[2], anAttributes[3]);
-  myStorage->addConstraint(myBaseConstraint, aNewConstraints);
+  myStorage->addConstraint(myBaseConstraint, aNewConstraint);
 
   adjustConstraint();
 }
@@ -123,69 +126,42 @@ void SketchSolver_Constraint::process()
 void SketchSolver_Constraint::update()
 {
   cleanErrorMsg();
-  std::list<ConstraintWrapperPtr> aWrapper = myStorage->constraint(myBaseConstraint);
-  std::list<ConstraintWrapperPtr>::iterator aWIt = aWrapper.begin();
 
-  // Check if attributes of constraint are changed, rebuild constraint
-  std::set<AttributePtr> anAttributes;
-  std::set<AttributePtr>::iterator aFoundAttr;
-  std::set<FeaturePtr> aFeatures;
-  std::set<FeaturePtr>::iterator aFoundFeat;
+  // Get list of attributes of the constraint and compare it with previously stored.
+  // If the lists are different, fully rebuild constraint
+  std::set<EntityWrapperPtr> anAttributes;
   for (int anEntIndex = 0; anEntIndex < 4; ++anEntIndex) {
     AttributePtr anAttr =
         myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(anEntIndex));
     if (!anAttr)
       continue;
 
-    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
-    if (aRefAttr) {
-      if (aRefAttr->isObject()) {
-        FeaturePtr aFeat = ModelAPI_Feature::feature(aRefAttr->object());
-        if (myBaseConstraint->getKind() != SketchPlugin_ConstraintLength::ID())
-          aFeatures.insert(aFeat);
-        else {
-          // Workaround for the Length constraint: add points of line, not line itself
-          anAttributes.insert(aFeat->attribute(SketchPlugin_Line::START_ID()));
-          anAttributes.insert(aFeat->attribute(SketchPlugin_Line::END_ID()));
-        }
-      } else
-        anAttributes.insert(aRefAttr->attr());
-    } else
-      anAttributes.insert(anAttr);
-  }
-  bool hasNewAttr = !(anAttributes.empty() && aFeatures.empty());
-  for (; hasNewAttr && aWIt != aWrapper.end(); ++ aWIt) {
-    const std::list<EntityWrapperPtr>& aSubs = (*aWIt)->entities();
-    std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
-    for (; hasNewAttr && aSIt != aSubs.end(); ++aSIt) {
-      if ((*aSIt)->baseAttribute()) {
-        aFoundAttr = anAttributes.find((*aSIt)->baseAttribute());
-        if (aFoundAttr != anAttributes.end())
-          anAttributes.erase(aFoundAttr);
-      } else {
-        aFoundFeat = aFeatures.find((*aSIt)->baseFeature());
-        if (aFoundFeat != aFeatures.end())
-          aFeatures.erase(aFoundFeat);
+    if (myBaseConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) {
+      AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
+      FeaturePtr aFeat = ModelAPI_Feature::feature(aRefAttr->object());
+      if (aFeat) {
+        // Workaround for the Length constraint: add points of line, not line itself
+        anAttributes.insert(myStorage->entity(aFeat->attribute(SketchPlugin_Line::START_ID())));
+        anAttributes.insert(myStorage->entity(aFeat->attribute(SketchPlugin_Line::END_ID())));
       }
-      hasNewAttr = !(anAttributes.empty() && aFeatures.empty());
-    }
+    } else
+      anAttributes.insert(myStorage->entity(anAttr));
   }
-  if (hasNewAttr) {
+
+  std::set<EntityWrapperPtr>::iterator aFound;
+  std::list<EntityWrapperPtr>::const_iterator anAttrIt = myAttributes.begin();
+  for (; anAttrIt != myAttributes.end() && !anAttributes.empty(); ++anAttrIt)
+    anAttributes.erase(*anAttrIt);
+
+  if (!anAttributes.empty()) {
     remove();
     process();
     return;
   }
 
-  AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
-      myBaseConstraint->attribute(SketchPlugin_Constraint::VALUE()));
-  if (aValueAttr) {
-    for (aWIt = aWrapper.begin(); aWIt != aWrapper.end(); ++aWIt)
-      if (fabs((*aWIt)->value() - aValueAttr->value()) > tolerance) {
-        (*aWIt)->setValue(aValueAttr->value());
-        myStorage->setNeedToResolve(true);
-      }
-  }
-  myStorage->addConstraint(myBaseConstraint, aWrapper);
+  AttributeDoublePtr aValueAttr = myBaseConstraint->real(SketchPlugin_Constraint::VALUE());
+  if (aValueAttr)
+    myStorage->update(aValueAttr);
 
   adjustConstraint();
 }
@@ -194,11 +170,12 @@ bool SketchSolver_Constraint::remove()
 {
   cleanErrorMsg();
   myType = CONSTRAINT_UNKNOWN;
+  myStorage->unsubscribeUpdates(this);
   return myStorage->removeConstraint(myBaseConstraint);
 }
 
 void SketchSolver_Constraint::getAttributes(
-    double& theValue,
+    EntityWrapperPtr& theValue,
     std::vector<EntityWrapperPtr>& theAttributes)
 {
   static const int anInitNbOfAttr = 4;
@@ -210,9 +187,12 @@ void SketchSolver_Constraint::getAttributes(
 
   myType = TYPE(myBaseConstraint);
 
-  AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
-      aData->attribute(SketchPlugin_Constraint::VALUE()));
-  theValue = aValueAttr ? aValueAttr->value() : 0.0;
+  AttributeDoublePtr aValueAttr = aData->real(SketchPlugin_Constraint::VALUE());
+  if (aValueAttr) {
+    PlaneGCSSolver_AttributeBuilder aValueBuilder;
+    theValue = aValueBuilder.createAttribute(aValueAttr);
+    myStorage->addEntity(aValueAttr, theValue);
+  }
 
   int aPtInd = 0; // index of first point in the list of attributes
   int aEntInd = 2; // index of first entity in the list of attributes
@@ -226,13 +206,8 @@ void SketchSolver_Constraint::getAttributes(
       return;
     }
 
-    myStorage->update(*anIter/*, myGroupID*/);
+    myStorage->update(*anIter, true);
     EntityWrapperPtr anEntity = myStorage->entity(*anIter);
-    if (!anEntity) {
-      // Force creation of an entity
-      myStorage->update(*anIter, GID_UNKNOWN, true);
-      anEntity = myStorage->entity(*anIter);
-    }
     myAttributes.push_back(anEntity);
 
     SketchSolver_EntityType aType = anEntity->type();
@@ -249,41 +224,3 @@ void SketchSolver_Constraint::getAttributes(
     }
   }
 }
-
-bool SketchSolver_Constraint::isUsed(FeaturePtr theFeature) const
-{
-  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;
-
-  return false;
-}
-
-bool SketchSolver_Constraint::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();
-  }
-
-  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;
-  return false;
-}
index 69513749c3fb3d5ad24b3e357e45da18438407e8..5c06e0aa5434f268cfd35570011e0375cb26e696 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "SketchSolver.h"
 #include <SketchSolver_Storage.h>
+#include <PlaneGCSSolver_Update.h>
 
 #include <SketchPlugin_Constraint.h>
 
@@ -27,50 +28,41 @@ class SketchSolver_Constraint
 protected:
   /// Default constructor
   SketchSolver_Constraint()
-    : myGroupID(GID_UNKNOWN),
-      myType(CONSTRAINT_UNKNOWN)
+    : myType(CONSTRAINT_UNKNOWN)
   {}
 
 public:
   /// Constructor based on SketchPlugin constraint
-  SKETCHSOLVER_EXPORT SketchSolver_Constraint(ConstraintPtr theConstraint);
+  SketchSolver_Constraint(ConstraintPtr theConstraint);
 
   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);
+  /// \param theStorage       [in]  storage where to place new constraint
+  /// \param theEventsBlocked [in]  all events from this constraint should be blocked
+  void process(StoragePtr theStorage, bool theEvensBlocked);
+
+  /// \brief Notify this object about the feature is changed somewhere
+  virtual void notify(const FeaturePtr& theFeature, PlaneGCSSolver_Update* theUpdater) {}
 
   /// \brief Update constraint
-  SKETCHSOLVER_EXPORT virtual void update();
+  virtual void update();
 
   /// \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();
+
+  /// \brief Block or unblock events from this constraint
+  virtual void blockEvents(bool isBlocked);
 
   /// \brief Obtain a type of SketchPlugin constraint
-  SKETCHSOLVER_EXPORT static SketchSolver_ConstraintType TYPE(ConstraintPtr theConstraint);
+  static SketchSolver_ConstraintType TYPE(ConstraintPtr theConstraint);
 
   /// \brief Returns the type of constraint
   virtual SketchSolver_ConstraintType getType() const
   { return myType; }
 
-  /// \brief Returns list of attributes of constraint
-  const std::list<EntityWrapperPtr>& attributes() const
-  { return myAttributes; }
-
-  /// \brief Verify the feature or any its attribute is used by constraint
-  virtual bool isUsed(FeaturePtr theFeature) const;
-  /// \brief Verify the attribute is used by constraint
-  virtual bool isUsed(AttributePtr theAttribute) const;
-
-  /// \brief Notify constraint, that coincidence appears or removed
-  virtual void notifyCoincidenceChanged(EntityWrapperPtr theCoincAttr1,
-    EntityWrapperPtr theCoincAttr2) { /* implement in derived class */ }
-
   /// \brief Shows error message
   const std::string& error() const
   { return myErrorMsg; }
@@ -82,7 +74,8 @@ 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);
+  virtual void getAttributes(EntityWrapperPtr&              theValue,
+                             std::vector<EntityWrapperPtr>& theAttributes);
 
   /// \brief This method is used in derived objects to check consistency of constraint.
   ///        E.g. the distance between line and point may be signed.
@@ -94,9 +87,8 @@ protected:
   { 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
+  ConstraintWrapperPtr mySolverConstraint; ///< wrapper for PlaneGCS constraint
 
   /// storage, which contains all information about entities and constraints
   StoragePtr    myStorage;
index f4207163b241f406bbe39f35116326f883fbaf44..38ba87eb40c64b92ec3f6aed838025c7d40d5fc6 100644 (file)
@@ -1,41 +1,20 @@
 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
 
 #include <SketchSolver_ConstraintAngle.h>
-#include <SketchSolver_Manager.h>
-
-#include <GeomAPI_Dir2d.h>
-#include <GeomAPI_Lin2d.h>
-#include <GeomAPI_Pnt2d.h>
-#include <GeomAPI_XY.h>
 
 #include <ModelAPI_AttributeInteger.h>
-
 #include <SketchPlugin_ConstraintAngle.h>
 
-#include <cmath>
-
 void SketchSolver_ConstraintAngle::getAttributes(
-    double& theValue, std::vector<EntityWrapperPtr>& theAttributes)
+    EntityWrapperPtr& theValue, std::vector<EntityWrapperPtr>& theAttributes)
 {
   SketchSolver_Constraint::getAttributes(theValue, theAttributes);
-
-  myAngle = theValue;
   myType = myBaseConstraint->integer(SketchPlugin_ConstraintAngle::TYPE_ID())->value();
 }
 
 
 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();
-  aBuilder->adjustConstraint(aConstraint);
-  myStorage->addConstraint(myBaseConstraint, aConstraint);
-
   int aType = myBaseConstraint->integer(SketchPlugin_ConstraintAngle::TYPE_ID())->value();
   if (aType != myType) {
     myType = aType;
index cff6937c39f2a54ff5e7cb0661e169b9232d5f6e..1c6883c063eb2f08709ae236546ab33e7f94ad49 100644 (file)
@@ -17,22 +17,21 @@ class SketchSolver_ConstraintAngle : public SketchSolver_Constraint
 {
 public:
   /// Constructor based on SketchPlugin constraint
-  SketchSolver_ConstraintAngle(ConstraintPtr theConstraint) :
-      SketchSolver_Constraint(theConstraint),
-      myAngle(0.0)
+  SketchSolver_ConstraintAngle(ConstraintPtr theConstraint)
+    : SketchSolver_Constraint(theConstraint)
   {}
 
   /// \brief This method is used in derived objects to check consistence of constraint.
-  virtual void adjustConstraint();
+  virtual void adjustConstraint() override;
 
 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);
+  virtual void getAttributes(EntityWrapperPtr&              theValue,
+                             std::vector<EntityWrapperPtr>& theAttributes) override;
 
 private:
-  double myAngle;
   int    myType;
 };
 
index 18594018c4f38fe3c38f00aa468eae76d1d478d2..8501289fd2b475d9532f2d77cc5eba1796d783d6 100644 (file)
@@ -3,9 +3,37 @@
 #include <SketchSolver_ConstraintCoincidence.h>
 #include <SketchSolver_Error.h>
 #include <SketchSolver_Manager.h>
+#include <PlaneGCSSolver_UpdateCoincidence.h>
+
+void SketchSolver_ConstraintCoincidence::process()
+{
+  cleanErrorMsg();
+  if (!myBaseConstraint || !myStorage) {
+    // Not enough parameters are assigned
+    return;
+  }
+
+  EntityWrapperPtr aValue;
+  std::vector<EntityWrapperPtr> anAttributes;
+  getAttributes(aValue, anAttributes);
+  if (!myErrorMsg.empty())
+    return;
+  if (anAttributes.empty()) {
+    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+    return;
+  }
+
+  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
+  mySolverConstraint = aBuilder->createConstraint(
+      myBaseConstraint, getType(),
+      aValue, anAttributes[0], anAttributes[1], anAttributes[2], anAttributes[3]);
+
+  myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateCoincidence::GROUP());
+  myStorage->notify(myBaseConstraint);
+}
 
 void SketchSolver_ConstraintCoincidence::getAttributes(
-    double& theValue,
+    EntityWrapperPtr& theValue,
     std::vector<EntityWrapperPtr>& theAttributes)
 {
   SketchSolver_Constraint::getAttributes(theValue, theAttributes);
@@ -14,19 +42,8 @@ void SketchSolver_ConstraintCoincidence::getAttributes(
     return;
   }
 
-  if (theAttributes[1]) {
+  if (theAttributes[1])
     myType = CONSTRAINT_PT_PT_COINCIDENT;
-    if (myStorage->isFixed(theAttributes[1]) && !myStorage->isFixed(theAttributes[0])) {
-      // fixed point should go first
-      EntityWrapperPtr aTemp = theAttributes[0];
-      theAttributes[0] = theAttributes[1];
-      theAttributes[1] = aTemp;
-    }
-    // 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]);
-  }
   else if (theAttributes[2]) {
     // check the type of entity (line or circle)
     SketchSolver_EntityType anEntType = theAttributes[2]->type();
@@ -39,3 +56,22 @@ void SketchSolver_ConstraintCoincidence::getAttributes(
   } else
     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
 }
+
+void SketchSolver_ConstraintCoincidence::notify(const FeaturePtr&      theFeature,
+                                                PlaneGCSSolver_Update* theUpdater)
+{
+  PlaneGCSSolver_UpdateCoincidence* anUpdater =
+      static_cast<PlaneGCSSolver_UpdateCoincidence*>(theUpdater);
+  bool isAccepted = anUpdater->checkCoincidence(myAttributes.front(), myAttributes.back());
+  if (isAccepted) {
+    if (!myInSolver) {
+      myInSolver = true;
+      myStorage->addConstraint(myBaseConstraint, mySolverConstraint);
+    }
+  } else {
+    if (myInSolver) {
+      myInSolver = false;
+      myStorage->removeConstraint(myBaseConstraint);
+    }
+  }
+}
index 58b0d98dfdad486a6c53818215d2bf95fdce21c0..634618ff2c3c536d97055df6d040829aa4d301ae 100644 (file)
@@ -18,15 +18,27 @@ 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),
+      myInSolver(false)
   {}
 
+  /// \brief Notify this object about the feature is changed somewhere
+  virtual void notify(const FeaturePtr&      theFeature,
+                      PlaneGCSSolver_Update* theUpdater) override;
+
 protected:
+  /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+  virtual void process() override;
+
   /// \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);
+  virtual void getAttributes(EntityWrapperPtr&              theValue,
+                             std::vector<EntityWrapperPtr>& theAttributes) override;
+
+protected:
+  bool myInSolver; ///< shows the constraint is added to the solver
 };
 
 #endif
index 194d47aa012ddbb9ab0b4ef7ef732f3e12b54f55..f99ab425fdd8c0208a9f877069c420236d4e5c13 100644 (file)
@@ -10,47 +10,47 @@ SketchSolver_ConstraintCollinear::SketchSolver_ConstraintCollinear(ConstraintPtr
 {
 }
 
-void SketchSolver_ConstraintCollinear::notifyCoincidenceChanged(
-    EntityWrapperPtr theCoincAttr1,
-    EntityWrapperPtr theCoincAttr2)
-{
-  bool used = true;
-
-  // obtain IDs of all boundary points of lines
-  EntityID aPointIDs[4];
-  for (int i = 0; i < 2; ++i) {
-    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-        myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i)));
-    if (!aRefAttr->object())
-      continue;
-    FeaturePtr aLine = ModelAPI_Feature::feature(aRefAttr->object());
-    AttributePtr aLinePt = aLine->attribute(SketchPlugin_Line::START_ID());
-    aPointIDs[2*i] = myStorage->entity(aLinePt)->id();
-    aLinePt = aLine->attribute(SketchPlugin_Line::END_ID());
-    aPointIDs[2*i + 1] = myStorage->entity(aLinePt)->id();
-  }
-
-  EntityWrapperPtr anAttrs[2] = {theCoincAttr1, theCoincAttr2};
-  for (int i = 0; i < 2 && used; ++i) {
-    if (anAttrs[i]->baseAttribute())
-      used = used && isUsed(anAttrs[i]->baseAttribute());
-    else
-      used = used && isUsed(anAttrs[i]->baseFeature());
-
-    if (!used) {
-      if (anAttrs[i]->type() == ENTITY_POINT) {
-        EntityID anID = anAttrs[i]->id();
-        for (int j = 0; j < 4; ++j)
-          if (anID == aPointIDs[j]) {
-            used = true;
-            break;
-          }
-      }
-    }
-  }
-
-  if (used) {
-    remove();
-    process();
-  }
-}
+////void SketchSolver_ConstraintCollinear::notifyCoincidenceChanged(
+////    EntityWrapperPtr theCoincAttr1,
+////    EntityWrapperPtr theCoincAttr2)
+////{
+////  bool used = true;
+////
+////  // obtain IDs of all boundary points of lines
+////  EntityID aPointIDs[4];
+////  for (int i = 0; i < 2; ++i) {
+////    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+////        myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i)));
+////    if (!aRefAttr->object())
+////      continue;
+////    FeaturePtr aLine = ModelAPI_Feature::feature(aRefAttr->object());
+////    AttributePtr aLinePt = aLine->attribute(SketchPlugin_Line::START_ID());
+////    aPointIDs[2*i] = myStorage->entity(aLinePt)->id();
+////    aLinePt = aLine->attribute(SketchPlugin_Line::END_ID());
+////    aPointIDs[2*i + 1] = myStorage->entity(aLinePt)->id();
+////  }
+////
+////  EntityWrapperPtr anAttrs[2] = {theCoincAttr1, theCoincAttr2};
+////  for (int i = 0; i < 2 && used; ++i) {
+////    if (anAttrs[i]->baseAttribute())
+////      used = used && isUsed(anAttrs[i]->baseAttribute());
+////    else
+////      used = used && isUsed(anAttrs[i]->baseFeature());
+////
+////    if (!used) {
+////      if (anAttrs[i]->type() == ENTITY_POINT) {
+////        EntityID anID = anAttrs[i]->id();
+////        for (int j = 0; j < 4; ++j)
+////          if (anID == aPointIDs[j]) {
+////            used = true;
+////            break;
+////          }
+////      }
+////    }
+////  }
+////
+////  if (used) {
+////    remove();
+////    process();
+////  }
+////}
index 5d6187eb41b363b13328a1651f03a3b4c0aaca64..7ab635581472b64ca4dc746795bd168ff00f8696 100644 (file)
@@ -17,13 +17,13 @@ class SketchSolver_ConstraintCollinear : public SketchSolver_Constraint
 {
 public:
   /// Constructor based on SketchPlugin constraint
-  SKETCHSOLVER_EXPORT SketchSolver_ConstraintCollinear(ConstraintPtr theConstraint);
+  SketchSolver_ConstraintCollinear(ConstraintPtr theConstraint);
 
   virtual ~SketchSolver_ConstraintCollinear() {}
 
-  /// \brief Notify constraint, that coincidence appears or removed
-  virtual void notifyCoincidenceChanged(EntityWrapperPtr theCoincAttr1,
-                                        EntityWrapperPtr theCoincAttr2);
+////  /// \brief Notify constraint, that coincidence appears or removed
+////  virtual void notifyCoincidenceChanged(EntityWrapperPtr theCoincAttr1,
+////                                        EntityWrapperPtr theCoincAttr2);
 };
 
 #endif
index afe792932bd99f06b85e9d2a49e76bb7b774b388..9e01c65a8377ae06fb3db06751e8f1da238aa7cd 100644 (file)
@@ -13,7 +13,7 @@
 
 
 void SketchSolver_ConstraintDistance::getAttributes(
-    double& theValue,
+    EntityWrapperPtr& theValue,
     std::vector<EntityWrapperPtr>& theAttributes)
 {
   SketchSolver_Constraint::getAttributes(theValue, theAttributes);
@@ -34,37 +34,58 @@ void SketchSolver_ConstraintDistance::getAttributes(
 
 void SketchSolver_ConstraintDistance::adjustConstraint()
 {
-  ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
+  ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint);
 
   // Adjust point-point distance if the points are equal
   if (getType() == CONSTRAINT_PT_PT_DISTANCE) {
-    const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
-    if (aSubs.front()->isEqual(aSubs.back())) {
-      // Change X coordinate of second point to eliminate coincidence
-      ParameterWrapperPtr aX = aSubs.back()->parameters().front();
-      aX->setValue(aX->value() + 1.0);
-      myStorage->update(aX);
-    }
+////    AttributePtr aPt1 = myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A());
+////    AttributePtr aPt2 = myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B());
+////
+////    BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
+////    std::shared_ptr<GeomAPI_Pnt2d> aPoint1 = aBuilder->point(myStorage->entity(aPt1));
+////    EntityWrapperPtr anEntity2 = myStorage->entity(aPt2);
+////    std::shared_ptr<GeomAPI_Pnt2d> aPoint2 = aBuilder->point(anEntity2);
+////
+////////    if (aPoint1->distance(aPoint2) < tolerance) {
+////////      // Change X coordinate of second point to eliminate coincidence
+////////      ParameterWrapperPtr aX = aSubs.back()->parameters().front();
+////////      aX->setValue(aX->value() + 1.0);
+////////      myStorage->update(aX);
+////////    }
     return;
   }
 
   // Adjust point-line distance
   if (fabs(myPrevValue) == fabs(aConstraint->value())) {
     // sign of distance is not changed
-    aConstraint->setValue(myPrevValue);
-    myStorage->addConstraint(myBaseConstraint, aConstraint);
+////    aConstraint->setValue(myPrevValue);
+////    myStorage->addConstraint(myBaseConstraint, aConstraint);
     return;
   }
 
-  // Adjust the sign of constraint value
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-  aBuilder->adjustConstraint(aConstraint);
-  myStorage->addConstraint(myBaseConstraint, aConstraint);
+////  // Adjust the sign of constraint value
+////  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
+////
+////  std::shared_ptr<GeomAPI_Lin2d> aLine;
+////  std::shared_ptr<GeomAPI_Pnt2d> aPoint;
+////  for (int i = 0; i < 2; ++i) {
+////    AttributePtr anAttr = myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i));
+////    EntityWrapperPtr anEntity = myStorage->entity(anAttr);
+////    if (anEntity->type() == ENTITY_POINT)
+////      aPoint = aBuilder->point(anEntity);
+////    else if (anEntity->type() == ENTITY_LINE)
+////      aLine = aBuilder->line(anEntity);
+////  }
+////
+////  std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
+////  std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
+////  if (aLineVec->cross(aPtLineVec) * aConstraint->value() < 0.0)
+////    aConstraint->setValue(aConstraint->value() * (-1.0));
 }
 
 void SketchSolver_ConstraintDistance::update()
 {
-  ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
+  ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint);
   myPrevValue = aConstraint->value();
 
   SketchSolver_Constraint::update();
index 80a6fb5e359fa266affa436fe6f676d8092a5971..08df9670a529740e7b00af0a6d5d6a8defb2eb34 100644 (file)
@@ -24,17 +24,18 @@ public:
   {}
 
   /// \brief Update constraint
-  virtual void update();
+  virtual void update() override;
 
 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);
+  virtual void getAttributes(EntityWrapperPtr&              theValue,
+                             std::vector<EntityWrapperPtr>& theAttributes) override;
 
   /// \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();
+  virtual void adjustConstraint() override;
 
 private:
   double myPrevValue; ///< previous value of distance (for correct calculation of a distance sign)
index 33cb9f5dd5755d8c686b19402dcf8dd547155a88..b2cfa0a712c752a6e11d73e5d6f2e5e7da97575a 100644 (file)
@@ -3,8 +3,11 @@
 #include <SketchSolver_ConstraintEqual.h>
 #include <SketchSolver_Error.h>
 
+#include <ModelAPI_AttributeRefAttr.h>
+#include <SketchPlugin_Line.h>
+
 void SketchSolver_ConstraintEqual::getAttributes(
-    double& theValue,
+    EntityWrapperPtr& theValue,
     std::vector<EntityWrapperPtr>& theAttributes)
 {
   SketchSolver_Constraint::getAttributes(theValue, theAttributes);
@@ -51,6 +54,15 @@ void SketchSolver_ConstraintEqual::getAttributes(
     break;
   default:
     myType = CONSTRAINT_EQUAL_LINES;
+
+    AttributeRefAttrPtr aRefLine1 =
+        myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+    FeaturePtr aLine1 = ModelAPI_Feature::feature(aRefLine1->object());
+    if (aLine1) {
+      // store length of first line as a value for constraint
+      // (will be used to make equal lengths of lines)
+      theValue = myStorage->entity(aLine1->attribute(SketchPlugin_Line::LENGTH_ID()));
+    }
     break;
   }
 }
index 12e6a334e973650cc65b7c8c01699c1690d36df3..88a03aa16ffdc55a163a9b657d74b650d5192862 100644 (file)
@@ -26,7 +26,8 @@ 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);
+  virtual void getAttributes(EntityWrapperPtr&              theValue,
+                             std::vector<EntityWrapperPtr>& theAttributes) override;
 };
 
 #endif
index ca14864cb5cf8f5b00013eaaf8f25d444f9970cf..73f9808ebc454a638efbfa79b6aa0be77a5cf119 100644 (file)
@@ -2,32 +2,22 @@
 
 #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 <PlaneGCSSolver_ConstraintWrapper.h>
+#include <PlaneGCSSolver_EntityWrapper.h>
+#include <PlaneGCSSolver_PointWrapper.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()
+  : SketchSolver_Constraint(theConstraint)
 {
-  myBaseConstraint = theConstraint;
   myType = CONSTRAINT_FIXED;
-  AttributeRefAttrPtr anAttribute =
-      theConstraint->refattr(SketchPlugin_ConstraintRigid::ENTITY_A());
-  if (anAttribute->isObject())
-    myFixedFeature = ModelAPI_Feature::feature(anAttribute->object());
-  else
-    myFixedAttribute = anAttribute->attr();
+////  AttributeRefAttrPtr anAttribute =
+////      theConstraint->refattr(SketchPlugin_ConstraintRigid::ENTITY_A());
+////  if (anAttribute->isObject())
+////    myFixedFeature = ModelAPI_Feature::feature(anAttribute->object());
+////  else
+////    myFixedAttribute = anAttribute->attr();
 }
 
 SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(FeaturePtr theFeature)
@@ -35,91 +25,119 @@ SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(FeaturePtr theFeature
     myBaseFeature(theFeature)
 {
   myType = CONSTRAINT_FIXED;
-  process();
+////  process();
+}
+
+void SketchSolver_ConstraintFixed::blockEvents(bool isBlocked)
+{
+  if (myBaseFeature)
+    myBaseFeature->data()->blockSendAttributeUpdated(isBlocked);
+  if (myBaseConstraint)
+    SketchSolver_Constraint::blockEvents(isBlocked);
 }
 
 void SketchSolver_ConstraintFixed::process()
 {
   cleanErrorMsg();
-  if ((!myBaseConstraint && !myBaseFeature) || !myStorage || myGroupID == GID_UNKNOWN) {
+  if ((!myBaseConstraint && !myBaseFeature) || !myStorage) {
     // Not enough parameters are assigned
     return;
   }
 
-  ParameterWrapperPtr aValue;
+  EntityWrapperPtr aValue;
   std::vector<EntityWrapperPtr> anEntities;
   getAttributes(aValue, anEntities);
-  if (!myErrorMsg.empty() || anEntities.empty())
+  if (anEntities.empty())
+    myErrorMsg = SketchSolver_Error::ALREADY_FIXED();
+  if (!myErrorMsg.empty())
     return;
   fixFeature(anEntities.front());
 }
 
 void SketchSolver_ConstraintFixed::fixFeature(EntityWrapperPtr theFeature)
 {
-  // extract feature from the group
-  if (theFeature->baseAttribute())
-    myStorage->update(theFeature->baseAttribute(), GID_OUTOFGROUP);
-  else if (theFeature->baseFeature())
-    myStorage->update(theFeature->baseFeature(), GID_OUTOFGROUP);
+  std::shared_ptr<PlaneGCSSolver_EntityWrapper> anEntity =
+      std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theFeature);
+
+  GCS::VEC_pD aParameters; // parameters of entity to be fixed
+
+  // Collect parameters for each type of entity
+  switch (theFeature->type()) {
+  case ENTITY_POINT: {
+    std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+        std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theFeature);
+    aParameters.push_back(aPoint->point()->x);
+    aParameters.push_back(aPoint->point()->y);
+    break;
+    }
+  case ENTITY_LINE: {
+    std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
+    aParameters.push_back(aLine->p1.x);
+    aParameters.push_back(aLine->p1.y);
+    aParameters.push_back(aLine->p2.x);
+    aParameters.push_back(aLine->p2.y);
+    break;
+    }
+  case ENTITY_CIRCLE: {
+    std::shared_ptr<GCS::Circle> aCircle =
+        std::dynamic_pointer_cast<GCS::Circle>(anEntity->entity());
+    aParameters.push_back(aCircle->center.x);
+    aParameters.push_back(aCircle->center.y);
+    aParameters.push_back(aCircle->rad);
+    break;
+    }
+  case ENTITY_ARC: {
+    myFixedValues.reserve(4);
+    std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEntity->entity());
+    aParameters.push_back(anArc->center.x);
+    aParameters.push_back(anArc->center.y);
+    aParameters.push_back(anArc->rad);
+    aParameters.push_back(anArc->startAngle);
+    aParameters.push_back(anArc->endAngle);
+    break;
+    }
+  default:
+    break;
+  }
+
+  // Fix given list of parameters
+  std::list<GCSConstraintPtr> aConstraints;
+  myFixedValues.reserve(aParameters.size());
+  GCS::VEC_pD::const_iterator anIt = aParameters.begin();
+  for (int i = 0; anIt != aParameters.end(); ++anIt, ++i) {
+    myFixedValues.push_back(**anIt);
+    aConstraints.push_back(
+        GCSConstraintPtr(new GCS::ConstraintEqual(*anIt, &myFixedValues[i])));
+  }
+
+  myConstraint = ConstraintWrapperPtr(
+      new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
 
   if (myBaseConstraint)
-    myStorage->addConstraint(myBaseConstraint, std::list<ConstraintWrapperPtr>());
+    myStorage->addConstraint(myBaseConstraint, myConstraint);
+  else
+    myStorage->addTemporaryConstraint(myConstraint);
 }
 
 void SketchSolver_ConstraintFixed::getAttributes(
-    ParameterWrapperPtr& theValue,
+    EntityWrapperPtr& 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);
+    myStorage->update(myBaseFeature);
+    EntityWrapperPtr aSolverEntity = myStorage->entity(myBaseFeature);
+    if (aSolverEntity)
+      theAttributes.push_back(aSolverEntity);
   } 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);
+    std::vector<EntityWrapperPtr> anAttributes;
+    SketchSolver_Constraint::getAttributes(theValue, anAttributes);
+    std::vector<EntityWrapperPtr>::const_iterator anIt = anAttributes.begin();
+    for (; anIt != anAttributes.end(); ++anIt)
+      if (*anIt)
+        theAttributes.push_back(*anIt);
   } 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) {
-    if (myFixedFeature)
-      aFeature = myFixedFeature;
-    else if (myFixedAttribute)
-      myStorage->update(AttributePtr(myFixedAttribute), myGroupID);
-  }
-  if (aFeature)
-    myStorage->update(aFeature, myGroupID);
-  myStorage->setNeedToResolve(true);
-
-  // 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;
 }
index fd56f87d910966f4e39cca63f59bfd89584bc189..bccf4402aee14ed1082840f9e08416bb4a45998c 100644 (file)
  *
  *  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
+  /// Creates temporary constraint based on feature (useful while the feature is being moved)
   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();
+  /// \brief Block or unblock events from this constraint
+  virtual void blockEvents(bool isBlocked) override;
 
 protected:
   /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
-  virtual void process();
+  virtual void process() override;
 
   /// \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);
+  virtual void getAttributes(EntityWrapperPtr&              theValue,
+                             std::vector<EntityWrapperPtr>& theAttributes) override;
 
   /// \brief Fixed feature basing on its type
   /// \param theFeature [in]  feature, converted to solver specific format
   virtual void fixFeature(EntityWrapperPtr theFeature);
 
-protected:
+private:
   FeaturePtr myBaseFeature; ///< fixed feature (when it is set, myBaseConstraint should be NULL)
 
-private:
-  AttributePtr myFixedAttribute; ///< possible attribute of a fixed constraint (for correct remove)
-  FeaturePtr   myFixedFeature;   ///< possible attribute of a fixed constraint (for correct remove)
+  ConstraintWrapperPtr myConstraint;
+  std::vector<double> myFixedValues;
 };
 
 #endif
diff --git a/src/SketchSolver/SketchSolver_ConstraintFixedArcRadius.cpp b/src/SketchSolver/SketchSolver_ConstraintFixedArcRadius.cpp
deleted file mode 100644 (file)
index af32f19..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-#include <SketchSolver_ConstraintFixedArcRadius.h>
-#include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
-
-#include <SketchPlugin_Arc.h>
-#include <GeomAPI_Pnt2d.h>
-
-SketchSolver_ConstraintFixedArcRadius::SketchSolver_ConstraintFixedArcRadius(FeaturePtr theFeature)
-  : SketchSolver_ConstraintFixed(theFeature)
-{
-  myType = CONSTRAINT_RADIUS;
-  process();
-}
-
-void SketchSolver_ConstraintFixedArcRadius::process()
-{
-  cleanErrorMsg();
-  if (!myBaseFeature || !myStorage || myGroupID == GID_UNKNOWN) {
-    // Not enough parameters are assigned
-    return;
-  }
-
-  if (myBaseFeature->getKind() != SketchPlugin_Arc::ID()) {
-    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-    return;
-  }
-
-  ParameterWrapperPtr aValue;
-  std::vector<EntityWrapperPtr> anEntities;
-  getAttributes(aValue, anEntities);
-  if (!myErrorMsg.empty() || anEntities.empty())
-    return;
-  fixFeature(anEntities.front());
-}
-
-void SketchSolver_ConstraintFixedArcRadius::fixFeature(EntityWrapperPtr theFeature)
-{
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
-  // Calculate radius of the arc
-  std::list<EntityWrapperPtr> aSubs = theFeature->subEntities();
-  std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
-  std::shared_ptr<GeomAPI_Pnt2d> aCenter = aBuilder->point(*aSubIt++);
-  std::shared_ptr<GeomAPI_Pnt2d> aStart  = aBuilder->point(*aSubIt++);
-  double aRadius = aCenter->distance(aStart);
-
-  // Create constraint
-  std::list<ConstraintWrapperPtr> aConstrList = aBuilder->createConstraint(ConstraintPtr(),
-      myGroupID, mySketchID, myType, aRadius, EntityWrapperPtr(), EntityWrapperPtr(), theFeature);
-  myRadiusConstraint = aConstrList.front();
-  myStorage->addConstraint(ConstraintPtr(), myRadiusConstraint);
-}
-
-bool SketchSolver_ConstraintFixedArcRadius::remove()
-{
-  bool isFullyRemoved = true;
-  if (myBaseFeature)
-    isFullyRemoved = myStorage->removeEntity(myBaseFeature) && isFullyRemoved;
-  if (myRadiusConstraint)
-    isFullyRemoved = myStorage->removeConstraint(ConstraintPtr()) &&
-                     myStorage->remove(myRadiusConstraint) && isFullyRemoved;
-  return isFullyRemoved;
-}
diff --git a/src/SketchSolver/SketchSolver_ConstraintFixedArcRadius.h b/src/SketchSolver/SketchSolver_ConstraintFixedArcRadius.h
deleted file mode 100644 (file)
index 6bb3e67..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SketchSolver_ConstraintFixedArcRadiusArcRadius.h
-// Created: 22 Jan 2016
-// Author:  Artem ZHIDKOV
-
-#ifndef SketchSolver_ConstraintFixedArcRadius_H_
-#define SketchSolver_ConstraintFixedArcRadius_H_
-
-#include "SketchSolver.h"
-#include <SketchSolver_ConstraintFixed.h>
-
-/** \class   SketchSolver_ConstraintFixedArcRadius
- *  \ingroup Plugins
- *  \brief   Fix radius of the arc. Temporary constraint. Based on an arc, sharp!
- */
-class SketchSolver_ConstraintFixedArcRadius : public SketchSolver_ConstraintFixed
-{
-public:
-  /// Creates temporary constraint based on feature
-  SketchSolver_ConstraintFixedArcRadius(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 Fix radius of arc
-  /// \param theFeature [in]  feature, converted to solver specific format
-  virtual void fixFeature(EntityWrapperPtr theFeature);
-
-private:
-  ConstraintWrapperPtr myRadiusConstraint;
-};
-
-#endif
index be89bb53d3f2c31f7e36f8853827c91465fbff3f..1a4be5072b2ef7059654f2a949fa04fbc31c847b 100644 (file)
@@ -3,9 +3,11 @@
 #include <SketchSolver_ConstraintLength.h>
 #include <SketchSolver_Error.h>
 
+#include <SketchPlugin_Line.h>
+
 
 void SketchSolver_ConstraintLength::getAttributes(
-    double& theValue,
+    EntityWrapperPtr& theValue,
     std::vector<EntityWrapperPtr>& theAttributes)
 {
   SketchSolver_Constraint::getAttributes(theValue, theAttributes);
@@ -15,13 +17,11 @@ void SketchSolver_ConstraintLength::getAttributes(
     return;
   }
 
-  // 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;
+  AttributeRefAttrPtr aRefAttr = myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+  FeaturePtr aLine = ModelAPI_Feature::feature(aRefAttr->object());
+
+  theAttributes[0] = myStorage->entity(aLine->attribute(SketchPlugin_Line::START_ID()));
+  theAttributes[1] = myStorage->entity(aLine->attribute(SketchPlugin_Line::END_ID()));
 
   myType = CONSTRAINT_PT_PT_DISTANCE;
 }
index 0899d8b732419e138208af79263d0f7c56abc20c..1626f1c48360aca3e301ca463683c1300c80b4c5 100644 (file)
@@ -26,7 +26,8 @@ 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);
+  virtual void getAttributes(EntityWrapperPtr&              theValue,
+                             std::vector<EntityWrapperPtr>& theAttributes) override;
 };
 
 #endif
index 69de3881e0c751381c97375320a71c41c38ac9f2..6680004c8f633395b340b231f0ca80381b6c4976 100644 (file)
@@ -1,54 +1,64 @@
 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
 
 #include <SketchSolver_ConstraintMiddle.h>
+#include <PlaneGCSSolver_ConstraintWrapper.h>
+#include <PlaneGCSSolver_UpdateCoincidence.h>
 
-#include <SketchSolver_Builder.h>
-#include <SketchSolver_Manager.h>
-
-#include <GeomAPI_XY.h>
-
-SketchSolver_ConstraintMiddle::SketchSolver_ConstraintMiddle(ConstraintPtr theConstraint)
-  : SketchSolver_Constraint(theConstraint)
+void SketchSolver_ConstraintMiddle::getAttributes(
+    EntityWrapperPtr& theValue,
+    std::vector<EntityWrapperPtr>& theAttributes)
 {
+  SketchSolver_Constraint::getAttributes(theValue, theAttributes);
 }
 
-void SketchSolver_ConstraintMiddle::notifyCoincidenceChanged(
-    EntityWrapperPtr theCoincAttr1,
-    EntityWrapperPtr theCoincAttr2)
+void SketchSolver_ConstraintMiddle::notify(const FeaturePtr&      theFeature,
+                                           PlaneGCSSolver_Update* theUpdater)
 {
-  // Check the coincidence between point and line has been changed
-  AttributePtr aPoint;
-  FeaturePtr aLine;
-  EntityWrapperPtr anEntities[2] = {theCoincAttr1, theCoincAttr2};
-  for (int i = 0; i < 2; ++i) {
-    if (anEntities[i]->type() == ENTITY_POINT)
-      aPoint = anEntities[i]->baseAttribute();
-    else if (anEntities[i]->type() == ENTITY_LINE)
-      aLine = anEntities[i]->baseFeature();
-  }
-  if (!aPoint || !aLine)
-    return;
-
-  // Check the attributes of middle-point constraint are the same point and line
-  bool isSameAttr = true;
-  for (int i = 0; i < 2 && isSameAttr; ++i) {
-    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-        myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i)));
-    if (!aRefAttr)
-    {
-      // It seems the Middle point constraint has been deleted, so keep it unchanged.
-      // It will be removed later.
-      return;
+  PlaneGCSSolver_UpdateCoincidence* anUpdater =
+      static_cast<PlaneGCSSolver_UpdateCoincidence*>(theUpdater);
+  bool isAccepted = anUpdater->checkCoincidence(myAttributes.front(), myAttributes.back());
+  if (isAccepted) {
+    if (!myInSolver) {
+      myInSolver = true;
+
+      if (myMiddle) {
+        // remove previously adde constraint
+        myStorage->removeConstraint(myBaseConstraint);
+        // merge divided constraints into single object
+        std::list<GCSConstraintPtr> aGCSConstraints;
+        std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
+            std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(myMiddle);
+        aGCSConstraints.push_back(aConstraint->constraints().front());
+        aConstraint =
+            std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(mySolverConstraint);
+        aGCSConstraints.push_back(aConstraint->constraints().front());
+
+        myMiddle = ConstraintWrapperPtr();
+        mySolverConstraint = ConstraintWrapperPtr(
+            new PlaneGCSSolver_ConstraintWrapper(aGCSConstraints, CONSTRAINT_MIDDLE_POINT));
+      }
+
+      myStorage->addConstraint(myBaseConstraint, mySolverConstraint);
     }
-    if (aRefAttr->isObject()) {
-      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
-      isSameAttr = (aFeature == aLine);
-    } else
-      isSameAttr = (aRefAttr->attr() == aPoint);
-  }
+  } else {
+    if (myInSolver) {
+      myInSolver = false;
+      myStorage->removeConstraint(myBaseConstraint);
+    }
+
+    if (!myMiddle) {
+      // divide solver constraints to the middle point and point-line coincidence
+      std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
+          std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(mySolverConstraint);
+      std::list<GCSConstraintPtr> aGCSConstraints = aConstraint->constraints();
 
-  if (isSameAttr) {
-    remove();
-    process();
+      myMiddle = ConstraintWrapperPtr(
+          new PlaneGCSSolver_ConstraintWrapper(aGCSConstraints.front(), CONSTRAINT_MIDDLE_POINT));
+      mySolverConstraint = ConstraintWrapperPtr(
+          new PlaneGCSSolver_ConstraintWrapper(aGCSConstraints.back(), CONSTRAINT_MIDDLE_POINT));
+
+      // send middle constraint only
+      myStorage->addConstraint(myBaseConstraint, myMiddle);
+    }
   }
 }
index bc0053b207d9b476aedab7b36f7bbe368f0eb984..4d08057043291b181c84c5eff49c83dc212e475a 100644 (file)
@@ -7,23 +7,33 @@
 #ifndef SketchSolver_ConstraintMiddle_H_
 #define SketchSolver_ConstraintMiddle_H_
 
-#include <SketchSolver_Constraint.h>
+#include <SketchSolver_ConstraintCoincidence.h>
 
 /** \class   SketchSolver_ConstraintMiddle
  *  \ingroup Plugins
  *  \brief   Converts middle-point constraint to the constraint applicable for solver
  */
-class SketchSolver_ConstraintMiddle : public SketchSolver_Constraint
+class SketchSolver_ConstraintMiddle : public SketchSolver_ConstraintCoincidence
 {
 public:
   /// Constructor based on SketchPlugin constraint
-  SKETCHSOLVER_EXPORT SketchSolver_ConstraintMiddle(ConstraintPtr theConstraint);
+  SketchSolver_ConstraintMiddle(ConstraintPtr theConstraint)
+    : SketchSolver_ConstraintCoincidence(theConstraint)
+  {}
 
-  virtual ~SketchSolver_ConstraintMiddle() {}
+  /// \brief Notify this object about the feature is changed somewhere
+  virtual void notify(const FeaturePtr&      theFeature,
+                      PlaneGCSSolver_Update* theUpdater) override;
 
-  /// \brief Notify constraint, that coincidence appears or removed
-  virtual void notifyCoincidenceChanged(EntityWrapperPtr theCoincAttr1,
-                                        EntityWrapperPtr theCoincAttr2);
+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(EntityWrapperPtr&              theValue,
+                             std::vector<EntityWrapperPtr>& theAttributes) override;
+
+private:
+  ConstraintWrapperPtr myMiddle;
 };
 
 #endif
index c91121d767ff46ea17f319e621e3165a1ae06e4b..6381b2bd3dc8f85750cab74f798213a6d37bfb40 100644 (file)
@@ -4,98 +4,89 @@
 #include <SketchSolver_Error.h>
 #include <SketchSolver_Manager.h>
 
+#include <PlaneGCSSolver_UpdateFeature.h>
+
+#include <GeomAPI_XY.h>
+#include <GeomDataAPI_Point2D.h>
 #include <ModelAPI_AttributeRefList.h>
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+
+
+static void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
+                         const AttributePoint2DPtr& theOriginal,
+                         const AttributePoint2DPtr& theMirrored);
+
+static void mirrorEntities(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
+                           const FeaturePtr& theOriginal,
+                           const FeaturePtr& theMirrored);
+
+
 
 void SketchSolver_ConstraintMirror::getAttributes(
-    EntityWrapperPtr& theMirrorLine,
-    std::vector<EntityWrapperPtr>& theBaseEntities,
-    std::vector<EntityWrapperPtr>& theMirrorEntities)
+    EntityWrapperPtr&,
+    std::vector<EntityWrapperPtr>&)
 {
-  AttributePtr aMirLineAttr = myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A());
   AttributeRefAttrPtr aMirLineRefAttr =
-      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aMirLineAttr);
+      myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
   if (!aMirLineRefAttr || !aMirLineRefAttr->isInitialized() || !aMirLineRefAttr->isObject()) {
     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
     return;
   }
 
+  FeaturePtr aMirrorLine = ModelAPI_Feature::feature(aMirLineRefAttr->object());
+  myFeatures.insert(aMirrorLine);
+
   myType = TYPE(myBaseConstraint);
-  myStorage->update(aMirLineAttr/*, myGroupID*/);
-  theMirrorLine = myStorage->entity(aMirLineAttr);
-
-  // Create SolveSpace entity for all features
-  AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
-  AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C()));
+  myStorage->update(aMirrorLine);
+
+
+  AttributeRefListPtr aBaseRefList =
+      myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
+  AttributeRefListPtr aMirroredRefList =
+      myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
   myNumberOfObjects = aMirroredRefList->size();
   if (!aBaseRefList || !aMirroredRefList) {
     myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE();
     return;
   }
 
-  std::list<ObjectPtr> aBaseList = aBaseRefList->list();
-  std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
-
-  FeaturePtr aFeature;
-  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;
-    for ( ; anIter != aEndIter; anIter++) {
-      aFeature = ModelAPI_Feature::feature(*anIter);
-      if (!aFeature)
-        continue;
-
-      myStorage->update(aFeature, GID_UNKNOWN, true);
-      aList->push_back(myStorage->entity(aFeature));
+  // store only original entities because mirrored ones
+  // will be updated separately in adjustConstraint
+  std::list<ObjectPtr> aList = aBaseRefList->list();
+  std::list<ObjectPtr>::iterator anIt = aList.begin();
+  for (; anIt != aList.end(); ++anIt) {
+    FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+    if (aFeature) {
+      myStorage->update(aFeature);
+      myFeatures.insert(aFeature);
     }
   }
-
-  if (theBaseEntities.size() > theMirrorEntities.size() || aMirroredList.empty())
-    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+  // add mirrored features to the list
+  aList = aMirroredRefList->list();
+  for (anIt = aList.begin(); anIt != aList.end(); ++anIt) {
+    FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+    if (aFeature)
+      myFeatures.insert(aFeature);
+  }
 }
 
 void SketchSolver_ConstraintMirror::process()
 {
   cleanErrorMsg();
-  if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
+  if (!myBaseConstraint || !myStorage) {
     // Not enough parameters are assigned
     return;
   }
 
   EntityWrapperPtr aMirrorLine;
   std::vector<EntityWrapperPtr> aBaseList;
-  std::vector<EntityWrapperPtr> aMirrorList;
-  getAttributes(aMirrorLine, aBaseList, aMirrorList);
+  getAttributes(aMirrorLine, aBaseList);
   if (!myErrorMsg.empty())
     return;
 
-  if (aBaseList.size() != aMirrorList.size()) {
-    myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE();
-    return;
-  }
-
-  std::list<ConstraintWrapperPtr> aNewConstraints;
-  SketchSolver_ConstraintType aConstrType = getType();
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-  std::list<ConstraintWrapperPtr> aMirConstrList;
-
-  // update mirrored features to be in the current group
-  std::vector<EntityWrapperPtr>::iterator aMIt = aMirrorList.begin();
-  for (; aMIt != aMirrorList.end(); ++aMIt)
-    myStorage->update((*aMIt)->baseFeature(), myGroupID);
-
-  std::vector<EntityWrapperPtr>::iterator aBIt = aBaseList.begin();
-  for (aMIt = aMirrorList.begin(); aBIt != aBaseList.end(); ++aBIt, ++aMIt) {
-    aNewConstraints = aBuilder->createConstraint(
-        myBaseConstraint, myGroupID, mySketchID, aConstrType,
-        0.0, *aBIt, *aMIt, aMirrorLine);
-    aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
-  }
-  myStorage->addConstraint(myBaseConstraint, aMirConstrList);
-
   adjustConstraint();
+  myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP());
 }
 
 
@@ -110,9 +101,86 @@ 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 aMirrLineRefAttr =
+      myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+  std::shared_ptr<GeomAPI_Lin2d> aMirrorLine =
+      aBuilder->line(ModelAPI_Feature::feature(aMirrLineRefAttr->object()));
+
+  AttributeRefListPtr aBaseRefList =
+      myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
+  AttributeRefListPtr aMirroredRefList =
+      myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
+
+  std::list<ObjectPtr> aBaseList = aBaseRefList->list();
+  std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
+  std::list<ObjectPtr>::iterator aBIt, aMIt;
+  for (aBIt = aBaseList.begin(), aMIt = aMirroredList.begin();
+       aBIt != aBaseList.end() && aMIt != aMirroredList.end();
+       ++aBIt, ++aMIt) {
+    FeaturePtr aBase = ModelAPI_Feature::feature(*aBIt);
+    FeaturePtr aMirrored = ModelAPI_Feature::feature(*aMIt);
+    mirrorEntities(aMirrorLine, aBase, aMirrored);
+  }
+}
+
+void SketchSolver_ConstraintMirror::notify(const FeaturePtr& theFeature,
+                                           PlaneGCSSolver_Update*)
+{
+  if (myFeatures.find(theFeature) == myFeatures.end())
+    return; // the feature is not used by constraint => nothing to update
+  adjustConstraint();
+}
+
+void SketchSolver_ConstraintMirror::blockEvents(bool isBlocked)
+{
+  std::set<FeaturePtr>::iterator anIt = myFeatures.begin();
+  for (; anIt != myFeatures.end(); ++anIt)
+    (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
+
+  SketchSolver_Constraint::blockEvents(isBlocked);
+}
+
+
+
+
+// =================   Auxiliary functions   ==================================
+void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
+                  const AttributePoint2DPtr& theOriginal,
+                  const AttributePoint2DPtr& theMirrored)
+{
+  std::shared_ptr<GeomAPI_Pnt2d> anOriginal = theOriginal->pnt();
+  std::shared_ptr<GeomAPI_Pnt2d> aPtOnLine = theMirrorLine->project(anOriginal);
+  std::shared_ptr<GeomAPI_XY> aPerp = aPtOnLine->xy()->decreased(anOriginal->xy());
+  theMirrored->setValue(anOriginal->x() + aPerp->x() * 2.0, anOriginal->y() + aPerp->y() * 2.0);
+}
+
+void mirrorEntities(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
+                    const FeaturePtr& theOriginal,
+                    const FeaturePtr& theMirrored)
+{
+  std::list<AttributePtr> aPoints0 =
+      theOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
+  std::list<AttributePtr> aPoints1 =
+      theMirrored->data()->attributes(GeomDataAPI_Point2D::typeId());
+
+  // process specific features
+  if (theOriginal->getKind() == SketchPlugin_Arc::ID()) {
+    // orientation of arc
+    theMirrored->boolean(SketchPlugin_Arc::INVERSED_ID())->setValue(
+        !theOriginal->boolean(SketchPlugin_Arc::INVERSED_ID())->value());
+  } else if (theOriginal->getKind() == SketchPlugin_Circle::ID()) {
+    // radius of the circle
+    theMirrored->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
+        theOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
+  }
+
+  // mirror all initialized points of features
+  std::list<AttributePtr>::iterator anIt0, anIt1;
+  for (anIt0 = aPoints0.begin(), anIt1 = aPoints1.begin();
+       anIt0 != aPoints0.end() && anIt1 != aPoints1.end(); ++anIt0, ++anIt1) {
+    AttributePoint2DPtr aPt0 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt0);
+    AttributePoint2DPtr aPt1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt1);
+    if (aPt0->isInitialized() && aPt1->isInitialized())
+      mirrorPoints(theMirrorLine, aPt0, aPt1);
+  }
 }
index 9986fc2a07436a57bdd637f808fbb13eea1c271d..ead02ee24a6e93e40e5941e2360cadc2054e1932 100644 (file)
@@ -24,32 +24,28 @@ public:
   {}
 
   /// \brief Update constraint
-  virtual void update();
+  virtual void update() override;
+
+  /// \brief Notify this object about the feature is changed somewhere
+  virtual void notify(const FeaturePtr& theFeature, PlaneGCSSolver_Update*) override;
+
+  /// \brief Block or unblock events from this constraint
+  virtual void blockEvents(bool isBlocked) override;
 
 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(double& theValue, std::vector<EntityWrapperPtr>& theAttributes)
-  { /* do nothing here */ }
+  virtual void process() override;
 
   /// \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);
+  virtual void getAttributes(EntityWrapperPtr&, std::vector<EntityWrapperPtr>&) override;
 
   /// \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();
+  virtual void adjustConstraint() override;
 
 private:
   size_t myNumberOfObjects;  ///< number of previously mirrored objects
+  std::set<FeaturePtr> myFeatures; ///< mirror line, original and mirrored features
 };
 
 #endif
diff --git a/src/SketchSolver/SketchSolver_ConstraintMovement.cpp b/src/SketchSolver/SketchSolver_ConstraintMovement.cpp
deleted file mode 100644 (file)
index 916b8d5..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-#include <SketchSolver_ConstraintMovement.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 <GeomDataAPI_Point2D.h>
-
-
-void SketchSolver_ConstraintMovement::process()
-{
-  cleanErrorMsg();
-  if (!myBaseFeature || !myStorage || myGroupID == GID_UNKNOWN) {
-    // Not enough parameters are initialized
-    return;
-  }
-
-  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();
-    return;
-  }
-
-  std::vector<EntityWrapperPtr>::iterator anEntIt = myMovedEntities.begin();
-  for (; anEntIt != myMovedEntities.end(); ++anEntIt)
-    fixFeature(*anEntIt);
-}
-
-
-static std::list<EntityWrapperPtr> movedEntities(
-    EntityWrapperPtr theOld, StoragePtr theOldStorage,
-    EntityWrapperPtr theNew, StoragePtr theNewStorage)
-{
-  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);
-    // check only the points to be moved (because arcs in PlaneGCS have scalar subs too)
-    if ((*anOldIt)->type() == ENTITY_POINT &&
-       (aMovedSubs.size() != 1 || aMovedSubs.front() != *anOldIt))
-      isFullyMoved = false;
-    aMoved.insert(aMoved.end(), aMovedSubs.begin(), aMovedSubs.end());
-  }
-  if (isFullyMoved) {
-    aMoved.clear();
-    aMoved.push_back(theOld);
-  }
-  return aMoved;
-}
-
-
-void SketchSolver_ConstraintMovement::getAttributes(
-    ParameterWrapperPtr& theValue,
-    std::vector<EntityWrapperPtr>& theAttributes)
-{
-  // 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);
-
-  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());
-    }
-  }
-  theAttributes.clear();
-  theAttributes.insert(theAttributes.begin(), aMoved.begin(), aMoved.end());
-}
-
-bool SketchSolver_ConstraintMovement::remove()
-{
-  cleanErrorMsg();
-  // Move fixed entities back to the current group
-  std::vector<EntityWrapperPtr>::iterator aMoveIt = myMovedEntities.begin();
-  for (; aMoveIt != myMovedEntities.end(); ++aMoveIt) {
-    if ((*aMoveIt)->baseAttribute())
-      myStorage->update((*aMoveIt)->baseAttribute(), myGroupID);
-    else if ((*aMoveIt)->baseFeature())
-      myStorage->update((*aMoveIt)->baseFeature(), myGroupID);
-  }
-
-  // Remove base feature
-  if (myBaseFeature)
-    myStorage->removeEntity(myBaseFeature);
-  return true;
-}
diff --git a/src/SketchSolver/SketchSolver_ConstraintMovement.h b/src/SketchSolver/SketchSolver_ConstraintMovement.h
deleted file mode 100644 (file)
index 63211fa..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    SketchSolver_ConstraintMovement.h
-// Created: 15 Jun 2015
-// Author:  Artem ZHIDKOV
-
-#ifndef SketchSolver_ConstraintMovement_H_
-#define SketchSolver_ConstraintMovement_H_
-
-#include "SketchSolver.h"
-#include <SketchSolver_ConstraintFixed.h>
-
-/** \class   SketchSolver_ConstraintMovement
- *  \ingroup Plugins
- *  \brief   Stores data to the Fixed constraint for the moved feature only
- */
-class SketchSolver_ConstraintMovement : public SketchSolver_ConstraintFixed
-{
-private:
-  /// Creates constraint to manage the given constraint from plugin
-  SketchSolver_ConstraintMovement(ConstraintPtr theConstraint)
-    : SketchSolver_ConstraintFixed(theConstraint)
-  {}
-
-public:
-  /// Creates temporary constraint based on feature
-  SketchSolver_ConstraintMovement(FeaturePtr theFeature)
-    : SketchSolver_ConstraintFixed(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 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);
-
-private:
-  std::vector<EntityWrapperPtr> myMovedEntities; ///< list of entities that are moved
-};
-
-#endif
index a86ab8b5fbd51731f26d30fdade40e31a67a402d..4ca7e088b2911bf1067f87703b6c126d84485e8d 100644 (file)
 void SketchSolver_ConstraintMulti::getEntities(std::list<EntityWrapperPtr>& theEntities)
 {
   myAdjusted = false;
-  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()));
+  AttributeRefListPtr anInitialRefList =
+      myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_A());
   myNumberOfObjects = anInitialRefList->size();
-  myNumberOfCopies = aData->integer(nameNbObjects())->value() - 1;
+  myNumberOfCopies = myBaseConstraint->integer(nameNbObjects())->value() - 1;
   if (myNumberOfCopies <= 0)
     return;
 
-  AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-      aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
+  AttributeRefListPtr aRefList =
+      myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
   if (!aRefList || aRefList->size() == 0) {
     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
     return;
@@ -48,7 +47,7 @@ void SketchSolver_ConstraintMulti::getEntities(std::list<EntityWrapperPtr>& theE
 
     // the entity is not created, so it is a copy in "multi" constraint, force its creation
     if (!myStorage->update(aFeature))
-      myStorage->update(aFeature, myGroupID, true);
+      myStorage->update(aFeature, true);
     theEntities.push_back(myStorage->entity(aFeature));
     myFeatures.insert(aFeature);
     for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
@@ -62,20 +61,17 @@ void SketchSolver_ConstraintMulti::getEntities(std::list<EntityWrapperPtr>& theE
 
 bool SketchSolver_ConstraintMulti::remove()
 {
+  myStorage->unsubscribeUpdates(this);
+
   myFeatures.clear();
   return SketchSolver_Constraint::remove();
 }
 
 void SketchSolver_ConstraintMulti::update()
-{
-  update(false);
-}
-
-void SketchSolver_ConstraintMulti::update(bool isForce)
 {
   cleanErrorMsg();
-  AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  AttributeRefListPtr anInitialRefList =
+      myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_A());
   AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
   if (!anInitialRefList || !aNbObjects)
     return; // the "Multi" constraint is in queue to remove
@@ -83,8 +79,8 @@ void SketchSolver_ConstraintMulti::update(bool isForce)
     anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies;
   if (!isUpdated) {
     // additional check that the features and their copies are changed
-    AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-        myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+    AttributeRefListPtr aRefList =
+        myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
     if (aRefList && aRefList->size() != 0) {
       FeaturePtr aFeature;
       std::list<ObjectPtr> anObjectList = aRefList->list();
@@ -102,26 +98,21 @@ void SketchSolver_ConstraintMulti::update(bool isForce)
   if (isUpdated) {
     remove();
     process();
-    return;
   }
-
-  // update derivative object
-  updateLocal();
-  if (isForce)
-    myAdjusted = false;
-  adjustConstraint();
 }
 
 void SketchSolver_ConstraintMulti::adjustConstraint()
 {
-  AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+  AttributeRefListPtr aRefList =
+      myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
   if (!aRefList || aRefList->size() == 0) {
     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
     return;
   }
 
   FeaturePtr anOriginal, aFeature;
+  std::list<double>::iterator aXIt, aYIt;
+
   std::list<ObjectPtr> anObjectList = aRefList->list();
   std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
   while (anObjIt != anObjectList.end()) {
@@ -131,25 +122,19 @@ void SketchSolver_ConstraintMulti::adjustConstraint()
 
     // Fill lists of coordinates of points composing a feature
     std::list<double> aX, aY;
-    std::list<double>::iterator aXIt, aYIt;
     double aXCoord, aYCoord;
-    EntityWrapperPtr anEntity = myStorage->entity(anOriginal);
-    std::list<EntityWrapperPtr> aSubs = anEntity->subEntities();
-    std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
-    for (; aSIt != aSubs.end(); ++aSIt) {
-      if ((*aSIt)->type() != ENTITY_POINT)
-        continue;
-      AttributePoint2DPtr aPoint =
-          std::dynamic_pointer_cast<GeomDataAPI_Point2D>((*aSIt)->baseAttribute());
-      if (aPoint) {
-        aXCoord = aPoint->x();
-        aYCoord = aPoint->y();
-      } else {
-        std::list<ParameterWrapperPtr> aParameters = (*aSIt)->parameters();
-        aXCoord = aParameters.front()->value();
-        aYCoord = aParameters.back()->value();
-      }
-      getRelative(aXCoord, aYCoord, aXCoord, aYCoord);
+    std::list<AttributePtr> aPoints =
+        anOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
+    std::list<AttributePtr>::iterator aPtIt = aPoints.begin();
+    for (; aPtIt != aPoints.end(); ++aPtIt) {
+      AttributePoint2DPtr aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
+      if (aPoint2D->isInitialized()) {
+        aXCoord = aPoint2D->x();
+        aYCoord = aPoint2D->y();
+        getRelative(aXCoord, aYCoord, aXCoord, aYCoord);
+      } else
+        aXCoord = aYCoord = 0;
+
       aX.push_back(aXCoord);
       aY.push_back(aYCoord);
     }
@@ -159,78 +144,51 @@ void SketchSolver_ConstraintMulti::adjustConstraint()
       aFeature = ModelAPI_Feature::feature(*anObjIt);
       if (!aFeature)
         continue;
-      anEntity = myStorage->entity(aFeature);
-
-      bool aWasBlocked = false;
-      if (!anEntity || !myStorage->isEventsBlocked())
-        aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
-
-      std::list<AttributePtr> aPoints;
-      if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
-        aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
-        aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::START_ID()));
-        aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::END_ID()));
-      } else if (aFeature->getKind() == SketchPlugin_Line::ID()) {
-        aPoints.push_back(aFeature->attribute(SketchPlugin_Line::START_ID()));
-        aPoints.push_back(aFeature->attribute(SketchPlugin_Line::END_ID()));
-      } else if (aFeature->getKind() == SketchPlugin_Circle::ID()) {
-        aPoints.push_back(aFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
-        // update circle's radius
+
+      if (myIsEventsBlocked)
+        aFeature->data()->blockSendAttributeUpdated(true);
+
+      if (aFeature->getKind() == SketchPlugin_Circle::ID()) // update circle's radius
         aFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
             anOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
-      } else if (aFeature->getKind() == SketchPlugin_Point::ID() ||
-               aFeature->getKind() == SketchPlugin_IntersectionPoint::ID())
-        aPoints.push_back(aFeature->attribute(SketchPlugin_Point::COORD_ID()));
 
-      std::list<AttributePtr>::iterator aPtIt = aPoints.begin();
-      for (aXIt = aX.begin(), aYIt = aY.begin(); aPtIt != aPoints.end(); ++aXIt, ++aYIt, ++aPtIt) {
+      aPoints = aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+      for (aPtIt = aPoints.begin(), aXIt = aX.begin(), aYIt = aY.begin();
+           aPtIt != aPoints.end(); ++aXIt, ++aYIt, ++aPtIt) {
+        if (!(*aPtIt)->isInitialized())
+          continue;
         transformRelative(*aXIt, *aYIt);
         getAbsolute(*aXIt, *aYIt, aXCoord, aYCoord);
 
-        std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+        AttributePoint2DPtr aPoint2D =
             std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
         aPoint2D->setValue(aXCoord, aYCoord);
       }
-
-      // update feature in the storage if it is used by another constraints
-      if (anEntity)
-        myStorage->update(aFeature);
-      else { // update attributes, if they exist in the storage
-        for (aPtIt = aPoints.begin(); aPtIt != aPoints.end(); ++aPtIt) {
-          EntityWrapperPtr aPntEnt = myStorage->entity(*aPtIt);
-          if (aPntEnt)
-            myStorage->update(*aPtIt);
-        }
-      }
-
-      if (!anEntity || !myStorage->isEventsBlocked())
-        aFeature->data()->blockSendAttributeUpdated(aWasBlocked);
     }
   }
 
   myAdjusted = true;
 }
 
-bool SketchSolver_ConstraintMulti::isUsed(FeaturePtr theFeature) const
+void SketchSolver_ConstraintMulti::notify(const FeaturePtr& theFeature,
+                                          PlaneGCSSolver_Update*)
 {
-  return theFeature && (myFeatures.find(theFeature) != myFeatures.end() ||
-         SketchSolver_Constraint::isUsed(theFeature));
+  if (myFeatures.find(theFeature) == myFeatures.end())
+    return; // the feature is not used by constraint => nothing to update
+
+  // update derivative object
+  updateLocal();
+  myAdjusted = false;
+  adjustConstraint();
 }
 
-bool SketchSolver_ConstraintMulti::isUsed(AttributePtr theAttribute) const
+void SketchSolver_ConstraintMulti::blockEvents(bool isBlocked)
 {
-  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();
-  }
-  if (!anAttribute)
-    return false;
+  myIsEventsBlocked = isBlocked;
+
+  std::set<FeaturePtr>::iterator anIt = myFeatures.begin();
+  for (; anIt != myFeatures.end(); ++anIt)
+    (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
 
-  FeaturePtr anOwner = ModelAPI_Feature::feature(anAttribute->owner());
-  return myFeatures.find(anOwner) != myFeatures.end();
+  SketchSolver_Constraint::blockEvents(isBlocked);
 }
index 7a9edc96e6a241ac413f109e4e8f401f7b5abb35..ea311e90de68550a340c4de757e46e0e53b6f234 100644 (file)
@@ -24,41 +24,39 @@ public:
       SketchSolver_Constraint(theConstraint),
       myNumberOfObjects(0),
       myNumberOfCopies(0),
+      myIsFullValue(false),
       myAdjusted(false),
-      myIsFullValue(false)
+      myIsEventsBlocked(false)
   {}
 
   /// \brief Update constraint
-  virtual void update();
-  /// \brief Update constraint
-  void update(bool isForce);
+  virtual void update() override;
+
+  /// \brief Notify this object about the feature is changed somewhere
+  virtual void notify(const FeaturePtr& theFeature, PlaneGCSSolver_Update*) override;
 
   /// \brief Tries to remove constraint
   /// \return \c false, if current constraint contains another SketchPlugin
   /// constraints (like for multiple coincidence)
-  virtual bool remove();
+  virtual bool remove() override;
 
-  /// \brief Check the feature is a source or a copy of Multi-constraint
-  virtual bool isUsed(FeaturePtr theFeature) const;
-  /// \brief Check the attribute is used in Multi-constraint
-  virtual bool isUsed(AttributePtr theAttribute) const;
+  /// \brief Block or unblock events from this constraint
+  virtual void blockEvents(bool isBlocked) override;
 
 protected:
   /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
-  virtual void process()
+  virtual void process() override
   { /* do nothing here */ }
 
-  /// \brief Collect entities which translated or rotated (not their copies)
+  /// \brief Collect entities which are translated or rotated (not their copies)
   void getEntities(std::list<EntityWrapperPtr>& theEntities);
 
   /// \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(EntityWrapperPtr&, std::vector<EntityWrapperPtr>&) override
   { /* do nothing here */ }
 
   /// \brief This method is used in derived objects to check consistence of constraint.
-  virtual void adjustConstraint();
+  virtual void adjustConstraint() override;
 
   /// \brief Update parameters of derived classes
   virtual void updateLocal() = 0;
@@ -83,6 +81,8 @@ protected:
 
   /// list of features and their copies to find whether some of them are disappeared
   std::set<FeaturePtr> myFeatures;
+
+  bool myIsEventsBlocked;
 };
 
 #endif
index 910bdaf4f4db6894182828111ca9954b712deec1..5d857e914bf292817e71513776787d0190b656d8 100644 (file)
@@ -4,21 +4,27 @@
 #include <SketchSolver_Error.h>
 #include <SketchSolver_Manager.h>
 
+#include <PlaneGCSSolver_AttributeBuilder.h>
+#include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_ScalarWrapper.h>
+#include <PlaneGCSSolver_UpdateFeature.h>
+
 #include <SketchPlugin_MultiRotation.h>
 
 #include <ModelAPI_AttributeString.h>
 
-#include <math.h>
+#include <cmath>
 
 void SketchSolver_ConstraintMultiRotation::getAttributes(
-    EntityWrapperPtr& theCenter, double& theAngle,
+    EntityWrapperPtr& theCenter, EntityWrapperPtr& theAngle,
     bool& theFullValue, std::list<EntityWrapperPtr>& theEntities)
 {
-  DataPtr aData = myBaseConstraint->data();
-  theAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
-      aData->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value();
+  AttributePtr anAngleAttr = myBaseConstraint->attribute(SketchPlugin_MultiRotation::ANGLE_ID());
+  PlaneGCSSolver_AttributeBuilder aValueBuilder;
+  theAngle = aValueBuilder.createAttribute(anAngleAttr);
+  myStorage->addEntity(anAngleAttr, theAngle);
 
-  AttributePtr aCenterAttr = aData->attribute(SketchPlugin_MultiRotation::CENTER_ID());
+  AttributePtr aCenterAttr = myBaseConstraint->attribute(SketchPlugin_MultiRotation::CENTER_ID());
   if (!aCenterAttr || !aCenterAttr->isInitialized()) {
     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
     return;
@@ -29,7 +35,8 @@ void SketchSolver_ConstraintMultiRotation::getAttributes(
   myStorage->update(aCenterAttr);
   theCenter = myStorage->entity(aCenterAttr);
 
-  AttributeStringPtr aMethodTypeAttr = aData->string(SketchPlugin_MultiRotation::ANGLE_TYPE());
+  AttributeStringPtr aMethodTypeAttr =
+      myBaseConstraint->string(SketchPlugin_MultiRotation::ANGLE_TYPE());
   theFullValue = aMethodTypeAttr->value() != "SingleAngle";
 
   getEntities(theEntities);
@@ -38,39 +45,30 @@ void SketchSolver_ConstraintMultiRotation::getAttributes(
 void SketchSolver_ConstraintMultiRotation::process()
 {
   cleanErrorMsg();
-  if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
-    /// TODO: Put error message here
+  if (!myBaseConstraint || !myStorage) {
+    // Not enough parameters are assigned
     return;
   }
 
+  EntityWrapperPtr anAngle;
   EntityWrapperPtr aRotationCenter;
   bool isFullValue;
   std::list<EntityWrapperPtr> aBaseEntities;
-  getAttributes(aRotationCenter, myAngle, isFullValue, aBaseEntities);
+  getAttributes(aRotationCenter, anAngle, isFullValue, aBaseEntities);
   if (!myErrorMsg.empty())
     return;
 
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-  std::list<ConstraintWrapperPtr> aRotConstraints;
-
-  std::list<EntityWrapperPtr>::iterator anEntIt = aBaseEntities.begin();
-  for (; anEntIt != aBaseEntities.end(); ++anEntIt) {
-    std::list<ConstraintWrapperPtr> aNewConstraints =
-        aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID, myType,
-        myAngle, isFullValue, aRotationCenter, EntityWrapperPtr(),
-        std::list<EntityWrapperPtr>(1, *anEntIt));
-    aRotConstraints.insert(aRotConstraints.end(), aNewConstraints.begin(), aNewConstraints.end());
-  }
-  myStorage->addConstraint(myBaseConstraint, aRotConstraints);
-
+  ScalarWrapperPtr anAngleVal = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anAngle);
+  myAngle = anAngleVal->value();
   myAdjusted = false;
   adjustConstraint();
+
+  myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP());
 }
 
 void SketchSolver_ConstraintMultiRotation::updateLocal()
 {
-  double aValue = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
-      myBaseConstraint->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value();
+  double aValue = myBaseConstraint->real(SketchPlugin_MultiRotation::ANGLE_ID())->value();
   if (fabs(myAngle - aValue) > tolerance)
     myAdjusted = false;
   // update angle value
@@ -90,38 +88,8 @@ void SketchSolver_ConstraintMultiRotation::updateLocal()
   if (isMethodChanged)
     myIsFullValue = aFullValue;
 
-  if (aCenterPointChanged || isMethodChanged) {
-    DataPtr aData = myBaseConstraint->data();
-    std::list<ConstraintWrapperPtr> aConstraints = myStorage->constraint(myBaseConstraint);
-    std::list<ConstraintWrapperPtr>::const_iterator anIt = aConstraints.begin(),
-      aLast = aConstraints.end();
-    std::list<EntityWrapperPtr> anEntities;
-    for (; anIt != aLast; anIt++) {
-      ConstraintWrapperPtr aConstraint = *anIt;
-      aConstraint->setIsFullValue(myIsFullValue);
-      if (aCenterPointChanged) {
-        anEntities.clear();
-        const std::list<EntityWrapperPtr>& aConstraintEntities = aConstraint->entities();
-        std::list<EntityWrapperPtr>::const_iterator aSIt = aConstraintEntities.begin(),
-          aSLast = aConstraintEntities.end();
-        EntityWrapperPtr aCenterPointEntity = *aSIt++;
-        if (aCenterPointChanged) {
-          AttributePtr aCenterPointAttr = aData->attribute(SketchPlugin_MultiRotation::CENTER_ID());
-          myStorage->update(aCenterPointAttr);
-          aCenterPointEntity = myStorage->entity(aCenterPointAttr);
-        }
-        anEntities.push_back(aCenterPointEntity);
-
-        for (; aSIt != aSLast; ++aSIt)
-          anEntities.push_back(*aSIt);
-
-        aConstraint->setEntities(anEntities);
-      }
-    }
-    myStorage->addConstraint(myBaseConstraint, aConstraints);
-
+  if (aCenterPointChanged || isMethodChanged)
     myAdjusted = false;
-  }
 }
 
 void SketchSolver_ConstraintMultiRotation::adjustConstraint()
@@ -134,17 +102,13 @@ void SketchSolver_ConstraintMultiRotation::adjustConstraint()
     return;
   }
 
-  const std::list<ConstraintWrapperPtr>& aConstraints = myStorage->constraint(myBaseConstraint);
-  std::list<ConstraintWrapperPtr>::const_iterator aCIt = aConstraints.begin();
-  for (; aCIt != aConstraints.end(); ++aCIt)
-    (*aCIt)->setValue(myAngle);
-
   // Obtain coordinates of rotation center
-  EntityWrapperPtr aRotCenter = myStorage->entity(
-      myBaseConstraint->attribute(SketchPlugin_MultiRotation::CENTER_ID()));
-  std::list<ParameterWrapperPtr> aParams = aRotCenter->parameters();
-  myCenterCoord[0] = aParams.front()->value();
-  myCenterCoord[1] = aParams.back()->value();
+  std::shared_ptr<PlaneGCSSolver_PointWrapper> aRotCenter =
+      std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(myStorage->entity(
+      myBaseConstraint->attribute(SketchPlugin_MultiRotation::CENTER_ID())));
+  GCSPointPtr aCenterPoint = aRotCenter->point();
+  myCenterCoord[0] = *(aCenterPoint->x);
+  myCenterCoord[1] = *(aCenterPoint->y);
 
   double anAngleValue = myAngle;
   if (myIsFullValue && myNumberOfCopies > 0)
index 10087cc67b6b124ca5804b82fc2e668c303bd68f..7a8daf78ddd1f5f01f8eaa90bcdf8364add2b443 100644 (file)
@@ -26,32 +26,36 @@ public:
 
 protected:
   /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
-  virtual void process();
+  virtual void process() override;
 
   /// \brief Generate list of rotated entities
   /// \param[out] theCenter   central point of rotation
   /// \param[out] theAngle    rotation angle
   /// \param[out] theFullValue  applying translation using the disstance as a full or single value
   /// \param[out] theEntities list of base entities
-  void getAttributes(EntityWrapperPtr& theCenter, double& theAngle, bool& theFullValue,
+  void getAttributes(EntityWrapperPtr&            theCenter,
+                     EntityWrapperPtr&            theAngle,
+                     bool&                        theFullValue,
                      std::list<EntityWrapperPtr>& theEntities);
 
   /// \brief This method is used in derived objects to check consistence of constraint.
-  virtual void adjustConstraint();
+  virtual void adjustConstraint() override;
 
   /// \brief Update parameters (called from base class)
-  virtual void updateLocal();
+  virtual void updateLocal() override;
 
 private:
   /// \brief Convert absolute coordinates to relative coordinates
-  virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY);
+  virtual void getRelative(double theAbsX, double theAbsY,
+                           double& theRelX, double& theRelY) override;
   /// \brief Convert relative coordinates to absolute coordinates
-  virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY);
+  virtual void getAbsolute(double theRelX, double theRelY,
+                           double& theAbsX, double& theAbsY) override;
   /// \brief Apply transformation for relative coordinates
-  virtual void transformRelative(double& theX, double& theY);
+  virtual void transformRelative(double& theX, double& theY) override;
 
   /// \brief Returns name of NUMBER_OF_COPIES parameter for corresponding feature
-  virtual const std::string& nameNbObjects();
+  virtual const std::string& nameNbObjects() override;
 
 private:
   AttributePoint2DPtr myCenterPointAttribute; ///< a center of rotation
index 4f1741e7662916798ecae0c844f21434d02118ed..5244ec6a4f5f66e1e5f43e6a391c526d2623a59a 100644 (file)
@@ -4,6 +4,8 @@
 #include <SketchSolver_Error.h>
 #include <SketchSolver_Manager.h>
 
+#include <PlaneGCSSolver_PointWrapper.h>
+
 #include <SketchPlugin_MultiTranslation.h>
 
 #include <ModelAPI_AttributeString.h>
@@ -39,8 +41,8 @@ void SketchSolver_ConstraintMultiTranslation::getAttributes(
 void SketchSolver_ConstraintMultiTranslation::process()
 {
   cleanErrorMsg();
-  if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
-    /// TODO: Put error message here
+  if (!myBaseConstraint || !myStorage) {
+    // Not enough parameters are assigned
     return;
   }
 
@@ -51,25 +53,10 @@ void SketchSolver_ConstraintMultiTranslation::process()
   if (!myErrorMsg.empty())
     return;
 
-  AttributeStringPtr aMethodTypeAttr =
-      myBaseConstraint->data()->string(SketchPlugin_MultiTranslation::VALUE_TYPE());
-
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-  std::list<ConstraintWrapperPtr> aTransConstraints;
-
-  std::list<EntityWrapperPtr>::iterator anEntIt = aBaseEntities.begin();
-  for (; anEntIt != aBaseEntities.end(); ++anEntIt) {
-    std::list<ConstraintWrapperPtr> aNewConstraints =
-        aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID, myType,
-        0.0, aFullValue, aStartPoint, aEndPoint, std::list<EntityWrapperPtr>(1, *anEntIt));
-    aTransConstraints.insert(aTransConstraints.end(),
-                             aNewConstraints.begin(), aNewConstraints.end());
-  }
-
-  myStorage->addConstraint(myBaseConstraint, aTransConstraints);
-
   myAdjusted = false;
   adjustConstraint();
+
+  myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP());
 }
 
 const std::string& SketchSolver_ConstraintMultiTranslation::nameNbObjects()
@@ -98,47 +85,8 @@ void SketchSolver_ConstraintMultiTranslation::updateLocal()
   if (isMethodChanged)
     myIsFullValue = aFullValue;
 
-  if (aStartPointChanged || anEndPointChanged || isMethodChanged) {
-    DataPtr aData = myBaseConstraint->data();
-    std::list<ConstraintWrapperPtr> aConstraints = myStorage->constraint(myBaseConstraint);
-    std::list<ConstraintWrapperPtr>::const_iterator anIt = aConstraints.begin(),
-                                                    aLast = aConstraints.end();
-    std::list<EntityWrapperPtr> anEntities;
-    for (; anIt != aLast; anIt++) {
-      ConstraintWrapperPtr aConstraint = *anIt;
-      aConstraint->setIsFullValue(myIsFullValue);
-      anEntities.clear();
-
-      const std::list<EntityWrapperPtr>& aConstraintEntities = aConstraint->entities();
-      std::list<EntityWrapperPtr>::const_iterator aSIt = aConstraintEntities.begin(),
-                                                  aSLast = aConstraintEntities.end();
-      EntityWrapperPtr aStartEntity = *aSIt++;
-      if (aStartPointChanged) {
-        AttributePtr aStartPointAttr =
-          aData->attribute(SketchPlugin_MultiTranslation::START_POINT_ID());
-        myStorage->update(aStartPointAttr);
-        aStartEntity = myStorage->entity(aStartPointAttr);
-      }
-      anEntities.push_back(aStartEntity);
-
-      EntityWrapperPtr anEndEntity = *aSIt++;
-      if (anEndPointChanged) {
-        AttributePtr anEndPointAttr =
-          aData->attribute(SketchPlugin_MultiTranslation::END_POINT_ID());
-        myStorage->update(anEndPointAttr);
-        anEndEntity = myStorage->entity(anEndPointAttr);
-      }
-      anEntities.push_back(anEndEntity);
-
-      for (; aSIt != aSLast; ++aSIt)
-        anEntities.push_back(*aSIt);
-
-      aConstraint->setEntities(anEntities);
-    }
-    myStorage->addConstraint(myBaseConstraint, aConstraints);
-
+  if (aStartPointChanged || anEndPointChanged || isMethodChanged)
     myAdjusted = false;
-  }
 }
 
 void SketchSolver_ConstraintMultiTranslation::adjustConstraint()
@@ -147,15 +95,18 @@ void SketchSolver_ConstraintMultiTranslation::adjustConstraint()
     return;
 
   // Obtain delta between start and end points of translation
-  EntityWrapperPtr aStart = myStorage->entity(
-      myBaseConstraint->attribute(SketchPlugin_MultiTranslation::START_POINT_ID()));
-  std::list<ParameterWrapperPtr> aStartParams = aStart->parameters();
-  EntityWrapperPtr aEnd = myStorage->entity(
-      myBaseConstraint->attribute(SketchPlugin_MultiTranslation::END_POINT_ID()));
-  std::list<ParameterWrapperPtr> aEndParams = aEnd->parameters();
-
-  myDelta[0] = aEndParams.front()->value() - aStartParams.front()->value();
-  myDelta[1] = aEndParams.back()->value() - aStartParams.back()->value();
+  std::shared_ptr<PlaneGCSSolver_PointWrapper> aStartWrapper =
+      std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(myStorage->entity(
+      myBaseConstraint->attribute(SketchPlugin_MultiTranslation::START_POINT_ID())));
+  std::shared_ptr<PlaneGCSSolver_PointWrapper> aEndWrapper =
+      std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(myStorage->entity(
+      myBaseConstraint->attribute(SketchPlugin_MultiTranslation::END_POINT_ID())));
+
+  GCSPointPtr aStart = aStartWrapper->point();
+  GCSPointPtr aEnd   = aEndWrapper->point();
+
+  myDelta[0] = *(aEnd->x) - *(aStart->x);
+  myDelta[1] = *(aEnd->y) - *(aStart->y);
 
   if (myIsFullValue && myNumberOfCopies > 0) {
     myDelta[0] /= myNumberOfCopies;
index 7c93d6d0e156c29df701e66d74ee16713bd26568..60e70f21ca6c1176aa887e5cd1277cc51c8e8f96 100644 (file)
@@ -26,7 +26,7 @@ public:
 
 protected:
   /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
-  virtual void process();
+  virtual void process() override;
 
   /// \brief Generate list of translated entities
   /// \param[out] theStartPoint start point of translation
@@ -37,21 +37,23 @@ protected:
                      bool& theFullValue, std::list<EntityWrapperPtr>& theEntities);
 
   /// \brief This method is used in derived objects to check consistence of constraint.
-  virtual void adjustConstraint();
+  virtual void adjustConstraint() override;
 
   /// \brief Update parameters (called from base class)
-  virtual void updateLocal();
+  virtual void updateLocal() override;
 
 private:
   /// \brief Convert absolute coordinates to relative coordinates
-  virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY);
+  virtual void getRelative(double theAbsX, double theAbsY,
+                           double& theRelX, double& theRelY) override;
   /// \brief Convert relative coordinates to absolute coordinates
-  virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY);
+  virtual void getAbsolute(double theRelX, double theRelY,
+                           double& theAbsX, double& theAbsY) override;
   /// \brief Apply transformation for relative coordinates
-  virtual void transformRelative(double& theX, double& theY);
+  virtual void transformRelative(double& theX, double& theY) override;
 
   /// \brief Returns name of NUMBER_OF_COPIES parameter for corresponding feature
-  virtual const std::string& nameNbObjects();
+  virtual const std::string& nameNbObjects() override;
 
 private:
   AttributePoint2DPtr myStartPointAttribute;
index 690587ae238e72030798244b7912f75e8331932d..2a7b52a873bff314c77001c40ad7187507290bf8 100644 (file)
@@ -6,38 +6,32 @@
 
 #include <GeomAPI_Pnt2d.h>
 #include <SketchPlugin_Circle.h>
+#include <SketchPlugin_ConstraintCoincidence.h>
 
 #include <cmath>
 
 
-/// \brief Check whether the entities has only one shared point
-static bool hasSingleCoincidence(EntityWrapperPtr theEntity1, EntityWrapperPtr theEntity2)
+/// \brief Check whether the entities has only one shared point or less
+static bool hasSingleCoincidence(FeaturePtr theFeature1, FeaturePtr theFeature2)
 {
-  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) {
-    if ((*anIt1)->type() != ENTITY_POINT)
-      continue;
-    std::shared_ptr<GeomAPI_Pnt2d> aPt1 = aBuilder->point(*anIt1);
-    for (anIt2 = aStartIt2; anIt2 != aPoints2.end(); ++anIt2) {
-      if ((*anIt2)->type() != ENTITY_POINT)
-        continue;
-      std::shared_ptr<GeomAPI_Pnt2d> aPt2 = aBuilder->point(*anIt2);
-      if (aPt1->distance(aPt2) < tolerance)
-        ++aNbCoinc;
-    }
+  const std::set<AttributePtr>& aRefs1 = theFeature1->data()->refsToMe();
+  const std::set<AttributePtr>& aRefs2 = theFeature2->data()->refsToMe();
+
+  // collect all shared coincidendes
+  std::set<FeaturePtr> aCoincidences;
+  std::set<AttributePtr>::const_iterator anIt;
+  for (anIt = aRefs1.begin(); anIt != aRefs1.end(); ++anIt) {
+    FeaturePtr aRef = ModelAPI_Feature::feature((*anIt)->owner());
+    if (aRef && aRef->getKind() == SketchPlugin_ConstraintCoincidence::ID())
+      aCoincidences.insert(aRef);
   }
-  return aNbCoinc == 1;
+  for (anIt = aRefs2.begin(); anIt != aRefs2.end(); ++anIt) {
+    FeaturePtr aRef = ModelAPI_Feature::feature((*anIt)->owner());
+    if (aRef)
+      aCoincidences.erase(aRef);
+  }
+
+  return aCoincidences.size() <= 1;
 }
 
 /// \brief Check if two connected arcs have centers
@@ -50,7 +44,7 @@ static bool isInternalTangency(EntityWrapperPtr theEntity1, EntityWrapperPtr the
 
 
 void SketchSolver_ConstraintTangent::getAttributes(
-    double& theValue,
+    EntityWrapperPtr& theValue,
     std::vector<EntityWrapperPtr>& theAttributes)
 {
   SketchSolver_Constraint::getAttributes(theValue, theAttributes);
@@ -97,9 +91,15 @@ void SketchSolver_ConstraintTangent::getAttributes(
     return;
   }
 
-  if (myType == CONSTRAINT_TANGENT_ARC_LINE &&
-      !hasSingleCoincidence(theAttributes[2], theAttributes[3]))
-    myErrorMsg = SketchSolver_Error::TANGENCY_FAILED();
+  if (myType == CONSTRAINT_TANGENT_ARC_LINE) {
+    AttributeRefAttrPtr aRefAttr = myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+    FeaturePtr aFeature1 = ModelAPI_Feature::feature(aRefAttr->object());
+    aRefAttr = myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
+    FeaturePtr aFeature2 = ModelAPI_Feature::feature(aRefAttr->object());
+
+    if (!hasSingleCoincidence(aFeature1, aFeature2))
+      myErrorMsg = SketchSolver_Error::TANGENCY_FAILED();
+  }
 
   if (isSwap) {
     EntityWrapperPtr aTemp = theAttributes[2];
@@ -110,29 +110,13 @@ void SketchSolver_ConstraintTangent::getAttributes(
 
 void SketchSolver_ConstraintTangent::adjustConstraint()
 {
-  if (myType == CONSTRAINT_TANGENT_CIRCLE_LINE) {
-    ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
-    AttributePtr aCircleCenter = aConstraint->entities().front()->baseAttribute();
-    if (!aCircleCenter)
-      return;
-    FeaturePtr aCircle = ModelAPI_Feature::feature(aCircleCenter->owner());
-    AttributeDoublePtr aRadius = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
-        aCircle->attribute(SketchPlugin_Circle::RADIUS_ID()));
-
-    if (fabs(aRadius->value()) == fabs(aConstraint->value()))
-      return;
-
-    aConstraint->setValue(aRadius->value());
-
-    // Adjust the sign of constraint value
-    BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-    aBuilder->adjustConstraint(aConstraint);
-    myStorage->addConstraint(myBaseConstraint, aConstraint);
-  }
-  else if (myType == CONSTRAINT_TANGENT_ARC_ARC) {
-    ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
-    if (isArcArcInternal != isInternalTangency(
-        aConstraint->entities().front(), aConstraint->entities().back())) {
+  if (myType == CONSTRAINT_TANGENT_ARC_ARC) {
+    EntityWrapperPtr anEntity1 =
+        myStorage->entity(myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A()));
+    EntityWrapperPtr anEntity2 =
+        myStorage->entity(myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_B()));
+
+    if (isArcArcInternal != isInternalTangency(anEntity1, anEntity2)) {
       // fully rebuld constraint, because it is unable to access attributes of PlaneGCS constraint
       remove();
       process();
index 589d1ab4537a365a01b66a17f3e4559a7571c38d..35e724420534f8bd0cfbab00f67cef8eec5aafc5 100644 (file)
@@ -27,11 +27,12 @@ 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);
+  virtual void getAttributes(EntityWrapperPtr&              theValue,
+                             std::vector<EntityWrapperPtr>& theAttributes) override;
 
   /// \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();
+  virtual void adjustConstraint() override;
 
 private:
   bool isArcArcInternal;
index 867775e50d2301b9defd228c2831157cfe4c37a8..8db65a33778b44e35b1c96c13c9a72a33376ce10 100644 (file)
@@ -5,62 +5,15 @@
 // Author:  Artem ZHIDKOV
 
 #include "SketchSolver_Group.h"
-
-#include <SketchSolver_Constraint.h>
-#include <SketchSolver_ConstraintCoincidence.h>
-#include <SketchSolver_ConstraintMulti.h>
 #include <SketchSolver_Error.h>
 #include <SketchSolver_Manager.h>
 
+#include <PlaneGCSSolver_Solver.h>
+
 #include <Events_InfoMessage.h>
-#include <Events_Loop.h>
 #include <ModelAPI_AttributeString.h>
 #include <ModelAPI_Events.h>
-#include <ModelAPI_Session.h>
-#include <ModelAPI_Validator.h>
-
-#include <SketchPlugin_Arc.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_ConstraintFillet.h>
-#include <SketchPlugin_ConstraintMirror.h>
-#include <SketchPlugin_ConstraintParallel.h>
-#include <SketchPlugin_ConstraintPerpendicular.h>
-#include <SketchPlugin_ConstraintRadius.h>
 #include <SketchPlugin_ConstraintRigid.h>
-#include <SketchPlugin_ConstraintSplit.h>
-#include <SketchPlugin_ConstraintTangent.h>
-#include <SketchPlugin_ConstraintVertical.h>
-#include <SketchPlugin_MultiRotation.h>
-#include <SketchPlugin_MultiTranslation.h>
-
-#include <math.h>
-#include <assert.h>
-
-
-/// \brief This class is used to give unique index to the groups
-class GroupIndexer
-{
-public:
-  /// \brief Return vacant index
-  static GroupID NEW_GROUP() { return ++myGroupIndex; }
-  /// \brief Removes the index
-  static void REMOVE_GROUP(const GroupID& theIndex) {
-    if (myGroupIndex == theIndex)
-      myGroupIndex--;
-  }
-
-private:
-  GroupIndexer() {};
-
-  static GroupID myGroupIndex; ///< index of the group
-};
-
-GroupID GroupIndexer::myGroupIndex = GID_OUTOFGROUP;
 
 
 static void sendMessage(const char* theMessageName)
@@ -85,20 +38,19 @@ static void sendMessage(const char* theMessageName, const std::set<ObjectPtr>& t
 // =========  SketchSolver_Group  ===============
 // ========================================================
 
-SketchSolver_Group::SketchSolver_Group(
-    std::shared_ptr<ModelAPI_CompositeFeature> theWorkplane)
-    : myID(GroupIndexer::NEW_GROUP()),
-      myPrevResult(STATUS_UNKNOWN)
+SketchSolver_Group::SketchSolver_Group(const CompositeFeaturePtr& theWorkplane)
+  : mySketch(theWorkplane),
+    myPrevResult(STATUS_UNKNOWN),
+    myIsEventsBlocked(false)
 {
-  // Initialize workplane
-  myWorkplaneID = EID_UNKNOWN;
-  addWorkplane(theWorkplane);
+  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
+  mySketchSolver = aBuilder->createSolver();
+  myStorage = aBuilder->createStorage(mySketchSolver);
 }
 
 SketchSolver_Group::~SketchSolver_Group()
 {
   myConstraints.clear();
-  GroupIndexer::REMOVE_GROUP(myID);
   // send the message that there is no more conflicting constraints
   if (!myConflictingConstraints.empty()) {
     sendMessage(EVENT_SOLVER_REPAIRED, myConflictingConstraints);
@@ -106,49 +58,6 @@ SketchSolver_Group::~SketchSolver_Group()
   }
 }
 
-// ============================================================================
-//  Function: isBaseWorkplane
-//  Class:    SketchSolver_Group
-//  Purpose:  verify the group is based on the given workplane
-// ============================================================================
-bool SketchSolver_Group::isBaseWorkplane(CompositeFeaturePtr theWorkplane) const
-{
-  return theWorkplane == mySketch;
-}
-
-// ============================================================================
-//  Function: isInteract
-//  Class:    SketchSolver_Group
-//  Purpose:  verify are there any entities in the group used by given constraint
-// ============================================================================
-bool SketchSolver_Group::isInteract(FeaturePtr theFeature) const
-{
-  // Empty group interacts with everything
-  if (isEmpty())
-    return true;
-  // Check interaction with the storage
-  bool isInteracted = myStorage->isInteract(theFeature);
-  ConstraintConstraintMap::const_iterator anIt = myConstraints.begin();
-  for (; !isInteracted && anIt != myConstraints.end(); ++anIt)
-    if (anIt->first->getKind() == SketchPlugin_MultiRotation::ID() ||
-        anIt->first->getKind() == SketchPlugin_MultiTranslation::ID()) {
-      isInteracted = anIt->second->isUsed(theFeature);
-      if (isInteracted)
-        break;
-      // if theFeature is a constraint, check its attributes
-      ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
-      if (!aConstraint)
-        continue;
-      for (int i = 0; i < 4 && !isInteracted; ++i) {
-        AttributeRefAttrPtr aRefAttr = aConstraint->refattr(aConstraint->ATTRIBUTE(i));
-        if (!aRefAttr)
-          continue;
-        isInteracted = anIt->second->isUsed((AttributePtr)aRefAttr);
-      }
-    }
-  return isInteracted;
-}
-
 // ============================================================================
 //  Function: changeConstraint
 //  Class:    SketchSolver_Group
@@ -157,183 +66,48 @@ bool SketchSolver_Group::isInteract(FeaturePtr theFeature) const
 bool SketchSolver_Group::changeConstraint(
     std::shared_ptr<SketchPlugin_Constraint> theConstraint)
 {
-  // There is no workplane yet, something wrong
-  if (myWorkplaneID == EID_UNKNOWN)
-    return false;
-
-  if (!theConstraint || !theConstraint->data())
-    return false;
-
-  if (!checkFeatureValidity(theConstraint))
-    return false;
-
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-  myStorage->blockEvents(true);
-
   bool isNewConstraint = myConstraints.find(theConstraint) == myConstraints.end();
   if (isNewConstraint) {
+    BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
     // Add constraint to the current group
     SolverConstraintPtr aConstraint = aBuilder->createConstraint(theConstraint);
     if (!aConstraint)
       return false;
-    aConstraint->process(myStorage, getId(), getWorkplaneId());
+    aConstraint->process(myStorage, myIsEventsBlocked);
     if (!aConstraint->error().empty()) {
       if (aConstraint->error() == SketchSolver_Error::NOT_INITIALIZED())
         return false; // some attribute are not initialized yet, don't show message
       Events_InfoMessage("SketchSolver_Group", aConstraint->error(), this).send();
     }
     myConstraints[theConstraint] = aConstraint;
-
-    if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID())
-      notifyCoincidenceChanged(myConstraints[theConstraint]);
   }
   else
     myConstraints[theConstraint]->update();
-
-  // 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()));
-      if (aFeature) {
-        SolverConstraintPtr aConstraint = aBuilder->createFixedConstraint(aFeature);
-        if (aConstraint) {
-          aConstraint->process(myStorage, getId(), getWorkplaneId());
-          setTemporary(aConstraint);
-        }
-      }
-    }
-  }
   return true;
 }
 
-// Update constraints if they contain specific feature
-static void updateMultiConstraints(ConstraintConstraintMap& theConstraints, FeaturePtr theFeature)
-{
-  ConstraintConstraintMap::iterator aCIt = theConstraints.begin();
-  for (; aCIt != theConstraints.end(); ++aCIt) {
-    SketchSolver_ConstraintType aType = aCIt->second->getType();
-    if ((aType == CONSTRAINT_MULTI_ROTATION ||
-         aType == CONSTRAINT_MULTI_TRANSLATION)
-        && aCIt->second->isUsed(theFeature))
-      std::dynamic_pointer_cast<SketchSolver_ConstraintMulti>(aCIt->second)->update(true);
-    else if ((aType == CONSTRAINT_TANGENT_CIRCLE_LINE || aType == CONSTRAINT_TANGENT_ARC_ARC ||
-              aType == CONSTRAINT_SYMMETRIC || aType == CONSTRAINT_ANGLE)
-             && aCIt->second->isUsed(theFeature))
-      aCIt->second->update();
-  }
-}
-
-// Recalculate slave features of the Multi constraints
-static void updateMultiConstraints(ConstraintConstraintMap& theConstraints)
-{
-  ConstraintConstraintMap::iterator aCIt = theConstraints.begin();
-  for (; aCIt != theConstraints.end(); ++aCIt) {
-    SketchSolver_ConstraintType aType = aCIt->second->getType();
-    if ((aType == CONSTRAINT_MULTI_ROTATION ||
-         aType == CONSTRAINT_MULTI_TRANSLATION))
-      std::dynamic_pointer_cast<SketchSolver_ConstraintMulti>(aCIt->second)->update(true);
-  }
-}
-
 bool SketchSolver_Group::updateFeature(FeaturePtr theFeature)
 {
-  if (!checkFeatureValidity(theFeature))
-    return false;
-
-  bool isBlocked = myStorage->isEventsBlocked();
-  if (!isBlocked)
-    myStorage->blockEvents(true);
-
-  myStorage->refresh(true);
-  bool isUpdated = myStorage->update(theFeature);
-
-  updateMultiConstraints(myConstraints, theFeature);
-
-  // events were not blocked before, the feature has not been updated,
-  // so it is necessary to revert blocking
-  if (!isUpdated && !isBlocked)
-    myStorage->blockEvents(false);
-  return isUpdated;
+  return myStorage->update(theFeature);
 }
 
 bool SketchSolver_Group::moveFeature(FeaturePtr theFeature)
 {
   BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
 
-  // Firstly, revert changes in the fixed entities
-  myStorage->blockEvents(true);
-  myStorage->refresh(true);
-
-  // Secondly, search attributes of the feature in the list of the Multi constraints and update them
-  updateMultiConstraints(myConstraints, theFeature);
-
-  // Then, create temporary Fixed constraint
+  // Create temporary Fixed constraint
   SolverConstraintPtr aConstraint = aBuilder->createMovementConstraint(theFeature);
   if (!aConstraint)
     return false;
-  aConstraint->process(myStorage, getId(), getWorkplaneId());
+  aConstraint->process(myStorage, myIsEventsBlocked);
   if (aConstraint->error().empty())
     setTemporary(aConstraint);
+  else
+    myStorage->notify(theFeature);
 
-  // Workaround to process arcs.
-  // When move unconstrained arc, add temporary constraint to fix radius.
-  if (theFeature->getKind() == SketchPlugin_Arc::ID()) {
-    bool hasDup = myStorage->hasDuplicatedConstraint();
-    SolverConstraintPtr aFixedRadius = aBuilder->createFixedArcRadiusConstraint(theFeature);
-    if (aFixedRadius) {
-      aFixedRadius->process(myStorage, getId(), getWorkplaneId());
-      hasDup = myStorage->hasDuplicatedConstraint() && !hasDup;
-      if (aFixedRadius->error().empty() && !hasDup)
-        setTemporary(aFixedRadius);
-      else
-        aFixedRadius->remove();
-    }
-  }
-  return true;
-}
-
-// ============================================================================
-//  Function: addWorkplane
-//  Class:    SketchSolver_Group
-//  Purpose:  create workplane for the group
-// ============================================================================
-bool SketchSolver_Group::addWorkplane(CompositeFeaturePtr theSketch)
-{
-  if (myWorkplaneID != EID_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;
-  }
   return true;
 }
 
-// ============================================================================
-//  Function: updateWorkplane
-//  Class:    SketchSolver_Group
-//  Purpose:  update parameters of workplane
-// ============================================================================
-bool SketchSolver_Group::updateWorkplane()
-{
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-  if (!myStorage) // Create storage if not exists
-    myStorage = aBuilder->createStorage(getId());
-
-  // 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();
-  }
-  return isUpdated;
-}
-
 // ============================================================================
 //  Function: resolveConstraints
 //  Class:    SketchSolver_Group
@@ -345,19 +119,16 @@ bool SketchSolver_Group::resolveConstraints()
   bool isGroupEmpty = isEmpty() && myStorage->isEmpty();
   if (myStorage->isNeedToResolve() &&
       (!isGroupEmpty || !myConflictingConstraints.empty() || myPrevResult == STATUS_FAILED)) {
-    if (!mySketchSolver)
-      mySketchSolver = SketchSolver_Manager::instance()->builder()->createSolver();
+////    if (!mySketchSolver)
+////      mySketchSolver = SketchSolver_Manager::instance()->builder()->createSolver();
 
-    mySketchSolver->setGroup(myID);
-    mySketchSolver->calculateFailedConstraints(false);
-    myStorage->initializeSolver(mySketchSolver);
-    mySketchSolver->prepare();
+////    mySketchSolver->calculateFailedConstraints(false);
+    myStorage->initializeSolver();
+////    mySketchSolver->prepare();
 
     SketchSolver_SolveStatus aResult = STATUS_OK;
     try {
-      if (myStorage->hasDuplicatedConstraint())
-        aResult = STATUS_INCONSISTENT;
-      else if (!isGroupEmpty) {
+      if (!isGroupEmpty) {
         // To avoid overconstraint situation, we will remove temporary constraints one-by-one
         // and try to find the case without overconstraint
         bool isLastChance = false;
@@ -373,7 +144,7 @@ bool SketchSolver_Group::resolveConstraints()
 
           removeTemporaryConstraints();
           mySketchSolver->calculateFailedConstraints(true); // something failed => need to find it
-          myStorage->initializeSolver(mySketchSolver);
+          myStorage->initializeSolver();
         }
       }
     } catch (...) {
@@ -392,10 +163,10 @@ bool SketchSolver_Group::resolveConstraints()
     if (aResult == STATUS_OK || aResult == STATUS_EMPTYSET) {
       myStorage->setNeedToResolve(false);
       myStorage->refresh();
-      updateMultiConstraints(myConstraints);
-      // multi-constraints updated some parameters, need to store them
-      if (myStorage->isNeedToResolve())
-        resolveConstraints();
+////      updateMultiConstraints(myConstraints);
+////      // multi-constraints updated some parameters, need to store them
+////      if (myStorage->isNeedToResolve())
+////        resolveConstraints();
 
       if (myPrevResult != STATUS_OK || myPrevResult == STATUS_UNKNOWN) {
         getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue("");
@@ -448,142 +219,18 @@ bool SketchSolver_Group::resolveConstraints()
       myStorage->refresh();
   }
   removeTemporaryConstraints();
-  myStorage->blockEvents(false);
   myStorage->setNeedToResolve(false);
   return aResolved;
 }
 
 // ============================================================================
-//  Function: mergeGroups
-//  Class:    SketchSolver_Group
-//  Purpose:  append specified group to the current group
-// ============================================================================
-void SketchSolver_Group::mergeGroups(const SketchSolver_Group& theGroup)
-{
-  // If specified group is empty, no need to merge
-  if (theGroup.isEmpty())
-    return;
-
-  std::set<ObjectPtr> aConstraints;
-  ConstraintConstraintMap::const_iterator aConstrIter = theGroup.myConstraints.begin();
-  for (; aConstrIter != theGroup.myConstraints.end(); aConstrIter++)
-    aConstraints.insert(aConstrIter->first);
-
-  std::list<FeaturePtr> aSortedConstraints = selectApplicableFeatures(aConstraints);
-  std::list<FeaturePtr>::iterator aSCIter = aSortedConstraints.begin();
-  for (; aSCIter != aSortedConstraints.end(); ++aSCIter) {
-    ConstraintPtr aConstr = std::dynamic_pointer_cast<SketchPlugin_Constraint>(*aSCIter);
-    if (!aConstr)
-      continue;
-    changeConstraint(aConstr);
-  }
-
-  // merge previous states of groups => use the worst state,
-  // so the group after rebuilt may discard error messages if exist
-  if (theGroup.myPrevResult > myPrevResult)
-    myPrevResult = theGroup.myPrevResult;
-}
-
-// ============================================================================
-//  Function: splitGroup
-//  Class:    SketchSolver_Group
-//  Purpose:  divide the group into several subgroups
-// ============================================================================
-void SketchSolver_Group::splitGroup(std::list<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());
-  // empty vector to avoid creation of solver's constraints
-  std::list<ConstraintWrapperPtr> aDummyVec;
-
-  // Obtain constraints, which should be separated
-  std::list<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);
-  }
-
-  // Check the unused constraints once again,
-  // because they may become interacted with new storage since adding constraints
-  std::list<ConstraintPtr>::iterator aUnuseIt = anUnusedConstraints.begin();
-  while (aUnuseIt != anUnusedConstraints.end()) {
-    if (aNewStorage->isInteract(FeaturePtr(*aUnuseIt))) {
-      aNewStorage->addConstraint(*aUnuseIt, aDummyVec);
-      anUnusedConstraints.erase(aUnuseIt);
-      aUnuseIt = anUnusedConstraints.begin();
-      continue;
-    }
-    aUnuseIt++;
-  }
-
-  std::list<SketchSolver_Group*>::iterator aCutsIter;
-  // Remove unused constraints
-  for (aUnuseIt = anUnusedConstraints.begin(); aUnuseIt != anUnusedConstraints.end(); ++aUnuseIt)
-    removeConstraint(*aUnuseIt);
-
-  SketchSolver_Group* aBaseGroup;
-  for (aUnuseIt = anUnusedConstraints.begin(); aUnuseIt != anUnusedConstraints.end(); ++aUnuseIt) {
-    aBaseGroup = 0;
-    aCutsIter = theCuts.begin();
-    // Try to append constraint to the current group
-    if (isInteract(*aUnuseIt)) {
-      changeConstraint(*aUnuseIt);
-      aBaseGroup = this;
-    } else {
-      // Try to append constraint to already existent group
-      for (; aCutsIter != theCuts.end(); ++aCutsIter)
-        if ((*aCutsIter)->isInteract(*aUnuseIt)) {
-          (*aCutsIter)->changeConstraint(*aUnuseIt);
-          break;
-        }
-    }
-
-    if (aCutsIter == theCuts.end() && !aBaseGroup) {
-      // Add new group
-      SketchSolver_Group* aGroup = new SketchSolver_Group(mySketch);
-      aGroup->changeConstraint(*aUnuseIt);
-      theCuts.push_back(aGroup);
-    } else {
-      if (!aBaseGroup)
-        aBaseGroup = *aCutsIter++;
-      // Find other groups interacting with constraint
-      for (; aCutsIter != theCuts.end(); ++aCutsIter)
-        if ((*aCutsIter)->isInteract(*aUnuseIt)) {
-          aBaseGroup->mergeGroups(**aCutsIter);
-          std::list<SketchSolver_Group*>::iterator aRemoveIt = aCutsIter--;
-          theCuts.erase(aRemoveIt);
-        }
-    }
-  }
-}
-
-// ============================================================================
-//  Function: isConsistent
+//  Function: repairConsistency
 //  Class:    SketchSolver_Group
 //  Purpose:  search removed entities and constraints
 // ============================================================================
-bool SketchSolver_Group::isConsistent()
+void SketchSolver_Group::repairConsistency()
 {
-  if (isEmpty()) // 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;
-      }
-  }
-  if (!aResult) {
+  if (!myStorage->isConsistent()) {
     // remove invalid constraints
     std::set<ConstraintPtr> anInvalidConstraints;
     ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
@@ -594,10 +241,10 @@ 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;
 }
 
 // ============================================================================
@@ -608,14 +255,18 @@ bool SketchSolver_Group::isConsistent()
 // ============================================================================
 void SketchSolver_Group::removeTemporaryConstraints()
 {
-  std::set<SolverConstraintPtr>::iterator aTmpIt = myTempConstraints.begin();
-  for (; aTmpIt != myTempConstraints.end(); ++aTmpIt)
-    (*aTmpIt)->remove();
+  if (!myTempConstraints.empty()) {
+    std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(
+        mySketchSolver)->removeConstraint(CID_MOVEMENT);
+
+    std::set<SolverConstraintPtr>::iterator aTmpIt = myTempConstraints.begin();
+    for (; aTmpIt != myTempConstraints.end(); ++aTmpIt)
+      (*aTmpIt)->remove();
+
+    myTempConstraints.clear();
+  }
 
-  if (!myTempConstraints.empty())
-    myStorage->verifyFixed();
   myStorage->setNeedToResolve(false);
-  myTempConstraints.clear();
 }
 
 // ============================================================================
@@ -629,18 +280,10 @@ void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint)
   for (; aCIter != myConstraints.end(); aCIter++)
     if (aCIter->first == theConstraint) {
       aCIter->second->remove(); // the constraint is not fully removed
-      if (aCIter->first->getKind() == SketchPlugin_ConstraintCoincidence::ID())
-        notifyCoincidenceChanged(aCIter->second);
       break;
     }
   if (aCIter != myConstraints.end())
     myConstraints.erase(aCIter);
-  // empty group => clear storage
-  if (myConstraints.empty()) {
-    myStorage = StoragePtr();
-    mySketchSolver = SolverPtr();
-    updateWorkplane();
-  }
 }
 
 // ============================================================================
@@ -653,114 +296,23 @@ void SketchSolver_Group::setTemporary(SolverConstraintPtr theConstraint)
   myTempConstraints.insert(theConstraint);
 }
 
-
 // ============================================================================
-//  Function: checkFeatureValidity
+//  Function: blockEvents
 //  Class:    SketchSolver_Group
-//  Purpose:  verifies is the feature valid
+//  Purpose:  block or unblock events from features in this group
 // ============================================================================
-bool SketchSolver_Group::checkFeatureValidity(FeaturePtr theFeature)
-{
-  if (!theFeature || !theFeature->data()->isValid())
-    return true;
-
-  SessionPtr aMgr = ModelAPI_Session::get();
-  ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
-  return aFactory->validate(theFeature);
-}
-
-
-
-
-// ===========   Auxiliary functions   ========================================
-static double featureToVal(FeaturePtr theFeature)
-{
-  if (theFeature->getKind() == SketchPlugin_Sketch::ID())
-    return 0.0; // sketch
-  ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
-  if (!aConstraint)
-    return 1.0; // features (arc, circle, line, point)
-
-  const std::string& anID = aConstraint->getKind();
-  if (anID == SketchPlugin_ConstraintCoincidence::ID()) {
-    AttributeRefAttrPtr anAttrA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-        aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
-    AttributeRefAttrPtr anAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-        aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
-    if (anAttrA && anAttrB && (anAttrA->isObject() || anAttrB->isObject()))
-      // point-on-line and point-on-circle should go before points coincidence constraint
-      return 2.0;
-    return 2.5;
-  }
-  if (anID == SketchPlugin_ConstraintDistance::ID() ||
-      anID == SketchPlugin_ConstraintLength::ID() ||
-      anID == SketchPlugin_ConstraintRadius::ID())
-    return 3.0;
-  if (anID == SketchPlugin_ConstraintAngle::ID())
-    return 3.5;
-  if (anID == SketchPlugin_ConstraintHorizontal::ID() ||
-      anID == SketchPlugin_ConstraintVertical::ID() ||
-      anID == SketchPlugin_ConstraintParallel::ID() ||
-      anID == SketchPlugin_ConstraintPerpendicular::ID())
-    return 4.0;
-  if (anID == SketchPlugin_ConstraintEqual::ID())
-    return 5.0;
-  if (anID == SketchPlugin_ConstraintTangent::ID() ||
-      anID == SketchPlugin_ConstraintMirror::ID())
-    return 6.0;
-  if (anID == SketchPlugin_ConstraintRigid::ID())
-    return 0.5;
-  if (anID == SketchPlugin_MultiRotation::ID() ||
-      anID == SketchPlugin_MultiTranslation::ID())
-    return 8.0;
-
-  // all other constraints are placed between Equal and Tangent constraints
-  return 5.5;
-}
-
-static bool isLess(FeaturePtr theFeature1, FeaturePtr theFeature2)
+void SketchSolver_Group::blockEvents(bool isBlocked)
 {
-  return featureToVal(theFeature1) < featureToVal(theFeature2);
-}
-
-std::list<FeaturePtr> SketchSolver_Group::
-  selectApplicableFeatures(const std::set<ObjectPtr>& theObjects)
-{
-  std::list<FeaturePtr> aResult;
-  std::list<FeaturePtr>::iterator aResIt;
-
-  std::set<ObjectPtr>::const_iterator anObjIter = theObjects.begin();
-  for (; anObjIter != theObjects.end(); ++anObjIter) {
-    // Operate sketch itself and SketchPlugin features only.
-    // Also, the Fillet and Split need to be skipped,
-    // because there are several separated constraints composing it.
-    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anObjIter);
-    if (!aFeature)
-      continue;
-    std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
-        std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
-    if ((aFeature->getKind() != SketchPlugin_Sketch::ID() && !aSketchFeature) ||
-        aFeature->getKind() == SketchPlugin_ConstraintFillet::ID() ||
-        aFeature->getKind() == SketchPlugin_ConstraintSplit::ID())
-      continue;
-
-    // Find the place where to insert a feature
-    for (aResIt = aResult.begin(); aResIt != aResult.end(); ++aResIt)
-      if (isLess(aFeature, *aResIt))
-        break;
-    aResult.insert(aResIt, aFeature);
-  }
+  if (myIsEventsBlocked == isBlocked)
+    return;
 
-  return aResult;
-}
+  // block/unblock events from the features in the storage
+  myStorage->blockEvents(isBlocked);
 
-void SketchSolver_Group::notifyCoincidenceChanged(SolverConstraintPtr theCoincidence)
-{
-  const std::list<EntityWrapperPtr>& aCoincident = theCoincidence->attributes();
-  EntityWrapperPtr anAttr1 = aCoincident.front();
-  EntityWrapperPtr anAttr2 = aCoincident.back();
+  // block/unblock events from constraints
+  ConstraintConstraintMap::iterator aCIt = myConstraints.begin();
+  for (; aCIt != myConstraints.end(); ++aCIt)
+    aCIt->second->blockEvents(isBlocked);
 
-  ConstraintConstraintMap::iterator anIt = myConstraints.begin();
-  for (; anIt != myConstraints.end(); ++anIt)
-    anIt->second->notifyCoincidenceChanged(anAttr1, anAttr2);
+  myIsEventsBlocked = isBlocked;
 }
index 193e1d54182391bfa0aa62f17d57b7b0f4392d73..c37524fa24663a90803f514199e26a7e3677f4f2 100644 (file)
@@ -7,24 +7,20 @@
 #ifndef SketchSolver_Group_H_
 #define SketchSolver_Group_H_
 
-#include "SketchSolver.h"
 #include <SketchSolver_Constraint.h>
 #include <SketchSolver_Storage.h>
 #include <SketchSolver_ISolver.h>
 
 #include <SketchPlugin_Constraint.h>
-#include <ModelAPI_Feature.h>
 
 #include <memory>
-#include <list>
 #include <map>
-#include <set>
 
 typedef std::map<ConstraintPtr, SolverConstraintPtr> ConstraintConstraintMap;
 
 /** \class   SketchSolver_Group
  *  \ingroup Plugins
- *  \brief   Keeps the group of constraints which based on the same entities
+ *  \brief   Keeps the group of constraints which placed in the same sketch
  */
 class SketchSolver_Group
 {
@@ -33,21 +29,9 @@ class SketchSolver_Group
    *         Throws an exception if theWorkplane is not an object of SketchPlugin_Sketch type
    *  \remark Type of theSketch is not verified inside
    */
-  SketchSolver_Group(std::shared_ptr<ModelAPI_CompositeFeature> theWorkplane);
+  SketchSolver_Group(const CompositeFeaturePtr& theWorkplane);
 
-  ~SketchSolver_Group();
-
-  /// \brief Returns group's unique identifier
-  inline const GroupID& getId() const
-  {
-    return myID;
-  }
-
-  /// \brief Returns identifier of the workplane
-  inline const EntityID& getWorkplaneId() const
-  {
-    return myWorkplaneID;
-  }
+  virtual ~SketchSolver_Group();
 
   /// \brief Returns true if the group has no constraints yet
   inline bool isEmpty() const
@@ -61,12 +45,6 @@ class SketchSolver_Group
     return mySketch->data() && mySketch->data()->isValid();
   }
 
-  /// \brief Check the group has conflicting constraints
-  inline bool isFailed() const
-  {
-    return !myConflictingConstraints.empty();
-  }
-
   /** \brief Adds or updates a constraint in the group
    *  \param[in] theConstraint constraint to be changed
    *  \return \c true if the constraint added or updated successfully
@@ -85,100 +63,52 @@ class SketchSolver_Group
    */
   bool moveFeature(FeaturePtr 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;
-
-  /** \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
-   *  \return \c true if workplanes are the same
-   */
-  bool isBaseWorkplane(CompositeFeaturePtr theWorkplane) const;
-
   /// Returns the current workplane
-  std::shared_ptr<ModelAPI_CompositeFeature> getWorkplane() const
+  inline const CompositeFeaturePtr& getWorkplane() const
   {
     return mySketch;
   }
 
-  /** \brief Update parameters of workplane. Should be called when Update event is coming.
-   *  \return \c true if workplane updated successfully, 
-   *  \c false if workplane parameters are not consistent
-   */
-  bool updateWorkplane();
-
   /** \brief Searches invalid features and constraints in the group and removes them
    *  \return \c false if the group several constraints were removed
    */
-  bool isConsistent();
-
-  /** \brief Add specified group to this one
-   *  \param[in] theGroup group of constraint to be added
-   */
-  void mergeGroups(const SketchSolver_Group& theGroup);
-
-  /** \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 repairConsistency();
 
   /** \brief Start solution procedure if necessary and update attributes of features
    *  \return \c false when no need to solve constraints
    */
   bool resolveConstraints();
 
-  /** \brief Collect all features applicable for the sketch
-   *  \param theObjects  list of features
-   *  \return list of bolted and sorted features
-   */
-  static std::list<FeaturePtr> selectApplicableFeatures(const std::set<ObjectPtr>& theObjects);
+  /// \brief Block or unblock events sent by features in this group
+  void blockEvents(bool isBlocked);
 
-protected:
+private:
   /** \brief Removes constraints from the group
    *  \param[in] theConstraint constraint to be removed
    */
   void removeConstraint(ConstraintPtr theConstraint);
 
-  /// \brief Remove all temporary constraint after computation finished
+  /// \brief Remove all temporary constraints after the computation finished
   void removeTemporaryConstraints();
 
-private:
-  /** \brief Creates a workplane from the sketch parameters
-   *  \param[in] theSketch parameters of workplane are the attributes of this sketch
-   *  \return \c true if success, \c false if workplane parameters are not consistent
-   */
-  bool addWorkplane(CompositeFeaturePtr theSketch);
-
   /// \brief Append given constraint to the group of temporary constraints
   void setTemporary(SolverConstraintPtr theConstraint);
 
-  /// \brief Verifies is the feature valid
-  bool checkFeatureValidity(FeaturePtr theFeature);
-
-  /// \brief Notify all interested constraints that coincidence appears or removed
-  /// \param[in] theCoincidence  coincidence constraint
-  void notifyCoincidenceChanged(SolverConstraintPtr theCoincidence);
-
 private:
-  GroupID  myID; ///< Index of the group
-  EntityID myWorkplaneID; ///< Index of workplane, the group is based on
-  CompositeFeaturePtr mySketch; ///< Sketch is equivalent to workplane
+  CompositeFeaturePtr mySketch; ///< Sketch for this group
   ConstraintConstraintMap myConstraints; ///< List of constraints
   std::set<SolverConstraintPtr> myTempConstraints; ///< List of temporary constraints
 
-  /// List of parametric constraints
-  std::map<AttributePtr, SolverConstraintPtr> myParametricConstraints;
-
   StoragePtr myStorage; ///< Container for the set of SolveSpace constraints and their entities
-
   SolverPtr mySketchSolver;  ///< Solver for set of equations obtained by constraints
 
   /// Result of previous solution of the set of constraints
   SketchSolver_SolveStatus myPrevResult;
   std::set<ObjectPtr>      myConflictingConstraints; ///< List of conflicting constraints
+
+  bool myIsEventsBlocked; ///< shows the events are blocked for this group
 };
 
+typedef std::shared_ptr<SketchSolver_Group> SketchGroupPtr;
+
 #endif
index 12bf834230261837c64ada37ec8be8470e14392d..04b7e917f05fa03c5314311f4c9e869e1803ab9b 100644 (file)
@@ -54,17 +54,11 @@ 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 GroupID group() const = 0;
+  /// \brief Return ID of current constraint
+  const ConstraintID& id() const
+  { return myID; }
+  /// \brief Change constraint ID
+  virtual void setId( const ConstraintID& theID) = 0;
 
   /// \brief Return type of current entity
   virtual SketchSolver_ConstraintType type() const = 0;
@@ -77,11 +71,9 @@ public:
   { return myConstrained; }
 
   /// \brief Assign numeric parameter of constraint
-  virtual void setValue(const double& theValue)
-  { myValue = theValue; }
+  virtual void setValue(const double& theValue) = 0;
   /// \brief Return numeric parameter of constraint
-  const double& value() const
-  { return myValue; }
+  virtual double value() const = 0;
 
   /// \brief Store a boolean flag for full value using
   void setIsFullValue(const bool& theFullValue)
@@ -90,22 +82,9 @@ public:
   const bool& isFullValue() const
   { return myIsFullValue; }
 
-  /// \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;
+  ConstraintID                myID;
   std::list<EntityWrapperPtr> myConstrained;
-  double                      myValue;
   bool                        myIsFullValue;
 };
 
index 15735e73358a4ea15a7d4ae2da0a4a4950349c52..41f561ababe49b81ddf23ef6ce9a9734d699f9f2 100644 (file)
@@ -8,7 +8,6 @@
 #define SketchSolver_IEntityWrapper_H_
 
 #include <SketchSolver.h>
-#include <SketchSolver_IParameterWrapper.h>
 
 #include <ModelAPI_Attribute.h>
 #include <ModelAPI_Feature.h>
@@ -22,11 +21,9 @@ enum SketchSolver_EntityType {
   ENTITY_SCALAR,
   ENTITY_ANGLE,
   ENTITY_POINT,
-  ENTITY_NORMAL,
   ENTITY_LINE,
   ENTITY_CIRCLE,
-  ENTITY_ARC,
-  ENTITY_SKETCH
+  ENTITY_ARC
 };
 
 /**
@@ -35,65 +32,19 @@ enum SketchSolver_EntityType {
 class SketchSolver_IEntityWrapper
 {
 public:
+  SketchSolver_IEntityWrapper() : myExternal(false) {}
   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 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;
+  /// \brief Change flag indicating the entity cannot be changed in the solver
+  void setExternal(bool theExternal) { myExternal = theExternal; }
+  /// \brief Return the External flag
+  bool isExternal() const { return myExternal; }
 
-  std::list<ParameterWrapperPtr>                            myParameters;
-  std::list<std::shared_ptr<SketchSolver_IEntityWrapper> >  mySubEntities;
+private:
+  bool myExternal;
 };
 
 typedef std::shared_ptr<SketchSolver_IEntityWrapper> EntityWrapperPtr;
diff --git a/src/SketchSolver/SketchSolver_IParameterWrapper.h b/src/SketchSolver/SketchSolver_IParameterWrapper.h
deleted file mode 100644 (file)
index 751e346..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 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
index cd525405737336e56b39985edd012189e9797934..c1c21bffa8f7974f7332583e20676d4bba10d528 100644 (file)
@@ -29,10 +29,6 @@ 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; }
@@ -54,7 +50,6 @@ public:
   virtual int dof() const = 0;
 
 protected:
-  GroupID myGroup;       ///< ID of the group to be solved
   bool    myFindFaileds; ///< flag to find conflicting or inappropriate constraints
 };
 
index 80f1f98ef7349e26fcc46d12c48a5fec78a01b5e..0d20365a4d8243ed11af416daa8579fb9a11cd87 100644 (file)
@@ -8,58 +8,26 @@
 #include "SketchSolver_Error.h"
 
 #include <Events_Loop.h>
-
-#include <GeomDataAPI_Point2D.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 <ModelAPI_AttributeInteger.h>
-#include <ModelAPI_AttributeString.h>
-
-#include <SketchPlugin_Constraint.h>
-#include <SketchPlugin_ConstraintAngle.h>
-#include <SketchPlugin_ConstraintCoincidence.h>
-#include <SketchPlugin_ConstraintCollinear.h>
-#include <SketchPlugin_ConstraintDistance.h>
-#include <SketchPlugin_ConstraintEqual.h>
-#include <SketchPlugin_ConstraintHorizontal.h>
-#include <SketchPlugin_ConstraintLength.h>
-#include <SketchPlugin_ConstraintMiddle.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 <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
-#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Point.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
 #include <SketchPlugin_Sketch.h>
-#include <SketchPlugin_Feature.h>
 
-#include <assert.h>
-#include <list>
-#include <set>
-#include <memory>
-#include <sstream>
+/// Global constraint manager object
+static SketchSolver_Manager* myManager = SketchSolver_Manager::instance();
 
-static const Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+/// \brief Verifies is the feature valid
+static bool isFeatureValid(FeaturePtr theFeature)
+{
+  if (!theFeature || !theFeature->data() || !theFeature->data()->isValid())
+    return false;
 
-// Initialization of constraint manager self pointer
-SketchSolver_Manager* SketchSolver_Manager::mySelf = 0;
+  SessionPtr aMgr = ModelAPI_Session::get();
+  ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
+  return aFactory->validate(theFeature);
+}
 
-/// Global constraint manager object
-SketchSolver_Manager* myManager = SketchSolver_Manager::instance();
 
 
 // ========================================================
@@ -67,6 +35,7 @@ SketchSolver_Manager* myManager = SketchSolver_Manager::instance();
 // ========================================================
 SketchSolver_Manager* SketchSolver_Manager::instance()
 {
+  static SketchSolver_Manager* mySelf = 0; // Self pointer to implement singleton functionality
   if (!mySelf)
     mySelf = new SketchSolver_Manager();
   return mySelf;
@@ -79,12 +48,12 @@ SketchSolver_Manager::SketchSolver_Manager()
 
   // Register in event loop
   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
-  Events_Loop::loop()->registerListener(this, anUpdateEvent);
+  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));
 
-  Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_FAILED));
-  Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_REPAIRED));
+  ////Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_FAILED));
+  ////Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_REPAIRED));
   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SKETCH_PREPARED));
 }
 
@@ -115,6 +84,7 @@ bool SketchSolver_Manager::groupMessages()
 void SketchSolver_Manager::processEvent(
   const std::shared_ptr<Events_Message>& theMessage)
 {
+  static const Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
   static const Events_ID aSketchPreparedEvent = Events_Loop::eventByName(EVENT_SKETCH_PREPARED);
   // sketch is prepared for resolve: all the needed events
   // are collected and must be processed by the solver
@@ -123,15 +93,10 @@ void SketchSolver_Manager::processEvent(
     return;
   }
 
-  checkConflictingConstraints(theMessage);
-
   if (myIsComputed)
     return;
   myIsComputed = true;
 
-  // Shows that the message has at least one feature applicable for solver
-  bool hasProperFeature = false;
-
   if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)
       || theMessage->eventID() == anUpdateEvent
       || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) {
@@ -143,45 +108,30 @@ void SketchSolver_Manager::processEvent(
 
     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)) {
-          // Want to avoid recalculation of DoF too frequently.
-          // So, set the flag when the feature is really moved.
-          hasProperFeature = true;
-        }
-      }
-      if (!hasProperFeature)
-        // in this iteration it will compute nothing, so, no problem with recursion
-        // it is important that solver flushes signal updated after processing move signal as there
-        // is optimization that relies on this update, might be found by key "optimization"
-        myIsComputed = false;
-    } 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;
-      }
+
+    // Shows that the message has at least one feature applicable for solver
+    bool hasProperFeature = false;
+
+    // update sketch features only
+    std::set<ObjectPtr>::iterator aFeatIter;
+    for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
+      std::shared_ptr<SketchPlugin_Feature> aFeature =
+          std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+      if (!aFeature || aFeature->isMacro())
+        continue;
+
+      hasProperFeature = updateFeature(aFeature, isMovedEvt) || hasProperFeature;
+    }
+
+    if (isMovedEvt && !hasProperFeature) {
+      // in this iteration it will compute nothing, so, no problem with recursion
+      // it is important that solver flushes signal updated after processing move signal as there
+      // is optimization that relies on this update, might be found by key "optimization"
+      myIsComputed = false;
     }
 
-    bool needToUpdate = false;
     // Solve the set of constraints
-    if (hasProperFeature)
-      needToUpdate = resolveConstraints();
+    bool needToUpdate = resolveConstraints();
 
     // Features may be updated => now send events, but for all changed at once
     if (isUpdateFlushed)
@@ -203,672 +153,111 @@ void SketchSolver_Manager::processEvent(
     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)
+          aFGrIter->compare(ModelAPI_Feature::group()) == 0)
         break;
 
     if (aFGrIter != aFeatureGroups.end()) {
-      hasProperFeature = true;
-      std::list<SketchSolver_Group*> aGroupsToResolve;
-      std::list<SketchSolver_Group*>::iterator aGroupIter = myGroups.begin();
-      std::list<SketchSolver_Group*> aSeparatedGroups;
+      std::list<SketchGroupPtr>::iterator aGroupIter = myGroups.begin();
       while (aGroupIter != myGroups.end()) {
         if (!(*aGroupIter)->isWorkplaneValid()) {  // the group should be removed
-          delete *aGroupIter;
-          std::list<SketchSolver_Group*>::iterator aRemoveIt = aGroupIter++;
+          std::list<SketchGroupPtr>::iterator aRemoveIt = aGroupIter++;
           myGroups.erase(aRemoveIt);
           continue;
         }
-        if (!(*aGroupIter)->isConsistent()) {
-          // some constraints were removed, try to split the group
-          (*aGroupIter)->splitGroup(aSeparatedGroups);
-          if (!(*aGroupIter)->getWorkplane()->string(
-              SketchPlugin_Sketch::SOLVER_ERROR())->value().empty() ||
-              (*aGroupIter)->isFailed())
-            aGroupsToResolve.push_back(*aGroupIter);
-        }
-        aGroupIter++;
-      }
-      if (aSeparatedGroups.size() > 0) {
-        myGroups.insert(myGroups.end(), aSeparatedGroups.begin(), aSeparatedGroups.end());
-        aGroupsToResolve.insert(aGroupsToResolve.end(),
-            aSeparatedGroups.begin(), aSeparatedGroups.end());
-      }
 
-      if (!aGroupsToResolve.empty())
-        resolveConstraints(aGroupsToResolve);
-    }
-    myIsComputed = false;
-  }
-
-  if (hasProperFeature)
-    degreesOfFreedom();
-}
-
-void SketchSolver_Manager::
-  checkConflictingConstraints(const std::shared_ptr<Events_Message>& theMessage)
-{
-  if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_SOLVER_REPAIRED)) {
-    std::shared_ptr<ModelAPI_SolverFailedMessage> aMessage =
-        std::dynamic_pointer_cast<ModelAPI_SolverFailedMessage>(theMessage);
-    std::set<ObjectPtr> aSentObjs = aMessage->objects();
-    if (!aSentObjs.empty()) {
-      // Obtain sketch where the constraints are placed.
-      // It is enough to check only one constraint.
-      CompositeFeaturePtr aSketch;
-      FeaturePtr aConstraint = ModelAPI_Feature::feature(*aSentObjs.begin());
-      std::list<SketchSolver_Group*>::const_iterator aGrIt = myGroups.begin();
-      for (; aGrIt != myGroups.end(); ++aGrIt)
-        if ((*aGrIt)->isInteract(aConstraint)) {
-          aSketch = (*aGrIt)->getWorkplane();
-          break;
-        }
-
-      // Search failed groups built on the same sketch
-      if (aSketch) {
-        for (aGrIt = myGroups.begin(); aGrIt != myGroups.end(); ++aGrIt) {
-          SketchSolver_Group* aGroup = *aGrIt;
-          if (aGroup->isBaseWorkplane(aSketch) && aGroup->isFailed() &&
-              !aGroup->isInteract(aConstraint)) {
-            // reset error message on the sketch
-            aGroup->getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(
-                SketchSolver_Error::CONSTRAINTS());
-            break;
-          }
-        }
+        (*aGroupIter)->repairConsistency();
+        ++aGroupIter;
       }
-    }
-  }
-}
 
-// ============================================================================
-//  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::list<SketchSolver_Group*>::iterator aGroupIter;
-  for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
-    if ((*aGroupIter)->isBaseWorkplane(theSketch)) {
-      isUpdated = true;
-      aResult = false;
+      resolveConstraints();
     }
-  // 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);
+    myIsComputed = false;
   }
-  return aResult || isUpdated;
 }
 
 // ============================================================================
 //  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)
+bool SketchSolver_Manager::updateFeature(std::shared_ptr<SketchPlugin_Feature> theFeature,
+                                         bool theMoved)
 {
-  // Search the groups which this feature touches
-  std::set<GroupID> aGroups;
-  findGroups(theFeature, aGroups);
+  // Check feature validity and find a group to place it.
+  // If the feature is not valid, the returned group will be empty.
+  // This will protect to deal with wrong (not fully initialized) features.
+  SketchGroupPtr aGroup = findGroup(theFeature);
+  if (!aGroup)
+    return false;
+  aGroup->blockEvents(true);
 
   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::list<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::list<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::list<SketchSolver_Group*>::iterator anOtherGroupIter = aFirstGroupIter;
-    ++anOtherGroupIter;
-    for (aGroupsIter++; aGroupsIter != aGroups.end(); aGroupsIter++) {
-      for (; anOtherGroupIter != myGroups.end(); anOtherGroupIter++)
-        if ((*anOtherGroupIter)->getId() == *aGroupsIter)
-          break;
-      if (anOtherGroupIter == myGroups.end()) {  // Group disappears
-        anOtherGroupIter = aFirstGroupIter;
-        ++anOtherGroupIter;
-        continue;
-      }
-
-      (*aFirstGroupIter)->mergeGroups(**anOtherGroupIter);
-      std::list<SketchSolver_Group*>::iterator aRemoveIt = anOtherGroupIter++;
-      delete *aRemoveIt;
-      myGroups.erase(aRemoveIt);
-    }
-
-    if (aConstraint)
-      (*aFirstGroupIter)->changeConstraint(aConstraint);
-    else
-      (*aFirstGroupIter)->updateFeature(theFeature);
-    // groups are merged => need to resolve them
-    return true;
-  }
-
-  // Something goes wrong
-  return false;
-}
-
-// ============================================================================
-//  Function: moveEntity
-//  Purpose:  update element moved on the sketch, which is used by constraints
-// ============================================================================
-bool SketchSolver_Manager::moveEntity(std::shared_ptr<SketchPlugin_Feature> theFeature)
-{
-  bool isMoved = false;
-  std::list<SketchSolver_Group*>::iterator aGroupIt = myGroups.begin();
-  for (; aGroupIt != myGroups.end(); aGroupIt++)
-    if (!(*aGroupIt)->isEmpty() && (*aGroupIt)->isInteract(theFeature))
-      isMoved = (*aGroupIt)->moveFeature(theFeature) || isMoved;
-
-  if (!isMoved && theFeature->getKind() == SketchPlugin_Arc::ID()) {
-    // Workaround to move arc.
-    // If the arc has not been constrained, we will push it into empty group and apply movement.
-    bool hasEmptyGroup = false;
-    for (aGroupIt = myGroups.begin(); aGroupIt != myGroups.end(); aGroupIt++)
-      if ((*aGroupIt)->isEmpty()) {
-        isMoved = (*aGroupIt)->moveFeature(theFeature) || isMoved;
-        hasEmptyGroup = true;
-      }
-    // There is no empty group, create it explicitly
-    if (!hasEmptyGroup) {
-      // find sketch containing the arc
-      CompositeFeaturePtr aWP;
-      const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
-      std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
-      for (; aRefIt != aRefs.end(); ++aRefIt) {
-        FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
-        if (anOwner && anOwner->getKind() == SketchPlugin_Sketch::ID()) {
-          aWP = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(anOwner);
-          break;
-        }
-      }
-      if (aWP) {
-        SketchSolver_Group* aGroup = new SketchSolver_Group(aWP);
-        isMoved = aGroup->moveFeature(theFeature) || isMoved;
-        myGroups.push_back(aGroup);
-      }
-    }
-  }
-  return isMoved;
+  bool isOk = false;
+  if (aConstraint)
+    isOk = aGroup->changeConstraint(aConstraint);
+  else if (theMoved)
+    isOk = aGroup->moveFeature(theFeature);
+  else
+    isOk = aGroup->updateFeature(theFeature);
+  return isOk;
 }
 
 // ============================================================================
-//  Function: findGroups
+//  Function: findGroup
 //  Purpose:  search groups of entities interacting with given feature
 // ============================================================================
-void SketchSolver_Manager::findGroups(
-    std::shared_ptr<SketchPlugin_Feature> theFeature,
-    std::set<GroupID>& theGroupIDs) const
+SketchGroupPtr SketchSolver_Manager::findGroup(
+    std::shared_ptr<SketchPlugin_Feature> theFeature)
 {
-  std::shared_ptr<ModelAPI_CompositeFeature> aWP = findWorkplane(theFeature);
-
-  SketchSolver_Group* anEmptyGroup = 0;  // appropriate empty group for specified constraint
-  std::list<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;
+  if (!isFeatureValid(theFeature))
+    return SketchGroupPtr(); // do not process wrong features
+
+  // Obtain sketch, containing the feature
+  CompositeFeaturePtr aSketch;
+  const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
+  std::set<AttributePtr>::const_iterator aRefIt = aRefsList.begin();
+  for (; aRefIt != aRefsList.end(); ++aRefIt) {
+    FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
+    if (anOwner && anOwner->getKind() == SketchPlugin_Sketch::ID()) {
+      aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(anOwner);
+      break;
     }
+  }
 
-  // When only empty group is found, use it
-  if (anEmptyGroup && theGroupIDs.empty())
-    theGroupIDs.insert(anEmptyGroup->getId());
-}
+  if (!aSketch)
+    return SketchGroupPtr(); // not a sketch's feature
 
-// ============================================================================
-//  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::list<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);
-  }
+  std::list<SketchGroupPtr>::const_iterator aGroupIt;
+  for (aGroupIt = myGroups.begin(); aGroupIt != myGroups.end(); ++aGroupIt)
+    if ((*aGroupIt)->getWorkplane() == aSketch)
+      return *aGroupIt;
 
-  return std::shared_ptr<ModelAPI_CompositeFeature>();
+  // group for the sketch does not created yet
+  SketchGroupPtr aNewGroup = SketchGroupPtr(new SketchSolver_Group(aSketch));
+  myGroups.push_back(aNewGroup);
+  return aNewGroup;
 }
 
 // ============================================================================
 //  Function: resolveConstraints
 //  Purpose:  change entities according to available constraints
 // ============================================================================
-bool SketchSolver_Manager::resolveConstraints(const std::list<SketchSolver_Group*>& theGroups)
+bool SketchSolver_Manager::resolveConstraints()
 {
   bool needToUpdate = false;
-  const std::list<SketchSolver_Group*>& aGroupsToResolve = theGroups.empty() ?
-                                                           myGroups : theGroups;
-  std::list<SketchSolver_Group*>::const_iterator aGroupIter = aGroupsToResolve.begin();
-  for (; aGroupIter != aGroupsToResolve.end(); aGroupIter++)
+  std::list<SketchGroupPtr>::const_iterator aGroupIter = myGroups.begin();
+  for (; aGroupIter != myGroups.end(); ++aGroupIter) {
     if ((*aGroupIter)->resolveConstraints())
       needToUpdate = true;
-  return needToUpdate;
-}
-
-
-// Obtain points and their copies for Mirror, Multi-Rotation and Multi-Translation constraints
-static void collectPointsAndCopies(FeaturePtr theConstraint,
-                                   std::list<std::set<AttributePtr> >& thePoints)
-{
-  typedef std::list<std::string> strlist;
-  static strlist aPointAttributes(1, SketchPlugin_Point::COORD_ID());
-  static strlist aLineAttributes;
-  if (aLineAttributes.empty()) {
-    aLineAttributes.push_back(SketchPlugin_Line::START_ID());
-    aLineAttributes.push_back(SketchPlugin_Line::END_ID());
-  };
-  static strlist aCircleAttributes(1, SketchPlugin_Circle::CENTER_ID());
-  static strlist anArcAttributes;
-  if (anArcAttributes.empty()) {
-    anArcAttributes.push_back(SketchPlugin_Arc::CENTER_ID());
-    anArcAttributes.push_back(SketchPlugin_Arc::START_ID());
-    anArcAttributes.push_back(SketchPlugin_Arc::END_ID());
-  };
-
-  static std::map<std::string, strlist> aFeatureAttributes;
-  if (aFeatureAttributes.empty()) {
-    aFeatureAttributes[SketchPlugin_Point::ID()] = aPointAttributes;
-    aFeatureAttributes[SketchPlugin_Line::ID()] = aLineAttributes;
-    aFeatureAttributes[SketchPlugin_Circle::ID()] = aCircleAttributes;
-    aFeatureAttributes[SketchPlugin_Arc::ID()] = anArcAttributes;
-  }
-
-
-  std::set<AttributePtr> aPoints;
-  if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
-    AttributeRefListPtr aBaseRefList = theConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
-    AttributeRefListPtr aMirrRefList = theConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
-
-    std::list<ObjectPtr> aBaseList = aBaseRefList->list();
-    std::list<ObjectPtr> aMirrList = aMirrRefList->list();
-    std::list<ObjectPtr>::const_iterator aBIt, aMIt;
-    for (aBIt = aBaseList.begin(), aMIt = aMirrList.begin();
-         aBIt != aBaseList.end() && aMIt != aMirrList.end(); ++aBIt, ++aMIt) {
-      FeaturePtr aBaseFeature = ModelAPI_Feature::feature(*aBIt);
-      FeaturePtr aMirrFeature = ModelAPI_Feature::feature(*aMIt);
-
-      strlist anAttrList = aFeatureAttributes[aBaseFeature->getKind()];
-      strlist::iterator anIt = anAttrList.begin();
-      for (; anIt != anAttrList.end(); ++anIt) {
-        aPoints.clear();
-        aPoints.insert(aBaseFeature->attribute(*anIt));
-        aPoints.insert(aMirrFeature->attribute(*anIt));
-        thePoints.push_back(aPoints);
-      }
-    }
-  }
-  else { // the "Multi" constraints
-    std::string aNbObjName;
-    if (theConstraint->getKind() == SketchPlugin_MultiRotation::ID())
-      aNbObjName = SketchPlugin_MultiRotation::NUMBER_OF_OBJECTS_ID();
-    else
-      aNbObjName = SketchPlugin_MultiTranslation::NUMBER_OF_OBJECTS_ID();
-    int aNbCopies = theConstraint->integer(aNbObjName)->value();
-
-    AttributeRefListPtr aRefList = theConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
-    std::list<ObjectPtr> aFullList = aRefList->list();
-    std::list<ObjectPtr>::const_iterator anObjIt = aFullList.begin();
-    std::list<ObjectPtr>::const_iterator aCopyIt;
-    while (anObjIt != aFullList.end()) {
-      FeaturePtr aBaseFeature = ModelAPI_Feature::feature(*anObjIt);
-      strlist anAttrList = aFeatureAttributes[aBaseFeature->getKind()];
-      strlist::iterator anIt = anAttrList.begin();
-      for (; anIt != anAttrList.end(); ++anIt) {
-        aPoints.clear();
-        aCopyIt = anObjIt;
-        for (int i = 0; i < aNbCopies && aCopyIt != aFullList.end(); ++i, ++aCopyIt) {
-          FeaturePtr aFeature = ModelAPI_Feature::feature(*aCopyIt);
-          aPoints.insert(aFeature->attribute(*anIt));
-        }
-        thePoints.push_back(aPoints);
-      }
-      anObjIt = aCopyIt;
-    }
-  }
-}
-
-
-// returns true if the feature is external
-static bool isExternal(const FeaturePtr& theFeature)
-{
-  AttributeSelectionPtr anAttr = theFeature->selection(SketchPlugin_SketchEntity::EXTERNAL_ID());
-  return anAttr && anAttr->context() && !anAttr->isInvalid();
-}
-
-// ============================================================================
-//  Function: degreesOfFreedom
-//  Purpose:  calculate DoFs for each sketch
-// ============================================================================
-void SketchSolver_Manager::degreesOfFreedom()
-{
-  static std::map<std::string, int> aDoFDelta; // indicates how many DoF adds or decreases a feature
-  static bool isNeedInit = true;
-  if (isNeedInit) {
-    aDoFDelta[SketchPlugin_Point::ID()] = 2;
-    aDoFDelta[SketchPlugin_Line::ID()] = 4;
-    aDoFDelta[SketchPlugin_Circle::ID()] = 3;
-    aDoFDelta[SketchPlugin_Arc::ID()] = 5;
-
-    aDoFDelta[SketchPlugin_ConstraintAngle::ID()] = -1;
-    aDoFDelta[SketchPlugin_ConstraintCollinear::ID()] = -1;
-    aDoFDelta[SketchPlugin_ConstraintDistance::ID()] = -1;
-    aDoFDelta[SketchPlugin_ConstraintEqual::ID()] = -1;
-    aDoFDelta[SketchPlugin_ConstraintHorizontal::ID()] = -1;
-    aDoFDelta[SketchPlugin_ConstraintLength::ID()] = -1;
-    aDoFDelta[SketchPlugin_ConstraintParallel::ID()] = -1;
-    aDoFDelta[SketchPlugin_ConstraintPerpendicular::ID()] = -1;
-    aDoFDelta[SketchPlugin_ConstraintRadius::ID()] = -1;
-    aDoFDelta[SketchPlugin_ConstraintTangent::ID()] = -1;
-    aDoFDelta[SketchPlugin_ConstraintVertical::ID()] = -1;
-
-    isNeedInit = false;
-  }
-
-  std::map<CompositeFeaturePtr, int> aSketchDoF;
-
-  std::list<SketchSolver_Group*>::const_iterator aGroupIt = myGroups.begin();
-  for (; aGroupIt != myGroups.end(); ++aGroupIt) {
-    CompositeFeaturePtr aSketch = (*aGroupIt)->getWorkplane();
-    bool isSketchValid = aSketch->data() && aSketch->data()->isValid();
-
-    if (isSketchValid) {
-      std::shared_ptr<GeomDataAPI_Dir> aNormal =
-          std::dynamic_pointer_cast<GeomDataAPI_Dir>(
-          aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
-      isSketchValid = aNormal && aNormal->isInitialized();
-    }
-
-    if (!isSketchValid) {
-      myDoF.erase(aSketch);
-      continue;
-    }
-
-    // check conflicting constraints in the group
-    if ((*aGroupIt)->isFailed())
-      aSketchDoF[aSketch] = -1;
-    // check the sketch is already processed
-    if (aSketchDoF.find(aSketch) != aSketchDoF.end() || aSketchDoF[aSketch] < 0)
-      continue;
-
-    std::set<AttributePtr> aCoincidentPoints;
-    std::set<AttributePtr> aFixedPoints;
-    std::map<AttributePtr, std::set<FeaturePtr> > aPointOnLine;
-    std::list<std::set<AttributePtr> > aPointsInMultiConstraints;
-    int aDoF = 0;
-    int aNbSubs = aSketch->numberOfSubs();
-    for (int i = 0; i < aNbSubs; ++i) {
-      FeaturePtr aFeature = aSketch->subFeature(i);
-      // do not change DoF for external feature
-      if (isExternal(aFeature))
-        continue;
-      // check DoF delta for invariant types
-      std::map<std::string, int>::const_iterator aFound = aDoFDelta.find(aFeature->getKind());
-      if (aFound != aDoFDelta.end()) {
-        aDoF += aFound->second;
-        continue;
-      }
-
-      // DoF delta in specific cases
-      if (aFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
-        AttributePtr aCoincPoint[2] = {AttributePtr(), AttributePtr()};
-        FeaturePtr aCoincLine;
-        for (int j = 0; j < 2; ++j) {
-          AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-              aFeature->attribute(SketchPlugin_Constraint::ATTRIBUTE(j)));
-          if (!aRefAttr)
-            continue;
-          if (!aRefAttr->isObject())
-            aCoincPoint[j] = aRefAttr->attr();
-          else {
-            FeaturePtr anAttr = ModelAPI_Feature::feature(aRefAttr->object());
-            if (!anAttr)
-              continue;
-            if (anAttr->getKind() == SketchPlugin_Point::ID())
-              aCoincPoint[j] = anAttr->attribute(SketchPlugin_Point::COORD_ID());
-            else if (anAttr->getKind() == SketchPlugin_Line::ID())
-              aCoincLine = anAttr;
-          }
-        }
-        if (aCoincPoint[0] && aCoincPoint[1]) {
-          bool isDoFDecreased = false;
-          // point-point coincidence
-          if (aCoincidentPoints.find(aCoincPoint[0]) == aCoincidentPoints.end() ||
-              aCoincidentPoints.find(aCoincPoint[1]) == aCoincidentPoints.end()) {
-            aDoF -= 2;
-            isDoFDecreased = true;
-          }
-          // check the coincident point is used in "multi" constraints
-          std::list<std::set<AttributePtr> >::const_iterator
-              aPtIt = aPointsInMultiConstraints.begin();
-          bool isFound[2] = {false, false};
-          for (; aPtIt != aPointsInMultiConstraints.end(); ++aPtIt) {
-            if ((!isFound[0] && (isFound[0] = (aPtIt->find(aCoincPoint[0]) != aPtIt->end())))
-             || (!isFound[1] && (isFound[1] = (aPtIt->find(aCoincPoint[1]) != aPtIt->end()))))
-              aCoincidentPoints.insert(aPtIt->begin(), aPtIt->end());
-            if (isFound[0] && isFound[1])
-              break;
-          }
-          // check both points are fixed => not need to decrease DoF
-          bool isFixed[2] = { aFixedPoints.find(aCoincPoint[0]) != aFixedPoints.end(),
-                              aFixedPoints.find(aCoincPoint[1]) != aFixedPoints.end() };
-          if (isFixed[0] && isFixed[1] && isDoFDecreased)
-            aDoF += 2; // revert decrease of DoF
-          else if (isFixed[0] && !isFixed[1])
-            aFixedPoints.insert(aCoincPoint[1]);
-          else if (!isFixed[0] && isFixed[1])
-            aFixedPoints.insert(aCoincPoint[0]);
-        } else {
-          aDoF -= 1;
-          if (aCoincPoint[0] && aCoincLine) {
-            // if the point is already coincident to a line
-            // (by middle point constraint), do not decrease DoF
-            std::map<AttributePtr, std::set<FeaturePtr> >::iterator
-                aPtFound = aPointOnLine.find(aCoincPoint[0]);
-            if (aPtFound != aPointOnLine.end() &&
-                aPtFound->second.find(aCoincLine) != aPtFound->second.end())
-              aDoF += 1; // restore value decreased above
-            else
-              aPointOnLine[aCoincPoint[0]].insert(aCoincLine);
-          }
-        }
-        for (int j = 0; j < 2; ++j)
-          if (aCoincPoint[j])
-            aCoincidentPoints.insert(aCoincPoint[j]);
-      }
-      else if (aFeature->getKind() == SketchPlugin_ConstraintMiddle::ID()) {
-        AttributePtr aPoint;
-        FeaturePtr aLine;
-        for (int j = 0; j < 2; ++j) {
-          AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-              aFeature->attribute(SketchPlugin_Constraint::ATTRIBUTE(j)));
-          if (!aRefAttr)
-            continue;
-          if (aRefAttr->isObject())
-            aLine = ModelAPI_Feature::feature(aRefAttr->object());
-          else
-            aPoint = aRefAttr->attr();
-        }
-        if (aPoint && aLine) {
-          // if the point is already on the line, decrease 1 DoF, instead decrease 2 DoF
-          std::map<AttributePtr, std::set<FeaturePtr> >::iterator
-              aPtFound = aPointOnLine.find(aPoint);
-          if (aPtFound != aPointOnLine.end() &&
-              aPtFound->second.find(aLine) != aPtFound->second.end())
-            aDoF -= 1;
-          else {
-            aDoF -= 2;
-            aPointOnLine[aPoint].insert(aLine);
-          }
-        }
-      }
-      else if (aFeature->getKind() == SketchPlugin_ConstraintRigid::ID()) {
-        AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-            aFeature->attribute(SketchPlugin_Constraint::ENTITY_A()));
-        assert(aRefAttr);
-        std::set<AttributePtr> aPoints;
-        if (!aRefAttr->isObject()) {
-          aDoF -= 2; // attribute is a point
-          aPoints.insert(aRefAttr->attr());
-        } else {
-          FeaturePtr anAttr = ModelAPI_Feature::feature(aRefAttr->object());
-          if (anAttr) {
-            if (isExternal(anAttr))
-              continue; // feature is already fixed since it is external
-            aDoF -= aDoFDelta[anAttr->getKind()];
-            std::list<AttributePtr> aPtAttrs =
-              anAttr->data()->attributes(GeomDataAPI_Point2D::typeId());
-            aPoints.insert(aPtAttrs.begin(), aPtAttrs.end());
-          }
-        }
-
-        // Check whether feature's points are already coincident with fixed points.
-        // In this case we need to revert decrease of DoF for these points.
-        // If the coordinates of fixed points are different, it will be processed by solver.
-        for (int k = 0; k < i; ++k) {
-          FeaturePtr aFeature = aSketch->subFeature(k);
-          if (aFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
-            continue;
-          AttributePtr aCoincPoint[2] = {AttributePtr(), AttributePtr()};
-          for (int j = 0; j < 2; ++j) {
-            AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-                aFeature->attribute(SketchPlugin_Constraint::ATTRIBUTE(j)));
-            if (!aRefAttr)
-              continue;
-            if (!aRefAttr->isObject())
-              aCoincPoint[j] = aRefAttr->attr();
-            else {
-              FeaturePtr anAttr = ModelAPI_Feature::feature(aRefAttr->object());
-              if (anAttr && anAttr->getKind() == SketchPlugin_Point::ID())
-                aCoincPoint[j] = anAttr->attribute(SketchPlugin_Point::COORD_ID());
-            }
-          }
-          if (aCoincPoint[0] && aCoincPoint[1]) {
-            if ((aFixedPoints.find(aCoincPoint[0]) != aFixedPoints.end() &&
-                 aPoints.find(aCoincPoint[1]) != aPoints.end()) ||
-                (aFixedPoints.find(aCoincPoint[1]) != aFixedPoints.end() &&
-                 aPoints.find(aCoincPoint[0]) != aPoints.end()))
-              aDoF += 2; // point already fixed
-          }
-        }
-        // store fixed points
-        aFixedPoints.insert(aPoints.begin(), aPoints.end());
-      }
-      else if (aFeature->getKind() == SketchPlugin_ConstraintMirror::ID() ||
-               aFeature->getKind() == SketchPlugin_MultiRotation::ID() ||
-               aFeature->getKind() == SketchPlugin_MultiTranslation::ID()) {
-        int aNbCopies = 1;
-        std::string anAttrName;
-        if (aFeature->getKind() == SketchPlugin_ConstraintMirror::ID())
-          anAttrName = SketchPlugin_Constraint::ENTITY_B();
-        else {
-          if (aFeature->getKind() == SketchPlugin_MultiRotation::ID())
-            aNbCopies =
-            aFeature->integer(SketchPlugin_MultiRotation::NUMBER_OF_OBJECTS_ID())->value() - 1;
-          else if (aFeature->getKind() == SketchPlugin_MultiTranslation::ID())
-            aNbCopies =
-            aFeature->integer(SketchPlugin_MultiTranslation::NUMBER_OF_OBJECTS_ID())->value() - 1;
-          anAttrName = SketchPlugin_Constraint::ENTITY_A();
-        }
-
-        AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-            aFeature->attribute(anAttrName));
-        std::list<ObjectPtr> anObjList = aRefListOfShapes->list();
-        std::list<ObjectPtr>::const_iterator anObjIt = anObjList.begin();
-        for (; anObjIt != anObjList.end(); ++anObjIt) {
-          FeaturePtr aSub = ModelAPI_Feature::feature(*anObjIt);
-          aDoF -= aDoFDelta[aSub->getKind()] * aNbCopies;
-        }
-        // collect points and their copies for correct calculation of DoF for coincident points
-        collectPointsAndCopies(aFeature, aPointsInMultiConstraints);
-      }
-    }
-
-    aSketchDoF[aSketch] = aDoF;
-  }
-
-  // Check the degrees of freedom are changed
-  std::map<CompositeFeaturePtr, int>::const_iterator aDoFIt = aSketchDoF.begin();
-  std::map<CompositeFeaturePtr, int>::iterator aFound;
-  for (; aDoFIt != aSketchDoF.end(); ++aDoFIt) {
-    if (aDoFIt->second < 0)
-      continue; // conflicting constraints on the current sketch
-    aFound = myDoF.find(aDoFIt->first);
-    if (aFound != myDoF.end() && aFound->second == aDoFIt->second)
-      continue; // nothing is changed
-    myDoF[aDoFIt->first] = aDoFIt->second;
-    // change attribute value
-    std::ostringstream aStream;
-    if (aDoFIt->second == 0)
-      aStream << "Sketch fully fixed (DOF = " << aDoFIt->second << ")";
-    else
-      aStream << "DOF (degree of freedom) = " << aDoFIt->second;
-    aDoFIt->first->data()->string(SketchPlugin_Sketch::SOLVER_DOF())->setValue(aStream.str());
+    (*aGroupIter)->blockEvents(false);
   }
+  return needToUpdate;
 }
 
 bool SketchSolver_Manager::stopSendUpdate() const
 {
+static const 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) {
@@ -879,5 +268,5 @@ bool SketchSolver_Manager::stopSendUpdate() const
 
 void SketchSolver_Manager::allowSendUpdate() const
 {
-  Events_Loop::loop()->setFlushed(anUpdateEvent, true);
+  Events_Loop::loop()->setFlushed(Events_Loop::eventByName(EVENT_OBJECT_UPDATED), true);
 }
index c1e853603273d070854a9f1d1a98b0460ae796a6..89a9b7acc77aa4d9edd2960c15ce33df67af22e2 100644 (file)
 /** \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.
+ *           feature into the format understandable by sketch solver.
  *
  *  \remark This is a singleton.
  */
@@ -34,7 +30,7 @@ public:
   /** \brief Main method to create constraint manager
    *  \return pointer to the singleton
    */
-  SKETCHSOLVER_EXPORT static SketchSolver_Manager* instance();
+  static SketchSolver_Manager* instance();
 
   /** \brief Implementation of Event Listener method
    *  \param[in] theMessage the data of the event
@@ -49,7 +45,7 @@ public:
 
   /// \brief Initialize builder for solver's data structure entities
   /// \param theBuilder [in]  solver's specific builder
-  SKETCHSOLVER_EXPORT void setBuilder(BuilderPtr theBuilder);
+  void setBuilder(BuilderPtr theBuilder);
   /// \brief Returns the builder specific for the solver
   BuilderPtr builder();
 
@@ -59,9 +55,10 @@ protected:
 
   /** \brief Adds or updates a constraint or an entity in the suitable group
    *  \param[in] theFeature sketch feature to be changed
+   *  \param[in] theMoved   \c true if the feature has been moved in the viewer
    *  \return \c true if the feature changed successfully
    */
-  bool changeFeature(std::shared_ptr<SketchPlugin_Feature> theFeature);
+  bool updateFeature(std::shared_ptr<SketchPlugin_Feature> theFeature, bool theMoved = false);
 
   /** \brief Removes a constraint from the manager
    *  \param[in] theConstraint constraint to be removed
@@ -69,48 +66,18 @@ protected:
    */
   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
-   *  \return \c true, if the entity has been moved
-   */
-  bool moveEntity(std::shared_ptr<SketchPlugin_Feature> theFeature);
-
   /** \brief Goes through the list of groups and solve the constraints
-   *  \param[in] theGroups  list of groups to be resolved (if empty list, all groups are resolved)
    *  \return \c true, if groups are resolved, and features should be updated 
    *  (send the Update event)
    */
-  bool resolveConstraints(const std::list<SketchSolver_Group*>& theGroups =
-    std::list<SketchSolver_Group*>());
+  bool resolveConstraints();
 
 private:
-  /** \brief Searches list of groups which interact with specified feature
+  /** \brief Searches group 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
+   *  \return Pointer to corresponding group or NULL if the group cannot be created.
    */
-  std::shared_ptr<ModelAPI_CompositeFeature> findWorkplane(
-      std::shared_ptr<SketchPlugin_Feature> theFeature) const;
+  SketchGroupPtr findGroup(std::shared_ptr<SketchPlugin_Feature> theFeature);
 
   /// \brief Stop sending the Update event until all features updated
   /// \return \c true, if the last flushed event is Update
@@ -118,22 +85,12 @@ private:
   /// \brief Allow to send the Update event
   void allowSendUpdate() const;
 
-  /// \brief If the message shows that any group is repaired after conflicting,
-  ///        find other groups on the same sketch, which have conflicts.
-  void checkConflictingConstraints(const std::shared_ptr<Events_Message>& theMessage);
-
-  /// \brief Calculate DoF for each sketch and send messages if changed
-  void degreesOfFreedom();
-
 private:
-  static SketchSolver_Manager*     mySelf;    ///< Self pointer to implement singleton functionality
-  std::list<SketchSolver_Group*>   myGroups;  ///< Groups of constraints
-  BuilderPtr                       myBuilder; ///< Builder for solver's entities
+  std::list<SketchGroupPtr>   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;
-
-  std::map<CompositeFeaturePtr, int> myDoF; ///< Degree of freedom for corresponding sketch
 };
 
 #endif
index d1f6c4f17bbe88a2619731e5bb59c8c854be1183..81714314f264bd8c0b95dbc3d286a9c61752c4c7 100644 (file)
@@ -5,9 +5,9 @@
 // Author:  Artem ZHIDKOV
 
 #include <SketchSolver_Storage.h>
-#include <SketchSolver_Manager.h>
+#include <PlaneGCSSolver_UpdateCoincidence.h>
+#include <PlaneGCSSolver_UpdateFeature.h>
 
-#include <GeomDataAPI_Point2D.h>
 #include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_AttributeRefList.h>
 #include <SketchPlugin_Arc.h>
 #include <SketchPlugin_ConstraintCoincidence.h>
 #include <SketchPlugin_ConstraintMirror.h>
 #include <SketchPlugin_ConstraintRigid.h>
-#include <SketchPlugin_Projection.h>
 
 
-/// \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 Convert result to feature or attribute
-static void resultToFeatureOrAttribute(const ObjectPtr& theResult,
-    FeaturePtr& theFeature, AttributePtr& theAttribute);
-
-
-void SketchSolver_Storage::addConstraint(ConstraintPtr        theConstraint,
-                                         ConstraintWrapperPtr theSolverConstraint)
+SketchSolver_Storage::SketchSolver_Storage(SolverPtr theSolver)
+  : mySketchSolver(theSolver),
+    myNeedToResolve(false),
+    myEventsBlocked(false)
 {
-  if (theSolverConstraint) {
-    std::list<ConstraintWrapperPtr> aConstrList(1, theSolverConstraint);
-    addConstraint(theConstraint, aConstrList);
-  } else
-    addConstraint(theConstraint, std::list<ConstraintWrapperPtr>());
+  // create updaters (constraints processed at first)
+  UpdaterPtr aFeatureUpdater(new PlaneGCSSolver_UpdateFeature);
+  myUpdaters = UpdaterPtr(new PlaneGCSSolver_UpdateCoincidence(aFeatureUpdater));
 }
 
-void SketchSolver_Storage::addConstraint(
-    ConstraintPtr                   theConstraint,
-    std::list<ConstraintWrapperPtr> theSolverConstraints)
+void SketchSolver_Storage::addConstraint(ConstraintPtr        theConstraint,
+                                         ConstraintWrapperPtr theSolverConstraint)
 {
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
+  std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
       aFound = myConstraintMap.find(theConstraint);
-  if (aFound == myConstraintMap.end() || !isEqual(aFound->second, theSolverConstraints))
+  if (aFound == myConstraintMap.end() || aFound->second != theSolverConstraint)
     setNeedToResolve(true);
 
-  if (theSolverConstraints.empty()) {
-    // constraint links to the empty list, add its attributes linked to the empty entities
-    std::list<AttributePtr> aRefAttrs =
-        theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
-    std::list<AttributePtr>::const_iterator anAttrIt = aRefAttrs.begin();
-    for (; anAttrIt != aRefAttrs.end(); ++anAttrIt) {
-      AttributeRefAttrPtr aRef = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIt);
-      if (aRef->isObject()) {
-        FeaturePtr aFeature = ModelAPI_Feature::feature(aRef->object());
-        if (aFeature) addEntity(aFeature, EntityWrapperPtr());
-      } else
-        addEntity(aRef->attr(), EntityWrapperPtr());
-    }
-    std::list<AttributePtr> aRefLists =
-        theConstraint->data()->attributes(ModelAPI_AttributeRefList::typeId());
-    for (anAttrIt = aRefLists.begin(); anAttrIt != aRefLists.end(); ++anAttrIt) {
-      AttributeRefListPtr aRef = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIt);
-      std::list<ObjectPtr> anObj = aRef->list();
-      std::list<ObjectPtr>::iterator anIt = anObj.begin();
-      for (; anIt != anObj.end(); ++anIt) {
-        FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
-        if (aFeature) addEntity(aFeature, EntityWrapperPtr());
-      }
-    }
-  }
-  else if (theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) {
-    // Do not add point-point coincidence, because it is already made by setting
-    // the same parameters for both points
-    std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
-    for (; aCIt != theSolverConstraints.end(); ++aCIt)
-      update(*aCIt);
-  }
-
-  if (!theSolverConstraints.empty() || aFound == myConstraintMap.end())
-    myConstraintMap[theConstraint] = theSolverConstraints;
+////  if (theSolverConstraints.empty()) {
+////    // constraint links to the empty list, add its attributes linked to the empty entities
+////    std::list<AttributePtr> aRefAttrs =
+////        theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
+////    std::list<AttributePtr>::const_iterator anAttrIt = aRefAttrs.begin();
+////    for (; anAttrIt != aRefAttrs.end(); ++anAttrIt) {
+////      AttributeRefAttrPtr aRef = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIt);
+////      if (aRef->isObject()) {
+////        FeaturePtr aFeature = ModelAPI_Feature::feature(aRef->object());
+////        if (aFeature) addEntity(aFeature, EntityWrapperPtr());
+////      } else
+////        addEntity(aRef->attr(), EntityWrapperPtr());
+////    }
+////    std::list<AttributePtr> aRefLists =
+////        theConstraint->data()->attributes(ModelAPI_AttributeRefList::typeId());
+////    for (anAttrIt = aRefLists.begin(); anAttrIt != aRefLists.end(); ++anAttrIt) {
+////      AttributeRefListPtr aRef = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIt);
+////      std::list<ObjectPtr> anObj = aRef->list();
+////      std::list<ObjectPtr>::iterator anIt = anObj.begin();
+////      for (; anIt != anObj.end(); ++anIt) {
+////        FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+////        if (aFeature) addEntity(aFeature, EntityWrapperPtr());
+////      }
+////    }
+////  }
+////  else if (theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) {
+////    // Do not add point-point coincidence, because it is already made by setting
+////    // the same parameters for both points
+////    std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
+////    for (; aCIt != theSolverConstraints.end(); ++aCIt)
+////      update(*aCIt);
+////  }
+
+  if (!theSolverConstraint || aFound == myConstraintMap.end())
+    myConstraintMap[theConstraint] = theSolverConstraint;
   // block events if necessary
   if (myEventsBlocked && theConstraint && theConstraint->data() && theConstraint->data()->isValid())
     theConstraint->data()->blockSendAttributeUpdated(myEventsBlocked);
@@ -115,21 +103,17 @@ static std::list<AttributePtr> pointAttributes(FeaturePtr theFeature)
 void SketchSolver_Storage::addEntity(FeaturePtr       theFeature,
                                      EntityWrapperPtr theSolverEntity)
 {
-  std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
-  if (aFound == myFeatureMap.end() || !aFound->second ||
-     (theSolverEntity && !aFound->second->isEqual(theSolverEntity)))
-    setNeedToResolve(true); // the entity is new or modified
-
-  if (!theSolverEntity) {
+  if (theSolverEntity) {
+    myFeatureMap[theFeature] = theSolverEntity;
+    setNeedToResolve(true);
+  } else {
     // feature links to the empty entity, add its attributes
     std::list<AttributePtr> aPntAttrs = pointAttributes(theFeature);
     std::list<AttributePtr>::const_iterator anAttrIt = aPntAttrs.begin();
     for (; anAttrIt != aPntAttrs.end(); ++anAttrIt)
       addEntity(*anAttrIt, EntityWrapperPtr());
-    if (aFound == myFeatureMap.end())
-      myFeatureMap[theFeature] = theSolverEntity;
-  } else
     myFeatureMap[theFeature] = theSolverEntity;
+  }
 
   // block events if necessary
   if (myEventsBlocked && theFeature->data() && theFeature->data()->isValid())
@@ -139,14 +123,11 @@ void SketchSolver_Storage::addEntity(FeaturePtr       theFeature,
 void SketchSolver_Storage::addEntity(AttributePtr     theAttribute,
                                      EntityWrapperPtr theSolverEntity)
 {
-  std::map<AttributePtr, EntityWrapperPtr>::const_iterator aFound =
-    myAttributeMap.find(theAttribute);
-  if (aFound == myAttributeMap.end() || !aFound->second ||
-     (theSolverEntity && !aFound->second->isEqual(theSolverEntity)))
-    setNeedToResolve(true); // the entity is new or modified
-
-  if (theSolverEntity || aFound == myAttributeMap.end())
+  if (theSolverEntity) {
     myAttributeMap[theAttribute] = theSolverEntity;
+    setNeedToResolve(true);
+  }
+
   // block events if necessary
   if (myEventsBlocked && theAttribute->owner() &&
       theAttribute->owner()->data() && theAttribute->owner()->data()->isValid())
@@ -154,140 +135,13 @@ void SketchSolver_Storage::addEntity(AttributePtr     theAttribute,
 }
 
 
-static bool isCopyInMulti(std::shared_ptr<SketchPlugin_Feature> theFeature,
-    const std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >& theConstraints)
-{
-  if (!theFeature)
-    return false;
-  bool aResult = theFeature->isCopy();
-  if (aResult) {
-    const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
-    for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
-         aRefIt != aRefs.end() && aResult; ++aRefIt) {
-      FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
-      if ((anOwner->getKind() == SketchPlugin_ConstraintMirror::ID() &&
-          (*aRefIt)->id() == SketchPlugin_Constraint::ENTITY_C()) ||
-         (anOwner->getKind() == SketchPlugin_Projection::ID()))
-        aResult = false;
-    }
-  }
-  return aResult;
-}
-
-bool SketchSolver_Storage::update(FeaturePtr theFeature, const GroupID& theGroup, bool theForce)
-{
-  bool isUpdated = false;
-  EntityWrapperPtr aRelated = entity(theFeature);
-  if (!aRelated) { // Feature is not exist, create it
-    std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
-        std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
-    bool isCopy = isCopyInMulti(aSketchFeature, myConstraintMap);
-    // the feature is a copy in "Multi" constraint and does not used in other constraints
-    if (!theForce && isCopy && myFeatureMap.find(theFeature) == myFeatureMap.end())
-      return false;
-
-    std::list<EntityWrapperPtr> aSubs;
-    // Reserve the feature in the map of features (do not want to add several copies of it)
-    myFeatureMap[theFeature] = aRelated;
-    // Firstly, create/update its attributes
-    std::list<AttributePtr> anAttrs = pointAttributes(theFeature);
-    std::list<AttributePtr>::const_iterator anIt = anAttrs.begin();
-    for (; anIt != anAttrs.end(); ++anIt) {
-      if (!(*anIt)->isInitialized())
-        return false;
-      isUpdated = update(*anIt, theGroup, theForce) || isUpdated;
-      aSubs.push_back(entity(*anIt));
-    }
-    // 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, theForce) || isUpdated;
-      aSubs.push_back(entity(aRadius));
-    }
-    // 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);
-    }
-    // Secondly, convert feature
-    BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-    GroupID aGroup = theGroup != GID_UNKNOWN ? theGroup : myGroupID;
-    // Check external feature
-    if (aSketchFeature && (aSketchFeature->isExternal() || isCopy))
-      aGroup = GID_OUTOFGROUP;
-    aRelated = aBuilder->createFeature(theFeature, aSubs, aGroup);
-    if (!aRelated)
-      return false;
-    addEntity(theFeature, aRelated);
-  } else if (theGroup != GID_UNKNOWN)
-    changeGroup(aRelated, theGroup);
-  return update(aRelated) || isUpdated;
-}
-
-bool SketchSolver_Storage::update(AttributePtr theAttribute, const GroupID& theGroup, bool theForce)
-{
-  if (!theAttribute->isInitialized())
-    return false;
-
-  AttributePtr anAttribute = theAttribute;
-  AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
-  if (aRefAttr) {
-    if (aRefAttr->isObject()) {
-      FeaturePtr aFeature;
-      resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute);
-      if (aFeature)
-        return update(aFeature, theGroup, theForce);
-    } else {
-      anAttribute = aRefAttr->attr();
-      if (!anAttribute->isInitialized())
-        return false;
-    }
-  }
-
-  EntityWrapperPtr aRelated = entity(anAttribute);
-  if (!aRelated) { // Attribute is not exist, create it
-    // verify the attribute is a point of arc and add whole arc
-    if (anAttribute->owner()) {
-      FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
-      if (aFeature->getKind() == SketchPlugin_Arc::ID() &&
-          myFeatureMap.find(aFeature) == myFeatureMap.end()) {
-        // Additional checking that all attributes are initialized
-        if (aFeature->attribute(SketchPlugin_Arc::CENTER_ID())->isInitialized() &&
-            aFeature->attribute(SketchPlugin_Arc::START_ID())->isInitialized() &&
-            aFeature->attribute(SketchPlugin_Arc::END_ID())->isInitialized()) {
-          return SketchSolver_Storage::update(aFeature, theGroup, theForce);
-        } else {
-          myFeatureMap[aFeature] = EntityWrapperPtr();
-          myExistArc = true;
-        }
-      }
-    }
-    BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-    GroupID aGroup = theGroup != GID_UNKNOWN ? theGroup : myGroupID;
-    // Check attribute of external features
-    std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
-        std::dynamic_pointer_cast<SketchPlugin_Feature>(anAttribute->owner());
-    if (aSketchFeature && (aSketchFeature->isExternal() ||
-        isCopyInMulti(aSketchFeature, myConstraintMap)))
-      aGroup = GID_OUTOFGROUP;
-    aRelated = aBuilder->createAttribute(anAttribute, aGroup);
-    if (!aRelated)
-      return false;
-    addEntity(anAttribute, aRelated);
-  } else if (theGroup != GID_UNKNOWN)
-    changeGroup(aRelated, theGroup);
-  return update(aRelated);
-}
-
-
 
-const std::list<ConstraintWrapperPtr>& SketchSolver_Storage::constraint(
+const ConstraintWrapperPtr& SketchSolver_Storage::constraint(
     const ConstraintPtr& theConstraint) const
 {
-  static std::list<ConstraintWrapperPtr> aDummy;
+  static ConstraintWrapperPtr aDummy;
 
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr>>::const_iterator
+  std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
       aFound = myConstraintMap.find(theConstraint);
   if (aFound != myConstraintMap.end())
     return aFound->second;
@@ -296,18 +150,16 @@ const std::list<ConstraintWrapperPtr>& SketchSolver_Storage::constraint(
 
 const EntityWrapperPtr& SketchSolver_Storage::entity(const FeaturePtr& theFeature) const
 {
-  static EntityWrapperPtr aDummy;
-
   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
   if (aFound != myFeatureMap.end())
     return aFound->second;
+
+  static EntityWrapperPtr aDummy;
   return aDummy;
 }
 
 const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttribute) const
 {
-  static EntityWrapperPtr aDummy;
-
   std::map<AttributePtr, EntityWrapperPtr>::const_iterator
       aFound = myAttributeMap.find(theAttribute);
   if (aFound != myAttributeMap.end())
@@ -316,471 +168,40 @@ const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttr
   AttributeRefAttrPtr aRefAttr =
       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
   if (aRefAttr) {
+    AttributePtr anAttribute;
+
     if (aRefAttr->isObject()) {
+      /// TODO: Check resultToFeatureOrAttribute() precisely. Create additional unit-test
       FeaturePtr aFeature;
-      AttributePtr anAttribute;
       resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute);
       if (aFeature)
         return entity(aFeature);
-      else
-        return entity(anAttribute);
     } else
-      return entity(aRefAttr->attr());
-  }
-  return aDummy;
-}
-
-bool SketchSolver_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;
-    }
-  }
-  return isFullyRemoved;
-}
-
-template <class ENT_TYPE>
-static bool isUsed(ConstraintWrapperPtr theConstraint, ENT_TYPE theEntity)
-{
-  if (!theConstraint || !theEntity)
-    return false;
-  std::list<EntityWrapperPtr>::const_iterator anEntIt = theConstraint->entities().begin();
-  for (; anEntIt != theConstraint->entities().end(); ++anEntIt)
-    if ((*anEntIt)->isBase(theEntity))
-      return true;
-  return false;
-}
-
-static bool isUsed(EntityWrapperPtr theFeature, AttributePtr theSubEntity)
-{
-  if (!theFeature || !theSubEntity)
-    return false;
-  std::list<EntityWrapperPtr>::const_iterator aSubIt = theFeature->subEntities().begin();
-  for (; aSubIt != theFeature->subEntities().end(); ++aSubIt)
-    if ((*aSubIt)->isBase(theSubEntity))
-      return true;
-  return false;
-}
-
-static bool isUsed(FeaturePtr theFeature, AttributePtr theAttribute)
-{
-  if (!theFeature || !theAttribute)
-    return false;
-  std::list<AttributePtr> anAttrList = theFeature->data()->attributes(std::string());
-  std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
-  for (; anIt != anAttrList.end(); ++anIt) {
-    if (*anIt == theAttribute)
-      return true;
-    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIt);
-    if (aRefAttr && !aRefAttr->isObject() && aRefAttr->attr() == theAttribute)
-      return true;
-  }
-  return false;
-}
-
-bool SketchSolver_Storage::isUsed(FeaturePtr theFeature) const
-{
-  if (myFeatureMap.find(theFeature) != myFeatureMap.end())
-    return true;
-  // check constraints
-  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 = pointAttributes(theFeature);
-  std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
-  for (; anIt != anAttrList.end(); ++anIt)
-    if (isUsed(*anIt))
-      return true;
-  return false;
-}
-
-bool SketchSolver_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();
-  }
-
-  if (myAttributeMap.find(theAttribute) != myAttributeMap.end())
-    return true;
-  // check in constraints
-  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;
-    // Additional check for the Fixed constraints, which have no wrapper associated.
-    if (aCIt->first->getKind() == SketchPlugin_ConstraintRigid::ID() &&
-        ::isUsed(FeaturePtr(aCIt->first), anAttribute))
-      return true;
-  }
-  // check in features
-  std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
-  for (; aFIt != myFeatureMap.end(); ++aFIt)
-    if (::isUsed(aFIt->second, anAttribute))
-      return true;
-  return false;
-}
-
-
-bool SketchSolver_Storage::removeEntity(FeaturePtr theFeature)
-{
-  std::map<FeaturePtr, EntityWrapperPtr>::iterator aFound = myFeatureMap.find(theFeature);
-  if (aFound == myFeatureMap.end())
-    return true; // feature not found, nothing to delete
-
-  EntityWrapperPtr anEntity = aFound->second;
-  myFeatureMap.erase(aFound);
-
-  // Check if the feature is not used by constraints, remove it
-  if (!anEntity || (!isUsed(theFeature) && remove(anEntity)))
-    return true;
-
-  // feature is not removed, revert operation
-  myFeatureMap[theFeature] = anEntity;
-  update(anEntity);
-  return false;
-}
-
-bool SketchSolver_Storage::removeEntity(AttributePtr theAttribute)
-{
-  std::map<AttributePtr, EntityWrapperPtr>::iterator aFound = myAttributeMap.find(theAttribute);
-  if (aFound == myAttributeMap.end())
-    return true; // attribute not found, nothing to delete
-
-  EntityWrapperPtr anEntity = aFound->second;
-  myAttributeMap.erase(aFound);
-
-  // Check if the attribute is not used by constraints and features, remove it
-  if (!anEntity || (!isUsed(theAttribute) && remove(anEntity)))
-    return true;
-
-  // attribute is not removed, revert operation
-  myAttributeMap[theAttribute] = anEntity;
-  update(anEntity);
-  return false;
-}
-
-// Merge groups containing given entities
-static void mergeGroups(std::list<std::set<EntityWrapperPtr> >& theGroups,
-    const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2)
-{
-  std::list<std::set<EntityWrapperPtr> >::iterator aFound1 = theGroups.end();
-  std::list<std::set<EntityWrapperPtr> >::iterator aFound2 = theGroups.end();
-  std::list<std::set<EntityWrapperPtr> >::iterator anIt = theGroups.begin();
-  for (; anIt != theGroups.end() && (aFound1 == theGroups.end() || aFound2 == theGroups.end());
-       ++anIt) {
-    if (anIt->find(theEntity1) != anIt->end())
-      aFound1 = anIt;
-    if (anIt->find(theEntity2) != anIt->end())
-      aFound2 = anIt;
-  }
-
-  if (aFound1 == aFound2 || aFound1 == theGroups.end() || aFound2 == theGroups.end())
-    return; // nothing to merge
-
-  aFound1->insert(aFound2->begin(), aFound2->end());
-  theGroups.erase(aFound2);
-}
-
-bool SketchSolver_Storage::removeCoincidence(ConstraintWrapperPtr theConstraint)
-{
-  std::list<EntityWrapperPtr> aPoints = theConstraint->entities();
-  std::list<EntityWrapperPtr>::const_iterator aPIt;
-
-  CoincidentPointsMap::iterator aPtPtIt = myCoincidentPoints.begin();
-  for (; aPtPtIt != myCoincidentPoints.end(); ++aPtPtIt) {
-    for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt)
-      if (aPtPtIt->first == *aPIt ||
-          aPtPtIt->second.find(*aPIt) != aPtPtIt->second.end())
-        break;
-    if (aPIt != aPoints.end())
-      break;
-  }
-
-  if (aPtPtIt == myCoincidentPoints.end())
-    return true; // already removed
-
-  // Removing of coincidence may split this group of coincident point to several groups.
-  // Find all of them and also the points which become alone.
-  std::list< std::set<EntityWrapperPtr> > aCoincGroups;
-  std::set<EntityWrapperPtr> aGroup;
-  aGroup.insert(aPtPtIt->first);
-  aCoincGroups.push_back(aGroup);
-  std::set<EntityWrapperPtr>::const_iterator aTempIt = aPtPtIt->second.begin();
-  for (; aTempIt != aPtPtIt->second.end(); ++aTempIt) {
-    aGroup.clear();
-    aGroup.insert(*aTempIt);
-    aCoincGroups.push_back(aGroup);
-  }
-
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
-      aConstrIt = myConstraintMap.begin();
-  for (; aConstrIt != myConstraintMap.end(); ++aConstrIt) {
-    if (aConstrIt->first->getKind() != SketchPlugin_ConstraintCoincidence::ID())
-      continue;
-
-    AttributeRefAttrPtr aRefAttr[2] = {
-        aConstrIt->first->refattr(SketchPlugin_Constraint::ENTITY_A()),
-        aConstrIt->first->refattr(SketchPlugin_Constraint::ENTITY_B())
-    };
-    AttributePtr anAttr[2];
-    if (aConstrIt->first->data()->isValid()) {
-      if (!aRefAttr[0] || !aRefAttr[1])
-        continue;
-
-      for (int i = 0; i < 2; ++i) {
-        if (aRefAttr[i]->isObject()) {
-          FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr[i]->object());
-          if (!aFeature || (aFeature->getKind() != SketchPlugin_Point::ID() &&
-              aFeature->getKind() != SketchPlugin_IntersectionPoint::ID()))
-            continue;
-          anAttr[i] = aFeature->attribute(SketchPlugin_Point::COORD_ID());
-        } else
-          anAttr[i] = aRefAttr[i]->attr();
-      }
-    } else {
-      // obtain attributes from the constraint wrapper
-      // if SketchPlugin_Constraint has invalid data (already removed)
-      ConstraintWrapperPtr aWrapper = aConstrIt->second.front();
-      anAttr[0] = aWrapper->entities().front()->baseAttribute();
-      anAttr[1] = aWrapper->entities().back()->baseAttribute();
-    }
-
-    EntityWrapperPtr anEntities[2];
-    for (int i = 0; i < 2; ++i) {
-      std::map<AttributePtr, EntityWrapperPtr>::iterator
-          aFound = myAttributeMap.find(anAttr[i]);
-      if (aFound != myAttributeMap.end())
-        anEntities[i] = aFound->second;
-    }
-    mergeGroups(aCoincGroups, anEntities[0], anEntities[1]);
-  }
 
-  // Collect alone points and build them new instances
-  std::list<EntityWrapperPtr> aShutOffList;
-  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-  std::map<EntityWrapperPtr, EntityWrapperPtr> aNotCoinc;
-  std::list<std::set<EntityWrapperPtr> >::iterator aGroupIt = aCoincGroups.begin();
-  while (aGroupIt != aCoincGroups.end()) {
-    if (aGroupIt->size() == 1) {
-      EntityWrapperPtr aPoint = *aGroupIt->begin();
-      aShutOffList.push_back(aPoint);
-      aNotCoinc[aPoint] =
-          aBuilder->createAttribute(aPoint->baseAttribute(), myGroupID, mySketchID);
-      std::list<std::set<EntityWrapperPtr> >::iterator aRemoveIt = aGroupIt++;
-      aCoincGroups.erase(aRemoveIt);
-    } else // point is not alone
-      ++aGroupIt;
+    return entity(anAttribute);
   }
 
-  if (aNotCoinc.empty() && aCoincGroups.size() == 1)
-    return false;
-
-  // Find all features and constraints uses non-coincident points
-  replaceEntities(aNotCoinc);
-
-  // Remove not coincident points and points in separated groups
-  if (!aCoincGroups.empty()) {
-    aGroupIt = aCoincGroups.begin();
-    for (++aGroupIt; aGroupIt != aCoincGroups.end(); ++aGroupIt)
-      aShutOffList.insert(aShutOffList.end(), aGroupIt->begin(), aGroupIt->end());
-  }
-  std::list<EntityWrapperPtr>::iterator aNotCIt = aShutOffList.begin();
-  for (; aNotCIt != aShutOffList.end(); ++aNotCIt) {
-    if (aPtPtIt->second.size() <= 1) {
-      myCoincidentPoints.erase(aPtPtIt);
-      break;
-    }
-    if (aPtPtIt->first == *aNotCIt) {
-      std::set<EntityWrapperPtr> aSlaves = aPtPtIt->second;
-      EntityWrapperPtr aNewMaster = *aSlaves.begin();
-      aSlaves.erase(aSlaves.begin());
-      myCoincidentPoints.erase(aPtPtIt);
-      myCoincidentPoints[aNewMaster] = aSlaves;
-      aPtPtIt = myCoincidentPoints.find(aNewMaster);
-    } else
-      aPtPtIt->second.erase(*aNotCIt);
-  }
-
-  // Create additional groups of coincident points
-  aGroupIt = aCoincGroups.begin();
-  if (!aCoincGroups.empty())
-    ++aGroupIt;
-  for (; aGroupIt != aCoincGroups.end(); ++aGroupIt) {
-    aNotCoinc.clear();
-    std::set<EntityWrapperPtr>::iterator anEntIt = aGroupIt->begin();
-    for (; anEntIt != aGroupIt->end(); ++anEntIt) {
-      aNotCoinc[*anEntIt] =
-          aBuilder->createAttribute((*anEntIt)->baseAttribute(), myGroupID, mySketchID);
-    }
-    // replace points by newly created
-    replaceEntities(aNotCoinc);
-    // set new group of coincident points
-    EntityWrapperPtr aMasterEnt = aNotCoinc.begin()->second;
-    std::map<EntityWrapperPtr, EntityWrapperPtr>::iterator aNCIt = aNotCoinc.begin();
-    for (++aNCIt; aNCIt != aNotCoinc.end(); ++aNCIt)
-      addCoincidentPoints(aMasterEnt, aNCIt->second);
-  }
-
-  return true;
+  static EntityWrapperPtr aDummy;
+  return aDummy;
 }
 
-void SketchSolver_Storage::replaceEntities(const std::map<EntityWrapperPtr,
-                                           EntityWrapperPtr>& theChange)
-{
-  std::set<EntityWrapperPtr> anUpdFeatures;
-  std::map<EntityWrapperPtr, EntityWrapperPtr>::const_iterator aSubIt;
-  std::map<FeaturePtr, EntityWrapperPtr>::iterator aFIt = myFeatureMap.begin();
-  for (; aFIt != myFeatureMap.end(); ++aFIt) {
-    if (!aFIt->second)
-      continue; // avoid not completed arcs
-    for (aSubIt = theChange.begin(); aSubIt != theChange.end(); ++aSubIt) {
-      if (!aSubIt->second || !::isUsed(aFIt->first, aSubIt->first->baseAttribute()))
-        continue;
-      std::list<EntityWrapperPtr> aSubs = aFIt->second->subEntities();
-      std::list<EntityWrapperPtr>::iterator aSIt = aSubs.begin();
-      bool isUpd = false;
-      for (; aSIt != aSubs.end(); ++aSIt)
-        if (*aSIt == aSubIt->first) {
-          (*aSIt)->update(aSubIt->second);
-          (*aSIt)->setGroup(aFIt->second->group());
-          isUpd = true;
-        }
-      if (isUpd) {
-        aFIt->second->setSubEntities(aSubs);
-        anUpdFeatures.insert(aFIt->second);
-      }
-    }
-  }
-  // update features
-  std::set<EntityWrapperPtr>::iterator anUpdIt = anUpdFeatures.begin();
-  for (; anUpdIt != anUpdFeatures.end(); ++anUpdIt)
-    update(EntityWrapperPtr(*anUpdIt));
-}
 
-bool SketchSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
+void SketchSolver_Storage::removeFeature(FeaturePtr theFeature)
 {
-  bool isFullyRemoved = true;
-  std::list<EntityWrapperPtr>::const_iterator anIt = theConstraint->entities().begin();
-  for (; anIt != theConstraint->entities().end(); ++anIt) {
-    FeaturePtr aBaseFeature = (*anIt)->baseFeature();
-    if (aBaseFeature)
-      isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseFeature) && isFullyRemoved;
-    else
-      isFullyRemoved =
-        SketchSolver_Storage::removeEntity((*anIt)->baseAttribute()) && isFullyRemoved;
-  }
-  return isFullyRemoved;
+  myFeatureMap.erase(theFeature);
 }
 
-bool SketchSolver_Storage::remove(EntityWrapperPtr theEntity)
+void SketchSolver_Storage::removeAttribute(AttributePtr theAttribute)
 {
-  bool isFullyRemoved = true;
-  std::list<EntityWrapperPtr>::const_iterator anEntIt = theEntity->subEntities().begin();
-  for (; anEntIt != theEntity->subEntities().end(); ++anEntIt) {
-    FeaturePtr aBaseFeature = (*anEntIt)->baseFeature();
-    if (aBaseFeature)
-      isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseFeature) && isFullyRemoved;
-    else {
-      AttributePtr aBaseAttr = (*anEntIt)->baseAttribute();
-      if (aBaseAttr)
-        isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseAttr) && isFullyRemoved;
-      else
-        remove(*anEntIt);
-    }
-  }
-
-  std::list<ParameterWrapperPtr>::const_iterator aParIt = theEntity->parameters().begin();
-  for (; aParIt != theEntity->parameters().end(); ++aParIt)
-    isFullyRemoved = remove(*aParIt) && isFullyRemoved;
-  return isFullyRemoved;
+  myAttributeMap.erase(theAttribute);
 }
 
 
-bool SketchSolver_Storage::isInteract(const FeaturePtr& theFeature) const
-{
-  if (!theFeature)
-    return false;
-  if (myConstraintMap.empty())
-    return true; // empty storage interacts with each feature
-
-  ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
-  if (aConstraint) {
-    if (myConstraintMap.find(aConstraint) != myConstraintMap.end())
-      return true;
-  } else if (myFeatureMap.find(theFeature) != myFeatureMap.end())
-    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))
-      return true;
-
-  return false;
-}
-
-bool SketchSolver_Storage::isInteract(const AttributePtr& theAttribute) const
-{
-  if (!theAttribute)
-    return false;
-
-  AttributeRefListPtr aRefList =
-      std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
-  if (aRefList) {
-    std::list<ObjectPtr> anObjects = aRefList->list();
-    std::list<ObjectPtr>::iterator anObjIt = anObjects.begin();
-    for (; anObjIt != anObjects.end(); ++anObjIt) {
-      FeaturePtr aFeature = ModelAPI_Feature::feature(*anObjIt);
-      if (isInteract(aFeature))
-        return true;
-    }
-    return false;
-  }
-
-  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();
-
-  FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
-  return isInteract(aFeature);
-}
-
 bool SketchSolver_Storage::isConsistent() const
 {
   // Check the constraints are valid
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
+  std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
       aCIter = myConstraintMap.begin();
   for (; aCIter != myConstraintMap.end(); ++aCIter)
     if (!aCIter->first->data() || !aCIter->first->data()->isValid())
@@ -793,128 +214,8 @@ bool SketchSolver_Storage::isConsistent() const
   return true;
 }
 
-bool SketchSolver_Storage::isFixed(EntityWrapperPtr theEntity) const
-{
-  if (theEntity->group() != myGroupID)
-    return true;
-  // no need additional checking for entities differ than point
-  if (theEntity->type() != ENTITY_POINT)
-    return false;
-
-  CoincidentPointsMap::const_iterator anIt = myCoincidentPoints.begin();
-  for (; anIt != myCoincidentPoints.end(); ++anIt)
-    if (anIt->first == theEntity || anIt->second.find(theEntity) != anIt->second.end()) {
-      if (anIt->first->group() != myGroupID)
-        return true;
-      std::set<EntityWrapperPtr>::const_iterator anEntIt = anIt->second.begin();
-      for (; anEntIt != anIt->second.end(); ++anEntIt)
-        if ((*anEntIt)->group() != myGroupID)
-          return true;
-    }
-
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator aCIt =
-    myConstraintMap.begin();
-  std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
-  for (; aCIt != myConstraintMap.end(); ++aCIt) {
-    if (aCIt->second.empty())
-      continue;
-    aCWIt = aCIt->second.begin();
-    if ((*aCWIt)->type() != CONSTRAINT_FIXED)
-      continue;
-    for (; aCWIt != aCIt->second.end(); ++aCIt)
-      if ((theEntity->baseAttribute() && (*aCWIt)->isUsed(theEntity->baseAttribute())) ||
-          (theEntity->baseFeature() && (*aCWIt)->isUsed(theEntity->baseFeature())))
-        return true;
-  }
-
-  return false;
-}
-
-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 && aFIt->second->type() == ENTITY_SKETCH)
-      break;
-  if (aFIt == myFeatureMap.end())
-    return aDummySketch;
-  return aFIt->second;
-}
-
-void SketchSolver_Storage::setSketch(const EntityWrapperPtr& theSketch)
-{
-  if (sketch())
-    return;
-  addEntity(FeaturePtr(), theSketch);
-}
-
-void SketchSolver_Storage::processArcs()
-{
-  myExistArc = false;
-  std::map<FeaturePtr, EntityWrapperPtr>::iterator aFIt = myFeatureMap.begin();
-  for (; aFIt != myFeatureMap.end(); ++aFIt)
-    if (!aFIt->second && aFIt->first->getKind() == SketchPlugin_Arc::ID()) {
-      // Additional checking the attributes are initialized
-      if (aFIt->first->attribute(SketchPlugin_Arc::CENTER_ID())->isInitialized() &&
-          aFIt->first->attribute(SketchPlugin_Arc::START_ID())->isInitialized() &&
-          aFIt->first->attribute(SketchPlugin_Arc::END_ID())->isInitialized())
-        update(aFIt->first);
-      else
-        myExistArc = true;
-    }
-}
-
 void SketchSolver_Storage::blockEvents(bool isBlocked)
 {
-  if (isBlocked == myEventsBlocked)
-    return;
-
-  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);
-
   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
   for (; aFIter != myFeatureMap.end(); aFIter++)
     if (aFIter->first->data() && aFIter->first->data()->isValid())
@@ -925,61 +226,47 @@ void SketchSolver_Storage::blockEvents(bool isBlocked)
     if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
         anAtIter->first->owner()->data()->isValid())
       anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
+
   myEventsBlocked = isBlocked;
 }
 
 std::set<ObjectPtr> SketchSolver_Storage::getConflictingConstraints(SolverPtr theSolver) const
 {
   std::set<ObjectPtr> aConflicting;
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
+  std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
       aConstrIt = myConstraintMap.begin();
   for (; aConstrIt != myConstraintMap.end(); ++aConstrIt) {
-    std::list<ConstraintWrapperPtr>::const_iterator anIt = aConstrIt->second.begin();
-    for (; anIt != aConstrIt->second.end(); ++anIt)
-      if (theSolver->isConflicting((*anIt)->id())) {
-        aConflicting.insert(aConstrIt->first);
-        break;
-      }
+    if (theSolver->isConflicting(aConstrIt->second->id())) {
+      aConflicting.insert(aConstrIt->first);
+      break;
+    }
   }
   return aConflicting;
 }
 
+void SketchSolver_Storage::subscribeUpdates(
+    SketchSolver_Constraint* theSubscriber, const std::string& theGroup) const
+{
+  myUpdaters->attach(theSubscriber, theGroup);
+}
 
+void SketchSolver_Storage::unsubscribeUpdates(SketchSolver_Constraint* theSubscriber) const
+{
+  myUpdaters->detach(theSubscriber);
+}
 
-
-
-// ==============   Auxiliary functions   ====================================
-bool isEqual(const std::list<ConstraintWrapperPtr>& theCVec1,
-             const std::list<ConstraintWrapperPtr>& theCVec2)
+void SketchSolver_Storage::notify(const FeaturePtr & theFeature) const
 {
-  if (theCVec1.size() != theCVec2.size())
-    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;
-  }
-  return true;
+  myUpdaters->update(theFeature);
 }
 
-void resultToFeatureOrAttribute(const ObjectPtr& theResult,
+void SketchSolver_Storage::resultToFeatureOrAttribute(const ObjectPtr& theResult,
     FeaturePtr& theFeature, AttributePtr& theAttribute)
 {
   FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);
+  if (!aFeature)
+    return;
+
   // if the feature has several results, we choose which one is referred
   const std::list<ResultPtr>& aResults = aFeature->results();
   if (aResults.size() > 1 && theResult != aFeature->lastResult()) {
index c4dd63ddb7200c0d9a73b108d256dc0d094aed82..8c227cba5e23f8e0c4bc893bf00e5da6b6aeb86f 100644 (file)
 #include <SketchSolver.h>
 #include <SketchSolver_IConstraintWrapper.h>
 #include <SketchSolver_IEntityWrapper.h>
-#include <SketchSolver_IParameterWrapper.h>
 #include <SketchSolver_ISolver.h>
 
+#include <PlaneGCSSolver_UpdateFeature.h>
+
 #include <ModelAPI_Attribute.h>
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_Feature.h>
@@ -30,93 +31,68 @@ typedef std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> > CoincidentPoints
 class SketchSolver_Storage
 {
 private:
-  SketchSolver_Storage();
   SketchSolver_Storage(const SketchSolver_Storage&);
   SketchSolver_Storage& operator=(const SketchSolver_Storage&);
 
 public:
-  SketchSolver_Storage(const GroupID& theGroup)
-    : myGroupID(theGroup),
-      mySketchID(EID_UNKNOWN),
-      myNeedToResolve(false),
-      myEventsBlocked(false),
-      myExistArc(false)
-  {}
+  SketchSolver_Storage(SolverPtr theSolver);
 
   /// \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 virtual
-    void addConstraint(ConstraintPtr                   theConstraint,
-                       std::list<ConstraintWrapperPtr> theSolverConstraints);
+  /// \param theSolverConstraint [in]   solver's constraint
+  virtual void addConstraint(ConstraintPtr        theConstraint,
+                             ConstraintWrapperPtr theSolverConstraint);
+
+  /// \brief Add list of temporary constraints which will be destroyed
+  ///        after the next solving of the set of constraints.
+  /// \param theSolverConstraint [in]  solver's constraint
+  virtual void addTemporaryConstraint(const ConstraintWrapperPtr& theSolverConstraint) = 0;
+
+  /// \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
+  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
+  void addEntity(AttributePtr     theAttribute,
+                 EntityWrapperPtr theSolverEntity);
 
   /// \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
   /// \param theForce   [in]  forced feature creation
   /// \return \c true if the feature has been created or updated
-  SKETCHSOLVER_EXPORT bool update(FeaturePtr theFeature,
-                                  const GroupID& theGroup = GID_UNKNOWN, bool theForce = false);
+  virtual bool update(FeaturePtr theFeature, bool theForce = false) = 0;
 
   /// \brief Convert attribute to the form applicable for specific solver and map it
   /// \param theAttribute [in]  attribute to convert
-  /// \param theGroup     [in]  id of the group where the feature should be placed
   /// \param theForce     [in]  forced feature creation
   /// \return \c true if the attribute has been created or updated
-  SKETCHSOLVER_EXPORT bool update(AttributePtr theAttribute,
-                                  const GroupID& theGroup = GID_UNKNOWN, bool theForce = false);
+  virtual bool update(AttributePtr theAttribute, bool theForce = false) = 0;
 
   /// \brief Returns constraint related to corresponding constraint
-  SKETCHSOLVER_EXPORT
-    const std::list<ConstraintWrapperPtr>& constraint(const ConstraintPtr& theConstraint) const;
+  const ConstraintWrapperPtr& constraint(const ConstraintPtr& theConstraint) const;
 
   /// \brief Returns entity related to corresponding feature
-  SKETCHSOLVER_EXPORT const EntityWrapperPtr& entity(const FeaturePtr& theFeature) const;
+  const EntityWrapperPtr& entity(const FeaturePtr& theFeature) const;
   /// \brief Returns entity related to corresponding attribute
-  SKETCHSOLVER_EXPORT const EntityWrapperPtr& entity(const AttributePtr& 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;
+  const EntityWrapperPtr& entity(const AttributePtr& theAttribute) const;
 
   /// \brief Removes constraint from the storage
   /// \return \c true if the constraint and all its parameters are removed successfully
-  SKETCHSOLVER_EXPORT bool removeConstraint(ConstraintPtr theConstraint);
+  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.
-  SKETCHSOLVER_EXPORT bool removeEntity(FeaturePtr theFeature);
+  void removeFeature(FeaturePtr theFeature);
   /// \brief Removes attribute from the storage
-  /// \return \c true if the attribute is not used by remaining features and constraints
-  SKETCHSOLVER_EXPORT bool removeEntity(AttributePtr theAttribute);
+  void removeAttribute(AttributePtr theAttribute);
 
   /// \brief Remove all features became invalid
-  SKETCHSOLVER_EXPORT void removeInvalidEntities();
-
-  /// \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;
+  virtual void removeInvalidEntities() = 0;
 
   /// \brief Check the features is not removed
   bool isConsistent() const;
@@ -125,10 +101,6 @@ public:
   bool isEmpty() const
   { return myConstraintMap.empty(); }
 
-  /// \brief Check the entity is fixed.
-  ///        If the point is under verification, all coincident points are checked too.
-  SKETCHSOLVER_EXPORT bool isFixed(EntityWrapperPtr theEntity) const;
-
   /// \brief Shows the sketch should be resolved
   virtual bool isNeedToResolve()
   { return myNeedToResolve; }
@@ -137,109 +109,46 @@ public:
   { myNeedToResolve = theFlag; }
 
   /// \brief Initialize solver by constraints, entities and parameters
-  virtual void initializeSolver(SolverPtr theSolver) = 0;
+  virtual void initializeSolver() = 0;
   /// \brief Return list of conflicting constraints
   std::set<ObjectPtr> getConflictingConstraints(SolverPtr theSolver) const;
 
   /// \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;
+  virtual void refresh() const = 0;
 
   /// \brief Block or unblock events when refreshing features
-  SKETCHSOLVER_EXPORT void blockEvents(bool isBlocked);
-  /// \brief Shows the events are blocked for the features in the storage
-  bool isEventsBlocked() const
-  { return myEventsBlocked; }
+  void blockEvents(bool isBlocked);
 
-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 Subscribe for updates of features
+  /// \param theSubscriber [in]  object which wants to revceive notifications
+  /// \param theGroup      [in]  group of updates features to be send
+  void subscribeUpdates(SketchSolver_Constraint* theSubscriber, const std::string& theGroup) const;
+  /// \brief Unsubscribe for updates of features
+  /// \param theSubscriber [in]  object which does not want to revceive notifications anymore
+  void unsubscribeUpdates(SketchSolver_Constraint* theSubscriber) const;
 
-  /// \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 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
-  SKETCHSOLVER_EXPORT virtual bool remove(ConstraintWrapperPtr theConstraint);
-  /// \brief Remove entity
-  /// \return \c true if the entity and all its parameters are removed successfully
-  SKETCHSOLVER_EXPORT virtual bool remove(EntityWrapperPtr theEntity);
-  /// \brief Remove parameter
-  /// \return \c true if the parameter has been removed
-  virtual bool remove(ParameterWrapperPtr theParameter) = 0;
-
-  /// \brief Remove point-point coincidence
-  SKETCHSOLVER_EXPORT bool removeCoincidence(ConstraintWrapperPtr theConstraint);
-
-  /// \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 Verify the feature or any its attribute is used by constraint
-  SKETCHSOLVER_EXPORT bool isUsed(FeaturePtr theFeature) const;
-  /// \brief Verify the attribute is used by constraint
-  SKETCHSOLVER_EXPORT bool isUsed(AttributePtr theAttirubute) const;
-
-  /// \brief Find arcs without corresponding entity applicable for the solver and build them
-  SKETCHSOLVER_EXPORT void processArcs();
+  /// \brief Notify all subscribers about update of the feature
+  void notify(const FeaturePtr& theFeature) const;
 
-  /// \brief Replace entities by others
-  void replaceEntities(const std::map<EntityWrapperPtr, EntityWrapperPtr>& theChange);
-
-private:
-  /// \brief Find the normal of the sketch
-  EntityWrapperPtr getNormal() const;
+protected:
+  /// \brief Convert result to feature or attribute if theResult is linked to center of circle/arc
+  static void resultToFeatureOrAttribute(const ObjectPtr& theResult,
+                                         FeaturePtr&      theFeature,
+                                         AttributePtr&    theAttribute);
 
 protected:
-  EntityID mySketchID;     ///< identifier of the sketch
-  GroupID myGroupID;       ///< identifier of the group, this storage belongs to
+  SolverPtr mySketchSolver; ///< Sketch solver, prepared in corresponding group
   bool    myNeedToResolve; ///< parameters are changed and group needs to be resolved
   bool    myEventsBlocked; ///< indicates that features do not send events
-  bool    myExistArc;      ///< the storage has any point of arc but not full arc, need to add it
 
   /// map SketchPlugin constraint to a list of solver's constraints
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> > myConstraintMap;
+  std::map<ConstraintPtr, ConstraintWrapperPtr> myConstraintMap;
   /// map SketchPlugin feature to solver's entity
-  std::map<FeaturePtr, EntityWrapperPtr>                    myFeatureMap;
+  std::map<FeaturePtr, EntityWrapperPtr>        myFeatureMap;
   /// map attribute to solver's entity
-  std::map<AttributePtr, EntityWrapperPtr>                  myAttributeMap;
-
-  /// lists of coincident points (first is a master point, second is a set of slaves)
-  CoincidentPointsMap myCoincidentPoints;
+  std::map<AttributePtr, EntityWrapperPtr>      myAttributeMap;
 
-  // to be able to update entities from constraints
-  friend class SketchSolver_ConstraintDistance;
-  friend class SketchSolver_ConstraintFixedArcRadius;
+  UpdaterPtr myUpdaters;
 };
 
 typedef std::shared_ptr<SketchSolver_Storage> StoragePtr;