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 // Change ID of constraints
71 if (aConstraint->id() == CID_UNKNOWN)
72 aConstraint->setId(++myConstraintLastID);
77 /// \brief Update coordinates of the point or scalar using its base attribute
78 static bool updateValues(EntityWrapperPtr& theEntity)
80 bool isUpdated = false;
81 AttributePtr anAttr = theEntity->baseAttribute();
82 const std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
86 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
87 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
89 aCoord[0] = aPoint2D->x();
90 aCoord[1] = aPoint2D->y();
92 AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttr);
94 aCoord[0] = aScalar->value();
97 std::list<ParameterWrapperPtr>::const_iterator anIt = aParams.begin();
98 for (int i = 0; anIt != aParams.end(); ++anIt, ++i)
99 if (fabs((*anIt)->value() - aCoord[i]) > tolerance) {
100 (*anIt)->setValue(aCoord[i]);
106 bool PlaneGCSSolver_Storage::update(EntityWrapperPtr theEntity)
108 if (theEntity->type() == ENTITY_SKETCH)
109 return true; // sketch is not necessary for PlaneGCS, so it is always says true
111 bool isUpdated = false;
113 if (theEntity->baseAttribute()) {
114 isUpdated = updateValues(theEntity);
116 setNeedToResolve(true);
120 std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
121 std::list<ParameterWrapperPtr>::iterator aPIt = aParams.begin();
122 for (; aPIt != aParams.end(); ++aPIt)
123 isUpdated = update(*aPIt) || isUpdated;
125 // update sub-entities
126 std::list<EntityWrapperPtr> aSubEntities = theEntity->subEntities();
127 std::list<EntityWrapperPtr>::iterator aSIt = aSubEntities.begin();
128 for (; aSIt != aSubEntities.end(); ++aSIt)
129 isUpdated = update(*aSIt) || isUpdated;
131 // additional constraints for the arc processing
132 if (theEntity->type() == ENTITY_ARC)
133 processArc(theEntity);
135 // Change entity's ID, if necessary
136 if (theEntity->id() == EID_UNKNOWN) {
137 if (theEntity->type() == ENTITY_POINT) {
138 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
139 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
141 aPoint = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
142 theEntity->subEntities().front());
144 aPoint->setId(++myEntityLastID);
145 } else if (theEntity->type() == ENTITY_SCALAR) {
146 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aScalar =
147 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(theEntity);
148 aScalar->setId(++myEntityLastID);
150 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aGCSEnt =
151 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity);
152 aGCSEnt->setId(++myEntityLastID);
158 bool PlaneGCSSolver_Storage::update(ParameterWrapperPtr theParameter)
160 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
161 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(theParameter);
162 if (aParam->isProcessed())
164 if (theParameter->group() != myGroupID || theParameter->isParametric())
165 myConst.push_back(aParam->parameter());
167 myParameters.push_back(aParam->parameter());
168 aParam->setProcessed(true);
173 bool PlaneGCSSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
175 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
176 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
178 bool isFullyRemoved = true;
179 const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
180 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
181 for (; aSIt != aSubs.end(); ++ aSIt)
182 isFullyRemoved = remove(*aSIt) && isFullyRemoved;
184 if (aConstraint->valueParameter())
185 isFullyRemoved = remove(aConstraint->valueParameter()) && isFullyRemoved;
186 if (!isFullyRemoved && aConstraint->baseConstraint() &&
187 (!aConstraint->baseConstraint()->data() || !aConstraint->baseConstraint()->data()->isValid()))
188 isFullyRemoved = true;
189 setNeedToResolve(true);
190 myRemovedConstraints.insert(myRemovedConstraints.end(),
191 aConstraint->constraints().begin(), aConstraint->constraints().end());
193 if (isFullyRemoved && theConstraint->id() == myConstraintLastID)
194 --myConstraintLastID;
196 return isFullyRemoved;
199 bool PlaneGCSSolver_Storage::remove(EntityWrapperPtr theEntity)
201 if ((theEntity->baseAttribute() && isUsed(theEntity->baseAttribute())) ||
202 (theEntity->baseFeature() && isUsed(theEntity->baseFeature())))
205 bool isFullyRemoved = SketchSolver_Storage::remove(theEntity);
206 if (isFullyRemoved && theEntity->id() == myEntityLastID)
208 return isFullyRemoved;
211 bool PlaneGCSSolver_Storage::remove(ParameterWrapperPtr theParameter)
213 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
214 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(theParameter);
215 if (aParam->isProcessed()) {
216 double* aValPtr = aParam->parameter();
217 GCS::VEC_pD::iterator anIt = myParameters.begin();
218 for (; anIt != myParameters.end(); ++anIt)
219 if (*anIt == aValPtr)
221 if (anIt != myParameters.end()) {
222 myParameters.erase(anIt);
223 setNeedToResolve(true);
226 for (anIt = myConst.begin(); anIt != myConst.end(); ++anIt)
227 if (*anIt == aValPtr)
229 if (anIt != myConst.end()) {
231 setNeedToResolve(true);
235 aParam->setProcessed(false);
240 void PlaneGCSSolver_Storage::addCoincidentPoints(
241 EntityWrapperPtr theMaster, EntityWrapperPtr theSlave)
243 if (theMaster->type() != ENTITY_POINT || theSlave->type() != ENTITY_POINT)
246 std::shared_ptr<PlaneGCSSolver_PointWrapper> aMaster =
247 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theMaster);
249 aMaster = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
250 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMaster)->subEntities().front());
251 std::shared_ptr<PlaneGCSSolver_PointWrapper> aSlave =
252 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theSlave);
254 aSlave = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
255 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theSlave)->subEntities().front());
257 // Search available coincidence
258 CoincidentPointsMap::iterator aMasterFound = myCoincidentPoints.find(aMaster);
259 CoincidentPointsMap::iterator aSlaveFound = myCoincidentPoints.find(aSlave);
260 if (aMasterFound == myCoincidentPoints.end() && aSlaveFound == myCoincidentPoints.end()) {
261 // try to find master and slave points in the lists of slaves of already existent coincidences
262 CoincidentPointsMap::iterator anIt = myCoincidentPoints.begin();
263 for (; anIt != myCoincidentPoints.end(); ++anIt) {
264 if (anIt->second.find(aMaster) != anIt->second.end())
266 else if (anIt->second.find(aSlave) != anIt->second.end())
269 if (aMasterFound != myCoincidentPoints.end() && aSlaveFound != myCoincidentPoints.end())
274 if (aMasterFound == myCoincidentPoints.end()) {
276 myCoincidentPoints[aMaster] = std::set<EntityWrapperPtr>();
277 aMasterFound = myCoincidentPoints.find(aMaster);
278 } else if (aMasterFound == aSlaveFound)
279 return; // already coincident
281 if (aSlaveFound != myCoincidentPoints.end()) {
282 // A slave has been found, we need to attach all points coincident with it to the new master
283 std::set<EntityWrapperPtr> aNewSlaves = aSlaveFound->second;
284 aNewSlaves.insert(aSlaveFound->first);
285 myCoincidentPoints.erase(aSlaveFound);
287 std::set<EntityWrapperPtr>::const_iterator aSlIt = aNewSlaves.begin();
288 for (; aSlIt != aNewSlaves.end(); ++aSlIt)
289 addCoincidentPoints(aMaster, *aSlIt);
291 //std::list<ParameterWrapperPtr> aSlaveParams = aSlave->parameters();
292 //aSlave->setParameters(aMaster->parameters());
294 //// Remove slave's parameters
295 //std::list<ParameterWrapperPtr>::iterator aParIt = aSlaveParams.begin();
296 //for (; aParIt != aSlaveParams.end(); ++aParIt)
299 aMasterFound->second.insert(aSlave);
304 void PlaneGCSSolver_Storage::changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup)
306 theEntity->setGroup(theGroup);
307 if (theGroup == myGroupID)
308 makeVariable(theEntity);
310 if (theEntity->type() == ENTITY_POINT)
312 makeConstant(theEntity);
316 void PlaneGCSSolver_Storage::changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup)
321 void PlaneGCSSolver_Storage::verifyFixed()
326 void PlaneGCSSolver_Storage::processArc(const EntityWrapperPtr& theArc)
328 // Calculate additional parameters necessary for PlaneGCS
329 const std::list<EntityWrapperPtr>& aSubs = theArc->subEntities();
330 std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
331 while ((*aSubIt)->type() == ENTITY_POINT) // search scalar entities
333 double* aStartAngle = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
334 double* aEndAngle = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
335 double* aRadius = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt)->scalar();
337 FeaturePtr anArcFeature = theArc->baseFeature();
338 std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
339 anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
340 std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
341 anArcFeature->attribute(SketchPlugin_Arc::START_ID()));
342 std::shared_ptr<GeomDataAPI_Point2D> aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
343 anArcFeature->attribute(SketchPlugin_Arc::END_ID()));
344 if (!aCenterAttr || !aStartAttr || !aEndAttr)
346 std::shared_ptr<GeomAPI_Pnt2d> aCenterPnt = aCenterAttr->pnt();
347 std::shared_ptr<GeomAPI_Pnt2d> aStartPnt = aStartAttr->pnt();
348 std::shared_ptr<GeomAPI_Pnt2d> aEndPnt = aEndAttr->pnt();
350 *aRadius = aCenterPnt->distance(aStartPnt);
351 if (!anArcFeature->lastResult())
353 std::shared_ptr<GeomAPI_Edge> anArcEdge =
354 std::dynamic_pointer_cast<GeomAPI_Edge>(anArcFeature->lastResult()->shape());
357 anArcEdge->getRange(*aStartAngle, *aEndAngle);
359 // No need to add constraints if they are already exist
360 std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
361 aFound = myArcConstraintMap.find(theArc);
362 if (aFound != myArcConstraintMap.end())
365 // Prepare additional constraints to produce the arc
366 std::vector<GCSConstraintPtr> anArcConstraints;
367 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt =
368 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theArc);
369 std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt->entity());
370 // Distances from center till start and end points are equal to radius
371 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
372 anArc->center, anArc->start, anArc->rad)));
373 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
374 anArc->center, anArc->end, anArc->rad)));
375 // Angles of start and end points should be equal to given angles
376 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
377 anArc->center, anArc->start, anArc->startAngle)));
378 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
379 anArc->center, anArc->end, anArc->endAngle)));
381 myArcConstraintMap[theArc] = anArcConstraints;
385 void PlaneGCSSolver_Storage::makeConstant(const EntityWrapperPtr& theEntity)
387 toggleEntity(theEntity, myParameters, myConst);
388 if (theEntity->type() == ENTITY_POINT)
389 updateCoincident(theEntity);
392 void PlaneGCSSolver_Storage::makeVariable(const EntityWrapperPtr& theEntity)
394 toggleEntity(theEntity, myConst, myParameters);
397 static void getParametersToMove(const EntityWrapperPtr& theEntity, std::set<double*>& theParamList)
399 const std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
400 std::list<ParameterWrapperPtr>::const_iterator aPIt = aParams.begin();
401 for (; aPIt != aParams.end(); ++aPIt)
403 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*aPIt)->parameter());
405 const std::list<EntityWrapperPtr> aSubs = theEntity->subEntities();
406 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
407 for (; aSIt != aSubs.end(); ++aSIt)
408 getParametersToMove(*aSIt, theParamList);
411 void PlaneGCSSolver_Storage::toggleEntity(
412 const EntityWrapperPtr& theEntity, GCS::VEC_pD& theFrom, GCS::VEC_pD& theTo)
414 std::set<double*> aParamsToMove;
415 getParametersToMove(theEntity, aParamsToMove);
417 GCS::VEC_pD::iterator anIt = theFrom.begin();
418 while (anIt != theFrom.end()) {
419 if (aParamsToMove.find(*anIt) == aParamsToMove.end()) {
424 theTo.push_back(*anIt);
425 int aShift = anIt - theFrom.begin();
427 anIt = theFrom.begin() + aShift;
431 void PlaneGCSSolver_Storage::updateCoincident(const EntityWrapperPtr& thePoint)
433 CoincidentPointsMap::iterator anIt = myCoincidentPoints.begin();
434 for (; anIt != myCoincidentPoints.end(); ++anIt) {
435 if (anIt->first == thePoint || anIt->second.find(thePoint) != anIt->second.end()) {
436 std::set<EntityWrapperPtr> aCoincident = anIt->second;
437 aCoincident.insert(anIt->first);
439 const std::list<ParameterWrapperPtr>& aBaseParams = thePoint->parameters();
440 std::list<ParameterWrapperPtr> aParams;
441 std::list<ParameterWrapperPtr>::const_iterator aBaseIt, anUpdIt;
443 std::set<EntityWrapperPtr>::const_iterator aCoincIt = aCoincident.begin();
444 for (; aCoincIt != aCoincident.end(); ++aCoincIt)
445 if (*aCoincIt != thePoint && (*aCoincIt)->group() != GID_OUTOFGROUP) {
446 aParams = (*aCoincIt)->parameters();
447 aBaseIt = aBaseParams.begin();
448 for (anUpdIt = aParams.begin(); anUpdIt != aParams.end(); ++anUpdIt, ++aBaseIt)
449 (*anUpdIt)->setValue((*aBaseIt)->value());
458 void PlaneGCSSolver_Storage::initializeSolver(SolverPtr theSolver)
460 std::shared_ptr<PlaneGCSSolver_Solver> aSolver =
461 std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(theSolver);
468 // initialize constraints
469 std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
470 aCIt = myConstraintMap.begin();
471 for (; aCIt != myConstraintMap.end(); ++aCIt) {
472 std::list<ConstraintWrapperPtr>::const_iterator aCWIt = aCIt->second.begin();
473 for (; aCWIt != aCIt->second.end(); ++ aCWIt) {
474 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aGCS =
475 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(*aCWIt);
476 std::list<GCSConstraintPtr>::const_iterator anIt = aGCS->constraints().begin();
477 for (; anIt != aGCS->constraints().end(); ++anIt)
478 aSolver->addConstraint(*anIt);
481 // additional constraints for arcs
482 std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
483 anArcIt = myArcConstraintMap.begin();
484 for (; anArcIt != myArcConstraintMap.end(); ++anArcIt) {
485 std::vector<GCSConstraintPtr>::const_iterator anIt = anArcIt->second.begin();
486 for (; anIt != anArcIt->second.end(); ++anIt)
487 aSolver->addConstraint(*anIt);
489 // removed waste constraints
490 std::list<GCSConstraintPtr>::const_iterator aRemIt = myRemovedConstraints.begin();
491 for (; aRemIt != myRemovedConstraints.end(); ++aRemIt)
492 aSolver->removeConstraint(*aRemIt);
493 myRemovedConstraints.clear();
494 // initialize unknowns
495 aSolver->setParameters(myParameters);
498 void PlaneGCSSolver_Storage::refresh(bool theFixedOnly) const
502 std::map<AttributePtr, EntityWrapperPtr>::const_iterator anIt = myAttributeMap.begin();
503 std::list<ParameterWrapperPtr> aParams;
504 std::list<ParameterWrapperPtr>::const_iterator aParIt;
505 for (; anIt != myAttributeMap.end(); ++anIt) {
506 // the external feature always should keep the up to date values, so,
507 // refresh from the solver is never needed
508 bool isExternal = false;
509 if (anIt->first.get()) {
510 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
511 std::dynamic_pointer_cast<SketchPlugin_Feature>(anIt->first->owner());
512 if (aSketchFeature.get() && aSketchFeature->isExternal())
516 // update parameter wrappers and obtain values of attributes
517 aParams = anIt->second->parameters();
519 bool isUpd[3] = {false};
521 for (aParIt = aParams.begin(); i < 3 && aParIt != aParams.end(); ++aParIt, ++i) {
522 if (!theFixedOnly || isExternal ||
523 (*aParIt)->group() == GID_OUTOFGROUP || (*aParIt)->isParametric()) {
524 aCoords[i] = (*aParIt)->value();
528 if (!isUpd[0] && !isUpd[1] && !isUpd[2])
529 continue; // nothing is updated
531 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
532 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anIt->first);
534 if ((isUpd[0] && fabs(aPoint2D->x() - aCoords[0]) > tolerance) ||
535 (isUpd[1] && fabs(aPoint2D->y() - aCoords[1]) > tolerance) || isExternal) {
536 if (!isUpd[0] || isExternal) aCoords[0] = aPoint2D->x();
537 if (!isUpd[1] || isExternal) aCoords[1] = aPoint2D->y();
538 aPoint2D->setValue(aCoords[0], aCoords[1]);
539 // Find points coincident with this one (probably not in GID_OUTOFGROUP)
540 CoincidentPointsMap::const_iterator aCoincIt = myCoincidentPoints.begin();
541 for (; aCoincIt != myCoincidentPoints.end(); ++aCoincIt)
542 if (aCoincIt->first == anIt->second ||
543 aCoincIt->second.find(anIt->second) != aCoincIt->second.end())
545 if (aCoincIt != myCoincidentPoints.end()) {
546 aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
547 aCoincIt->first->baseAttribute());
549 aPoint2D->setValue(aCoords[0], aCoords[1]);
550 std::set<EntityWrapperPtr>::const_iterator aSlaveIt = aCoincIt->second.begin();
551 for (; aSlaveIt != aCoincIt->second.end(); ++aSlaveIt) {
552 aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>((*aSlaveIt)->baseAttribute());
554 aPoint2D->setValue(aCoords[0], aCoords[1]);
560 AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anIt->first);
561 if (aScalar && !isExternal) {
562 if (isUpd[0] && fabs(aScalar->value() - aCoords[0]) > tolerance)
563 aScalar->setValue(aCoords[0]);
568 //blockEvents(false);
571 EntityWrapperPtr PlaneGCSSolver_Storage::calculateMiddlePoint(
572 EntityWrapperPtr theBase, double theCoeff)
574 std::shared_ptr<PlaneGCSSolver_Builder> aBuilder =
575 std::dynamic_pointer_cast<PlaneGCSSolver_Builder>(PlaneGCSSolver_Builder::getInstance());
577 std::shared_ptr<GeomAPI_XY> aMidPoint;
578 if (theBase->type() == ENTITY_LINE) {
579 std::shared_ptr<GeomAPI_Pnt2d> aPoints[2];
580 const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
581 std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
582 for (int i = 0; i < 2; ++i, ++anIt)
583 aPoints[i] = aBuilder->point(*anIt);
584 aMidPoint = aPoints[0]->xy()->multiplied(1.0 - theCoeff)->added(
585 aPoints[1]->xy()->multiplied(theCoeff));
587 else if (theBase->type() == ENTITY_ARC) {
589 double anArcPoint[3][2];
590 const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
591 std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
592 for (int i = 0; i < 3; ++i, ++anIt) {
593 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(*anIt);
594 anArcPoint[i][0] = aPoint->x();
595 anArcPoint[i][1] = aPoint->y();
597 // project last point of arc on the arc
598 double x = anArcPoint[1][0] - anArcPoint[0][0];
599 double y = anArcPoint[1][1] - anArcPoint[0][1];
600 double aRad = sqrt(x*x + y*y);
601 x = anArcPoint[2][0] - anArcPoint[0][0];
602 y = anArcPoint[2][1] - anArcPoint[0][1];
603 double aNorm = sqrt(x*x + y*y);
604 if (aNorm >= tolerance) {
605 anArcPoint[2][0] = x * aRad / aNorm;
606 anArcPoint[2][1] = y * aRad / aNorm;
608 anArcPoint[1][0] -= anArcPoint[0][0];
609 anArcPoint[1][1] -= anArcPoint[0][1];
610 if (theCoeff < tolerance) {
611 theX = anArcPoint[0][0] + anArcPoint[1][0];
612 theY = anArcPoint[0][1] + anArcPoint[1][1];
613 } else if (1 - theCoeff < tolerance) {
614 theX = anArcPoint[0][0] + anArcPoint[2][0];
615 theY = anArcPoint[0][1] + anArcPoint[2][1];
617 std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
618 std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
619 double anAngle = aStartDir->angle(aEndDir);
623 double aCos = cos(anAngle);
624 double aSin = sin(anAngle);
625 theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
626 theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
628 aMidPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(theX, theY));
632 return EntityWrapperPtr();
634 std::list<ParameterWrapperPtr> aParameters;
635 aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->x()));
636 aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->y()));
637 // Create entity (parameters are not filled)
638 GCSPointPtr aPnt(new GCS::Point);
639 aPnt->x = std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
640 aPnt->y = std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
642 EntityWrapperPtr aResult(new PlaneGCSSolver_PointWrapper(AttributePtr(), aPnt));
643 aResult->setGroup(myGroupID);
644 aResult->setParameters(aParameters);