1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: PlaneGCSSolver_Builder.cpp
4 // Created: 14 Dec 2015
5 // Author: Artem ZHIDKOV
7 #include <PlaneGCSSolver_Builder.h>
8 #include <PlaneGCSSolver_Solver.h>
9 #include <PlaneGCSSolver_Storage.h>
10 #include <PlaneGCSSolver_ParameterWrapper.h>
11 #include <PlaneGCSSolver_AngleWrapper.h>
12 #include <PlaneGCSSolver_EntityWrapper.h>
13 #include <PlaneGCSSolver_PointWrapper.h>
14 #include <PlaneGCSSolver_ScalarWrapper.h>
15 #include <PlaneGCSSolver_ConstraintWrapper.h>
17 #include <SketchSolver_Manager.h>
19 #include <GeomAPI_Dir2d.h>
20 #include <GeomAPI_Pnt2d.h>
21 #include <GeomAPI_XY.h>
22 #include <GeomDataAPI_Dir.h>
23 #include <GeomDataAPI_Point.h>
24 #include <GeomDataAPI_Point2D.h>
25 #include <ModelAPI_Attribute.h>
26 #include <ModelAPI_AttributeRefAttr.h>
28 #include <SketchPlugin_Arc.h>
29 #include <SketchPlugin_Circle.h>
30 #include <SketchPlugin_Line.h>
31 #include <SketchPlugin_Point.h>
32 #include <SketchPlugin_ConstraintAngle.h>
37 #define GCS_ENTITY_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(x)
38 #define GCS_POINT_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(x)
39 #define GCS_PARAMETER_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(x)
42 /// \brief Converts a value to SolveSpace parameter
43 /// \param theGroup [in] group to store parameter
44 /// \param theValue [in] value of parameter
45 /// \param theExpr [in] shows the parameter is given by expression
46 /// \return Created parameter's wrapper
47 static ParameterWrapperPtr createParameter(const GroupID& theGroup,
48 const double theValue = 0.0,
49 const bool theExpr = false);
51 static ParameterWrapperPtr createParamAngle(const GroupID& theGroup,
52 const double& theValue = 0.0);
54 static std::shared_ptr<PlaneGCSSolver_ScalarWrapper>
55 createScalar(const GroupID& theGroupID,
56 AttributeDoublePtr theDoubleAttr = AttributeDoublePtr());
58 static EntityWrapperPtr createLine(FeaturePtr theFeature,
59 const std::list<EntityWrapperPtr>& theAttributes,
60 const GroupID& theGroupID);
61 static EntityWrapperPtr createCircle(FeaturePtr theFeature,
62 const std::list<EntityWrapperPtr>& theAttributes,
63 const GroupID& theGroupID);
64 static EntityWrapperPtr createArc(FeaturePtr theFeature,
65 const std::list<EntityWrapperPtr>& theAttributes,
66 const GroupID& theGroupID);
69 static ConstraintWrapperPtr
70 createConstraintCoincidence(ConstraintPtr theConstraint,
71 const GroupID& theGroupID,
72 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
73 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
74 static ConstraintWrapperPtr
75 createConstraintPointOnEntity(ConstraintPtr theConstraint,
76 const GroupID& theGroupID,
77 const SketchSolver_ConstraintType& theType,
78 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
79 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
80 static ConstraintWrapperPtr
81 createConstraintDistancePointPoint(ConstraintPtr theConstraint,
82 const GroupID& theGroupID,
83 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
84 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
85 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
86 static ConstraintWrapperPtr
87 createConstraintDistancePointLine(ConstraintPtr theConstraint,
88 const GroupID& theGroupID,
89 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
90 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
91 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
92 static ConstraintWrapperPtr
93 createConstraintRadius(ConstraintPtr theConstraint,
94 const GroupID& theGroupID,
95 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
96 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
97 static ConstraintWrapperPtr
98 createConstraintAngle(ConstraintPtr theConstraint,
99 const GroupID& theGroupID,
100 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
101 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
102 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
103 static ConstraintWrapperPtr
104 createConstraintHorizVert(ConstraintPtr theConstraint,
105 const GroupID& theGroupID,
106 const SketchSolver_ConstraintType& theType,
107 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
108 static ConstraintWrapperPtr
109 createConstraintParallel(ConstraintPtr theConstraint,
110 const GroupID& theGroupID,
111 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
112 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
113 static ConstraintWrapperPtr
114 createConstraintPerpendicular(ConstraintPtr theConstraint,
115 const GroupID& theGroupID,
116 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
117 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
118 static ConstraintWrapperPtr
119 createConstraintEqual(ConstraintPtr theConstraint,
120 const GroupID& theGroupID,
121 const SketchSolver_ConstraintType& theType,
122 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
123 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
124 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed);
125 static ConstraintWrapperPtr
126 createConstraintTangent(ConstraintPtr theConstraint,
127 const GroupID& theGroupID,
128 const SketchSolver_ConstraintType& theType,
129 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
130 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
134 /// \brief Set flags for angle constraint
135 static void adjustAngle(ConstraintWrapperPtr theConstraint);
136 /// \brief Update mirror points
137 static void adjustMirror(ConstraintWrapperPtr theConstraint);
138 /// \brief Update a sign of the point-line distance constraint
139 static void adjustPtLineDistance(ConstraintWrapperPtr theConstraint);
141 /// \brief Transform points to be symmetric regarding to the mirror line
142 static void makeMirrorPoints(EntityWrapperPtr theOriginal,
143 EntityWrapperPtr theMirrored,
144 EntityWrapperPtr theMirrorLine);
148 // Initialization of constraint builder self pointer
149 BuilderPtr PlaneGCSSolver_Builder::mySelf = PlaneGCSSolver_Builder::getInstance();
151 BuilderPtr PlaneGCSSolver_Builder::getInstance()
154 mySelf = BuilderPtr(new PlaneGCSSolver_Builder);
155 SketchSolver_Manager::instance()->setBuilder(mySelf);
160 StoragePtr PlaneGCSSolver_Builder::createStorage(const GroupID& theGroup) const
162 return StoragePtr(new PlaneGCSSolver_Storage(theGroup));
165 SolverPtr PlaneGCSSolver_Builder::createSolver() const
167 return SolverPtr(new PlaneGCSSolver_Solver);
171 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
172 ConstraintPtr theConstraint,
173 const GroupID& theGroupID,
174 const EntityID& theSketchID,
175 const SketchSolver_ConstraintType& theType,
176 const double& theValue,
177 const EntityWrapperPtr& thePoint1,
178 const EntityWrapperPtr& thePoint2,
179 const EntityWrapperPtr& theEntity1,
180 const EntityWrapperPtr& theEntity2) const
182 ConstraintWrapperPtr aResult;
183 ParameterWrapperPtr anIntermediate;
185 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(thePoint1);
186 if (!aPoint1 && thePoint1 && thePoint1->type() == ENTITY_POINT)
187 aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint1)->subEntities().front() );
188 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(thePoint2);
189 if (!aPoint2 && thePoint2 && thePoint2->type() == ENTITY_POINT)
190 aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint2)->subEntities().front() );
193 case CONSTRAINT_PT_PT_COINCIDENT:
194 aResult = createConstraintCoincidence(theConstraint, theGroupID, aPoint1, aPoint2);
196 case CONSTRAINT_PT_ON_LINE:
197 case CONSTRAINT_PT_ON_CIRCLE:
198 aResult = createConstraintPointOnEntity(theConstraint, theGroupID, theType,
199 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
201 case CONSTRAINT_PT_PT_DISTANCE:
202 aResult = createConstraintDistancePointPoint(theConstraint, theGroupID,
203 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
206 case CONSTRAINT_PT_LINE_DISTANCE:
207 aResult = createConstraintDistancePointLine(theConstraint, theGroupID,
208 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
209 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
211 case CONSTRAINT_RADIUS:
212 aResult = createConstraintRadius(theConstraint, theGroupID,
213 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
214 GCS_ENTITY_WRAPPER(theEntity1));
216 case CONSTRAINT_ANGLE:
217 aResult = createConstraintAngle(theConstraint, theGroupID,
218 GCS_PARAMETER_WRAPPER(createParamAngle(GID_OUTOFGROUP, theValue)),
219 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
221 case CONSTRAINT_FIXED:
223 case CONSTRAINT_HORIZONTAL:
224 case CONSTRAINT_VERTICAL:
225 aResult = createConstraintHorizVert(theConstraint, theGroupID, theType,
226 GCS_ENTITY_WRAPPER(theEntity1));
228 case CONSTRAINT_PARALLEL:
229 aResult = createConstraintParallel(theConstraint, theGroupID,
230 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
232 case CONSTRAINT_PERPENDICULAR:
233 aResult = createConstraintPerpendicular(theConstraint, theGroupID,
234 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
236 case CONSTRAINT_EQUAL_LINES:
237 anIntermediate = createParameter(theGroupID);
238 case CONSTRAINT_EQUAL_LINE_ARC:
239 case CONSTRAINT_EQUAL_RADIUS:
240 aResult = createConstraintEqual(theConstraint, theGroupID, theType,
241 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2),
242 GCS_PARAMETER_WRAPPER(anIntermediate));
244 case CONSTRAINT_TANGENT_ARC_LINE:
245 case CONSTRAINT_TANGENT_CIRCLE_LINE:
246 case CONSTRAINT_TANGENT_ARC_ARC:
247 aResult = createConstraintTangent(theConstraint, theGroupID, theType,
248 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
250 case CONSTRAINT_MULTI_TRANSLATION:
251 case CONSTRAINT_MULTI_ROTATION:
253 case CONSTRAINT_SYMMETRIC:
254 return createMirror(theConstraint, theGroupID, theSketchID,
255 thePoint1, thePoint2, theEntity1);
261 return std::list<ConstraintWrapperPtr>();
262 adjustConstraint(aResult);
263 return std::list<ConstraintWrapperPtr>(1, aResult);
266 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
267 ConstraintPtr theConstraint,
268 const GroupID& theGroupID,
269 const EntityID& theSketchID,
270 const SketchSolver_ConstraintType& theType,
271 const double& theValue,
272 const bool theFullValue,
273 const EntityWrapperPtr& thePoint1,
274 const EntityWrapperPtr& thePoint2,
275 const std::list<EntityWrapperPtr>& theTrsfEnt) const
277 ParameterWrapperPtr anAngleParam;
278 if (theType == CONSTRAINT_MULTI_ROTATION)
279 anAngleParam = createParamAngle(theGroupID, theValue);
280 else if (theType != CONSTRAINT_MULTI_TRANSLATION)
281 return std::list<ConstraintWrapperPtr>();
283 std::list<EntityWrapperPtr> aConstrAttrList = theTrsfEnt;
285 aConstrAttrList.push_front(thePoint2);
286 aConstrAttrList.push_front(thePoint1);
288 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
289 new PlaneGCSSolver_ConstraintWrapper(theConstraint, std::list<GCSConstraintPtr>(), theType));
290 aResult->setGroup(theGroupID);
291 aResult->setEntities(aConstrAttrList);
293 aResult->setValueParameter(anAngleParam);
294 aResult->setIsFullValue(theFullValue);
295 return std::list<ConstraintWrapperPtr>(1, aResult);
299 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createMirror(
300 ConstraintPtr theConstraint,
301 const GroupID& theGroupID,
302 const EntityID& theSketchID,
303 const EntityWrapperPtr& theEntity1,
304 const EntityWrapperPtr& theEntity2,
305 const EntityWrapperPtr& theMirrorLine) const
307 std::list<ConstraintWrapperPtr> aResult;
308 std::list<EntityWrapperPtr> aConstrAttrList;
309 if (theEntity1->type() == ENTITY_POINT) {
310 if (theEntity2->group() == theGroupID) // theEntity2 is not fixed
311 makeMirrorPoints(theEntity1, theEntity2, theMirrorLine);
313 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(theEntity1);
314 if (!aPoint1 && theEntity1->type() == ENTITY_POINT)
315 aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity1)->subEntities().front() );
316 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(theEntity2);
317 if (!aPoint2 && theEntity2->type() == ENTITY_POINT)
318 aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity2)->subEntities().front() );
320 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aMirrorLine =
321 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMirrorLine);
322 std::shared_ptr<GCS::Line> aLine =
323 std::dynamic_pointer_cast<GCS::Line>(aMirrorLine->entity());
325 std::list<GCSConstraintPtr> aConstrList;
326 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
327 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
328 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintMidpointOnLine(
329 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
331 ConstraintWrapperPtr aSubResult(new PlaneGCSSolver_ConstraintWrapper(
332 theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
333 aSubResult->setGroup(theGroupID);
334 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
335 aSubs.push_back(theEntity2);
336 aSubs.push_back(theMirrorLine);
337 aSubResult->setEntities(aSubs);
338 aResult.push_back(aSubResult);
340 else if (theEntity1->type() == ENTITY_LINE) {
341 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
342 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
343 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
344 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
345 for (; anIt1 != aPoints1.end() && anIt2 != aPoints2.end(); ++anIt1, ++anIt2) {
346 std::list<ConstraintWrapperPtr> aMrrList =
347 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
348 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
351 else if (theEntity1->type() == ENTITY_CIRCLE) {
352 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
353 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
354 for (; anIt1 != aPoints1.end(); ++anIt1)
355 if ((*anIt1)->type() == ENTITY_POINT)
357 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
358 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
359 for (; anIt2 != aPoints2.end(); ++anIt2)
360 if ((*anIt2)->type() == ENTITY_POINT)
363 std::list<ConstraintWrapperPtr> aMrrList =
364 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
365 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
367 // Additional constraint for equal radii
368 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
369 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
370 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
372 else if (theEntity1->type() == ENTITY_ARC) {
373 // Do not allow mirrored arc recalculate its position until coordinated of all points recalculated
374 FeaturePtr aMirrArc = theEntity2->baseFeature();
375 aMirrArc->data()->blockSendAttributeUpdated(true);
377 // Make mirror for center and start point of original arc
378 std::list<ConstraintWrapperPtr> aMrrList;
379 std::list<EntityWrapperPtr>::const_iterator anIt1 = theEntity1->subEntities().begin();
380 std::list<EntityWrapperPtr>::const_iterator anIt2 = theEntity2->subEntities().begin();
381 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
382 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
386 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
387 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
389 // make symmetric last point of original arc and first point of mirrored arc without additional constraint
392 makeMirrorPoints(*anIt1, *anIt2, theMirrorLine);
394 // Additionally, make equal radii...
395 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
396 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
397 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
398 // ... and make parametric length of arcs the same
399 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt1 =
400 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity1);
401 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt2 =
402 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity2);
403 std::shared_ptr<GCS::Arc> anArc1 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt1->entity());
404 std::shared_ptr<GCS::Arc> anArc2 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt2->entity());
405 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> anIntermed =
406 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(
407 createParameter(theGroupID, *(anArc1->endAngle) - *(anArc1->startAngle)));
408 // By the way, recalculate start and end angles of mirrored arc
409 std::shared_ptr<GeomAPI_Dir2d> anOX(new GeomAPI_Dir2d(1.0, 0.0));
410 std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(
411 *(anArc2->start.x) - *(anArc2->center.x), *(anArc2->start.y) - *(anArc2->center.y)));
412 std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(
413 *(anArc2->end.x) - *(anArc2->center.x), *(anArc2->end.y) - *(anArc2->center.y)));
414 *anArc2->startAngle = anOX->angle(aStartDir);
415 *anArc2->endAngle = anOX->angle(aEndDir);
417 std::list<GCSConstraintPtr> aConstrList;
418 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
419 anArc1->endAngle, anArc1->startAngle, anIntermed->parameter())));
420 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
421 anArc2->endAngle, anArc2->startAngle, anIntermed->parameter())));
423 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aSubResult(
424 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
425 aSubResult->setGroup(theGroupID);
426 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
427 aSubs.push_back(theEntity2);
428 aSubs.push_back(theMirrorLine);
429 aSubResult->setEntities(aSubs);
430 aSubResult->setValueParameter(anIntermed);
431 aResult.push_back(aSubResult);
433 // Restore event sending
434 aMirrArc->data()->blockSendAttributeUpdated(false);
439 void PlaneGCSSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstraint) const
441 SketchSolver_ConstraintType aType = theConstraint->type();
442 // Update flags and parameters in constraints
443 if (aType == CONSTRAINT_ANGLE)
444 adjustAngle(theConstraint);
445 else if (aType == CONSTRAINT_PT_LINE_DISTANCE)
446 adjustPtLineDistance(theConstraint);
449 EntityWrapperPtr PlaneGCSSolver_Builder::createFeature(
450 FeaturePtr theFeature,
451 const std::list<EntityWrapperPtr>& theAttributes,
452 const GroupID& theGroupID,
453 const EntityID& /*theSketchID*/) const
455 static EntityWrapperPtr aDummy;
456 if (!theFeature->data()->isValid())
460 CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
462 return createSketchEntity(aSketch, theGroupID);
464 // SketchPlugin features
465 std::shared_ptr<SketchPlugin_Feature> aFeature =
466 std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
470 // Verify the feature by its kind
471 const std::string& aFeatureKind = aFeature->getKind();
473 if (aFeatureKind == SketchPlugin_Line::ID())
474 return createLine(theFeature, theAttributes, theGroupID);
476 else if (aFeatureKind == SketchPlugin_Circle::ID())
477 return createCircle(theFeature, theAttributes, theGroupID);
479 else if (aFeatureKind == SketchPlugin_Arc::ID())
480 return createArc(theFeature, theAttributes, theGroupID);
481 // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
482 else if (aFeatureKind == SketchPlugin_Point::ID()) {
483 EntityWrapperPtr aSub;
484 if (theAttributes.size() == 1)
485 aSub = theAttributes.front();
487 AttributePtr aPoint = theFeature->attribute(SketchPlugin_Point::COORD_ID());
488 if (aPoint->isInitialized())
489 aSub = createAttribute(aPoint, theGroupID);
494 GCSPointPtr aSubEnt =
495 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aSub)->point();
496 EntityWrapperPtr aNewEntity(new PlaneGCSSolver_EntityWrapper(theFeature));
497 aNewEntity->setSubEntities(std::list<EntityWrapperPtr>(1, aSub));
505 EntityWrapperPtr PlaneGCSSolver_Builder::createAttribute(
506 AttributePtr theAttribute,
507 const GroupID& theGroupID,
508 const EntityID& theSketchID) const
510 AttributePtr anAttribute = theAttribute;
511 AttributeRefAttrPtr aRefAttr =
512 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
514 if (aRefAttr->isObject()) {
515 // do not create features here
516 return EntityWrapperPtr();
518 anAttribute = aRefAttr->attr();
521 std::list<ParameterWrapperPtr> aParameters;
522 EntityWrapperPtr aResult;
525 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
526 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
528 aParameters.push_back(::createParameter(theGroupID, aPoint2D->x(), !aPoint2D->textX().empty()));
529 aParameters.push_back(::createParameter(theGroupID, aPoint2D->y(), !aPoint2D->textY().empty()));
530 GCSPointPtr aGCSPoint(new GCS::Point);
531 aGCSPoint->x = std::dynamic_pointer_cast<
532 PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
533 aGCSPoint->y = std::dynamic_pointer_cast<
534 PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
535 // Create entity (parameters are not filled)
536 aResult = EntityWrapperPtr(new PlaneGCSSolver_PointWrapper(theAttribute, aGCSPoint));
538 // Scalar value (used for the distance entities)
539 AttributeDoublePtr aScalar =
540 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
542 return createScalar(theGroupID, aScalar);
546 // unknown attribute type
547 return EntityWrapperPtr();
550 aResult->setGroup(theGroupID);
551 aResult->setParameters(aParameters);
555 ParameterWrapperPtr PlaneGCSSolver_Builder::createParameter(
556 const GroupID& theGroupID, double theValue) const
558 return ::createParameter(theGroupID, theValue);
562 EntityWrapperPtr PlaneGCSSolver_Builder::createSketchEntity(
563 CompositeFeaturePtr theSketch,
564 const GroupID& theGroupID) const
566 DataPtr aSketchData = theSketch->data();
567 if (!aSketchData || !aSketchData->isValid())
568 return EntityWrapperPtr(); // the sketch is incorrect
570 // Create dummy wrapper representing workplane
571 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aSketchEnt(
572 new PlaneGCSSolver_EntityWrapper(FeaturePtr(theSketch)));
573 aSketchEnt->setGroup(theGroupID);
574 aSketchEnt->setId(EID_SKETCH);
582 // ================ Auxiliary functions ==========================
583 ParameterWrapperPtr createParameter(
584 const GroupID& theGroup, const double theValue, const bool theExpr)
586 double* aParam = new double(theValue);
587 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_ParameterWrapper(aParam));
588 aWrapper->setGroup(theGroup);
589 aWrapper->setIsParametric(theExpr);
593 ParameterWrapperPtr createParamAngle(const GroupID& theGroup, const double& theValue)
595 double* aParam = new double(theValue);
596 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_AngleWrapper(aParam));
597 aWrapper->setGroup(theGroup);
601 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> createScalar(
602 const GroupID& theGroupID,
603 AttributeDoublePtr theDoubleAttr)
605 ParameterWrapperPtr aParam = createParameter(theGroupID, theDoubleAttr ? theDoubleAttr->value() : 0.0);
606 return std::shared_ptr<PlaneGCSSolver_ScalarWrapper>(
607 new PlaneGCSSolver_ScalarWrapper(theDoubleAttr, aParam));
610 EntityWrapperPtr createLine(FeaturePtr theFeature,
611 const std::list<EntityWrapperPtr>& theAttributes,
612 const GroupID& theGroupID)
614 EntityWrapperPtr aNewEntity;
615 std::list<EntityWrapperPtr> aSubs;
617 AttributePtr aStart = theFeature->attribute(SketchPlugin_Line::START_ID());
618 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Line::END_ID());
619 if (!aStart->isInitialized() || !aEnd->isInitialized())
622 std::shared_ptr<PlaneGCSSolver_PointWrapper> aStartEnt, aEndEnt;
623 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
624 for (; anIt != theAttributes.end(); ++anIt) {
625 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
626 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
629 if (aWrapper->isBase(aStart))
630 aStartEnt = aWrapper;
631 else if (aWrapper->isBase(aEnd))
634 if (!aStartEnt || !aEndEnt)
637 aSubs.push_back(aStartEnt);
638 aSubs.push_back(aEndEnt);
640 std::shared_ptr<GCS::Line> aLine(new GCS::Line);
641 aLine->p1 = *(aStartEnt->point());
642 aLine->p2 = *(aEndEnt->point());
644 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aLine));
645 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
646 aNewEntity->setSubEntities(aSubs);
650 EntityWrapperPtr createCircle(FeaturePtr theFeature,
651 const std::list<EntityWrapperPtr>& theAttributes,
652 const GroupID& theGroupID)
654 EntityWrapperPtr aNewEntity;
655 std::list<EntityWrapperPtr> aSubs;
657 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Circle::CENTER_ID());
658 AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
659 if (!aCenter->isInitialized() || !aRadius->isInitialized())
662 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt;
663 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aRadiusEnt;
664 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
665 for (; anIt != theAttributes.end(); ++anIt) {
666 if ((*anIt)->isBase(aCenter))
667 aCenterEnt = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
668 else if ((*anIt)->isBase(aRadius))
669 aRadiusEnt = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*anIt);
671 if (!aCenterEnt || !aRadiusEnt)
674 aSubs.push_back(aCenterEnt);
675 aSubs.push_back(aRadiusEnt);
677 std::shared_ptr<GCS::Circle> aCircle(new GCS::Circle);
678 aCircle->center = *(aCenterEnt->point());
679 aCircle->rad = aRadiusEnt->scalar();
681 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aCircle));
682 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
683 aNewEntity->setSubEntities(aSubs);
687 EntityWrapperPtr createArc(FeaturePtr theFeature,
688 const std::list<EntityWrapperPtr>& theAttributes,
689 const GroupID& theGroupID)
691 EntityWrapperPtr aNewEntity;
692 std::list<EntityWrapperPtr> aSubs;
694 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Arc::CENTER_ID());
695 AttributePtr aStart = theFeature->attribute(SketchPlugin_Arc::START_ID());
696 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Arc::END_ID());
697 if (!aCenter->isInitialized() || !aStart->isInitialized() || !aEnd->isInitialized())
700 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt, aStartEnt, aEndEnt;
701 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
702 for (; anIt != theAttributes.end(); ++anIt) {
703 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
704 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
707 if (aWrapper->isBase(aCenter))
708 aCenterEnt = aWrapper;
709 else if (aWrapper->isBase(aStart))
710 aStartEnt = aWrapper;
711 else if (aWrapper->isBase(aEnd))
714 if (!aCenterEnt || !aStartEnt || !aEndEnt)
717 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aStartAng, aEndAng, aRadius;
718 aStartAng = createScalar(theGroupID);
719 aEndAng = createScalar(theGroupID);
720 aRadius = createScalar(theGroupID);
722 aSubs.push_back(aCenterEnt);
723 aSubs.push_back(aStartEnt);
724 aSubs.push_back(aEndEnt);
725 aSubs.push_back(aStartAng);
726 aSubs.push_back(aEndAng);
727 aSubs.push_back(aRadius);
729 std::shared_ptr<GCS::Arc> anArc(new GCS::Arc);
730 anArc->center = *(aCenterEnt->point());
731 anArc->start = *(aStartEnt->point());
732 anArc->end = *(aEndEnt->point());
733 anArc->startAngle = aStartAng->scalar();
734 anArc->endAngle = aEndAng->scalar();
735 anArc->rad = aRadius->scalar();
737 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, anArc));
738 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
739 aNewEntity->setSubEntities(aSubs);
745 ConstraintWrapperPtr createConstraintCoincidence(
746 ConstraintPtr theConstraint,
747 const GroupID& theGroupID,
748 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
749 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
751 // Create equality constraint for corresponding attributes of the points
752 std::list<GCSConstraintPtr> aConstrList;
753 std::list<ParameterWrapperPtr>::const_iterator anIt1 = thePoint1->parameters().begin();
754 std::list<ParameterWrapperPtr>::const_iterator anIt2 = thePoint2->parameters().begin();
755 for (; anIt1 != thePoint1->parameters().end(); ++anIt1, ++anIt2) {
756 if (*anIt1 == *anIt2)
757 continue; // points use same parameters, no need additional constraints
758 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam1 =
759 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt1);
760 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam2 =
761 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt2);
762 aConstrList.push_back(
763 GCSConstraintPtr(new GCS::ConstraintEqual(aParam1->parameter(), aParam2->parameter())));
766 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
767 theConstraint, aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
768 aResult->setGroup(theGroupID);
769 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
770 aSubs.push_back(thePoint2);
771 aResult->setEntities(aSubs);
775 ConstraintWrapperPtr createConstraintPointOnEntity(
776 ConstraintPtr theConstraint,
777 const GroupID& theGroupID,
778 const SketchSolver_ConstraintType& theType,
779 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
780 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
782 GCSConstraintPtr aNewConstr;
784 switch (theEntity->type()) {
786 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
787 aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnLine(*(thePoint->point()), *aLine));
791 case ENTITY_CIRCLE: {
792 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
793 aNewConstr = GCSConstraintPtr(
794 new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
798 return ConstraintWrapperPtr();
801 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
802 theConstraint, aNewConstr, theType));
803 aResult->setGroup(theGroupID);
804 std::list<EntityWrapperPtr> aSubs(1, thePoint);
805 aSubs.push_back(theEntity);
806 aResult->setEntities(aSubs);
810 ConstraintWrapperPtr createConstraintDistancePointPoint(
811 ConstraintPtr theConstraint,
812 const GroupID& theGroupID,
813 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
814 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
815 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
817 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
818 *(thePoint1->point()), *(thePoint2->point()), theValue->parameter()));
820 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
821 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
822 aResult->setGroup(theGroupID);
823 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
824 aSubs.push_back(thePoint2);
825 aResult->setEntities(aSubs);
826 aResult->setValueParameter(theValue);
830 ConstraintWrapperPtr createConstraintDistancePointLine(
831 ConstraintPtr theConstraint,
832 const GroupID& theGroupID,
833 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
834 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
835 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
837 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
838 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
839 *(thePoint->point()), *(aLine), theValue->parameter()));
841 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
842 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
843 aResult->setGroup(theGroupID);
844 std::list<EntityWrapperPtr> aSubs(1, thePoint);
845 aSubs.push_back(theEntity);
846 aResult->setEntities(aSubs);
847 aResult->setValueParameter(theValue);
851 ConstraintWrapperPtr createConstraintRadius(
852 ConstraintPtr theConstraint,
853 const GroupID& theGroupID,
854 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
855 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
857 std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
858 GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->parameter()));
860 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
861 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_RADIUS));
862 aResult->setGroup(theGroupID);
863 std::list<EntityWrapperPtr> aSubs(1, theEntity);
864 aResult->setEntities(aSubs);
865 aResult->setValueParameter(theValue);
869 ConstraintWrapperPtr createConstraintAngle(
870 ConstraintPtr theConstraint,
871 const GroupID& theGroupID,
872 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
873 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
874 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
876 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
877 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
878 GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
879 *(aLine1), *(aLine2), theValue->parameter()));
881 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
882 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_ANGLE));
883 aResult->setGroup(theGroupID);
884 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
885 aSubs.push_back(theEntity2);
886 aResult->setEntities(aSubs);
887 aResult->setValueParameter(theValue);
891 ConstraintWrapperPtr createConstraintHorizVert(
892 ConstraintPtr theConstraint,
893 const GroupID& theGroupID,
894 const SketchSolver_ConstraintType& theType,
895 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
897 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
898 GCSConstraintPtr aNewConstr;
899 if (theType == CONSTRAINT_HORIZONTAL)
900 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.y, aLine->p2.y));
902 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
904 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
905 theConstraint, aNewConstr, theType));
906 aResult->setGroup(theGroupID);
907 std::list<EntityWrapperPtr> aSubs(1, theEntity);
908 aResult->setEntities(aSubs);
912 ConstraintWrapperPtr createConstraintParallel(
913 ConstraintPtr theConstraint,
914 const GroupID& theGroupID,
915 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
916 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
918 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
919 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
920 GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
922 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
923 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PARALLEL));
924 aResult->setGroup(theGroupID);
925 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
926 aSubs.push_back(theEntity2);
927 aResult->setEntities(aSubs);
931 ConstraintWrapperPtr createConstraintPerpendicular(
932 ConstraintPtr theConstraint,
933 const GroupID& theGroupID,
934 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
935 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
937 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
938 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
939 GCSConstraintPtr aNewConstr(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
941 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
942 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PERPENDICULAR));
943 aResult->setGroup(theGroupID);
944 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
945 aSubs.push_back(theEntity2);
946 aResult->setEntities(aSubs);
950 ConstraintWrapperPtr createConstraintEqual(
951 ConstraintPtr theConstraint,
952 const GroupID& theGroupID,
953 const SketchSolver_ConstraintType& theType,
954 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
955 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
956 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed)
958 if (theType == CONSTRAINT_EQUAL_LINE_ARC)
959 return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
961 std::list<GCSConstraintPtr> aConstrList;
962 if (theType == CONSTRAINT_EQUAL_LINES) {
963 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
964 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
966 aConstrList.push_back(GCSConstraintPtr(
967 new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->parameter())));
968 aConstrList.push_back(GCSConstraintPtr(
969 new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->parameter())));
971 std::shared_ptr<GCS::Circle> aCirc1 =
972 std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
973 std::shared_ptr<GCS::Circle> aCirc2 =
974 std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
976 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
979 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
980 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, theType));
981 aResult->setGroup(theGroupID);
982 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
983 aSubs.push_back(theEntity2);
984 aResult->setEntities(aSubs);
986 aResult->setValueParameter(theIntermed);
990 ConstraintWrapperPtr createConstraintTangent(
991 ConstraintPtr theConstraint,
992 const GroupID& theGroupID,
993 const SketchSolver_ConstraintType& theType,
994 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
995 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
997 GCSConstraintPtr aNewConstr;
998 if (theType == CONSTRAINT_TANGENT_ARC_LINE || theType == CONSTRAINT_TANGENT_CIRCLE_LINE) {
999 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1000 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1002 aNewConstr = GCSConstraintPtr(new GCS::ConstraintP2LDistance(aCirc->center, *aLine, aCirc->rad));
1004 std::shared_ptr<GCS::Circle> aCirc1 = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1005 std::shared_ptr<GCS::Circle> aCirc2 = std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
1007 double aDX = *(aCirc1->center.x) - *(aCirc2->center.x);
1008 double aDY = *(aCirc1->center.y) - *(aCirc2->center.y);
1009 double aDist = sqrt(aDX * aDX + aDY * aDY);
1010 aNewConstr = GCSConstraintPtr(new GCS::ConstraintTangentCircumf(aCirc1->center, aCirc2->center,
1011 aCirc1->rad, aCirc2->rad, (aDist < *(aCirc1->rad) || aDist < *(aCirc2->rad))));
1014 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1015 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, theType));
1016 aResult->setGroup(theGroupID);
1017 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1018 aSubs.push_back(theEntity2);
1019 aResult->setEntities(aSubs);
1027 void adjustAngle(ConstraintWrapperPtr theConstraint)
1029 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1031 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
1032 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
1034 std::shared_ptr<GeomAPI_Pnt2d> aPoints[2][2]; // start and end points of lines
1035 const std::list<EntityWrapperPtr>& aConstrLines = aConstraint->entities();
1036 std::list<EntityWrapperPtr>::const_iterator aCLIt = aConstrLines.begin();
1037 for (int i = 0; aCLIt != aConstrLines.end(); ++i, ++aCLIt) {
1038 const std::list<EntityWrapperPtr>& aLinePoints = (*aCLIt)->subEntities();
1039 std::list<EntityWrapperPtr>::const_iterator aLPIt = aLinePoints.begin();
1040 for (int j = 0; aLPIt != aLinePoints.end(); ++j, ++aLPIt)
1041 aPoints[i][j] = aBuilder->point(*aLPIt);
1044 std::shared_ptr<GeomAPI_Lin2d> aLine[2] = {
1045 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[0][0], aPoints[0][1])),
1046 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[1][0], aPoints[1][1]))
1048 std::shared_ptr<GeomAPI_Pnt2d> anIntersection = aLine[0]->intersect(aLine[1]);
1049 if (!anIntersection)
1052 for (int i = 0; i < 2; i++) {
1053 for (int j = 0; j < 2; j++) {
1054 aDist[i][j] = anIntersection->distance(aPoints[i][j]);
1055 if (fabs(aDist[i][j]) <= tolerance)
1058 if (aDist[i][0] > tolerance && aDist[i][1] > tolerance &&
1059 aDist[i][0] + aDist[i][1] < aPoints[i][0]->distance(aPoints[i][1]) + 2.0 * tolerance) {
1060 // the intersection point is an inner point of the line,
1061 // we change the sign of distance till start point to calculate correct coordinates
1063 aDist[i][0] *= -1.0;
1066 std::shared_ptr<GeomAPI_Dir2d> aDir[2];
1067 for (int i = 0; i < 2; i++) {
1068 if (aDist[i][1] > fabs(aDist[i][0]))
1069 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1070 aPoints[i][1]->xy()->decreased(anIntersection->xy())));
1072 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1073 aPoints[i][0]->xy()->decreased(anIntersection->xy())));
1074 // main direction is opposite => change signs
1075 if (aDist[i][0] < 0.0) {
1076 aDist[i][0] *= -1.0;
1077 aDist[i][1] *= -1.0;
1082 double anAngle = aLine[0]->direction()->angle(aLine[1]->direction()) / PI * 180;
1083 if (anAngle * aConstraint->value() < 0.0)
1084 aConstraint->setValue(-aConstraint->value());
1085 if ((90.0 - fabs(anAngle)) * (fabs(aConstraint->value()) - 90.0) > 0.0) {
1086 if (aConstraint->value() < 0.0)
1087 aConstraint->setValue(-180.0 - aConstraint->value());
1089 aConstraint->setValue(180.0 - aConstraint->value());
1093 void makeMirrorPoints(EntityWrapperPtr theOriginal,
1094 EntityWrapperPtr theMirrored,
1095 EntityWrapperPtr theMirrorLine)
1097 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1099 std::shared_ptr<GeomAPI_Lin2d> aMirrorLine = aBuilder->line(theMirrorLine);
1100 std::shared_ptr<GeomAPI_Dir2d> aMLDir = aMirrorLine->direction();
1101 // orthogonal direction
1102 aMLDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aMLDir->y(), -aMLDir->x()));
1104 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(theOriginal);
1105 std::shared_ptr<GeomAPI_XY> aVec = aPoint->xy()->decreased(aMirrorLine->location()->xy());
1106 double aDist = aVec->dot(aMLDir->xy());
1107 aVec = aPoint->xy()->added(aMLDir->xy()->multiplied(-2.0 * aDist));
1108 double aCoord[2] = {aVec->x(), aVec->y()};
1109 std::list<ParameterWrapperPtr>::const_iterator aMIt = theMirrored->parameters().begin();
1110 for (int i = 0; aMIt != theMirrored->parameters().end(); ++aMIt, ++i)
1111 (*aMIt)->setValue(aCoord[i]);
1113 // update corresponding attribute
1114 AttributePtr anAttr = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theMirrored)->baseAttribute();
1116 std::shared_ptr<GeomDataAPI_Point2D> aMirroredPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
1117 aMirroredPnt->setValue(aCoord[0], aCoord[1]);
1121 void adjustPtLineDistance(ConstraintWrapperPtr theConstraint)
1123 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1125 std::shared_ptr<GeomAPI_Pnt2d> aPoint;
1126 std::shared_ptr<GeomAPI_Lin2d> aLine;
1127 std::list<EntityWrapperPtr> aSubs = theConstraint->entities();
1128 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
1129 for (; aSIt != aSubs.end(); ++aSIt) {
1130 if ((*aSIt)->type() == ENTITY_POINT)
1131 aPoint = aBuilder->point(*aSIt);
1132 else if ((*aSIt)->type() == ENTITY_LINE)
1133 aLine = aBuilder->line(*aSIt);
1136 std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
1137 std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
1138 if (aPtLineVec->cross(aLineVec) * theConstraint->value() < 0.0)
1139 theConstraint->setValue(theConstraint->value() * (-1.0));