Salome HOME
Issue #1157: Using parameters in point coordinates
[modules/shaper.git] / src / SketchSolver / SolveSpaceSolver / SolveSpaceSolver_Storage.cpp
index 2a6fb95bf08fb7694c762431a8405c7c92f25b40..999f43eefc46a7e7451a83382f998de382839106 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
@@ -47,7 +50,7 @@ SolveSpaceSolver_Storage::SolveSpaceSolver_Storage(const GroupID& theGroup)
 {
 }
 
-bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr& theConstraint)
+bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr theConstraint)
 {
   bool isUpdated = false;
   std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
@@ -73,6 +76,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) {
@@ -105,7 +111,7 @@ bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr& theConstraint)
   return isUpdated;
 }
 
-bool SolveSpaceSolver_Storage::update(EntityWrapperPtr& theEntity)
+bool SolveSpaceSolver_Storage::update(EntityWrapperPtr theEntity)
 {
   bool isUpdated = false;
   std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity = 
@@ -158,6 +164,15 @@ bool SolveSpaceSolver_Storage::update(EntityWrapperPtr& theEntity)
       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;
+    }
+  }
 
   // update entity itself
   if (aSlvsEnt.wrkpl == SLVS_E_UNKNOWN && myWorkplaneID != SLVS_E_UNKNOWN)
@@ -165,17 +180,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);
@@ -292,8 +308,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 +328,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();
@@ -1108,67 +1127,6 @@ void SolveSpaceSolver_Storage::addConstraintWhereDragged(const Slvs_hConstraint&
     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)
 {
@@ -1264,7 +1222,7 @@ void SolveSpaceSolver_Storage::fixPoint(const Slvs_Entity& thePoint,
   Slvs_Constraint aConstraint;
   Slvs_hConstraint aConstrID = SLVS_E_UNKNOWN;
   bool isFixed = isPointFixed(thePoint.h, aConstrID, true);
-  bool isForceUpdate = (isFixed && isTemporary(aConstrID));
+  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,
@@ -1503,143 +1461,106 @@ bool SolveSpaceSolver_Storage::isUsedInEqual(
   return false;
 }
 
-void SolveSpaceSolver_Storage::setTemporary(ConstraintPtr theConstraint)
-{
-  // TODO
-}
 
-bool SolveSpaceSolver_Storage::removeConstraint(ConstraintPtr theConstraint)
+bool SolveSpaceSolver_Storage::removeCoincidence(ConstraintWrapperPtr 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;
-    }
+  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 (!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;
-}
+  if (aPtPtIt == myCoincidentPoints.end())
+    return true; // already removed
 
-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();
+  // 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;
   }
 
-  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;
+  // 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) {
+    for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) {
+      if (!aFIt->second->isUsed(aNotCIt->first->baseAttribute()))
+        continue;
+      std::list<EntityWrapperPtr> aSubs = aFIt->second->subEntities();
+      std::list<EntityWrapperPtr>::iterator aSIt = aSubs.begin();
+      for (; aSIt != aSubs.end(); ++aSIt)
+        if (*aSIt == aNotCIt->first)
+          *aSIt = aNotCIt->second;
+      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));
+
+  // 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[aNewMaster] = aSlaves;
+      myCoincidentPoints.erase(aPtPtIt);
+      aPtPtIt = myCoincidentPoints.find(aNewMaster);
+    } else
+      aPtPtIt->second.erase(aNotCIt->first);
+  }
+  return true;
 }
 
-
 bool SolveSpaceSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
 {
   std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
@@ -1657,41 +1578,22 @@ bool SolveSpaceSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
 
   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;
-  }
+  // remove point-point coincidence
+  if (aConstraint->type() == CONSTRAINT_PT_PT_COINCIDENT)
+    isFullyRemoved = removeCoincidence(theConstraint);
 
-  return isFullyRemoved;
+  return SketchSolver_Storage::remove(theConstraint) && isFullyRemoved;
 }
 
 bool SolveSpaceSolver_Storage::remove(EntityWrapperPtr theEntity)
 {
+  if (!theEntity)
+    return false;
+
   std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity = 
         std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theEntity);
   bool isFullyRemoved = removeEntity((Slvs_hEntity)anEntity->id());
-
-  std::list<EntityWrapperPtr>::const_iterator anEntIt = anEntity->subEntities().begin();
-  for (; anEntIt != anEntity->subEntities().end(); ++anEntIt) {
-    std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSubEntity = 
-        std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anEntIt);
-    FeaturePtr aBaseFeature = aSubEntity->baseFeature();
-    if (aBaseFeature)
-      isFullyRemoved = removeEntity(aBaseFeature) && isFullyRemoved;
-    else
-      isFullyRemoved = removeEntity(aSubEntity->baseAttribute()) && isFullyRemoved;
-  }
-
-  std::list<ParameterWrapperPtr>::const_iterator aParIt = anEntity->parameters().begin();
-  for (; aParIt != anEntity->parameters().end(); ++aParIt)
-    isFullyRemoved = remove(*aParIt) && isFullyRemoved;
-  return isFullyRemoved;
+  return SketchSolver_Storage::remove(theEntity) && isFullyRemoved;
 }
 
 bool SolveSpaceSolver_Storage::remove(ParameterWrapperPtr theParameter)
@@ -1702,12 +1604,23 @@ 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()) {
+      std::shared_ptr<SketchPlugin_Feature> aSketchFeature = 
+        std::dynamic_pointer_cast<SketchPlugin_Feature>(anIt->first->owner());
+      if (aSketchFeature.get() && aSketchFeature->isExternal())
+        continue;
+    }
+
     // update parameter wrappers and obtain values of attributes
     aParams = anIt->second->parameters();
     double aCoords[3];
@@ -1764,13 +1677,15 @@ 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;
     const std::list<ParameterWrapperPtr>& aParameters = anAttrIt->second->parameters();
     std::list<ParameterWrapperPtr>::const_iterator aParIt = aParameters.begin();
     for (; aParIt != aParameters.end(); ++aParIt)