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_IntersectionPoint.h>
33 #include <SketchPlugin_ConstraintAngle.h>
38 #define GCS_ENTITY_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(x)
39 #define GCS_POINT_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(x)
40 #define GCS_PARAMETER_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(x)
43 /// \brief Converts a value to SolveSpace parameter
44 /// \param theGroup [in] group to store parameter
45 /// \param theValue [in] value of parameter
46 /// \param theExpr [in] shows the parameter is given by expression
47 /// \return Created parameter's wrapper
48 static ParameterWrapperPtr createParameter(const GroupID& theGroup,
49 const double theValue = 0.0,
50 const bool theExpr = false);
52 static ParameterWrapperPtr createParamAngle(const GroupID& theGroup,
53 const double& theValue = 0.0);
55 static std::shared_ptr<PlaneGCSSolver_ScalarWrapper>
56 createScalar(const GroupID& theGroupID,
57 AttributeDoublePtr theDoubleAttr = AttributeDoublePtr());
59 static EntityWrapperPtr createLine(FeaturePtr theFeature,
60 const std::list<EntityWrapperPtr>& theAttributes,
61 const GroupID& theGroupID);
62 static EntityWrapperPtr createCircle(FeaturePtr theFeature,
63 const std::list<EntityWrapperPtr>& theAttributes,
64 const GroupID& theGroupID);
65 static EntityWrapperPtr createArc(FeaturePtr theFeature,
66 const std::list<EntityWrapperPtr>& theAttributes,
67 const GroupID& theGroupID);
70 static ConstraintWrapperPtr
71 createConstraintCoincidence(ConstraintPtr theConstraint,
72 const GroupID& theGroupID,
73 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
74 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
75 static ConstraintWrapperPtr
76 createConstraintPointOnEntity(ConstraintPtr theConstraint,
77 const GroupID& theGroupID,
78 const SketchSolver_ConstraintType& theType,
79 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
80 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
81 static ConstraintWrapperPtr
82 createConstraintDistancePointPoint(ConstraintPtr theConstraint,
83 const GroupID& theGroupID,
84 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
85 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
86 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
87 static ConstraintWrapperPtr
88 createConstraintDistancePointLine(ConstraintPtr theConstraint,
89 const GroupID& theGroupID,
90 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
91 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
92 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
93 static ConstraintWrapperPtr
94 createConstraintRadius(ConstraintPtr theConstraint,
95 const GroupID& theGroupID,
96 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
97 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
98 static ConstraintWrapperPtr
99 createConstraintAngle(ConstraintPtr theConstraint,
100 const GroupID& theGroupID,
101 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
102 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
103 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
104 static ConstraintWrapperPtr
105 createConstraintHorizVert(ConstraintPtr theConstraint,
106 const GroupID& theGroupID,
107 const SketchSolver_ConstraintType& theType,
108 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
109 static ConstraintWrapperPtr
110 createConstraintParallel(ConstraintPtr theConstraint,
111 const GroupID& theGroupID,
112 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
113 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
114 static ConstraintWrapperPtr
115 createConstraintPerpendicular(ConstraintPtr theConstraint,
116 const GroupID& theGroupID,
117 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
118 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
119 static ConstraintWrapperPtr
120 createConstraintEqual(ConstraintPtr theConstraint,
121 const GroupID& theGroupID,
122 const SketchSolver_ConstraintType& theType,
123 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
124 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
125 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed);
126 static ConstraintWrapperPtr
127 createConstraintTangent(ConstraintPtr theConstraint,
128 const GroupID& theGroupID,
129 const SketchSolver_ConstraintType& theType,
130 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
131 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
132 static ConstraintWrapperPtr
133 createConstraintCollinear(ConstraintPtr theConstraint,
134 const GroupID& theGroupID,
135 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
136 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
137 static ConstraintWrapperPtr
138 createConstraintMiddlePoint(ConstraintPtr theConstraint,
139 const GroupID& theGroupID,
140 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
141 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
145 /// \brief Update mirror points
146 static void adjustMirror(ConstraintWrapperPtr theConstraint);
147 /// \brief Update a sign of the point-line distance constraint
148 static void adjustPtLineDistance(ConstraintWrapperPtr theConstraint);
150 /// \brief Transform points to be symmetric regarding to the mirror line
151 static void makeMirrorPoints(EntityWrapperPtr theOriginal,
152 EntityWrapperPtr theMirrored,
153 EntityWrapperPtr theMirrorLine);
157 // Initialization of constraint builder self pointer
158 BuilderPtr PlaneGCSSolver_Builder::mySelf = PlaneGCSSolver_Builder::getInstance();
160 BuilderPtr PlaneGCSSolver_Builder::getInstance()
163 mySelf = BuilderPtr(new PlaneGCSSolver_Builder);
164 SketchSolver_Manager::instance()->setBuilder(mySelf);
169 StoragePtr PlaneGCSSolver_Builder::createStorage(const GroupID& theGroup) const
171 return StoragePtr(new PlaneGCSSolver_Storage(theGroup));
174 SolverPtr PlaneGCSSolver_Builder::createSolver() const
176 return SolverPtr(new PlaneGCSSolver_Solver);
180 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
181 ConstraintPtr theConstraint,
182 const GroupID& theGroupID,
183 const EntityID& theSketchID,
184 const SketchSolver_ConstraintType& theType,
185 const double& theValue,
186 const EntityWrapperPtr& thePoint1,
187 const EntityWrapperPtr& thePoint2,
188 const EntityWrapperPtr& theEntity1,
189 const EntityWrapperPtr& theEntity2) const
191 ConstraintWrapperPtr aResult;
192 ParameterWrapperPtr anIntermediate;
194 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(thePoint1);
195 if (!aPoint1 && thePoint1 && thePoint1->type() == ENTITY_POINT)
196 aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint1)->subEntities().front() );
197 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(thePoint2);
198 if (!aPoint2 && thePoint2 && thePoint2->type() == ENTITY_POINT)
199 aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint2)->subEntities().front() );
202 case CONSTRAINT_PT_PT_COINCIDENT:
203 aResult = createConstraintCoincidence(theConstraint, theGroupID, aPoint1, aPoint2);
205 case CONSTRAINT_PT_ON_LINE:
206 case CONSTRAINT_PT_ON_CIRCLE:
207 aResult = createConstraintPointOnEntity(theConstraint, theGroupID, theType,
208 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
210 case CONSTRAINT_MIDDLE_POINT:
211 aResult = createConstraintMiddlePoint(theConstraint, theGroupID,
212 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
214 case CONSTRAINT_PT_PT_DISTANCE:
215 aResult = createConstraintDistancePointPoint(theConstraint, theGroupID,
216 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
219 case CONSTRAINT_PT_LINE_DISTANCE:
220 aResult = createConstraintDistancePointLine(theConstraint, theGroupID,
221 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
222 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
224 case CONSTRAINT_RADIUS:
225 aResult = createConstraintRadius(theConstraint, theGroupID,
226 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
227 GCS_ENTITY_WRAPPER(theEntity1));
229 case CONSTRAINT_ANGLE:
230 aResult = createConstraintAngle(theConstraint, theGroupID,
231 GCS_PARAMETER_WRAPPER(createParamAngle(GID_OUTOFGROUP, theValue)),
232 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
234 case CONSTRAINT_FIXED:
236 case CONSTRAINT_HORIZONTAL:
237 case CONSTRAINT_VERTICAL:
238 aResult = createConstraintHorizVert(theConstraint, theGroupID, theType,
239 GCS_ENTITY_WRAPPER(theEntity1));
241 case CONSTRAINT_PARALLEL:
242 aResult = createConstraintParallel(theConstraint, theGroupID,
243 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
245 case CONSTRAINT_PERPENDICULAR:
246 aResult = createConstraintPerpendicular(theConstraint, theGroupID,
247 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
249 case CONSTRAINT_EQUAL_LINES:
250 anIntermediate = createParameter(theGroupID);
251 case CONSTRAINT_EQUAL_LINE_ARC:
252 case CONSTRAINT_EQUAL_RADIUS:
253 aResult = createConstraintEqual(theConstraint, theGroupID, theType,
254 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2),
255 GCS_PARAMETER_WRAPPER(anIntermediate));
257 case CONSTRAINT_TANGENT_ARC_LINE:
258 case CONSTRAINT_TANGENT_CIRCLE_LINE:
259 case CONSTRAINT_TANGENT_ARC_ARC:
260 aResult = createConstraintTangent(theConstraint, theGroupID, theType,
261 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
263 case CONSTRAINT_COLLINEAR:
264 aResult = createConstraintCollinear(theConstraint, theGroupID,
265 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
267 case CONSTRAINT_MULTI_TRANSLATION:
268 case CONSTRAINT_MULTI_ROTATION:
270 case CONSTRAINT_SYMMETRIC:
271 return createMirror(theConstraint, theGroupID, theSketchID,
272 thePoint1, thePoint2, theEntity1);
278 return std::list<ConstraintWrapperPtr>();
279 adjustConstraint(aResult);
280 return std::list<ConstraintWrapperPtr>(1, aResult);
283 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
284 ConstraintPtr theConstraint,
285 const GroupID& theGroupID,
286 const EntityID& theSketchID,
287 const SketchSolver_ConstraintType& theType,
288 const double& theValue,
289 const bool theFullValue,
290 const EntityWrapperPtr& thePoint1,
291 const EntityWrapperPtr& thePoint2,
292 const std::list<EntityWrapperPtr>& theTrsfEnt) const
294 ParameterWrapperPtr anAngleParam;
295 if (theType == CONSTRAINT_MULTI_ROTATION)
296 anAngleParam = createParamAngle(theGroupID, theValue);
297 else if (theType != CONSTRAINT_MULTI_TRANSLATION)
298 return std::list<ConstraintWrapperPtr>();
300 std::list<EntityWrapperPtr> aConstrAttrList = theTrsfEnt;
302 aConstrAttrList.push_front(thePoint2);
303 aConstrAttrList.push_front(thePoint1);
305 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
306 new PlaneGCSSolver_ConstraintWrapper(theConstraint, std::list<GCSConstraintPtr>(), theType));
307 aResult->setGroup(theGroupID);
308 aResult->setEntities(aConstrAttrList);
310 aResult->setValueParameter(anAngleParam);
311 aResult->setIsFullValue(theFullValue);
312 return std::list<ConstraintWrapperPtr>(1, aResult);
316 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createMirror(
317 ConstraintPtr theConstraint,
318 const GroupID& theGroupID,
319 const EntityID& theSketchID,
320 const EntityWrapperPtr& theEntity1,
321 const EntityWrapperPtr& theEntity2,
322 const EntityWrapperPtr& theMirrorLine) const
324 std::list<ConstraintWrapperPtr> aResult;
325 std::list<EntityWrapperPtr> aConstrAttrList;
326 if (theEntity1->type() == ENTITY_POINT) {
327 if (theEntity2->group() == theGroupID) // theEntity2 is not fixed
328 makeMirrorPoints(theEntity1, theEntity2, theMirrorLine);
330 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(theEntity1);
331 if (!aPoint1 && theEntity1->type() == ENTITY_POINT)
332 aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity1)->subEntities().front() );
333 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(theEntity2);
334 if (!aPoint2 && theEntity2->type() == ENTITY_POINT)
335 aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity2)->subEntities().front() );
337 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aMirrorLine =
338 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMirrorLine);
339 std::shared_ptr<GCS::Line> aLine =
340 std::dynamic_pointer_cast<GCS::Line>(aMirrorLine->entity());
342 std::list<GCSConstraintPtr> aConstrList;
343 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintMidpointOnLine(
344 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
345 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
346 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
348 ConstraintWrapperPtr aSubResult(new PlaneGCSSolver_ConstraintWrapper(
349 theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
350 aSubResult->setGroup(theGroupID);
351 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
352 aSubs.push_back(theEntity2);
353 aSubs.push_back(theMirrorLine);
354 aSubResult->setEntities(aSubs);
355 aResult.push_back(aSubResult);
357 else if (theEntity1->type() == ENTITY_LINE) {
358 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
359 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
360 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
361 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
362 for (; anIt1 != aPoints1.end() && anIt2 != aPoints2.end(); ++anIt1, ++anIt2) {
363 std::list<ConstraintWrapperPtr> aMrrList =
364 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
365 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
368 else if (theEntity1->type() == ENTITY_CIRCLE) {
369 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
370 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
371 for (; anIt1 != aPoints1.end(); ++anIt1)
372 if ((*anIt1)->type() == ENTITY_POINT)
374 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
375 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
376 for (; anIt2 != aPoints2.end(); ++anIt2)
377 if ((*anIt2)->type() == ENTITY_POINT)
380 std::list<ConstraintWrapperPtr> aMrrList =
381 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
382 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
384 // Additional constraint for equal radii
385 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
386 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
387 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
389 else if (theEntity1->type() == ENTITY_ARC) {
390 // Do not allow mirrored arc recalculate its position until
391 // coordinated of all points recalculated
392 FeaturePtr aMirrArc = theEntity2->baseFeature();
393 bool aWasBlocked = aMirrArc->data()->blockSendAttributeUpdated(true);
395 // Make mirror for center and start point of original arc
396 std::list<ConstraintWrapperPtr> aMrrList;
397 std::list<EntityWrapperPtr>::const_iterator anIt1 = theEntity1->subEntities().begin();
398 std::list<EntityWrapperPtr>::const_iterator anIt2 = theEntity2->subEntities().begin();
399 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
400 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
404 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
405 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
407 // make symmetric last point of original arc and first point of
408 // mirrored arc without additional constraint
411 makeMirrorPoints(*anIt1, *anIt2, theMirrorLine);
413 // Additionally, make equal radii...
414 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
415 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
416 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
417 // ... and make parametric length of arcs the same
418 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt1 =
419 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity1);
420 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt2 =
421 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity2);
422 std::shared_ptr<GCS::Arc> anArc1 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt1->entity());
423 std::shared_ptr<GCS::Arc> anArc2 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt2->entity());
424 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> anIntermed =
425 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(
426 createParameter(theGroupID, *(anArc1->endAngle) - *(anArc1->startAngle)));
427 // By the way, recalculate start and end angles of mirrored arc
428 std::shared_ptr<GeomAPI_Dir2d> anOX(new GeomAPI_Dir2d(1.0, 0.0));
429 std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(
430 *(anArc2->start.x) - *(anArc2->center.x), *(anArc2->start.y) - *(anArc2->center.y)));
431 std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(
432 *(anArc2->end.x) - *(anArc2->center.x), *(anArc2->end.y) - *(anArc2->center.y)));
433 *anArc2->startAngle = anOX->angle(aStartDir);
434 *anArc2->endAngle = anOX->angle(aEndDir);
436 std::list<GCSConstraintPtr> aConstrList;
437 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
438 anArc1->endAngle, anArc1->startAngle, anIntermed->parameter())));
439 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
440 anArc2->endAngle, anArc2->startAngle, anIntermed->parameter())));
442 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aSubResult(
443 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
444 aSubResult->setGroup(theGroupID);
445 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
446 aSubs.push_back(theEntity2);
447 aSubs.push_back(theMirrorLine);
448 aSubResult->setEntities(aSubs);
449 aSubResult->setValueParameter(anIntermed);
450 aResult.push_back(aSubResult);
452 // Restore event sending
453 aMirrArc->data()->blockSendAttributeUpdated(aWasBlocked);
458 void PlaneGCSSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstraint) const
460 SketchSolver_ConstraintType aType = theConstraint->type();
461 // Update flags and parameters in constraints
462 if (aType == CONSTRAINT_PT_LINE_DISTANCE)
463 adjustPtLineDistance(theConstraint);
464 else if (aType == CONSTRAINT_SYMMETRIC)
465 adjustMirror(theConstraint);
468 EntityWrapperPtr PlaneGCSSolver_Builder::createFeature(
469 FeaturePtr theFeature,
470 const std::list<EntityWrapperPtr>& theAttributes,
471 const GroupID& theGroupID,
472 const EntityID& /*theSketchID*/) const
474 static EntityWrapperPtr aDummy;
475 if (!theFeature->data()->isValid())
479 CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
481 return createSketchEntity(aSketch, theGroupID);
483 // SketchPlugin features
484 std::shared_ptr<SketchPlugin_Feature> aFeature =
485 std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
489 // Verify the feature by its kind
490 const std::string& aFeatureKind = aFeature->getKind();
492 if (aFeatureKind == SketchPlugin_Line::ID())
493 return createLine(theFeature, theAttributes, theGroupID);
495 else if (aFeatureKind == SketchPlugin_Circle::ID())
496 return createCircle(theFeature, theAttributes, theGroupID);
498 else if (aFeatureKind == SketchPlugin_Arc::ID())
499 return createArc(theFeature, theAttributes, theGroupID);
500 // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
501 else if (aFeatureKind == SketchPlugin_Point::ID() ||
502 aFeatureKind == SketchPlugin_IntersectionPoint::ID()) {
503 EntityWrapperPtr aSub;
504 if (theAttributes.size() == 1)
505 aSub = theAttributes.front();
507 AttributePtr aPoint = theFeature->attribute(SketchPlugin_Point::COORD_ID());
508 if (aPoint->isInitialized())
509 aSub = createAttribute(aPoint, theGroupID);
514 GCSPointPtr aSubEnt =
515 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aSub)->point();
516 EntityWrapperPtr aNewEntity(new PlaneGCSSolver_EntityWrapper(theFeature));
517 aNewEntity->setSubEntities(std::list<EntityWrapperPtr>(1, aSub));
525 EntityWrapperPtr PlaneGCSSolver_Builder::createAttribute(
526 AttributePtr theAttribute,
527 const GroupID& theGroupID,
528 const EntityID& theSketchID) const
530 AttributePtr anAttribute = theAttribute;
531 AttributeRefAttrPtr aRefAttr =
532 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
534 if (aRefAttr->isObject()) {
535 // do not create features here
536 return EntityWrapperPtr();
538 anAttribute = aRefAttr->attr();
541 std::list<ParameterWrapperPtr> aParameters;
542 EntityWrapperPtr aResult;
545 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
546 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
548 aParameters.push_back(::createParameter(theGroupID, aPoint2D->x(), !aPoint2D->textX().empty()));
549 aParameters.push_back(::createParameter(theGroupID, aPoint2D->y(), !aPoint2D->textY().empty()));
550 GCSPointPtr aGCSPoint(new GCS::Point);
551 aGCSPoint->x = std::dynamic_pointer_cast<
552 PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
553 aGCSPoint->y = std::dynamic_pointer_cast<
554 PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
555 // Create entity (parameters are not filled)
556 aResult = EntityWrapperPtr(new PlaneGCSSolver_PointWrapper(theAttribute, aGCSPoint));
558 // Scalar value (used for the distance entities)
559 AttributeDoublePtr aScalar =
560 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
562 return createScalar(theGroupID, aScalar);
566 // unknown attribute type
567 return EntityWrapperPtr();
570 aResult->setGroup(theGroupID);
571 aResult->setParameters(aParameters);
575 ParameterWrapperPtr PlaneGCSSolver_Builder::createParameter(
576 const GroupID& theGroupID, double theValue) const
578 return ::createParameter(theGroupID, theValue);
582 EntityWrapperPtr PlaneGCSSolver_Builder::createSketchEntity(
583 CompositeFeaturePtr theSketch,
584 const GroupID& theGroupID) const
586 DataPtr aSketchData = theSketch->data();
587 if (!aSketchData || !aSketchData->isValid())
588 return EntityWrapperPtr(); // the sketch is incorrect
590 // Create dummy wrapper representing workplane
591 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aSketchEnt(
592 new PlaneGCSSolver_EntityWrapper(FeaturePtr(theSketch)));
593 aSketchEnt->setGroup(theGroupID);
594 aSketchEnt->setId(EID_SKETCH);
602 // ================ Auxiliary functions ==========================
603 ParameterWrapperPtr createParameter(
604 const GroupID& theGroup, const double theValue, const bool theExpr)
606 double* aParam = new double(theValue);
607 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_ParameterWrapper(aParam));
608 aWrapper->setGroup(theGroup);
609 aWrapper->setIsParametric(theExpr);
613 ParameterWrapperPtr createParamAngle(const GroupID& theGroup, const double& theValue)
615 double* aParam = new double(theValue);
616 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_AngleWrapper(aParam));
617 aWrapper->setGroup(theGroup);
621 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> createScalar(
622 const GroupID& theGroupID,
623 AttributeDoublePtr theDoubleAttr)
625 ParameterWrapperPtr aParam =
626 createParameter(theGroupID, theDoubleAttr ? theDoubleAttr->value() : 0.0);
627 return std::shared_ptr<PlaneGCSSolver_ScalarWrapper>(
628 new PlaneGCSSolver_ScalarWrapper(theDoubleAttr, aParam));
631 EntityWrapperPtr createLine(FeaturePtr theFeature,
632 const std::list<EntityWrapperPtr>& theAttributes,
633 const GroupID& theGroupID)
635 EntityWrapperPtr aNewEntity;
636 std::list<EntityWrapperPtr> aSubs;
638 AttributePtr aStart = theFeature->attribute(SketchPlugin_Line::START_ID());
639 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Line::END_ID());
640 if (!aStart->isInitialized() || !aEnd->isInitialized())
643 std::shared_ptr<PlaneGCSSolver_PointWrapper> aStartEnt, aEndEnt;
644 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
645 for (; anIt != theAttributes.end(); ++anIt) {
646 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
647 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
650 if (aWrapper->isBase(aStart))
651 aStartEnt = aWrapper;
652 else if (aWrapper->isBase(aEnd))
655 if (!aStartEnt || !aEndEnt)
658 aSubs.push_back(aStartEnt);
659 aSubs.push_back(aEndEnt);
661 std::shared_ptr<GCS::Line> aLine(new GCS::Line);
662 aLine->p1 = *(aStartEnt->point());
663 aLine->p2 = *(aEndEnt->point());
665 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aLine));
666 // sub-entities should not change their groups, therefore they are added later
667 aNewEntity->setGroup(theGroupID);
668 aNewEntity->setSubEntities(aSubs);
672 EntityWrapperPtr createCircle(FeaturePtr theFeature,
673 const std::list<EntityWrapperPtr>& theAttributes,
674 const GroupID& theGroupID)
676 EntityWrapperPtr aNewEntity;
677 std::list<EntityWrapperPtr> aSubs;
679 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Circle::CENTER_ID());
680 AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
681 if (!aCenter->isInitialized() || !aRadius->isInitialized())
684 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt;
685 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aRadiusEnt;
686 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
687 for (; anIt != theAttributes.end(); ++anIt) {
688 if ((*anIt)->isBase(aCenter))
689 aCenterEnt = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
690 else if ((*anIt)->isBase(aRadius))
691 aRadiusEnt = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*anIt);
693 if (!aCenterEnt || !aRadiusEnt)
696 aSubs.push_back(aCenterEnt);
697 aSubs.push_back(aRadiusEnt);
699 std::shared_ptr<GCS::Circle> aCircle(new GCS::Circle);
700 aCircle->center = *(aCenterEnt->point());
701 aCircle->rad = aRadiusEnt->scalar();
703 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aCircle));
704 // sub-entities should not change their groups, therefore they are added later
705 aNewEntity->setGroup(theGroupID);
706 aNewEntity->setSubEntities(aSubs);
710 EntityWrapperPtr createArc(FeaturePtr theFeature,
711 const std::list<EntityWrapperPtr>& theAttributes,
712 const GroupID& theGroupID)
714 EntityWrapperPtr aNewEntity;
715 std::list<EntityWrapperPtr> aSubs;
717 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Arc::CENTER_ID());
718 AttributePtr aStart = theFeature->attribute(SketchPlugin_Arc::START_ID());
719 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Arc::END_ID());
720 if (!aCenter->isInitialized() || !aStart->isInitialized() || !aEnd->isInitialized())
723 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt, aStartEnt, aEndEnt;
724 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
725 for (; anIt != theAttributes.end(); ++anIt) {
726 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
727 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
730 if (aWrapper->isBase(aCenter))
731 aCenterEnt = aWrapper;
732 else if (aWrapper->isBase(aStart))
733 aStartEnt = aWrapper;
734 else if (aWrapper->isBase(aEnd))
737 if (!aCenterEnt || !aStartEnt || !aEndEnt)
740 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aStartAng, aEndAng, aRadius;
741 aStartAng = createScalar(theGroupID);
742 aEndAng = createScalar(theGroupID);
743 aRadius = createScalar(theGroupID);
745 aSubs.push_back(aCenterEnt);
746 aSubs.push_back(aStartEnt);
747 aSubs.push_back(aEndEnt);
748 aSubs.push_back(aStartAng);
749 aSubs.push_back(aEndAng);
750 aSubs.push_back(aRadius);
752 std::shared_ptr<GCS::Arc> anArc(new GCS::Arc);
753 anArc->center = *(aCenterEnt->point());
754 anArc->start = *(aStartEnt->point());
755 anArc->end = *(aEndEnt->point());
756 anArc->startAngle = aStartAng->scalar();
757 anArc->endAngle = aEndAng->scalar();
758 anArc->rad = aRadius->scalar();
760 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, anArc));
761 // sub-entities should not change their groups, therefore they are added later
762 aNewEntity->setGroup(theGroupID);
763 aNewEntity->setSubEntities(aSubs);
769 ConstraintWrapperPtr createConstraintCoincidence(
770 ConstraintPtr theConstraint,
771 const GroupID& theGroupID,
772 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
773 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
775 // Create equality constraint for corresponding attributes of the points
776 std::list<GCSConstraintPtr> aConstrList;
777 std::list<ParameterWrapperPtr>::const_iterator anIt1 = thePoint1->parameters().begin();
778 std::list<ParameterWrapperPtr>::const_iterator anIt2 = thePoint2->parameters().begin();
779 for (; anIt1 != thePoint1->parameters().end(); ++anIt1, ++anIt2) {
780 if (*anIt1 == *anIt2)
781 continue; // points use same parameters, no need additional constraints
782 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam1 =
783 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt1);
784 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam2 =
785 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt2);
786 aConstrList.push_back(
787 GCSConstraintPtr(new GCS::ConstraintEqual(aParam1->parameter(), aParam2->parameter())));
790 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
791 theConstraint, aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
792 aResult->setGroup(theGroupID);
793 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
794 aSubs.push_back(thePoint2);
795 aResult->setEntities(aSubs);
799 ConstraintWrapperPtr createConstraintPointOnEntity(
800 ConstraintPtr theConstraint,
801 const GroupID& theGroupID,
802 const SketchSolver_ConstraintType& theType,
803 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
804 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
806 GCSConstraintPtr aNewConstr;
808 switch (theEntity->type()) {
810 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
811 aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnLine(*(thePoint->point()), *aLine));
815 case ENTITY_CIRCLE: {
816 std::shared_ptr<GCS::Circle> aCirc =
817 std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
818 aNewConstr = GCSConstraintPtr(
819 new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
823 return ConstraintWrapperPtr();
826 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
827 theConstraint, aNewConstr, theType));
828 aResult->setGroup(theGroupID);
829 std::list<EntityWrapperPtr> aSubs(1, thePoint);
830 aSubs.push_back(theEntity);
831 aResult->setEntities(aSubs);
835 // calculate length of the line
836 static inline double lineLength(const GCS::Line& theLine)
838 double aDir[2] = {*(theLine.p2.x) - *(theLine.p1.x), *(theLine.p2.y) - *(theLine.p1.y)};
839 return sqrt(aDir[0] * aDir[0] + aDir[1] * aDir[1]);
842 // check the point is on the line
843 static inline bool isPointOnLine(const GCS::Point& thePoint, const GCS::Line& theLine)
845 double aDir[2] = {*(theLine.p2.x) - *(theLine.p1.x), *(theLine.p2.y) - *(theLine.p1.y)};
846 double aVec[2] = {*(thePoint.x) - *(theLine.p1.x), *(thePoint.y) - *(theLine.p1.y)};
847 double aCross = aVec[0] * aDir[1] - aVec[1] * aDir[0];
848 return fabs(aCross) < tolerance;
851 ConstraintWrapperPtr createConstraintMiddlePoint(
852 ConstraintPtr theConstraint,
853 const GroupID& theGroupID,
854 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
855 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
857 GCSPointPtr aPoint = thePoint->point();
858 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
860 return ConstraintWrapperPtr();
862 std::list<GCSConstraintPtr> aConstrList;
863 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPointOnLine(*aPoint, *aLine)));
864 double aDist = lineLength(*aLine);
865 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aDistance =
866 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(
867 createParameter(theGroupID, aDist * 0.5));
868 aConstrList.push_back(GCSConstraintPtr(
869 new GCS::ConstraintP2PDistance(*aPoint, aLine->p1, aDistance->parameter())));
870 aConstrList.push_back(GCSConstraintPtr(
871 new GCS::ConstraintP2PDistance(*aPoint, aLine->p2, aDistance->parameter())));
873 // Workaround to avoid conflicting constraints when the point is already placed on line
874 if (thePoint->group() != GID_UNKNOWN && isPointOnLine(*aPoint, *aLine)) {
875 std::shared_ptr<GeomDataAPI_Point2D> aCoord =
876 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(thePoint->baseAttribute());
878 *(aPoint->x) = (*(aLine->p1.x) + *(aLine->p2.x)) * 0.5;
879 *(aPoint->y) = (*(aLine->p1.y) + *(aLine->p2.y)) * 0.5;
880 aCoord->setValue(*(aPoint->x), *(aPoint->y));
884 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(new PlaneGCSSolver_ConstraintWrapper(
885 theConstraint, aConstrList, CONSTRAINT_MIDDLE_POINT));
886 aResult->setGroup(theGroupID);
887 std::list<EntityWrapperPtr> aSubs(1, thePoint);
888 aSubs.push_back(theEntity);
889 aResult->setEntities(aSubs);
890 aResult->setValueParameter(aDistance);
895 ConstraintWrapperPtr createConstraintDistancePointPoint(
896 ConstraintPtr theConstraint,
897 const GroupID& theGroupID,
898 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
899 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
900 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
902 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
903 *(thePoint1->point()), *(thePoint2->point()), theValue->parameter()));
905 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
906 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
907 aResult->setGroup(theGroupID);
908 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
909 aSubs.push_back(thePoint2);
910 aResult->setEntities(aSubs);
911 aResult->setValueParameter(theValue);
915 ConstraintWrapperPtr createConstraintDistancePointLine(
916 ConstraintPtr theConstraint,
917 const GroupID& theGroupID,
918 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
919 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
920 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
922 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
923 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
924 *(thePoint->point()), *(aLine), theValue->parameter()));
926 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
927 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
928 aResult->setGroup(theGroupID);
929 std::list<EntityWrapperPtr> aSubs(1, thePoint);
930 aSubs.push_back(theEntity);
931 aResult->setEntities(aSubs);
932 aResult->setValueParameter(theValue);
936 ConstraintWrapperPtr createConstraintRadius(
937 ConstraintPtr theConstraint,
938 const GroupID& theGroupID,
939 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
940 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
942 std::shared_ptr<GCS::Circle> aCircle =
943 std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
944 GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->parameter()));
946 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
947 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_RADIUS));
948 aResult->setGroup(theGroupID);
949 std::list<EntityWrapperPtr> aSubs(1, theEntity);
950 aResult->setEntities(aSubs);
951 aResult->setValueParameter(theValue);
955 ConstraintWrapperPtr createConstraintAngle(
956 ConstraintPtr theConstraint,
957 const GroupID& theGroupID,
958 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
959 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
960 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
962 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
963 bool isLine1Rev = theConstraint->boolean(
964 SketchPlugin_ConstraintAngle::ANGLE_REVERSED_FIRST_LINE_ID())->value();
965 GCS::Point aLine1Pt1 = isLine1Rev ? aLine1->p2 : aLine1->p1;
966 GCS::Point aLine1Pt2 = isLine1Rev ? aLine1->p1 : aLine1->p2;
968 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
969 bool isLine2Rev = theConstraint->boolean(
970 SketchPlugin_ConstraintAngle::ANGLE_REVERSED_SECOND_LINE_ID())->value();
971 GCS::Point aLine2Pt1 = isLine2Rev ? aLine2->p2 : aLine2->p1;
972 GCS::Point aLine2Pt2 = isLine2Rev ? aLine2->p1 : aLine2->p2;
974 GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
975 aLine1Pt1, aLine1Pt2, aLine2Pt1, aLine2Pt2, theValue->parameter()));
977 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
978 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_ANGLE));
979 aResult->setGroup(theGroupID);
980 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
981 aSubs.push_back(theEntity2);
982 aResult->setEntities(aSubs);
983 aResult->setValueParameter(theValue);
987 ConstraintWrapperPtr createConstraintHorizVert(
988 ConstraintPtr theConstraint,
989 const GroupID& theGroupID,
990 const SketchSolver_ConstraintType& theType,
991 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
993 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
994 GCSConstraintPtr aNewConstr;
995 if (theType == CONSTRAINT_HORIZONTAL)
996 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.y, aLine->p2.y));
998 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
1000 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
1001 theConstraint, aNewConstr, theType));
1002 aResult->setGroup(theGroupID);
1003 std::list<EntityWrapperPtr> aSubs(1, theEntity);
1004 aResult->setEntities(aSubs);
1008 ConstraintWrapperPtr createConstraintCollinear(
1009 ConstraintPtr theConstraint,
1010 const GroupID& theGroupID,
1011 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1012 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
1014 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
1015 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1017 // create two point-on-line constraints
1018 std::list<GCSConstraintPtr> aConstrList;
1019 aConstrList.push_back( GCSConstraintPtr(new GCS::ConstraintPointOnLine(aLine2->p1, *aLine1)) );
1020 aConstrList.push_back( GCSConstraintPtr(new GCS::ConstraintPointOnLine(aLine2->p2, *aLine1)) );
1022 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
1023 theConstraint, aConstrList, CONSTRAINT_COLLINEAR));
1024 aResult->setGroup(theGroupID);
1025 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1026 aSubs.push_back(theEntity2);
1027 aResult->setEntities(aSubs);
1031 ConstraintWrapperPtr createConstraintParallel(
1032 ConstraintPtr theConstraint,
1033 const GroupID& theGroupID,
1034 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1035 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
1037 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
1038 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1039 GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
1041 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1042 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PARALLEL));
1043 aResult->setGroup(theGroupID);
1044 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1045 aSubs.push_back(theEntity2);
1046 aResult->setEntities(aSubs);
1050 ConstraintWrapperPtr createConstraintPerpendicular(
1051 ConstraintPtr theConstraint,
1052 const GroupID& theGroupID,
1053 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1054 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
1056 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
1057 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1058 GCSConstraintPtr aNewConstr(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
1060 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1061 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PERPENDICULAR));
1062 aResult->setGroup(theGroupID);
1063 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1064 aSubs.push_back(theEntity2);
1065 aResult->setEntities(aSubs);
1069 ConstraintWrapperPtr createConstraintEqual(
1070 ConstraintPtr theConstraint,
1071 const GroupID& theGroupID,
1072 const SketchSolver_ConstraintType& theType,
1073 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1074 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
1075 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed)
1077 if (theType == CONSTRAINT_EQUAL_LINE_ARC)
1078 return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
1080 std::list<GCSConstraintPtr> aConstrList;
1081 if (theType == CONSTRAINT_EQUAL_LINES) {
1082 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
1083 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1085 aConstrList.push_back(GCSConstraintPtr(
1086 new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->parameter())));
1087 aConstrList.push_back(GCSConstraintPtr(
1088 new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->parameter())));
1089 // update value of intermediate parameter
1090 double x = *aLine1->p1.x - *aLine1->p2.x;
1091 double y = *aLine1->p1.y - *aLine1->p2.y;
1092 double aLen = sqrt(x*x + y*y);
1093 theIntermed->setValue(aLen);
1095 std::shared_ptr<GCS::Circle> aCirc1 =
1096 std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1097 std::shared_ptr<GCS::Circle> aCirc2 =
1098 std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
1100 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
1103 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1104 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, theType));
1105 aResult->setGroup(theGroupID);
1106 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1107 aSubs.push_back(theEntity2);
1108 aResult->setEntities(aSubs);
1110 aResult->setValueParameter(theIntermed);
1114 ConstraintWrapperPtr createConstraintTangent(
1115 ConstraintPtr theConstraint,
1116 const GroupID& theGroupID,
1117 const SketchSolver_ConstraintType& theType,
1118 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1119 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
1121 GCSConstraintPtr aNewConstr;
1122 if (theType == CONSTRAINT_TANGENT_ARC_LINE || theType == CONSTRAINT_TANGENT_CIRCLE_LINE) {
1123 std::shared_ptr<GCS::Circle> aCirc =
1124 std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1125 std::shared_ptr<GCS::Line> aLine =
1126 std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1129 GCSConstraintPtr(new GCS::ConstraintP2LDistance(aCirc->center, *aLine, aCirc->rad));
1131 std::shared_ptr<GCS::Circle> aCirc1 =
1132 std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1133 std::shared_ptr<GCS::Circle> aCirc2 =
1134 std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
1136 double aDX = *(aCirc1->center.x) - *(aCirc2->center.x);
1137 double aDY = *(aCirc1->center.y) - *(aCirc2->center.y);
1138 double aDist = sqrt(aDX * aDX + aDY * aDY);
1139 aNewConstr = GCSConstraintPtr(new GCS::ConstraintTangentCircumf(aCirc1->center, aCirc2->center,
1140 aCirc1->rad, aCirc2->rad, (aDist < *(aCirc1->rad) || aDist < *(aCirc2->rad))));
1143 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1144 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, theType));
1145 aResult->setGroup(theGroupID);
1146 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1147 aSubs.push_back(theEntity2);
1148 aResult->setEntities(aSubs);
1156 void makeMirrorPoints(EntityWrapperPtr theOriginal,
1157 EntityWrapperPtr theMirrored,
1158 EntityWrapperPtr theMirrorLine)
1160 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1162 std::shared_ptr<GeomAPI_Lin2d> aMirrorLine = aBuilder->line(theMirrorLine);
1163 std::shared_ptr<GeomAPI_Dir2d> aMLDir = aMirrorLine->direction();
1164 // orthogonal direction
1165 aMLDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aMLDir->y(), -aMLDir->x()));
1167 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(theOriginal);
1168 std::shared_ptr<GeomAPI_XY> aVec = aPoint->xy()->decreased(aMirrorLine->location()->xy());
1169 double aDist = aVec->dot(aMLDir->xy());
1170 aVec = aPoint->xy()->added(aMLDir->xy()->multiplied(-2.0 * aDist));
1171 double aCoord[2] = {aVec->x(), aVec->y()};
1172 std::list<ParameterWrapperPtr>::const_iterator aMIt = theMirrored->parameters().begin();
1173 for (int i = 0; aMIt != theMirrored->parameters().end(); ++aMIt, ++i)
1174 (*aMIt)->setValue(aCoord[i]);
1176 // update corresponding attribute
1177 AttributePtr anAttr =
1178 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theMirrored)->baseAttribute();
1180 std::shared_ptr<GeomDataAPI_Point2D> aMirroredPnt =
1181 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
1182 aMirroredPnt->setValue(aCoord[0], aCoord[1]);
1186 void adjustPtLineDistance(ConstraintWrapperPtr theConstraint)
1188 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1190 std::shared_ptr<GeomAPI_Pnt2d> aPoint;
1191 std::shared_ptr<GeomAPI_Lin2d> aLine;
1192 std::list<EntityWrapperPtr> aSubs = theConstraint->entities();
1193 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
1194 for (; aSIt != aSubs.end(); ++aSIt) {
1195 if ((*aSIt)->type() == ENTITY_POINT)
1196 aPoint = aBuilder->point(*aSIt);
1197 else if ((*aSIt)->type() == ENTITY_LINE)
1198 aLine = aBuilder->line(*aSIt);
1201 std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
1202 std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
1203 if (aPtLineVec->cross(aLineVec) * theConstraint->value() < 0.0)
1204 theConstraint->setValue(theConstraint->value() * (-1.0));
1207 void adjustMirror(ConstraintWrapperPtr theConstraint)
1209 std::vector<EntityWrapperPtr> aPoints;
1210 EntityWrapperPtr aMirrorLine;
1212 const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
1213 std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
1214 for (; anIt != aSubs.end(); ++anIt) {
1215 if ((*anIt)->type() == ENTITY_POINT)
1216 aPoints.push_back(*anIt);
1217 else if ((*anIt)->type() == ENTITY_LINE)
1218 aMirrorLine = *anIt;
1221 if (aPoints.size() == 2)
1222 makeMirrorPoints(aPoints[0], aPoints[1], aMirrorLine);
1224 // update scales of constraints
1225 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aGCSConstraint =
1226 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
1227 std::list<GCSConstraintPtr>::const_iterator aCIt = aGCSConstraint->constraints().begin();
1228 for (; aCIt != aGCSConstraint->constraints().end(); ++aCIt)
1232 bool PlaneGCSSolver_Builder::isArcArcTangencyInternal(
1233 EntityWrapperPtr theArc1, EntityWrapperPtr theArc2) const
1235 std::shared_ptr<GCS::Circle> aCirc1 = std::dynamic_pointer_cast<GCS::Circle>(
1236 GCS_ENTITY_WRAPPER(theArc1)->entity());
1237 std::shared_ptr<GCS::Circle> aCirc2 = std::dynamic_pointer_cast<GCS::Circle>(
1238 GCS_ENTITY_WRAPPER(theArc2)->entity());
1240 if (!aCirc1 || !aCirc2)
1243 double aDX = *(aCirc1->center.x) - *(aCirc2->center.x);
1244 double aDY = *(aCirc1->center.y) - *(aCirc2->center.y);
1245 double aDist = sqrt(aDX * aDX + aDY * aDY);
1247 return (aDist < *(aCirc1->rad) || aDist < *(aCirc2->rad));