1 // Copyright (C) 2014-2019 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include <PlaneGCSSolver_Storage.h>
21 #include <PlaneGCSSolver_Solver.h>
22 #include <PlaneGCSSolver_BooleanWrapper.h>
23 #include <PlaneGCSSolver_ConstraintWrapper.h>
24 #include <PlaneGCSSolver_EdgeWrapper.h>
25 #include <PlaneGCSSolver_PointWrapper.h>
26 #include <PlaneGCSSolver_Tools.h>
28 #include <PlaneGCSSolver_AttributeBuilder.h>
29 #include <PlaneGCSSolver_FeatureBuilder.h>
30 #include <PlaneGCSSolver_EntityDestroyer.h>
32 #include <GeomAPI_Dir2d.h>
33 #include <GeomAPI_Pnt2d.h>
34 #include <GeomAPI_XY.h>
35 #include <GeomDataAPI_Point2D.h>
36 #include <ModelAPI_AttributeRefAttr.h>
37 #include <SketchPlugin_Ellipse.h>
38 #include <SketchPlugin_Projection.h>
43 static void constraintsToSolver(const ConstraintWrapperPtr& theConstraint,
44 const SolverPtr& theSolver)
46 const std::list<GCSConstraintPtr>& aConstraints =
47 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint)->constraints();
48 theSolver->addConstraint(theConstraint->id(), aConstraints);
52 PlaneGCSSolver_Storage::PlaneGCSSolver_Storage(const SolverPtr& theSolver)
53 : SketchSolver_Storage(theSolver),
54 myConstraintLastID(CID_UNKNOWN)
58 void PlaneGCSSolver_Storage::addConstraint(
59 ConstraintPtr theConstraint,
60 ConstraintWrapperPtr theSolverConstraint)
62 SketchSolver_Storage::addConstraint(theConstraint, theSolverConstraint);
64 theSolverConstraint->setId(++myConstraintLastID);
65 constraintsToSolver(theSolverConstraint, mySketchSolver);
68 void PlaneGCSSolver_Storage::addMovementConstraint(
69 const ConstraintWrapperPtr& theSolverConstraint)
71 // before adding movement constraint to solver, re-check its DOF
72 if (mySketchSolver->dof() == 0)
73 mySketchSolver->diagnose();
75 theSolverConstraint->setId(CID_MOVEMENT);
76 constraintsToSolver(theSolverConstraint, mySketchSolver);
80 EntityWrapperPtr PlaneGCSSolver_Storage::createFeature(
81 const FeaturePtr& theFeature,
82 PlaneGCSSolver_EntityBuilder* theBuilder)
84 std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
85 std::list<AttributePtr>::const_iterator anIt = anAttributes.begin();
86 for (; anIt != anAttributes.end(); ++anIt)
87 createAttribute(*anIt, theBuilder);
89 EntityWrapperPtr aResult = theBuilder->createFeature(theFeature);
91 addEntity(theFeature, aResult);
95 EntityWrapperPtr PlaneGCSSolver_Storage::createAttribute(
96 const AttributePtr& theAttribute,
97 PlaneGCSSolver_EntityBuilder* theBuilder)
99 EntityWrapperPtr aResult = theBuilder->createAttribute(theAttribute);
101 addEntity(theAttribute, aResult);
105 /// \brief Update value
106 static bool updateValue(const double& theSource, double& theDest)
108 static const double aTol = 1.e4 * tolerance;
109 bool isUpdated = fabs(theSource - theDest) > aTol;
115 /// \brief Update coordinates of the point or scalar using its base attribute
116 static bool updateValues(AttributePtr& theAttribute, EntityWrapperPtr& theEntity)
118 bool isUpdated = false;
120 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
121 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
123 const GCSPointPtr& aGCSPoint =
124 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity)->point();
125 isUpdated = updateValue(aPoint2D->x(), *(aGCSPoint->x)) || isUpdated;
126 isUpdated = updateValue(aPoint2D->y(), *(aGCSPoint->y)) || isUpdated;
128 AttributeDoublePtr aScalar =
129 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
131 ScalarWrapperPtr aWrapper =
132 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(theEntity);
133 // There is possible angular value, which is converted between degrees and radians.
134 // So, we use its value instead of using direct pointer to value.
135 double aValue = aWrapper->value();
136 isUpdated = updateValue(aScalar->value(), aValue);
138 aWrapper->setValue(aValue);
140 AttributeBooleanPtr aBoolean =
141 std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(theAttribute);
143 BooleanWrapperPtr aWrapper =
144 std::dynamic_pointer_cast<PlaneGCSSolver_BooleanWrapper>(theEntity);
145 isUpdated = aWrapper->value() != aBoolean->value();
146 aWrapper->setValue(aBoolean->value());
154 static bool hasReference(std::shared_ptr<SketchPlugin_Feature> theFeature,
155 const std::string& theFeatureKind)
157 const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
158 for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
159 aRefIt != aRefs.end(); ++aRefIt) {
160 FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
161 if (anOwner && anOwner->getKind() == theFeatureKind)
167 static bool isCopyFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
169 return theFeature && theFeature->isCopy();
172 bool PlaneGCSSolver_Storage::update(FeaturePtr theFeature, bool theForce)
174 bool sendNotify = false;
175 bool isUpdated = false;
176 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
177 std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
178 EntityWrapperPtr aRelated = entity(theFeature);
179 if (aRelated) // send signal to subscribers
181 else { // Feature is not exist, create it
182 bool isCopy = isCopyFeature(aSketchFeature);
183 bool isProjReferred = hasReference(aSketchFeature, SketchPlugin_Projection::ID());
184 // the feature is a copy in "Multi" constraint and does not used in other constraints
185 if (!theForce && (isCopy && !isProjReferred) &&
186 myFeatureMap.find(theFeature) == myFeatureMap.end())
189 // external feature processing
191 (aSketchFeature && (aSketchFeature->isExternal() || isCopy || isProjReferred));
193 PlaneGCSSolver_FeatureBuilder aBuilder(isExternal ? 0 : this);
195 // Reserve the feature in the map of features
196 // (do not want to add several copies of it while adding attributes)
197 aRelated = createFeature(theFeature, &aBuilder);
198 myFeatureMap[theFeature] = aRelated;
199 createAuxiliaryConstraints(aRelated);
203 std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
204 std::list<AttributePtr>::iterator anAttrIt = anAttributes.begin();
205 for (; anAttrIt != anAttributes.end(); ++anAttrIt)
206 if ((*anAttrIt)->attributeType() == GeomDataAPI_Point2D::typeId() ||
207 (*anAttrIt)->attributeType() == ModelAPI_AttributeDouble::typeId() ||
208 (*anAttrIt)->attributeType() == ModelAPI_AttributeBoolean::typeId())
209 isUpdated = update(*anAttrIt) || isUpdated;
211 // check external attribute is changed
212 bool isExternal = aSketchFeature &&
213 (aSketchFeature->isExternal() || isCopyFeature(aSketchFeature));
214 if (aRelated && isExternal != aRelated->isExternal()) {
216 makeExternal(aRelated);
218 makeNonExternal(aRelated);
222 // send notification to listeners due to at least one attribute is changed
223 if (sendNotify && isUpdated)
228 PlaneGCSSolver_Tools::recalculateArcParameters(aRelated);
233 bool PlaneGCSSolver_Storage::update(AttributePtr theAttribute, bool theForce)
235 if (!theAttribute->isInitialized())
238 AttributePtr anAttribute = theAttribute;
239 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
241 if (aRefAttr->isObject()) {
243 /// TODO: Check resultToFeatureOrAttribute() precisely.
244 resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute);
246 return update(aFeature, theForce);
248 anAttribute = aRefAttr->attr();
251 EntityWrapperPtr aRelated = entity(anAttribute);
252 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
253 if (!aRelated) { // Attribute does not exist, create it.
254 // First of all check if the parent feature exists. If not, add it.
255 if (aFeature && myFeatureMap.find(aFeature) == myFeatureMap.end())
256 return update(aFeature, theForce); // theAttribute has been processed while adding feature
257 return aRelated.get() != 0;
260 bool isUpdated = updateValues(anAttribute, aRelated);
262 setNeedToResolve(true);
268 void PlaneGCSSolver_Storage::makeExternal(const EntityWrapperPtr& theEntity)
270 if (theEntity->isExternal())
273 removeAuxiliaryConstraints(theEntity);
275 GCS::SET_pD aParameters = PlaneGCSSolver_Tools::parameters(theEntity);
276 mySketchSolver->removeParameters(aParameters);
277 theEntity->setExternal(true);
278 myNeedToResolve = true;
281 void PlaneGCSSolver_Storage::makeNonExternal(const EntityWrapperPtr& theEntity)
283 if (!theEntity->isExternal())
286 GCS::SET_pD aParameters = PlaneGCSSolver_Tools::parameters(theEntity);
287 mySketchSolver->addParameters(aParameters);
288 theEntity->setExternal(false);
290 createAuxiliaryConstraints(theEntity);
292 myNeedToResolve = true;
296 static void createArcConstraints(const EntityWrapperPtr& theArc,
297 const SolverPtr& theSolver,
298 const ConstraintID theConstraintID,
299 std::map<EntityWrapperPtr, ConstraintWrapperPtr>& theConstraints)
301 EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theArc);
302 std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEdge->entity());
304 // Additional constaints to fix arc's extra DoF (if the arc is not external):
305 std::list<GCSConstraintPtr> anArcConstraints;
306 // 1. distances from center till start and end points are equal to radius
307 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
308 anArc->center, anArc->start, anArc->rad)));
309 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
310 anArc->center, anArc->end, anArc->rad)));
311 // 2. angles of start and end points should be equal to the arc angles
312 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
313 anArc->center, anArc->start, anArc->startAngle)));
314 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
315 anArc->center, anArc->end, anArc->endAngle)));
317 ConstraintWrapperPtr aWrapper(
318 new PlaneGCSSolver_ConstraintWrapper(anArcConstraints, CONSTRAINT_UNKNOWN));
319 aWrapper->setId(theConstraintID);
320 constraintsToSolver(aWrapper, theSolver);
322 theConstraints[theArc] = aWrapper;
325 static void createEllipseConstraints(
326 const EntityWrapperPtr& theEllipse,
327 const SolverPtr& theSolver,
328 const ConstraintID theConstraintID,
329 std::map<EntityWrapperPtr, ConstraintWrapperPtr>& theConstraints)
331 EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEllipse);
332 std::shared_ptr<GCS::Ellipse> anEllipse =
333 std::dynamic_pointer_cast<GCS::Ellipse>(anEdge->entity());
335 // Additional constaints to fix ellipse's extra points
336 std::list<GCSConstraintPtr> anEllipseConstraints;
338 const std::map<std::string, EntityWrapperPtr>& anAttributes = theEllipse->additionalAttributes();
339 for (std::map<std::string, EntityWrapperPtr>::const_iterator anIt = anAttributes.begin();
340 anIt != anAttributes.end(); ++anIt) {
341 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
342 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
346 GCS::InternalAlignmentType anAlignmentX, anAlignmentY;
347 if (anIt->first == SketchPlugin_Ellipse::SECOND_FOCUS_ID())
348 anAlignmentX = GCS::EllipseFocus2X;
349 else if (anIt->first == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID())
350 anAlignmentX = GCS::EllipseNegativeMajorX;
351 else if (anIt->first == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID())
352 anAlignmentX = GCS::EllipsePositiveMajorX;
353 else if (anIt->first == SketchPlugin_Ellipse::MINOR_AXIS_START_ID())
354 anAlignmentX = GCS::EllipseNegativeMinorX;
355 else if (anIt->first == SketchPlugin_Ellipse::MINOR_AXIS_END_ID())
356 anAlignmentX = GCS::EllipsePositiveMinorX;
358 anEllipseConstraints.push_back(GCSConstraintPtr(
359 new GCS::ConstraintInternalAlignmentPoint2Ellipse(
360 *anEllipse, *(aPoint->point()), anAlignmentX)));
361 anAlignmentY = (GCS::InternalAlignmentType)((int)anAlignmentX + 1);
362 anEllipseConstraints.push_back(GCSConstraintPtr(
363 new GCS::ConstraintInternalAlignmentPoint2Ellipse(
364 *anEllipse, *(aPoint->point()), anAlignmentY)));
367 // constraint to bind the major radius value
368 std::shared_ptr<PlaneGCSSolver_PointWrapper> aMajorAxisStart =
369 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
370 anAttributes.at(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()));
371 ScalarWrapperPtr aMajorRadius =
372 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(
373 anAttributes.at(SketchPlugin_Ellipse::MAJOR_RADIUS_ID()));
374 anEllipseConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
375 anEllipse->center, *(aMajorAxisStart->point()), aMajorRadius->scalar())));
377 ConstraintWrapperPtr aWrapper(
378 new PlaneGCSSolver_ConstraintWrapper(anEllipseConstraints, CONSTRAINT_UNKNOWN));
379 aWrapper->setId(theConstraintID);
381 constraintsToSolver(aWrapper, theSolver);
383 theConstraints[theEllipse] = aWrapper;
386 static void createEllipticArcConstraints(
387 const EntityWrapperPtr& theEllipticArc,
388 const SolverPtr& theSolver,
389 const ConstraintID theConstraintID,
390 std::map<EntityWrapperPtr, ConstraintWrapperPtr>& theConstraints)
392 // create base constraints for the ellipse without adding them to solver
393 createEllipseConstraints(theEllipticArc, SolverPtr(), theConstraintID, theConstraints);
395 ConstraintWrapperPtr& aConstraint = theConstraints[theEllipticArc];
396 std::list<GCSConstraintPtr> anEllArcConstraints = aConstraint->constraints();
398 // constrain extremities of the elliptic arc
399 EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEllipticArc);
400 std::shared_ptr<GCS::ArcOfEllipse> anArc =
401 std::dynamic_pointer_cast<GCS::ArcOfEllipse>(anEdge->entity());
403 anEllArcConstraints.push_back(GCSConstraintPtr(
404 new GCS::ConstraintCurveValue(anArc->start, anArc->start.x, *anArc, anArc->startAngle)));
405 anEllArcConstraints.push_back(GCSConstraintPtr(
406 new GCS::ConstraintCurveValue(anArc->start, anArc->start.y, *anArc, anArc->startAngle)));
407 anEllArcConstraints.push_back(GCSConstraintPtr(
408 new GCS::ConstraintCurveValue(anArc->end, anArc->end.x, *anArc, anArc->endAngle)));
409 anEllArcConstraints.push_back(GCSConstraintPtr(
410 new GCS::ConstraintCurveValue(anArc->end, anArc->end.y, *anArc, anArc->endAngle)));
412 aConstraint->setConstraints(anEllArcConstraints);
413 constraintsToSolver(aConstraint, theSolver);
416 void PlaneGCSSolver_Storage::createAuxiliaryConstraints(const EntityWrapperPtr& theEntity)
418 if (!theEntity || theEntity->isExternal())
421 if (theEntity->type() == ENTITY_ARC)
422 createArcConstraints(theEntity, mySketchSolver, ++myConstraintLastID, myAuxConstraintMap);
423 else if (theEntity->type() == ENTITY_ELLIPSE)
424 createEllipseConstraints(theEntity, mySketchSolver, ++myConstraintLastID, myAuxConstraintMap);
425 else if (theEntity->type() == ENTITY_ELLIPTIC_ARC) {
426 createEllipticArcConstraints(theEntity, mySketchSolver,
427 ++myConstraintLastID, myAuxConstraintMap);
431 void PlaneGCSSolver_Storage::removeAuxiliaryConstraints(const EntityWrapperPtr& theEntity)
433 std::map<EntityWrapperPtr, ConstraintWrapperPtr>::iterator
434 aFound = myAuxConstraintMap.find(theEntity);
435 if (aFound != myAuxConstraintMap.end()) {
436 mySketchSolver->removeConstraint(aFound->second->id());
437 myAuxConstraintMap.erase(aFound);
441 template <typename ARCTYPE>
442 void adjustArcParametrization(ARCTYPE& theArc, bool theReversed)
444 // tune start angle of the arc to be in [0, 2PI]
445 while (*theArc.startAngle < -PI)
446 *theArc.startAngle += 2.0 * PI;
447 while (*theArc.startAngle >= PI)
448 *theArc.startAngle -= 2.0 * PI;
449 // adjust end angle of the arc
451 while (*theArc.endAngle > *theArc.startAngle)
452 *theArc.endAngle -= 2.0 * PI;
453 while (*theArc.endAngle + 2 * PI < *theArc.startAngle)
454 *theArc.endAngle += 2.0 * PI;
457 while (*theArc.endAngle < *theArc.startAngle)
458 *theArc.endAngle += 2.0 * PI;
459 while (*theArc.endAngle > *theArc.startAngle + 2 * PI)
460 *theArc.endAngle -= 2.0 * PI;
464 void PlaneGCSSolver_Storage::adjustParametrizationOfArcs()
466 std::map<EntityWrapperPtr, ConstraintWrapperPtr>::iterator anIt = myAuxConstraintMap.begin();
467 for (; anIt != myAuxConstraintMap.end(); ++anIt) {
468 EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(anIt->first);
469 std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEdge->entity());
471 adjustArcParametrization(*anArc, anEdge->isReversed());
473 std::shared_ptr<GCS::ArcOfEllipse> aEllArc =
474 std::dynamic_pointer_cast<GCS::ArcOfEllipse>(anEdge->entity());
476 adjustArcParametrization(*aEllArc, anEdge->isReversed());
480 // update parameters of Middle point constraint for point on arc
481 std::map<ConstraintPtr, ConstraintWrapperPtr>::iterator aCIt = myConstraintMap.begin();
482 for (; aCIt != myConstraintMap.end(); ++aCIt)
483 if (aCIt->second->type() == CONSTRAINT_MIDDLE_POINT) {
489 bool PlaneGCSSolver_Storage::removeConstraint(ConstraintPtr theConstraint)
491 std::map<ConstraintPtr, ConstraintWrapperPtr>::iterator
492 aFound = myConstraintMap.find(theConstraint);
493 if (aFound != myConstraintMap.end()) {
494 ConstraintWrapperPtr aCW = aFound->second;
495 ConstraintID anID = aCW->id();
497 // Remove solver's constraints
498 mySketchSolver->removeConstraint(anID);
500 // Remove value if exists
501 const ScalarWrapperPtr& aValue = aCW->valueParameter();
503 GCS::SET_pD aParToRemove;
504 aParToRemove.insert(aValue->scalar());
505 removeParameters(aParToRemove);
509 myConstraintMap.erase(aFound);
511 if (anID != CID_MOVEMENT)
512 myNeedToResolve = true;
515 notify(theConstraint);
520 void PlaneGCSSolver_Storage::removeInvalidEntities()
522 PlaneGCSSolver_EntityDestroyer aDestroyer;
524 // Remove invalid constraints
525 std::list<ConstraintPtr> anInvalidConstraints;
526 std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
527 aCIter = myConstraintMap.begin();
528 for (; aCIter != myConstraintMap.end(); ++aCIter)
529 if (!aCIter->first->data() || !aCIter->first->data()->isValid())
530 anInvalidConstraints.push_back(aCIter->first);
531 std::list<ConstraintPtr>::const_iterator anInvCIt = anInvalidConstraints.begin();
532 for (; anInvCIt != anInvalidConstraints.end(); ++anInvCIt)
533 removeConstraint(*anInvCIt);
535 // Remove invalid features
536 std::list<FeaturePtr> anInvalidFeatures;
537 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
538 for (; aFIter != myFeatureMap.end(); aFIter++)
539 if (!aFIter->first->data() || !aFIter->first->data()->isValid()) {
540 anInvalidFeatures.push_back(aFIter->first);
542 aDestroyer.remove(aFIter->second);
544 // remove invalid arc
545 removeAuxiliaryConstraints(aFIter->second);
547 std::list<FeaturePtr>::const_iterator anInvFIt = anInvalidFeatures.begin();
548 for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt)
549 removeFeature(*anInvFIt);
551 // Remove invalid attributes
552 std::list<AttributePtr> anInvalidAttributes;
553 std::map<AttributePtr, EntityWrapperPtr>::const_iterator anAttrIt = myAttributeMap.begin();
554 for (; anAttrIt != myAttributeMap.end(); ++anAttrIt) {
555 FeaturePtr anOwner = ModelAPI_Feature::feature(anAttrIt->first->owner());
556 if (!anOwner || !anOwner->data() || !anOwner->data()->isValid()) {
557 anInvalidAttributes.push_back(anAttrIt->first);
558 aDestroyer.remove(anAttrIt->second);
561 std::list<AttributePtr>::const_iterator anInvAtIt = anInvalidAttributes.begin();
562 for (; anInvAtIt != anInvalidAttributes.end(); ++anInvAtIt)
563 removeAttribute(*anInvAtIt);
565 // free memory occupied by parameters
566 removeParameters(aDestroyer.parametersToRemove());
568 /// TODO: Think on optimization of checking invalid features and attributes
573 double* PlaneGCSSolver_Storage::createParameter()
575 return mySketchSolver->createParameter();
578 void PlaneGCSSolver_Storage::removeParameters(const GCS::SET_pD& theParams)
580 mySketchSolver->removeParameters(theParams);
583 // indicates attribute containing in the external feature
584 static bool isExternalAttribute(const AttributePtr& theAttribute)
588 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
589 std::dynamic_pointer_cast<SketchPlugin_Feature>(theAttribute->owner());
590 return aSketchFeature.get() && aSketchFeature->isExternal();
593 static void addOwnerToSet(const AttributePtr& theAttribute, std::set<FeaturePtr>& theFeatures)
595 FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
597 theFeatures.insert(anOwner);
600 void PlaneGCSSolver_Storage::refresh() const
602 const double aTol = 1000. * tolerance; // tolerance to prevent frequent updates
604 std::set<FeaturePtr> anUpdatedFeatures;
606 std::map<AttributePtr, EntityWrapperPtr>::const_iterator anIt = myAttributeMap.begin();
607 for (; anIt != myAttributeMap.end(); ++anIt) {
608 if (!anIt->first->isInitialized())
611 // the external feature always should keep the up to date values, so,
612 // refresh from the solver is never needed
613 if (isExternalAttribute(anIt->first))
616 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
617 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anIt->first);
619 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPointWrapper =
620 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
621 GCSPointPtr aGCSPoint = aPointWrapper->point();
622 if (fabs(aPoint2D->x() - (*aGCSPoint->x)) > aTol ||
623 fabs(aPoint2D->y() - (*aGCSPoint->y)) > aTol) {
624 aPoint2D->setValue(*aGCSPoint->x, *aGCSPoint->y);
625 addOwnerToSet(anIt->first, anUpdatedFeatures);
629 AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anIt->first);
631 ScalarWrapperPtr aScalarWrapper =
632 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
633 if (fabs(aScalar->value() - aScalarWrapper->value()) > aTol) {
634 aScalar->setValue(aScalarWrapper->value());
635 addOwnerToSet(anIt->first, anUpdatedFeatures);
641 // notify listeners about features update
642 std::set<FeaturePtr>::const_iterator aFIt = anUpdatedFeatures.begin();
643 for (; aFIt != anUpdatedFeatures.end(); ++aFIt)
647 PlaneGCSSolver_Solver::SolveStatus PlaneGCSSolver_Storage::checkDegeneratedGeometry() const
649 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
650 for (; aFIt != myFeatureMap.end(); ++aFIt) {
651 EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(aFIt->second);
652 if (anEdge && anEdge->isDegenerated())
653 return PlaneGCSSolver_Solver::STATUS_DEGENERATED;
655 return PlaneGCSSolver_Solver::STATUS_OK;