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_PointArrayWrapper.h>
27 #include <PlaneGCSSolver_ScalarArrayWrapper.h>
28 #include <PlaneGCSSolver_Tools.h>
30 #include <PlaneGCSSolver_AttributeBuilder.h>
31 #include <PlaneGCSSolver_FeatureBuilder.h>
32 #include <PlaneGCSSolver_EntityDestroyer.h>
34 #include <GeomAPI_Dir2d.h>
35 #include <GeomAPI_Pnt2d.h>
36 #include <GeomAPI_XY.h>
37 #include <GeomDataAPI_Point2D.h>
38 #include <GeomDataAPI_Point2DArray.h>
39 #include <ModelAPI_AttributeDoubleArray.h>
40 #include <ModelAPI_AttributeRefAttr.h>
41 #include <SketchPlugin_Ellipse.h>
42 #include <SketchPlugin_Projection.h>
47 static void constraintsToSolver(const ConstraintWrapperPtr& theConstraint,
48 const SolverPtr& theSolver)
50 const std::list<GCSConstraintPtr>& aConstraints =
51 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint)->constraints();
52 theSolver->addConstraint(theConstraint->id(), aConstraints);
56 PlaneGCSSolver_Storage::PlaneGCSSolver_Storage(const SolverPtr& theSolver)
57 : SketchSolver_Storage(theSolver),
58 myConstraintLastID(CID_UNKNOWN)
62 void PlaneGCSSolver_Storage::addConstraint(
63 ConstraintPtr theConstraint,
64 ConstraintWrapperPtr theSolverConstraint)
66 SketchSolver_Storage::addConstraint(theConstraint, theSolverConstraint);
68 theSolverConstraint->setId(++myConstraintLastID);
69 constraintsToSolver(theSolverConstraint, mySketchSolver);
72 void PlaneGCSSolver_Storage::addMovementConstraint(
73 const ConstraintWrapperPtr& theSolverConstraint)
75 // before adding movement constraint to solver, re-check its DOF
76 if (mySketchSolver->dof() == 0)
77 mySketchSolver->diagnose();
79 theSolverConstraint->setId(CID_MOVEMENT);
80 constraintsToSolver(theSolverConstraint, mySketchSolver);
84 EntityWrapperPtr PlaneGCSSolver_Storage::createFeature(
85 const FeaturePtr& theFeature,
86 PlaneGCSSolver_EntityBuilder* theBuilder)
88 std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
89 std::list<AttributePtr>::const_iterator anIt = anAttributes.begin();
90 for (; anIt != anAttributes.end(); ++anIt)
91 createAttribute(*anIt, theBuilder);
93 EntityWrapperPtr aResult = theBuilder->createFeature(theFeature);
95 addEntity(theFeature, aResult);
99 EntityWrapperPtr PlaneGCSSolver_Storage::createAttribute(
100 const AttributePtr& theAttribute,
101 PlaneGCSSolver_EntityBuilder* theBuilder)
103 EntityWrapperPtr aResult = theBuilder->createAttribute(theAttribute);
105 addEntity(theAttribute, aResult);
109 static bool hasReference(std::shared_ptr<SketchPlugin_Feature> theFeature,
110 const std::string& theFeatureKind)
112 const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
113 for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
114 aRefIt != aRefs.end(); ++aRefIt) {
115 FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
116 if (anOwner && anOwner->getKind() == theFeatureKind)
122 static bool isCopyFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
124 return theFeature && theFeature->isCopy();
127 bool PlaneGCSSolver_Storage::update(FeaturePtr theFeature, bool theForce)
129 bool sendNotify = false;
130 bool isUpdated = false;
131 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
132 std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
133 EntityWrapperPtr aRelated = entity(theFeature);
134 if (aRelated) // send signal to subscribers
136 else { // Feature is not exist, create it
137 bool isCopy = isCopyFeature(aSketchFeature);
138 bool isProjReferred = hasReference(aSketchFeature, SketchPlugin_Projection::ID());
139 // the feature is a copy in "Multi" constraint and does not used in other constraints
140 if (!theForce && (isCopy && !isProjReferred) &&
141 myFeatureMap.find(theFeature) == myFeatureMap.end())
144 // external feature processing
146 (aSketchFeature && (aSketchFeature->isExternal() || isCopy || isProjReferred));
148 PlaneGCSSolver_FeatureBuilder aBuilder(isExternal ? 0 : this);
150 // Reserve the feature in the map of features
151 // (do not want to add several copies of it while adding attributes)
152 aRelated = createFeature(theFeature, &aBuilder);
153 myFeatureMap[theFeature] = aRelated;
154 createAuxiliaryConstraints(aRelated);
158 std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
159 std::list<AttributePtr>::iterator anAttrIt = anAttributes.begin();
160 for (; anAttrIt != anAttributes.end(); ++anAttrIt)
161 if (PlaneGCSSolver_Tools::isAttributeApplicable((*anAttrIt)->id(), theFeature->getKind()))
162 isUpdated = update(*anAttrIt) || isUpdated;
164 // check external attribute is changed
165 bool isExternal = aSketchFeature &&
166 (aSketchFeature->isExternal() || isCopyFeature(aSketchFeature));
167 if (aRelated && isExternal != aRelated->isExternal()) {
169 makeExternal(aRelated);
171 makeNonExternal(aRelated);
175 // send notification to listeners due to at least one attribute is changed
176 if (sendNotify && isUpdated)
181 PlaneGCSSolver_Tools::recalculateArcParameters(aRelated);
186 bool PlaneGCSSolver_Storage::update(AttributePtr theAttribute, bool theForce)
188 if (!theAttribute->isInitialized())
191 AttributePtr anAttribute = theAttribute;
192 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
194 if (aRefAttr->isObject()) {
196 /// TODO: Check resultToFeatureOrAttribute() precisely.
197 resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute);
199 return update(aFeature, theForce);
201 anAttribute = aRefAttr->attr();
204 EntityWrapperPtr aRelated = entity(anAttribute);
205 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
206 if (!aRelated) { // Attribute does not exist, create it.
207 // First of all check if the parent feature exists. If not, add it.
208 if (aFeature && myFeatureMap.find(aFeature) == myFeatureMap.end())
209 return update(aFeature, theForce); // theAttribute has been processed while adding feature
210 return aRelated.get() != 0;
213 PlaneGCSSolver_AttributeBuilder aBuilder(aRelated->isExternal() ? 0 : this);
214 bool isUpdated = aBuilder.updateAttribute(anAttribute, aRelated);
216 setNeedToResolve(true);
222 void PlaneGCSSolver_Storage::makeExternal(const EntityWrapperPtr& theEntity)
224 if (theEntity->isExternal())
227 removeAuxiliaryConstraints(theEntity);
229 GCS::SET_pD aParameters = PlaneGCSSolver_Tools::parameters(theEntity);
230 mySketchSolver->removeParameters(aParameters);
231 theEntity->setExternal(true);
232 myNeedToResolve = true;
235 void PlaneGCSSolver_Storage::makeNonExternal(const EntityWrapperPtr& theEntity)
237 if (!theEntity->isExternal())
240 GCS::SET_pD aParameters = PlaneGCSSolver_Tools::parameters(theEntity);
241 mySketchSolver->addParameters(aParameters);
242 theEntity->setExternal(false);
244 createAuxiliaryConstraints(theEntity);
246 myNeedToResolve = true;
250 static void createArcConstraints(const EntityWrapperPtr& theArc,
251 const SolverPtr& theSolver,
252 const ConstraintID theConstraintID,
253 std::map<EntityWrapperPtr, ConstraintWrapperPtr>& theConstraints)
255 EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theArc);
256 std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEdge->entity());
258 // Additional constaints to fix arc's extra DoF (if the arc is not external):
259 std::list<GCSConstraintPtr> anArcConstraints;
260 // 1. distances from center till start and end points are equal to radius
261 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
262 anArc->center, anArc->start, anArc->rad)));
263 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
264 anArc->center, anArc->end, anArc->rad)));
265 // 2. angles of start and end points should be equal to the arc angles
266 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
267 anArc->center, anArc->start, anArc->startAngle)));
268 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
269 anArc->center, anArc->end, anArc->endAngle)));
271 ConstraintWrapperPtr aWrapper(
272 new PlaneGCSSolver_ConstraintWrapper(anArcConstraints, CONSTRAINT_UNKNOWN));
273 aWrapper->setId(theConstraintID);
274 constraintsToSolver(aWrapper, theSolver);
276 theConstraints[theArc] = aWrapper;
279 static void createEllipseConstraints(
280 const EntityWrapperPtr& theEllipse,
281 const SolverPtr& theSolver,
282 const ConstraintID theConstraintID,
283 std::map<EntityWrapperPtr, ConstraintWrapperPtr>& theConstraints)
285 EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEllipse);
286 std::shared_ptr<GCS::Ellipse> anEllipse =
287 std::dynamic_pointer_cast<GCS::Ellipse>(anEdge->entity());
289 // Additional constaints to fix ellipse's extra points
290 std::list<GCSConstraintPtr> anEllipseConstraints;
292 const std::map<std::string, EntityWrapperPtr>& anAttributes = theEllipse->additionalAttributes();
293 for (std::map<std::string, EntityWrapperPtr>::const_iterator anIt = anAttributes.begin();
294 anIt != anAttributes.end(); ++anIt) {
295 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
296 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
300 GCS::InternalAlignmentType anAlignmentX, anAlignmentY;
301 if (anIt->first == SketchPlugin_Ellipse::SECOND_FOCUS_ID())
302 anAlignmentX = GCS::EllipseFocus2X;
303 else if (anIt->first == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID())
304 anAlignmentX = GCS::EllipseNegativeMajorX;
305 else if (anIt->first == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID())
306 anAlignmentX = GCS::EllipsePositiveMajorX;
307 else if (anIt->first == SketchPlugin_Ellipse::MINOR_AXIS_START_ID())
308 anAlignmentX = GCS::EllipseNegativeMinorX;
309 else if (anIt->first == SketchPlugin_Ellipse::MINOR_AXIS_END_ID())
310 anAlignmentX = GCS::EllipsePositiveMinorX;
312 anEllipseConstraints.push_back(GCSConstraintPtr(
313 new GCS::ConstraintInternalAlignmentPoint2Ellipse(
314 *anEllipse, *(aPoint->point()), anAlignmentX)));
315 anAlignmentY = (GCS::InternalAlignmentType)((int)anAlignmentX + 1);
316 anEllipseConstraints.push_back(GCSConstraintPtr(
317 new GCS::ConstraintInternalAlignmentPoint2Ellipse(
318 *anEllipse, *(aPoint->point()), anAlignmentY)));
321 // constraint to bind the major radius value
322 std::shared_ptr<PlaneGCSSolver_PointWrapper> aMajorAxisStart =
323 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
324 anAttributes.at(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()));
325 ScalarWrapperPtr aMajorRadius =
326 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(
327 anAttributes.at(SketchPlugin_Ellipse::MAJOR_RADIUS_ID()));
328 anEllipseConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
329 anEllipse->center, *(aMajorAxisStart->point()), aMajorRadius->scalar())));
331 ConstraintWrapperPtr aWrapper(
332 new PlaneGCSSolver_ConstraintWrapper(anEllipseConstraints, CONSTRAINT_UNKNOWN));
333 aWrapper->setId(theConstraintID);
335 constraintsToSolver(aWrapper, theSolver);
337 theConstraints[theEllipse] = aWrapper;
340 static void createEllipticArcConstraints(
341 const EntityWrapperPtr& theEllipticArc,
342 const SolverPtr& theSolver,
343 const ConstraintID theConstraintID,
344 std::map<EntityWrapperPtr, ConstraintWrapperPtr>& theConstraints)
346 // create base constraints for the ellipse without adding them to solver
347 createEllipseConstraints(theEllipticArc, SolverPtr(), theConstraintID, theConstraints);
349 ConstraintWrapperPtr& aConstraint = theConstraints[theEllipticArc];
350 std::list<GCSConstraintPtr> anEllArcConstraints = aConstraint->constraints();
352 // constrain extremities of the elliptic arc
353 EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEllipticArc);
354 std::shared_ptr<GCS::ArcOfEllipse> anArc =
355 std::dynamic_pointer_cast<GCS::ArcOfEllipse>(anEdge->entity());
357 anEllArcConstraints.push_back(GCSConstraintPtr(
358 new GCS::ConstraintCurveValue(anArc->start, anArc->start.x, *anArc, anArc->startAngle)));
359 anEllArcConstraints.push_back(GCSConstraintPtr(
360 new GCS::ConstraintCurveValue(anArc->start, anArc->start.y, *anArc, anArc->startAngle)));
361 anEllArcConstraints.push_back(GCSConstraintPtr(
362 new GCS::ConstraintCurveValue(anArc->end, anArc->end.x, *anArc, anArc->endAngle)));
363 anEllArcConstraints.push_back(GCSConstraintPtr(
364 new GCS::ConstraintCurveValue(anArc->end, anArc->end.y, *anArc, anArc->endAngle)));
366 aConstraint->setConstraints(anEllArcConstraints);
367 constraintsToSolver(aConstraint, theSolver);
370 void PlaneGCSSolver_Storage::createAuxiliaryConstraints(const EntityWrapperPtr& theEntity)
372 if (!theEntity || theEntity->isExternal())
375 if (theEntity->type() == ENTITY_ARC)
376 createArcConstraints(theEntity, mySketchSolver, ++myConstraintLastID, myAuxConstraintMap);
377 else if (theEntity->type() == ENTITY_ELLIPSE)
378 createEllipseConstraints(theEntity, mySketchSolver, ++myConstraintLastID, myAuxConstraintMap);
379 else if (theEntity->type() == ENTITY_ELLIPTIC_ARC) {
380 createEllipticArcConstraints(theEntity, mySketchSolver,
381 ++myConstraintLastID, myAuxConstraintMap);
385 void PlaneGCSSolver_Storage::removeAuxiliaryConstraints(const EntityWrapperPtr& theEntity)
387 std::map<EntityWrapperPtr, ConstraintWrapperPtr>::iterator
388 aFound = myAuxConstraintMap.find(theEntity);
389 if (aFound != myAuxConstraintMap.end()) {
390 mySketchSolver->removeConstraint(aFound->second->id());
391 myAuxConstraintMap.erase(aFound);
395 template <typename ARCTYPE>
396 void adjustArcParametrization(ARCTYPE& theArc, bool theReversed)
398 // tune start angle of the arc to be in [0, 2PI]
399 while (*theArc.startAngle < -PI)
400 *theArc.startAngle += 2.0 * PI;
401 while (*theArc.startAngle >= PI)
402 *theArc.startAngle -= 2.0 * PI;
403 // adjust end angle of the arc
405 while (*theArc.endAngle > *theArc.startAngle)
406 *theArc.endAngle -= 2.0 * PI;
407 while (*theArc.endAngle + 2 * PI < *theArc.startAngle)
408 *theArc.endAngle += 2.0 * PI;
411 while (*theArc.endAngle < *theArc.startAngle)
412 *theArc.endAngle += 2.0 * PI;
413 while (*theArc.endAngle > *theArc.startAngle + 2 * PI)
414 *theArc.endAngle -= 2.0 * PI;
418 void PlaneGCSSolver_Storage::adjustParametrizationOfArcs()
420 std::map<EntityWrapperPtr, ConstraintWrapperPtr>::iterator anIt = myAuxConstraintMap.begin();
421 for (; anIt != myAuxConstraintMap.end(); ++anIt) {
422 EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(anIt->first);
423 std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEdge->entity());
425 adjustArcParametrization(*anArc, anEdge->isReversed());
427 std::shared_ptr<GCS::ArcOfEllipse> aEllArc =
428 std::dynamic_pointer_cast<GCS::ArcOfEllipse>(anEdge->entity());
430 adjustArcParametrization(*aEllArc, anEdge->isReversed());
434 // update parameters of Middle point constraint for point on arc
435 std::map<ConstraintPtr, ConstraintWrapperPtr>::iterator aCIt = myConstraintMap.begin();
436 for (; aCIt != myConstraintMap.end(); ++aCIt)
437 if (aCIt->second->type() == CONSTRAINT_MIDDLE_POINT) {
443 bool PlaneGCSSolver_Storage::removeConstraint(ConstraintPtr theConstraint)
445 std::map<ConstraintPtr, ConstraintWrapperPtr>::iterator
446 aFound = myConstraintMap.find(theConstraint);
447 if (aFound != myConstraintMap.end()) {
448 ConstraintWrapperPtr aCW = aFound->second;
449 ConstraintID anID = aCW->id();
451 // Remove solver's constraints
452 mySketchSolver->removeConstraint(anID);
454 // Remove value if exists
455 const ScalarWrapperPtr& aValue = aCW->valueParameter();
457 GCS::SET_pD aParToRemove;
458 aParToRemove.insert(aValue->scalar());
459 removeParameters(aParToRemove);
463 myConstraintMap.erase(aFound);
465 if (anID != CID_MOVEMENT)
466 myNeedToResolve = true;
469 notify(theConstraint);
474 void PlaneGCSSolver_Storage::removeInvalidEntities()
476 PlaneGCSSolver_EntityDestroyer aDestroyer;
478 // Remove invalid constraints
479 std::list<ConstraintPtr> anInvalidConstraints;
480 std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
481 aCIter = myConstraintMap.begin();
482 for (; aCIter != myConstraintMap.end(); ++aCIter)
483 if (!aCIter->first->data() || !aCIter->first->data()->isValid())
484 anInvalidConstraints.push_back(aCIter->first);
485 std::list<ConstraintPtr>::const_iterator anInvCIt = anInvalidConstraints.begin();
486 for (; anInvCIt != anInvalidConstraints.end(); ++anInvCIt)
487 removeConstraint(*anInvCIt);
489 // Remove invalid features
490 std::list<FeaturePtr> anInvalidFeatures;
491 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
492 for (; aFIter != myFeatureMap.end(); aFIter++)
493 if (!aFIter->first->data() || !aFIter->first->data()->isValid()) {
494 anInvalidFeatures.push_back(aFIter->first);
496 aDestroyer.remove(aFIter->second);
498 // remove invalid arc
499 removeAuxiliaryConstraints(aFIter->second);
501 std::list<FeaturePtr>::const_iterator anInvFIt = anInvalidFeatures.begin();
502 for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt)
503 removeFeature(*anInvFIt);
505 // Remove invalid attributes
506 std::list<AttributePtr> anInvalidAttributes;
507 std::map<AttributePtr, EntityWrapperPtr>::const_iterator anAttrIt = myAttributeMap.begin();
508 for (; anAttrIt != myAttributeMap.end(); ++anAttrIt) {
509 FeaturePtr anOwner = ModelAPI_Feature::feature(anAttrIt->first->owner());
510 if (!anOwner || !anOwner->data() || !anOwner->data()->isValid()) {
511 anInvalidAttributes.push_back(anAttrIt->first);
512 aDestroyer.remove(anAttrIt->second);
515 std::list<AttributePtr>::const_iterator anInvAtIt = anInvalidAttributes.begin();
516 for (; anInvAtIt != anInvalidAttributes.end(); ++anInvAtIt)
517 removeAttribute(*anInvAtIt);
519 // free memory occupied by parameters
520 removeParameters(aDestroyer.parametersToRemove());
522 /// TODO: Think on optimization of checking invalid features and attributes
527 double* PlaneGCSSolver_Storage::createParameter()
529 return mySketchSolver->createParameter();
532 void PlaneGCSSolver_Storage::removeParameters(const GCS::SET_pD& theParams)
534 mySketchSolver->removeParameters(theParams);
535 for (GCS::SET_pD::iterator it = theParams.begin(); it != theParams.end(); ++it)
539 // indicates attribute containing in the external feature
540 static bool isExternalAttribute(const AttributePtr& theAttribute)
544 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
545 std::dynamic_pointer_cast<SketchPlugin_Feature>(theAttribute->owner());
546 return aSketchFeature.get() && aSketchFeature->isExternal();
549 static void addOwnerToSet(const AttributePtr& theAttribute, std::set<FeaturePtr>& theFeatures)
551 FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
553 theFeatures.insert(anOwner);
556 void PlaneGCSSolver_Storage::refresh() const
558 const double aTol = 1000. * tolerance; // tolerance to prevent frequent updates
560 std::set<FeaturePtr> anUpdatedFeatures;
562 std::map<AttributePtr, EntityWrapperPtr>::const_iterator anIt = myAttributeMap.begin();
563 for (; anIt != myAttributeMap.end(); ++anIt) {
564 if (!anIt->first->isInitialized())
567 // the external feature always should keep the up to date values, so,
568 // refresh from the solver is never needed
569 if (isExternalAttribute(anIt->first))
572 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
573 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anIt->first);
575 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPointWrapper =
576 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
577 GCSPointPtr aGCSPoint = aPointWrapper->point();
578 if (fabs(aPoint2D->x() - (*aGCSPoint->x)) > aTol ||
579 fabs(aPoint2D->y() - (*aGCSPoint->y)) > aTol) {
580 aPoint2D->setValue(*aGCSPoint->x, *aGCSPoint->y);
581 addOwnerToSet(anIt->first, anUpdatedFeatures);
585 std::shared_ptr<GeomDataAPI_Point2DArray> aPointArray =
586 std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(anIt->first);
588 std::shared_ptr<PlaneGCSSolver_PointArrayWrapper> anArrayWrapper =
589 std::dynamic_pointer_cast<PlaneGCSSolver_PointArrayWrapper>(anIt->second);
590 int aSize = aPointArray->size();
591 for (int anIndex = 0; anIndex < aSize; ++anIndex) {
592 GeomPnt2dPtr anOriginal = aPointArray->pnt(anIndex);
593 GCSPointPtr aGCSPoint = anArrayWrapper->value(anIndex)->point();
594 if (fabs(anOriginal->x() - (*aGCSPoint->x)) > aTol ||
595 fabs(anOriginal->y() - (*aGCSPoint->y)) > aTol) {
596 aPointArray->setPnt(anIndex, *aGCSPoint->x, *aGCSPoint->y);
597 addOwnerToSet(anIt->first, anUpdatedFeatures);
602 AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anIt->first);
604 ScalarWrapperPtr aScalarWrapper =
605 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
606 if (fabs(aScalar->value() - aScalarWrapper->value()) > aTol) {
607 aScalar->setValue(aScalarWrapper->value());
608 addOwnerToSet(anIt->first, anUpdatedFeatures);
612 AttributeDoubleArrayPtr aRealArray =
613 std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(anIt->first);
615 std::shared_ptr<PlaneGCSSolver_ScalarArrayWrapper> anArrayWrapper =
616 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(anIt->second);
617 int aSize = aRealArray->size();
618 for (int anIndex = 0; anIndex < aSize; ++anIndex) {
619 if (fabs(aRealArray->value(anIndex) - *anArrayWrapper->array()[anIndex]) > aTol) {
620 aRealArray->setValue(anIndex, *anArrayWrapper->array()[anIndex]);
621 addOwnerToSet(anIt->first, anUpdatedFeatures);
628 // notify listeners about features update
629 std::set<FeaturePtr>::const_iterator aFIt = anUpdatedFeatures.begin();
630 for (; aFIt != anUpdatedFeatures.end(); ++aFIt)
634 PlaneGCSSolver_Solver::SolveStatus PlaneGCSSolver_Storage::checkDegeneratedGeometry() const
636 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
637 for (; aFIt != myFeatureMap.end(); ++aFIt) {
638 EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(aFIt->second);
639 if (anEdge && anEdge->isDegenerated())
640 return PlaneGCSSolver_Solver::STATUS_DEGENERATED;
642 return PlaneGCSSolver_Solver::STATUS_OK;
646 void PlaneGCSSolver_Storage::getUnderconstrainedGeometry(std::set<ObjectPtr>& theFeatures) const
648 std::set<double*> aFreeParams;
649 mySketchSolver->getFreeParameters(aFreeParams);
650 if (aFreeParams.empty())
653 for (std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
654 aFIt != myFeatureMap.end(); ++aFIt) {
657 GCS::SET_pD aParams = PlaneGCSSolver_Tools::parameters(aFIt->second);
658 for (GCS::SET_pD::iterator aPIt = aParams.begin(); aPIt != aParams.end(); ++aPIt)
659 if (aFreeParams.find(*aPIt) != aFreeParams.end()) {
660 theFeatures.insert(aFIt->first);