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);
138 /// \brief Update positions of rotated features
139 static void adjustMultiRotation(ConstraintWrapperPtr theConstraint);
140 /// \brief Update positions of translated features
141 static void adjustMultiTranslation(ConstraintWrapperPtr theConstraint);
143 /// \brief Transform points to be symmetric regarding to the mirror line
144 static void makeMirrorPoints(EntityWrapperPtr theOriginal,
145 EntityWrapperPtr theMirrored,
146 EntityWrapperPtr theMirrorLine);
150 // Initialization of constraint builder self pointer
151 BuilderPtr PlaneGCSSolver_Builder::mySelf = PlaneGCSSolver_Builder::getInstance();
153 BuilderPtr PlaneGCSSolver_Builder::getInstance()
156 mySelf = BuilderPtr(new PlaneGCSSolver_Builder);
157 SketchSolver_Manager::instance()->setBuilder(mySelf);
162 StoragePtr PlaneGCSSolver_Builder::createStorage(const GroupID& theGroup) const
164 return StoragePtr(new PlaneGCSSolver_Storage(theGroup));
167 SolverPtr PlaneGCSSolver_Builder::createSolver() const
169 return SolverPtr(new PlaneGCSSolver_Solver);
173 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
174 ConstraintPtr theConstraint,
175 const GroupID& theGroupID,
176 const EntityID& theSketchID,
177 const SketchSolver_ConstraintType& theType,
178 const double& theValue,
179 const EntityWrapperPtr& thePoint1,
180 const EntityWrapperPtr& thePoint2,
181 const EntityWrapperPtr& theEntity1,
182 const EntityWrapperPtr& theEntity2) const
184 ConstraintWrapperPtr aResult;
185 ParameterWrapperPtr anIntermediate;
187 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(thePoint1);
188 if (!aPoint1 && thePoint1 && thePoint1->type() == ENTITY_POINT)
189 aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint1)->subEntities().front() );
190 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(thePoint2);
191 if (!aPoint2 && thePoint2 && thePoint2->type() == ENTITY_POINT)
192 aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint2)->subEntities().front() );
195 case CONSTRAINT_PT_PT_COINCIDENT:
196 aResult = createConstraintCoincidence(theConstraint, theGroupID, aPoint1, aPoint2);
198 case CONSTRAINT_PT_ON_LINE:
199 case CONSTRAINT_PT_ON_CIRCLE:
200 aResult = createConstraintPointOnEntity(theConstraint, theGroupID, theType,
201 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
203 case CONSTRAINT_PT_PT_DISTANCE:
204 aResult = createConstraintDistancePointPoint(theConstraint, theGroupID,
205 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
208 case CONSTRAINT_PT_LINE_DISTANCE:
209 aResult = createConstraintDistancePointLine(theConstraint, theGroupID,
210 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
211 aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
213 case CONSTRAINT_RADIUS:
214 aResult = createConstraintRadius(theConstraint, theGroupID,
215 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
216 GCS_ENTITY_WRAPPER(theEntity1));
218 case CONSTRAINT_ANGLE:
219 aResult = createConstraintAngle(theConstraint, theGroupID,
220 GCS_PARAMETER_WRAPPER(createParamAngle(GID_OUTOFGROUP, theValue)),
221 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
223 case CONSTRAINT_FIXED:
225 case CONSTRAINT_HORIZONTAL:
226 case CONSTRAINT_VERTICAL:
227 aResult = createConstraintHorizVert(theConstraint, theGroupID, theType,
228 GCS_ENTITY_WRAPPER(theEntity1));
230 case CONSTRAINT_PARALLEL:
231 aResult = createConstraintParallel(theConstraint, theGroupID,
232 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
234 case CONSTRAINT_PERPENDICULAR:
235 aResult = createConstraintPerpendicular(theConstraint, theGroupID,
236 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
238 case CONSTRAINT_EQUAL_LINES:
239 anIntermediate = createParameter(theGroupID);
240 case CONSTRAINT_EQUAL_LINE_ARC:
241 case CONSTRAINT_EQUAL_RADIUS:
242 aResult = createConstraintEqual(theConstraint, theGroupID, theType,
243 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2),
244 GCS_PARAMETER_WRAPPER(anIntermediate));
246 case CONSTRAINT_TANGENT_ARC_LINE:
247 case CONSTRAINT_TANGENT_ARC_ARC:
248 aResult = createConstraintTangent(theConstraint, theGroupID, theType,
249 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
251 case CONSTRAINT_MULTI_TRANSLATION:
252 case CONSTRAINT_MULTI_ROTATION:
254 case CONSTRAINT_SYMMETRIC:
255 return createMirror(theConstraint, theGroupID, theSketchID,
256 thePoint1, thePoint2, theEntity1);
262 return std::list<ConstraintWrapperPtr>();
263 adjustConstraint(aResult);
264 return std::list<ConstraintWrapperPtr>(1, aResult);
267 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
268 ConstraintPtr theConstraint,
269 const GroupID& theGroupID,
270 const EntityID& theSketchID,
271 const SketchSolver_ConstraintType& theType,
272 const double& theValue,
273 const bool theFullValue,
274 const EntityWrapperPtr& thePoint1,
275 const EntityWrapperPtr& thePoint2,
276 const std::list<EntityWrapperPtr>& theTrsfEnt) const
278 ParameterWrapperPtr anAngleParam;
279 if (theType == CONSTRAINT_MULTI_ROTATION)
280 anAngleParam = createParamAngle(theGroupID, theValue);
281 else if (theType != CONSTRAINT_MULTI_TRANSLATION)
282 return std::list<ConstraintWrapperPtr>();
284 std::list<EntityWrapperPtr> aConstrAttrList = theTrsfEnt;
286 aConstrAttrList.push_front(thePoint2);
287 aConstrAttrList.push_front(thePoint1);
289 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
290 new PlaneGCSSolver_ConstraintWrapper(theConstraint, std::list<GCSConstraintPtr>(), theType));
291 aResult->setGroup(theGroupID);
292 aResult->setEntities(aConstrAttrList);
294 aResult->setValueParameter(anAngleParam);
295 aResult->setIsFullValue(theFullValue);
296 return std::list<ConstraintWrapperPtr>(1, aResult);
300 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createMirror(
301 ConstraintPtr theConstraint,
302 const GroupID& theGroupID,
303 const EntityID& theSketchID,
304 const EntityWrapperPtr& theEntity1,
305 const EntityWrapperPtr& theEntity2,
306 const EntityWrapperPtr& theMirrorLine) const
308 std::list<ConstraintWrapperPtr> aResult;
309 std::list<EntityWrapperPtr> aConstrAttrList;
310 if (theEntity1->type() == ENTITY_POINT) {
311 if (theEntity2->group() == theGroupID) // theEntity2 is not fixed
312 makeMirrorPoints(theEntity1, theEntity2, theMirrorLine);
314 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(theEntity1);
315 if (!aPoint1 && theEntity1->type() == ENTITY_POINT)
316 aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity1)->subEntities().front() );
317 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(theEntity2);
318 if (!aPoint2 && theEntity2->type() == ENTITY_POINT)
319 aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity2)->subEntities().front() );
321 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aMirrorLine =
322 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMirrorLine);
323 std::shared_ptr<GCS::Line> aLine =
324 std::dynamic_pointer_cast<GCS::Line>(aMirrorLine->entity());
326 std::list<GCSConstraintPtr> aConstrList;
327 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
328 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
329 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintMidpointOnLine(
330 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
332 ConstraintWrapperPtr aSubResult(new PlaneGCSSolver_ConstraintWrapper(
333 theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
334 aSubResult->setGroup(theGroupID);
335 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
336 aSubs.push_back(theEntity2);
337 aSubs.push_back(theMirrorLine);
338 aSubResult->setEntities(aSubs);
339 aResult.push_back(aSubResult);
341 else if (theEntity1->type() == ENTITY_LINE) {
342 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
343 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
344 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
345 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
346 for (; anIt1 != aPoints1.end() && anIt2 != aPoints2.end(); ++anIt1, ++anIt2) {
347 std::list<ConstraintWrapperPtr> aMrrList =
348 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
349 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
352 else if (theEntity1->type() == ENTITY_CIRCLE) {
353 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
354 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
355 for (; anIt1 != aPoints1.end(); ++anIt1)
356 if ((*anIt1)->type() == ENTITY_POINT)
358 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
359 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
360 for (; anIt2 != aPoints2.end(); ++anIt2)
361 if ((*anIt2)->type() == ENTITY_POINT)
364 std::list<ConstraintWrapperPtr> aMrrList =
365 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
366 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
368 // Additional constraint for equal radii
369 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
370 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
371 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
373 else if (theEntity1->type() == ENTITY_ARC) {
374 // Do not allow mirrored arc recalculate its position until coordinated of all points recalculated
375 FeaturePtr aMirrArc = theEntity2->baseFeature();
376 aMirrArc->data()->blockSendAttributeUpdated(true);
378 // Make mirror for center and start point of original arc
379 std::list<ConstraintWrapperPtr> aMrrList;
380 std::list<EntityWrapperPtr>::const_iterator anIt1 = theEntity1->subEntities().begin();
381 std::list<EntityWrapperPtr>::const_iterator anIt2 = theEntity2->subEntities().begin();
382 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
383 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
387 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
388 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
390 // make symmetric last point of original arc and first point of mirrored arc without additional constraint
393 makeMirrorPoints(*anIt1, *anIt2, theMirrorLine);
395 // Additionally, make equal radii...
396 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
397 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
398 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
399 // ... and make parametric length of arcs the same
400 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt1 =
401 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity1);
402 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt2 =
403 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity2);
404 std::shared_ptr<GCS::Arc> anArc1 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt1->entity());
405 std::shared_ptr<GCS::Arc> anArc2 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt2->entity());
406 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> anIntermed =
407 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(
408 createParameter(theGroupID, *(anArc1->endAngle) - *(anArc1->startAngle)));
409 // By the way, recalculate start and end angles of mirrored arc
410 std::shared_ptr<GeomAPI_Dir2d> anOX(new GeomAPI_Dir2d(1.0, 0.0));
411 std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(
412 *(anArc2->start.x) - *(anArc2->center.x), *(anArc2->start.y) - *(anArc2->center.y)));
413 std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(
414 *(anArc2->end.x) - *(anArc2->center.x), *(anArc2->end.y) - *(anArc2->center.y)));
415 *anArc2->startAngle = anOX->angle(aStartDir);
416 *anArc2->endAngle = anOX->angle(aEndDir);
418 std::list<GCSConstraintPtr> aConstrList;
419 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
420 anArc1->endAngle, anArc1->startAngle, anIntermed->parameter())));
421 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
422 anArc2->endAngle, anArc2->startAngle, anIntermed->parameter())));
424 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aSubResult(
425 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
426 aSubResult->setGroup(theGroupID);
427 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
428 aSubs.push_back(theEntity2);
429 aSubs.push_back(theMirrorLine);
430 aSubResult->setEntities(aSubs);
431 aSubResult->setValueParameter(anIntermed);
432 aResult.push_back(aSubResult);
434 // Restore event sending
435 aMirrArc->data()->blockSendAttributeUpdated(false);
440 void PlaneGCSSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstraint) const
442 SketchSolver_ConstraintType aType = theConstraint->type();
443 // Update flags and parameters in constraints
444 if (aType == CONSTRAINT_ANGLE)
445 adjustAngle(theConstraint);
446 //else if (aType == CONSTRAINT_SYMMETRIC)
447 // adjustMirror(theConstraint);
448 else if (aType == CONSTRAINT_MULTI_ROTATION)
449 adjustMultiRotation(theConstraint);
450 else if (aType == CONSTRAINT_MULTI_TRANSLATION)
451 adjustMultiTranslation(theConstraint);
454 EntityWrapperPtr PlaneGCSSolver_Builder::createFeature(
455 FeaturePtr theFeature,
456 const std::list<EntityWrapperPtr>& theAttributes,
457 const GroupID& theGroupID,
458 const EntityID& /*theSketchID*/) const
460 static EntityWrapperPtr aDummy;
461 if (!theFeature->data()->isValid())
465 CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
467 return createSketchEntity(aSketch, theGroupID);
469 // SketchPlugin features
470 std::shared_ptr<SketchPlugin_Feature> aFeature =
471 std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
475 // Verify the feature by its kind
476 const std::string& aFeatureKind = aFeature->getKind();
478 if (aFeatureKind == SketchPlugin_Line::ID())
479 return createLine(theFeature, theAttributes, theGroupID);
481 else if (aFeatureKind == SketchPlugin_Circle::ID())
482 return createCircle(theFeature, theAttributes, theGroupID);
484 else if (aFeatureKind == SketchPlugin_Arc::ID())
485 return createArc(theFeature, theAttributes, theGroupID);
486 // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
487 else if (aFeatureKind == SketchPlugin_Point::ID()) {
488 EntityWrapperPtr aSub;
489 if (theAttributes.size() == 1)
490 aSub = theAttributes.front();
492 AttributePtr aPoint = theFeature->attribute(SketchPlugin_Point::COORD_ID());
493 if (aPoint->isInitialized())
494 aSub = createAttribute(aPoint, theGroupID);
499 GCSPointPtr aSubEnt =
500 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aSub)->point();
501 EntityWrapperPtr aNewEntity(new PlaneGCSSolver_EntityWrapper(theFeature));
502 aNewEntity->setSubEntities(std::list<EntityWrapperPtr>(1, aSub));
510 EntityWrapperPtr PlaneGCSSolver_Builder::createAttribute(
511 AttributePtr theAttribute,
512 const GroupID& theGroupID,
513 const EntityID& theSketchID) const
515 AttributePtr anAttribute = theAttribute;
516 AttributeRefAttrPtr aRefAttr =
517 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
519 if (aRefAttr->isObject()) {
520 // do not create features here
521 return EntityWrapperPtr();
523 anAttribute = aRefAttr->attr();
526 std::list<ParameterWrapperPtr> aParameters;
527 EntityWrapperPtr aResult;
530 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
531 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
533 aParameters.push_back(::createParameter(theGroupID, aPoint2D->x(), !aPoint2D->textX().empty()));
534 aParameters.push_back(::createParameter(theGroupID, aPoint2D->y(), !aPoint2D->textY().empty()));
535 GCSPointPtr aGCSPoint(new GCS::Point);
536 aGCSPoint->x = std::dynamic_pointer_cast<
537 PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
538 aGCSPoint->y = std::dynamic_pointer_cast<
539 PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
540 // Create entity (parameters are not filled)
541 aResult = EntityWrapperPtr(new PlaneGCSSolver_PointWrapper(theAttribute, aGCSPoint));
543 // Scalar value (used for the distance entities)
544 AttributeDoublePtr aScalar =
545 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
547 return createScalar(theGroupID, aScalar);
551 // unknown attribute type
552 return EntityWrapperPtr();
555 aResult->setGroup(theGroupID);
556 aResult->setParameters(aParameters);
560 ParameterWrapperPtr PlaneGCSSolver_Builder::createParameter(
561 const GroupID& theGroupID, double theValue) const
563 return ::createParameter(theGroupID, theValue);
567 EntityWrapperPtr PlaneGCSSolver_Builder::createSketchEntity(
568 CompositeFeaturePtr theSketch,
569 const GroupID& theGroupID) const
571 DataPtr aSketchData = theSketch->data();
572 if (!aSketchData || !aSketchData->isValid())
573 return EntityWrapperPtr(); // the sketch is incorrect
575 // Create dummy wrapper representing workplane
576 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aSketchEnt(
577 new PlaneGCSSolver_EntityWrapper(FeaturePtr(theSketch)));
578 aSketchEnt->setGroup(theGroupID);
579 aSketchEnt->setId(EID_SKETCH);
587 // ================ Auxiliary functions ==========================
588 ParameterWrapperPtr createParameter(
589 const GroupID& theGroup, const double theValue, const bool theExpr)
591 double* aParam = new double(theValue);
592 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_ParameterWrapper(aParam));
593 aWrapper->setGroup(theGroup);
594 aWrapper->setIsParametric(theExpr);
598 ParameterWrapperPtr createParamAngle(const GroupID& theGroup, const double& theValue)
600 double* aParam = new double(theValue);
601 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_AngleWrapper(aParam));
602 aWrapper->setGroup(theGroup);
606 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> createScalar(
607 const GroupID& theGroupID,
608 AttributeDoublePtr theDoubleAttr)
610 ParameterWrapperPtr aParam = createParameter(theGroupID, theDoubleAttr ? theDoubleAttr->value() : 0.0);
611 return std::shared_ptr<PlaneGCSSolver_ScalarWrapper>(
612 new PlaneGCSSolver_ScalarWrapper(theDoubleAttr, aParam));
615 EntityWrapperPtr createLine(FeaturePtr theFeature,
616 const std::list<EntityWrapperPtr>& theAttributes,
617 const GroupID& theGroupID)
619 EntityWrapperPtr aNewEntity;
620 std::list<EntityWrapperPtr> aSubs;
622 AttributePtr aStart = theFeature->attribute(SketchPlugin_Line::START_ID());
623 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Line::END_ID());
624 if (!aStart->isInitialized() || !aEnd->isInitialized())
627 std::shared_ptr<PlaneGCSSolver_PointWrapper> aStartEnt, aEndEnt;
628 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
629 for (; anIt != theAttributes.end(); ++anIt) {
630 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
631 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
634 if (aWrapper->isBase(aStart))
635 aStartEnt = aWrapper;
636 else if (aWrapper->isBase(aEnd))
639 if (!aStartEnt || !aEndEnt)
642 aSubs.push_back(aStartEnt);
643 aSubs.push_back(aEndEnt);
645 std::shared_ptr<GCS::Line> aLine(new GCS::Line);
646 aLine->p1 = *(aStartEnt->point());
647 aLine->p2 = *(aEndEnt->point());
649 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aLine));
650 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
651 aNewEntity->setSubEntities(aSubs);
655 EntityWrapperPtr createCircle(FeaturePtr theFeature,
656 const std::list<EntityWrapperPtr>& theAttributes,
657 const GroupID& theGroupID)
659 EntityWrapperPtr aNewEntity;
660 std::list<EntityWrapperPtr> aSubs;
662 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Circle::CENTER_ID());
663 AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
664 if (!aCenter->isInitialized() || !aRadius->isInitialized())
667 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt;
668 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aRadiusEnt;
669 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
670 for (; anIt != theAttributes.end(); ++anIt) {
671 if ((*anIt)->isBase(aCenter))
672 aCenterEnt = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
673 else if ((*anIt)->isBase(aRadius))
674 aRadiusEnt = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*anIt);
676 if (!aCenterEnt || !aRadiusEnt)
679 aSubs.push_back(aCenterEnt);
680 aSubs.push_back(aRadiusEnt);
682 std::shared_ptr<GCS::Circle> aCircle(new GCS::Circle);
683 aCircle->center = *(aCenterEnt->point());
684 aCircle->rad = aRadiusEnt->scalar();
686 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aCircle));
687 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
688 aNewEntity->setSubEntities(aSubs);
692 EntityWrapperPtr createArc(FeaturePtr theFeature,
693 const std::list<EntityWrapperPtr>& theAttributes,
694 const GroupID& theGroupID)
696 EntityWrapperPtr aNewEntity;
697 std::list<EntityWrapperPtr> aSubs;
699 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Arc::CENTER_ID());
700 AttributePtr aStart = theFeature->attribute(SketchPlugin_Arc::START_ID());
701 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Arc::END_ID());
702 if (!aCenter->isInitialized() || !aStart->isInitialized() || !aEnd->isInitialized())
705 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt, aStartEnt, aEndEnt;
706 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
707 for (; anIt != theAttributes.end(); ++anIt) {
708 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
709 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
712 if (aWrapper->isBase(aCenter))
713 aCenterEnt = aWrapper;
714 else if (aWrapper->isBase(aStart))
715 aStartEnt = aWrapper;
716 else if (aWrapper->isBase(aEnd))
719 if (!aCenterEnt || !aStartEnt || !aEndEnt)
722 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aStartAng, aEndAng, aRadius;
723 aStartAng = createScalar(theGroupID);
724 aEndAng = createScalar(theGroupID);
725 aRadius = createScalar(theGroupID);
727 aSubs.push_back(aCenterEnt);
728 aSubs.push_back(aStartEnt);
729 aSubs.push_back(aEndEnt);
730 aSubs.push_back(aStartAng);
731 aSubs.push_back(aEndAng);
732 aSubs.push_back(aRadius);
734 std::shared_ptr<GCS::Arc> anArc(new GCS::Arc);
735 anArc->center = *(aCenterEnt->point());
736 anArc->start = *(aStartEnt->point());
737 anArc->end = *(aEndEnt->point());
738 anArc->startAngle = aStartAng->scalar();
739 anArc->endAngle = aEndAng->scalar();
740 anArc->rad = aRadius->scalar();
742 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, anArc));
743 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
744 aNewEntity->setSubEntities(aSubs);
750 ConstraintWrapperPtr createConstraintCoincidence(
751 ConstraintPtr theConstraint,
752 const GroupID& theGroupID,
753 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
754 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
756 // Create equality constraint for corresponding attributes of the points
757 std::list<GCSConstraintPtr> aConstrList;
758 std::list<ParameterWrapperPtr>::const_iterator anIt1 = thePoint1->parameters().begin();
759 std::list<ParameterWrapperPtr>::const_iterator anIt2 = thePoint2->parameters().begin();
760 for (; anIt1 != thePoint1->parameters().end(); ++anIt1, ++anIt2) {
761 if (*anIt1 == *anIt2)
762 continue; // points use same parameters, no need additional constraints
763 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam1 =
764 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt1);
765 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam2 =
766 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt2);
767 aConstrList.push_back(
768 GCSConstraintPtr(new GCS::ConstraintEqual(aParam1->parameter(), aParam2->parameter())));
771 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
772 theConstraint, aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
773 aResult->setGroup(theGroupID);
774 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
775 aSubs.push_back(thePoint2);
776 aResult->setEntities(aSubs);
780 ConstraintWrapperPtr createConstraintPointOnEntity(
781 ConstraintPtr theConstraint,
782 const GroupID& theGroupID,
783 const SketchSolver_ConstraintType& theType,
784 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
785 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
787 GCSConstraintPtr aNewConstr;
789 switch (theEntity->type()) {
791 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
792 aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnLine(*(thePoint->point()), *aLine));
796 case ENTITY_CIRCLE: {
797 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
798 aNewConstr = GCSConstraintPtr(
799 new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
803 return ConstraintWrapperPtr();
806 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
807 theConstraint, aNewConstr, theType));
808 aResult->setGroup(theGroupID);
809 std::list<EntityWrapperPtr> aSubs(1, thePoint);
810 aSubs.push_back(theEntity);
811 aResult->setEntities(aSubs);
815 ConstraintWrapperPtr createConstraintDistancePointPoint(
816 ConstraintPtr theConstraint,
817 const GroupID& theGroupID,
818 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
819 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
820 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
822 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
823 *(thePoint1->point()), *(thePoint2->point()), theValue->parameter()));
825 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
826 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
827 aResult->setGroup(theGroupID);
828 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
829 aSubs.push_back(thePoint2);
830 aResult->setEntities(aSubs);
831 aResult->setValueParameter(theValue);
835 ConstraintWrapperPtr createConstraintDistancePointLine(
836 ConstraintPtr theConstraint,
837 const GroupID& theGroupID,
838 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
839 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
840 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
842 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
843 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
844 *(thePoint->point()), *(aLine), theValue->parameter()));
846 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
847 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
848 aResult->setGroup(theGroupID);
849 std::list<EntityWrapperPtr> aSubs(1, thePoint);
850 aSubs.push_back(theEntity);
851 aResult->setEntities(aSubs);
852 aResult->setValueParameter(theValue);
856 ConstraintWrapperPtr createConstraintRadius(
857 ConstraintPtr theConstraint,
858 const GroupID& theGroupID,
859 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
860 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
862 std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
863 GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->parameter()));
865 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
866 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_RADIUS));
867 aResult->setGroup(theGroupID);
868 std::list<EntityWrapperPtr> aSubs(1, theEntity);
869 aResult->setEntities(aSubs);
870 aResult->setValueParameter(theValue);
874 ConstraintWrapperPtr createConstraintAngle(
875 ConstraintPtr theConstraint,
876 const GroupID& theGroupID,
877 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
878 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
879 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
881 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
882 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
883 GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
884 *(aLine1), *(aLine2), theValue->parameter()));
886 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
887 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_ANGLE));
888 aResult->setGroup(theGroupID);
889 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
890 aSubs.push_back(theEntity2);
891 aResult->setEntities(aSubs);
892 aResult->setValueParameter(theValue);
896 ConstraintWrapperPtr createConstraintHorizVert(
897 ConstraintPtr theConstraint,
898 const GroupID& theGroupID,
899 const SketchSolver_ConstraintType& theType,
900 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
902 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
903 GCSConstraintPtr aNewConstr;
904 if (theType == CONSTRAINT_HORIZONTAL)
905 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.y, aLine->p2.y));
907 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
909 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
910 theConstraint, aNewConstr, theType));
911 aResult->setGroup(theGroupID);
912 std::list<EntityWrapperPtr> aSubs(1, theEntity);
913 aResult->setEntities(aSubs);
917 ConstraintWrapperPtr createConstraintParallel(
918 ConstraintPtr theConstraint,
919 const GroupID& theGroupID,
920 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
921 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
923 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
924 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
925 GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
927 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
928 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PARALLEL));
929 aResult->setGroup(theGroupID);
930 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
931 aSubs.push_back(theEntity2);
932 aResult->setEntities(aSubs);
936 ConstraintWrapperPtr createConstraintPerpendicular(
937 ConstraintPtr theConstraint,
938 const GroupID& theGroupID,
939 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
940 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
942 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
943 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
944 GCSConstraintPtr aNewConstr(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
946 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
947 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PERPENDICULAR));
948 aResult->setGroup(theGroupID);
949 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
950 aSubs.push_back(theEntity2);
951 aResult->setEntities(aSubs);
955 ConstraintWrapperPtr createConstraintEqual(
956 ConstraintPtr theConstraint,
957 const GroupID& theGroupID,
958 const SketchSolver_ConstraintType& theType,
959 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
960 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
961 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed)
963 if (theType == CONSTRAINT_EQUAL_LINE_ARC)
964 return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
966 std::list<GCSConstraintPtr> aConstrList;
967 if (theType == CONSTRAINT_EQUAL_LINES) {
968 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
969 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
971 aConstrList.push_back(GCSConstraintPtr(
972 new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->parameter())));
973 aConstrList.push_back(GCSConstraintPtr(
974 new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->parameter())));
976 std::shared_ptr<GCS::Circle> aCirc1 =
977 std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
978 std::shared_ptr<GCS::Circle> aCirc2 =
979 std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
981 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
984 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
985 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, theType));
986 aResult->setGroup(theGroupID);
987 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
988 aSubs.push_back(theEntity2);
989 aResult->setEntities(aSubs);
991 aResult->setValueParameter(theIntermed);
995 ConstraintWrapperPtr createConstraintTangent(
996 ConstraintPtr theConstraint,
997 const GroupID& theGroupID,
998 const SketchSolver_ConstraintType& theType,
999 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1000 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
1002 GCSConstraintPtr aNewConstr;
1003 if (theType == CONSTRAINT_TANGENT_ARC_LINE) {
1004 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1005 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1007 aNewConstr = GCSConstraintPtr(new GCS::ConstraintP2LDistance(aCirc->center, *aLine, aCirc->rad));
1009 std::shared_ptr<GCS::Circle> aCirc1 = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1010 std::shared_ptr<GCS::Circle> aCirc2 = std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
1012 double aDX = *(aCirc1->center.x) - *(aCirc2->center.x);
1013 double aDY = *(aCirc1->center.y) - *(aCirc2->center.y);
1014 double aDist = sqrt(aDX * aDX + aDY * aDY);
1015 aNewConstr = GCSConstraintPtr(new GCS::ConstraintTangentCircumf(aCirc1->center, aCirc2->center,
1016 aCirc1->rad, aCirc2->rad, (aDist < *(aCirc1->rad) || aDist < *(aCirc2->rad))));
1019 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1020 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, theType));
1021 aResult->setGroup(theGroupID);
1022 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1023 aSubs.push_back(theEntity2);
1024 aResult->setEntities(aSubs);
1032 void adjustAngle(ConstraintWrapperPtr theConstraint)
1034 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1036 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
1037 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
1039 std::shared_ptr<GeomAPI_Pnt2d> aPoints[2][2]; // start and end points of lines
1040 const std::list<EntityWrapperPtr>& aConstrLines = aConstraint->entities();
1041 std::list<EntityWrapperPtr>::const_iterator aCLIt = aConstrLines.begin();
1042 for (int i = 0; aCLIt != aConstrLines.end(); ++i, ++aCLIt) {
1043 const std::list<EntityWrapperPtr>& aLinePoints = (*aCLIt)->subEntities();
1044 std::list<EntityWrapperPtr>::const_iterator aLPIt = aLinePoints.begin();
1045 for (int j = 0; aLPIt != aLinePoints.end(); ++j, ++aLPIt)
1046 aPoints[i][j] = aBuilder->point(*aLPIt);
1049 std::shared_ptr<GeomAPI_Lin2d> aLine[2] = {
1050 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[0][0], aPoints[0][1])),
1051 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[1][0], aPoints[1][1]))
1053 std::shared_ptr<GeomAPI_Pnt2d> anIntersection = aLine[0]->intersect(aLine[1]);
1054 if (!anIntersection)
1057 for (int i = 0; i < 2; i++) {
1058 for (int j = 0; j < 2; j++) {
1059 aDist[i][j] = anIntersection->distance(aPoints[i][j]);
1060 if (fabs(aDist[i][j]) <= tolerance)
1063 if (aDist[i][0] > tolerance && aDist[i][1] > tolerance &&
1064 aDist[i][0] + aDist[i][1] < aPoints[i][0]->distance(aPoints[i][1]) + 2.0 * tolerance) {
1065 // the intersection point is an inner point of the line,
1066 // we change the sign of distance till start point to calculate correct coordinates
1068 aDist[i][0] *= -1.0;
1071 std::shared_ptr<GeomAPI_Dir2d> aDir[2];
1072 for (int i = 0; i < 2; i++) {
1073 if (aDist[i][1] > fabs(aDist[i][0]))
1074 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1075 aPoints[i][1]->xy()->decreased(anIntersection->xy())));
1077 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1078 aPoints[i][0]->xy()->decreased(anIntersection->xy())));
1079 // main direction is opposite => change signs
1080 if (aDist[i][0] < 0.0) {
1081 aDist[i][0] *= -1.0;
1082 aDist[i][1] *= -1.0;
1087 double anAngle = aLine[0]->direction()->angle(aLine[1]->direction()) / PI * 180;
1088 if (anAngle * aConstraint->value() < 0.0)
1089 aConstraint->setValue(-aConstraint->value());
1090 if ((90.0 - fabs(anAngle)) * (fabs(aConstraint->value()) - 90.0) > 0.0) {
1091 if (aConstraint->value() < 0.0)
1092 aConstraint->setValue(-180.0 - aConstraint->value());
1094 aConstraint->setValue(180.0 - aConstraint->value());
1098 ////void adjustMirror(ConstraintWrapperPtr theConstraint)
1100 //// std::vector<EntityWrapperPtr> aPoints;
1101 //// EntityWrapperPtr aMirrorLine;
1103 //// const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
1104 //// std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
1105 //// for (; anIt != aSubs.end(); ++anIt) {
1106 //// if ((*anIt)->type() == ENTITY_POINT)
1107 //// aPoints.push_back(*anIt);
1108 //// else if ((*anIt)->type() == ENTITY_LINE)
1109 //// aMirrorLine = *anIt;
1112 //// makeMirrorPoints(aPoints[0], aPoints[1], aMirrorLine);
1115 void makeMirrorPoints(EntityWrapperPtr theOriginal,
1116 EntityWrapperPtr theMirrored,
1117 EntityWrapperPtr theMirrorLine)
1119 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1121 std::shared_ptr<GeomAPI_Lin2d> aMirrorLine = aBuilder->line(theMirrorLine);
1122 std::shared_ptr<GeomAPI_Dir2d> aMLDir = aMirrorLine->direction();
1123 // orthogonal direction
1124 aMLDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aMLDir->y(), -aMLDir->x()));
1126 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(theOriginal);
1127 std::shared_ptr<GeomAPI_XY> aVec = aPoint->xy()->decreased(aMirrorLine->location()->xy());
1128 double aDist = aVec->dot(aMLDir->xy());
1129 aVec = aPoint->xy()->added(aMLDir->xy()->multiplied(-2.0 * aDist));
1130 double aCoord[2] = {aVec->x(), aVec->y()};
1131 std::list<ParameterWrapperPtr>::const_iterator aMIt = theMirrored->parameters().begin();
1132 for (int i = 0; aMIt != theMirrored->parameters().end(); ++aMIt, ++i)
1133 (*aMIt)->setValue(aCoord[i]);
1135 // update corresponding attribute
1136 AttributePtr anAttr = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theMirrored)->baseAttribute();
1138 std::shared_ptr<GeomDataAPI_Point2D> aMirroredPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
1139 aMirroredPnt->setValue(aCoord[0], aCoord[1]);
1143 static void rotate(EntityWrapperPtr theSource, EntityWrapperPtr theDest,
1144 std::shared_ptr<GeomAPI_Pnt2d> theCenter,
1145 double theSin, double theCos)
1147 if (theSource->type() == ENTITY_POINT) {
1148 // Rotate single point
1149 std::shared_ptr<GeomDataAPI_Point2D> aSrcAttr =
1150 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theSource->baseAttribute());
1151 std::shared_ptr<GeomDataAPI_Point2D> aDstAttr =
1152 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theDest->baseAttribute());
1153 if (aSrcAttr && aDstAttr) {
1154 std::shared_ptr<GeomAPI_XY> aVec = aSrcAttr->pnt()->xy()->decreased(theCenter->xy());
1155 double aNewX = aVec->x() * theCos - aVec->y() * theSin;
1156 double aNewY = aVec->x() * theSin + aVec->y() * theCos;
1157 aDstAttr->setValue(theCenter->x() + aNewX, theCenter->y() + aNewY);
1162 FeaturePtr aDestFeature = theDest->baseFeature();
1164 aDestFeature->data()->blockSendAttributeUpdated(true);
1166 // Rotate points of the feature
1167 const std::list<EntityWrapperPtr>& aSrcSubs = theSource->subEntities();
1168 const std::list<EntityWrapperPtr>& aDstSubs = theDest->subEntities();
1169 std::list<EntityWrapperPtr>::const_iterator aSrcIt, aDstIt;
1170 for (aSrcIt = aSrcSubs.begin(), aDstIt = aDstSubs.begin();
1171 aSrcIt != aSrcSubs.end() && aDstIt != aDstSubs.end(); ++aSrcIt, ++aDstIt)
1172 rotate(*aSrcIt, *aDstIt, theCenter, theSin, theCos);
1175 aDestFeature->data()->blockSendAttributeUpdated(false);
1178 static void translate(EntityWrapperPtr theSource, EntityWrapperPtr theDest,
1179 std::shared_ptr<GeomAPI_XY> theDelta)
1181 if (theSource->type() == ENTITY_POINT) {
1182 // Translate single point
1183 std::shared_ptr<GeomDataAPI_Point2D> aSrcAttr =
1184 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theSource->baseAttribute());
1185 std::shared_ptr<GeomDataAPI_Point2D> aDstAttr =
1186 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theDest->baseAttribute());
1187 if (aSrcAttr && aDstAttr)
1188 aDstAttr->setValue(aSrcAttr->x() + theDelta->x(), aSrcAttr->y() + theDelta->y());
1192 FeaturePtr aDestFeature = theDest->baseFeature();
1194 aDestFeature->data()->blockSendAttributeUpdated(true);
1196 // Translate points of the feature
1197 const std::list<EntityWrapperPtr>& aSrcSubs = theSource->subEntities();
1198 const std::list<EntityWrapperPtr>& aDstSubs = theDest->subEntities();
1199 std::list<EntityWrapperPtr>::const_iterator aSrcIt, aDstIt;
1200 for (aSrcIt = aSrcSubs.begin(), aDstIt = aDstSubs.begin();
1201 aSrcIt != aSrcSubs.end() && aDstIt != aDstSubs.end(); ++aSrcIt, ++aDstIt)
1202 translate(*aSrcIt, *aDstIt, theDelta);
1205 aDestFeature->data()->blockSendAttributeUpdated(false);
1208 void adjustMultiRotation(ConstraintWrapperPtr theConstraint)
1210 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1212 double anAngleRad = theConstraint->value() * PI / 180.0;
1213 double aSin = sin(anAngleRad);
1214 double aCos = cos(anAngleRad);
1216 const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
1217 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
1219 std::shared_ptr<GeomAPI_Pnt2d> aCenter = aBuilder->point(*aSIt++);
1220 std::list<EntityWrapperPtr>::const_iterator aPrevIt = aSIt++;
1221 for (; aSIt != aSubs.end(); ++aPrevIt, ++aSIt)
1222 rotate(*aPrevIt, *aSIt, aCenter, aSin, aCos);
1225 void adjustMultiTranslation(ConstraintWrapperPtr theConstraint)
1227 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1229 const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
1230 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
1232 std::shared_ptr<GeomAPI_Pnt2d> aStartPnt = aBuilder->point(*aSIt++);
1233 std::shared_ptr<GeomAPI_Pnt2d> aEndPnt = aBuilder->point(*aSIt++);
1234 std::shared_ptr<GeomAPI_XY> aDelta = aEndPnt->xy()->decreased(aStartPnt->xy());
1236 std::list<EntityWrapperPtr>::const_iterator aPrevIt = aSIt++;
1237 for (; aSIt != aSubs.end(); ++aPrevIt, ++aSIt)
1238 translate(*aPrevIt, *aSIt, aDelta);