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 makeConstant(theEntity);
313 void PlaneGCSSolver_Storage::changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup)
318 void PlaneGCSSolver_Storage::verifyFixed()
323 void PlaneGCSSolver_Storage::processArc(const EntityWrapperPtr& theArc)
325 // Calculate additional parameters necessary for PlaneGCS
326 const std::list<EntityWrapperPtr>& aSubs = theArc->subEntities();
327 std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
328 while ((*aSubIt)->type() == ENTITY_POINT) // search scalar entities
330 double* aStartAngle = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
331 double* aEndAngle = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
332 double* aRadius = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt)->scalar();
334 FeaturePtr anArcFeature = theArc->baseFeature();
335 std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
336 anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
337 std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
338 anArcFeature->attribute(SketchPlugin_Arc::START_ID()));
339 std::shared_ptr<GeomDataAPI_Point2D> aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
340 anArcFeature->attribute(SketchPlugin_Arc::END_ID()));
341 if (!aCenterAttr || !aStartAttr || !aEndAttr)
343 std::shared_ptr<GeomAPI_Pnt2d> aCenterPnt = aCenterAttr->pnt();
344 std::shared_ptr<GeomAPI_Pnt2d> aStartPnt = aStartAttr->pnt();
345 std::shared_ptr<GeomAPI_Pnt2d> aEndPnt = aEndAttr->pnt();
347 *aRadius = aCenterPnt->distance(aStartPnt);
348 if (!anArcFeature->lastResult())
350 std::shared_ptr<GeomAPI_Edge> anArcEdge =
351 std::dynamic_pointer_cast<GeomAPI_Edge>(anArcFeature->lastResult()->shape());
354 anArcEdge->getRange(*aStartAngle, *aEndAngle);
356 // No need to add constraints if they are already exist
357 std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
358 aFound = myArcConstraintMap.find(theArc);
359 if (aFound != myArcConstraintMap.end())
362 // Prepare additional constraints to produce the arc
363 std::vector<GCSConstraintPtr> anArcConstraints;
364 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt =
365 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theArc);
366 std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt->entity());
367 // Distances from center till start and end points are equal to radius
368 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
369 anArc->center, anArc->start, anArc->rad)));
370 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
371 anArc->center, anArc->end, anArc->rad)));
372 // Angles of start and end points should be equal to given angles
373 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
374 anArc->center, anArc->start, anArc->startAngle)));
375 anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
376 anArc->center, anArc->end, anArc->endAngle)));
378 myArcConstraintMap[theArc] = anArcConstraints;
382 void PlaneGCSSolver_Storage::makeConstant(const EntityWrapperPtr& theEntity)
384 toggleEntity(theEntity, myParameters, myConst);
387 void PlaneGCSSolver_Storage::makeVariable(const EntityWrapperPtr& theEntity)
389 toggleEntity(theEntity, myConst, myParameters);
392 static void getParametersToMove(const EntityWrapperPtr& theEntity, std::set<double*>& theParamList)
394 const std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
395 std::list<ParameterWrapperPtr>::const_iterator aPIt = aParams.begin();
396 for (; aPIt != aParams.end(); ++aPIt)
398 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*aPIt)->parameter());
400 const std::list<EntityWrapperPtr> aSubs = theEntity->subEntities();
401 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
402 for (; aSIt != aSubs.end(); ++aSIt)
403 getParametersToMove(*aSIt, theParamList);
406 void PlaneGCSSolver_Storage::toggleEntity(
407 const EntityWrapperPtr& theEntity, GCS::VEC_pD& theFrom, GCS::VEC_pD& theTo)
409 std::set<double*> aParamsToMove;
410 getParametersToMove(theEntity, aParamsToMove);
412 GCS::VEC_pD::iterator anIt = theFrom.begin();
413 while (anIt != theFrom.end()) {
414 if (aParamsToMove.find(*anIt) == aParamsToMove.end()) {
419 theTo.push_back(*anIt);
420 int aShift = anIt - theFrom.begin();
422 anIt = theFrom.begin() + aShift;
427 void PlaneGCSSolver_Storage::initializeSolver(SolverPtr theSolver)
429 std::shared_ptr<PlaneGCSSolver_Solver> aSolver =
430 std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(theSolver);
437 // initialize constraints
438 std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
439 aCIt = myConstraintMap.begin();
440 for (; aCIt != myConstraintMap.end(); ++aCIt) {
441 std::list<ConstraintWrapperPtr>::const_iterator aCWIt = aCIt->second.begin();
442 for (; aCWIt != aCIt->second.end(); ++ aCWIt) {
443 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aGCS =
444 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(*aCWIt);
445 std::list<GCSConstraintPtr>::const_iterator anIt = aGCS->constraints().begin();
446 for (; anIt != aGCS->constraints().end(); ++anIt)
447 aSolver->addConstraint(*anIt);
450 // additional constraints for arcs
451 std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
452 anArcIt = myArcConstraintMap.begin();
453 for (; anArcIt != myArcConstraintMap.end(); ++anArcIt) {
454 std::vector<GCSConstraintPtr>::const_iterator anIt = anArcIt->second.begin();
455 for (; anIt != anArcIt->second.end(); ++anIt)
456 aSolver->addConstraint(*anIt);
458 // removed waste constraints
459 std::list<GCSConstraintPtr>::const_iterator aRemIt = myRemovedConstraints.begin();
460 for (; aRemIt != myRemovedConstraints.end(); ++aRemIt)
461 aSolver->removeConstraint(*aRemIt);
462 myRemovedConstraints.clear();
463 // initialize unknowns
464 aSolver->setParameters(myParameters);
467 void PlaneGCSSolver_Storage::refresh(bool theFixedOnly) const
471 std::map<AttributePtr, EntityWrapperPtr>::const_iterator anIt = myAttributeMap.begin();
472 std::list<ParameterWrapperPtr> aParams;
473 std::list<ParameterWrapperPtr>::const_iterator aParIt;
474 for (; anIt != myAttributeMap.end(); ++anIt) {
475 // the external feature always should keep the up to date values, so,
476 // refresh from the solver is never needed
477 bool isExternal = false;
478 if (anIt->first.get()) {
479 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
480 std::dynamic_pointer_cast<SketchPlugin_Feature>(anIt->first->owner());
481 if (aSketchFeature.get() && aSketchFeature->isExternal())
485 // update parameter wrappers and obtain values of attributes
486 aParams = anIt->second->parameters();
488 bool isUpd[3] = {false};
490 for (aParIt = aParams.begin(); i < 3 && aParIt != aParams.end(); ++aParIt, ++i) {
491 if (!theFixedOnly || isExternal ||
492 (*aParIt)->group() == GID_OUTOFGROUP || (*aParIt)->isParametric()) {
493 aCoords[i] = (*aParIt)->value();
497 if (!isUpd[0] && !isUpd[1] && !isUpd[2])
498 continue; // nothing is updated
500 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
501 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anIt->first);
503 if ((isUpd[0] && fabs(aPoint2D->x() - aCoords[0]) > tolerance) ||
504 (isUpd[1] && fabs(aPoint2D->y() - aCoords[1]) > tolerance) || isExternal) {
505 if (!isUpd[0] || isExternal) aCoords[0] = aPoint2D->x();
506 if (!isUpd[1] || isExternal) aCoords[1] = aPoint2D->y();
507 aPoint2D->setValue(aCoords[0], aCoords[1]);
508 // Find points coincident with this one (probably not in GID_OUTOFGROUP)
509 CoincidentPointsMap::const_iterator aCoincIt = myCoincidentPoints.begin();
510 for (; aCoincIt != myCoincidentPoints.end(); ++aCoincIt)
511 if (aCoincIt->first == anIt->second ||
512 aCoincIt->second.find(anIt->second) != aCoincIt->second.end())
514 if (aCoincIt != myCoincidentPoints.end()) {
515 aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
516 aCoincIt->first->baseAttribute());
518 aPoint2D->setValue(aCoords[0], aCoords[1]);
519 std::set<EntityWrapperPtr>::const_iterator aSlaveIt = aCoincIt->second.begin();
520 for (; aSlaveIt != aCoincIt->second.end(); ++aSlaveIt) {
521 aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>((*aSlaveIt)->baseAttribute());
523 aPoint2D->setValue(aCoords[0], aCoords[1]);
529 AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anIt->first);
530 if (aScalar && !isExternal) {
531 if (isUpd[0] && fabs(aScalar->value() - aCoords[0]) > tolerance)
532 aScalar->setValue(aCoords[0]);
537 //blockEvents(false);
540 EntityWrapperPtr PlaneGCSSolver_Storage::calculateMiddlePoint(
541 EntityWrapperPtr theBase, double theCoeff)
543 std::shared_ptr<PlaneGCSSolver_Builder> aBuilder =
544 std::dynamic_pointer_cast<PlaneGCSSolver_Builder>(PlaneGCSSolver_Builder::getInstance());
546 std::shared_ptr<GeomAPI_XY> aMidPoint;
547 if (theBase->type() == ENTITY_LINE) {
548 std::shared_ptr<GeomAPI_Pnt2d> aPoints[2];
549 const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
550 std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
551 for (int i = 0; i < 2; ++i, ++anIt)
552 aPoints[i] = aBuilder->point(*anIt);
553 aMidPoint = aPoints[0]->xy()->multiplied(1.0 - theCoeff)->added(
554 aPoints[1]->xy()->multiplied(theCoeff));
556 else if (theBase->type() == ENTITY_ARC) {
558 double anArcPoint[3][2];
559 const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
560 std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
561 for (int i = 0; i < 3; ++i, ++anIt) {
562 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(*anIt);
563 anArcPoint[i][0] = aPoint->x();
564 anArcPoint[i][1] = aPoint->y();
566 // project last point of arc on the arc
567 double x = anArcPoint[1][0] - anArcPoint[0][0];
568 double y = anArcPoint[1][1] - anArcPoint[0][1];
569 double aRad = sqrt(x*x + y*y);
570 x = anArcPoint[2][0] - anArcPoint[0][0];
571 y = anArcPoint[2][1] - anArcPoint[0][1];
572 double aNorm = sqrt(x*x + y*y);
573 if (aNorm >= tolerance) {
574 anArcPoint[2][0] = x * aRad / aNorm;
575 anArcPoint[2][1] = y * aRad / aNorm;
577 anArcPoint[1][0] -= anArcPoint[0][0];
578 anArcPoint[1][1] -= anArcPoint[0][1];
579 if (theCoeff < tolerance) {
580 theX = anArcPoint[0][0] + anArcPoint[1][0];
581 theY = anArcPoint[0][1] + anArcPoint[1][1];
582 } else if (1 - theCoeff < tolerance) {
583 theX = anArcPoint[0][0] + anArcPoint[2][0];
584 theY = anArcPoint[0][1] + anArcPoint[2][1];
586 std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
587 std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
588 double anAngle = aStartDir->angle(aEndDir);
592 double aCos = cos(anAngle);
593 double aSin = sin(anAngle);
594 theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
595 theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
597 aMidPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(theX, theY));
601 return EntityWrapperPtr();
603 std::list<ParameterWrapperPtr> aParameters;
604 aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->x()));
605 aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->y()));
606 // Create entity (parameters are not filled)
607 GCSPointPtr aPnt(new GCS::Point);
608 aPnt->x = std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
609 aPnt->y = std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
611 EntityWrapperPtr aResult(new PlaneGCSSolver_PointWrapper(AttributePtr(), aPnt));
612 aResult->setGroup(myGroupID);
613 aResult->setParameters(aParameters);