]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp
Salome HOME
Update conditions to add arc into solver (issue #1165)
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_Storage.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:    PlaneGCSSolver_Storage.cpp
4 // Created: 14 Dec 2015
5 // Author:  Artem ZHIDKOV
6
7 #include <PlaneGCSSolver_Storage.h>
8 #include <PlaneGCSSolver_Builder.h>
9 #include <PlaneGCSSolver_Solver.h>
10 #include <PlaneGCSSolver_ConstraintWrapper.h>
11 #include <PlaneGCSSolver_EntityWrapper.h>
12 #include <PlaneGCSSolver_PointWrapper.h>
13 #include <PlaneGCSSolver_ScalarWrapper.h>
14 #include <PlaneGCSSolver_ParameterWrapper.h>
15
16 #include <GeomAPI_Edge.h>
17 #include <GeomAPI_Dir2d.h>
18 #include <GeomAPI_Pnt2d.h>
19 #include <GeomAPI_XY.h>
20 #include <GeomDataAPI_Point2D.h>
21 ////#include <ModelAPI_AttributeRefAttr.h>
22 ////#include <ModelAPI_Feature.h>
23 ////#include <ModelAPI_ResultConstruction.h>
24
25 #include <SketchPlugin_Arc.h>
26 ////#include <SketchPlugin_Circle.h>
27 ////#include <SketchPlugin_Line.h>
28 ////#include <SketchPlugin_Point.h>
29 ////
30 ////#ifndef OBSOLETE
31 ////#include <SketchPlugin_ConstraintAngle.h>
32 ////#endif
33
34 #include <cmath>
35
36 ////#ifdef OBSOLETE
37 /////** \brief Search the entity/parameter with specified ID in the list of elements
38 //// *  \param[in] theEntityID unique ID of the element
39 //// *  \param[in] theEntities list of elements
40 //// *  \return position of the found element or -1 if the element is not found
41 //// */
42 ////template<typename T>
43 ////static int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities);
44 ////
45 /////// \brief Compare two parameters to be different
46 ////static bool IsNotEqual(const Slvs_Param& theParam1, const Slvs_Param& theParam2);
47 /////// \brief Compare two entities to be different
48 ////static bool IsNotEqual(const Slvs_Entity& theEntity1, const Slvs_Entity& theEntity2);
49 /////// \brief Compare two constriants to be different
50 ////static bool IsNotEqual(const Slvs_Constraint& theConstraint1, const Slvs_Constraint& theConstraint2);
51 ////#endif
52
53
54 PlaneGCSSolver_Storage::PlaneGCSSolver_Storage(const GroupID& theGroup)
55   : SketchSolver_Storage(theGroup),
56     myEntityLastID(EID_SKETCH)
57 {
58 }
59
60 void PlaneGCSSolver_Storage::addConstraint(
61     ConstraintPtr                   theConstraint,
62     std::list<ConstraintWrapperPtr> theSolverConstraints)
63 {
64   SketchSolver_Storage::addConstraint(theConstraint, theSolverConstraints);
65
66   // update point-point coincidence
67   if (!theSolverConstraints.empty() &&
68       theSolverConstraints.front()->type() == CONSTRAINT_PT_PT_COINCIDENT) {
69     std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
70     for (; aCIt != theSolverConstraints.end(); ++aCIt)
71       update(*aCIt);
72   }
73 }
74
75
76 bool PlaneGCSSolver_Storage::update(ConstraintWrapperPtr theConstraint)
77 {
78   bool isUpdated = false;
79   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
80       std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
81
82   // point-Line distance should be positive
83   if (aConstraint->type() == CONSTRAINT_PT_LINE_DISTANCE && aConstraint->value() < 0.0)
84     aConstraint->setValue(-aConstraint->value());
85
86   // make value of constraint unchangeable
87   ParameterWrapperPtr aValue = aConstraint->valueParameter();
88   if (aValue)
89     isUpdated = update(aValue) || isUpdated;
90
91   // update constrained entities
92   std::list<EntityWrapperPtr> anEntities = theConstraint->entities();
93   std::list<EntityWrapperPtr>::iterator anIt = anEntities.begin();
94   for (; anIt != anEntities.end(); ++anIt)
95     isUpdated = update(*anIt) || isUpdated;
96
97   return isUpdated;
98 }
99
100 /// \brief Update coordinates of the point or scalar using its base attribute
101 static bool updateValues(EntityWrapperPtr& theEntity)
102 {
103   bool isUpdated = false;
104   AttributePtr anAttr = theEntity->baseAttribute();
105   const std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
106
107   double aCoord[2];
108
109   std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
110       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
111   if (aPoint2D) {
112     aCoord[0] = aPoint2D->x();
113     aCoord[1] = aPoint2D->y();
114   } else {
115     AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttr);
116     if (aScalar)
117       aCoord[0] = aScalar->value();
118   }
119
120   std::list<ParameterWrapperPtr>::const_iterator anIt = aParams.begin();
121   for (int i = 0; anIt != aParams.end(); ++anIt, ++i)
122     if (fabs((*anIt)->value() - aCoord[i]) > tolerance) {
123       (*anIt)->setValue(aCoord[i]);
124       isUpdated = true;
125     }
126   return isUpdated;
127 }
128
129 bool PlaneGCSSolver_Storage::update(EntityWrapperPtr theEntity)
130 {
131   if (theEntity->type() == ENTITY_SKETCH)
132     return true; // sketch is not necessary for PlaneGCS, so it is always says true
133
134   bool isUpdated = false;
135
136   if (theEntity->baseAttribute()) {
137     isUpdated = updateValues(theEntity);
138     if (isUpdated)
139       setNeedToResolve(true);
140   }
141
142   // update parameters
143   std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
144   std::list<ParameterWrapperPtr>::iterator aPIt = aParams.begin();
145   for (; aPIt != aParams.end(); ++aPIt)
146     isUpdated = update(*aPIt) || isUpdated;
147
148   // update sub-entities
149   std::list<EntityWrapperPtr> aSubEntities = theEntity->subEntities();
150   std::list<EntityWrapperPtr>::iterator aSIt = aSubEntities.begin();
151   for (; aSIt != aSubEntities.end(); ++aSIt)
152     isUpdated = update(*aSIt) || isUpdated;
153
154   // additional constraints for the arc processing
155   if (theEntity->type() == ENTITY_ARC)
156     processArc(theEntity);
157
158   // Change entity's ID, if necessary
159   if (theEntity->id() == EID_UNKNOWN) {
160     if (theEntity->type() == ENTITY_POINT) {
161       std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
162           std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
163       aPoint->setId(++myEntityLastID);
164     } else if (theEntity->type() == ENTITY_SCALAR) {
165       std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aScalar =
166           std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(theEntity);
167       aScalar->setId(++myEntityLastID);
168     } else {
169       std::shared_ptr<PlaneGCSSolver_EntityWrapper> aGCSEnt =
170           std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity);
171       aGCSEnt->setId(++myEntityLastID);
172     }
173   }
174   return isUpdated;
175 }
176
177 bool PlaneGCSSolver_Storage::update(ParameterWrapperPtr theParameter)
178 {
179   std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
180       std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(theParameter);
181   if (aParam->isProcessed())
182     return false;
183   if (theParameter->group() != myGroupID || theParameter->isParametric())
184     myConst.push_back(aParam->parameter());
185   else
186     myParameters.push_back(aParam->parameter());
187   aParam->setProcessed(true);
188   return true;
189 }
190
191
192 bool PlaneGCSSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
193 {
194   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
195     std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
196
197   bool isFullyRemoved = true;
198   const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
199   std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
200   for (; aSIt != aSubs.end(); ++ aSIt)
201     isFullyRemoved = remove(*aSIt) && isFullyRemoved;
202
203   if (aConstraint->valueParameter())
204     isFullyRemoved = remove(aConstraint->valueParameter()) && isFullyRemoved;
205   if (!isFullyRemoved &&
206      (!aConstraint->baseConstraint()->data() || !aConstraint->baseConstraint()->data()->isValid()))
207     isFullyRemoved = true;
208   if (isFullyRemoved) {
209     setNeedToResolve(true);
210     myRemovedConstraints.insert(myRemovedConstraints.end(),
211         aConstraint->constraints().begin(), aConstraint->constraints().end());
212   }
213   return isFullyRemoved;
214 }
215
216 bool PlaneGCSSolver_Storage::remove(EntityWrapperPtr theEntity)
217 {
218   if ((theEntity->baseAttribute() && isUsed(theEntity->baseAttribute())) ||
219       (theEntity->baseFeature() && isUsed(theEntity->baseFeature())))
220     return false;
221
222   bool isFullyRemoved = SketchSolver_Storage::remove(theEntity);
223   if (isFullyRemoved && theEntity->id() == myEntityLastID)
224     --myEntityLastID;
225   return isFullyRemoved;
226 }
227
228 bool PlaneGCSSolver_Storage::remove(ParameterWrapperPtr theParameter)
229 {
230   std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
231       std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(theParameter);
232   if (aParam->isProcessed()) {
233     double* aValPtr = aParam->parameter();
234     GCS::VEC_pD::iterator anIt =  myParameters.begin();
235     for (; anIt != myParameters.end(); ++anIt)
236       if (*anIt == aValPtr)
237         break;
238     if (anIt != myParameters.end()) {
239       myParameters.erase(anIt);
240       setNeedToResolve(true);
241     }
242     else {
243       for (anIt = myConst.begin(); anIt != myConst.end(); ++anIt)
244         if (*anIt == aValPtr)
245           break;
246       if (anIt != myConst.end()) {
247         myConst.erase(anIt);
248         setNeedToResolve(true);
249       }
250     }
251   }
252   aParam->setProcessed(false);
253   return true;
254 }
255
256
257 void PlaneGCSSolver_Storage::addCoincidentPoints(
258     EntityWrapperPtr theMaster, EntityWrapperPtr theSlave)
259 {
260   if (theMaster->type() != ENTITY_POINT || theSlave->type() != ENTITY_POINT)
261     return;
262
263   // Search available coincidence
264   CoincidentPointsMap::iterator aMasterFound = myCoincidentPoints.find(theMaster);
265   CoincidentPointsMap::iterator aSlaveFound = myCoincidentPoints.find(theSlave);
266   if (aMasterFound == myCoincidentPoints.end() &&  aSlaveFound == myCoincidentPoints.end()) {
267     // try to find master and slave points in the lists of slaves of already existent coincidences
268     CoincidentPointsMap::iterator anIt = myCoincidentPoints.begin();
269     for (; anIt != myCoincidentPoints.end(); ++anIt) {
270       if (anIt->second.find(theMaster) != anIt->second.end())
271         aMasterFound = anIt;
272       else if (anIt->second.find(theSlave) != anIt->second.end())
273         aSlaveFound = anIt;
274
275       if (aMasterFound != myCoincidentPoints.end() &&  aSlaveFound != myCoincidentPoints.end())
276         break;
277     }
278   }
279
280   if (aMasterFound == myCoincidentPoints.end()) {
281     // create new group
282     myCoincidentPoints[theMaster] = std::set<EntityWrapperPtr>();
283     aMasterFound = myCoincidentPoints.find(theMaster);
284   } else if (aMasterFound == aSlaveFound)
285     return; // already coincident
286
287   if (aSlaveFound != myCoincidentPoints.end()) {
288     // A slave has been found, we need to attach all points coincident with it to the new master
289     std::set<EntityWrapperPtr> aNewSlaves = aSlaveFound->second;
290     aNewSlaves.insert(aSlaveFound->first);
291     myCoincidentPoints.erase(aSlaveFound);
292
293     std::set<EntityWrapperPtr>::const_iterator aSlIt = aNewSlaves.begin();
294     for (; aSlIt != aNewSlaves.end(); ++aSlIt)
295       addCoincidentPoints(theMaster, *aSlIt);
296   } else {
297 ////    std::list<ParameterWrapperPtr> aSlaveParams = theSlave->parameters();
298 ////    theSlave->setParameters(theMaster->parameters());
299 ////
300 ////    // Remove slave's parameters
301 ////    std::list<ParameterWrapperPtr>::iterator aParIt = aSlaveParams.begin();
302 ////    for (; aParIt != aSlaveParams.end(); ++aParIt)
303 ////      remove(*aParIt);
304
305     aMasterFound->second.insert(theSlave);
306   }
307 }
308
309
310 void PlaneGCSSolver_Storage::changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup)
311 {
312   theEntity->setGroup(theGroup);
313   if (theGroup == myGroupID)
314     makeVariable(theEntity);
315   else
316     makeConstant(theEntity);
317 }
318
319 void PlaneGCSSolver_Storage::changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup)
320 {
321 ////  // TODO
322 }
323
324 void PlaneGCSSolver_Storage::verifyFixed()
325 {
326 ////  // TODO
327 }
328
329
330 #ifndef OBSOLETE
331 ////
332 ////void PlaneGCSSolver_Storage::changeConstraint(
333 ////    const ConstraintPtr& theConstraint,
334 ////    const std::vector<GCSConstraintPtr>& theGCSConstraints)
335 ////{
336 ////  myConstraintsMap[theConstraint] = theGCSConstraints;
337 ////}
338
339 ////void PlaneGCSSolver_Storage::addConstraint(GCSConstraintPtr theConstraint)
340 ////{
341 ////  std::map<ConstraintPtr, std::vector<GCSConstraintPtr> >::iterator
342 ////      aFound = myConstraintsMap.find(ConstraintPtr());
343 ////  if (aFound != myConstraintsMap.end())
344 ////    aFound->second.push_back(theConstraint);
345 ////  else {
346 ////    std::vector<GCSConstraintPtr> aConstrVec(1, theConstraint);
347 ////    myConstraintsMap[ConstraintPtr()] = aConstrVec;
348 ////  }
349 ////}
350
351 ////EntityID PlaneGCSSolver_Storage::changeEntity(const FeaturePtr& theEntity)
352 ////{
353 ////  if (!theEntity || !theEntity->data() || !theEntity->data()->isValid())
354 ////    return ENTITY_UNKNOWN;
355 ////
356 ////  // Firstly, try to find entity
357 ////  std::map<FeaturePtr, EntityID>::const_iterator aFound = myFeatureEntityMap.find(theEntity);
358 ////
359 ////  EntityID aNewEntID;
360 ////  if (aFound != myFeatureEntityMap.end())
361 ////    aNewEntID = aFound->second;
362 ////
363 ////  const std::string& aFeatureKind = theEntity->getKind();
364 ////  // SketchPlugin features
365 ////  if (aFeatureKind == SketchPlugin_Line::ID())
366 ////    updateLine(theEntity, aNewEntID);
367 ////  // Circle
368 ////  else if (aFeatureKind == SketchPlugin_Circle::ID())
369 ////    updateCircle(theEntity, aNewEntID);
370 ////  // Arc
371 ////  else if (aFeatureKind == SketchPlugin_Arc::ID())
372 ////    updateArc(theEntity, aNewEntID);
373 ////  // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
374 ////  else if (aFeatureKind == SketchPlugin_Point::ID()) {
375 ////    AttributePtr anAttribute = theEntity->attribute(SketchPlugin_Point::COORD_ID());
376 ////    if (!anAttribute->isInitialized())
377 ////      return ENTITY_UNKNOWN;
378 ////    // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier
379 ////    aNewEntID = changeEntity(anAttribute);
380 ////  }
381 ////  else // NOTE: Other types of entities are unsupported
382 ////    aNewEntID = ENTITY_UNKNOWN;
383 ////
384 ////  if (aNewEntID != ENTITY_UNKNOWN)
385 ////    myFeatureEntityMap[theEntity] = aNewEntID;
386 ////  return aNewEntID;
387 ////}
388 ////
389 ////EntityID PlaneGCSSolver_Storage::changeEntity(const AttributePtr& theEntity)
390 ////{
391 ////  if (!theEntity)
392 ////    return ENTITY_UNKNOWN;
393 ////
394 ////  AttributeRefAttrPtr aRefAttr =
395 ////      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theEntity);
396 ////  if (aRefAttr) {
397 ////    if (aRefAttr->isObject()) {
398 ////      ResultConstructionPtr aRC =
399 ////          std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aRefAttr->object());
400 ////      if (!aRC)
401 ////        return ENTITY_UNKNOWN;
402 ////      return changeEntity(ModelAPI_Feature::feature(aRC));
403 ////    }
404 ////    else
405 ////      return changeEntity(aRefAttr->attr());
406 ////  }
407 ////
408 ////  EntityID aNewEntID = ENTITY_UNKNOWN;
409 ////
410 ////  // Firstly, try to find entity
411 ////  std::map<AttributePtr, EntityID>::const_iterator aFound = myAttributeEntityMap.find(theEntity);
412 ////  // Check type of attribute and create corresponding entity
413 ////  std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
414 ////      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEntity);
415 ////  if (aPoint2D) {
416 ////    if (aFound != myAttributeEntityMap.end())
417 ////      aNewEntID = aFound->second;
418 ////    updatePoint(aPoint2D, aNewEntID);
419 ////  } else {
420 ////    AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theEntity);
421 ////    if (aScalar) {
422 ////      // Check the scalar represents an angular value
423 ////      bool isAngular = false;
424 ////      FeaturePtr anOwner = ModelAPI_Feature::feature(aScalar->owner());
425 ////      if (anOwner && anOwner->getKind() == SketchPlugin_ConstraintAngle::ID())
426 ////        isAngular = true;
427 ////
428 ////      if (aFound != myAttributeEntityMap.end())
429 ////        aNewEntID = aFound->second;
430 ////      if (isAngular)
431 ////        updateAngle(aScalar, aNewEntID);
432 ////      else
433 ////        updateScalar(aScalar, aNewEntID);
434 ////    }
435 ////  }
436 ////  // NOTE: Other types of attributes are not supported
437 ////
438 ////  // Map attribute and new entity ID
439 ////  if (aFound == myAttributeEntityMap.end() && aNewEntID != ENTITY_UNKNOWN)
440 ////    myAttributeEntityMap[theEntity] = aNewEntID;
441 ////  return aNewEntID;
442 ////}
443
444
445 ////bool PlaneGCSSolver_Storage::removeConstraint(const ConstraintPtr& theConstraint)
446 ////{
447 ////  std::map<ConstraintPtr, std::vector<GCSConstraintPtr> >::iterator
448 ////      aFound = myConstraintsMap.find(theConstraint);
449 ////  if (aFound == myConstraintsMap.end())
450 ////    return true; // no constraint - nothing to remove
451 ////
452 ////  std::vector<GCSConstraintPtr> aConstrList = aFound->second;
453 ////  myConstraintsMap.erase(aFound);
454 ////  bool isFullyRemoved = removeEntity(theConstraint->attribute(SketchPlugin_Constraint::VALUE()));
455 ////  for (int ind = 0; ind < CONSTRAINT_ATTR_SIZE; ++ind)
456 ////    isFullyRemoved = removeEntity(theConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(ind)))
457 ////                   && isFullyRemoved;
458 ////
459 ////  myRemovedConstraints.insert(myRemovedConstraints.end(), aConstrList.begin(), aConstrList.end());
460 ////
461 ////  return isFullyRemoved;
462 ////}
463
464 ////bool PlaneGCSSolver_Storage::removeConstraint(GCSConstraintPtr theConstraint)
465 ////{
466 ////  std::map<ConstraintPtr, std::vector<GCSConstraintPtr> >::iterator
467 ////      aFound = myConstraintsMap.find(ConstraintPtr());
468 ////  if (aFound != myConstraintsMap.end()) {
469 ////    std::vector<GCSConstraintPtr>::iterator anIt = aFound->second.begin();
470 ////    for (; anIt != aFound->second.end(); ++anIt)
471 ////      if (*anIt == theConstraint) {
472 ////        aFound->second.erase(anIt);
473 ////        break;
474 ////      }
475 ////  }
476 ////
477 ////  myRemovedConstraints.push_back(theConstraint);
478 ////  return true;
479 ////}
480 ////
481 ////bool PlaneGCSSolver_Storage::removeEntity(const FeaturePtr& theFeature)
482 ////{
483 ////  if (!theFeature)
484 ////    return true;
485 ////  if (isUsed(theFeature))
486 ////    return false;
487 ////
488 ////  // remove feature and corresponding entity
489 ////  std::map<FeaturePtr, EntityID>::iterator aFound = myFeatureEntityMap.find(theFeature);
490 ////  if (aFound != myFeatureEntityMap.end()) {
491 ////    if (aFound->second.type == ARC) {
492 ////      // remove additional arc constraints
493 ////      std::map<EntityID, std::vector<GCSConstraintPtr> >::iterator aFoundArc =
494 ////          myArcConstraintMap.find(aFound->second);
495 ////      if (aFoundArc != myArcConstraintMap.end()) {
496 ////        myRemovedConstraints.insert(myRemovedConstraints.end(),
497 ////            aFoundArc->second.begin(), aFoundArc->second.end());
498 ////        myArcConstraintMap.erase(aFoundArc);
499 ////      }
500 ////    }
501 ////    myGCSEntities.erase(aFound->second);
502 ////    myFeatureEntityMap.erase(aFound);
503 ////  }
504 ////
505 ////  // remove feature's attributes
506 ////  bool isFullyRemoved = true;
507 ////  std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
508 ////  std::list<AttributePtr>::iterator anAttrIt = anAttributes.begin();
509 ////  for (; anAttrIt != anAttributes.end(); ++anAttrIt)
510 ////    isFullyRemoved = removeEntity(*anAttrIt) && isFullyRemoved;
511 ////  return isFullyRemoved;
512 ////}
513 ////
514 ////bool PlaneGCSSolver_Storage::removeEntity(const AttributePtr& theAttribute)
515 ////{
516 ////  if (!theAttribute)
517 ////    return true;
518 ////  if (isUsed(theAttribute))
519 ////    return false;
520 ////
521 ////  AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
522 ////  if (aRefAttr) {
523 ////    if (aRefAttr->isObject()) {
524 ////      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
525 ////      return removeEntity(aFeature);
526 ////    } else
527 ////      return removeEntity(aRefAttr->attr());
528 ////  }
529 ////
530 ////  // remove attribute and corresponding entity
531 ////  std::map<AttributePtr, EntityID>::iterator aFound = myAttributeEntityMap.find(theAttribute);
532 ////  if (aFound == myAttributeEntityMap.end())
533 ////    return true; // no attribute, nothing to remove
534 ////
535 ////  if (aFound->second.type == SCALAR || aFound->second.type == ANGLE) {
536 ////    std::map<EntityID, double*>::iterator aFoundScalar = myGCSScalars.find(aFound->second);
537 ////    if (aFoundScalar != myGCSScalars.end()) {
538 ////      removeParameters(aFoundScalar->second);
539 ////      myGCSScalars.erase(aFoundScalar);
540 ////    }
541 ////  }
542 ////  else if (aFound->second.type == POINT) {
543 ////    std::map<EntityID, GCSPointPtr>::iterator aFoundPoint = myGCSPoints.find(aFound->second);
544 ////    if (aFoundPoint != myGCSPoints.end()) {
545 ////      removeParameters(aFoundPoint->second->x, aFoundPoint->second->y);
546 ////      myGCSPoints.erase(aFoundPoint);
547 ////    }
548 ////  }
549 ////
550 ////  myAttributeEntityMap.erase(aFound);
551 ////  return true;
552 ////}
553
554 ////void PlaneGCSSolver_Storage::removeParameters(double* theParam1, double* theParam2)
555 ////{
556 ////  int aNbRemoved = 2;
557 ////  for (int ind = 0; ind < 2 && aNbRemoved > 0; ++ind) {
558 ////    GCS::VEC_pD& aList = ind ==0 ? myParameters : myConst;
559 ////
560 ////    GCS::VEC_pD::iterator aParIt = aList.begin();
561 ////    while (aNbRemoved > 0 && aParIt != aList.end()) {
562 ////      if (*aParIt != theParam1 && *aParIt != theParam2) {
563 ////        ++aParIt;
564 ////        continue;
565 ////      }
566 ////
567 ////      myRemovedParameters.push_back(*aParIt);
568 ////      int aShift = aParIt - aList.begin();
569 ////      aList.erase(aParIt);
570 ////      aParIt = aList.begin() + aShift;
571 ////      --aNbRemoved;
572 ////    }
573 ////  }
574 ////}
575
576
577 ////double* PlaneGCSSolver_Storage::createScalar(const AttributeDoublePtr& theScalar)
578 ////{
579 ////  double* aResult = new double;
580 ////  if (theScalar)
581 ////    *aResult = theScalar->value();
582 ////  myParameters.push_back(aResult);
583 ////  myNeedToResolve = true;
584 ////  return aResult;
585 ////}
586 ////
587 ////void PlaneGCSSolver_Storage::updateScalar(const AttributeDoublePtr& theScalar, EntityID& theID)
588 ////{
589 ////  std::map<EntityID, double*>::const_iterator aFound = myGCSScalars.find(theID);
590 ////  if (aFound == myGCSScalars.end()) {
591 ////    // new scalar
592 ////    theID = ++myEntityLastID;
593 ////    theID.type = SCALAR;
594 ////    myGCSScalars[theID] = createScalar(theScalar);
595 ////  }
596 ////  else if (fabs(*(myGCSScalars[theID]) - theScalar->value()) > tolerance) {
597 ////    *(myGCSScalars[theID]) = theScalar->value();
598 ////    myNeedToResolve = true;
599 ////  }
600 ////}
601 ////
602 ////void PlaneGCSSolver_Storage::updateAngle(const AttributeDoublePtr& theAngle, EntityID& theID)
603 ////{
604 ////  std::map<EntityID, double*>::const_iterator aFound = myGCSScalars.find(theID);
605 ////  if (aFound == myGCSScalars.end()) {
606 ////    // new scalar
607 ////    theID = ++myEntityLastID;
608 ////    theID.type = ANGLE;
609 ////    myGCSScalars[theID] = createScalar(theAngle);
610 ////  }
611 ////  else if (fabs(*(myGCSScalars[theID]) - theAngle->value()) > tolerance) {
612 ////    *(myGCSScalars[theID]) = theAngle->value();
613 ////    myNeedToResolve = true;
614 ////  }
615 ////  // Convert degrees to radians
616 ////  *(myGCSScalars[theID]) *= M_PI / 180.0;
617 ////}
618 ////
619 ////GCS::Point PlaneGCSSolver_Storage::createPoint(const std::shared_ptr<GeomDataAPI_Point2D>& thePoint)
620 ////{
621 ////  GCS::Point aResult;
622 ////  aResult.x = new double(thePoint->x());
623 ////  aResult.y = new double(thePoint->y());
624 ////
625 ////  myParameters.push_back(aResult.x);
626 ////  myParameters.push_back(aResult.y);
627 ////
628 ////  myNeedToResolve = true;
629 ////  return aResult;
630 ////}
631 ////
632 ////void PlaneGCSSolver_Storage::updatePoint(const std::shared_ptr<GeomDataAPI_Point2D>& thePoint,
633 ////                                             EntityID&                             theID)
634 ////{
635 ////  std::map<EntityID, GCSPointPtr>::iterator aFound = myGCSPoints.find(theID);
636 ////  if (aFound == myGCSPoints.end()) {
637 ////    // new point
638 ////    theID = ++myEntityLastID;
639 ////    theID.type = POINT;
640 ////    myGCSPoints[theID] = GCSPointPtr(new GCS::Point(createPoint(thePoint)));
641 ////  }
642 ////  else if (fabs(*(aFound->second->x) - thePoint->x()) > tolerance ||
643 ////           fabs(*(aFound->second->y) - thePoint->y()) > tolerance) {
644 ////    // update point
645 ////    *(aFound->second->x) = thePoint->x();
646 ////    *(aFound->second->y) = thePoint->y();
647 ////    myNeedToResolve = true;
648 ////  }
649 ////}
650 ////
651 ////void PlaneGCSSolver_Storage::updateLine(const FeaturePtr& theLine, EntityID& theID)
652 ////{
653 ////  std::shared_ptr<GeomDataAPI_Point2D> aStartAttr =
654 ////      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
655 ////      theLine->attribute(SketchPlugin_Line::START_ID()));
656 ////  std::shared_ptr<GeomDataAPI_Point2D> aEndAttr =
657 ////      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
658 ////      theLine->attribute(SketchPlugin_Line::END_ID()));
659 ////  if (!aStartAttr->isInitialized() || !aEndAttr->isInitialized()) {
660 ////    theID = ENTITY_UNKNOWN;
661 ////    return;
662 ////  }
663 ////
664 ////  std::map<EntityID, GCSCurvePtr>::iterator aFound = myGCSEntities.find(theID);
665 ////  if (aFound == myGCSEntities.end()) {
666 ////////    // new line
667 ////////    theID = ++myEntityLastID;
668 ////////    theID.type = LINE;
669 ////////
670 ////////    EntityID aStartID = changeEntity(aStartAttr);
671 ////////    EntityID aEndID   = changeEntity(aEndAttr);
672 ////////    GCS::Point* aStart = getPoint(aStartID);
673 ////////    GCS::Point* aEnd   = getPoint(aEndID);
674 ////////
675 ////////    std::shared_ptr<GCS::Line> aLine(new GCS::Line);
676 ////////    aLine->p1 = *aStart;
677 ////////    aLine->p2 = *aEnd;
678 ////////    myGCSEntities[theID] = aLine;
679 ////  }
680 ////  else {
681 ////    // update line parameters
682 ////    std::map<AttributePtr, EntityID>::iterator aFoundAttr = myAttributeEntityMap.find(aStartAttr);
683 ////    if (aFoundAttr != myAttributeEntityMap.end())
684 ////      updatePoint(aStartAttr, aFoundAttr->second);
685 ////    aFoundAttr = myAttributeEntityMap.find(aEndAttr);
686 ////    if (aFoundAttr != myAttributeEntityMap.end())
687 ////      updatePoint(aEndAttr, aFoundAttr->second);
688 ////  }
689 ////}
690 ////
691 ////void PlaneGCSSolver_Storage::updateCircle(const FeaturePtr& theCircle, EntityID& theID)
692 ////{
693 ////  std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
694 ////      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
695 ////      theCircle->attribute(SketchPlugin_Circle::CENTER_ID()));
696 ////  AttributeDoublePtr aRadiusAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
697 ////      theCircle->attribute(SketchPlugin_Circle::RADIUS_ID()));
698 ////  if (!aCenterAttr->isInitialized() || !aRadiusAttr->isInitialized()) {
699 ////    theID = ENTITY_UNKNOWN;
700 ////    return;
701 ////  }
702 ////
703 ////  std::map<EntityID, GCSCurvePtr>::iterator aFound = myGCSEntities.find(theID);
704 ////  if (aFound == myGCSEntities.end()) {
705 ////////    // new circle
706 ////////    theID = ++myEntityLastID;
707 ////////    theID.type = CIRCLE;
708 ////////
709 ////////    EntityID aCenterID = changeEntity(aCenterAttr);
710 ////////    EntityID aRadiusID = changeEntity(aRadiusAttr);
711 ////////    GCS::Point* aCenter = getPoint(aCenterID);
712 ////////    double* aRadius = getScalar(aRadiusID);
713 ////////
714 ////////    std::shared_ptr<GCS::Circle> aCircle(new GCS::Circle);
715 ////////    aCircle->center = *aCenter;
716 ////////    aCircle->rad = aRadius;
717 ////////    myGCSEntities[theID] = aCircle;
718 ////  }
719 ////  else {
720 ////    // update circle parameters
721 ////    std::map<AttributePtr, EntityID>::iterator aFoundAttr = myAttributeEntityMap.find(aCenterAttr);
722 ////    if (aFoundAttr != myAttributeEntityMap.end())
723 ////      updatePoint(aCenterAttr, aFoundAttr->second);
724 ////    aFoundAttr = myAttributeEntityMap.find(aRadiusAttr);
725 ////    if (aFoundAttr != myAttributeEntityMap.end())
726 ////      updateScalar(aRadiusAttr, aFoundAttr->second);
727 ////  }
728 ////}
729 ////
730 ////void PlaneGCSSolver_Storage::updateArc(const FeaturePtr& theArc, EntityID& theID)
731 ////{
732 ////  std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
733 ////      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
734 ////      theArc->attribute(SketchPlugin_Arc::CENTER_ID()));
735 ////  std::shared_ptr<GeomDataAPI_Point2D> aStartAttr =
736 ////      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
737 ////      theArc->attribute(SketchPlugin_Arc::START_ID()));
738 ////  std::shared_ptr<GeomDataAPI_Point2D> aEndAttr =
739 ////      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
740 ////      theArc->attribute(SketchPlugin_Arc::END_ID()));
741 ////  if (!aCenterAttr->isInitialized() ||
742 ////      !aStartAttr->isInitialized()  ||
743 ////      !aEndAttr->isInitialized()) {
744 ////    theID = ENTITY_UNKNOWN;
745 ////    return;
746 ////  }
747 ////
748 ////  std::shared_ptr<GCS::Arc> anArc;
749 ////  std::map<EntityID, GCSCurvePtr>::iterator aFound = myGCSEntities.find(theID);
750 ////  if (aFound == myGCSEntities.end()) {
751 ////    // new arc
752 ////    theID = ++myEntityLastID;
753 ////    theID.type = ARC;
754 ////
755 ////    EntityID aCenterID = changeEntity(aCenterAttr);
756 ////    EntityID aStartID  = changeEntity(aStartAttr);
757 ////    EntityID aEndID    = changeEntity(aEndAttr);
758 ////    GCS::Point* aCenter = getPoint(aCenterID);
759 ////    GCS::Point* aStart  = getPoint(aStartID);
760 ////    GCS::Point* aEnd    = getPoint(aEndID);
761 ////
762 ////    anArc = std::shared_ptr<GCS::Arc>(new GCS::Arc);
763 ////    anArc->center = *aCenter;
764 ////    anArc->start  = *aStart;
765 ////    anArc->end    = *aEnd;
766 ////    anArc->startAngle = createScalar();
767 ////    anArc->endAngle   = createScalar();
768 ////    anArc->rad        = createScalar();
769 ////    myGCSEntities[theID] = anArc;
770 ////
771 ////    // Additional constraints for new arc
772 ////    processArc(theID);
773 ////  }
774 ////  else {
775 ////    // update arc parameters
776 ////    anArc = std::dynamic_pointer_cast<GCS::Arc>(aFound->second);
777 ////    std::map<AttributePtr, EntityID>::iterator aFoundAttr = myAttributeEntityMap.find(aCenterAttr);
778 ////    if (aFoundAttr != myAttributeEntityMap.end())
779 ////      updatePoint(aCenterAttr, aFoundAttr->second);
780 ////    aFoundAttr = myAttributeEntityMap.find(aStartAttr);
781 ////    if (aFoundAttr != myAttributeEntityMap.end())
782 ////      updatePoint(aStartAttr, aFoundAttr->second);
783 ////    aFoundAttr = myAttributeEntityMap.find(aEndAttr);
784 ////    if (aFoundAttr != myAttributeEntityMap.end())
785 ////      updatePoint(aEndAttr, aFoundAttr->second);
786 ////  }
787 ////
788 ////  // Calculate additional parameters necessary for FreeGCS
789 ////  std::shared_ptr<GeomAPI_Pnt2d> aCenterPnt = aCenterAttr->pnt();
790 ////  std::shared_ptr<GeomAPI_Pnt2d> aStartPnt  = aStartAttr->pnt();
791 ////  std::shared_ptr<GeomAPI_Pnt2d> aEndPnt    = aEndAttr->pnt();
792 ////
793 ////  *(anArc->rad) = aCenterPnt->distance(aStartPnt);
794 ////  std::shared_ptr<GeomAPI_Edge> anArcEdge =
795 ////      std::dynamic_pointer_cast<GeomAPI_Edge>(theArc->lastResult()->shape());
796 ////  if (!anArcEdge) {
797 ////    theID = ENTITY_UNKNOWN;
798 ////    return;
799 ////  }
800 ////  anArcEdge->getRange(*(anArc->startAngle), *(anArc->endAngle));
801 ////}
802
803
804 ////double* PlaneGCSSolver_Storage::getScalar(const EntityID& theID) const
805 ////{
806 ////  std::map<EntityID, double*>::const_iterator aFound = myGCSScalars.find(theID);
807 ////  if (aFound == myGCSScalars.end())
808 ////    return 0;
809 ////  return aFound->second;
810 ////}
811 ////
812 ////GCS::Point* PlaneGCSSolver_Storage::getPoint(const EntityID& theID) const
813 ////{
814 ////  std::map<EntityID, GCSPointPtr>::const_iterator aFound = myGCSPoints.find(theID);
815 ////  if (aFound == myGCSPoints.end())
816 ////    return 0;
817 ////  return aFound->second.get();
818 ////}
819 ////
820 ////GCS::Line* PlaneGCSSolver_Storage::getLine(const EntityID& theID) const
821 ////{
822 ////  std::map<EntityID, GCSCurvePtr>::const_iterator aFound = myGCSEntities.find(theID);
823 ////  if (aFound == myGCSEntities.end())
824 ////    return 0;
825 ////  std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(aFound->second);
826 ////  if (!aLine)
827 ////    return 0;
828 ////  return aLine.get();
829 ////}
830 ////
831 ////GCS::Circle* PlaneGCSSolver_Storage::getCircle(const EntityID& theID) const
832 ////{
833 ////  std::map<EntityID, GCSCurvePtr>::const_iterator aFound = myGCSEntities.find(theID);
834 ////  if (aFound == myGCSEntities.end())
835 ////    return 0;
836 ////  std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(aFound->second);
837 ////  if (!aCircle)
838 ////    return 0;
839 ////  return aCircle.get();
840 ////}
841 ////
842 ////GCS::Arc* PlaneGCSSolver_Storage::getArc(const EntityID& theID) const
843 ////{
844 ////  std::map<EntityID, GCSCurvePtr>::const_iterator aFound = myGCSEntities.find(theID);
845 ////  if (aFound == myGCSEntities.end())
846 ////    return 0;
847 ////  std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(aFound->second);
848 ////  if (!anArc)
849 ////    return 0;
850 ////  return anArc.get();
851 ////}
852
853 void PlaneGCSSolver_Storage::processArc(const EntityWrapperPtr& theArc)
854 {
855   // Calculate additional parameters necessary for PlaneGCS
856   const std::list<EntityWrapperPtr>& aSubs = theArc->subEntities();
857   std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
858   while ((*aSubIt)->type() == ENTITY_POINT) // search scalar entities
859     ++aSubIt;
860   double* aStartAngle = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
861   double* aEndAngle   = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
862   double* aRadius     = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt)->scalar();
863
864   FeaturePtr anArcFeature = theArc->baseFeature();
865   std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
866       anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
867   std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
868       anArcFeature->attribute(SketchPlugin_Arc::START_ID()));
869   std::shared_ptr<GeomDataAPI_Point2D> aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
870       anArcFeature->attribute(SketchPlugin_Arc::END_ID()));
871   std::shared_ptr<GeomAPI_Pnt2d> aCenterPnt = aCenterAttr->pnt();
872   std::shared_ptr<GeomAPI_Pnt2d> aStartPnt  = aStartAttr->pnt();
873   std::shared_ptr<GeomAPI_Pnt2d> aEndPnt    = aEndAttr->pnt();
874
875   *aRadius = aCenterPnt->distance(aStartPnt);
876   if (!anArcFeature->lastResult())
877     return;
878   std::shared_ptr<GeomAPI_Edge> anArcEdge =
879       std::dynamic_pointer_cast<GeomAPI_Edge>(anArcFeature->lastResult()->shape());
880   if (!anArcEdge)
881     return;
882   anArcEdge->getRange(*aStartAngle, *aEndAngle);
883
884   // No need to add constraints if they are already exist
885   std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
886       aFound = myArcConstraintMap.find(theArc);
887   if (aFound != myArcConstraintMap.end())
888     return;
889
890   // Prepare additional constraints to produce the arc
891   std::vector<GCSConstraintPtr> anArcConstraints;
892   std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt =
893       std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theArc);
894   std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt->entity());
895   // Distances from center till start and end points are equal to radius
896   anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
897       anArc->center, anArc->start, anArc->rad)));
898   anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
899       anArc->center, anArc->end, anArc->rad)));
900   // Angles of start and end points should be equal to given angles
901   anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
902       anArc->center, anArc->start, anArc->startAngle)));
903   anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
904       anArc->center, anArc->end, anArc->endAngle)));
905
906   myArcConstraintMap[theArc] = anArcConstraints;
907 }
908
909 ////const std::vector<GCSConstraintPtr>& PlaneGCSSolver_Storage::getConstraint(
910 ////    const ConstraintPtr& theConstraint) const
911 ////{
912 ////  static const std::vector<GCSConstraintPtr> aDummy;
913 ////
914 ////  std::map<ConstraintPtr, std::vector<GCSConstraintPtr> >::const_iterator
915 ////      aFound = myConstraintsMap.find(theConstraint);
916 ////  if (aFound == myConstraintsMap.end())
917 ////    return aDummy;
918 ////  return aFound->second;
919 ////}
920
921
922 void PlaneGCSSolver_Storage::makeConstant(const EntityWrapperPtr& theEntity)
923 {
924   toggleEntity(theEntity, myParameters, myConst);
925 }
926
927 void PlaneGCSSolver_Storage::makeVariable(const EntityWrapperPtr& theEntity)
928 {
929   toggleEntity(theEntity, myConst, myParameters);
930 }
931
932 static void getParametersToMove(const EntityWrapperPtr& theEntity, std::set<double*>& theParamList)
933 {
934   const std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
935   std::list<ParameterWrapperPtr>::const_iterator aPIt = aParams.begin();
936   for (; aPIt != aParams.end(); ++aPIt)
937     theParamList.insert(
938         std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*aPIt)->parameter());
939
940   const std::list<EntityWrapperPtr> aSubs = theEntity->subEntities();
941   std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
942   for (; aSIt != aSubs.end(); ++aSIt)
943     getParametersToMove(*aSIt, theParamList);
944 }
945
946 void PlaneGCSSolver_Storage::toggleEntity(
947     const EntityWrapperPtr& theEntity, GCS::VEC_pD& theFrom, GCS::VEC_pD& theTo)
948 {
949   std::set<double*> aParamsToMove;
950   getParametersToMove(theEntity, aParamsToMove);
951
952   GCS::VEC_pD::iterator anIt = theFrom.begin();
953   while (anIt != theFrom.end()) {
954     if (aParamsToMove.find(*anIt) == aParamsToMove.end()) {
955       ++anIt;
956       continue;
957     }
958
959     theTo.push_back(*anIt);
960     int aShift = anIt - theFrom.begin();
961     theFrom.erase(anIt);
962     anIt = theFrom.begin() + aShift;
963   }
964 }
965
966
967 void PlaneGCSSolver_Storage::initializeSolver(SolverPtr theSolver)
968 {
969   std::shared_ptr<PlaneGCSSolver_Solver> aSolver =
970       std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(theSolver);
971   if (!aSolver)
972     return;
973
974   if (myExistArc)
975     processArcs();
976
977   // initialize constraints
978   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
979       aCIt = myConstraintMap.begin();
980   for (; aCIt != myConstraintMap.end(); ++aCIt) {
981     std::list<ConstraintWrapperPtr>::const_iterator aCWIt = aCIt->second.begin();
982     for (; aCWIt != aCIt->second.end(); ++ aCWIt) {
983       std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aGCS =
984           std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(*aCWIt);
985       std::list<GCSConstraintPtr>::const_iterator anIt = aGCS->constraints().begin();
986       for (; anIt != aGCS->constraints().end(); ++anIt)
987         aSolver->addConstraint(*anIt);
988     }
989   }
990   // additional constraints for arcs
991   std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
992       anArcIt = myArcConstraintMap.begin();
993   for (; anArcIt != myArcConstraintMap.end(); ++anArcIt) {
994     std::vector<GCSConstraintPtr>::const_iterator anIt = anArcIt->second.begin();
995     for (; anIt != anArcIt->second.end(); ++anIt)
996       aSolver->addConstraint(*anIt);
997   }
998   // removed waste constraints
999   std::list<GCSConstraintPtr>::const_iterator aRemIt = myRemovedConstraints.begin();
1000   for (; aRemIt != myRemovedConstraints.end(); ++aRemIt)
1001     aSolver->removeConstraint(*aRemIt);
1002   myRemovedConstraints.clear();
1003 ////  // remove waste parameters
1004 ////  std::list<double*>::const_iterator aRemParIt = myRemovedParameters.begin();
1005 ////  for (; aRemParIt != myRemovedParameters.end(); ++aRemParIt)
1006 ////    delete *aRemParIt;
1007 ////  myRemovedParameters.clear();
1008   // initialize unknowns
1009   aSolver->setParameters(myParameters);
1010 }
1011
1012 void PlaneGCSSolver_Storage::refresh(bool theFixedOnly) const
1013 {
1014   //blockEvents(true);
1015
1016   std::map<AttributePtr, EntityWrapperPtr>::const_iterator anIt = myAttributeMap.begin();
1017   std::list<ParameterWrapperPtr> aParams;
1018   std::list<ParameterWrapperPtr>::const_iterator aParIt;
1019   for (; anIt != myAttributeMap.end(); ++anIt) {
1020     // the external feature always should keep the up to date values, so, 
1021     // refresh from the solver is never needed
1022     if (anIt->first.get()) {
1023       std::shared_ptr<SketchPlugin_Feature> aSketchFeature = 
1024         std::dynamic_pointer_cast<SketchPlugin_Feature>(anIt->first->owner());
1025       if (aSketchFeature.get() && aSketchFeature->isExternal())
1026         continue;
1027     }
1028
1029     // update parameter wrappers and obtain values of attributes
1030     aParams = anIt->second->parameters();
1031     double aCoords[3];
1032     bool isUpd[3] = {false};
1033     int i = 0;
1034     for (aParIt = aParams.begin(); i < 3 && aParIt != aParams.end(); ++aParIt, ++i) {
1035       if (!theFixedOnly || (*aParIt)->group() == GID_OUTOFGROUP || (*aParIt)->isParametric()) {
1036         aCoords[i] = (*aParIt)->value();
1037         isUpd[i] = true;
1038       }
1039     }
1040     if (!isUpd[0] && !isUpd[1] && !isUpd[2])
1041       continue; // nothing is updated
1042
1043     std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
1044         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anIt->first);
1045     if (aPoint2D) {
1046       if ((isUpd[0] && fabs(aPoint2D->x() - aCoords[0]) > tolerance) ||
1047           (isUpd[1] && fabs(aPoint2D->y() - aCoords[1]) > tolerance)) {
1048         if (!isUpd[0]) aCoords[0] = aPoint2D->x();
1049         if (!isUpd[1]) aCoords[1] = aPoint2D->y();
1050         aPoint2D->setValue(aCoords[0], aCoords[1]);
1051         // Find points coincident with this one (probably not in GID_OUTOFGROUP)
1052         std::map<AttributePtr, EntityWrapperPtr>::const_iterator aLocIt =
1053             theFixedOnly ? myAttributeMap.begin() : anIt;
1054         for (++aLocIt; aLocIt != myAttributeMap.end(); ++aLocIt)
1055           if (anIt->second->id() == aLocIt->second->id()) {
1056             aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aLocIt->first);
1057             if (aPoint2D)
1058               aPoint2D->setValue(aCoords[0], aCoords[1]);
1059           }
1060       }
1061       continue;
1062     }
1063     AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anIt->first);
1064     if (aScalar) {
1065       if (isUpd[0] && fabs(aScalar->value() - aCoords[0]) > tolerance)
1066         aScalar->setValue(aCoords[0]);
1067       continue;
1068     }
1069   }
1070
1071   //blockEvents(false);
1072 }
1073
1074 EntityWrapperPtr PlaneGCSSolver_Storage::calculateMiddlePoint(
1075     EntityWrapperPtr theBase, double theCoeff)
1076 {
1077   std::shared_ptr<PlaneGCSSolver_Builder> aBuilder =
1078       std::dynamic_pointer_cast<PlaneGCSSolver_Builder>(PlaneGCSSolver_Builder::getInstance());
1079
1080   std::shared_ptr<GeomAPI_XY> aMidPoint;
1081   if (theBase->type() == ENTITY_LINE) {
1082     std::shared_ptr<GeomAPI_Pnt2d> aPoints[2];
1083     const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
1084     std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
1085     for (int i = 0; i < 2; ++i, ++anIt)
1086       aPoints[i] = aBuilder->point(*anIt);
1087     aMidPoint = aPoints[0]->xy()->multiplied(1.0 - theCoeff)->added(
1088         aPoints[1]->xy()->multiplied(theCoeff));
1089   }
1090   else if (theBase->type() == ENTITY_ARC) {
1091     double theX, theY;
1092     double anArcPoint[3][2];
1093     const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
1094     std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
1095     for (int i = 0; i < 3; ++i, ++anIt) {
1096       std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(*anIt);
1097       anArcPoint[i][0] = aPoint->x();
1098       anArcPoint[i][1] = aPoint->y();
1099     }
1100     // project last point of arc on the arc
1101     double x = anArcPoint[1][0] - anArcPoint[0][0];
1102     double y = anArcPoint[1][1] - anArcPoint[0][1];
1103     double aRad = sqrt(x*x + y*y);
1104     x = anArcPoint[2][0] - anArcPoint[0][0];
1105     y = anArcPoint[2][1] - anArcPoint[0][1];
1106     double aNorm = sqrt(x*x + y*y);
1107     if (aNorm >= tolerance) {
1108       anArcPoint[2][0] = x * aRad / aNorm;
1109       anArcPoint[2][1] = y * aRad / aNorm;
1110     }
1111     anArcPoint[1][0] -= anArcPoint[0][0];
1112     anArcPoint[1][1] -= anArcPoint[0][1];
1113     if (theCoeff < tolerance) {
1114       theX = anArcPoint[0][0] + anArcPoint[1][0];
1115       theY = anArcPoint[0][1] + anArcPoint[1][1];
1116     } else if (1 - theCoeff < tolerance) {
1117       theX = anArcPoint[0][0] + anArcPoint[2][0];
1118       theY = anArcPoint[0][1] + anArcPoint[2][1];
1119     } else {
1120       std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
1121       std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
1122       double anAngle = aStartDir->angle(aEndDir);
1123       if (anAngle < 0)
1124         anAngle += 2.0 * PI;
1125       anAngle *= theCoeff;
1126       double aCos = cos(anAngle);
1127       double aSin = sin(anAngle);
1128       theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
1129       theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
1130     }
1131     aMidPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(theX, theY));
1132   }
1133
1134   if (!aMidPoint)
1135     return EntityWrapperPtr();
1136
1137   std::list<ParameterWrapperPtr> aParameters;
1138   aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->x()));
1139   aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->y()));
1140   // Create entity (parameters are not filled)
1141   GCSPointPtr aPnt(new GCS::Point);
1142   aPnt->x = std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
1143   aPnt->y = std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
1144
1145   EntityWrapperPtr aResult(new PlaneGCSSolver_PointWrapper(AttributePtr(), aPnt));
1146   aResult->setGroup(myGroupID);
1147   aResult->setParameters(aParameters);
1148
1149   update(aResult);
1150   return aResult;
1151 }
1152
1153 ////bool PlaneGCSSolver_Storage::isInteract(AttributePtr theAttribute) const
1154 ////{
1155 ////  std::map<AttributePtr, EntityID>::const_iterator aFound = myAttributeEntityMap.find(theAttribute);
1156 ////  if (aFound != myAttributeEntityMap.end())
1157 ////    return true;
1158 ////
1159 ////  AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
1160 ////  if (!aRefAttr)
1161 ////    return false;
1162 ////  if (aRefAttr->isObject()) {
1163 ////    FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
1164 ////    if (!aFeature)
1165 ////      return false;
1166 ////    return isInteract(aFeature);
1167 ////  }
1168 ////
1169 ////  return isInteract(aRefAttr->attr());
1170 ////}
1171 ////
1172 ////bool PlaneGCSSolver_Storage::isInteract(FeaturePtr theFeature) const
1173 ////{
1174 ////  if (myFeatureEntityMap.find(theFeature) != myFeatureEntityMap.end())
1175 ////    return true;
1176 ////  std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
1177 ////  std::list<AttributePtr>::iterator anIt = anAttributes.begin();
1178 ////  for (; anIt != anAttributes.end(); ++anIt)
1179 ////    if (isInteract(*anIt))
1180 ////      return true;
1181 ////  return false;
1182 ////}
1183
1184
1185 ////bool PlaneGCSSolver_Storage::isUsed(const FeaturePtr& theFeature) const
1186 ////{
1187 ////  // There is checked only the feature itself, not its attributes.
1188 ////  // The attributes should be checked separately.
1189 ////
1190 ////  std::map<ConstraintPtr, std::vector<GCSConstraintPtr> >::const_iterator
1191 ////      aCIt = myConstraintsMap.begin();
1192 ////  for (; aCIt != myConstraintsMap.end(); ++aCIt) {
1193 ////    if (!aCIt->first)
1194 ////      continue;
1195 ////    for (int ind = 0; ind < CONSTRAINT_ATTR_SIZE; ++ind) {
1196 ////      AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1197 ////          aCIt->first->attribute(SketchPlugin_Constraint::ATTRIBUTE(ind)));
1198 ////      if (aRefAttr && aRefAttr->isObject()) {
1199 ////        FeaturePtr aFeat = ModelAPI_Feature::feature(aRefAttr->object());
1200 ////        if (aFeat == theFeature)
1201 ////          return true;
1202 ////      }
1203 ////    }
1204 ////  }
1205 ////  return false;
1206 ////}
1207 ////
1208 ////bool PlaneGCSSolver_Storage::isUsed(const AttributePtr& theAttribute) const
1209 ////{
1210 ////  // Check whether the attribute is used by constraints
1211 ////  std::map<ConstraintPtr, std::vector<GCSConstraintPtr> >::const_iterator
1212 ////      aCIt = myConstraintsMap.begin();
1213 ////  for (; aCIt != myConstraintsMap.end(); ++aCIt) {
1214 ////    if (!aCIt->first)
1215 ////      continue;
1216 ////    if (aCIt->first->attribute(SketchPlugin_Constraint::VALUE()) == theAttribute)
1217 ////      return true;
1218 ////    for (int ind = 0; ind < CONSTRAINT_ATTR_SIZE; ++ind) {
1219 ////      AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1220 ////          aCIt->first->attribute(SketchPlugin_Constraint::ATTRIBUTE(ind)));
1221 ////      if (!aRefAttr)
1222 ////        continue;
1223 ////      if (aRefAttr == theAttribute ||
1224 ////         (!aRefAttr->isObject() && aRefAttr->attr() == theAttribute))
1225 ////        return true;
1226 ////    }
1227 ////  }
1228 ////
1229 ////  // Check whether the attribute is used by features
1230 ////  std::map<FeaturePtr, EntityID>::const_iterator aFIt = myFeatureEntityMap.begin();
1231 ////  for (; aFIt != myFeatureEntityMap.end(); ++aFIt) {
1232 ////    std::list<AttributePtr> anAttrs =
1233 ////        aFIt->first->data()->attributes(GeomDataAPI_Point2D::typeId());
1234 ////    std::list<AttributePtr>::const_iterator anIt = anAttrs.begin();
1235 ////    for (; anIt != anAttrs.end(); ++anIt)
1236 ////      if (*anIt == theAttribute)
1237 ////        return true;
1238 ////  }
1239 ////
1240 ////  return false;
1241 ////}
1242
1243
1244 ////void PlaneGCSSolver_Storage::blockEvents(bool isBlocked)
1245 ////{
1246 ////  std::map<FeaturePtr, EntityID>::iterator aFIt = myFeatureEntityMap.begin();
1247 ////  for (; aFIt != myFeatureEntityMap.end(); ++aFIt)
1248 ////    if (aFIt->first->data() && aFIt->first->data()->isValid())
1249 ////      aFIt->first->data()->blockSendAttributeUpdated(isBlocked);
1250 ////
1251 ////  std::map<AttributePtr, EntityID>::iterator anAIt = myAttributeEntityMap.begin();
1252 ////  for (; anAIt != myAttributeEntityMap.end(); ++anAIt)
1253 ////    if (anAIt->first->owner() && anAIt->first->owner()->data() &&
1254 ////        anAIt->first->owner()->data()->isValid())
1255 ////      anAIt->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
1256 ////}
1257
1258
1259 #else
1260
1261 #endif