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 Set flags for angle constraint
146 static void adjustAngle(ConstraintWrapperPtr theConstraint);
147 /// \brief Update mirror points
148 static void adjustMirror(ConstraintWrapperPtr theConstraint);
149 /// \brief Update a sign of the point-line distance constraint
150 static void adjustPtLineDistance(ConstraintWrapperPtr theConstraint);
152 /// \brief Transform points to be symmetric regarding to the mirror line
153 static void makeMirrorPoints(EntityWrapperPtr theOriginal,
154 EntityWrapperPtr theMirrored,
155 EntityWrapperPtr theMirrorLine);
159 // Initialization of constraint builder self pointer
160 BuilderPtr PlaneGCSSolver_Builder::mySelf = PlaneGCSSolver_Builder::getInstance();
162 BuilderPtr PlaneGCSSolver_Builder::getInstance()
165 mySelf = BuilderPtr(new PlaneGCSSolver_Builder);
166 SketchSolver_Manager::instance()->setBuilder(mySelf);
171 StoragePtr PlaneGCSSolver_Builder::createStorage(const GroupID& theGroup) const
173 return StoragePtr(new PlaneGCSSolver_Storage(theGroup));
176 SolverPtr PlaneGCSSolver_Builder::createSolver() const
178 return SolverPtr(new PlaneGCSSolver_Solver);
182 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
183 ConstraintPtr theConstraint,
184 const GroupID& theGroupID,
185 const EntityID& theSketchID,
186 const SketchSolver_ConstraintType& theType,
187 const double& theValue,
188 const EntityWrapperPtr& thePoint1,
189 const EntityWrapperPtr& thePoint2,
190 const EntityWrapperPtr& theEntity1,
191 const EntityWrapperPtr& theEntity2) const
193 ConstraintWrapperPtr aResult;
194 ParameterWrapperPtr anIntermediate;
196 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(thePoint1);
197 if (!aPoint1 && thePoint1 && thePoint1->type() == ENTITY_POINT)
198 aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint1)->subEntities().front() );
199 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(thePoint2);
200 if (!aPoint2 && thePoint2 && thePoint2->type() == ENTITY_POINT)
201 aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint2)->subEntities().front() );
204 case CONSTRAINT_PT_PT_COINCIDENT:
205 aResult = createConstraintCoincidence(theConstraint, theGroupID, aPoint1, aPoint2);
207 case CONSTRAINT_PT_ON_LINE:
208 case CONSTRAINT_PT_ON_CIRCLE:
209 aResult = createConstraintPointOnEntity(theConstraint, theGroupID, theType,
210 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
212 case CONSTRAINT_MIDDLE_POINT:
213 aResult = createConstraintMiddlePoint(theConstraint, theGroupID,
214 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
216 case CONSTRAINT_PT_PT_DISTANCE:
217 aResult = createConstraintDistancePointPoint(theConstraint, theGroupID,
218 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
221 case CONSTRAINT_PT_LINE_DISTANCE:
222 aResult = createConstraintDistancePointLine(theConstraint, theGroupID,
223 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
224 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
226 case CONSTRAINT_RADIUS:
227 aResult = createConstraintRadius(theConstraint, theGroupID,
228 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
229 GCS_ENTITY_WRAPPER(theEntity1));
231 case CONSTRAINT_ANGLE:
232 aResult = createConstraintAngle(theConstraint, theGroupID,
233 GCS_PARAMETER_WRAPPER(createParamAngle(GID_OUTOFGROUP, theValue)),
234 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
236 case CONSTRAINT_FIXED:
238 case CONSTRAINT_HORIZONTAL:
239 case CONSTRAINT_VERTICAL:
240 aResult = createConstraintHorizVert(theConstraint, theGroupID, theType,
241 GCS_ENTITY_WRAPPER(theEntity1));
243 case CONSTRAINT_PARALLEL:
244 aResult = createConstraintParallel(theConstraint, theGroupID,
245 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
247 case CONSTRAINT_PERPENDICULAR:
248 aResult = createConstraintPerpendicular(theConstraint, theGroupID,
249 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
251 case CONSTRAINT_EQUAL_LINES:
252 anIntermediate = createParameter(theGroupID);
253 case CONSTRAINT_EQUAL_LINE_ARC:
254 case CONSTRAINT_EQUAL_RADIUS:
255 aResult = createConstraintEqual(theConstraint, theGroupID, theType,
256 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2),
257 GCS_PARAMETER_WRAPPER(anIntermediate));
259 case CONSTRAINT_TANGENT_ARC_LINE:
260 case CONSTRAINT_TANGENT_CIRCLE_LINE:
261 case CONSTRAINT_TANGENT_ARC_ARC:
262 aResult = createConstraintTangent(theConstraint, theGroupID, theType,
263 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
265 case CONSTRAINT_COLLINEAR:
266 aResult = createConstraintCollinear(theConstraint, theGroupID,
267 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
269 case CONSTRAINT_MULTI_TRANSLATION:
270 case CONSTRAINT_MULTI_ROTATION:
272 case CONSTRAINT_SYMMETRIC:
273 return createMirror(theConstraint, theGroupID, theSketchID,
274 thePoint1, thePoint2, theEntity1);
280 return std::list<ConstraintWrapperPtr>();
281 adjustConstraint(aResult);
282 return std::list<ConstraintWrapperPtr>(1, aResult);
285 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
286 ConstraintPtr theConstraint,
287 const GroupID& theGroupID,
288 const EntityID& theSketchID,
289 const SketchSolver_ConstraintType& theType,
290 const double& theValue,
291 const bool theFullValue,
292 const EntityWrapperPtr& thePoint1,
293 const EntityWrapperPtr& thePoint2,
294 const std::list<EntityWrapperPtr>& theTrsfEnt) const
296 ParameterWrapperPtr anAngleParam;
297 if (theType == CONSTRAINT_MULTI_ROTATION)
298 anAngleParam = createParamAngle(theGroupID, theValue);
299 else if (theType != CONSTRAINT_MULTI_TRANSLATION)
300 return std::list<ConstraintWrapperPtr>();
302 std::list<EntityWrapperPtr> aConstrAttrList = theTrsfEnt;
304 aConstrAttrList.push_front(thePoint2);
305 aConstrAttrList.push_front(thePoint1);
307 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
308 new PlaneGCSSolver_ConstraintWrapper(theConstraint, std::list<GCSConstraintPtr>(), theType));
309 aResult->setGroup(theGroupID);
310 aResult->setEntities(aConstrAttrList);
312 aResult->setValueParameter(anAngleParam);
313 aResult->setIsFullValue(theFullValue);
314 return std::list<ConstraintWrapperPtr>(1, aResult);
318 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createMirror(
319 ConstraintPtr theConstraint,
320 const GroupID& theGroupID,
321 const EntityID& theSketchID,
322 const EntityWrapperPtr& theEntity1,
323 const EntityWrapperPtr& theEntity2,
324 const EntityWrapperPtr& theMirrorLine) const
326 std::list<ConstraintWrapperPtr> aResult;
327 std::list<EntityWrapperPtr> aConstrAttrList;
328 if (theEntity1->type() == ENTITY_POINT) {
329 if (theEntity2->group() == theGroupID) // theEntity2 is not fixed
330 makeMirrorPoints(theEntity1, theEntity2, theMirrorLine);
332 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(theEntity1);
333 if (!aPoint1 && theEntity1->type() == ENTITY_POINT)
334 aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity1)->subEntities().front() );
335 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(theEntity2);
336 if (!aPoint2 && theEntity2->type() == ENTITY_POINT)
337 aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity2)->subEntities().front() );
339 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aMirrorLine =
340 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMirrorLine);
341 std::shared_ptr<GCS::Line> aLine =
342 std::dynamic_pointer_cast<GCS::Line>(aMirrorLine->entity());
344 std::list<GCSConstraintPtr> aConstrList;
345 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
346 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
347 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintMidpointOnLine(
348 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
350 ConstraintWrapperPtr aSubResult(new PlaneGCSSolver_ConstraintWrapper(
351 theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
352 aSubResult->setGroup(theGroupID);
353 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
354 aSubs.push_back(theEntity2);
355 aSubs.push_back(theMirrorLine);
356 aSubResult->setEntities(aSubs);
357 aResult.push_back(aSubResult);
359 else if (theEntity1->type() == ENTITY_LINE) {
360 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
361 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
362 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
363 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
364 for (; anIt1 != aPoints1.end() && anIt2 != aPoints2.end(); ++anIt1, ++anIt2) {
365 std::list<ConstraintWrapperPtr> aMrrList =
366 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
367 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
370 else if (theEntity1->type() == ENTITY_CIRCLE) {
371 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
372 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
373 for (; anIt1 != aPoints1.end(); ++anIt1)
374 if ((*anIt1)->type() == ENTITY_POINT)
376 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
377 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
378 for (; anIt2 != aPoints2.end(); ++anIt2)
379 if ((*anIt2)->type() == ENTITY_POINT)
382 std::list<ConstraintWrapperPtr> aMrrList =
383 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
384 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
386 // Additional constraint for equal radii
387 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
388 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
389 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
391 else if (theEntity1->type() == ENTITY_ARC) {
392 // Do not allow mirrored arc recalculate its position until coordinated of all points recalculated
393 FeaturePtr aMirrArc = theEntity2->baseFeature();
394 aMirrArc->data()->blockSendAttributeUpdated(true);
396 // Make mirror for center and start point of original arc
397 std::list<ConstraintWrapperPtr> aMrrList;
398 std::list<EntityWrapperPtr>::const_iterator anIt1 = theEntity1->subEntities().begin();
399 std::list<EntityWrapperPtr>::const_iterator anIt2 = theEntity2->subEntities().begin();
400 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
401 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
405 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
406 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
408 // make symmetric last point of original arc and first point of 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(false);
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_ANGLE)
463 adjustAngle(theConstraint);
464 else if (aType == CONSTRAINT_PT_LINE_DISTANCE)
465 adjustPtLineDistance(theConstraint);
466 else if (aType == CONSTRAINT_SYMMETRIC)
467 adjustMirror(theConstraint);
470 EntityWrapperPtr PlaneGCSSolver_Builder::createFeature(
471 FeaturePtr theFeature,
472 const std::list<EntityWrapperPtr>& theAttributes,
473 const GroupID& theGroupID,
474 const EntityID& /*theSketchID*/) const
476 static EntityWrapperPtr aDummy;
477 if (!theFeature->data()->isValid())
481 CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
483 return createSketchEntity(aSketch, theGroupID);
485 // SketchPlugin features
486 std::shared_ptr<SketchPlugin_Feature> aFeature =
487 std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
491 // Verify the feature by its kind
492 const std::string& aFeatureKind = aFeature->getKind();
494 if (aFeatureKind == SketchPlugin_Line::ID())
495 return createLine(theFeature, theAttributes, theGroupID);
497 else if (aFeatureKind == SketchPlugin_Circle::ID())
498 return createCircle(theFeature, theAttributes, theGroupID);
500 else if (aFeatureKind == SketchPlugin_Arc::ID())
501 return createArc(theFeature, theAttributes, theGroupID);
502 // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
503 else if (aFeatureKind == SketchPlugin_Point::ID() ||
504 aFeatureKind == SketchPlugin_IntersectionPoint::ID()) {
505 EntityWrapperPtr aSub;
506 if (theAttributes.size() == 1)
507 aSub = theAttributes.front();
509 AttributePtr aPoint = theFeature->attribute(SketchPlugin_Point::COORD_ID());
510 if (aPoint->isInitialized())
511 aSub = createAttribute(aPoint, theGroupID);
516 GCSPointPtr aSubEnt =
517 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aSub)->point();
518 EntityWrapperPtr aNewEntity(new PlaneGCSSolver_EntityWrapper(theFeature));
519 aNewEntity->setSubEntities(std::list<EntityWrapperPtr>(1, aSub));
527 EntityWrapperPtr PlaneGCSSolver_Builder::createAttribute(
528 AttributePtr theAttribute,
529 const GroupID& theGroupID,
530 const EntityID& theSketchID) const
532 AttributePtr anAttribute = theAttribute;
533 AttributeRefAttrPtr aRefAttr =
534 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
536 if (aRefAttr->isObject()) {
537 // do not create features here
538 return EntityWrapperPtr();
540 anAttribute = aRefAttr->attr();
543 std::list<ParameterWrapperPtr> aParameters;
544 EntityWrapperPtr aResult;
547 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
548 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
550 aParameters.push_back(::createParameter(theGroupID, aPoint2D->x(), !aPoint2D->textX().empty()));
551 aParameters.push_back(::createParameter(theGroupID, aPoint2D->y(), !aPoint2D->textY().empty()));
552 GCSPointPtr aGCSPoint(new GCS::Point);
553 aGCSPoint->x = std::dynamic_pointer_cast<
554 PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
555 aGCSPoint->y = std::dynamic_pointer_cast<
556 PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
557 // Create entity (parameters are not filled)
558 aResult = EntityWrapperPtr(new PlaneGCSSolver_PointWrapper(theAttribute, aGCSPoint));
560 // Scalar value (used for the distance entities)
561 AttributeDoublePtr aScalar =
562 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
564 return createScalar(theGroupID, aScalar);
568 // unknown attribute type
569 return EntityWrapperPtr();
572 aResult->setGroup(theGroupID);
573 aResult->setParameters(aParameters);
577 ParameterWrapperPtr PlaneGCSSolver_Builder::createParameter(
578 const GroupID& theGroupID, double theValue) const
580 return ::createParameter(theGroupID, theValue);
584 EntityWrapperPtr PlaneGCSSolver_Builder::createSketchEntity(
585 CompositeFeaturePtr theSketch,
586 const GroupID& theGroupID) const
588 DataPtr aSketchData = theSketch->data();
589 if (!aSketchData || !aSketchData->isValid())
590 return EntityWrapperPtr(); // the sketch is incorrect
592 // Create dummy wrapper representing workplane
593 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aSketchEnt(
594 new PlaneGCSSolver_EntityWrapper(FeaturePtr(theSketch)));
595 aSketchEnt->setGroup(theGroupID);
596 aSketchEnt->setId(EID_SKETCH);
604 // ================ Auxiliary functions ==========================
605 ParameterWrapperPtr createParameter(
606 const GroupID& theGroup, const double theValue, const bool theExpr)
608 double* aParam = new double(theValue);
609 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_ParameterWrapper(aParam));
610 aWrapper->setGroup(theGroup);
611 aWrapper->setIsParametric(theExpr);
615 ParameterWrapperPtr createParamAngle(const GroupID& theGroup, const double& theValue)
617 double* aParam = new double(theValue);
618 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_AngleWrapper(aParam));
619 aWrapper->setGroup(theGroup);
623 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> createScalar(
624 const GroupID& theGroupID,
625 AttributeDoublePtr theDoubleAttr)
627 ParameterWrapperPtr aParam = createParameter(theGroupID, theDoubleAttr ? theDoubleAttr->value() : 0.0);
628 return std::shared_ptr<PlaneGCSSolver_ScalarWrapper>(
629 new PlaneGCSSolver_ScalarWrapper(theDoubleAttr, aParam));
632 EntityWrapperPtr createLine(FeaturePtr theFeature,
633 const std::list<EntityWrapperPtr>& theAttributes,
634 const GroupID& theGroupID)
636 EntityWrapperPtr aNewEntity;
637 std::list<EntityWrapperPtr> aSubs;
639 AttributePtr aStart = theFeature->attribute(SketchPlugin_Line::START_ID());
640 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Line::END_ID());
641 if (!aStart->isInitialized() || !aEnd->isInitialized())
644 std::shared_ptr<PlaneGCSSolver_PointWrapper> aStartEnt, aEndEnt;
645 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
646 for (; anIt != theAttributes.end(); ++anIt) {
647 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
648 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
651 if (aWrapper->isBase(aStart))
652 aStartEnt = aWrapper;
653 else if (aWrapper->isBase(aEnd))
656 if (!aStartEnt || !aEndEnt)
659 aSubs.push_back(aStartEnt);
660 aSubs.push_back(aEndEnt);
662 std::shared_ptr<GCS::Line> aLine(new GCS::Line);
663 aLine->p1 = *(aStartEnt->point());
664 aLine->p2 = *(aEndEnt->point());
666 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aLine));
667 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
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 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
705 aNewEntity->setSubEntities(aSubs);
709 EntityWrapperPtr createArc(FeaturePtr theFeature,
710 const std::list<EntityWrapperPtr>& theAttributes,
711 const GroupID& theGroupID)
713 EntityWrapperPtr aNewEntity;
714 std::list<EntityWrapperPtr> aSubs;
716 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Arc::CENTER_ID());
717 AttributePtr aStart = theFeature->attribute(SketchPlugin_Arc::START_ID());
718 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Arc::END_ID());
719 if (!aCenter->isInitialized() || !aStart->isInitialized() || !aEnd->isInitialized())
722 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt, aStartEnt, aEndEnt;
723 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
724 for (; anIt != theAttributes.end(); ++anIt) {
725 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
726 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
729 if (aWrapper->isBase(aCenter))
730 aCenterEnt = aWrapper;
731 else if (aWrapper->isBase(aStart))
732 aStartEnt = aWrapper;
733 else if (aWrapper->isBase(aEnd))
736 if (!aCenterEnt || !aStartEnt || !aEndEnt)
739 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aStartAng, aEndAng, aRadius;
740 aStartAng = createScalar(theGroupID);
741 aEndAng = createScalar(theGroupID);
742 aRadius = createScalar(theGroupID);
744 aSubs.push_back(aCenterEnt);
745 aSubs.push_back(aStartEnt);
746 aSubs.push_back(aEndEnt);
747 aSubs.push_back(aStartAng);
748 aSubs.push_back(aEndAng);
749 aSubs.push_back(aRadius);
751 std::shared_ptr<GCS::Arc> anArc(new GCS::Arc);
752 anArc->center = *(aCenterEnt->point());
753 anArc->start = *(aStartEnt->point());
754 anArc->end = *(aEndEnt->point());
755 anArc->startAngle = aStartAng->scalar();
756 anArc->endAngle = aEndAng->scalar();
757 anArc->rad = aRadius->scalar();
759 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, anArc));
760 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
761 aNewEntity->setSubEntities(aSubs);
767 ConstraintWrapperPtr createConstraintCoincidence(
768 ConstraintPtr theConstraint,
769 const GroupID& theGroupID,
770 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
771 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
773 // Create equality constraint for corresponding attributes of the points
774 std::list<GCSConstraintPtr> aConstrList;
775 std::list<ParameterWrapperPtr>::const_iterator anIt1 = thePoint1->parameters().begin();
776 std::list<ParameterWrapperPtr>::const_iterator anIt2 = thePoint2->parameters().begin();
777 for (; anIt1 != thePoint1->parameters().end(); ++anIt1, ++anIt2) {
778 if (*anIt1 == *anIt2)
779 continue; // points use same parameters, no need additional constraints
780 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam1 =
781 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt1);
782 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam2 =
783 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt2);
784 aConstrList.push_back(
785 GCSConstraintPtr(new GCS::ConstraintEqual(aParam1->parameter(), aParam2->parameter())));
788 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
789 theConstraint, aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
790 aResult->setGroup(theGroupID);
791 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
792 aSubs.push_back(thePoint2);
793 aResult->setEntities(aSubs);
797 ConstraintWrapperPtr createConstraintPointOnEntity(
798 ConstraintPtr theConstraint,
799 const GroupID& theGroupID,
800 const SketchSolver_ConstraintType& theType,
801 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
802 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
804 GCSConstraintPtr aNewConstr;
806 switch (theEntity->type()) {
808 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
809 aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnLine(*(thePoint->point()), *aLine));
813 case ENTITY_CIRCLE: {
814 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
815 aNewConstr = GCSConstraintPtr(
816 new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
820 return ConstraintWrapperPtr();
823 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
824 theConstraint, aNewConstr, theType));
825 aResult->setGroup(theGroupID);
826 std::list<EntityWrapperPtr> aSubs(1, thePoint);
827 aSubs.push_back(theEntity);
828 aResult->setEntities(aSubs);
832 // calculate length of the line
833 static inline double lineLength(const GCS::Line& theLine)
835 double aDir[2] = {*(theLine.p2.x) - *(theLine.p1.x), *(theLine.p2.y) - *(theLine.p1.y)};
836 return sqrt(aDir[0] * aDir[0] + aDir[1] * aDir[1]);
839 // check the point is on the line
840 static inline bool isPointOnLine(const GCS::Point& thePoint, const GCS::Line& theLine)
842 double aDir[2] = {*(theLine.p2.x) - *(theLine.p1.x), *(theLine.p2.y) - *(theLine.p1.y)};
843 double aVec[2] = {*(thePoint.x) - *(theLine.p1.x), *(thePoint.y) - *(theLine.p1.y)};
844 double aCross = aVec[0] * aDir[1] - aVec[1] * aDir[0];
845 return fabs(aCross) < tolerance;
848 ConstraintWrapperPtr createConstraintMiddlePoint(
849 ConstraintPtr theConstraint,
850 const GroupID& theGroupID,
851 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
852 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
854 GCSPointPtr aPoint = thePoint->point();
855 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
857 return ConstraintWrapperPtr();
859 std::list<GCSConstraintPtr> aConstrList;
860 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPointOnLine(*aPoint, *aLine)));
861 double aDist = lineLength(*aLine);
862 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aDistance =
863 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(createParameter(theGroupID, aDist));
864 aConstrList.push_back(GCSConstraintPtr(
865 new GCS::ConstraintP2PDistance(*aPoint, aLine->p1, aDistance->parameter())));
866 aConstrList.push_back(GCSConstraintPtr(
867 new GCS::ConstraintP2PDistance(*aPoint, aLine->p2, aDistance->parameter())));
869 // Workaround to avoid conflicting constraints when the point is already placed on line
870 if (thePoint->group() != GID_UNKNOWN && isPointOnLine(*aPoint, *aLine)) {
871 std::shared_ptr<GeomDataAPI_Point2D> aCoord =
872 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(thePoint->baseAttribute());
874 *(aPoint->x) = (*(aLine->p1.x) + *(aLine->p2.x)) * 0.5;
875 *(aPoint->y) = (*(aLine->p1.y) + *(aLine->p2.y)) * 0.5;
876 aCoord->setValue(*(aPoint->x), *(aPoint->y));
880 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(new PlaneGCSSolver_ConstraintWrapper(
881 theConstraint, aConstrList, CONSTRAINT_MIDDLE_POINT));
882 aResult->setGroup(theGroupID);
883 std::list<EntityWrapperPtr> aSubs(1, thePoint);
884 aSubs.push_back(theEntity);
885 aResult->setEntities(aSubs);
886 aResult->setValueParameter(aDistance);
891 ConstraintWrapperPtr createConstraintDistancePointPoint(
892 ConstraintPtr theConstraint,
893 const GroupID& theGroupID,
894 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
895 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
896 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
898 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
899 *(thePoint1->point()), *(thePoint2->point()), theValue->parameter()));
901 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
902 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
903 aResult->setGroup(theGroupID);
904 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
905 aSubs.push_back(thePoint2);
906 aResult->setEntities(aSubs);
907 aResult->setValueParameter(theValue);
911 ConstraintWrapperPtr createConstraintDistancePointLine(
912 ConstraintPtr theConstraint,
913 const GroupID& theGroupID,
914 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
915 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
916 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
918 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
919 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
920 *(thePoint->point()), *(aLine), theValue->parameter()));
922 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
923 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
924 aResult->setGroup(theGroupID);
925 std::list<EntityWrapperPtr> aSubs(1, thePoint);
926 aSubs.push_back(theEntity);
927 aResult->setEntities(aSubs);
928 aResult->setValueParameter(theValue);
932 ConstraintWrapperPtr createConstraintRadius(
933 ConstraintPtr theConstraint,
934 const GroupID& theGroupID,
935 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
936 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
938 std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
939 GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->parameter()));
941 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
942 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_RADIUS));
943 aResult->setGroup(theGroupID);
944 std::list<EntityWrapperPtr> aSubs(1, theEntity);
945 aResult->setEntities(aSubs);
946 aResult->setValueParameter(theValue);
950 ConstraintWrapperPtr createConstraintAngle(
951 ConstraintPtr theConstraint,
952 const GroupID& theGroupID,
953 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
954 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
955 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
957 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
958 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
959 GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
960 *(aLine1), *(aLine2), theValue->parameter()));
962 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
963 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_ANGLE));
964 aResult->setGroup(theGroupID);
965 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
966 aSubs.push_back(theEntity2);
967 aResult->setEntities(aSubs);
968 aResult->setValueParameter(theValue);
972 ConstraintWrapperPtr createConstraintHorizVert(
973 ConstraintPtr theConstraint,
974 const GroupID& theGroupID,
975 const SketchSolver_ConstraintType& theType,
976 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
978 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
979 GCSConstraintPtr aNewConstr;
980 if (theType == CONSTRAINT_HORIZONTAL)
981 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.y, aLine->p2.y));
983 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
985 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
986 theConstraint, aNewConstr, theType));
987 aResult->setGroup(theGroupID);
988 std::list<EntityWrapperPtr> aSubs(1, theEntity);
989 aResult->setEntities(aSubs);
993 ConstraintWrapperPtr createConstraintCollinear(
994 ConstraintPtr theConstraint,
995 const GroupID& theGroupID,
996 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
997 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
999 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
1000 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1002 // create two point-on-line constraints
1003 std::list<GCSConstraintPtr> aConstrList;
1004 aConstrList.push_back( GCSConstraintPtr(new GCS::ConstraintPointOnLine(aLine2->p1, *aLine1)) );
1005 aConstrList.push_back( GCSConstraintPtr(new GCS::ConstraintPointOnLine(aLine2->p2, *aLine1)) );
1007 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
1008 theConstraint, aConstrList, CONSTRAINT_COLLINEAR));
1009 aResult->setGroup(theGroupID);
1010 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1011 aSubs.push_back(theEntity2);
1012 aResult->setEntities(aSubs);
1016 ConstraintWrapperPtr createConstraintParallel(
1017 ConstraintPtr theConstraint,
1018 const GroupID& theGroupID,
1019 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1020 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
1022 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
1023 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1024 GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
1026 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1027 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PARALLEL));
1028 aResult->setGroup(theGroupID);
1029 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1030 aSubs.push_back(theEntity2);
1031 aResult->setEntities(aSubs);
1035 ConstraintWrapperPtr createConstraintPerpendicular(
1036 ConstraintPtr theConstraint,
1037 const GroupID& theGroupID,
1038 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1039 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
1041 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
1042 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1043 GCSConstraintPtr aNewConstr(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
1045 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1046 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PERPENDICULAR));
1047 aResult->setGroup(theGroupID);
1048 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1049 aSubs.push_back(theEntity2);
1050 aResult->setEntities(aSubs);
1054 ConstraintWrapperPtr createConstraintEqual(
1055 ConstraintPtr theConstraint,
1056 const GroupID& theGroupID,
1057 const SketchSolver_ConstraintType& theType,
1058 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1059 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
1060 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed)
1062 if (theType == CONSTRAINT_EQUAL_LINE_ARC)
1063 return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
1065 std::list<GCSConstraintPtr> aConstrList;
1066 if (theType == CONSTRAINT_EQUAL_LINES) {
1067 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
1068 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1070 aConstrList.push_back(GCSConstraintPtr(
1071 new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->parameter())));
1072 aConstrList.push_back(GCSConstraintPtr(
1073 new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->parameter())));
1075 std::shared_ptr<GCS::Circle> aCirc1 =
1076 std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1077 std::shared_ptr<GCS::Circle> aCirc2 =
1078 std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
1080 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
1083 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1084 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, theType));
1085 aResult->setGroup(theGroupID);
1086 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1087 aSubs.push_back(theEntity2);
1088 aResult->setEntities(aSubs);
1090 aResult->setValueParameter(theIntermed);
1094 ConstraintWrapperPtr createConstraintTangent(
1095 ConstraintPtr theConstraint,
1096 const GroupID& theGroupID,
1097 const SketchSolver_ConstraintType& theType,
1098 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1099 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
1101 GCSConstraintPtr aNewConstr;
1102 if (theType == CONSTRAINT_TANGENT_ARC_LINE || theType == CONSTRAINT_TANGENT_CIRCLE_LINE) {
1103 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1104 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1106 aNewConstr = GCSConstraintPtr(new GCS::ConstraintP2LDistance(aCirc->center, *aLine, aCirc->rad));
1108 std::shared_ptr<GCS::Circle> aCirc1 = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1109 std::shared_ptr<GCS::Circle> aCirc2 = std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
1111 double aDX = *(aCirc1->center.x) - *(aCirc2->center.x);
1112 double aDY = *(aCirc1->center.y) - *(aCirc2->center.y);
1113 double aDist = sqrt(aDX * aDX + aDY * aDY);
1114 aNewConstr = GCSConstraintPtr(new GCS::ConstraintTangentCircumf(aCirc1->center, aCirc2->center,
1115 aCirc1->rad, aCirc2->rad, (aDist < *(aCirc1->rad) || aDist < *(aCirc2->rad))));
1118 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1119 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, theType));
1120 aResult->setGroup(theGroupID);
1121 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1122 aSubs.push_back(theEntity2);
1123 aResult->setEntities(aSubs);
1131 void adjustAngle(ConstraintWrapperPtr theConstraint)
1133 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1135 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
1136 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
1138 std::shared_ptr<GeomAPI_Pnt2d> aPoints[2][2]; // start and end points of lines
1139 const std::list<EntityWrapperPtr>& aConstrLines = aConstraint->entities();
1140 std::list<EntityWrapperPtr>::const_iterator aCLIt = aConstrLines.begin();
1141 for (int i = 0; aCLIt != aConstrLines.end(); ++i, ++aCLIt) {
1142 const std::list<EntityWrapperPtr>& aLinePoints = (*aCLIt)->subEntities();
1143 std::list<EntityWrapperPtr>::const_iterator aLPIt = aLinePoints.begin();
1144 for (int j = 0; aLPIt != aLinePoints.end(); ++j, ++aLPIt)
1145 aPoints[i][j] = aBuilder->point(*aLPIt);
1148 std::shared_ptr<GeomAPI_Lin2d> aLine[2] = {
1149 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[0][0], aPoints[0][1])),
1150 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[1][0], aPoints[1][1]))
1152 std::shared_ptr<GeomAPI_Pnt2d> anIntersection = aLine[0]->intersect(aLine[1]);
1153 if (!anIntersection)
1156 for (int i = 0; i < 2; i++) {
1157 for (int j = 0; j < 2; j++) {
1158 aDist[i][j] = anIntersection->distance(aPoints[i][j]);
1159 if (fabs(aDist[i][j]) <= tolerance)
1162 if (aDist[i][0] > tolerance && aDist[i][1] > tolerance &&
1163 aDist[i][0] + aDist[i][1] < aPoints[i][0]->distance(aPoints[i][1]) + 2.0 * tolerance) {
1164 // the intersection point is an inner point of the line,
1165 // we change the sign of distance till start point to calculate correct coordinates
1167 aDist[i][0] *= -1.0;
1170 std::shared_ptr<GeomAPI_Dir2d> aDir[2];
1171 for (int i = 0; i < 2; i++) {
1172 if (aDist[i][1] > fabs(aDist[i][0]))
1173 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1174 aPoints[i][1]->xy()->decreased(anIntersection->xy())));
1176 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1177 aPoints[i][0]->xy()->decreased(anIntersection->xy())));
1178 // main direction is opposite => change signs
1179 if (aDist[i][0] < 0.0) {
1180 aDist[i][0] *= -1.0;
1181 aDist[i][1] *= -1.0;
1186 double anAngle = aLine[0]->direction()->angle(aLine[1]->direction()) / PI * 180;
1187 if (anAngle * aConstraint->value() < 0.0)
1188 aConstraint->setValue(-aConstraint->value());
1189 if ((90.0 - fabs(anAngle)) * (fabs(aConstraint->value()) - 90.0) > 0.0) {
1190 if (aConstraint->value() < 0.0)
1191 aConstraint->setValue(-180.0 - aConstraint->value());
1193 aConstraint->setValue(180.0 - aConstraint->value());
1197 void makeMirrorPoints(EntityWrapperPtr theOriginal,
1198 EntityWrapperPtr theMirrored,
1199 EntityWrapperPtr theMirrorLine)
1201 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1203 std::shared_ptr<GeomAPI_Lin2d> aMirrorLine = aBuilder->line(theMirrorLine);
1204 std::shared_ptr<GeomAPI_Dir2d> aMLDir = aMirrorLine->direction();
1205 // orthogonal direction
1206 aMLDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aMLDir->y(), -aMLDir->x()));
1208 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(theOriginal);
1209 std::shared_ptr<GeomAPI_XY> aVec = aPoint->xy()->decreased(aMirrorLine->location()->xy());
1210 double aDist = aVec->dot(aMLDir->xy());
1211 aVec = aPoint->xy()->added(aMLDir->xy()->multiplied(-2.0 * aDist));
1212 double aCoord[2] = {aVec->x(), aVec->y()};
1213 std::list<ParameterWrapperPtr>::const_iterator aMIt = theMirrored->parameters().begin();
1214 for (int i = 0; aMIt != theMirrored->parameters().end(); ++aMIt, ++i)
1215 (*aMIt)->setValue(aCoord[i]);
1217 // update corresponding attribute
1218 AttributePtr anAttr = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theMirrored)->baseAttribute();
1220 std::shared_ptr<GeomDataAPI_Point2D> aMirroredPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
1221 aMirroredPnt->setValue(aCoord[0], aCoord[1]);
1225 void adjustPtLineDistance(ConstraintWrapperPtr theConstraint)
1227 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1229 std::shared_ptr<GeomAPI_Pnt2d> aPoint;
1230 std::shared_ptr<GeomAPI_Lin2d> aLine;
1231 std::list<EntityWrapperPtr> aSubs = theConstraint->entities();
1232 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
1233 for (; aSIt != aSubs.end(); ++aSIt) {
1234 if ((*aSIt)->type() == ENTITY_POINT)
1235 aPoint = aBuilder->point(*aSIt);
1236 else if ((*aSIt)->type() == ENTITY_LINE)
1237 aLine = aBuilder->line(*aSIt);
1240 std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
1241 std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
1242 if (aPtLineVec->cross(aLineVec) * theConstraint->value() < 0.0)
1243 theConstraint->setValue(theConstraint->value() * (-1.0));
1246 void adjustMirror(ConstraintWrapperPtr theConstraint)
1248 std::vector<EntityWrapperPtr> aPoints;
1249 EntityWrapperPtr aMirrorLine;
1251 const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
1252 std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
1253 for (; anIt != aSubs.end(); ++anIt) {
1254 if ((*anIt)->type() == ENTITY_POINT)
1255 aPoints.push_back(*anIt);
1256 else if ((*anIt)->type() == ENTITY_LINE)
1257 aMirrorLine = *anIt;
1260 makeMirrorPoints(aPoints[0], aPoints[1], aMirrorLine);