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);
131 static ConstraintWrapperPtr
132 createConstraintCollinear(ConstraintPtr theConstraint,
133 const GroupID& theGroupID,
134 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
135 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
139 /// \brief Set flags for angle constraint
140 static void adjustAngle(ConstraintWrapperPtr theConstraint);
141 /// \brief Update mirror points
142 static void adjustMirror(ConstraintWrapperPtr theConstraint);
143 /// \brief Update a sign of the point-line distance constraint
144 static void adjustPtLineDistance(ConstraintWrapperPtr theConstraint);
146 /// \brief Transform points to be symmetric regarding to the mirror line
147 static void makeMirrorPoints(EntityWrapperPtr theOriginal,
148 EntityWrapperPtr theMirrored,
149 EntityWrapperPtr theMirrorLine);
153 // Initialization of constraint builder self pointer
154 BuilderPtr PlaneGCSSolver_Builder::mySelf = PlaneGCSSolver_Builder::getInstance();
156 BuilderPtr PlaneGCSSolver_Builder::getInstance()
159 mySelf = BuilderPtr(new PlaneGCSSolver_Builder);
160 SketchSolver_Manager::instance()->setBuilder(mySelf);
165 StoragePtr PlaneGCSSolver_Builder::createStorage(const GroupID& theGroup) const
167 return StoragePtr(new PlaneGCSSolver_Storage(theGroup));
170 SolverPtr PlaneGCSSolver_Builder::createSolver() const
172 return SolverPtr(new PlaneGCSSolver_Solver);
176 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
177 ConstraintPtr theConstraint,
178 const GroupID& theGroupID,
179 const EntityID& theSketchID,
180 const SketchSolver_ConstraintType& theType,
181 const double& theValue,
182 const EntityWrapperPtr& thePoint1,
183 const EntityWrapperPtr& thePoint2,
184 const EntityWrapperPtr& theEntity1,
185 const EntityWrapperPtr& theEntity2) const
187 ConstraintWrapperPtr aResult;
188 ParameterWrapperPtr anIntermediate;
190 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(thePoint1);
191 if (!aPoint1 && thePoint1 && thePoint1->type() == ENTITY_POINT)
192 aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint1)->subEntities().front() );
193 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(thePoint2);
194 if (!aPoint2 && thePoint2 && thePoint2->type() == ENTITY_POINT)
195 aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint2)->subEntities().front() );
198 case CONSTRAINT_PT_PT_COINCIDENT:
199 aResult = createConstraintCoincidence(theConstraint, theGroupID, aPoint1, aPoint2);
201 case CONSTRAINT_PT_ON_LINE:
202 case CONSTRAINT_PT_ON_CIRCLE:
203 aResult = createConstraintPointOnEntity(theConstraint, theGroupID, theType,
204 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
206 case CONSTRAINT_PT_PT_DISTANCE:
207 aResult = createConstraintDistancePointPoint(theConstraint, theGroupID,
208 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
211 case CONSTRAINT_PT_LINE_DISTANCE:
212 aResult = createConstraintDistancePointLine(theConstraint, theGroupID,
213 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
214 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
216 case CONSTRAINT_RADIUS:
217 aResult = createConstraintRadius(theConstraint, theGroupID,
218 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
219 GCS_ENTITY_WRAPPER(theEntity1));
221 case CONSTRAINT_ANGLE:
222 aResult = createConstraintAngle(theConstraint, theGroupID,
223 GCS_PARAMETER_WRAPPER(createParamAngle(GID_OUTOFGROUP, theValue)),
224 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
226 case CONSTRAINT_FIXED:
228 case CONSTRAINT_HORIZONTAL:
229 case CONSTRAINT_VERTICAL:
230 aResult = createConstraintHorizVert(theConstraint, theGroupID, theType,
231 GCS_ENTITY_WRAPPER(theEntity1));
233 case CONSTRAINT_PARALLEL:
234 aResult = createConstraintParallel(theConstraint, theGroupID,
235 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
237 case CONSTRAINT_PERPENDICULAR:
238 aResult = createConstraintPerpendicular(theConstraint, theGroupID,
239 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
241 case CONSTRAINT_EQUAL_LINES:
242 anIntermediate = createParameter(theGroupID);
243 case CONSTRAINT_EQUAL_LINE_ARC:
244 case CONSTRAINT_EQUAL_RADIUS:
245 aResult = createConstraintEqual(theConstraint, theGroupID, theType,
246 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2),
247 GCS_PARAMETER_WRAPPER(anIntermediate));
249 case CONSTRAINT_TANGENT_ARC_LINE:
250 case CONSTRAINT_TANGENT_CIRCLE_LINE:
251 case CONSTRAINT_TANGENT_ARC_ARC:
252 aResult = createConstraintTangent(theConstraint, theGroupID, theType,
253 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
255 case CONSTRAINT_COLLINEAR:
256 aResult = createConstraintCollinear(theConstraint, theGroupID,
257 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
259 case CONSTRAINT_MULTI_TRANSLATION:
260 case CONSTRAINT_MULTI_ROTATION:
262 case CONSTRAINT_SYMMETRIC:
263 return createMirror(theConstraint, theGroupID, theSketchID,
264 thePoint1, thePoint2, theEntity1);
270 return std::list<ConstraintWrapperPtr>();
271 adjustConstraint(aResult);
272 return std::list<ConstraintWrapperPtr>(1, aResult);
275 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
276 ConstraintPtr theConstraint,
277 const GroupID& theGroupID,
278 const EntityID& theSketchID,
279 const SketchSolver_ConstraintType& theType,
280 const double& theValue,
281 const bool theFullValue,
282 const EntityWrapperPtr& thePoint1,
283 const EntityWrapperPtr& thePoint2,
284 const std::list<EntityWrapperPtr>& theTrsfEnt) const
286 ParameterWrapperPtr anAngleParam;
287 if (theType == CONSTRAINT_MULTI_ROTATION)
288 anAngleParam = createParamAngle(theGroupID, theValue);
289 else if (theType != CONSTRAINT_MULTI_TRANSLATION)
290 return std::list<ConstraintWrapperPtr>();
292 std::list<EntityWrapperPtr> aConstrAttrList = theTrsfEnt;
294 aConstrAttrList.push_front(thePoint2);
295 aConstrAttrList.push_front(thePoint1);
297 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
298 new PlaneGCSSolver_ConstraintWrapper(theConstraint, std::list<GCSConstraintPtr>(), theType));
299 aResult->setGroup(theGroupID);
300 aResult->setEntities(aConstrAttrList);
302 aResult->setValueParameter(anAngleParam);
303 aResult->setIsFullValue(theFullValue);
304 return std::list<ConstraintWrapperPtr>(1, aResult);
308 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createMirror(
309 ConstraintPtr theConstraint,
310 const GroupID& theGroupID,
311 const EntityID& theSketchID,
312 const EntityWrapperPtr& theEntity1,
313 const EntityWrapperPtr& theEntity2,
314 const EntityWrapperPtr& theMirrorLine) const
316 std::list<ConstraintWrapperPtr> aResult;
317 std::list<EntityWrapperPtr> aConstrAttrList;
318 if (theEntity1->type() == ENTITY_POINT) {
319 if (theEntity2->group() == theGroupID) // theEntity2 is not fixed
320 makeMirrorPoints(theEntity1, theEntity2, theMirrorLine);
322 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(theEntity1);
323 if (!aPoint1 && theEntity1->type() == ENTITY_POINT)
324 aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity1)->subEntities().front() );
325 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(theEntity2);
326 if (!aPoint2 && theEntity2->type() == ENTITY_POINT)
327 aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity2)->subEntities().front() );
329 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aMirrorLine =
330 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMirrorLine);
331 std::shared_ptr<GCS::Line> aLine =
332 std::dynamic_pointer_cast<GCS::Line>(aMirrorLine->entity());
334 std::list<GCSConstraintPtr> aConstrList;
335 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
336 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
337 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintMidpointOnLine(
338 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
340 ConstraintWrapperPtr aSubResult(new PlaneGCSSolver_ConstraintWrapper(
341 theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
342 aSubResult->setGroup(theGroupID);
343 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
344 aSubs.push_back(theEntity2);
345 aSubs.push_back(theMirrorLine);
346 aSubResult->setEntities(aSubs);
347 aResult.push_back(aSubResult);
349 else if (theEntity1->type() == ENTITY_LINE) {
350 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
351 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
352 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
353 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
354 for (; anIt1 != aPoints1.end() && anIt2 != aPoints2.end(); ++anIt1, ++anIt2) {
355 std::list<ConstraintWrapperPtr> aMrrList =
356 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
357 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
360 else if (theEntity1->type() == ENTITY_CIRCLE) {
361 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
362 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
363 for (; anIt1 != aPoints1.end(); ++anIt1)
364 if ((*anIt1)->type() == ENTITY_POINT)
366 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
367 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
368 for (; anIt2 != aPoints2.end(); ++anIt2)
369 if ((*anIt2)->type() == ENTITY_POINT)
372 std::list<ConstraintWrapperPtr> aMrrList =
373 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
374 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
376 // Additional constraint for equal radii
377 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
378 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
379 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
381 else if (theEntity1->type() == ENTITY_ARC) {
382 // Do not allow mirrored arc recalculate its position until coordinated of all points recalculated
383 FeaturePtr aMirrArc = theEntity2->baseFeature();
384 aMirrArc->data()->blockSendAttributeUpdated(true);
386 // Make mirror for center and start point of original arc
387 std::list<ConstraintWrapperPtr> aMrrList;
388 std::list<EntityWrapperPtr>::const_iterator anIt1 = theEntity1->subEntities().begin();
389 std::list<EntityWrapperPtr>::const_iterator anIt2 = theEntity2->subEntities().begin();
390 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
391 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
395 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
396 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
398 // make symmetric last point of original arc and first point of mirrored arc without additional constraint
401 makeMirrorPoints(*anIt1, *anIt2, theMirrorLine);
403 // Additionally, make equal radii...
404 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
405 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
406 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
407 // ... and make parametric length of arcs the same
408 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt1 =
409 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity1);
410 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt2 =
411 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity2);
412 std::shared_ptr<GCS::Arc> anArc1 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt1->entity());
413 std::shared_ptr<GCS::Arc> anArc2 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt2->entity());
414 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> anIntermed =
415 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(
416 createParameter(theGroupID, *(anArc1->endAngle) - *(anArc1->startAngle)));
417 // By the way, recalculate start and end angles of mirrored arc
418 std::shared_ptr<GeomAPI_Dir2d> anOX(new GeomAPI_Dir2d(1.0, 0.0));
419 std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(
420 *(anArc2->start.x) - *(anArc2->center.x), *(anArc2->start.y) - *(anArc2->center.y)));
421 std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(
422 *(anArc2->end.x) - *(anArc2->center.x), *(anArc2->end.y) - *(anArc2->center.y)));
423 *anArc2->startAngle = anOX->angle(aStartDir);
424 *anArc2->endAngle = anOX->angle(aEndDir);
426 std::list<GCSConstraintPtr> aConstrList;
427 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
428 anArc1->endAngle, anArc1->startAngle, anIntermed->parameter())));
429 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
430 anArc2->endAngle, anArc2->startAngle, anIntermed->parameter())));
432 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aSubResult(
433 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
434 aSubResult->setGroup(theGroupID);
435 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
436 aSubs.push_back(theEntity2);
437 aSubs.push_back(theMirrorLine);
438 aSubResult->setEntities(aSubs);
439 aSubResult->setValueParameter(anIntermed);
440 aResult.push_back(aSubResult);
442 // Restore event sending
443 aMirrArc->data()->blockSendAttributeUpdated(false);
448 void PlaneGCSSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstraint) const
450 SketchSolver_ConstraintType aType = theConstraint->type();
451 // Update flags and parameters in constraints
452 if (aType == CONSTRAINT_ANGLE)
453 adjustAngle(theConstraint);
454 else if (aType == CONSTRAINT_PT_LINE_DISTANCE)
455 adjustPtLineDistance(theConstraint);
458 EntityWrapperPtr PlaneGCSSolver_Builder::createFeature(
459 FeaturePtr theFeature,
460 const std::list<EntityWrapperPtr>& theAttributes,
461 const GroupID& theGroupID,
462 const EntityID& /*theSketchID*/) const
464 static EntityWrapperPtr aDummy;
465 if (!theFeature->data()->isValid())
469 CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
471 return createSketchEntity(aSketch, theGroupID);
473 // SketchPlugin features
474 std::shared_ptr<SketchPlugin_Feature> aFeature =
475 std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
479 // Verify the feature by its kind
480 const std::string& aFeatureKind = aFeature->getKind();
482 if (aFeatureKind == SketchPlugin_Line::ID())
483 return createLine(theFeature, theAttributes, theGroupID);
485 else if (aFeatureKind == SketchPlugin_Circle::ID())
486 return createCircle(theFeature, theAttributes, theGroupID);
488 else if (aFeatureKind == SketchPlugin_Arc::ID())
489 return createArc(theFeature, theAttributes, theGroupID);
490 // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
491 else if (aFeatureKind == SketchPlugin_Point::ID()) {
492 EntityWrapperPtr aSub;
493 if (theAttributes.size() == 1)
494 aSub = theAttributes.front();
496 AttributePtr aPoint = theFeature->attribute(SketchPlugin_Point::COORD_ID());
497 if (aPoint->isInitialized())
498 aSub = createAttribute(aPoint, theGroupID);
503 GCSPointPtr aSubEnt =
504 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aSub)->point();
505 EntityWrapperPtr aNewEntity(new PlaneGCSSolver_EntityWrapper(theFeature));
506 aNewEntity->setSubEntities(std::list<EntityWrapperPtr>(1, aSub));
514 EntityWrapperPtr PlaneGCSSolver_Builder::createAttribute(
515 AttributePtr theAttribute,
516 const GroupID& theGroupID,
517 const EntityID& theSketchID) const
519 AttributePtr anAttribute = theAttribute;
520 AttributeRefAttrPtr aRefAttr =
521 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
523 if (aRefAttr->isObject()) {
524 // do not create features here
525 return EntityWrapperPtr();
527 anAttribute = aRefAttr->attr();
530 std::list<ParameterWrapperPtr> aParameters;
531 EntityWrapperPtr aResult;
534 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
535 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
537 aParameters.push_back(::createParameter(theGroupID, aPoint2D->x(), !aPoint2D->textX().empty()));
538 aParameters.push_back(::createParameter(theGroupID, aPoint2D->y(), !aPoint2D->textY().empty()));
539 GCSPointPtr aGCSPoint(new GCS::Point);
540 aGCSPoint->x = std::dynamic_pointer_cast<
541 PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
542 aGCSPoint->y = std::dynamic_pointer_cast<
543 PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
544 // Create entity (parameters are not filled)
545 aResult = EntityWrapperPtr(new PlaneGCSSolver_PointWrapper(theAttribute, aGCSPoint));
547 // Scalar value (used for the distance entities)
548 AttributeDoublePtr aScalar =
549 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
551 return createScalar(theGroupID, aScalar);
555 // unknown attribute type
556 return EntityWrapperPtr();
559 aResult->setGroup(theGroupID);
560 aResult->setParameters(aParameters);
564 ParameterWrapperPtr PlaneGCSSolver_Builder::createParameter(
565 const GroupID& theGroupID, double theValue) const
567 return ::createParameter(theGroupID, theValue);
571 EntityWrapperPtr PlaneGCSSolver_Builder::createSketchEntity(
572 CompositeFeaturePtr theSketch,
573 const GroupID& theGroupID) const
575 DataPtr aSketchData = theSketch->data();
576 if (!aSketchData || !aSketchData->isValid())
577 return EntityWrapperPtr(); // the sketch is incorrect
579 // Create dummy wrapper representing workplane
580 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aSketchEnt(
581 new PlaneGCSSolver_EntityWrapper(FeaturePtr(theSketch)));
582 aSketchEnt->setGroup(theGroupID);
583 aSketchEnt->setId(EID_SKETCH);
591 // ================ Auxiliary functions ==========================
592 ParameterWrapperPtr createParameter(
593 const GroupID& theGroup, const double theValue, const bool theExpr)
595 double* aParam = new double(theValue);
596 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_ParameterWrapper(aParam));
597 aWrapper->setGroup(theGroup);
598 aWrapper->setIsParametric(theExpr);
602 ParameterWrapperPtr createParamAngle(const GroupID& theGroup, const double& theValue)
604 double* aParam = new double(theValue);
605 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_AngleWrapper(aParam));
606 aWrapper->setGroup(theGroup);
610 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> createScalar(
611 const GroupID& theGroupID,
612 AttributeDoublePtr theDoubleAttr)
614 ParameterWrapperPtr aParam = createParameter(theGroupID, theDoubleAttr ? theDoubleAttr->value() : 0.0);
615 return std::shared_ptr<PlaneGCSSolver_ScalarWrapper>(
616 new PlaneGCSSolver_ScalarWrapper(theDoubleAttr, aParam));
619 EntityWrapperPtr createLine(FeaturePtr theFeature,
620 const std::list<EntityWrapperPtr>& theAttributes,
621 const GroupID& theGroupID)
623 EntityWrapperPtr aNewEntity;
624 std::list<EntityWrapperPtr> aSubs;
626 AttributePtr aStart = theFeature->attribute(SketchPlugin_Line::START_ID());
627 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Line::END_ID());
628 if (!aStart->isInitialized() || !aEnd->isInitialized())
631 std::shared_ptr<PlaneGCSSolver_PointWrapper> aStartEnt, aEndEnt;
632 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
633 for (; anIt != theAttributes.end(); ++anIt) {
634 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
635 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
638 if (aWrapper->isBase(aStart))
639 aStartEnt = aWrapper;
640 else if (aWrapper->isBase(aEnd))
643 if (!aStartEnt || !aEndEnt)
646 aSubs.push_back(aStartEnt);
647 aSubs.push_back(aEndEnt);
649 std::shared_ptr<GCS::Line> aLine(new GCS::Line);
650 aLine->p1 = *(aStartEnt->point());
651 aLine->p2 = *(aEndEnt->point());
653 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aLine));
654 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
655 aNewEntity->setSubEntities(aSubs);
659 EntityWrapperPtr createCircle(FeaturePtr theFeature,
660 const std::list<EntityWrapperPtr>& theAttributes,
661 const GroupID& theGroupID)
663 EntityWrapperPtr aNewEntity;
664 std::list<EntityWrapperPtr> aSubs;
666 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Circle::CENTER_ID());
667 AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
668 if (!aCenter->isInitialized() || !aRadius->isInitialized())
671 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt;
672 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aRadiusEnt;
673 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
674 for (; anIt != theAttributes.end(); ++anIt) {
675 if ((*anIt)->isBase(aCenter))
676 aCenterEnt = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
677 else if ((*anIt)->isBase(aRadius))
678 aRadiusEnt = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*anIt);
680 if (!aCenterEnt || !aRadiusEnt)
683 aSubs.push_back(aCenterEnt);
684 aSubs.push_back(aRadiusEnt);
686 std::shared_ptr<GCS::Circle> aCircle(new GCS::Circle);
687 aCircle->center = *(aCenterEnt->point());
688 aCircle->rad = aRadiusEnt->scalar();
690 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aCircle));
691 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
692 aNewEntity->setSubEntities(aSubs);
696 EntityWrapperPtr createArc(FeaturePtr theFeature,
697 const std::list<EntityWrapperPtr>& theAttributes,
698 const GroupID& theGroupID)
700 EntityWrapperPtr aNewEntity;
701 std::list<EntityWrapperPtr> aSubs;
703 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Arc::CENTER_ID());
704 AttributePtr aStart = theFeature->attribute(SketchPlugin_Arc::START_ID());
705 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Arc::END_ID());
706 if (!aCenter->isInitialized() || !aStart->isInitialized() || !aEnd->isInitialized())
709 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt, aStartEnt, aEndEnt;
710 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
711 for (; anIt != theAttributes.end(); ++anIt) {
712 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
713 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
716 if (aWrapper->isBase(aCenter))
717 aCenterEnt = aWrapper;
718 else if (aWrapper->isBase(aStart))
719 aStartEnt = aWrapper;
720 else if (aWrapper->isBase(aEnd))
723 if (!aCenterEnt || !aStartEnt || !aEndEnt)
726 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aStartAng, aEndAng, aRadius;
727 aStartAng = createScalar(theGroupID);
728 aEndAng = createScalar(theGroupID);
729 aRadius = createScalar(theGroupID);
731 aSubs.push_back(aCenterEnt);
732 aSubs.push_back(aStartEnt);
733 aSubs.push_back(aEndEnt);
734 aSubs.push_back(aStartAng);
735 aSubs.push_back(aEndAng);
736 aSubs.push_back(aRadius);
738 std::shared_ptr<GCS::Arc> anArc(new GCS::Arc);
739 anArc->center = *(aCenterEnt->point());
740 anArc->start = *(aStartEnt->point());
741 anArc->end = *(aEndEnt->point());
742 anArc->startAngle = aStartAng->scalar();
743 anArc->endAngle = aEndAng->scalar();
744 anArc->rad = aRadius->scalar();
746 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, anArc));
747 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
748 aNewEntity->setSubEntities(aSubs);
754 ConstraintWrapperPtr createConstraintCoincidence(
755 ConstraintPtr theConstraint,
756 const GroupID& theGroupID,
757 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
758 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
760 // Create equality constraint for corresponding attributes of the points
761 std::list<GCSConstraintPtr> aConstrList;
762 std::list<ParameterWrapperPtr>::const_iterator anIt1 = thePoint1->parameters().begin();
763 std::list<ParameterWrapperPtr>::const_iterator anIt2 = thePoint2->parameters().begin();
764 for (; anIt1 != thePoint1->parameters().end(); ++anIt1, ++anIt2) {
765 if (*anIt1 == *anIt2)
766 continue; // points use same parameters, no need additional constraints
767 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam1 =
768 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt1);
769 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam2 =
770 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt2);
771 aConstrList.push_back(
772 GCSConstraintPtr(new GCS::ConstraintEqual(aParam1->parameter(), aParam2->parameter())));
775 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
776 theConstraint, aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
777 aResult->setGroup(theGroupID);
778 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
779 aSubs.push_back(thePoint2);
780 aResult->setEntities(aSubs);
784 ConstraintWrapperPtr createConstraintPointOnEntity(
785 ConstraintPtr theConstraint,
786 const GroupID& theGroupID,
787 const SketchSolver_ConstraintType& theType,
788 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
789 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
791 GCSConstraintPtr aNewConstr;
793 switch (theEntity->type()) {
795 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
796 aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnLine(*(thePoint->point()), *aLine));
800 case ENTITY_CIRCLE: {
801 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
802 aNewConstr = GCSConstraintPtr(
803 new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
807 return ConstraintWrapperPtr();
810 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
811 theConstraint, aNewConstr, theType));
812 aResult->setGroup(theGroupID);
813 std::list<EntityWrapperPtr> aSubs(1, thePoint);
814 aSubs.push_back(theEntity);
815 aResult->setEntities(aSubs);
819 ConstraintWrapperPtr createConstraintDistancePointPoint(
820 ConstraintPtr theConstraint,
821 const GroupID& theGroupID,
822 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
823 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
824 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
826 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
827 *(thePoint1->point()), *(thePoint2->point()), theValue->parameter()));
829 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
830 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
831 aResult->setGroup(theGroupID);
832 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
833 aSubs.push_back(thePoint2);
834 aResult->setEntities(aSubs);
835 aResult->setValueParameter(theValue);
839 ConstraintWrapperPtr createConstraintDistancePointLine(
840 ConstraintPtr theConstraint,
841 const GroupID& theGroupID,
842 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
843 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
844 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
846 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
847 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
848 *(thePoint->point()), *(aLine), theValue->parameter()));
850 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
851 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
852 aResult->setGroup(theGroupID);
853 std::list<EntityWrapperPtr> aSubs(1, thePoint);
854 aSubs.push_back(theEntity);
855 aResult->setEntities(aSubs);
856 aResult->setValueParameter(theValue);
860 ConstraintWrapperPtr createConstraintRadius(
861 ConstraintPtr theConstraint,
862 const GroupID& theGroupID,
863 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
864 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
866 std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
867 GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->parameter()));
869 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
870 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_RADIUS));
871 aResult->setGroup(theGroupID);
872 std::list<EntityWrapperPtr> aSubs(1, theEntity);
873 aResult->setEntities(aSubs);
874 aResult->setValueParameter(theValue);
878 ConstraintWrapperPtr createConstraintAngle(
879 ConstraintPtr theConstraint,
880 const GroupID& theGroupID,
881 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
882 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
883 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
885 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
886 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
887 GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
888 *(aLine1), *(aLine2), theValue->parameter()));
890 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
891 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_ANGLE));
892 aResult->setGroup(theGroupID);
893 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
894 aSubs.push_back(theEntity2);
895 aResult->setEntities(aSubs);
896 aResult->setValueParameter(theValue);
900 ConstraintWrapperPtr createConstraintHorizVert(
901 ConstraintPtr theConstraint,
902 const GroupID& theGroupID,
903 const SketchSolver_ConstraintType& theType,
904 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
906 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
907 GCSConstraintPtr aNewConstr;
908 if (theType == CONSTRAINT_HORIZONTAL)
909 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.y, aLine->p2.y));
911 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
913 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
914 theConstraint, aNewConstr, theType));
915 aResult->setGroup(theGroupID);
916 std::list<EntityWrapperPtr> aSubs(1, theEntity);
917 aResult->setEntities(aSubs);
921 ConstraintWrapperPtr createConstraintCollinear(
922 ConstraintPtr theConstraint,
923 const GroupID& theGroupID,
924 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
925 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
927 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
928 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
930 // create two point-on-line constraints
931 std::list<GCSConstraintPtr> aConstrList;
932 aConstrList.push_back( GCSConstraintPtr(new GCS::ConstraintPointOnLine(aLine2->p1, *aLine1)) );
933 aConstrList.push_back( GCSConstraintPtr(new GCS::ConstraintPointOnLine(aLine2->p2, *aLine1)) );
935 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
936 theConstraint, aConstrList, CONSTRAINT_COLLINEAR));
937 aResult->setGroup(theGroupID);
938 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
939 aSubs.push_back(theEntity2);
940 aResult->setEntities(aSubs);
944 ConstraintWrapperPtr createConstraintParallel(
945 ConstraintPtr theConstraint,
946 const GroupID& theGroupID,
947 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
948 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
950 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
951 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
952 GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
954 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
955 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PARALLEL));
956 aResult->setGroup(theGroupID);
957 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
958 aSubs.push_back(theEntity2);
959 aResult->setEntities(aSubs);
963 ConstraintWrapperPtr createConstraintPerpendicular(
964 ConstraintPtr theConstraint,
965 const GroupID& theGroupID,
966 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
967 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
969 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
970 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
971 GCSConstraintPtr aNewConstr(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
973 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
974 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PERPENDICULAR));
975 aResult->setGroup(theGroupID);
976 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
977 aSubs.push_back(theEntity2);
978 aResult->setEntities(aSubs);
982 ConstraintWrapperPtr createConstraintEqual(
983 ConstraintPtr theConstraint,
984 const GroupID& theGroupID,
985 const SketchSolver_ConstraintType& theType,
986 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
987 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
988 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed)
990 if (theType == CONSTRAINT_EQUAL_LINE_ARC)
991 return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
993 std::list<GCSConstraintPtr> aConstrList;
994 if (theType == CONSTRAINT_EQUAL_LINES) {
995 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
996 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
998 aConstrList.push_back(GCSConstraintPtr(
999 new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->parameter())));
1000 aConstrList.push_back(GCSConstraintPtr(
1001 new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->parameter())));
1003 std::shared_ptr<GCS::Circle> aCirc1 =
1004 std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1005 std::shared_ptr<GCS::Circle> aCirc2 =
1006 std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
1008 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
1011 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1012 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, theType));
1013 aResult->setGroup(theGroupID);
1014 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1015 aSubs.push_back(theEntity2);
1016 aResult->setEntities(aSubs);
1018 aResult->setValueParameter(theIntermed);
1022 ConstraintWrapperPtr createConstraintTangent(
1023 ConstraintPtr theConstraint,
1024 const GroupID& theGroupID,
1025 const SketchSolver_ConstraintType& theType,
1026 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1027 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
1029 GCSConstraintPtr aNewConstr;
1030 if (theType == CONSTRAINT_TANGENT_ARC_LINE || theType == CONSTRAINT_TANGENT_CIRCLE_LINE) {
1031 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1032 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1034 aNewConstr = GCSConstraintPtr(new GCS::ConstraintP2LDistance(aCirc->center, *aLine, aCirc->rad));
1036 std::shared_ptr<GCS::Circle> aCirc1 = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1037 std::shared_ptr<GCS::Circle> aCirc2 = std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
1039 double aDX = *(aCirc1->center.x) - *(aCirc2->center.x);
1040 double aDY = *(aCirc1->center.y) - *(aCirc2->center.y);
1041 double aDist = sqrt(aDX * aDX + aDY * aDY);
1042 aNewConstr = GCSConstraintPtr(new GCS::ConstraintTangentCircumf(aCirc1->center, aCirc2->center,
1043 aCirc1->rad, aCirc2->rad, (aDist < *(aCirc1->rad) || aDist < *(aCirc2->rad))));
1046 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1047 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, theType));
1048 aResult->setGroup(theGroupID);
1049 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1050 aSubs.push_back(theEntity2);
1051 aResult->setEntities(aSubs);
1059 void adjustAngle(ConstraintWrapperPtr theConstraint)
1061 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1063 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
1064 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
1066 std::shared_ptr<GeomAPI_Pnt2d> aPoints[2][2]; // start and end points of lines
1067 const std::list<EntityWrapperPtr>& aConstrLines = aConstraint->entities();
1068 std::list<EntityWrapperPtr>::const_iterator aCLIt = aConstrLines.begin();
1069 for (int i = 0; aCLIt != aConstrLines.end(); ++i, ++aCLIt) {
1070 const std::list<EntityWrapperPtr>& aLinePoints = (*aCLIt)->subEntities();
1071 std::list<EntityWrapperPtr>::const_iterator aLPIt = aLinePoints.begin();
1072 for (int j = 0; aLPIt != aLinePoints.end(); ++j, ++aLPIt)
1073 aPoints[i][j] = aBuilder->point(*aLPIt);
1076 std::shared_ptr<GeomAPI_Lin2d> aLine[2] = {
1077 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[0][0], aPoints[0][1])),
1078 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[1][0], aPoints[1][1]))
1080 std::shared_ptr<GeomAPI_Pnt2d> anIntersection = aLine[0]->intersect(aLine[1]);
1081 if (!anIntersection)
1084 for (int i = 0; i < 2; i++) {
1085 for (int j = 0; j < 2; j++) {
1086 aDist[i][j] = anIntersection->distance(aPoints[i][j]);
1087 if (fabs(aDist[i][j]) <= tolerance)
1090 if (aDist[i][0] > tolerance && aDist[i][1] > tolerance &&
1091 aDist[i][0] + aDist[i][1] < aPoints[i][0]->distance(aPoints[i][1]) + 2.0 * tolerance) {
1092 // the intersection point is an inner point of the line,
1093 // we change the sign of distance till start point to calculate correct coordinates
1095 aDist[i][0] *= -1.0;
1098 std::shared_ptr<GeomAPI_Dir2d> aDir[2];
1099 for (int i = 0; i < 2; i++) {
1100 if (aDist[i][1] > fabs(aDist[i][0]))
1101 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1102 aPoints[i][1]->xy()->decreased(anIntersection->xy())));
1104 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1105 aPoints[i][0]->xy()->decreased(anIntersection->xy())));
1106 // main direction is opposite => change signs
1107 if (aDist[i][0] < 0.0) {
1108 aDist[i][0] *= -1.0;
1109 aDist[i][1] *= -1.0;
1114 double anAngle = aLine[0]->direction()->angle(aLine[1]->direction()) / PI * 180;
1115 if (anAngle * aConstraint->value() < 0.0)
1116 aConstraint->setValue(-aConstraint->value());
1117 if ((90.0 - fabs(anAngle)) * (fabs(aConstraint->value()) - 90.0) > 0.0) {
1118 if (aConstraint->value() < 0.0)
1119 aConstraint->setValue(-180.0 - aConstraint->value());
1121 aConstraint->setValue(180.0 - aConstraint->value());
1125 void makeMirrorPoints(EntityWrapperPtr theOriginal,
1126 EntityWrapperPtr theMirrored,
1127 EntityWrapperPtr theMirrorLine)
1129 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1131 std::shared_ptr<GeomAPI_Lin2d> aMirrorLine = aBuilder->line(theMirrorLine);
1132 std::shared_ptr<GeomAPI_Dir2d> aMLDir = aMirrorLine->direction();
1133 // orthogonal direction
1134 aMLDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aMLDir->y(), -aMLDir->x()));
1136 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(theOriginal);
1137 std::shared_ptr<GeomAPI_XY> aVec = aPoint->xy()->decreased(aMirrorLine->location()->xy());
1138 double aDist = aVec->dot(aMLDir->xy());
1139 aVec = aPoint->xy()->added(aMLDir->xy()->multiplied(-2.0 * aDist));
1140 double aCoord[2] = {aVec->x(), aVec->y()};
1141 std::list<ParameterWrapperPtr>::const_iterator aMIt = theMirrored->parameters().begin();
1142 for (int i = 0; aMIt != theMirrored->parameters().end(); ++aMIt, ++i)
1143 (*aMIt)->setValue(aCoord[i]);
1145 // update corresponding attribute
1146 AttributePtr anAttr = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theMirrored)->baseAttribute();
1148 std::shared_ptr<GeomDataAPI_Point2D> aMirroredPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
1149 aMirroredPnt->setValue(aCoord[0], aCoord[1]);
1153 void adjustPtLineDistance(ConstraintWrapperPtr theConstraint)
1155 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1157 std::shared_ptr<GeomAPI_Pnt2d> aPoint;
1158 std::shared_ptr<GeomAPI_Lin2d> aLine;
1159 std::list<EntityWrapperPtr> aSubs = theConstraint->entities();
1160 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
1161 for (; aSIt != aSubs.end(); ++aSIt) {
1162 if ((*aSIt)->type() == ENTITY_POINT)
1163 aPoint = aBuilder->point(*aSIt);
1164 else if ((*aSIt)->type() == ENTITY_LINE)
1165 aLine = aBuilder->line(*aSIt);
1168 std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
1169 std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
1170 if (aPtLineVec->cross(aLineVec) * theConstraint->value() < 0.0)
1171 theConstraint->setValue(theConstraint->value() * (-1.0));