Salome HOME
Angle presentation from NewGEOM_2.0.0. It is moved here to prepare a patch for OCCT...
[modules/shaper.git] / src / SketchSolver / SolveSpaceSolver / SolveSpaceSolver_Storage.cpp
index 04d8fe663bd83c9ddcc48fc26ba3464344b9cb08..d796f7964206c4a6598a9f7dab289f2ac8724ad1 100644 (file)
@@ -19,6 +19,9 @@
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Point2D.h>
 #include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_ConstraintCoincidence.h>
 
 /** \brief Search the entity/parameter with specified ID in the list of elements
  *  \param[in] theEntityID unique ID of the element
@@ -42,12 +45,11 @@ SolveSpaceSolver_Storage::SolveSpaceSolver_Storage(const GroupID& theGroup)
     myParamMaxID(SLVS_E_UNKNOWN),
     myEntityMaxID(SLVS_E_UNKNOWN),
     myConstrMaxID(SLVS_C_UNKNOWN),
-    myFixed(SLVS_E_UNKNOWN),
     myDuplicatedConstraint(false)
 {
 }
 
-bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr& theConstraint)
+bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr theConstraint)
 {
   bool isUpdated = false;
   std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
@@ -73,6 +75,9 @@ bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr& theConstraint)
   std::list<EntityWrapperPtr>::iterator anIt = anEntities.begin();
   for (; anIt != anEntities.end(); ++anIt) {
     isUpdated = update(*anIt) || isUpdated;
+    // do not update constrained entities for Multi constraints
+    if (aSlvsConstr.type == SLVS_C_MULTI_ROTATION || aSlvsConstr.type == SLVS_C_MULTI_TRANSLATION)
+      continue;
 
     Slvs_hEntity anID = (Slvs_hEntity)(*anIt)->id();
     if ((*anIt)->type() == ENTITY_POINT) {
@@ -96,16 +101,20 @@ bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr& theConstraint)
       aSlvsConstr.wrkpl = myWorkplaneID;
     if (aSlvsConstr.group == SLVS_G_UNKNOWN)
       aSlvsConstr.group = (Slvs_hGroup)myGroupID;
+    bool hasDupConstraints = myDuplicatedConstraint;
     Slvs_hConstraint aConstrID = updateConstraint(aSlvsConstr);
     if (aSlvsConstr.h == SLVS_C_UNKNOWN) {
       aConstraint->changeConstraint() = getConstraint(aConstrID);
       isUpdated = true;
+      // check duplicated constraints based on different attributes
+      if (myDuplicatedConstraint && findSameConstraint(aConstraint) && !hasDupConstraints)
+        myDuplicatedConstraint = false;
     }
   }
   return isUpdated;
 }
 
-bool SolveSpaceSolver_Storage::update(EntityWrapperPtr& theEntity)
+bool SolveSpaceSolver_Storage::update(EntityWrapperPtr theEntity)
 {
   bool isUpdated = false;
   std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity = 
@@ -155,6 +164,17 @@ bool SolveSpaceSolver_Storage::update(EntityWrapperPtr& theEntity)
       aSlvsEnt.distance = anID;
     else if (aSlvsEnt.point[anInd] != anID) {
       aSlvsEnt.point[anInd] = anID;
+      if ((*aSIt)->baseAttribute())
+        SketchSolver_Storage::addEntity((*aSIt)->baseAttribute(), *aSIt);
+      isUpdated = true;
+    }
+  }
+  if (theEntity->type() == ENTITY_POINT && aSubEntities.size() == 1) {
+    // theEntity is based on SketchPlugin_Point => need to substitute its attribute instead
+    bool isNew = (aSlvsEnt.h == SLVS_E_UNKNOWN);
+    aSlvsEnt = getEntity(aSlvsEnt.point[0]);
+    if (isNew) {
+      anEntity->changeEntity() = aSlvsEnt;
       isUpdated = true;
     }
   }
@@ -165,17 +185,18 @@ bool SolveSpaceSolver_Storage::update(EntityWrapperPtr& theEntity)
   if (aSlvsEnt.group == SLVS_G_UNKNOWN)
     aSlvsEnt.group = (Slvs_hGroup)myGroupID;
   Slvs_hEntity anEntID = updateEntity(aSlvsEnt);
-  if (aSlvsEnt.h == SLVS_E_UNKNOWN) {
+  if (aSlvsEnt.h == SLVS_E_UNKNOWN || isUpdated) {
     anEntity->changeEntity() = getEntity(anEntID);
     isUpdated = true;
 
     if (anEntity->type() == ENTITY_SKETCH)
       storeWorkplane(anEntity);
   }
+
   return isUpdated;
 }
 
-bool SolveSpaceSolver_Storage::update(ParameterWrapperPtr& theParameter)
+bool SolveSpaceSolver_Storage::update(ParameterWrapperPtr theParameter)
 {
   std::shared_ptr<SolveSpaceSolver_ParameterWrapper> aParameter = 
       std::dynamic_pointer_cast<SolveSpaceSolver_ParameterWrapper>(theParameter);
@@ -253,11 +274,18 @@ void SolveSpaceSolver_Storage::addCoincidentPoints(
 {
   if (theMaster->type() != ENTITY_POINT || theSlave->type() != ENTITY_POINT)
     return;
+  if (!theMaster->subEntities().empty() || !theSlave->subEntities().empty()) {
+    EntityWrapperPtr aSubMaster = theMaster->subEntities().empty() ?
+        theMaster : theMaster->subEntities().front();
+    EntityWrapperPtr aSubSlave = theSlave->subEntities().empty() ?
+        theSlave : theSlave->subEntities().front();
+    return addCoincidentPoints(aSubMaster, aSubSlave);
+  }
 
   // Search available coincidence
   CoincidentPointsMap::iterator aMasterFound = myCoincidentPoints.find(theMaster);
   CoincidentPointsMap::iterator aSlaveFound = myCoincidentPoints.find(theSlave);
-  if (aMasterFound == myCoincidentPoints.end() &&  aSlaveFound == myCoincidentPoints.end()) {
+  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) {
@@ -292,8 +320,9 @@ void SolveSpaceSolver_Storage::addCoincidentPoints(
     replaceInFeatures(theSlave, theMaster);
     replaceInConstraints(theSlave, theMaster);
 
-    // Remove slave entity
-    removeEntity((Slvs_hEntity)theSlave->id());
+    // Remove slave entity (if the IDs are equal no need to remove slave entity, just update it)
+    if (theMaster->id() != theSlave->id())
+      removeEntity((Slvs_hEntity)theSlave->id());
 
     std::shared_ptr<SolveSpaceSolver_EntityWrapper> aPointMaster = 
         std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theMaster);
@@ -311,6 +340,8 @@ void SolveSpaceSolver_Storage::replaceInFeatures(
 {
   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator anIt = myFeatureMap.begin();
   for (; anIt != myFeatureMap.end(); ++anIt) {
+    if (!anIt->second)
+      continue;
     bool isUpdated = false;
     std::list<EntityWrapperPtr> aSubs = anIt->second->subEntities();
     std::list<EntityWrapperPtr>::iterator aSubIt = aSubs.begin();
@@ -346,9 +377,11 @@ void SolveSpaceSolver_Storage::replaceInConstraints(
   std::list<ConstraintWrapperPtr>::const_iterator aCIt;
   for (; anIt != myConstraintMap.end(); ++anIt)
     for (aCIt = anIt->second.begin(); aCIt != anIt->second.end(); ++aCIt) {
-      // Do not process coincidence between points
+      // Do not process coincidence between points and "multi" constraints
       // (these constraints are stored to keep the structure of constraints).
-      if ((*aCIt)->type() == CONSTRAINT_PT_PT_COINCIDENT)
+      if ((*aCIt)->type() == CONSTRAINT_PT_PT_COINCIDENT ||
+          (*aCIt)->type() == CONSTRAINT_MULTI_ROTATION ||
+          (*aCIt)->type() == CONSTRAINT_MULTI_TRANSLATION)
         continue;
 
       bool isUpdated = false;
@@ -365,6 +398,13 @@ void SolveSpaceSolver_Storage::replaceInConstraints(
 
       std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aWrapper =
           std::dynamic_pointer_cast<SolveSpaceSolver_ConstraintWrapper>(*aCIt);
+      if (theSource->id() == theDest->id()) {
+        // No need to update SolveSpace constraint if the entities are the same
+        aWrapper->changeConstraint() = getConstraint((Slvs_hConstraint)aWrapper->id());
+        aWrapper->setEntities(aSubs);
+        continue;
+      }
+
       // change constraint entities
       Slvs_Constraint aConstr = aWrapper->constraint();
       if (aConstr.ptA == (Slvs_hEntity)theSource->id())
@@ -380,8 +420,14 @@ void SolveSpaceSolver_Storage::replaceInConstraints(
             aConstr.ptA == aSlvsCIt->ptA && aConstr.ptB == aSlvsCIt->ptB &&
             aConstr.entityA == aSlvsCIt->entityA && aConstr.entityB == aSlvsCIt->entityB &&
             aConstr.entityC == aSlvsCIt->entityC && aConstr.entityD == aSlvsCIt->entityD) {
-          removeConstraint(aConstr.h);
+          Slvs_hConstraint anIDToRemove = aConstr.h;
           aConstr = *aSlvsCIt;
+          int aShift = aSlvsCIt - myConstraints.begin();
+          removeConstraint(anIDToRemove);
+          aSlvsCIt = myConstraints.begin() + aShift - 1;
+          for (; aSlvsCIt != myConstraints.end(); ++aSlvsCIt)
+            if (aSlvsCIt->h == aConstr.h)
+              break;
           break;
         }
 
@@ -426,6 +472,40 @@ void SolveSpaceSolver_Storage::addSameConstraints(ConstraintWrapperPtr theConstr
   myEqualConstraints.push_back(aNewGroup);
 }
 
+bool SolveSpaceSolver_Storage::findSameConstraint(ConstraintWrapperPtr theConstraint)
+{
+  if (theConstraint->type() == CONSTRAINT_PT_PT_COINCIDENT ||
+      theConstraint->type() == CONSTRAINT_MULTI_ROTATION ||
+      theConstraint->type() == CONSTRAINT_MULTI_TRANSLATION)
+    return false;
+
+  const Slvs_Constraint& aCBase =
+      std::dynamic_pointer_cast<SolveSpaceSolver_ConstraintWrapper>(theConstraint)->constraint();
+
+  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 ((*aCWIt)->type() == CONSTRAINT_PT_PT_COINCIDENT ||
+          (*aCWIt)->type() == CONSTRAINT_MULTI_ROTATION ||
+          (*aCWIt)->type() == CONSTRAINT_MULTI_TRANSLATION)
+        continue;
+      if ((*aCWIt)->type() == theConstraint->type()) {
+        const Slvs_Constraint& aCComp = getConstraint((Slvs_hConstraint)(*aCWIt)->id());
+
+        if (aCBase.ptA == aCComp.ptA && aCBase.ptB == aCComp.ptB &&
+            aCBase.entityA == aCComp.entityA && aCBase.entityB == aCComp.entityB &&
+            aCBase.entityC == aCComp.entityC && aCBase.entityD == aCComp.entityD &&
+            fabs(aCBase.valA -aCComp.valA) < tolerance) {
+          addSameConstraints(*aCWIt, theConstraint);
+          return true;
+        }
+      }
+    }
+  return false;
+}
+
 
 EntityWrapperPtr SolveSpaceSolver_Storage::calculateMiddlePoint(
     EntityWrapperPtr theBase, double theCoeff)
@@ -534,10 +614,8 @@ Slvs_hParam SolveSpaceSolver_Storage::updateParameter(const Slvs_Param& theParam
     // parameter already used, rewrite it
     int aPos = Search(theParam.h, myParameters);
     if (aPos >= 0 && aPos < (int)myParameters.size()) {
-      if (IsNotEqual(myParameters[aPos], theParam)) {
-        myUpdatedParameters.insert(theParam.h);
+      if (IsNotEqual(myParameters[aPos], theParam))
         setNeedToResolve(true);
-      }
       myParameters[aPos] = theParam;
       return theParam.h;
     }
@@ -656,113 +734,11 @@ bool SolveSpaceSolver_Storage::removeEntity(const Slvs_hEntity& theEntityID)
     for (int i = 0; i < 4; i++)
       if (anEntity.param[i] != SLVS_E_UNKNOWN)
         aResult = removeParameter(anEntity.param[i]) && aResult;
-    for (int i = 0; i < 4; i++)
-      if (anEntity.point[i] != SLVS_E_UNKNOWN)
-        aResult = removeEntity(anEntity.point[i]) && aResult;
     myNeedToResolve = true;
   }
   return aResult;
 }
 
-void SolveSpaceSolver_Storage::removeUnusedEntities()
-{
-  std::set<Slvs_hEntity> anUnusedEntities;
-  std::vector<Slvs_Entity>::const_iterator aEIt = myEntities.begin();
-  for (; aEIt != myEntities.end(); ++aEIt) {
-    if (aEIt->h == aEIt->wrkpl) {
-      // don't remove workplane
-      anUnusedEntities.erase(aEIt->point[0]);
-      anUnusedEntities.erase(aEIt->normal);
-      continue;
-    }
-    anUnusedEntities.insert(aEIt->h);
-  }
-
-  std::vector<Slvs_Constraint>::const_iterator aCIt = myConstraints.begin();
-  for (; aCIt != myConstraints.end(); ++aCIt) {
-    Slvs_hEntity aSubs[6] = {
-        aCIt->entityA, aCIt->entityB,
-        aCIt->entityC, aCIt->entityD,
-        aCIt->ptA,     aCIt->ptB};
-    for (int i = 0; i < 6; i++) {
-      if (aSubs[i] != SLVS_E_UNKNOWN) {
-        anUnusedEntities.erase(aSubs[i]);
-        int aPos = Search(aSubs[i], myEntities);
-        if (aPos >= 0 && aPos < (int)myEntities.size()) {
-          for (int j = 0; j < 4; j++)
-            if (myEntities[aPos].point[j] != SLVS_E_UNKNOWN)
-              anUnusedEntities.erase(myEntities[aPos].point[j]);
-          if (myEntities[aPos].distance != SLVS_E_UNKNOWN)
-            anUnusedEntities.erase(myEntities[aPos].distance);
-        }
-      }
-    }
-  }
-
-  std::set<Slvs_hEntity>::const_iterator anEntIt = anUnusedEntities.begin();
-  while (anEntIt != anUnusedEntities.end()) {
-    int aPos = Search(*anEntIt, myEntities);
-    if (aPos < 0 && aPos >= (int)myEntities.size())
-      continue;
-    Slvs_Entity anEntity = myEntities[aPos];
-    // Remove entity if and only if all its parameters unused
-    bool isUsed = false;
-    if (anEntity.distance != SLVS_E_UNKNOWN && 
-      anUnusedEntities.find(anEntity.distance) == anUnusedEntities.end())
-      isUsed = true;
-    for (int i = 0; i < 4 && !isUsed; i++)
-      if (anEntity.point[i] != SLVS_E_UNKNOWN &&
-          anUnusedEntities.find(anEntity.point[i]) == anUnusedEntities.end())
-        isUsed = true;
-    if (isUsed) {
-      anUnusedEntities.erase(anEntity.distance);
-      for (int i = 0; i < 4; i++)
-        if (anEntity.point[i] != SLVS_E_UNKNOWN)
-          anUnusedEntities.erase(anEntity.point[i]);
-      std::set<Slvs_hEntity>::iterator aRemoveIt = anEntIt++;
-      anUnusedEntities.erase(aRemoveIt);
-      continue;
-    }
-    ++anEntIt;
-  }
-
-  for (anEntIt = anUnusedEntities.begin(); anEntIt != anUnusedEntities.end(); ++anEntIt) {
-    int aPos = Search(*anEntIt, myEntities);
-    if (aPos >= 0 && aPos < (int)myEntities.size()) {
-      // Remove entity and its parameters
-      Slvs_Entity anEntity = myEntities[aPos];
-      myEntities.erase(myEntities.begin() + aPos);
-      myEntityMaxID = myEntities.empty() ? SLVS_E_UNKNOWN : myEntities.back().h;
-      if (anEntity.distance != SLVS_E_UNKNOWN)
-        removeParameter(anEntity.distance);
-      for (int i = 0; i < 4; i++)
-        if (anEntity.param[i] != SLVS_E_UNKNOWN)
-          removeParameter(anEntity.param[i]);
-      for (int i = 0; i < 4; i++)
-        if (anEntity.point[i] != SLVS_E_UNKNOWN)
-          removeEntity(anEntity.point[i]);
-    }
-  }
-
-  if (!anUnusedEntities.empty())
-    myNeedToResolve = true;
-}
-
-bool SolveSpaceSolver_Storage::isUsedByConstraints(const Slvs_hEntity& theEntityID) const
-{
-  std::vector<Slvs_Constraint>::const_iterator aCIt = myConstraints.begin();
-  for (; aCIt != myConstraints.end(); ++aCIt) {
-    Slvs_hEntity aSubs[6] = {
-        aCIt->entityA, aCIt->entityB,
-        aCIt->entityC, aCIt->entityD,
-        aCIt->ptA,     aCIt->ptB};
-    for (int i = 0; i < 6; i++)
-      if (aSubs[i] != SLVS_E_UNKNOWN && aSubs[i] == theEntityID)
-        return true;
-  }
-  return false;
-}
-
 const Slvs_Entity& SolveSpaceSolver_Storage::getEntity(const Slvs_hEntity& theEntityID) const
 {
   int aPos = Search(theEntityID, myEntities);
@@ -775,220 +751,6 @@ const Slvs_Entity& SolveSpaceSolver_Storage::getEntity(const Slvs_hEntity& theEn
   return aDummy;
 }
 
-Slvs_hEntity SolveSpaceSolver_Storage::copyEntity(const Slvs_hEntity& theCopied)
-{
-  int aPos = Search(theCopied, myEntities);
-  if (aPos < 0 || aPos >= (int)myEntities.size())
-    return SLVS_E_UNKNOWN;
-
-  Slvs_Entity aCopy = myEntities[aPos];
-  aCopy.h = SLVS_E_UNKNOWN;
-  int i = 0;
-  while (aCopy.point[i] != SLVS_E_UNKNOWN) {
-    aCopy.point[i] = copyEntity(aCopy.point[i]);
-    i++;
-  }
-  if (aCopy.param[0] != SLVS_E_UNKNOWN) {
-    aPos = Search(aCopy.param[0], myParameters);
-    i = 0;
-    while (aCopy.param[i] != SLVS_E_UNKNOWN) {
-      Slvs_Param aNewParam = myParameters[aPos];
-      aNewParam.h = SLVS_E_UNKNOWN;
-      aCopy.param[i] = addParameter(aNewParam);
-      i++;
-      aPos++;
-    }
-  }
-  return addEntity(aCopy);
-}
-
-void SolveSpaceSolver_Storage::copyEntity(const Slvs_hEntity& theFrom, const Slvs_hEntity& theTo)
-{
-  int aPosFrom = Search(theFrom, myEntities);
-  int aPosTo = Search(theTo, myEntities);
-  if (aPosFrom < 0 || aPosFrom >= (int)myEntities.size() || 
-      aPosTo < 0 || aPosTo >= (int)myEntities.size())
-    return;
-
-  Slvs_Entity aEntFrom = myEntities[aPosFrom];
-  Slvs_Entity aEntTo = myEntities[aPosTo];
-  int i = 0;
-  while (aEntFrom.point[i] != SLVS_E_UNKNOWN) {
-    copyEntity(aEntFrom.point[i], aEntTo.point[i]);
-    i++;
-  }
-  if (aEntFrom.param[0] != SLVS_E_UNKNOWN) {
-    aPosFrom = Search(aEntFrom.param[0], myParameters);
-    aPosTo = Search(aEntTo.param[0], myParameters);
-    i = 0;
-    while (aEntFrom.param[i] != SLVS_E_UNKNOWN) {
-      myParameters[aPosTo++].val = myParameters[aPosFrom++].val;
-      i++;
-    }
-  }
-}
-
-
-bool SolveSpaceSolver_Storage::isPointFixed(
-    const Slvs_hEntity& thePointID, Slvs_hConstraint& theFixed, bool theAccurate) const
-{
-  // Search the set of coincident points
-  std::set<Slvs_hEntity> aCoincident;
-  aCoincident.insert(thePointID);
-
-  // Check whether one of coincident points is out-of-group
-  std::set<Slvs_hEntity>::const_iterator aCoincIt = aCoincident.begin();
-  for (; aCoincIt != aCoincident.end(); ++aCoincIt) {
-    Slvs_Entity aPoint = getEntity(*aCoincIt);
-    if (aPoint.group == SLVS_G_OUTOFGROUP)
-      return true;
-  }
-
-  // Search the Rigid constraint
-  theFixed = SLVS_C_UNKNOWN;
-  std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
-  for (; aConstrIter != myConstraints.end(); aConstrIter++)
-    if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
-        aCoincident.find(aConstrIter->ptA) != aCoincident.end()) {
-      theFixed = aConstrIter->h;
-      if (aConstrIter->ptA == thePointID)
-        return true;
-    }
-  if (theFixed != SLVS_C_UNKNOWN)
-    return true;
-
-  if (theAccurate) {
-    // Try to find the fixed entity which uses such point or its coincidence
-    std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
-    for (; anEntIter != myEntities.end(); anEntIter++) {
-      for (int i = 0; i < 4; i++) {
-        Slvs_hEntity aPt = anEntIter->point[i];
-        if (aPt != SLVS_E_UNKNOWN &&
-            (aPt == thePointID || aCoincident.find(aPt) != aCoincident.end())) {
-          if (isEntityFixed(anEntIter->h, true))
-            return true;
-        }
-      }
-    }
-  }
-  return SLVS_E_UNKNOWN;
-}
-
-bool SolveSpaceSolver_Storage::isEntityFixed(const Slvs_hEntity& theEntityID, bool theAccurate) const
-{
-  int aPos = Search(theEntityID, myEntities);
-  if (aPos < 0 || aPos >= (int)myEntities.size())
-    return false;
-
-  // Firstly, find how many points are under Rigid constraint
-  int aNbFixed = 0;
-  for (int i = 0; i < 4; i++) {
-    Slvs_hEntity aPoint = myEntities[aPos].point[i];
-    if (aPoint == SLVS_E_UNKNOWN)
-      continue;
-
-    std::set<Slvs_hEntity> aCoincident;
-    aCoincident.insert(aPoint);
-
-    // Search the Rigid constraint
-    std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
-    for (; aConstrIter != myConstraints.end(); aConstrIter++)
-      if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
-          aCoincident.find(aConstrIter->ptA) != aCoincident.end())
-        aNbFixed++;
-  }
-
-  std::list<Slvs_Constraint> aList;
-  std::list<Slvs_Constraint>::iterator anIt;
-  Slvs_hConstraint aTempID; // used in isPointFixed() method
-
-  if (myEntities[aPos].type == SLVS_E_LINE_SEGMENT) {
-    if (aNbFixed == 2)
-      return true;
-    else if (aNbFixed == 0 || !theAccurate)
-      return false;
-    // Additional check (the line may be fixed if it is used by different constraints):
-    // 1. The line is used in Equal constraint, another entity is fixed and there is a fixed point on line
-    aList = getConstraintsByType(SLVS_C_PT_ON_LINE);
-    for (anIt = aList.begin(); anIt != aList.end(); anIt++)
-      if (anIt->entityA == theEntityID && isPointFixed(anIt->ptA, aTempID))
-        break;
-    if (anIt != aList.end()) {
-      aList = getConstraintsByType(SLVS_C_EQUAL_LENGTH_LINES);
-      aList.splice(aList.end(), getConstraintsByType(SLVS_C_EQUAL_LINE_ARC_LEN));
-      for (anIt = aList.begin(); anIt != aList.end(); anIt++)
-        if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
-          Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
-          if (isEntityFixed(anOther, false))
-            return true;
-        }
-    }
-    // 2. The line is used in Parallel/Perpendicular/Vertical/Horizontal and Length constraints
-    aList = getConstraintsByType(SLVS_C_PARALLEL);
-    aList.splice(aList.end(), getConstraintsByType(SLVS_C_PERPENDICULAR));
-    aList.splice(aList.end(), getConstraintsByType(SLVS_C_VERTICAL));
-    aList.splice(aList.end(), getConstraintsByType(SLVS_C_HORIZONTAL));
-    for (anIt = aList.begin(); anIt != aList.end(); anIt++)
-      if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
-        Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
-        if (isEntityFixed(anOther, false))
-          break;
-      }
-    if (anIt != aList.end()) {
-      aList = getConstraintsByType(SLVS_C_PT_PT_DISTANCE);
-      for (anIt = aList.begin(); anIt != aList.end(); anIt++)
-        if ((anIt->ptA == myEntities[aPos].point[0] && anIt->ptB == myEntities[aPos].point[1]) ||
-            (anIt->ptA == myEntities[aPos].point[1] && anIt->ptB == myEntities[aPos].point[0]))
-          return true;
-    }
-    // 3. Another verifiers ...
-  } else if (myEntities[aPos].type == SLVS_E_CIRCLE) {
-    if (aNbFixed == 0)
-      return false;
-    // Search for Diameter constraint
-    aList = getConstraintsByType(SLVS_C_DIAMETER);
-    for (anIt = aList.begin(); anIt != aList.end(); anIt++)
-      if (anIt->entityA == theEntityID)
-        return true;
-    if (!theAccurate)
-      return false;
-    // Additional check (the circle may be fixed if it is used by different constraints):
-    // 1. The circle is used in Equal constraint and another entity is fixed
-    aList = getConstraintsByType(SLVS_C_EQUAL_RADIUS);
-    for (anIt = aList.begin(); anIt != aList.end(); anIt++)
-      if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
-        Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
-        if (isEntityFixed(anOther, false))
-          return true;
-      }
-    // 2. Another verifiers ...
-  } else if (myEntities[aPos].type == SLVS_E_ARC_OF_CIRCLE) {
-    if (aNbFixed > 2)
-      return true;
-    else if (aNbFixed <= 1)
-      return false;
-    // Search for Diameter constraint
-    aList = getConstraintsByType(SLVS_C_DIAMETER);
-    for (anIt = aList.begin(); anIt != aList.end(); anIt++)
-      if (anIt->entityA == theEntityID)
-        return true;
-    if (!theAccurate)
-      return false;
-    // Additional check (the arc may be fixed if it is used by different constraints):
-    // 1. The arc is used in Equal constraint and another entity is fixed
-    aList = getConstraintsByType(SLVS_C_EQUAL_RADIUS);
-    aList.splice(aList.end(), getConstraintsByType(SLVS_C_EQUAL_LINE_ARC_LEN));
-    for (anIt = aList.begin(); anIt != aList.end(); anIt++)
-      if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
-        Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
-        if (isEntityFixed(anOther, false))
-          return true;
-      }
-    // 2. Another verifiers ...
-  }
-  return false;
-}
-
 
 Slvs_hConstraint SolveSpaceSolver_Storage::addConstraint(const Slvs_Constraint& theConstraint)
 {
@@ -1006,8 +768,10 @@ Slvs_hConstraint SolveSpaceSolver_Storage::addConstraint(const Slvs_Constraint&
       continue;
     if (aConstraint.ptA == aCIt->ptA && aConstraint.ptB == aCIt->ptB &&
         aConstraint.entityA == aCIt->entityA && aConstraint.entityB == aCIt->entityB &&
-        aConstraint.entityC == aCIt->entityC && aConstraint.entityD == aCIt->entityD)
+        aConstraint.entityC == aCIt->entityC && aConstraint.entityD == aCIt->entityD) {
       myDuplicatedConstraint = true;
+      break;
+    }
   }
 
   if (aConstraint.h > myConstrMaxID)
@@ -1034,46 +798,42 @@ Slvs_hConstraint SolveSpaceSolver_Storage::updateConstraint(const Slvs_Constrain
   // Constraint is not found, add new one
   Slvs_Constraint aConstraint = theConstraint;
   aConstraint.h = 0;
+
+  // Firstly, check middle-point constraint conflicts with point-on-line
+  if (aConstraint.type == SLVS_C_AT_MIDPOINT) {
+    std::vector<Slvs_Constraint>::const_iterator anIt = myConstraints.begin();
+    for (; anIt != myConstraints.end(); ++anIt)
+      if (anIt->type == SLVS_C_PT_ON_LINE &&
+          anIt->ptA == aConstraint.ptA &&
+          anIt->entityA == aConstraint.entityA)
+        break;
+    if (anIt != myConstraints.end()) {
+      // change the constraint to the lengths equality to avoid conflicts
+      Slvs_Entity aLine = getEntity(aConstraint.entityA);
+      Slvs_Entity aNewLine1 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroupID,
+          myWorkplaneID, aLine.point[0], aConstraint.ptA);
+      aNewLine1.h = addEntity(aNewLine1);
+      Slvs_Entity aNewLine2 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroupID,
+          myWorkplaneID, aLine.point[1], aConstraint.ptA);
+      aNewLine2.h = addEntity(aNewLine2);
+      aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroupID, SLVS_C_EQUAL_LENGTH_LINES,
+          myWorkplaneID, 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aNewLine1.h, aNewLine2.h);
+    }
+  }
+
   return addConstraint(aConstraint);
 }
 
 bool SolveSpaceSolver_Storage::removeConstraint(const Slvs_hConstraint& theConstraintID)
 {
-  bool aResult = true;
   int aPos = Search(theConstraintID, myConstraints);
   if (aPos >= 0 && aPos < (int)myConstraints.size()) {
     Slvs_Constraint aConstraint = myConstraints[aPos];
     myConstraints.erase(myConstraints.begin() + aPos);
     myConstrMaxID = myConstraints.empty() ? SLVS_E_UNKNOWN : myConstraints.back().h;
     myNeedToResolve = true;
-
-    // Remove all entities
-    Slvs_hEntity anEntities[6] = {aConstraint.ptA, aConstraint.ptB,
-        aConstraint.entityA, aConstraint.entityB,
-        aConstraint.entityC, aConstraint.entityD};
-    for (int i = 0; i < 6; i++)
-      if (anEntities[i] != SLVS_E_UNKNOWN)
-        aResult = removeEntity(anEntities[i]) && aResult;
-    // remove temporary fixed point, if available
-    if (myFixed == theConstraintID)
-      myFixed = SLVS_E_UNKNOWN;
-    if (myDuplicatedConstraint) {
-      // Check the duplicated constraints are still available
-      myDuplicatedConstraint = false;
-      std::vector<Slvs_Constraint>::const_iterator anIt1 = myConstraints.begin();
-      std::vector<Slvs_Constraint>::const_iterator anIt2 = myConstraints.begin();
-      for (; anIt1 != myConstraints.end() && !myDuplicatedConstraint; anIt1++)
-        for (anIt2 = anIt1+1; anIt2 != myConstraints.end() && !myDuplicatedConstraint; anIt2++) {
-          if (anIt1->type != anIt2->type)
-            continue;
-          if (anIt1->ptA == anIt2->ptA && anIt1->ptB == anIt2->ptB &&
-              anIt1->entityA == anIt2->entityA && anIt1->entityB == anIt2->entityB &&
-              anIt1->entityC == anIt2->entityC && anIt1->entityD == anIt2->entityD)
-            myDuplicatedConstraint = true;
-        }
-    }
   }
-  return aResult;
+  return true;
 }
 
 const Slvs_Constraint& SolveSpaceSolver_Storage::getConstraint(const Slvs_hConstraint& theConstraintID) const
@@ -1088,87 +848,6 @@ const Slvs_Constraint& SolveSpaceSolver_Storage::getConstraint(const Slvs_hConst
   return aDummy;
 }
 
-std::list<Slvs_Constraint> SolveSpaceSolver_Storage::getConstraintsByType(int theConstraintType) const
-{
-  std::list<Slvs_Constraint> aResult;
-  std::vector<Slvs_Constraint>::const_iterator aCIter = myConstraints.begin();
-  for (; aCIter != myConstraints.end(); aCIter++)
-    if (aCIter->type == theConstraintType)
-      aResult.push_back(*aCIter);
-  return aResult;
-}
-
-
-void SolveSpaceSolver_Storage::addConstraintWhereDragged(const Slvs_hConstraint& theConstraintID)
-{
-  if (myFixed != SLVS_E_UNKNOWN)
-    return; // the point is already fixed
-  int aPos = Search(theConstraintID, myConstraints);
-  if (aPos >= 0 && aPos < (int)myConstraints.size())
-    myFixed = theConstraintID;
-}
-
-void SolveSpaceSolver_Storage::addTemporaryConstraint(const Slvs_hConstraint& theConstraintID)
-{
-  myTemporaryConstraints.insert(theConstraintID);
-}
-
-void SolveSpaceSolver_Storage::removeAllTemporary()
-{
-  myTemporaryConstraints.clear();
-}
-
-size_t SolveSpaceSolver_Storage::removeTemporary(size_t theNbConstraints)
-{
-  if (myTemporaryConstraints.empty())
-    return 0;
-  // Search the point-on-line or a non-rigid constraint
-  std::set<Slvs_hConstraint>::iterator aCIt = myTemporaryConstraints.begin();
-  for (; aCIt != myTemporaryConstraints.end(); aCIt++) {
-    int aPos = Search(*aCIt, myConstraints);
-    if (aPos >= (int)myConstraints.size() || myConstraints[aPos].type != SLVS_C_WHERE_DRAGGED)
-      break;
-    std::vector<Slvs_Constraint>::iterator anIt = myConstraints.begin();
-    for (; anIt != myConstraints.end(); anIt++)
-      if (anIt->type == SLVS_C_PT_ON_LINE && anIt->ptA == myConstraints[aPos].ptA)
-        break;
-    if (anIt != myConstraints.end())
-      break;
-  }
-  if (aCIt == myTemporaryConstraints.end())
-    aCIt = myTemporaryConstraints.begin();
-  bool aNewFixed = false;
-
-  size_t aNbRemain = theNbConstraints;
-  while (aNbRemain > 0 && aCIt != myTemporaryConstraints.end()) {
-    aNewFixed = aNewFixed || (*aCIt == myFixed);
-    --aNbRemain;
-
-    std::set<Slvs_hConstraint>::iterator aRemoveIt = aCIt++;
-    removeConstraint(*aRemoveIt);
-    myTemporaryConstraints.erase(aRemoveIt);
-    if (aCIt == myTemporaryConstraints.end())
-      aCIt = myTemporaryConstraints.begin();
-  }
-
-  if (aNewFixed) {
-    for (aCIt = myTemporaryConstraints.begin(); aCIt != myTemporaryConstraints.end(); aCIt++) {
-      int aPos = Search(*aCIt, myConstraints);
-      if (myConstraints[aPos].type == SLVS_C_WHERE_DRAGGED) {
-        myFixed = *aCIt;
-        break;
-      }
-    }
-  }
-  return myTemporaryConstraints.size();
-}
-
-bool SolveSpaceSolver_Storage::isTemporary(const Slvs_hConstraint& theConstraintID) const
-{
-  return myTemporaryConstraints.find(theConstraintID) != myTemporaryConstraints.end();
-}
-
-
 
 void SolveSpaceSolver_Storage::initializeSolver(SolverPtr theSolver)
 {
@@ -1177,6 +856,9 @@ void SolveSpaceSolver_Storage::initializeSolver(SolverPtr theSolver)
   if (!aSolver)
     return;
 
+  if (myExistArc)
+    processArcs();
+
   if (myConstraints.empty()) {
     // Adjust all arc to place their points correctly
     std::vector<Slvs_Entity>::const_iterator anEntIt = myEntities.begin();
@@ -1187,511 +869,180 @@ void SolveSpaceSolver_Storage::initializeSolver(SolverPtr theSolver)
 
   aSolver->setParameters(myParameters.data(), (int)myParameters.size());
   aSolver->setEntities(myEntities.data(), (int)myEntities.size());
-
-  // Copy constraints excluding the fixed one
-  std::vector<Slvs_Constraint> aConstraints = myConstraints;
-  if (myFixed != SLVS_E_UNKNOWN) {
-    Slvs_hEntity aFixedPoint = SLVS_E_UNKNOWN;
-    std::vector<Slvs_Constraint>::iterator anIt = aConstraints.begin();
-    for (; anIt != aConstraints.end(); anIt++)
-      if (anIt->h == myFixed) {
-        aFixedPoint = anIt->ptA;
-        aConstraints.erase(anIt);
-        break;
-      }
-    // set dragged parameters
-    int aPos = Search(aFixedPoint, myEntities);
-    aSolver->setDraggedParameters(myEntities[aPos].param);
-  }
-  aSolver->setConstraints(aConstraints.data(), (int)aConstraints.size());
-}
-
-
-bool SolveSpaceSolver_Storage::isEqual(
-    const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const
-{
-  // Precise checking of coincidence: verify that points have equal coordinates
-  int aEnt1Pos = Search(thePoint1, myEntities);
-  int aEnt2Pos = Search(thePoint2, myEntities);
-  if (aEnt1Pos >= 0 && aEnt1Pos < (int)myEntities.size() &&
-      aEnt2Pos >= 0 && aEnt2Pos < (int)myEntities.size()) {
-    double aDist[2];
-    int aParamPos;
-    for (int i = 0; i < 2; i++) {
-      aParamPos = Search(myEntities[aEnt1Pos].param[i], myParameters);
-      aDist[i] = myParameters[aParamPos].val;
-      aParamPos = Search(myEntities[aEnt2Pos].param[i], myParameters);
-      aDist[i] -= myParameters[aParamPos].val;
-    }
-    if (aDist[0] * aDist[0] + aDist[1] * aDist[1] < tolerance * tolerance)
-      return true;
-  }
-  return false;
+  aSolver->setConstraints(myConstraints.data(), (int)myConstraints.size());
 }
 
 
-std::vector<Slvs_hConstraint> SolveSpaceSolver_Storage::fixEntity(const Slvs_hEntity& theEntity)
+bool SolveSpaceSolver_Storage::removeCoincidence(ConstraintWrapperPtr theConstraint)
 {
-  std::vector<Slvs_hConstraint> aNewConstraints;
-
-  int aPos = Search(theEntity, myEntities);
-  if (aPos >= 0 && aPos < (int)myEntities.size()) {
-    switch (myEntities[aPos].type) {
-    case SLVS_E_POINT_IN_2D:
-    case SLVS_E_POINT_IN_3D:
-      fixPoint(myEntities[aPos], aNewConstraints);
-      break;
-    case SLVS_E_LINE_SEGMENT:
-      fixLine(myEntities[aPos], aNewConstraints);
-      break;
-    case SLVS_E_CIRCLE:
-      fixCircle(myEntities[aPos], aNewConstraints);
-      break;
-    case SLVS_E_ARC_OF_CIRCLE:
-      fixArc(myEntities[aPos], aNewConstraints);
-      break;
-    default:
+  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;
-    }
-  }
-
-  return aNewConstraints;
-}
-
-void SolveSpaceSolver_Storage::fixPoint(const Slvs_Entity& thePoint,
-    std::vector<Slvs_hConstraint>& theCreated)
-{
-  Slvs_Constraint aConstraint;
-  Slvs_hConstraint aConstrID = SLVS_E_UNKNOWN;
-  bool isFixed = isPointFixed(thePoint.h, aConstrID, true);
-  bool isForceUpdate = (isFixed && isTemporary(aConstrID));
-  if (!isForceUpdate) { // create new constraint
-    if (isFixed) return;
-    aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, thePoint.group, SLVS_C_WHERE_DRAGGED, thePoint.wrkpl,
-        0.0, thePoint.h, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-    aConstraint.h = addConstraint(aConstraint);
-    theCreated.push_back(aConstraint.h);
-  } else { // update already existent constraint
-    if (!isFixed || aConstrID == SLVS_E_UNKNOWN)
-      return;
-    int aPos = Search(aConstrID, myConstraints);
-    if (aPos >= 0 && aPos < (int)myConstraints.size())
-      myConstraints[aPos].ptA = thePoint.h;
   }
-}
 
-void SolveSpaceSolver_Storage::fixLine(const Slvs_Entity& theLine,
-    std::vector<Slvs_hConstraint>& theCreated)
-{
-  Slvs_Entity aPoint[2] = {
-      getEntity(theLine.point[0]),
-      getEntity(theLine.point[1])
-  };
-
-  Slvs_Constraint anEqual;
-  if (isAxisParallel(theLine.h)) {
-    // Fix one point and a line length
-    Slvs_hConstraint aFixed;
-    if (!isPointFixed(theLine.point[0], aFixed, true) &&
-        !isPointFixed(theLine.point[1], aFixed, true))
-      fixPoint(aPoint[0], theCreated);
-    if (!isUsedInEqual(theLine.h, anEqual)) {
-      // Check the distance is not set yet
-      std::vector<Slvs_Constraint>::const_iterator aDistIt = myConstraints.begin();
-      for (; aDistIt != myConstraints.end(); ++aDistIt)
-        if ((aDistIt->type == SLVS_C_PT_PT_DISTANCE) &&
-           ((aDistIt->ptA == theLine.point[0] && aDistIt->ptB == theLine.point[1]) ||
-            (aDistIt->ptA == theLine.point[1] && aDistIt->ptB == theLine.point[0])))
-          return;
-      // Calculate distance between points on the line
-      double aCoords[4];
-      for (int i = 0; i < 2; i++)
-        for (int j = 0; j < 2; j++) {
-          Slvs_Param aParam = getParameter(aPoint[i].param[j]);
-          aCoords[2*i+j] = aParam.val;
-        }
-
-      double aLength = sqrt((aCoords[2] - aCoords[0]) * (aCoords[2] - aCoords[0]) + 
-                            (aCoords[3] - aCoords[1]) * (aCoords[3] - aCoords[1]));
-      // fix line length
-      Slvs_Constraint aDistance = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theLine.group,
-          SLVS_C_PT_PT_DISTANCE, theLine.wrkpl, aLength,
-          theLine.point[0], theLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-      aDistance.h = addConstraint(aDistance);
-      theCreated.push_back(aDistance.h);
-    }
-    return;
-  }
-  else if (isUsedInEqual(theLine.h, anEqual)) {
-    // Check another entity of Equal is already fixed
-    Slvs_hEntity anOtherEntID = anEqual.entityA == theLine.h ? anEqual.entityB : anEqual.entityA;
-    if (isEntityFixed(anOtherEntID, true)) {
-      // Fix start point of the line (if end point is not fixed yet) ...
-      Slvs_hConstraint anEndFixedID = SLVS_E_UNKNOWN;
-      bool isFixed = isPointFixed(theLine.point[1], anEndFixedID, true);
-      if (isFixed == SLVS_E_UNKNOWN)
-        fixPoint(aPoint[0], theCreated);
-      // ...  and create fixed point lying on this line
-      Slvs_hEntity aPointToCopy = anEndFixedID == SLVS_E_UNKNOWN ? theLine.point[1] : theLine.point[0];
-      // Firstly, search already fixed point on line
-      bool isPonLineFixed = false;
-      Slvs_hEntity aFixedPoint;
-      std::vector<Slvs_Constraint>::const_iterator aPLIter = myConstraints.begin();
-      for (; aPLIter != myConstraints.end() && !isPonLineFixed; ++aPLIter)
-        if (aPLIter->type == SLVS_C_PT_ON_LINE && aPLIter->entityA == theLine.h) {
-          isPonLineFixed = isPointFixed(aPLIter->ptA, anEndFixedID);
-          aFixedPoint = aPLIter->ptA;
-        }
+  if (aPtPtIt == myCoincidentPoints.end())
+    return true; // already removed
 
-      if (isPonLineFixed) { // update existent constraint
-        copyEntity(aPointToCopy, aFixedPoint);
-      } else { // create new constraint
-        Slvs_hEntity aCopied = copyEntity(aPointToCopy);
-        Slvs_Constraint aPonLine = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theLine.group, SLVS_C_PT_ON_LINE,
-            theLine.wrkpl, 0.0, aCopied, SLVS_E_UNKNOWN, theLine.h, SLVS_E_UNKNOWN);
-        aPonLine.h = addConstraint(aPonLine);
-        theCreated.push_back(aPonLine.h);
-        fixPoint(getEntity(aCopied), theCreated);
-      }
-      return;
+  // Create new copies of coincident points
+  BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
+  std::list<EntityWrapperPtr> aNewPoints;
+  for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt)
+    aNewPoints.push_back(aBuilder->createAttribute(
+        (*aPIt)->baseAttribute(), myGroupID, myWorkplaneID));
+
+  // Find all points fallen out of group of coincident points
+  std::map<EntityWrapperPtr, EntityWrapperPtr> aNotCoinc;
+  aNotCoinc[aPtPtIt->first] = EntityWrapperPtr();
+  std::set<EntityWrapperPtr>::const_iterator aTempIt = aPtPtIt->second.begin();
+  for (; aTempIt != aPtPtIt->second.end(); ++aTempIt)
+    aNotCoinc[*aTempIt] = EntityWrapperPtr();
+  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
+      aConstrIt = myConstraintMap.begin();
+  for (; aConstrIt != myConstraintMap.end(); ++aConstrIt)
+    if (aConstrIt->first->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
+      AttributeRefAttrPtr aRefAttrA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+          aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_A()));
+      AttributeRefAttrPtr aRefAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+          aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_B()));
+      if (!aRefAttrA || !aRefAttrB || aRefAttrA->isObject() || aRefAttrB->isObject())
+        continue;
+      std::map<AttributePtr, EntityWrapperPtr>::iterator
+          aFound = myAttributeMap.find(aRefAttrA->attr());
+      if (aFound != myAttributeMap.end())
+        aNotCoinc.erase(aFound->second);
+      aFound = myAttributeMap.find(aRefAttrB->attr());
+      if (aFound != myAttributeMap.end())
+        aNotCoinc.erase(aFound->second);
     }
+  if (aNotCoinc.empty())
+    return false;
+  std::list<EntityWrapperPtr>::const_iterator aNewPIt;
+  for (aPIt = aPoints.begin(), aNewPIt = aNewPoints.begin();
+       aPIt != aPoints.end(); ++aPIt, ++aNewPIt) {
+    if (aNotCoinc.find(*aPIt) != aNotCoinc.end())
+      aNotCoinc[*aPIt] = *aNewPIt;
   }
 
-  // Fix both points
-  for (int i = 0; i < 2; i++)
-    fixPoint(aPoint[i], theCreated);
-}
-
-void SolveSpaceSolver_Storage::fixCircle(const Slvs_Entity& theCircle,
-    std::vector<Slvs_hConstraint>& theCreated)
-{
-  bool isFixRadius = true;
-  // Verify the arc is under Equal constraint
-  Slvs_Constraint anEqual;
-  if (isUsedInEqual(theCircle.h, anEqual)) {
-    // Check another entity of Equal is already fixed
-    Slvs_hEntity anOtherEntID = anEqual.entityA == theCircle.h ? anEqual.entityB : anEqual.entityA;
-    if (isEntityFixed(anOtherEntID, true))
-      isFixRadius = false;
-  }
-
-  fixPoint(getEntity(theCircle.point[0]), theCreated);
-
-  if (isFixRadius) {
-    // Search the radius is already fixed
-    std::vector<Slvs_Constraint>::const_iterator aDiamIter = myConstraints.begin();
-    for (; aDiamIter != myConstraints.end(); ++aDiamIter)
-      if (aDiamIter->type == SLVS_C_DIAMETER && aDiamIter->entityA == theCircle.h)
-        return;
-
-    // Fix radius of a circle
-    const Slvs_Entity& aRadEnt = getEntity(theCircle.distance);
-    double aRadius = getParameter(aRadEnt.param[0]).val;
-    Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theCircle.group, SLVS_C_DIAMETER,
-        theCircle.wrkpl, aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, theCircle.h, SLVS_E_UNKNOWN);
-    aFixedR.h = addConstraint(aFixedR);
-    theCreated.push_back(aFixedR.h);
-  }
-}
-
-void SolveSpaceSolver_Storage::fixArc(const Slvs_Entity& theArc,
-    std::vector<Slvs_hConstraint>& theCreated)
-{
-  Slvs_Entity aPoint[3] = {
-      getEntity(theArc.point[0]),
-      getEntity(theArc.point[1]),
-      getEntity(theArc.point[2])
-  };
-
-  bool isFixRadius = true;
-  std::list<Slvs_Entity> aPointsToFix;
-  aPointsToFix.push_back(aPoint[1]);
-  aPointsToFix.push_back(aPoint[2]);
-
-  // Verify the arc is under Equal constraint
-  Slvs_Constraint anEqual;
-  if (isUsedInEqual(theArc.h, anEqual)) {
-    // Check another entity of Equal is already fixed
-    Slvs_hEntity anOtherEntID = anEqual.entityA == theArc.h ? anEqual.entityB : anEqual.entityA;
-    if (isEntityFixed(anOtherEntID, true)) {
-      isFixRadius = false;
-      Slvs_Entity anOtherEntity = getEntity(anOtherEntID);
-      if (anOtherEntity.type == SLVS_E_LINE_SEGMENT) {
-        aPointsToFix.pop_back();
-        aPointsToFix.push_back(aPoint[0]);
+  // Find all features and constraints uses coincident points
+  std::map<EntityWrapperPtr, EntityWrapperPtr>::iterator aNotCIt;
+  std::set<EntityWrapperPtr> anUpdFeatures;
+  std::map<FeaturePtr, EntityWrapperPtr>::iterator aFIt = myFeatureMap.begin();
+  for (; aFIt != myFeatureMap.end(); ++aFIt) {
+    if (!aFIt->second)
+      continue; // avoid not completed arcs
+    for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) {
+      if (!aNotCIt->second || !aFIt->second->isUsed(aNotCIt->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 == aNotCIt->first) {
+          *aSIt = aNotCIt->second;
+          isUpd = true;
+        }
+      if (isUpd) {
+        aFIt->second->setSubEntities(aSubs);
+        anUpdFeatures.insert(aFIt->second);
       }
     }
   }
-
-  Slvs_hConstraint aConstrID;
-  int aNbPointsToFix = 2; // number of fixed points for the arc
-  if (isPointFixed(theArc.point[0], aConstrID, true))
-    aNbPointsToFix--;
-
-  double anArcPoints[3][2];
-  for (int i = 0; i < 3; i++) {
-    const Slvs_Entity& aPointOnArc = getEntity(theArc.point[i]);
-    for (int j = 0; j < 2; j++)
-      anArcPoints[i][j] = getParameter(aPointOnArc.param[j]).val;
-  }
-
-  // Radius of the arc
-  std::shared_ptr<GeomAPI_Pnt2d> aCenter(new GeomAPI_Pnt2d(anArcPoints[0][0], anArcPoints[0][1]));
-  std::shared_ptr<GeomAPI_Pnt2d> aStart(new GeomAPI_Pnt2d(anArcPoints[1][0], anArcPoints[1][1]));
-  double aRadius = aCenter->distance(aStart);
-
-  // Update end point of the arc to be on a curve
-  std::shared_ptr<GeomAPI_Pnt2d> anEnd(new GeomAPI_Pnt2d(anArcPoints[2][0], anArcPoints[2][1]));
-  double aDistance = anEnd->distance(aCenter);
-  std::shared_ptr<GeomAPI_XY> aDir = anEnd->xy()->decreased(aCenter->xy());
-  if (aDistance < tolerance)
-    aDir = aStart->xy()->decreased(aCenter->xy())->multiplied(-1.0);
-  else
-    aDir = aDir->multiplied(aRadius / aDistance);
-  double xy[2] = {aCenter->x() + aDir->x(), aCenter->y() + aDir->y()};
-  const Slvs_Entity& aEndPoint = getEntity(theArc.point[2]);
-  for (int i = 0; i < 2; i++) {
-    Slvs_Param aParam = getParameter(aEndPoint.param[i]);
-    aParam.val = xy[i];
-    updateParameter(aParam);
-  }
-
-  std::list<Slvs_Entity>::iterator aPtIt = aPointsToFix.begin();
-  for (; aNbPointsToFix > 0; aPtIt++, aNbPointsToFix--)
-    fixPoint(*aPtIt, theCreated);
-
-  if (isFixRadius) {
-    // Fix radius of the arc
-    bool isExists = false;
-    std::vector<Slvs_Constraint>::iterator anIt = myConstraints.begin();
-    for (; anIt != myConstraints.end() && !isExists; ++anIt)
-      if (anIt->type == SLVS_C_DIAMETER && anIt->entityA == theArc.h)
-        isExists = true;
-    if (!isExists) {
-      Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theArc.group, SLVS_C_DIAMETER,
-          theArc.wrkpl, aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, theArc.h, SLVS_E_UNKNOWN);
-      aFixedR.h = addConstraint(aFixedR);
-      theCreated.push_back(aFixedR.h);
-    }
-  }
-}
-
-
-bool SolveSpaceSolver_Storage::isAxisParallel(const Slvs_hEntity& theEntity) const
-{
-  std::vector<Slvs_Constraint>::const_iterator anIter = myConstraints.begin();
-  for (; anIter != myConstraints.end(); anIter++)
-    if ((anIter->type == SLVS_C_HORIZONTAL || anIter->type == SLVS_C_VERTICAL) && 
-        anIter->entityA == theEntity)
-      return true;
-  return false;
-}
-
-bool SolveSpaceSolver_Storage::isUsedInEqual(
-    const Slvs_hEntity& theEntity, Slvs_Constraint& theEqual) const
-{
-  // Check the entity is used in Equal constraint
-  std::vector<Slvs_Constraint>::const_iterator anEqIter = myConstraints.begin();
-  for (; anEqIter != myConstraints.end(); anEqIter++)
-    if ((anEqIter->type == SLVS_C_EQUAL_LENGTH_LINES ||
-         anEqIter->type == SLVS_C_EQUAL_LINE_ARC_LEN ||
-         anEqIter->type == SLVS_C_EQUAL_RADIUS) &&
-       (anEqIter->entityA == theEntity || anEqIter->entityB == theEntity)) {
-      theEqual = *anEqIter;
-      return true;
-    }
-  return false;
-}
-
-void SolveSpaceSolver_Storage::setTemporary(ConstraintPtr theConstraint)
-{
-  // TODO
-}
-
-bool SolveSpaceSolver_Storage::removeConstraint(ConstraintPtr theConstraint)
-{
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
-      aFound = myConstraintMap.find(theConstraint);
-  if (aFound == myConstraintMap.end())
-    return true; // no constraint, already deleted
-
-  // Remove constraint
-  std::list<ConstraintWrapperPtr> aConstrList = aFound->second;
-  myConstraintMap.erase(aFound);
-  // Remove SolveSpace constraints
-  bool isFullyRemoved = true;
-  std::list<ConstraintWrapperPtr>::iterator anIt = aConstrList.begin();
-  while (anIt != aConstrList.end()) {
-    if (remove(*anIt)) {
-      std::list<ConstraintWrapperPtr>::iterator aRemoveIt = anIt++;
-      aConstrList.erase(aRemoveIt);
-    } else {
-      isFullyRemoved = false;
-      ++anIt;
+  // update features
+  std::set<EntityWrapperPtr>::iterator anUpdIt = anUpdFeatures.begin();
+  for (; anUpdIt != anUpdFeatures.end(); ++anUpdIt)
+    update(EntityWrapperPtr(*anUpdIt));
+
+  // remove not coincident points
+  for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) {
+    if (aPtPtIt->second.size() <= 1) {
+      myCoincidentPoints.erase(aPtPtIt);
+      break;
     }
+    if (aPtPtIt->first == aNotCIt->first) {
+      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->first);
   }
-  if (!isFullyRemoved)
-    myConstraintMap[theConstraint] = aConstrList;
-  return isFullyRemoved;
-}
-
-template <class ENT_TYPE>
-static bool isUsed(ConstraintWrapperPtr theConstraint, ENT_TYPE theEntity)
-{
-  std::list<EntityWrapperPtr>::const_iterator anEntIt = theConstraint->entities().begin();
-  for (; anEntIt != theConstraint->entities().end(); ++anEntIt)
-    if (std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anEntIt)->isBase(theEntity))
-      return true;
-  return false;
-}
-
-static bool isUsed(EntityWrapperPtr theFeature, AttributePtr theSubEntity)
-{
-  std::list<EntityWrapperPtr>::const_iterator aSubIt = theFeature->subEntities().begin();
-  for (; aSubIt != theFeature->subEntities().end(); ++aSubIt)
-    if (std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*aSubIt)->isBase(theSubEntity))
-      return true;
-  return false;
-}
-
-bool SolveSpaceSolver_Storage::isUsed(FeaturePtr theFeature) const
-{
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
-      aCIt = myConstraintMap.begin();
-  std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
-  for (; aCIt != myConstraintMap.end(); ++aCIt)
-    for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
-      if (::isUsed(*aCWIt, theFeature))
-        return true;
-  // check attributes
-  std::list<AttributePtr> anAttrList = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
-  std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
-  for (; anIt != anAttrList.end(); ++anIt)
-    if (isUsed(*anIt))
-      return true;
-  return false;
-}
-
-bool SolveSpaceSolver_Storage::isUsed(AttributePtr theAttribute) const
-{
-  AttributePtr anAttribute = theAttribute;
-  AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
-  if (aRefAttr) {
-    if (aRefAttr->isObject())
-      return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
-    else
-      anAttribute = aRefAttr->attr();
-  }
-
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
-      aCIt = myConstraintMap.begin();
-  std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
-  for (; aCIt != myConstraintMap.end(); ++aCIt)
-    for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
-      if (::isUsed(*aCWIt, anAttribute))
-        return true;
-  return false;
-}
-
-
-bool SolveSpaceSolver_Storage::removeEntity(FeaturePtr theFeature)
-{
-  std::map<FeaturePtr, EntityWrapperPtr>::iterator aFound = myFeatureMap.find(theFeature);
-  if (aFound == myFeatureMap.end())
-    return false; // feature not found, nothing to delete
-
-  // Check the feature is not used by constraints
-  if (isUsed(theFeature))
-    return false; // the feature is used, don't remove it
-
-  // Remove feature
-  EntityWrapperPtr anEntity = aFound->second;
-  myFeatureMap.erase(aFound);
-  if (remove(anEntity))
-    return true;
-  // feature is not removed, revert operation
-  myFeatureMap[theFeature] = anEntity;
-  return false;
-}
-
-bool SolveSpaceSolver_Storage::removeEntity(AttributePtr theAttribute)
-{
-  std::map<AttributePtr, EntityWrapperPtr>::iterator aFound = myAttributeMap.find(theAttribute);
-  if (aFound == myAttributeMap.end())
-    return false; // attribute not found, nothing to delete
-
-  // Check the attribute is not used by constraints
-  if (isUsed(theAttribute))
-    return false; // the attribute is used, don't remove it
-  // Check the attribute is not used by other features
-  std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
-  for (; aFIt != myFeatureMap.end(); ++aFIt)
-    if (::isUsed(aFIt->second, theAttribute)) // the attribute is used, don't remove it
-      return false;
-
-  // Remove attribute
-  EntityWrapperPtr anEntity = aFound->second;
-  myAttributeMap.erase(aFound);
-  if (remove(anEntity))
-    return true;
-  // attribute is not removed, revert operation
-  myAttributeMap[theAttribute] = anEntity;
-  return false;
+  return true;
 }
 
-
 bool SolveSpaceSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
 {
   std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
       std::dynamic_pointer_cast<SolveSpaceSolver_ConstraintWrapper>(theConstraint);
 
   // verify whether the constraint has duplicated
+  bool hasSameID = false;
   SameConstraintMap::iterator anEqIt = myEqualConstraints.begin();
-  for (; anEqIt != myEqualConstraints.end(); ++anEqIt)
-    if (anEqIt->find(aConstraint) != anEqIt->end()) {
+  for (; anEqIt != myEqualConstraints.end(); ++anEqIt) {
+    std::set<ConstraintWrapperPtr>::const_iterator aFound = anEqIt->find(aConstraint);
+    if (aFound != anEqIt->end()) {
+      // verify there is a constraint with same ID
+      std::set<ConstraintWrapperPtr>::const_iterator anIt = anEqIt->begin();
+      ConstraintID anID = (*aFound)->id();
+      for (++anIt; anIt != anEqIt->end() && !hasSameID; ++anIt)
+        if ((*anIt)->id() == anID && aFound != anIt)
+          hasSameID = true;
+      // erase constraint
       anEqIt->erase(aConstraint);
       break;
     }
-  if (anEqIt != myEqualConstraints.end())
+  }
+  if (anEqIt != myEqualConstraints.end() && hasSameID)
     return true;
 
   bool isFullyRemoved = removeConstraint((Slvs_hConstraint)aConstraint->id());
-
-  std::list<EntityWrapperPtr>::const_iterator anIt = aConstraint->entities().begin();
-  for (; anIt != aConstraint->entities().end(); ++anIt) {
-    std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity = 
-        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anIt);
-    FeaturePtr aBaseFeature = anEntity->baseFeature();
-    if (aBaseFeature)
-      isFullyRemoved = removeEntity(aBaseFeature) && isFullyRemoved;
-    else
-      isFullyRemoved = removeEntity(anEntity->baseAttribute()) && isFullyRemoved;
-  }
-
-  return isFullyRemoved;
+  // remove point-point coincidence
+  if (aConstraint->type() == CONSTRAINT_PT_PT_COINCIDENT)
+    isFullyRemoved = removeCoincidence(theConstraint) && isFullyRemoved;
+  return SketchSolver_Storage::remove(theConstraint) && isFullyRemoved;
 }
 
 bool SolveSpaceSolver_Storage::remove(EntityWrapperPtr theEntity)
 {
-  std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity = 
-        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theEntity);
-  bool isFullyRemoved = removeEntity((Slvs_hEntity)anEntity->id());
-
-  std::list<EntityWrapperPtr>::const_iterator anEntIt = anEntity->subEntities().begin();
-  for (; anEntIt != anEntity->subEntities().end(); ++anEntIt) {
-    std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSubEntity = 
-        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anEntIt);
-    FeaturePtr aBaseFeature = aSubEntity->baseFeature();
-    if (aBaseFeature)
-      isFullyRemoved = removeEntity(aBaseFeature) && isFullyRemoved;
-    else
-      isFullyRemoved = removeEntity(aSubEntity->baseAttribute()) && isFullyRemoved;
+  if (!theEntity)
+    return false;
+
+  // Additional check for entity to be used in point-point coincidence
+  bool isCoincide = false;
+  if (theEntity->type() == ENTITY_POINT) {
+    CoincidentPointsMap::const_iterator anIt = myCoincidentPoints.begin();
+    std::set<EntityWrapperPtr>::const_iterator aCIt;
+    for (; anIt != myCoincidentPoints.end(); ++anIt) {
+      if (anIt->first == theEntity)
+        break;
+      for (aCIt = anIt->second.begin(); aCIt != anIt->second.end(); ++aCIt)
+        if (*aCIt == theEntity)
+          break;
+      if (aCIt != anIt->second.end())
+        break;
+    }
+    if (anIt != myCoincidentPoints.end()) {
+      if (anIt->first != theEntity && isUsed(anIt->first->baseAttribute()))
+        isCoincide = true;
+      for (aCIt = anIt->second.begin(); !isCoincide && aCIt != anIt->second.end(); ++aCIt)
+        if (*aCIt != theEntity && isUsed((*aCIt)->baseAttribute()))
+          isCoincide = true;
+    }
   }
 
-  std::list<ParameterWrapperPtr>::const_iterator aParIt = anEntity->parameters().begin();
-  for (; aParIt != anEntity->parameters().end(); ++aParIt)
-    isFullyRemoved = remove(*aParIt) && isFullyRemoved;
-  return isFullyRemoved;
+  std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity = 
+        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theEntity);
+  bool isFullyRemoved = isCoincide ? true : removeEntity((Slvs_hEntity)anEntity->id());
+  return (SketchSolver_Storage::remove(theEntity) || isCoincide) && isFullyRemoved;
 }
 
 bool SolveSpaceSolver_Storage::remove(ParameterWrapperPtr theParameter)
@@ -1702,12 +1053,14 @@ bool SolveSpaceSolver_Storage::remove(ParameterWrapperPtr theParameter)
 
 void SolveSpaceSolver_Storage::refresh(bool theFixedOnly) const
 {
-  blockEvents(true);
+  //blockEvents(true);
 
   std::map<AttributePtr, EntityWrapperPtr>::const_iterator anIt = myAttributeMap.begin();
   std::list<ParameterWrapperPtr> aParams;
   std::list<ParameterWrapperPtr>::const_iterator aParIt;
   for (; anIt != myAttributeMap.end(); ++anIt) {
+    if (!anIt->second)
+      continue;
     // the external feature always should keep the up to date values, so, 
     // refresh from the solver is never needed
     if (anIt->first.get()) {
@@ -1715,6 +1068,11 @@ void SolveSpaceSolver_Storage::refresh(bool theFixedOnly) const
         std::dynamic_pointer_cast<SketchPlugin_Feature>(anIt->first->owner());
       if (aSketchFeature.get() && aSketchFeature->isExternal())
         continue;
+      // not need to refresh here sketch's origin and normal vector
+      CompositeFeaturePtr aSketch =
+          std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(anIt->first->owner());
+      if (aSketch)
+        continue;
     }
 
     // update parameter wrappers and obtain values of attributes
@@ -1743,13 +1101,25 @@ void SolveSpaceSolver_Storage::refresh(bool theFixedOnly) const
         if (!isUpd[1]) aCoords[1] = aPoint2D->y();
         aPoint2D->setValue(aCoords[0], aCoords[1]);
         // Find points coincident with this one (probably not in GID_OUTOFGROUP)
-        std::map<AttributePtr, EntityWrapperPtr>::const_iterator aLocIt =
-            theFixedOnly ? myAttributeMap.begin() : anIt;
-        for (++aLocIt; aLocIt != myAttributeMap.end(); ++aLocIt)
+        std::map<AttributePtr, EntityWrapperPtr>::const_iterator aLocIt;
+        if (theFixedOnly) 
+          aLocIt = myAttributeMap.begin();
+        else {
+          aLocIt = anIt;
+          ++aLocIt;
+        }
+        for (; aLocIt != myAttributeMap.end(); ++aLocIt) {
+          if (!aLocIt->second)
+            continue;
+          std::shared_ptr<SketchPlugin_Feature> aSketchFeature = 
+            std::dynamic_pointer_cast<SketchPlugin_Feature>(aLocIt->first->owner());
+          if (aSketchFeature && aSketchFeature->isExternal())
+            continue;
           if (anIt->second->id() == aLocIt->second->id()) {
             aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aLocIt->first);
             aPoint2D->setValue(aCoords[0], aCoords[1]);
           }
+        }
       }
       continue;
     }
@@ -1773,17 +1143,26 @@ void SolveSpaceSolver_Storage::refresh(bool theFixedOnly) const
     }
   }
 
-  blockEvents(false);
+  //blockEvents(false);
 }
 
 void SolveSpaceSolver_Storage::verifyFixed()
 {
   std::map<AttributePtr, EntityWrapperPtr>::iterator anAttrIt = myAttributeMap.begin();
   for (; anAttrIt != myAttributeMap.end(); ++anAttrIt) {
+    if (!anAttrIt->second)
+      continue;
+    if (anAttrIt->second->group() == GID_OUTOFGROUP) {
+      Slvs_Entity anEnt = getEntity((Slvs_hEntity)anAttrIt->second->id());
+      if (anEnt.group != (Slvs_hEntity)GID_OUTOFGROUP)
+        anEnt.group = (Slvs_hEntity)GID_OUTOFGROUP;
+      updateEntity(anEnt);
+    }
+
     const std::list<ParameterWrapperPtr>& aParameters = anAttrIt->second->parameters();
     std::list<ParameterWrapperPtr>::const_iterator aParIt = aParameters.begin();
     for (; aParIt != aParameters.end(); ++aParIt)
-      if ((*aParIt)->group() == GID_OUTOFGROUP) {
+      if (anAttrIt->second->group() == GID_OUTOFGROUP || (*aParIt)->group() == GID_OUTOFGROUP) {
         Slvs_Param aParam = getParameter((Slvs_hParam)(*aParIt)->id());
         if (aParam.group != (Slvs_hParam)GID_OUTOFGROUP) {
           aParam.group = (Slvs_hParam)GID_OUTOFGROUP;