1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: PlaneGCSSolver_Builder.cpp
4 // Created: 14 Dec 2015
5 // Author: Artem ZHIDKOV
7 #include <PlaneGCSSolver_Builder.h>
8 #include <PlaneGCSSolver_Solver.h>
9 #include <PlaneGCSSolver_Storage.h>
10 #include <PlaneGCSSolver_ParameterWrapper.h>
11 #include <PlaneGCSSolver_AngleWrapper.h>
12 #include <PlaneGCSSolver_EntityWrapper.h>
13 #include <PlaneGCSSolver_PointWrapper.h>
14 #include <PlaneGCSSolver_ScalarWrapper.h>
15 #include <PlaneGCSSolver_ConstraintWrapper.h>
17 #include <SketchSolver_Manager.h>
19 #include <GeomAPI_Dir2d.h>
20 #include <GeomAPI_Pnt2d.h>
21 #include <GeomAPI_XY.h>
22 #include <GeomDataAPI_Dir.h>
23 #include <GeomDataAPI_Point.h>
24 #include <GeomDataAPI_Point2D.h>
25 #include <ModelAPI_Attribute.h>
26 #include <ModelAPI_AttributeRefAttr.h>
28 #include <SketchPlugin_Arc.h>
29 #include <SketchPlugin_Circle.h>
30 #include <SketchPlugin_Line.h>
31 #include <SketchPlugin_Point.h>
32 #include <SketchPlugin_ConstraintAngle.h>
37 #define GCS_ENTITY_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(x)
38 #define GCS_POINT_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(x)
39 #define GCS_PARAMETER_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(x)
42 /// \brief Converts a value to SolveSpace parameter
43 /// \param theGroup [in] group to store parameter
44 /// \param theValue [in] value of parameter
45 /// \param theExpr [in] shows the parameter is given by expression
46 /// \return Created parameter's wrapper
47 static ParameterWrapperPtr createParameter(const GroupID& theGroup,
48 const double theValue = 0.0,
49 const bool theExpr = false);
51 static ParameterWrapperPtr createParamAngle(const GroupID& theGroup,
52 const double& theValue = 0.0);
54 static std::shared_ptr<PlaneGCSSolver_ScalarWrapper>
55 createScalar(const GroupID& theGroupID,
56 AttributeDoublePtr theDoubleAttr = AttributeDoublePtr());
58 static EntityWrapperPtr createLine(FeaturePtr theFeature,
59 const std::list<EntityWrapperPtr>& theAttributes,
60 const GroupID& theGroupID);
61 static EntityWrapperPtr createCircle(FeaturePtr theFeature,
62 const std::list<EntityWrapperPtr>& theAttributes,
63 const GroupID& theGroupID);
64 static EntityWrapperPtr createArc(FeaturePtr theFeature,
65 const std::list<EntityWrapperPtr>& theAttributes,
66 const GroupID& theGroupID);
69 static ConstraintWrapperPtr
70 createConstraintCoincidence(ConstraintPtr theConstraint,
71 const GroupID& theGroupID,
72 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
73 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
74 static ConstraintWrapperPtr
75 createConstraintPointOnEntity(ConstraintPtr theConstraint,
76 const GroupID& theGroupID,
77 const SketchSolver_ConstraintType& theType,
78 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
79 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
80 static ConstraintWrapperPtr
81 createConstraintDistancePointPoint(ConstraintPtr theConstraint,
82 const GroupID& theGroupID,
83 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
84 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
85 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
86 static ConstraintWrapperPtr
87 createConstraintDistancePointLine(ConstraintPtr theConstraint,
88 const GroupID& theGroupID,
89 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
90 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
91 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
92 static ConstraintWrapperPtr
93 createConstraintRadius(ConstraintPtr theConstraint,
94 const GroupID& theGroupID,
95 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
96 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
97 static ConstraintWrapperPtr
98 createConstraintAngle(ConstraintPtr theConstraint,
99 const GroupID& theGroupID,
100 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
101 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
102 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
103 static ConstraintWrapperPtr
104 createConstraintHorizVert(ConstraintPtr theConstraint,
105 const GroupID& theGroupID,
106 const SketchSolver_ConstraintType& theType,
107 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
108 static ConstraintWrapperPtr
109 createConstraintParallel(ConstraintPtr theConstraint,
110 const GroupID& theGroupID,
111 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
112 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
113 static ConstraintWrapperPtr
114 createConstraintPerpendicular(ConstraintPtr theConstraint,
115 const GroupID& theGroupID,
116 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
117 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
118 static ConstraintWrapperPtr
119 createConstraintEqual(ConstraintPtr theConstraint,
120 const GroupID& theGroupID,
121 const SketchSolver_ConstraintType& theType,
122 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
123 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
124 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed);
125 static ConstraintWrapperPtr
126 createConstraintTangent(ConstraintPtr theConstraint,
127 const GroupID& theGroupID,
128 const SketchSolver_ConstraintType& theType,
129 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
130 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
131 static ConstraintWrapperPtr
132 createConstraintCollinear(ConstraintPtr theConstraint,
133 const GroupID& theGroupID,
134 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
135 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
136 static ConstraintWrapperPtr
137 createConstraintMiddlePoint(ConstraintPtr theConstraint,
138 const GroupID& theGroupID,
139 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
140 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
144 /// \brief Set flags for angle constraint
145 static void adjustAngle(ConstraintWrapperPtr theConstraint);
146 /// \brief Update mirror points
147 static void adjustMirror(ConstraintWrapperPtr theConstraint);
148 /// \brief Update a sign of the point-line distance constraint
149 static void adjustPtLineDistance(ConstraintWrapperPtr theConstraint);
151 /// \brief Transform points to be symmetric regarding to the mirror line
152 static void makeMirrorPoints(EntityWrapperPtr theOriginal,
153 EntityWrapperPtr theMirrored,
154 EntityWrapperPtr theMirrorLine);
158 // Initialization of constraint builder self pointer
159 BuilderPtr PlaneGCSSolver_Builder::mySelf = PlaneGCSSolver_Builder::getInstance();
161 BuilderPtr PlaneGCSSolver_Builder::getInstance()
164 mySelf = BuilderPtr(new PlaneGCSSolver_Builder);
165 SketchSolver_Manager::instance()->setBuilder(mySelf);
170 StoragePtr PlaneGCSSolver_Builder::createStorage(const GroupID& theGroup) const
172 return StoragePtr(new PlaneGCSSolver_Storage(theGroup));
175 SolverPtr PlaneGCSSolver_Builder::createSolver() const
177 return SolverPtr(new PlaneGCSSolver_Solver);
181 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
182 ConstraintPtr theConstraint,
183 const GroupID& theGroupID,
184 const EntityID& theSketchID,
185 const SketchSolver_ConstraintType& theType,
186 const double& theValue,
187 const EntityWrapperPtr& thePoint1,
188 const EntityWrapperPtr& thePoint2,
189 const EntityWrapperPtr& theEntity1,
190 const EntityWrapperPtr& theEntity2) const
192 ConstraintWrapperPtr aResult;
193 ParameterWrapperPtr anIntermediate;
195 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(thePoint1);
196 if (!aPoint1 && thePoint1 && thePoint1->type() == ENTITY_POINT)
197 aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint1)->subEntities().front() );
198 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(thePoint2);
199 if (!aPoint2 && thePoint2 && thePoint2->type() == ENTITY_POINT)
200 aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint2)->subEntities().front() );
203 case CONSTRAINT_PT_PT_COINCIDENT:
204 aResult = createConstraintCoincidence(theConstraint, theGroupID, aPoint1, aPoint2);
206 case CONSTRAINT_PT_ON_LINE:
207 case CONSTRAINT_PT_ON_CIRCLE:
208 aResult = createConstraintPointOnEntity(theConstraint, theGroupID, theType,
209 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
211 case CONSTRAINT_MIDDLE_POINT:
212 aResult = createConstraintMiddlePoint(theConstraint, theGroupID,
213 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
215 case CONSTRAINT_PT_PT_DISTANCE:
216 aResult = createConstraintDistancePointPoint(theConstraint, theGroupID,
217 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
220 case CONSTRAINT_PT_LINE_DISTANCE:
221 aResult = createConstraintDistancePointLine(theConstraint, theGroupID,
222 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
223 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
225 case CONSTRAINT_RADIUS:
226 aResult = createConstraintRadius(theConstraint, theGroupID,
227 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
228 GCS_ENTITY_WRAPPER(theEntity1));
230 case CONSTRAINT_ANGLE:
231 aResult = createConstraintAngle(theConstraint, theGroupID,
232 GCS_PARAMETER_WRAPPER(createParamAngle(GID_OUTOFGROUP, theValue)),
233 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
235 case CONSTRAINT_FIXED:
237 case CONSTRAINT_HORIZONTAL:
238 case CONSTRAINT_VERTICAL:
239 aResult = createConstraintHorizVert(theConstraint, theGroupID, theType,
240 GCS_ENTITY_WRAPPER(theEntity1));
242 case CONSTRAINT_PARALLEL:
243 aResult = createConstraintParallel(theConstraint, theGroupID,
244 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
246 case CONSTRAINT_PERPENDICULAR:
247 aResult = createConstraintPerpendicular(theConstraint, theGroupID,
248 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
250 case CONSTRAINT_EQUAL_LINES:
251 anIntermediate = createParameter(theGroupID);
252 case CONSTRAINT_EQUAL_LINE_ARC:
253 case CONSTRAINT_EQUAL_RADIUS:
254 aResult = createConstraintEqual(theConstraint, theGroupID, theType,
255 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2),
256 GCS_PARAMETER_WRAPPER(anIntermediate));
258 case CONSTRAINT_TANGENT_ARC_LINE:
259 case CONSTRAINT_TANGENT_CIRCLE_LINE:
260 case CONSTRAINT_TANGENT_ARC_ARC:
261 aResult = createConstraintTangent(theConstraint, theGroupID, theType,
262 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
264 case CONSTRAINT_COLLINEAR:
265 aResult = createConstraintCollinear(theConstraint, theGroupID,
266 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
268 case CONSTRAINT_MULTI_TRANSLATION:
269 case CONSTRAINT_MULTI_ROTATION:
271 case CONSTRAINT_SYMMETRIC:
272 return createMirror(theConstraint, theGroupID, theSketchID,
273 thePoint1, thePoint2, theEntity1);
279 return std::list<ConstraintWrapperPtr>();
280 adjustConstraint(aResult);
281 return std::list<ConstraintWrapperPtr>(1, aResult);
284 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
285 ConstraintPtr theConstraint,
286 const GroupID& theGroupID,
287 const EntityID& theSketchID,
288 const SketchSolver_ConstraintType& theType,
289 const double& theValue,
290 const bool theFullValue,
291 const EntityWrapperPtr& thePoint1,
292 const EntityWrapperPtr& thePoint2,
293 const std::list<EntityWrapperPtr>& theTrsfEnt) const
295 ParameterWrapperPtr anAngleParam;
296 if (theType == CONSTRAINT_MULTI_ROTATION)
297 anAngleParam = createParamAngle(theGroupID, theValue);
298 else if (theType != CONSTRAINT_MULTI_TRANSLATION)
299 return std::list<ConstraintWrapperPtr>();
301 std::list<EntityWrapperPtr> aConstrAttrList = theTrsfEnt;
303 aConstrAttrList.push_front(thePoint2);
304 aConstrAttrList.push_front(thePoint1);
306 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
307 new PlaneGCSSolver_ConstraintWrapper(theConstraint, std::list<GCSConstraintPtr>(), theType));
308 aResult->setGroup(theGroupID);
309 aResult->setEntities(aConstrAttrList);
311 aResult->setValueParameter(anAngleParam);
312 aResult->setIsFullValue(theFullValue);
313 return std::list<ConstraintWrapperPtr>(1, aResult);
317 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createMirror(
318 ConstraintPtr theConstraint,
319 const GroupID& theGroupID,
320 const EntityID& theSketchID,
321 const EntityWrapperPtr& theEntity1,
322 const EntityWrapperPtr& theEntity2,
323 const EntityWrapperPtr& theMirrorLine) const
325 std::list<ConstraintWrapperPtr> aResult;
326 std::list<EntityWrapperPtr> aConstrAttrList;
327 if (theEntity1->type() == ENTITY_POINT) {
328 if (theEntity2->group() == theGroupID) // theEntity2 is not fixed
329 makeMirrorPoints(theEntity1, theEntity2, theMirrorLine);
331 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(theEntity1);
332 if (!aPoint1 && theEntity1->type() == ENTITY_POINT)
333 aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity1)->subEntities().front() );
334 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(theEntity2);
335 if (!aPoint2 && theEntity2->type() == ENTITY_POINT)
336 aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity2)->subEntities().front() );
338 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aMirrorLine =
339 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMirrorLine);
340 std::shared_ptr<GCS::Line> aLine =
341 std::dynamic_pointer_cast<GCS::Line>(aMirrorLine->entity());
343 std::list<GCSConstraintPtr> aConstrList;
344 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
345 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
346 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintMidpointOnLine(
347 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
349 ConstraintWrapperPtr aSubResult(new PlaneGCSSolver_ConstraintWrapper(
350 theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
351 aSubResult->setGroup(theGroupID);
352 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
353 aSubs.push_back(theEntity2);
354 aSubs.push_back(theMirrorLine);
355 aSubResult->setEntities(aSubs);
356 aResult.push_back(aSubResult);
358 else if (theEntity1->type() == ENTITY_LINE) {
359 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
360 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
361 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
362 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
363 for (; anIt1 != aPoints1.end() && anIt2 != aPoints2.end(); ++anIt1, ++anIt2) {
364 std::list<ConstraintWrapperPtr> aMrrList =
365 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
366 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
369 else if (theEntity1->type() == ENTITY_CIRCLE) {
370 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
371 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
372 for (; anIt1 != aPoints1.end(); ++anIt1)
373 if ((*anIt1)->type() == ENTITY_POINT)
375 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
376 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
377 for (; anIt2 != aPoints2.end(); ++anIt2)
378 if ((*anIt2)->type() == ENTITY_POINT)
381 std::list<ConstraintWrapperPtr> aMrrList =
382 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
383 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
385 // Additional constraint for equal radii
386 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
387 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
388 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
390 else if (theEntity1->type() == ENTITY_ARC) {
391 // Do not allow mirrored arc recalculate its position until coordinated of all points recalculated
392 FeaturePtr aMirrArc = theEntity2->baseFeature();
393 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 mirrored arc without additional constraint
410 makeMirrorPoints(*anIt1, *anIt2, theMirrorLine);
412 // Additionally, make equal radii...
413 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
414 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
415 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
416 // ... and make parametric length of arcs the same
417 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt1 =
418 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity1);
419 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt2 =
420 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity2);
421 std::shared_ptr<GCS::Arc> anArc1 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt1->entity());
422 std::shared_ptr<GCS::Arc> anArc2 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt2->entity());
423 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> anIntermed =
424 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(
425 createParameter(theGroupID, *(anArc1->endAngle) - *(anArc1->startAngle)));
426 // By the way, recalculate start and end angles of mirrored arc
427 std::shared_ptr<GeomAPI_Dir2d> anOX(new GeomAPI_Dir2d(1.0, 0.0));
428 std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(
429 *(anArc2->start.x) - *(anArc2->center.x), *(anArc2->start.y) - *(anArc2->center.y)));
430 std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(
431 *(anArc2->end.x) - *(anArc2->center.x), *(anArc2->end.y) - *(anArc2->center.y)));
432 *anArc2->startAngle = anOX->angle(aStartDir);
433 *anArc2->endAngle = anOX->angle(aEndDir);
435 std::list<GCSConstraintPtr> aConstrList;
436 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
437 anArc1->endAngle, anArc1->startAngle, anIntermed->parameter())));
438 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
439 anArc2->endAngle, anArc2->startAngle, anIntermed->parameter())));
441 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aSubResult(
442 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
443 aSubResult->setGroup(theGroupID);
444 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
445 aSubs.push_back(theEntity2);
446 aSubs.push_back(theMirrorLine);
447 aSubResult->setEntities(aSubs);
448 aSubResult->setValueParameter(anIntermed);
449 aResult.push_back(aSubResult);
451 // Restore event sending
452 aMirrArc->data()->blockSendAttributeUpdated(false);
457 void PlaneGCSSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstraint) const
459 SketchSolver_ConstraintType aType = theConstraint->type();
460 // Update flags and parameters in constraints
461 if (aType == CONSTRAINT_ANGLE)
462 adjustAngle(theConstraint);
463 else if (aType == CONSTRAINT_PT_LINE_DISTANCE)
464 adjustPtLineDistance(theConstraint);
465 else if (aType == CONSTRAINT_SYMMETRIC)
466 adjustMirror(theConstraint);
469 EntityWrapperPtr PlaneGCSSolver_Builder::createFeature(
470 FeaturePtr theFeature,
471 const std::list<EntityWrapperPtr>& theAttributes,
472 const GroupID& theGroupID,
473 const EntityID& /*theSketchID*/) const
475 static EntityWrapperPtr aDummy;
476 if (!theFeature->data()->isValid())
480 CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
482 return createSketchEntity(aSketch, theGroupID);
484 // SketchPlugin features
485 std::shared_ptr<SketchPlugin_Feature> aFeature =
486 std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
490 // Verify the feature by its kind
491 const std::string& aFeatureKind = aFeature->getKind();
493 if (aFeatureKind == SketchPlugin_Line::ID())
494 return createLine(theFeature, theAttributes, theGroupID);
496 else if (aFeatureKind == SketchPlugin_Circle::ID())
497 return createCircle(theFeature, theAttributes, theGroupID);
499 else if (aFeatureKind == SketchPlugin_Arc::ID())
500 return createArc(theFeature, theAttributes, theGroupID);
501 // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
502 else if (aFeatureKind == SketchPlugin_Point::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 = createParameter(theGroupID, theDoubleAttr ? theDoubleAttr->value() : 0.0);
626 return std::shared_ptr<PlaneGCSSolver_ScalarWrapper>(
627 new PlaneGCSSolver_ScalarWrapper(theDoubleAttr, aParam));
630 EntityWrapperPtr createLine(FeaturePtr theFeature,
631 const std::list<EntityWrapperPtr>& theAttributes,
632 const GroupID& theGroupID)
634 EntityWrapperPtr aNewEntity;
635 std::list<EntityWrapperPtr> aSubs;
637 AttributePtr aStart = theFeature->attribute(SketchPlugin_Line::START_ID());
638 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Line::END_ID());
639 if (!aStart->isInitialized() || !aEnd->isInitialized())
642 std::shared_ptr<PlaneGCSSolver_PointWrapper> aStartEnt, aEndEnt;
643 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
644 for (; anIt != theAttributes.end(); ++anIt) {
645 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
646 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
649 if (aWrapper->isBase(aStart))
650 aStartEnt = aWrapper;
651 else if (aWrapper->isBase(aEnd))
654 if (!aStartEnt || !aEndEnt)
657 aSubs.push_back(aStartEnt);
658 aSubs.push_back(aEndEnt);
660 std::shared_ptr<GCS::Line> aLine(new GCS::Line);
661 aLine->p1 = *(aStartEnt->point());
662 aLine->p2 = *(aEndEnt->point());
664 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aLine));
665 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
666 aNewEntity->setSubEntities(aSubs);
670 EntityWrapperPtr createCircle(FeaturePtr theFeature,
671 const std::list<EntityWrapperPtr>& theAttributes,
672 const GroupID& theGroupID)
674 EntityWrapperPtr aNewEntity;
675 std::list<EntityWrapperPtr> aSubs;
677 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Circle::CENTER_ID());
678 AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
679 if (!aCenter->isInitialized() || !aRadius->isInitialized())
682 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt;
683 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aRadiusEnt;
684 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
685 for (; anIt != theAttributes.end(); ++anIt) {
686 if ((*anIt)->isBase(aCenter))
687 aCenterEnt = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
688 else if ((*anIt)->isBase(aRadius))
689 aRadiusEnt = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*anIt);
691 if (!aCenterEnt || !aRadiusEnt)
694 aSubs.push_back(aCenterEnt);
695 aSubs.push_back(aRadiusEnt);
697 std::shared_ptr<GCS::Circle> aCircle(new GCS::Circle);
698 aCircle->center = *(aCenterEnt->point());
699 aCircle->rad = aRadiusEnt->scalar();
701 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aCircle));
702 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
703 aNewEntity->setSubEntities(aSubs);
707 EntityWrapperPtr createArc(FeaturePtr theFeature,
708 const std::list<EntityWrapperPtr>& theAttributes,
709 const GroupID& theGroupID)
711 EntityWrapperPtr aNewEntity;
712 std::list<EntityWrapperPtr> aSubs;
714 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Arc::CENTER_ID());
715 AttributePtr aStart = theFeature->attribute(SketchPlugin_Arc::START_ID());
716 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Arc::END_ID());
717 if (!aCenter->isInitialized() || !aStart->isInitialized() || !aEnd->isInitialized())
720 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt, aStartEnt, aEndEnt;
721 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
722 for (; anIt != theAttributes.end(); ++anIt) {
723 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
724 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
727 if (aWrapper->isBase(aCenter))
728 aCenterEnt = aWrapper;
729 else if (aWrapper->isBase(aStart))
730 aStartEnt = aWrapper;
731 else if (aWrapper->isBase(aEnd))
734 if (!aCenterEnt || !aStartEnt || !aEndEnt)
737 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aStartAng, aEndAng, aRadius;
738 aStartAng = createScalar(theGroupID);
739 aEndAng = createScalar(theGroupID);
740 aRadius = createScalar(theGroupID);
742 aSubs.push_back(aCenterEnt);
743 aSubs.push_back(aStartEnt);
744 aSubs.push_back(aEndEnt);
745 aSubs.push_back(aStartAng);
746 aSubs.push_back(aEndAng);
747 aSubs.push_back(aRadius);
749 std::shared_ptr<GCS::Arc> anArc(new GCS::Arc);
750 anArc->center = *(aCenterEnt->point());
751 anArc->start = *(aStartEnt->point());
752 anArc->end = *(aEndEnt->point());
753 anArc->startAngle = aStartAng->scalar();
754 anArc->endAngle = aEndAng->scalar();
755 anArc->rad = aRadius->scalar();
757 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, anArc));
758 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
759 aNewEntity->setSubEntities(aSubs);
765 ConstraintWrapperPtr createConstraintCoincidence(
766 ConstraintPtr theConstraint,
767 const GroupID& theGroupID,
768 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
769 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
771 // Create equality constraint for corresponding attributes of the points
772 std::list<GCSConstraintPtr> aConstrList;
773 std::list<ParameterWrapperPtr>::const_iterator anIt1 = thePoint1->parameters().begin();
774 std::list<ParameterWrapperPtr>::const_iterator anIt2 = thePoint2->parameters().begin();
775 for (; anIt1 != thePoint1->parameters().end(); ++anIt1, ++anIt2) {
776 if (*anIt1 == *anIt2)
777 continue; // points use same parameters, no need additional constraints
778 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam1 =
779 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt1);
780 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam2 =
781 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt2);
782 aConstrList.push_back(
783 GCSConstraintPtr(new GCS::ConstraintEqual(aParam1->parameter(), aParam2->parameter())));
786 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
787 theConstraint, aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
788 aResult->setGroup(theGroupID);
789 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
790 aSubs.push_back(thePoint2);
791 aResult->setEntities(aSubs);
795 ConstraintWrapperPtr createConstraintPointOnEntity(
796 ConstraintPtr theConstraint,
797 const GroupID& theGroupID,
798 const SketchSolver_ConstraintType& theType,
799 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
800 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
802 GCSConstraintPtr aNewConstr;
804 switch (theEntity->type()) {
806 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
807 aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnLine(*(thePoint->point()), *aLine));
811 case ENTITY_CIRCLE: {
812 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
813 aNewConstr = GCSConstraintPtr(
814 new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
818 return ConstraintWrapperPtr();
821 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
822 theConstraint, aNewConstr, theType));
823 aResult->setGroup(theGroupID);
824 std::list<EntityWrapperPtr> aSubs(1, thePoint);
825 aSubs.push_back(theEntity);
826 aResult->setEntities(aSubs);
830 // calculate length of the line
831 static inline double lineLength(const GCS::Line& theLine)
833 double aDir[2] = {*(theLine.p2.x) - *(theLine.p1.x), *(theLine.p2.y) - *(theLine.p1.y)};
834 return sqrt(aDir[0] * aDir[0] + aDir[1] * aDir[1]);
837 // check the point is on the line
838 static inline bool isPointOnLine(const GCS::Point& thePoint, const GCS::Line& theLine)
840 double aDir[2] = {*(theLine.p2.x) - *(theLine.p1.x), *(theLine.p2.y) - *(theLine.p1.y)};
841 double aVec[2] = {*(thePoint.x) - *(theLine.p1.x), *(thePoint.y) - *(theLine.p1.y)};
842 double aCross = aVec[0] * aDir[1] - aVec[1] * aDir[0];
843 return fabs(aCross) < tolerance;
846 ConstraintWrapperPtr createConstraintMiddlePoint(
847 ConstraintPtr theConstraint,
848 const GroupID& theGroupID,
849 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
850 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
852 GCSPointPtr aPoint = thePoint->point();
853 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
855 return ConstraintWrapperPtr();
857 std::list<GCSConstraintPtr> aConstrList;
858 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPointOnLine(*aPoint, *aLine)));
859 double aDist = lineLength(*aLine);
860 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aDistance =
861 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(createParameter(theGroupID, aDist));
862 aConstrList.push_back(GCSConstraintPtr(
863 new GCS::ConstraintP2PDistance(*aPoint, aLine->p1, aDistance->parameter())));
864 aConstrList.push_back(GCSConstraintPtr(
865 new GCS::ConstraintP2PDistance(*aPoint, aLine->p2, aDistance->parameter())));
867 // Workaround to avoid conflicting constraints when the point is already placed on line
868 if (thePoint->group() != GID_UNKNOWN && isPointOnLine(*aPoint, *aLine)) {
869 std::shared_ptr<GeomDataAPI_Point2D> aCoord =
870 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(thePoint->baseAttribute());
872 *(aPoint->x) = (*(aLine->p1.x) + *(aLine->p2.x)) * 0.5;
873 *(aPoint->y) = (*(aLine->p1.y) + *(aLine->p2.y)) * 0.5;
874 aCoord->setValue(*(aPoint->x), *(aPoint->y));
878 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(new PlaneGCSSolver_ConstraintWrapper(
879 theConstraint, aConstrList, CONSTRAINT_MIDDLE_POINT));
880 aResult->setGroup(theGroupID);
881 std::list<EntityWrapperPtr> aSubs(1, thePoint);
882 aSubs.push_back(theEntity);
883 aResult->setEntities(aSubs);
884 aResult->setValueParameter(aDistance);
889 ConstraintWrapperPtr createConstraintDistancePointPoint(
890 ConstraintPtr theConstraint,
891 const GroupID& theGroupID,
892 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
893 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
894 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
896 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
897 *(thePoint1->point()), *(thePoint2->point()), theValue->parameter()));
899 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
900 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
901 aResult->setGroup(theGroupID);
902 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
903 aSubs.push_back(thePoint2);
904 aResult->setEntities(aSubs);
905 aResult->setValueParameter(theValue);
909 ConstraintWrapperPtr createConstraintDistancePointLine(
910 ConstraintPtr theConstraint,
911 const GroupID& theGroupID,
912 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
913 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
914 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
916 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
917 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
918 *(thePoint->point()), *(aLine), theValue->parameter()));
920 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
921 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
922 aResult->setGroup(theGroupID);
923 std::list<EntityWrapperPtr> aSubs(1, thePoint);
924 aSubs.push_back(theEntity);
925 aResult->setEntities(aSubs);
926 aResult->setValueParameter(theValue);
930 ConstraintWrapperPtr createConstraintRadius(
931 ConstraintPtr theConstraint,
932 const GroupID& theGroupID,
933 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
934 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
936 std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
937 GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->parameter()));
939 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
940 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_RADIUS));
941 aResult->setGroup(theGroupID);
942 std::list<EntityWrapperPtr> aSubs(1, theEntity);
943 aResult->setEntities(aSubs);
944 aResult->setValueParameter(theValue);
948 ConstraintWrapperPtr createConstraintAngle(
949 ConstraintPtr theConstraint,
950 const GroupID& theGroupID,
951 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
952 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
953 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
955 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
956 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
957 GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
958 *(aLine1), *(aLine2), theValue->parameter()));
960 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
961 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_ANGLE));
962 aResult->setGroup(theGroupID);
963 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
964 aSubs.push_back(theEntity2);
965 aResult->setEntities(aSubs);
966 aResult->setValueParameter(theValue);
970 ConstraintWrapperPtr createConstraintHorizVert(
971 ConstraintPtr theConstraint,
972 const GroupID& theGroupID,
973 const SketchSolver_ConstraintType& theType,
974 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
976 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
977 GCSConstraintPtr aNewConstr;
978 if (theType == CONSTRAINT_HORIZONTAL)
979 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.y, aLine->p2.y));
981 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
983 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
984 theConstraint, aNewConstr, theType));
985 aResult->setGroup(theGroupID);
986 std::list<EntityWrapperPtr> aSubs(1, theEntity);
987 aResult->setEntities(aSubs);
991 ConstraintWrapperPtr createConstraintCollinear(
992 ConstraintPtr theConstraint,
993 const GroupID& theGroupID,
994 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
995 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
997 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
998 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1000 // create two point-on-line constraints
1001 std::list<GCSConstraintPtr> aConstrList;
1002 aConstrList.push_back( GCSConstraintPtr(new GCS::ConstraintPointOnLine(aLine2->p1, *aLine1)) );
1003 aConstrList.push_back( GCSConstraintPtr(new GCS::ConstraintPointOnLine(aLine2->p2, *aLine1)) );
1005 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
1006 theConstraint, aConstrList, CONSTRAINT_COLLINEAR));
1007 aResult->setGroup(theGroupID);
1008 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1009 aSubs.push_back(theEntity2);
1010 aResult->setEntities(aSubs);
1014 ConstraintWrapperPtr createConstraintParallel(
1015 ConstraintPtr theConstraint,
1016 const GroupID& theGroupID,
1017 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1018 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
1020 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
1021 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1022 GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
1024 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1025 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PARALLEL));
1026 aResult->setGroup(theGroupID);
1027 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1028 aSubs.push_back(theEntity2);
1029 aResult->setEntities(aSubs);
1033 ConstraintWrapperPtr createConstraintPerpendicular(
1034 ConstraintPtr theConstraint,
1035 const GroupID& theGroupID,
1036 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1037 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
1039 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
1040 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1041 GCSConstraintPtr aNewConstr(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
1043 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1044 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PERPENDICULAR));
1045 aResult->setGroup(theGroupID);
1046 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1047 aSubs.push_back(theEntity2);
1048 aResult->setEntities(aSubs);
1052 ConstraintWrapperPtr createConstraintEqual(
1053 ConstraintPtr theConstraint,
1054 const GroupID& theGroupID,
1055 const SketchSolver_ConstraintType& theType,
1056 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1057 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
1058 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed)
1060 if (theType == CONSTRAINT_EQUAL_LINE_ARC)
1061 return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
1063 std::list<GCSConstraintPtr> aConstrList;
1064 if (theType == CONSTRAINT_EQUAL_LINES) {
1065 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
1066 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1068 aConstrList.push_back(GCSConstraintPtr(
1069 new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->parameter())));
1070 aConstrList.push_back(GCSConstraintPtr(
1071 new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->parameter())));
1073 std::shared_ptr<GCS::Circle> aCirc1 =
1074 std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1075 std::shared_ptr<GCS::Circle> aCirc2 =
1076 std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
1078 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
1081 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1082 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, theType));
1083 aResult->setGroup(theGroupID);
1084 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1085 aSubs.push_back(theEntity2);
1086 aResult->setEntities(aSubs);
1088 aResult->setValueParameter(theIntermed);
1092 ConstraintWrapperPtr createConstraintTangent(
1093 ConstraintPtr theConstraint,
1094 const GroupID& theGroupID,
1095 const SketchSolver_ConstraintType& theType,
1096 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1097 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
1099 GCSConstraintPtr aNewConstr;
1100 if (theType == CONSTRAINT_TANGENT_ARC_LINE || theType == CONSTRAINT_TANGENT_CIRCLE_LINE) {
1101 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1102 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1104 aNewConstr = GCSConstraintPtr(new GCS::ConstraintP2LDistance(aCirc->center, *aLine, aCirc->rad));
1106 std::shared_ptr<GCS::Circle> aCirc1 = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1107 std::shared_ptr<GCS::Circle> aCirc2 = std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
1109 double aDX = *(aCirc1->center.x) - *(aCirc2->center.x);
1110 double aDY = *(aCirc1->center.y) - *(aCirc2->center.y);
1111 double aDist = sqrt(aDX * aDX + aDY * aDY);
1112 aNewConstr = GCSConstraintPtr(new GCS::ConstraintTangentCircumf(aCirc1->center, aCirc2->center,
1113 aCirc1->rad, aCirc2->rad, (aDist < *(aCirc1->rad) || aDist < *(aCirc2->rad))));
1116 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1117 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, theType));
1118 aResult->setGroup(theGroupID);
1119 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1120 aSubs.push_back(theEntity2);
1121 aResult->setEntities(aSubs);
1129 void adjustAngle(ConstraintWrapperPtr theConstraint)
1131 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1133 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
1134 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
1136 std::shared_ptr<GeomAPI_Pnt2d> aPoints[2][2]; // start and end points of lines
1137 const std::list<EntityWrapperPtr>& aConstrLines = aConstraint->entities();
1138 std::list<EntityWrapperPtr>::const_iterator aCLIt = aConstrLines.begin();
1139 for (int i = 0; aCLIt != aConstrLines.end(); ++i, ++aCLIt) {
1140 const std::list<EntityWrapperPtr>& aLinePoints = (*aCLIt)->subEntities();
1141 std::list<EntityWrapperPtr>::const_iterator aLPIt = aLinePoints.begin();
1142 for (int j = 0; aLPIt != aLinePoints.end(); ++j, ++aLPIt)
1143 aPoints[i][j] = aBuilder->point(*aLPIt);
1146 std::shared_ptr<GeomAPI_Lin2d> aLine[2] = {
1147 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[0][0], aPoints[0][1])),
1148 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[1][0], aPoints[1][1]))
1150 std::shared_ptr<GeomAPI_Pnt2d> anIntersection = aLine[0]->intersect(aLine[1]);
1151 if (!anIntersection)
1154 for (int i = 0; i < 2; i++) {
1155 for (int j = 0; j < 2; j++) {
1156 aDist[i][j] = anIntersection->distance(aPoints[i][j]);
1157 if (fabs(aDist[i][j]) <= tolerance)
1160 if (aDist[i][0] > tolerance && aDist[i][1] > tolerance &&
1161 aDist[i][0] + aDist[i][1] < aPoints[i][0]->distance(aPoints[i][1]) + 2.0 * tolerance) {
1162 // the intersection point is an inner point of the line,
1163 // we change the sign of distance till start point to calculate correct coordinates
1165 aDist[i][0] *= -1.0;
1168 std::shared_ptr<GeomAPI_Dir2d> aDir[2];
1169 for (int i = 0; i < 2; i++) {
1170 if (aDist[i][1] > fabs(aDist[i][0]))
1171 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1172 aPoints[i][1]->xy()->decreased(anIntersection->xy())));
1174 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1175 aPoints[i][0]->xy()->decreased(anIntersection->xy())));
1176 // main direction is opposite => change signs
1177 if (aDist[i][0] < 0.0) {
1178 aDist[i][0] *= -1.0;
1179 aDist[i][1] *= -1.0;
1184 double anAngle = aLine[0]->direction()->angle(aLine[1]->direction()) / PI * 180;
1185 if (anAngle * aConstraint->value() < 0.0)
1186 aConstraint->setValue(-aConstraint->value());
1187 if ((90.0 - fabs(anAngle)) * (fabs(aConstraint->value()) - 90.0) > 0.0) {
1188 if (aConstraint->value() < 0.0)
1189 aConstraint->setValue(-180.0 - aConstraint->value());
1191 aConstraint->setValue(180.0 - aConstraint->value());
1195 void makeMirrorPoints(EntityWrapperPtr theOriginal,
1196 EntityWrapperPtr theMirrored,
1197 EntityWrapperPtr theMirrorLine)
1199 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1201 std::shared_ptr<GeomAPI_Lin2d> aMirrorLine = aBuilder->line(theMirrorLine);
1202 std::shared_ptr<GeomAPI_Dir2d> aMLDir = aMirrorLine->direction();
1203 // orthogonal direction
1204 aMLDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aMLDir->y(), -aMLDir->x()));
1206 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(theOriginal);
1207 std::shared_ptr<GeomAPI_XY> aVec = aPoint->xy()->decreased(aMirrorLine->location()->xy());
1208 double aDist = aVec->dot(aMLDir->xy());
1209 aVec = aPoint->xy()->added(aMLDir->xy()->multiplied(-2.0 * aDist));
1210 double aCoord[2] = {aVec->x(), aVec->y()};
1211 std::list<ParameterWrapperPtr>::const_iterator aMIt = theMirrored->parameters().begin();
1212 for (int i = 0; aMIt != theMirrored->parameters().end(); ++aMIt, ++i)
1213 (*aMIt)->setValue(aCoord[i]);
1215 // update corresponding attribute
1216 AttributePtr anAttr = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theMirrored)->baseAttribute();
1218 std::shared_ptr<GeomDataAPI_Point2D> aMirroredPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
1219 aMirroredPnt->setValue(aCoord[0], aCoord[1]);
1223 void adjustPtLineDistance(ConstraintWrapperPtr theConstraint)
1225 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1227 std::shared_ptr<GeomAPI_Pnt2d> aPoint;
1228 std::shared_ptr<GeomAPI_Lin2d> aLine;
1229 std::list<EntityWrapperPtr> aSubs = theConstraint->entities();
1230 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
1231 for (; aSIt != aSubs.end(); ++aSIt) {
1232 if ((*aSIt)->type() == ENTITY_POINT)
1233 aPoint = aBuilder->point(*aSIt);
1234 else if ((*aSIt)->type() == ENTITY_LINE)
1235 aLine = aBuilder->line(*aSIt);
1238 std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
1239 std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
1240 if (aPtLineVec->cross(aLineVec) * theConstraint->value() < 0.0)
1241 theConstraint->setValue(theConstraint->value() * (-1.0));
1244 void adjustMirror(ConstraintWrapperPtr theConstraint)
1246 std::vector<EntityWrapperPtr> aPoints;
1247 EntityWrapperPtr aMirrorLine;
1249 const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
1250 std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
1251 for (; anIt != aSubs.end(); ++anIt) {
1252 if ((*anIt)->type() == ENTITY_POINT)
1253 aPoints.push_back(*anIt);
1254 else if ((*anIt)->type() == ENTITY_LINE)
1255 aMirrorLine = *anIt;
1258 makeMirrorPoints(aPoints[0], aPoints[1], aMirrorLine);