1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: PlaneGCSSolver_Storage.cpp
4 // Created: 14 Dec 2015
5 // Author: Artem ZHIDKOV
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>
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 <SketchPlugin_Arc.h>
26 PlaneGCSSolver_Storage::PlaneGCSSolver_Storage(const GroupID& theGroup)
27 : SketchSolver_Storage(theGroup),
28 myEntityLastID(EID_SKETCH),
29 myConstraintLastID(CID_UNKNOWN)
33 void PlaneGCSSolver_Storage::addConstraint(
34 ConstraintPtr theConstraint,
35 std::list<ConstraintWrapperPtr> theSolverConstraints)
37 SketchSolver_Storage::addConstraint(theConstraint, theSolverConstraints);
39 // update point-point coincidence
40 if (!theSolverConstraints.empty() &&
41 theSolverConstraints.front()->type() == CONSTRAINT_PT_PT_COINCIDENT) {
42 std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
43 for (; aCIt != theSolverConstraints.end(); ++aCIt)
49 bool PlaneGCSSolver_Storage::update(ConstraintWrapperPtr theConstraint)
51 bool isUpdated = false;
52 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
53 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
55 // point-Line distance should be positive
56 if (aConstraint->type() == CONSTRAINT_PT_LINE_DISTANCE && aConstraint->value() < 0.0)
57 aConstraint->setValue(-aConstraint->value());
59 // make value of constraint unchangeable
60 ParameterWrapperPtr aValue = aConstraint->valueParameter();
62 isUpdated = update(aValue) || isUpdated;
64 // update constrained entities
65 std::list<EntityWrapperPtr> anEntities = theConstraint->entities();
66 std::list<EntityWrapperPtr>::iterator anIt = anEntities.begin();
67 for (; anIt != anEntities.end(); ++anIt)
68 isUpdated = update(*anIt) || isUpdated;
70 if (aConstraint->id() == CID_UNKNOWN) {
71 const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
72 // check middle-point constraint conflicts with point-on-line
73 if (aConstraint->type() == CONSTRAINT_MIDDLE_POINT) {
74 std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
75 anIt = myConstraintMap.begin();
76 for (; anIt != myConstraintMap.end(); ++anIt) {
77 EntityWrapperPtr aPoint, aLine;
78 ConstraintWrapperPtr aCurrentConstr = anIt->second.front();
79 if (aCurrentConstr->type() != CONSTRAINT_PT_ON_LINE)
81 const std::list<EntityWrapperPtr>& aCurSubs = aCurrentConstr->entities();
82 std::list<EntityWrapperPtr>::const_iterator aSIt1, aSIt2;
83 for (aSIt1 = aSubs.begin(); aSIt1 != aSubs.end(); ++aSIt1) {
84 if ((*aSIt1)->type() == ENTITY_POINT)
86 else if((*aSIt1)->type() == ENTITY_LINE)
90 for (aSIt2 = aCurSubs.begin(); aSIt2 != aCurSubs.end(); ++aSIt2)
91 if ((*aSIt1)->id() == (*aSIt2)->id())
93 if (aSIt2 == aCurSubs.end())
96 // point-on-line found, change it to bisector
97 if (aSIt1 == aSubs.end()) {
98 std::list<GCSConstraintPtr> aConstrList = aConstraint->constraints();
99 aConstrList.pop_front();
100 aConstraint->setConstraints(aConstrList);
106 // Change ID of constraints
107 aConstraint->setId(++myConstraintLastID);
113 /// \brief Update coordinates of the point or scalar using its base attribute
114 static bool updateValues(EntityWrapperPtr& theEntity)
116 bool isUpdated = false;
117 AttributePtr anAttr = theEntity->baseAttribute();
118 const std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
122 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
123 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
125 aCoord[0] = aPoint2D->x();
126 aCoord[1] = aPoint2D->y();
128 AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttr);
130 aCoord[0] = aScalar->value();
133 std::list<ParameterWrapperPtr>::const_iterator anIt = aParams.begin();
134 for (int i = 0; anIt != aParams.end(); ++anIt, ++i)
135 if (fabs((*anIt)->value() - aCoord[i]) > tolerance) {
136 (*anIt)->setValue(aCoord[i]);
142 bool PlaneGCSSolver_Storage::update(EntityWrapperPtr theEntity)
144 if (theEntity->type() == ENTITY_SKETCH)
145 return true; // sketch is not necessary for PlaneGCS, so it is always says true
147 bool isUpdated = false;
149 if (theEntity->baseAttribute()) {
150 isUpdated = updateValues(theEntity);
152 setNeedToResolve(true);
156 std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
157 std::list<ParameterWrapperPtr>::iterator aPIt = aParams.begin();
158 for (; aPIt != aParams.end(); ++aPIt)
159 isUpdated = update(*aPIt) || isUpdated;
161 // update sub-entities
162 std::list<EntityWrapperPtr> aSubEntities = theEntity->subEntities();
163 std::list<EntityWrapperPtr>::iterator aSIt = aSubEntities.begin();
164 for (; aSIt != aSubEntities.end(); ++aSIt)
165 isUpdated = update(*aSIt) || isUpdated;
167 // additional constraints for the arc processing
168 if (theEntity->type() == ENTITY_ARC)
169 processArc(theEntity);
171 // Change entity's ID, if necessary
172 if (theEntity->id() == EID_UNKNOWN) {
173 if (theEntity->type() == ENTITY_POINT) {
174 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
175 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
177 aPoint = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
178 theEntity->subEntities().front());
180 aPoint->setId(++myEntityLastID);
181 } else if (theEntity->type() == ENTITY_SCALAR) {
182 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aScalar =
183 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(theEntity);
184 aScalar->setId(++myEntityLastID);
186 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aGCSEnt =
187 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity);
188 aGCSEnt->setId(++myEntityLastID);
194 bool PlaneGCSSolver_Storage::update(ParameterWrapperPtr theParameter)
196 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
197 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(theParameter);
198 if (aParam->isProcessed())
200 if (theParameter->group() != myGroupID || theParameter->isParametric())
201 myConst.push_back(aParam->parameter());
203 myParameters.push_back(aParam->parameter());
204 aParam->setProcessed(true);
209 bool PlaneGCSSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
211 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
212 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
214 bool isFullyRemoved = true;
215 // remove point-point coincidence
216 if (aConstraint->type() == CONSTRAINT_PT_PT_COINCIDENT)
217 isFullyRemoved = removeCoincidence(theConstraint) && isFullyRemoved;
218 // remove sub-entities
219 const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
220 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
221 for (; aSIt != aSubs.end(); ++ aSIt)
222 isFullyRemoved = remove(*aSIt) && isFullyRemoved;
224 if (aConstraint->valueParameter())
225 isFullyRemoved = remove(aConstraint->valueParameter()) && isFullyRemoved;
226 if (!isFullyRemoved && aConstraint->baseConstraint() &&
227 (!aConstraint->baseConstraint()->data() || !aConstraint->baseConstraint()->data()->isValid()))
228 isFullyRemoved = true;
229 setNeedToResolve(true);
230 myRemovedConstraints.insert(myRemovedConstraints.end(),
231 aConstraint->constraints().begin(), aConstraint->constraints().end());
233 if (isFullyRemoved && theConstraint->id() == myConstraintLastID)
234 --myConstraintLastID;
236 return isFullyRemoved;
239 bool PlaneGCSSolver_Storage::remove(EntityWrapperPtr theEntity)
241 bool isFullyRemoved = SketchSolver_Storage::remove(theEntity);
242 if (isFullyRemoved) {
243 if (theEntity->type() == ENTITY_ARC) {
244 // remove arc additional constraints
245 std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::iterator
246 aFound = myArcConstraintMap.find(theEntity);
247 if (aFound != myArcConstraintMap.end()) {
248 myRemovedConstraints.insert(myRemovedConstraints.end(),
249 aFound->second.begin(), aFound->second.end());
250 myArcConstraintMap.erase(aFound);
253 if (theEntity->id() == myEntityLastID)
256 return isFullyRemoved;
259 bool PlaneGCSSolver_Storage::remove(ParameterWrapperPtr theParameter)
261 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
262 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(theParameter);
263 if (aParam->isProcessed()) {
264 double* aValPtr = aParam->parameter();
265 GCS::VEC_pD::iterator anIt = myParameters.begin();
266 for (; anIt != myParameters.end(); ++anIt)
267 if (*anIt == aValPtr)
269 if (anIt != myParameters.end()) {
270 myParameters.erase(anIt);
271 setNeedToResolve(true);
272 aParam->setProcessed(false);
275 for (anIt = myConst.begin(); anIt != myConst.end(); ++anIt)
276 if (*anIt == aValPtr)
278 if (anIt != myConst.end()) {
280 setNeedToResolve(true);
281 aParam->setProcessed(false);
289 void PlaneGCSSolver_Storage::addCoincidentPoints(
290 EntityWrapperPtr theMaster, EntityWrapperPtr theSlave)
292 if (theMaster->type() != ENTITY_POINT || theSlave->type() != ENTITY_POINT)
295 std::shared_ptr<PlaneGCSSolver_PointWrapper> aMaster =
296 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theMaster);
298 aMaster = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
299 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMaster)->subEntities().front());
300 std::shared_ptr<PlaneGCSSolver_PointWrapper> aSlave =
301 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theSlave);
303 aSlave = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
304 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theSlave)->subEntities().front());
306 // Search available coincidence
307 CoincidentPointsMap::iterator aMasterFound = myCoincidentPoints.find(aMaster);
308 CoincidentPointsMap::iterator aSlaveFound = myCoincidentPoints.find(aSlave);
309 if (aMasterFound == myCoincidentPoints.end() && aSlaveFound == myCoincidentPoints.end()) {
310 // try to find master and slave points in the lists of slaves of already existent coincidences
311 CoincidentPointsMap::iterator anIt = myCoincidentPoints.begin();
312 for (; anIt != myCoincidentPoints.end(); ++anIt) {
313 if (anIt->second.find(aMaster) != anIt->second.end())
315 else if (anIt->second.find(aSlave) != anIt->second.end())
318 if (aMasterFound != myCoincidentPoints.end() && aSlaveFound != myCoincidentPoints.end())
323 if (aMasterFound == myCoincidentPoints.end()) {
325 myCoincidentPoints[aMaster] = std::set<EntityWrapperPtr>();
326 aMasterFound = myCoincidentPoints.find(aMaster);
327 } else if (aMasterFound == aSlaveFound)
328 return; // already coincident
330 if (aSlaveFound != myCoincidentPoints.end()) {
331 // A slave has been found, we need to attach all points coincident with it to the new master
332 std::set<EntityWrapperPtr> aNewSlaves = aSlaveFound->second;
333 aNewSlaves.insert(aSlaveFound->first);
334 myCoincidentPoints.erase(aSlaveFound);
336 std::set<EntityWrapperPtr>::const_iterator aSlIt = aNewSlaves.begin();
337 for (; aSlIt != aNewSlaves.end(); ++aSlIt)
338 addCoincidentPoints(aMaster, *aSlIt);
340 //std::list<ParameterWrapperPtr> aSlaveParams = aSlave->parameters();
341 //aSlave->setParameters(aMaster->parameters());
343 //// Remove slave's parameters
344 //std::list<ParameterWrapperPtr>::iterator aParIt = aSlaveParams.begin();
345 //for (; aParIt != aSlaveParams.end(); ++aParIt)
348 aMasterFound->second.insert(aSlave);
353 void PlaneGCSSolver_Storage::changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup)
355 theEntity->setGroup(theGroup);
356 if (theGroup == myGroupID)
357 makeVariable(theEntity);
359 if (theEntity->type() == ENTITY_POINT)
361 makeConstant(theEntity);
365 void PlaneGCSSolver_Storage::changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup)
370 void PlaneGCSSolver_Storage::verifyFixed()
375 void PlaneGCSSolver_Storage::processArc(const EntityWrapperPtr& theArc)
377 // no need to constraint a fixed arc
378 if (theArc->group() == GID_OUTOFGROUP)
381 // Calculate additional parameters necessary for PlaneGCS
382 const std::list<EntityWrapperPtr>& aSubs = theArc->subEntities();
383 std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
384 while ((*aSubIt)->type() == ENTITY_POINT) // search scalar entities
386 double* aStartAngle = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
387 double* aEndAngle = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
388 double* aRadius = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt)->scalar();
390 std::shared_ptr<SketchPlugin_Feature> anArcFeature =
391 std::dynamic_pointer_cast<SketchPlugin_Feature>(theArc->baseFeature());
392 std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
393 anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
394 std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
395 anArcFeature->attribute(SketchPlugin_Arc::START_ID()));
396 std::shared_ptr<GeomDataAPI_Point2D> aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
397 anArcFeature->attribute(SketchPlugin_Arc::END_ID()));
398 if (!aCenterAttr || !aStartAttr || !aEndAttr)
400 std::shared_ptr<GeomAPI_Pnt2d> aCenterPnt = aCenterAttr->pnt();
401 std::shared_ptr<GeomAPI_Pnt2d> aStartPnt = aStartAttr->pnt();
402 std::shared_ptr<GeomAPI_Pnt2d> aEndPnt = aEndAttr->pnt();
404 *aRadius = aCenterPnt->distance(aStartPnt);
405 if (!anArcFeature->lastResult())
407 std::shared_ptr<GeomAPI_Edge> anArcEdge =
408 std::dynamic_pointer_cast<GeomAPI_Edge>(anArcFeature->lastResult()->shape());
411 anArcEdge->getRange(*aStartAngle, *aEndAngle);
413 // do not constraint copied arc
414 if (anArcFeature->isCopy())
416 // No need to add constraints if they are already exist
417 std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
418 aFound = myArcConstraintMap.find(theArc);
419 if (aFound != myArcConstraintMap.end())
422 // Prepare additional constraints to produce the arc
423 std::vector<GCSConstraintPtr> anArcConstraints;
424 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt =
425 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theArc);
426 std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt->entity());
427 // Distances from center till start and end points are equal to radius
428 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
429 anArc->center, anArc->start, anArc->rad)));
430 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
431 anArc->center, anArc->end, anArc->rad)));
432 // Angles of start and end points should be equal to given angles
433 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
434 anArc->center, anArc->start, anArc->startAngle)));
435 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
436 anArc->center, anArc->end, anArc->endAngle)));
438 myArcConstraintMap[theArc] = anArcConstraints;
442 void PlaneGCSSolver_Storage::makeConstant(const EntityWrapperPtr& theEntity)
444 toggleEntity(theEntity, myParameters, myConst);
445 if (theEntity->type() == ENTITY_POINT)
446 updateCoincident(theEntity);
449 void PlaneGCSSolver_Storage::makeVariable(const EntityWrapperPtr& theEntity)
451 toggleEntity(theEntity, myConst, myParameters);
454 static void getParametersToMove(const EntityWrapperPtr& theEntity, std::set<double*>& theParamList)
456 const std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
457 std::list<ParameterWrapperPtr>::const_iterator aPIt = aParams.begin();
458 for (; aPIt != aParams.end(); ++aPIt)
460 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*aPIt)->parameter());
462 const std::list<EntityWrapperPtr> aSubs = theEntity->subEntities();
463 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
465 if (theEntity->type() == ENTITY_ARC) {
466 // workaround for the arc processing, because the arc is fixed by a set of constraints,
467 // which will conflict with all parameters fixed:
469 getParametersToMove(*aSIt++, theParamList);
470 // 2. take start point
471 getParametersToMove(*aSIt++, theParamList);
472 // 3. skip end point, radius and start angle, but take end angle parameter
473 getParametersToMove(*(++aSIt), theParamList);
475 for (; aSIt != aSubs.end(); ++aSIt)
476 getParametersToMove(*aSIt, theParamList);
480 void PlaneGCSSolver_Storage::toggleEntity(
481 const EntityWrapperPtr& theEntity, GCS::VEC_pD& theFrom, GCS::VEC_pD& theTo)
483 std::set<double*> aParamsToMove;
484 getParametersToMove(theEntity, aParamsToMove);
486 GCS::VEC_pD::iterator anIt = theFrom.begin();
487 while (anIt != theFrom.end()) {
488 if (aParamsToMove.find(*anIt) == aParamsToMove.end()) {
493 theTo.push_back(*anIt);
494 int aShift = int(anIt - theFrom.begin());
496 anIt = theFrom.begin() + aShift;
500 void PlaneGCSSolver_Storage::updateCoincident(const EntityWrapperPtr& thePoint)
502 CoincidentPointsMap::iterator anIt = myCoincidentPoints.begin();
503 for (; anIt != myCoincidentPoints.end(); ++anIt) {
504 if (anIt->first == thePoint || anIt->second.find(thePoint) != anIt->second.end()) {
505 std::set<EntityWrapperPtr> aCoincident = anIt->second;
506 aCoincident.insert(anIt->first);
508 const std::list<ParameterWrapperPtr>& aBaseParams = thePoint->parameters();
509 std::list<ParameterWrapperPtr> aParams;
510 std::list<ParameterWrapperPtr>::const_iterator aBaseIt, anUpdIt;
512 std::set<EntityWrapperPtr>::const_iterator aCoincIt = aCoincident.begin();
513 for (; aCoincIt != aCoincident.end(); ++aCoincIt)
514 if (*aCoincIt != thePoint && (*aCoincIt)->group() != GID_OUTOFGROUP) {
515 aParams = (*aCoincIt)->parameters();
516 aBaseIt = aBaseParams.begin();
517 for (anUpdIt = aParams.begin(); anUpdIt != aParams.end(); ++anUpdIt, ++aBaseIt)
518 (*anUpdIt)->setValue((*aBaseIt)->value());
527 bool PlaneGCSSolver_Storage::isRedundant(
528 GCSConstraintPtr theCheckedConstraint,
529 ConstraintWrapperPtr theParentConstraint) const
531 if (theParentConstraint->type() == CONSTRAINT_SYMMETRIC) {
532 if (theCheckedConstraint->getTypeId() == GCS::Perpendicular) {
533 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
534 // check the initial point is placed on the mirror line
535 std::list<EntityWrapperPtr> aSubs = theParentConstraint->entities();
536 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(aSubs.front());
537 std::shared_ptr<GeomAPI_Lin2d> aLine = aBuilder->line(aSubs.back());
538 return aLine->distance(aPoint) < tolerance;
545 void PlaneGCSSolver_Storage::initializeSolver(SolverPtr theSolver)
547 std::shared_ptr<PlaneGCSSolver_Solver> aSolver =
548 std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(theSolver);
556 // initialize constraints
557 std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
558 aCIt = myConstraintMap.begin();
559 for (; aCIt != myConstraintMap.end(); ++aCIt) {
560 std::list<ConstraintWrapperPtr>::const_iterator aCWIt = aCIt->second.begin();
561 for (; aCWIt != aCIt->second.end(); ++ aCWIt) {
562 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aGCS =
563 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(*aCWIt);
564 std::list<GCSConstraintPtr>::const_iterator anIt = aGCS->constraints().begin();
565 for (; anIt != aGCS->constraints().end(); ++anIt)
566 if (!isRedundant(*anIt, aGCS))
567 aSolver->addConstraint(*anIt);
570 // additional constraints for arcs
571 std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
572 anArcIt = myArcConstraintMap.begin();
573 for (; anArcIt != myArcConstraintMap.end(); ++anArcIt) {
574 std::vector<GCSConstraintPtr>::const_iterator anIt = anArcIt->second.begin();
575 for (; anIt != anArcIt->second.end(); ++anIt)
576 aSolver->addConstraint(*anIt);
578 // removed waste constraints
579 std::list<GCSConstraintPtr>::const_iterator aRemIt = myRemovedConstraints.begin();
580 for (; aRemIt != myRemovedConstraints.end(); ++aRemIt)
581 aSolver->removeConstraint(*aRemIt);
582 myRemovedConstraints.clear();
583 // initialize unknowns
584 aSolver->setParameters(myParameters);
587 void PlaneGCSSolver_Storage::refresh(bool theFixedOnly) const
591 std::map<AttributePtr, EntityWrapperPtr>::const_iterator anIt = myAttributeMap.begin();
592 std::list<ParameterWrapperPtr> aParams;
593 std::list<ParameterWrapperPtr>::const_iterator aParIt;
594 for (; anIt != myAttributeMap.end(); ++anIt) {
595 // the external feature always should keep the up to date values, so,
596 // refresh from the solver is never needed
597 bool isExternal = false;
598 if (anIt->first.get()) {
599 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
600 std::dynamic_pointer_cast<SketchPlugin_Feature>(anIt->first->owner());
601 if (aSketchFeature.get() && aSketchFeature->isExternal())
605 // update parameter wrappers and obtain values of attributes
606 aParams = anIt->second->parameters();
608 bool isUpd[3] = {false};
610 for (aParIt = aParams.begin(); i < 3 && aParIt != aParams.end(); ++aParIt, ++i) {
611 if (!theFixedOnly || isExternal ||
612 (*aParIt)->group() == GID_OUTOFGROUP || (*aParIt)->isParametric()) {
613 aCoords[i] = (*aParIt)->value();
617 if (!isUpd[0] && !isUpd[1] && !isUpd[2])
618 continue; // nothing is updated
620 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
621 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anIt->first);
623 if ((isUpd[0] && fabs(aPoint2D->x() - aCoords[0]) > tolerance) ||
624 (isUpd[1] && fabs(aPoint2D->y() - aCoords[1]) > tolerance) || isExternal) {
625 if (!isUpd[0] || isExternal) aCoords[0] = aPoint2D->x();
626 if (!isUpd[1] || isExternal) aCoords[1] = aPoint2D->y();
627 aPoint2D->setValue(aCoords[0], aCoords[1]);
628 // Find points coincident with this one (probably not in GID_OUTOFGROUP)
629 CoincidentPointsMap::const_iterator aCoincIt = myCoincidentPoints.begin();
630 for (; aCoincIt != myCoincidentPoints.end(); ++aCoincIt)
631 if (aCoincIt->first == anIt->second ||
632 aCoincIt->second.find(anIt->second) != aCoincIt->second.end())
634 if (aCoincIt != myCoincidentPoints.end()) {
635 aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
636 aCoincIt->first->baseAttribute());
638 aPoint2D->setValue(aCoords[0], aCoords[1]);
639 std::set<EntityWrapperPtr>::const_iterator aSlaveIt = aCoincIt->second.begin();
640 for (; aSlaveIt != aCoincIt->second.end(); ++aSlaveIt) {
641 aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>((*aSlaveIt)->baseAttribute());
643 aPoint2D->setValue(aCoords[0], aCoords[1]);
649 AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anIt->first);
650 if (aScalar && !isExternal) {
651 if (isUpd[0] && fabs(aScalar->value() - aCoords[0]) > tolerance)
652 aScalar->setValue(aCoords[0]);
657 //blockEvents(false);
660 EntityWrapperPtr PlaneGCSSolver_Storage::calculateMiddlePoint(
661 EntityWrapperPtr theBase, double theCoeff)
663 std::shared_ptr<PlaneGCSSolver_Builder> aBuilder =
664 std::dynamic_pointer_cast<PlaneGCSSolver_Builder>(PlaneGCSSolver_Builder::getInstance());
666 std::shared_ptr<GeomAPI_XY> aMidPoint;
667 if (theBase->type() == ENTITY_LINE) {
668 std::shared_ptr<GeomAPI_Pnt2d> aPoints[2];
669 const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
670 std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
671 for (int i = 0; i < 2; ++i, ++anIt)
672 aPoints[i] = aBuilder->point(*anIt);
673 aMidPoint = aPoints[0]->xy()->multiplied(1.0 - theCoeff)->added(
674 aPoints[1]->xy()->multiplied(theCoeff));
676 else if (theBase->type() == ENTITY_ARC) {
678 double anArcPoint[3][2];
679 const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
680 std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
681 for (int i = 0; i < 3; ++i, ++anIt) {
682 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(*anIt);
683 anArcPoint[i][0] = aPoint->x();
684 anArcPoint[i][1] = aPoint->y();
686 // project last point of arc on the arc
687 double x = anArcPoint[1][0] - anArcPoint[0][0];
688 double y = anArcPoint[1][1] - anArcPoint[0][1];
689 double aRad = sqrt(x*x + y*y);
690 x = anArcPoint[2][0] - anArcPoint[0][0];
691 y = anArcPoint[2][1] - anArcPoint[0][1];
692 double aNorm = sqrt(x*x + y*y);
693 if (aNorm >= tolerance) {
694 anArcPoint[2][0] = x * aRad / aNorm;
695 anArcPoint[2][1] = y * aRad / aNorm;
697 anArcPoint[1][0] -= anArcPoint[0][0];
698 anArcPoint[1][1] -= anArcPoint[0][1];
699 if (theCoeff < tolerance) {
700 theX = anArcPoint[0][0] + anArcPoint[1][0];
701 theY = anArcPoint[0][1] + anArcPoint[1][1];
702 } else if (1 - theCoeff < tolerance) {
703 theX = anArcPoint[0][0] + anArcPoint[2][0];
704 theY = anArcPoint[0][1] + anArcPoint[2][1];
706 std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
707 std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
708 double anAngle = aStartDir->angle(aEndDir);
712 double aCos = cos(anAngle);
713 double aSin = sin(anAngle);
714 theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
715 theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
717 aMidPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(theX, theY));
721 return EntityWrapperPtr();
723 std::list<ParameterWrapperPtr> aParameters;
724 aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->x()));
725 aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->y()));
726 // Create entity (parameters are not filled)
727 GCSPointPtr aPnt(new GCS::Point);
728 aPnt->x = std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
729 aPnt->y = std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
731 EntityWrapperPtr aResult(new PlaneGCSSolver_PointWrapper(AttributePtr(), aPnt));
732 aResult->setGroup(myGroupID);
733 aResult->setParameters(aParameters);