1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: PlaneGCSSolver_Builder.cpp
4 // Created: 14 Dec 2015
5 // Author: Artem ZHIDKOV
7 #include <PlaneGCSSolver_Builder.h>
8 #include <PlaneGCSSolver_Solver.h>
9 #include <PlaneGCSSolver_Storage.h>
10 #include <PlaneGCSSolver_ParameterWrapper.h>
11 #include <PlaneGCSSolver_AngleWrapper.h>
12 #include <PlaneGCSSolver_EntityWrapper.h>
13 #include <PlaneGCSSolver_PointWrapper.h>
14 #include <PlaneGCSSolver_ScalarWrapper.h>
15 #include <PlaneGCSSolver_ConstraintWrapper.h>
17 #include <SketchSolver_Manager.h>
19 #include <GeomAPI_Dir2d.h>
20 #include <GeomAPI_Pnt2d.h>
21 #include <GeomAPI_XY.h>
22 #include <GeomDataAPI_Dir.h>
23 #include <GeomDataAPI_Point.h>
24 #include <GeomDataAPI_Point2D.h>
25 #include <ModelAPI_Attribute.h>
26 #include <ModelAPI_AttributeRefAttr.h>
28 #include <SketchPlugin_Arc.h>
29 #include <SketchPlugin_Circle.h>
30 #include <SketchPlugin_Line.h>
31 #include <SketchPlugin_Point.h>
32 #include <SketchPlugin_ConstraintAngle.h>
37 #define GCS_ENTITY_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(x)
38 #define GCS_POINT_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(x)
39 #define GCS_PARAMETER_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(x)
42 /// \brief Converts a value to SolveSpace parameter
43 /// \param theGroup [in] group to store parameter
44 /// \param theValue [in] value of parameter
45 /// \param theExpr [in] shows the parameter is given by expression
46 /// \return Created parameter's wrapper
47 static ParameterWrapperPtr createParameter(const GroupID& theGroup,
48 const double theValue = 0.0,
49 const bool theExpr = false);
51 static ParameterWrapperPtr createParamAngle(const GroupID& theGroup,
52 const double& theValue = 0.0);
54 static std::shared_ptr<PlaneGCSSolver_ScalarWrapper>
55 createScalar(const GroupID& theGroupID,
56 AttributeDoublePtr theDoubleAttr = AttributeDoublePtr());
58 static EntityWrapperPtr createLine(FeaturePtr theFeature,
59 const std::list<EntityWrapperPtr>& theAttributes,
60 const GroupID& theGroupID);
61 static EntityWrapperPtr createCircle(FeaturePtr theFeature,
62 const std::list<EntityWrapperPtr>& theAttributes,
63 const GroupID& theGroupID);
64 static EntityWrapperPtr createArc(FeaturePtr theFeature,
65 const std::list<EntityWrapperPtr>& theAttributes,
66 const GroupID& theGroupID);
69 static ConstraintWrapperPtr
70 createConstraintCoincidence(ConstraintPtr theConstraint,
71 const GroupID& theGroupID,
72 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
73 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
74 static ConstraintWrapperPtr
75 createConstraintPointOnEntity(ConstraintPtr theConstraint,
76 const GroupID& theGroupID,
77 const SketchSolver_ConstraintType& theType,
78 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
79 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
80 static ConstraintWrapperPtr
81 createConstraintDistancePointPoint(ConstraintPtr theConstraint,
82 const GroupID& theGroupID,
83 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
84 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
85 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
86 static ConstraintWrapperPtr
87 createConstraintDistancePointLine(ConstraintPtr theConstraint,
88 const GroupID& theGroupID,
89 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
90 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
91 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
92 static ConstraintWrapperPtr
93 createConstraintRadius(ConstraintPtr theConstraint,
94 const GroupID& theGroupID,
95 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
96 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
97 static ConstraintWrapperPtr
98 createConstraintAngle(ConstraintPtr theConstraint,
99 const GroupID& theGroupID,
100 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
101 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
102 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
103 static ConstraintWrapperPtr
104 createConstraintHorizVert(ConstraintPtr theConstraint,
105 const GroupID& theGroupID,
106 const SketchSolver_ConstraintType& theType,
107 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
108 static ConstraintWrapperPtr
109 createConstraintParallel(ConstraintPtr theConstraint,
110 const GroupID& theGroupID,
111 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
112 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
113 static ConstraintWrapperPtr
114 createConstraintPerpendicular(ConstraintPtr theConstraint,
115 const GroupID& theGroupID,
116 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
117 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
118 static ConstraintWrapperPtr
119 createConstraintEqual(ConstraintPtr theConstraint,
120 const GroupID& theGroupID,
121 const SketchSolver_ConstraintType& theType,
122 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
123 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
124 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed);
125 static ConstraintWrapperPtr
126 createConstraintTangent(ConstraintPtr theConstraint,
127 const GroupID& theGroupID,
128 const SketchSolver_ConstraintType& theType,
129 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
130 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
134 /// \brief Set flags for angle constraint
135 static void adjustAngle(ConstraintWrapperPtr theConstraint);
136 /// \brief Update mirror points
137 static void adjustMirror(ConstraintWrapperPtr theConstraint);
139 /// \brief Transform points to be symmetric regarding to the mirror line
140 static void makeMirrorPoints(EntityWrapperPtr theOriginal,
141 EntityWrapperPtr theMirrored,
142 EntityWrapperPtr theMirrorLine);
146 // Initialization of constraint builder self pointer
147 BuilderPtr PlaneGCSSolver_Builder::mySelf = PlaneGCSSolver_Builder::getInstance();
149 BuilderPtr PlaneGCSSolver_Builder::getInstance()
152 mySelf = BuilderPtr(new PlaneGCSSolver_Builder);
153 SketchSolver_Manager::instance()->setBuilder(mySelf);
158 StoragePtr PlaneGCSSolver_Builder::createStorage(const GroupID& theGroup) const
160 return StoragePtr(new PlaneGCSSolver_Storage(theGroup));
163 SolverPtr PlaneGCSSolver_Builder::createSolver() const
165 return SolverPtr(new PlaneGCSSolver_Solver);
169 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
170 ConstraintPtr theConstraint,
171 const GroupID& theGroupID,
172 const EntityID& theSketchID,
173 const SketchSolver_ConstraintType& theType,
174 const double& theValue,
175 const EntityWrapperPtr& thePoint1,
176 const EntityWrapperPtr& thePoint2,
177 const EntityWrapperPtr& theEntity1,
178 const EntityWrapperPtr& theEntity2) const
180 ConstraintWrapperPtr aResult;
181 ParameterWrapperPtr anIntermediate;
183 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(thePoint1);
184 if (!aPoint1 && thePoint1 && thePoint1->type() == ENTITY_POINT)
185 aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint1)->subEntities().front() );
186 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(thePoint2);
187 if (!aPoint2 && thePoint2 && thePoint2->type() == ENTITY_POINT)
188 aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint2)->subEntities().front() );
191 case CONSTRAINT_PT_PT_COINCIDENT:
192 aResult = createConstraintCoincidence(theConstraint, theGroupID, aPoint1, aPoint2);
194 case CONSTRAINT_PT_ON_LINE:
195 case CONSTRAINT_PT_ON_CIRCLE:
196 aResult = createConstraintPointOnEntity(theConstraint, theGroupID, theType,
197 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
199 case CONSTRAINT_PT_PT_DISTANCE:
200 aResult = createConstraintDistancePointPoint(theConstraint, theGroupID,
201 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
204 case CONSTRAINT_PT_LINE_DISTANCE:
205 aResult = createConstraintDistancePointLine(theConstraint, theGroupID,
206 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
207 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
209 case CONSTRAINT_RADIUS:
210 aResult = createConstraintRadius(theConstraint, theGroupID,
211 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
212 GCS_ENTITY_WRAPPER(theEntity1));
214 case CONSTRAINT_ANGLE:
215 aResult = createConstraintAngle(theConstraint, theGroupID,
216 GCS_PARAMETER_WRAPPER(createParamAngle(GID_OUTOFGROUP, theValue)),
217 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
219 case CONSTRAINT_FIXED:
221 case CONSTRAINT_HORIZONTAL:
222 case CONSTRAINT_VERTICAL:
223 aResult = createConstraintHorizVert(theConstraint, theGroupID, theType,
224 GCS_ENTITY_WRAPPER(theEntity1));
226 case CONSTRAINT_PARALLEL:
227 aResult = createConstraintParallel(theConstraint, theGroupID,
228 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
230 case CONSTRAINT_PERPENDICULAR:
231 aResult = createConstraintPerpendicular(theConstraint, theGroupID,
232 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
234 case CONSTRAINT_EQUAL_LINES:
235 anIntermediate = createParameter(theGroupID);
236 case CONSTRAINT_EQUAL_LINE_ARC:
237 case CONSTRAINT_EQUAL_RADIUS:
238 aResult = createConstraintEqual(theConstraint, theGroupID, theType,
239 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2),
240 GCS_PARAMETER_WRAPPER(anIntermediate));
242 case CONSTRAINT_TANGENT_ARC_LINE:
243 case CONSTRAINT_TANGENT_ARC_ARC:
244 aResult = createConstraintTangent(theConstraint, theGroupID, theType,
245 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
247 case CONSTRAINT_MULTI_TRANSLATION:
248 case CONSTRAINT_MULTI_ROTATION:
250 case CONSTRAINT_SYMMETRIC:
251 return createMirror(theConstraint, theGroupID, theSketchID,
252 thePoint1, thePoint2, theEntity1);
258 return std::list<ConstraintWrapperPtr>();
259 adjustConstraint(aResult);
260 return std::list<ConstraintWrapperPtr>(1, aResult);
263 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
264 ConstraintPtr theConstraint,
265 const GroupID& theGroupID,
266 const EntityID& theSketchID,
267 const SketchSolver_ConstraintType& theType,
268 const double& theValue,
269 const bool theFullValue,
270 const EntityWrapperPtr& thePoint1,
271 const EntityWrapperPtr& thePoint2,
272 const std::list<EntityWrapperPtr>& theTrsfEnt) const
274 ParameterWrapperPtr anAngleParam;
275 if (theType == CONSTRAINT_MULTI_ROTATION)
276 anAngleParam = createParamAngle(theGroupID, theValue);
277 else if (theType != CONSTRAINT_MULTI_TRANSLATION)
278 return std::list<ConstraintWrapperPtr>();
280 std::list<EntityWrapperPtr> aConstrAttrList = theTrsfEnt;
282 aConstrAttrList.push_front(thePoint2);
283 aConstrAttrList.push_front(thePoint1);
285 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
286 new PlaneGCSSolver_ConstraintWrapper(theConstraint, std::list<GCSConstraintPtr>(), theType));
287 aResult->setGroup(theGroupID);
288 aResult->setEntities(aConstrAttrList);
290 aResult->setValueParameter(anAngleParam);
291 aResult->setIsFullValue(theFullValue);
292 return std::list<ConstraintWrapperPtr>(1, aResult);
296 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createMirror(
297 ConstraintPtr theConstraint,
298 const GroupID& theGroupID,
299 const EntityID& theSketchID,
300 const EntityWrapperPtr& theEntity1,
301 const EntityWrapperPtr& theEntity2,
302 const EntityWrapperPtr& theMirrorLine) const
304 std::list<ConstraintWrapperPtr> aResult;
305 std::list<EntityWrapperPtr> aConstrAttrList;
306 if (theEntity1->type() == ENTITY_POINT) {
307 if (theEntity2->group() == theGroupID) // theEntity2 is not fixed
308 makeMirrorPoints(theEntity1, theEntity2, theMirrorLine);
310 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(theEntity1);
311 if (!aPoint1 && theEntity1->type() == ENTITY_POINT)
312 aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity1)->subEntities().front() );
313 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(theEntity2);
314 if (!aPoint2 && theEntity2->type() == ENTITY_POINT)
315 aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity2)->subEntities().front() );
317 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aMirrorLine =
318 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMirrorLine);
319 std::shared_ptr<GCS::Line> aLine =
320 std::dynamic_pointer_cast<GCS::Line>(aMirrorLine->entity());
322 std::list<GCSConstraintPtr> aConstrList;
323 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
324 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
325 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintMidpointOnLine(
326 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
328 ConstraintWrapperPtr aSubResult(new PlaneGCSSolver_ConstraintWrapper(
329 theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
330 aSubResult->setGroup(theGroupID);
331 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
332 aSubs.push_back(theEntity2);
333 aSubs.push_back(theMirrorLine);
334 aSubResult->setEntities(aSubs);
335 aResult.push_back(aSubResult);
337 else if (theEntity1->type() == ENTITY_LINE) {
338 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
339 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
340 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
341 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
342 for (; anIt1 != aPoints1.end() && anIt2 != aPoints2.end(); ++anIt1, ++anIt2) {
343 std::list<ConstraintWrapperPtr> aMrrList =
344 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
345 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
348 else if (theEntity1->type() == ENTITY_CIRCLE) {
349 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
350 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
351 for (; anIt1 != aPoints1.end(); ++anIt1)
352 if ((*anIt1)->type() == ENTITY_POINT)
354 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
355 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
356 for (; anIt2 != aPoints2.end(); ++anIt2)
357 if ((*anIt2)->type() == ENTITY_POINT)
360 std::list<ConstraintWrapperPtr> aMrrList =
361 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
362 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
364 // Additional constraint for equal radii
365 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
366 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
367 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
369 else if (theEntity1->type() == ENTITY_ARC) {
370 // Do not allow mirrored arc recalculate its position until coordinated of all points recalculated
371 FeaturePtr aMirrArc = theEntity2->baseFeature();
372 aMirrArc->data()->blockSendAttributeUpdated(true);
374 // Make mirror for center and start point of original arc
375 std::list<ConstraintWrapperPtr> aMrrList;
376 std::list<EntityWrapperPtr>::const_iterator anIt1 = theEntity1->subEntities().begin();
377 std::list<EntityWrapperPtr>::const_iterator anIt2 = theEntity2->subEntities().begin();
378 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
379 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
383 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
384 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
386 // make symmetric last point of original arc and first point of mirrored arc without additional constraint
389 makeMirrorPoints(*anIt1, *anIt2, theMirrorLine);
391 // Additionally, make equal radii...
392 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
393 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
394 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
395 // ... and make parametric length of arcs the same
396 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt1 =
397 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity1);
398 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt2 =
399 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity2);
400 std::shared_ptr<GCS::Arc> anArc1 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt1->entity());
401 std::shared_ptr<GCS::Arc> anArc2 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt2->entity());
402 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> anIntermed =
403 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(
404 createParameter(theGroupID, *(anArc1->endAngle) - *(anArc1->startAngle)));
405 // By the way, recalculate start and end angles of mirrored arc
406 std::shared_ptr<GeomAPI_Dir2d> anOX(new GeomAPI_Dir2d(1.0, 0.0));
407 std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(
408 *(anArc2->start.x) - *(anArc2->center.x), *(anArc2->start.y) - *(anArc2->center.y)));
409 std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(
410 *(anArc2->end.x) - *(anArc2->center.x), *(anArc2->end.y) - *(anArc2->center.y)));
411 *anArc2->startAngle = anOX->angle(aStartDir);
412 *anArc2->endAngle = anOX->angle(aEndDir);
414 std::list<GCSConstraintPtr> aConstrList;
415 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
416 anArc1->endAngle, anArc1->startAngle, anIntermed->parameter())));
417 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
418 anArc2->endAngle, anArc2->startAngle, anIntermed->parameter())));
420 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aSubResult(
421 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
422 aSubResult->setGroup(theGroupID);
423 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
424 aSubs.push_back(theEntity2);
425 aSubs.push_back(theMirrorLine);
426 aSubResult->setEntities(aSubs);
427 aSubResult->setValueParameter(anIntermed);
428 aResult.push_back(aSubResult);
430 // Restore event sending
431 aMirrArc->data()->blockSendAttributeUpdated(false);
436 void PlaneGCSSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstraint) const
438 SketchSolver_ConstraintType aType = theConstraint->type();
439 // Update flags and parameters in constraints
440 if (aType == CONSTRAINT_ANGLE)
441 adjustAngle(theConstraint);
444 EntityWrapperPtr PlaneGCSSolver_Builder::createFeature(
445 FeaturePtr theFeature,
446 const std::list<EntityWrapperPtr>& theAttributes,
447 const GroupID& theGroupID,
448 const EntityID& /*theSketchID*/) const
450 static EntityWrapperPtr aDummy;
451 if (!theFeature->data()->isValid())
455 CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
457 return createSketchEntity(aSketch, theGroupID);
459 // SketchPlugin features
460 std::shared_ptr<SketchPlugin_Feature> aFeature =
461 std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
465 // Verify the feature by its kind
466 const std::string& aFeatureKind = aFeature->getKind();
468 if (aFeatureKind == SketchPlugin_Line::ID())
469 return createLine(theFeature, theAttributes, theGroupID);
471 else if (aFeatureKind == SketchPlugin_Circle::ID())
472 return createCircle(theFeature, theAttributes, theGroupID);
474 else if (aFeatureKind == SketchPlugin_Arc::ID())
475 return createArc(theFeature, theAttributes, theGroupID);
476 // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
477 else if (aFeatureKind == SketchPlugin_Point::ID()) {
478 EntityWrapperPtr aSub;
479 if (theAttributes.size() == 1)
480 aSub = theAttributes.front();
482 AttributePtr aPoint = theFeature->attribute(SketchPlugin_Point::COORD_ID());
483 if (aPoint->isInitialized())
484 aSub = createAttribute(aPoint, theGroupID);
489 GCSPointPtr aSubEnt =
490 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aSub)->point();
491 EntityWrapperPtr aNewEntity(new PlaneGCSSolver_EntityWrapper(theFeature));
492 aNewEntity->setSubEntities(std::list<EntityWrapperPtr>(1, aSub));
500 EntityWrapperPtr PlaneGCSSolver_Builder::createAttribute(
501 AttributePtr theAttribute,
502 const GroupID& theGroupID,
503 const EntityID& theSketchID) const
505 AttributePtr anAttribute = theAttribute;
506 AttributeRefAttrPtr aRefAttr =
507 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
509 if (aRefAttr->isObject()) {
510 // do not create features here
511 return EntityWrapperPtr();
513 anAttribute = aRefAttr->attr();
516 std::list<ParameterWrapperPtr> aParameters;
517 EntityWrapperPtr aResult;
520 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
521 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
523 aParameters.push_back(::createParameter(theGroupID, aPoint2D->x(), !aPoint2D->textX().empty()));
524 aParameters.push_back(::createParameter(theGroupID, aPoint2D->y(), !aPoint2D->textY().empty()));
525 GCSPointPtr aGCSPoint(new GCS::Point);
526 aGCSPoint->x = std::dynamic_pointer_cast<
527 PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
528 aGCSPoint->y = std::dynamic_pointer_cast<
529 PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
530 // Create entity (parameters are not filled)
531 aResult = EntityWrapperPtr(new PlaneGCSSolver_PointWrapper(theAttribute, aGCSPoint));
533 // Scalar value (used for the distance entities)
534 AttributeDoublePtr aScalar =
535 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
537 return createScalar(theGroupID, aScalar);
541 // unknown attribute type
542 return EntityWrapperPtr();
545 aResult->setGroup(theGroupID);
546 aResult->setParameters(aParameters);
550 ParameterWrapperPtr PlaneGCSSolver_Builder::createParameter(
551 const GroupID& theGroupID, double theValue) const
553 return ::createParameter(theGroupID, theValue);
557 EntityWrapperPtr PlaneGCSSolver_Builder::createSketchEntity(
558 CompositeFeaturePtr theSketch,
559 const GroupID& theGroupID) const
561 DataPtr aSketchData = theSketch->data();
562 if (!aSketchData || !aSketchData->isValid())
563 return EntityWrapperPtr(); // the sketch is incorrect
565 // Create dummy wrapper representing workplane
566 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aSketchEnt(
567 new PlaneGCSSolver_EntityWrapper(FeaturePtr(theSketch)));
568 aSketchEnt->setGroup(theGroupID);
569 aSketchEnt->setId(EID_SKETCH);
577 // ================ Auxiliary functions ==========================
578 ParameterWrapperPtr createParameter(
579 const GroupID& theGroup, const double theValue, const bool theExpr)
581 double* aParam = new double(theValue);
582 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_ParameterWrapper(aParam));
583 aWrapper->setGroup(theGroup);
584 aWrapper->setIsParametric(theExpr);
588 ParameterWrapperPtr createParamAngle(const GroupID& theGroup, const double& theValue)
590 double* aParam = new double(theValue);
591 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_AngleWrapper(aParam));
592 aWrapper->setGroup(theGroup);
596 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> createScalar(
597 const GroupID& theGroupID,
598 AttributeDoublePtr theDoubleAttr)
600 ParameterWrapperPtr aParam = createParameter(theGroupID, theDoubleAttr ? theDoubleAttr->value() : 0.0);
601 return std::shared_ptr<PlaneGCSSolver_ScalarWrapper>(
602 new PlaneGCSSolver_ScalarWrapper(theDoubleAttr, aParam));
605 EntityWrapperPtr createLine(FeaturePtr theFeature,
606 const std::list<EntityWrapperPtr>& theAttributes,
607 const GroupID& theGroupID)
609 EntityWrapperPtr aNewEntity;
610 std::list<EntityWrapperPtr> aSubs;
612 AttributePtr aStart = theFeature->attribute(SketchPlugin_Line::START_ID());
613 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Line::END_ID());
614 if (!aStart->isInitialized() || !aEnd->isInitialized())
617 std::shared_ptr<PlaneGCSSolver_PointWrapper> aStartEnt, aEndEnt;
618 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
619 for (; anIt != theAttributes.end(); ++anIt) {
620 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
621 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
624 if (aWrapper->isBase(aStart))
625 aStartEnt = aWrapper;
626 else if (aWrapper->isBase(aEnd))
629 if (!aStartEnt || !aEndEnt)
632 aSubs.push_back(aStartEnt);
633 aSubs.push_back(aEndEnt);
635 std::shared_ptr<GCS::Line> aLine(new GCS::Line);
636 aLine->p1 = *(aStartEnt->point());
637 aLine->p2 = *(aEndEnt->point());
639 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aLine));
640 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
641 aNewEntity->setSubEntities(aSubs);
645 EntityWrapperPtr createCircle(FeaturePtr theFeature,
646 const std::list<EntityWrapperPtr>& theAttributes,
647 const GroupID& theGroupID)
649 EntityWrapperPtr aNewEntity;
650 std::list<EntityWrapperPtr> aSubs;
652 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Circle::CENTER_ID());
653 AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
654 if (!aCenter->isInitialized() || !aRadius->isInitialized())
657 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt;
658 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aRadiusEnt;
659 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
660 for (; anIt != theAttributes.end(); ++anIt) {
661 if ((*anIt)->isBase(aCenter))
662 aCenterEnt = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
663 else if ((*anIt)->isBase(aRadius))
664 aRadiusEnt = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*anIt);
666 if (!aCenterEnt || !aRadiusEnt)
669 aSubs.push_back(aCenterEnt);
670 aSubs.push_back(aRadiusEnt);
672 std::shared_ptr<GCS::Circle> aCircle(new GCS::Circle);
673 aCircle->center = *(aCenterEnt->point());
674 aCircle->rad = aRadiusEnt->scalar();
676 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aCircle));
677 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
678 aNewEntity->setSubEntities(aSubs);
682 EntityWrapperPtr createArc(FeaturePtr theFeature,
683 const std::list<EntityWrapperPtr>& theAttributes,
684 const GroupID& theGroupID)
686 EntityWrapperPtr aNewEntity;
687 std::list<EntityWrapperPtr> aSubs;
689 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Arc::CENTER_ID());
690 AttributePtr aStart = theFeature->attribute(SketchPlugin_Arc::START_ID());
691 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Arc::END_ID());
692 if (!aCenter->isInitialized() || !aStart->isInitialized() || !aEnd->isInitialized())
695 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt, aStartEnt, aEndEnt;
696 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
697 for (; anIt != theAttributes.end(); ++anIt) {
698 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
699 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
702 if (aWrapper->isBase(aCenter))
703 aCenterEnt = aWrapper;
704 else if (aWrapper->isBase(aStart))
705 aStartEnt = aWrapper;
706 else if (aWrapper->isBase(aEnd))
709 if (!aCenterEnt || !aStartEnt || !aEndEnt)
712 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aStartAng, aEndAng, aRadius;
713 aStartAng = createScalar(theGroupID);
714 aEndAng = createScalar(theGroupID);
715 aRadius = createScalar(theGroupID);
717 aSubs.push_back(aCenterEnt);
718 aSubs.push_back(aStartEnt);
719 aSubs.push_back(aEndEnt);
720 aSubs.push_back(aStartAng);
721 aSubs.push_back(aEndAng);
722 aSubs.push_back(aRadius);
724 std::shared_ptr<GCS::Arc> anArc(new GCS::Arc);
725 anArc->center = *(aCenterEnt->point());
726 anArc->start = *(aStartEnt->point());
727 anArc->end = *(aEndEnt->point());
728 anArc->startAngle = aStartAng->scalar();
729 anArc->endAngle = aEndAng->scalar();
730 anArc->rad = aRadius->scalar();
732 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, anArc));
733 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
734 aNewEntity->setSubEntities(aSubs);
740 ConstraintWrapperPtr createConstraintCoincidence(
741 ConstraintPtr theConstraint,
742 const GroupID& theGroupID,
743 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
744 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
746 // Create equality constraint for corresponding attributes of the points
747 std::list<GCSConstraintPtr> aConstrList;
748 std::list<ParameterWrapperPtr>::const_iterator anIt1 = thePoint1->parameters().begin();
749 std::list<ParameterWrapperPtr>::const_iterator anIt2 = thePoint2->parameters().begin();
750 for (; anIt1 != thePoint1->parameters().end(); ++anIt1, ++anIt2) {
751 if (*anIt1 == *anIt2)
752 continue; // points use same parameters, no need additional constraints
753 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam1 =
754 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt1);
755 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam2 =
756 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt2);
757 aConstrList.push_back(
758 GCSConstraintPtr(new GCS::ConstraintEqual(aParam1->parameter(), aParam2->parameter())));
761 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
762 theConstraint, aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
763 aResult->setGroup(theGroupID);
764 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
765 aSubs.push_back(thePoint2);
766 aResult->setEntities(aSubs);
770 ConstraintWrapperPtr createConstraintPointOnEntity(
771 ConstraintPtr theConstraint,
772 const GroupID& theGroupID,
773 const SketchSolver_ConstraintType& theType,
774 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
775 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
777 GCSConstraintPtr aNewConstr;
779 switch (theEntity->type()) {
781 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
782 aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnLine(*(thePoint->point()), *aLine));
786 case ENTITY_CIRCLE: {
787 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
788 aNewConstr = GCSConstraintPtr(
789 new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
793 return ConstraintWrapperPtr();
796 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
797 theConstraint, aNewConstr, theType));
798 aResult->setGroup(theGroupID);
799 std::list<EntityWrapperPtr> aSubs(1, thePoint);
800 aSubs.push_back(theEntity);
801 aResult->setEntities(aSubs);
805 ConstraintWrapperPtr createConstraintDistancePointPoint(
806 ConstraintPtr theConstraint,
807 const GroupID& theGroupID,
808 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
809 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
810 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
812 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
813 *(thePoint1->point()), *(thePoint2->point()), theValue->parameter()));
815 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
816 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
817 aResult->setGroup(theGroupID);
818 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
819 aSubs.push_back(thePoint2);
820 aResult->setEntities(aSubs);
821 aResult->setValueParameter(theValue);
825 ConstraintWrapperPtr createConstraintDistancePointLine(
826 ConstraintPtr theConstraint,
827 const GroupID& theGroupID,
828 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
829 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
830 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
832 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
833 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
834 *(thePoint->point()), *(aLine), theValue->parameter()));
836 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
837 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
838 aResult->setGroup(theGroupID);
839 std::list<EntityWrapperPtr> aSubs(1, thePoint);
840 aSubs.push_back(theEntity);
841 aResult->setEntities(aSubs);
842 aResult->setValueParameter(theValue);
846 ConstraintWrapperPtr createConstraintRadius(
847 ConstraintPtr theConstraint,
848 const GroupID& theGroupID,
849 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
850 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
852 std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
853 GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->parameter()));
855 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
856 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_RADIUS));
857 aResult->setGroup(theGroupID);
858 std::list<EntityWrapperPtr> aSubs(1, theEntity);
859 aResult->setEntities(aSubs);
860 aResult->setValueParameter(theValue);
864 ConstraintWrapperPtr createConstraintAngle(
865 ConstraintPtr theConstraint,
866 const GroupID& theGroupID,
867 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
868 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
869 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
871 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
872 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
873 GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
874 *(aLine1), *(aLine2), theValue->parameter()));
876 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
877 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_ANGLE));
878 aResult->setGroup(theGroupID);
879 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
880 aSubs.push_back(theEntity2);
881 aResult->setEntities(aSubs);
882 aResult->setValueParameter(theValue);
886 ConstraintWrapperPtr createConstraintHorizVert(
887 ConstraintPtr theConstraint,
888 const GroupID& theGroupID,
889 const SketchSolver_ConstraintType& theType,
890 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
892 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
893 GCSConstraintPtr aNewConstr;
894 if (theType == CONSTRAINT_HORIZONTAL)
895 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.y, aLine->p2.y));
897 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
899 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
900 theConstraint, aNewConstr, theType));
901 aResult->setGroup(theGroupID);
902 std::list<EntityWrapperPtr> aSubs(1, theEntity);
903 aResult->setEntities(aSubs);
907 ConstraintWrapperPtr createConstraintParallel(
908 ConstraintPtr theConstraint,
909 const GroupID& theGroupID,
910 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
911 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
913 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
914 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
915 GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
917 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
918 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PARALLEL));
919 aResult->setGroup(theGroupID);
920 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
921 aSubs.push_back(theEntity2);
922 aResult->setEntities(aSubs);
926 ConstraintWrapperPtr createConstraintPerpendicular(
927 ConstraintPtr theConstraint,
928 const GroupID& theGroupID,
929 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
930 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
932 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
933 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
934 GCSConstraintPtr aNewConstr(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
936 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
937 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PERPENDICULAR));
938 aResult->setGroup(theGroupID);
939 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
940 aSubs.push_back(theEntity2);
941 aResult->setEntities(aSubs);
945 ConstraintWrapperPtr createConstraintEqual(
946 ConstraintPtr theConstraint,
947 const GroupID& theGroupID,
948 const SketchSolver_ConstraintType& theType,
949 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
950 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
951 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed)
953 if (theType == CONSTRAINT_EQUAL_LINE_ARC)
954 return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
956 std::list<GCSConstraintPtr> aConstrList;
957 if (theType == CONSTRAINT_EQUAL_LINES) {
958 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
959 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
961 aConstrList.push_back(GCSConstraintPtr(
962 new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->parameter())));
963 aConstrList.push_back(GCSConstraintPtr(
964 new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->parameter())));
966 std::shared_ptr<GCS::Circle> aCirc1 =
967 std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
968 std::shared_ptr<GCS::Circle> aCirc2 =
969 std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
971 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
974 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
975 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, theType));
976 aResult->setGroup(theGroupID);
977 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
978 aSubs.push_back(theEntity2);
979 aResult->setEntities(aSubs);
981 aResult->setValueParameter(theIntermed);
985 ConstraintWrapperPtr createConstraintTangent(
986 ConstraintPtr theConstraint,
987 const GroupID& theGroupID,
988 const SketchSolver_ConstraintType& theType,
989 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
990 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
992 GCSConstraintPtr aNewConstr;
993 if (theType == CONSTRAINT_TANGENT_ARC_LINE) {
994 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
995 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
997 aNewConstr = GCSConstraintPtr(new GCS::ConstraintP2LDistance(aCirc->center, *aLine, aCirc->rad));
999 std::shared_ptr<GCS::Circle> aCirc1 = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1000 std::shared_ptr<GCS::Circle> aCirc2 = std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
1002 double aDX = *(aCirc1->center.x) - *(aCirc2->center.x);
1003 double aDY = *(aCirc1->center.y) - *(aCirc2->center.y);
1004 double aDist = sqrt(aDX * aDX + aDY * aDY);
1005 aNewConstr = GCSConstraintPtr(new GCS::ConstraintTangentCircumf(aCirc1->center, aCirc2->center,
1006 aCirc1->rad, aCirc2->rad, (aDist < *(aCirc1->rad) || aDist < *(aCirc2->rad))));
1009 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1010 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, theType));
1011 aResult->setGroup(theGroupID);
1012 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1013 aSubs.push_back(theEntity2);
1014 aResult->setEntities(aSubs);
1022 void adjustAngle(ConstraintWrapperPtr theConstraint)
1024 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1026 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
1027 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
1029 std::shared_ptr<GeomAPI_Pnt2d> aPoints[2][2]; // start and end points of lines
1030 const std::list<EntityWrapperPtr>& aConstrLines = aConstraint->entities();
1031 std::list<EntityWrapperPtr>::const_iterator aCLIt = aConstrLines.begin();
1032 for (int i = 0; aCLIt != aConstrLines.end(); ++i, ++aCLIt) {
1033 const std::list<EntityWrapperPtr>& aLinePoints = (*aCLIt)->subEntities();
1034 std::list<EntityWrapperPtr>::const_iterator aLPIt = aLinePoints.begin();
1035 for (int j = 0; aLPIt != aLinePoints.end(); ++j, ++aLPIt)
1036 aPoints[i][j] = aBuilder->point(*aLPIt);
1039 std::shared_ptr<GeomAPI_Lin2d> aLine[2] = {
1040 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[0][0], aPoints[0][1])),
1041 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[1][0], aPoints[1][1]))
1043 std::shared_ptr<GeomAPI_Pnt2d> anIntersection = aLine[0]->intersect(aLine[1]);
1044 if (!anIntersection)
1047 for (int i = 0; i < 2; i++) {
1048 for (int j = 0; j < 2; j++) {
1049 aDist[i][j] = anIntersection->distance(aPoints[i][j]);
1050 if (fabs(aDist[i][j]) <= tolerance)
1053 if (aDist[i][0] > tolerance && aDist[i][1] > tolerance &&
1054 aDist[i][0] + aDist[i][1] < aPoints[i][0]->distance(aPoints[i][1]) + 2.0 * tolerance) {
1055 // the intersection point is an inner point of the line,
1056 // we change the sign of distance till start point to calculate correct coordinates
1058 aDist[i][0] *= -1.0;
1061 std::shared_ptr<GeomAPI_Dir2d> aDir[2];
1062 for (int i = 0; i < 2; i++) {
1063 if (aDist[i][1] > fabs(aDist[i][0]))
1064 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1065 aPoints[i][1]->xy()->decreased(anIntersection->xy())));
1067 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1068 aPoints[i][0]->xy()->decreased(anIntersection->xy())));
1069 // main direction is opposite => change signs
1070 if (aDist[i][0] < 0.0) {
1071 aDist[i][0] *= -1.0;
1072 aDist[i][1] *= -1.0;
1077 double anAngle = aLine[0]->direction()->angle(aLine[1]->direction()) / PI * 180;
1078 if (anAngle * aConstraint->value() < 0.0)
1079 aConstraint->setValue(-aConstraint->value());
1080 if ((90.0 - fabs(anAngle)) * (fabs(aConstraint->value()) - 90.0) > 0.0) {
1081 if (aConstraint->value() < 0.0)
1082 aConstraint->setValue(-180.0 - aConstraint->value());
1084 aConstraint->setValue(180.0 - aConstraint->value());
1088 void makeMirrorPoints(EntityWrapperPtr theOriginal,
1089 EntityWrapperPtr theMirrored,
1090 EntityWrapperPtr theMirrorLine)
1092 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1094 std::shared_ptr<GeomAPI_Lin2d> aMirrorLine = aBuilder->line(theMirrorLine);
1095 std::shared_ptr<GeomAPI_Dir2d> aMLDir = aMirrorLine->direction();
1096 // orthogonal direction
1097 aMLDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aMLDir->y(), -aMLDir->x()));
1099 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(theOriginal);
1100 std::shared_ptr<GeomAPI_XY> aVec = aPoint->xy()->decreased(aMirrorLine->location()->xy());
1101 double aDist = aVec->dot(aMLDir->xy());
1102 aVec = aPoint->xy()->added(aMLDir->xy()->multiplied(-2.0 * aDist));
1103 double aCoord[2] = {aVec->x(), aVec->y()};
1104 std::list<ParameterWrapperPtr>::const_iterator aMIt = theMirrored->parameters().begin();
1105 for (int i = 0; aMIt != theMirrored->parameters().end(); ++aMIt, ++i)
1106 (*aMIt)->setValue(aCoord[i]);
1108 // update corresponding attribute
1109 AttributePtr anAttr = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theMirrored)->baseAttribute();
1111 std::shared_ptr<GeomDataAPI_Point2D> aMirroredPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
1112 aMirroredPnt->setValue(aCoord[0], aCoord[1]);