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();
408 if (theEntity->type() == ENTITY_ARC) {
409 // workaround for the arc processing, because the arc is fixed by a set of constraints,
410 // which will conflict with all parameters fixed:
412 getParametersToMove(*aSIt++, theParamList);
413 // 2. take start point
414 getParametersToMove(*aSIt++, theParamList);
415 // 3. skip end point, radius and start angle, but take end angle parameter
416 getParametersToMove(*(++aSIt), theParamList);
418 for (; aSIt != aSubs.end(); ++aSIt)
419 getParametersToMove(*aSIt, theParamList);
423 void PlaneGCSSolver_Storage::toggleEntity(
424 const EntityWrapperPtr& theEntity, GCS::VEC_pD& theFrom, GCS::VEC_pD& theTo)
426 std::set<double*> aParamsToMove;
427 getParametersToMove(theEntity, aParamsToMove);
429 GCS::VEC_pD::iterator anIt = theFrom.begin();
430 while (anIt != theFrom.end()) {
431 if (aParamsToMove.find(*anIt) == aParamsToMove.end()) {
436 theTo.push_back(*anIt);
437 int aShift = anIt - theFrom.begin();
439 anIt = theFrom.begin() + aShift;
443 void PlaneGCSSolver_Storage::updateCoincident(const EntityWrapperPtr& thePoint)
445 CoincidentPointsMap::iterator anIt = myCoincidentPoints.begin();
446 for (; anIt != myCoincidentPoints.end(); ++anIt) {
447 if (anIt->first == thePoint || anIt->second.find(thePoint) != anIt->second.end()) {
448 std::set<EntityWrapperPtr> aCoincident = anIt->second;
449 aCoincident.insert(anIt->first);
451 const std::list<ParameterWrapperPtr>& aBaseParams = thePoint->parameters();
452 std::list<ParameterWrapperPtr> aParams;
453 std::list<ParameterWrapperPtr>::const_iterator aBaseIt, anUpdIt;
455 std::set<EntityWrapperPtr>::const_iterator aCoincIt = aCoincident.begin();
456 for (; aCoincIt != aCoincident.end(); ++aCoincIt)
457 if (*aCoincIt != thePoint && (*aCoincIt)->group() != GID_OUTOFGROUP) {
458 aParams = (*aCoincIt)->parameters();
459 aBaseIt = aBaseParams.begin();
460 for (anUpdIt = aParams.begin(); anUpdIt != aParams.end(); ++anUpdIt, ++aBaseIt)
461 (*anUpdIt)->setValue((*aBaseIt)->value());
470 bool PlaneGCSSolver_Storage::isRedundant(
471 GCSConstraintPtr theCheckedConstraint,
472 ConstraintWrapperPtr theParentConstraint) const
474 if (theParentConstraint->type() == CONSTRAINT_SYMMETRIC) {
475 if (theCheckedConstraint->getTypeId() == GCS::Perpendicular) {
476 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
477 // check the initial point is placed on the mirror line
478 std::list<EntityWrapperPtr> aSubs = theParentConstraint->entities();
479 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(aSubs.front());
480 std::shared_ptr<GeomAPI_Lin2d> aLine = aBuilder->line(aSubs.back());
481 return aLine->distance(aPoint) < tolerance;
488 void PlaneGCSSolver_Storage::initializeSolver(SolverPtr theSolver)
490 std::shared_ptr<PlaneGCSSolver_Solver> aSolver =
491 std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(theSolver);
498 // initialize constraints
499 std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
500 aCIt = myConstraintMap.begin();
501 for (; aCIt != myConstraintMap.end(); ++aCIt) {
502 std::list<ConstraintWrapperPtr>::const_iterator aCWIt = aCIt->second.begin();
503 for (; aCWIt != aCIt->second.end(); ++ aCWIt) {
504 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aGCS =
505 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(*aCWIt);
506 std::list<GCSConstraintPtr>::const_iterator anIt = aGCS->constraints().begin();
507 for (; anIt != aGCS->constraints().end(); ++anIt)
508 if (!isRedundant(*anIt, aGCS))
509 aSolver->addConstraint(*anIt);
512 // additional constraints for arcs
513 std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
514 anArcIt = myArcConstraintMap.begin();
515 for (; anArcIt != myArcConstraintMap.end(); ++anArcIt) {
516 std::vector<GCSConstraintPtr>::const_iterator anIt = anArcIt->second.begin();
517 for (; anIt != anArcIt->second.end(); ++anIt)
518 aSolver->addConstraint(*anIt);
520 // removed waste constraints
521 std::list<GCSConstraintPtr>::const_iterator aRemIt = myRemovedConstraints.begin();
522 for (; aRemIt != myRemovedConstraints.end(); ++aRemIt)
523 aSolver->removeConstraint(*aRemIt);
524 myRemovedConstraints.clear();
525 // initialize unknowns
526 aSolver->setParameters(myParameters);
529 void PlaneGCSSolver_Storage::refresh(bool theFixedOnly) const
533 std::map<AttributePtr, EntityWrapperPtr>::const_iterator anIt = myAttributeMap.begin();
534 std::list<ParameterWrapperPtr> aParams;
535 std::list<ParameterWrapperPtr>::const_iterator aParIt;
536 for (; anIt != myAttributeMap.end(); ++anIt) {
537 // the external feature always should keep the up to date values, so,
538 // refresh from the solver is never needed
539 bool isExternal = false;
540 if (anIt->first.get()) {
541 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
542 std::dynamic_pointer_cast<SketchPlugin_Feature>(anIt->first->owner());
543 if (aSketchFeature.get() && aSketchFeature->isExternal())
547 // update parameter wrappers and obtain values of attributes
548 aParams = anIt->second->parameters();
550 bool isUpd[3] = {false};
552 for (aParIt = aParams.begin(); i < 3 && aParIt != aParams.end(); ++aParIt, ++i) {
553 if (!theFixedOnly || isExternal ||
554 (*aParIt)->group() == GID_OUTOFGROUP || (*aParIt)->isParametric()) {
555 aCoords[i] = (*aParIt)->value();
559 if (!isUpd[0] && !isUpd[1] && !isUpd[2])
560 continue; // nothing is updated
562 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
563 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anIt->first);
565 if ((isUpd[0] && fabs(aPoint2D->x() - aCoords[0]) > tolerance) ||
566 (isUpd[1] && fabs(aPoint2D->y() - aCoords[1]) > tolerance) || isExternal) {
567 if (!isUpd[0] || isExternal) aCoords[0] = aPoint2D->x();
568 if (!isUpd[1] || isExternal) aCoords[1] = aPoint2D->y();
569 aPoint2D->setValue(aCoords[0], aCoords[1]);
570 // Find points coincident with this one (probably not in GID_OUTOFGROUP)
571 CoincidentPointsMap::const_iterator aCoincIt = myCoincidentPoints.begin();
572 for (; aCoincIt != myCoincidentPoints.end(); ++aCoincIt)
573 if (aCoincIt->first == anIt->second ||
574 aCoincIt->second.find(anIt->second) != aCoincIt->second.end())
576 if (aCoincIt != myCoincidentPoints.end()) {
577 aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
578 aCoincIt->first->baseAttribute());
580 aPoint2D->setValue(aCoords[0], aCoords[1]);
581 std::set<EntityWrapperPtr>::const_iterator aSlaveIt = aCoincIt->second.begin();
582 for (; aSlaveIt != aCoincIt->second.end(); ++aSlaveIt) {
583 aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>((*aSlaveIt)->baseAttribute());
585 aPoint2D->setValue(aCoords[0], aCoords[1]);
591 AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anIt->first);
592 if (aScalar && !isExternal) {
593 if (isUpd[0] && fabs(aScalar->value() - aCoords[0]) > tolerance)
594 aScalar->setValue(aCoords[0]);
599 //blockEvents(false);
602 EntityWrapperPtr PlaneGCSSolver_Storage::calculateMiddlePoint(
603 EntityWrapperPtr theBase, double theCoeff)
605 std::shared_ptr<PlaneGCSSolver_Builder> aBuilder =
606 std::dynamic_pointer_cast<PlaneGCSSolver_Builder>(PlaneGCSSolver_Builder::getInstance());
608 std::shared_ptr<GeomAPI_XY> aMidPoint;
609 if (theBase->type() == ENTITY_LINE) {
610 std::shared_ptr<GeomAPI_Pnt2d> aPoints[2];
611 const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
612 std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
613 for (int i = 0; i < 2; ++i, ++anIt)
614 aPoints[i] = aBuilder->point(*anIt);
615 aMidPoint = aPoints[0]->xy()->multiplied(1.0 - theCoeff)->added(
616 aPoints[1]->xy()->multiplied(theCoeff));
618 else if (theBase->type() == ENTITY_ARC) {
620 double anArcPoint[3][2];
621 const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
622 std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
623 for (int i = 0; i < 3; ++i, ++anIt) {
624 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(*anIt);
625 anArcPoint[i][0] = aPoint->x();
626 anArcPoint[i][1] = aPoint->y();
628 // project last point of arc on the arc
629 double x = anArcPoint[1][0] - anArcPoint[0][0];
630 double y = anArcPoint[1][1] - anArcPoint[0][1];
631 double aRad = sqrt(x*x + y*y);
632 x = anArcPoint[2][0] - anArcPoint[0][0];
633 y = anArcPoint[2][1] - anArcPoint[0][1];
634 double aNorm = sqrt(x*x + y*y);
635 if (aNorm >= tolerance) {
636 anArcPoint[2][0] = x * aRad / aNorm;
637 anArcPoint[2][1] = y * aRad / aNorm;
639 anArcPoint[1][0] -= anArcPoint[0][0];
640 anArcPoint[1][1] -= anArcPoint[0][1];
641 if (theCoeff < tolerance) {
642 theX = anArcPoint[0][0] + anArcPoint[1][0];
643 theY = anArcPoint[0][1] + anArcPoint[1][1];
644 } else if (1 - theCoeff < tolerance) {
645 theX = anArcPoint[0][0] + anArcPoint[2][0];
646 theY = anArcPoint[0][1] + anArcPoint[2][1];
648 std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
649 std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
650 double anAngle = aStartDir->angle(aEndDir);
654 double aCos = cos(anAngle);
655 double aSin = sin(anAngle);
656 theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
657 theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
659 aMidPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(theX, theY));
663 return EntityWrapperPtr();
665 std::list<ParameterWrapperPtr> aParameters;
666 aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->x()));
667 aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->y()));
668 // Create entity (parameters are not filled)
669 GCSPointPtr aPnt(new GCS::Point);
670 aPnt->x = std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
671 aPnt->y = std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
673 EntityWrapperPtr aResult(new PlaneGCSSolver_PointWrapper(AttributePtr(), aPnt));
674 aResult->setGroup(myGroupID);
675 aResult->setParameters(aParameters);