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)
32 void PlaneGCSSolver_Storage::addConstraint(
33 ConstraintPtr theConstraint,
34 std::list<ConstraintWrapperPtr> theSolverConstraints)
36 SketchSolver_Storage::addConstraint(theConstraint, theSolverConstraints);
38 // update point-point coincidence
39 if (!theSolverConstraints.empty() &&
40 theSolverConstraints.front()->type() == CONSTRAINT_PT_PT_COINCIDENT) {
41 std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
42 for (; aCIt != theSolverConstraints.end(); ++aCIt)
48 bool PlaneGCSSolver_Storage::update(ConstraintWrapperPtr theConstraint)
50 bool isUpdated = false;
51 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
52 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
54 // point-Line distance should be positive
55 if (aConstraint->type() == CONSTRAINT_PT_LINE_DISTANCE && aConstraint->value() < 0.0)
56 aConstraint->setValue(-aConstraint->value());
58 // make value of constraint unchangeable
59 ParameterWrapperPtr aValue = aConstraint->valueParameter();
61 isUpdated = update(aValue) || isUpdated;
63 // update constrained entities
64 std::list<EntityWrapperPtr> anEntities = theConstraint->entities();
65 std::list<EntityWrapperPtr>::iterator anIt = anEntities.begin();
66 for (; anIt != anEntities.end(); ++anIt)
67 isUpdated = update(*anIt) || isUpdated;
72 /// \brief Update coordinates of the point or scalar using its base attribute
73 static bool updateValues(EntityWrapperPtr& theEntity)
75 bool isUpdated = false;
76 AttributePtr anAttr = theEntity->baseAttribute();
77 const std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
81 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
82 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
84 aCoord[0] = aPoint2D->x();
85 aCoord[1] = aPoint2D->y();
87 AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttr);
89 aCoord[0] = aScalar->value();
92 std::list<ParameterWrapperPtr>::const_iterator anIt = aParams.begin();
93 for (int i = 0; anIt != aParams.end(); ++anIt, ++i)
94 if (fabs((*anIt)->value() - aCoord[i]) > tolerance) {
95 (*anIt)->setValue(aCoord[i]);
101 bool PlaneGCSSolver_Storage::update(EntityWrapperPtr theEntity)
103 if (theEntity->type() == ENTITY_SKETCH)
104 return true; // sketch is not necessary for PlaneGCS, so it is always says true
106 bool isUpdated = false;
108 if (theEntity->baseAttribute()) {
109 isUpdated = updateValues(theEntity);
111 setNeedToResolve(true);
115 std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
116 std::list<ParameterWrapperPtr>::iterator aPIt = aParams.begin();
117 for (; aPIt != aParams.end(); ++aPIt)
118 isUpdated = update(*aPIt) || isUpdated;
120 // update sub-entities
121 std::list<EntityWrapperPtr> aSubEntities = theEntity->subEntities();
122 std::list<EntityWrapperPtr>::iterator aSIt = aSubEntities.begin();
123 for (; aSIt != aSubEntities.end(); ++aSIt)
124 isUpdated = update(*aSIt) || isUpdated;
126 // additional constraints for the arc processing
127 if (theEntity->type() == ENTITY_ARC)
128 processArc(theEntity);
130 // Change entity's ID, if necessary
131 if (theEntity->id() == EID_UNKNOWN) {
132 if (theEntity->type() == ENTITY_POINT) {
133 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
134 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
136 aPoint = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
137 theEntity->subEntities().front());
139 aPoint->setId(++myEntityLastID);
140 } else if (theEntity->type() == ENTITY_SCALAR) {
141 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aScalar =
142 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(theEntity);
143 aScalar->setId(++myEntityLastID);
145 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aGCSEnt =
146 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity);
147 aGCSEnt->setId(++myEntityLastID);
153 bool PlaneGCSSolver_Storage::update(ParameterWrapperPtr theParameter)
155 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
156 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(theParameter);
157 if (aParam->isProcessed())
159 if (theParameter->group() != myGroupID || theParameter->isParametric())
160 myConst.push_back(aParam->parameter());
162 myParameters.push_back(aParam->parameter());
163 aParam->setProcessed(true);
168 bool PlaneGCSSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
170 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
171 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
173 bool isFullyRemoved = true;
174 const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
175 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
176 for (; aSIt != aSubs.end(); ++ aSIt)
177 isFullyRemoved = remove(*aSIt) && isFullyRemoved;
179 if (aConstraint->valueParameter())
180 isFullyRemoved = remove(aConstraint->valueParameter()) && isFullyRemoved;
181 if (!isFullyRemoved &&
182 (!aConstraint->baseConstraint()->data() || !aConstraint->baseConstraint()->data()->isValid()))
183 isFullyRemoved = true;
184 setNeedToResolve(true);
185 myRemovedConstraints.insert(myRemovedConstraints.end(),
186 aConstraint->constraints().begin(), aConstraint->constraints().end());
187 return isFullyRemoved;
190 bool PlaneGCSSolver_Storage::remove(EntityWrapperPtr theEntity)
192 if ((theEntity->baseAttribute() && isUsed(theEntity->baseAttribute())) ||
193 (theEntity->baseFeature() && isUsed(theEntity->baseFeature())))
196 bool isFullyRemoved = SketchSolver_Storage::remove(theEntity);
197 if (isFullyRemoved && theEntity->id() == myEntityLastID)
199 return isFullyRemoved;
202 bool PlaneGCSSolver_Storage::remove(ParameterWrapperPtr theParameter)
204 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
205 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(theParameter);
206 if (aParam->isProcessed()) {
207 double* aValPtr = aParam->parameter();
208 GCS::VEC_pD::iterator anIt = myParameters.begin();
209 for (; anIt != myParameters.end(); ++anIt)
210 if (*anIt == aValPtr)
212 if (anIt != myParameters.end()) {
213 myParameters.erase(anIt);
214 setNeedToResolve(true);
217 for (anIt = myConst.begin(); anIt != myConst.end(); ++anIt)
218 if (*anIt == aValPtr)
220 if (anIt != myConst.end()) {
222 setNeedToResolve(true);
226 aParam->setProcessed(false);
231 void PlaneGCSSolver_Storage::addCoincidentPoints(
232 EntityWrapperPtr theMaster, EntityWrapperPtr theSlave)
234 if (theMaster->type() != ENTITY_POINT || theSlave->type() != ENTITY_POINT)
237 std::shared_ptr<PlaneGCSSolver_PointWrapper> aMaster =
238 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theMaster);
240 aMaster = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
241 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMaster)->subEntities().front());
242 std::shared_ptr<PlaneGCSSolver_PointWrapper> aSlave =
243 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theSlave);
245 aSlave = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
246 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theSlave)->subEntities().front());
248 // Search available coincidence
249 CoincidentPointsMap::iterator aMasterFound = myCoincidentPoints.find(aMaster);
250 CoincidentPointsMap::iterator aSlaveFound = myCoincidentPoints.find(aSlave);
251 if (aMasterFound == myCoincidentPoints.end() && aSlaveFound == myCoincidentPoints.end()) {
252 // try to find master and slave points in the lists of slaves of already existent coincidences
253 CoincidentPointsMap::iterator anIt = myCoincidentPoints.begin();
254 for (; anIt != myCoincidentPoints.end(); ++anIt) {
255 if (anIt->second.find(aMaster) != anIt->second.end())
257 else if (anIt->second.find(aSlave) != anIt->second.end())
260 if (aMasterFound != myCoincidentPoints.end() && aSlaveFound != myCoincidentPoints.end())
265 if (aMasterFound == myCoincidentPoints.end()) {
267 myCoincidentPoints[aMaster] = std::set<EntityWrapperPtr>();
268 aMasterFound = myCoincidentPoints.find(aMaster);
269 } else if (aMasterFound == aSlaveFound)
270 return; // already coincident
272 if (aSlaveFound != myCoincidentPoints.end()) {
273 // A slave has been found, we need to attach all points coincident with it to the new master
274 std::set<EntityWrapperPtr> aNewSlaves = aSlaveFound->second;
275 aNewSlaves.insert(aSlaveFound->first);
276 myCoincidentPoints.erase(aSlaveFound);
278 std::set<EntityWrapperPtr>::const_iterator aSlIt = aNewSlaves.begin();
279 for (; aSlIt != aNewSlaves.end(); ++aSlIt)
280 addCoincidentPoints(aMaster, *aSlIt);
282 //std::list<ParameterWrapperPtr> aSlaveParams = aSlave->parameters();
283 //aSlave->setParameters(aMaster->parameters());
285 //// Remove slave's parameters
286 //std::list<ParameterWrapperPtr>::iterator aParIt = aSlaveParams.begin();
287 //for (; aParIt != aSlaveParams.end(); ++aParIt)
290 aMasterFound->second.insert(aSlave);
295 void PlaneGCSSolver_Storage::changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup)
297 theEntity->setGroup(theGroup);
298 if (theGroup == myGroupID)
299 makeVariable(theEntity);
301 makeConstant(theEntity);
304 void PlaneGCSSolver_Storage::changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup)
309 void PlaneGCSSolver_Storage::verifyFixed()
314 void PlaneGCSSolver_Storage::processArc(const EntityWrapperPtr& theArc)
316 // Calculate additional parameters necessary for PlaneGCS
317 const std::list<EntityWrapperPtr>& aSubs = theArc->subEntities();
318 std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
319 while ((*aSubIt)->type() == ENTITY_POINT) // search scalar entities
321 double* aStartAngle = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
322 double* aEndAngle = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
323 double* aRadius = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt)->scalar();
325 FeaturePtr anArcFeature = theArc->baseFeature();
326 std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
327 anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
328 std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
329 anArcFeature->attribute(SketchPlugin_Arc::START_ID()));
330 std::shared_ptr<GeomDataAPI_Point2D> aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
331 anArcFeature->attribute(SketchPlugin_Arc::END_ID()));
332 if (!aCenterAttr || !aStartAttr || !aEndAttr)
334 std::shared_ptr<GeomAPI_Pnt2d> aCenterPnt = aCenterAttr->pnt();
335 std::shared_ptr<GeomAPI_Pnt2d> aStartPnt = aStartAttr->pnt();
336 std::shared_ptr<GeomAPI_Pnt2d> aEndPnt = aEndAttr->pnt();
338 *aRadius = aCenterPnt->distance(aStartPnt);
339 if (!anArcFeature->lastResult())
341 std::shared_ptr<GeomAPI_Edge> anArcEdge =
342 std::dynamic_pointer_cast<GeomAPI_Edge>(anArcFeature->lastResult()->shape());
345 anArcEdge->getRange(*aStartAngle, *aEndAngle);
347 // No need to add constraints if they are already exist
348 std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
349 aFound = myArcConstraintMap.find(theArc);
350 if (aFound != myArcConstraintMap.end())
353 // Prepare additional constraints to produce the arc
354 std::vector<GCSConstraintPtr> anArcConstraints;
355 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt =
356 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theArc);
357 std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt->entity());
358 // Distances from center till start and end points are equal to radius
359 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
360 anArc->center, anArc->start, anArc->rad)));
361 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
362 anArc->center, anArc->end, anArc->rad)));
363 // Angles of start and end points should be equal to given angles
364 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
365 anArc->center, anArc->start, anArc->startAngle)));
366 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
367 anArc->center, anArc->end, anArc->endAngle)));
369 myArcConstraintMap[theArc] = anArcConstraints;
373 void PlaneGCSSolver_Storage::makeConstant(const EntityWrapperPtr& theEntity)
375 toggleEntity(theEntity, myParameters, myConst);
378 void PlaneGCSSolver_Storage::makeVariable(const EntityWrapperPtr& theEntity)
380 toggleEntity(theEntity, myConst, myParameters);
383 static void getParametersToMove(const EntityWrapperPtr& theEntity, std::set<double*>& theParamList)
385 const std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
386 std::list<ParameterWrapperPtr>::const_iterator aPIt = aParams.begin();
387 for (; aPIt != aParams.end(); ++aPIt)
389 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*aPIt)->parameter());
391 const std::list<EntityWrapperPtr> aSubs = theEntity->subEntities();
392 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
393 for (; aSIt != aSubs.end(); ++aSIt)
394 getParametersToMove(*aSIt, theParamList);
397 void PlaneGCSSolver_Storage::toggleEntity(
398 const EntityWrapperPtr& theEntity, GCS::VEC_pD& theFrom, GCS::VEC_pD& theTo)
400 std::set<double*> aParamsToMove;
401 getParametersToMove(theEntity, aParamsToMove);
403 GCS::VEC_pD::iterator anIt = theFrom.begin();
404 while (anIt != theFrom.end()) {
405 if (aParamsToMove.find(*anIt) == aParamsToMove.end()) {
410 theTo.push_back(*anIt);
411 int aShift = anIt - theFrom.begin();
413 anIt = theFrom.begin() + aShift;
418 void PlaneGCSSolver_Storage::initializeSolver(SolverPtr theSolver)
420 std::shared_ptr<PlaneGCSSolver_Solver> aSolver =
421 std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(theSolver);
428 // initialize constraints
429 std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
430 aCIt = myConstraintMap.begin();
431 for (; aCIt != myConstraintMap.end(); ++aCIt) {
432 std::list<ConstraintWrapperPtr>::const_iterator aCWIt = aCIt->second.begin();
433 for (; aCWIt != aCIt->second.end(); ++ aCWIt) {
434 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aGCS =
435 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(*aCWIt);
436 std::list<GCSConstraintPtr>::const_iterator anIt = aGCS->constraints().begin();
437 for (; anIt != aGCS->constraints().end(); ++anIt)
438 aSolver->addConstraint(*anIt);
441 // additional constraints for arcs
442 std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
443 anArcIt = myArcConstraintMap.begin();
444 for (; anArcIt != myArcConstraintMap.end(); ++anArcIt) {
445 std::vector<GCSConstraintPtr>::const_iterator anIt = anArcIt->second.begin();
446 for (; anIt != anArcIt->second.end(); ++anIt)
447 aSolver->addConstraint(*anIt);
449 // removed waste constraints
450 std::list<GCSConstraintPtr>::const_iterator aRemIt = myRemovedConstraints.begin();
451 for (; aRemIt != myRemovedConstraints.end(); ++aRemIt)
452 aSolver->removeConstraint(*aRemIt);
453 myRemovedConstraints.clear();
454 // initialize unknowns
455 aSolver->setParameters(myParameters);
458 void PlaneGCSSolver_Storage::refresh(bool theFixedOnly) const
462 std::map<AttributePtr, EntityWrapperPtr>::const_iterator anIt = myAttributeMap.begin();
463 std::list<ParameterWrapperPtr> aParams;
464 std::list<ParameterWrapperPtr>::const_iterator aParIt;
465 for (; anIt != myAttributeMap.end(); ++anIt) {
466 // the external feature always should keep the up to date values, so,
467 // refresh from the solver is never needed
468 bool isExternal = false;
469 if (anIt->first.get()) {
470 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
471 std::dynamic_pointer_cast<SketchPlugin_Feature>(anIt->first->owner());
472 if (aSketchFeature.get() && aSketchFeature->isExternal())
476 // update parameter wrappers and obtain values of attributes
477 aParams = anIt->second->parameters();
479 bool isUpd[3] = {false};
481 for (aParIt = aParams.begin(); i < 3 && aParIt != aParams.end(); ++aParIt, ++i) {
482 if (!theFixedOnly || isExternal ||
483 (*aParIt)->group() == GID_OUTOFGROUP || (*aParIt)->isParametric()) {
484 aCoords[i] = (*aParIt)->value();
488 if (!isUpd[0] && !isUpd[1] && !isUpd[2])
489 continue; // nothing is updated
491 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
492 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anIt->first);
494 if ((isUpd[0] && fabs(aPoint2D->x() - aCoords[0]) > tolerance) ||
495 (isUpd[1] && fabs(aPoint2D->y() - aCoords[1]) > tolerance) || isExternal) {
496 if (!isUpd[0] || isExternal) aCoords[0] = aPoint2D->x();
497 if (!isUpd[1] || isExternal) aCoords[1] = aPoint2D->y();
498 aPoint2D->setValue(aCoords[0], aCoords[1]);
499 // Find points coincident with this one (probably not in GID_OUTOFGROUP)
500 CoincidentPointsMap::const_iterator aCoincIt = myCoincidentPoints.begin();
501 for (; aCoincIt != myCoincidentPoints.end(); ++aCoincIt)
502 if (aCoincIt->first == anIt->second ||
503 aCoincIt->second.find(anIt->second) != aCoincIt->second.end())
505 if (aCoincIt != myCoincidentPoints.end()) {
506 aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
507 aCoincIt->first->baseAttribute());
509 aPoint2D->setValue(aCoords[0], aCoords[1]);
510 std::set<EntityWrapperPtr>::const_iterator aSlaveIt = aCoincIt->second.begin();
511 for (; aSlaveIt != aCoincIt->second.end(); ++aSlaveIt) {
512 aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>((*aSlaveIt)->baseAttribute());
514 aPoint2D->setValue(aCoords[0], aCoords[1]);
520 AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anIt->first);
521 if (aScalar && !isExternal) {
522 if (isUpd[0] && fabs(aScalar->value() - aCoords[0]) > tolerance)
523 aScalar->setValue(aCoords[0]);
528 //blockEvents(false);
531 EntityWrapperPtr PlaneGCSSolver_Storage::calculateMiddlePoint(
532 EntityWrapperPtr theBase, double theCoeff)
534 std::shared_ptr<PlaneGCSSolver_Builder> aBuilder =
535 std::dynamic_pointer_cast<PlaneGCSSolver_Builder>(PlaneGCSSolver_Builder::getInstance());
537 std::shared_ptr<GeomAPI_XY> aMidPoint;
538 if (theBase->type() == ENTITY_LINE) {
539 std::shared_ptr<GeomAPI_Pnt2d> aPoints[2];
540 const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
541 std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
542 for (int i = 0; i < 2; ++i, ++anIt)
543 aPoints[i] = aBuilder->point(*anIt);
544 aMidPoint = aPoints[0]->xy()->multiplied(1.0 - theCoeff)->added(
545 aPoints[1]->xy()->multiplied(theCoeff));
547 else if (theBase->type() == ENTITY_ARC) {
549 double anArcPoint[3][2];
550 const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
551 std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
552 for (int i = 0; i < 3; ++i, ++anIt) {
553 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(*anIt);
554 anArcPoint[i][0] = aPoint->x();
555 anArcPoint[i][1] = aPoint->y();
557 // project last point of arc on the arc
558 double x = anArcPoint[1][0] - anArcPoint[0][0];
559 double y = anArcPoint[1][1] - anArcPoint[0][1];
560 double aRad = sqrt(x*x + y*y);
561 x = anArcPoint[2][0] - anArcPoint[0][0];
562 y = anArcPoint[2][1] - anArcPoint[0][1];
563 double aNorm = sqrt(x*x + y*y);
564 if (aNorm >= tolerance) {
565 anArcPoint[2][0] = x * aRad / aNorm;
566 anArcPoint[2][1] = y * aRad / aNorm;
568 anArcPoint[1][0] -= anArcPoint[0][0];
569 anArcPoint[1][1] -= anArcPoint[0][1];
570 if (theCoeff < tolerance) {
571 theX = anArcPoint[0][0] + anArcPoint[1][0];
572 theY = anArcPoint[0][1] + anArcPoint[1][1];
573 } else if (1 - theCoeff < tolerance) {
574 theX = anArcPoint[0][0] + anArcPoint[2][0];
575 theY = anArcPoint[0][1] + anArcPoint[2][1];
577 std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
578 std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
579 double anAngle = aStartDir->angle(aEndDir);
583 double aCos = cos(anAngle);
584 double aSin = sin(anAngle);
585 theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
586 theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
588 aMidPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(theX, theY));
592 return EntityWrapperPtr();
594 std::list<ParameterWrapperPtr> aParameters;
595 aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->x()));
596 aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->y()));
597 // Create entity (parameters are not filled)
598 GCSPointPtr aPnt(new GCS::Point);
599 aPnt->x = std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
600 aPnt->y = std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
602 EntityWrapperPtr aResult(new PlaneGCSSolver_PointWrapper(AttributePtr(), aPnt));
603 aResult->setGroup(myGroupID);
604 aResult->setParameters(aParameters);