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 case CONSTRAINT_PT_PT_COINCIDENT:
188 aResult = createConstraintCoincidence(theConstraint, theGroupID,
189 GCS_POINT_WRAPPER(thePoint1), GCS_POINT_WRAPPER(thePoint2));
191 case CONSTRAINT_PT_ON_LINE:
192 case CONSTRAINT_PT_ON_CIRCLE:
193 aResult = createConstraintPointOnEntity(theConstraint, theGroupID, theType,
194 GCS_POINT_WRAPPER(thePoint1), GCS_ENTITY_WRAPPER(theEntity1));
196 case CONSTRAINT_PT_PT_DISTANCE:
197 aResult = createConstraintDistancePointPoint(theConstraint, theGroupID,
198 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
199 GCS_POINT_WRAPPER(thePoint1), GCS_POINT_WRAPPER(thePoint2));
201 case CONSTRAINT_PT_LINE_DISTANCE:
202 aResult = createConstraintDistancePointLine(theConstraint, theGroupID,
203 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
204 GCS_POINT_WRAPPER(thePoint1), GCS_ENTITY_WRAPPER(theEntity1));
206 case CONSTRAINT_RADIUS:
207 aResult = createConstraintRadius(theConstraint, theGroupID,
208 GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
209 GCS_ENTITY_WRAPPER(theEntity1));
211 case CONSTRAINT_ANGLE:
212 aResult = createConstraintAngle(theConstraint, theGroupID,
213 GCS_PARAMETER_WRAPPER(createParamAngle(GID_OUTOFGROUP, theValue)),
214 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
216 case CONSTRAINT_FIXED:
218 case CONSTRAINT_HORIZONTAL:
219 case CONSTRAINT_VERTICAL:
220 aResult = createConstraintHorizVert(theConstraint, theGroupID, theType,
221 GCS_ENTITY_WRAPPER(theEntity1));
223 case CONSTRAINT_PARALLEL:
224 aResult = createConstraintParallel(theConstraint, theGroupID,
225 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
227 case CONSTRAINT_PERPENDICULAR:
228 aResult = createConstraintPerpendicular(theConstraint, theGroupID,
229 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
231 case CONSTRAINT_EQUAL_LINES:
232 anIntermediate = createParameter(theGroupID);
233 case CONSTRAINT_EQUAL_LINE_ARC:
234 case CONSTRAINT_EQUAL_RADIUS:
235 aResult = createConstraintEqual(theConstraint, theGroupID, theType,
236 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2),
237 GCS_PARAMETER_WRAPPER(anIntermediate));
239 case CONSTRAINT_TANGENT_ARC_LINE:
240 case CONSTRAINT_TANGENT_ARC_ARC:
241 aResult = createConstraintTangent(theConstraint, theGroupID, theType,
242 GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
244 case CONSTRAINT_MULTI_TRANSLATION:
245 case CONSTRAINT_MULTI_ROTATION:
247 case CONSTRAINT_SYMMETRIC:
248 return createMirror(theConstraint, theGroupID, theSketchID,
249 thePoint1, thePoint2, theEntity1);
255 return std::list<ConstraintWrapperPtr>();
256 adjustConstraint(aResult);
257 return std::list<ConstraintWrapperPtr>(1, aResult);
260 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
261 ConstraintPtr theConstraint,
262 const GroupID& theGroupID,
263 const EntityID& theSketchID,
264 const SketchSolver_ConstraintType& theType,
265 const double& theValue,
266 const bool theFullValue,
267 const EntityWrapperPtr& thePoint1,
268 const EntityWrapperPtr& thePoint2,
269 const std::list<EntityWrapperPtr>& theTrsfEnt) const
271 ParameterWrapperPtr anAngleParam;
272 if (theType == CONSTRAINT_MULTI_ROTATION)
273 anAngleParam = createParamAngle(theGroupID, theValue);
274 else if (theType != CONSTRAINT_MULTI_TRANSLATION)
275 return std::list<ConstraintWrapperPtr>();
277 std::list<EntityWrapperPtr> aConstrAttrList = theTrsfEnt;
279 aConstrAttrList.push_front(thePoint2);
280 aConstrAttrList.push_front(thePoint1);
282 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
283 new PlaneGCSSolver_ConstraintWrapper(theConstraint, std::list<GCSConstraintPtr>(), theType));
284 aResult->setGroup(theGroupID);
285 aResult->setEntities(aConstrAttrList);
287 aResult->setValueParameter(anAngleParam);
288 aResult->setIsFullValue(theFullValue);
289 return std::list<ConstraintWrapperPtr>(1, aResult);
293 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createMirror(
294 ConstraintPtr theConstraint,
295 const GroupID& theGroupID,
296 const EntityID& theSketchID,
297 const EntityWrapperPtr& theEntity1,
298 const EntityWrapperPtr& theEntity2,
299 const EntityWrapperPtr& theMirrorLine) const
301 std::list<ConstraintWrapperPtr> aResult;
302 std::list<EntityWrapperPtr> aConstrAttrList;
303 if (theEntity1->type() == ENTITY_POINT) {
304 if (theEntity2->group() == theGroupID) // theEntity2 is not fixed
305 makeMirrorPoints(theEntity1, theEntity2, theMirrorLine);
307 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 =
308 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity1);
309 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 =
310 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity2);
312 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aMirrorLine =
313 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMirrorLine);
314 std::shared_ptr<GCS::Line> aLine =
315 std::dynamic_pointer_cast<GCS::Line>(aMirrorLine->entity());
317 std::list<GCSConstraintPtr> aConstrList;
318 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
319 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
320 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintMidpointOnLine(
321 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
323 ConstraintWrapperPtr aSubResult(new PlaneGCSSolver_ConstraintWrapper(
324 theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
325 aSubResult->setGroup(theGroupID);
326 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
327 aSubs.push_back(theEntity2);
328 aSubs.push_back(theMirrorLine);
329 aSubResult->setEntities(aSubs);
330 aResult.push_back(aSubResult);
332 else if (theEntity1->type() == ENTITY_LINE) {
333 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
334 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
335 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
336 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
337 for (; anIt1 != aPoints1.end() && anIt2 != aPoints2.end(); ++anIt1, ++anIt2) {
338 std::list<ConstraintWrapperPtr> aMrrList =
339 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
340 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
343 else if (theEntity1->type() == ENTITY_CIRCLE) {
344 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
345 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
346 for (; anIt1 != aPoints1.end(); ++anIt1)
347 if ((*anIt1)->type() == ENTITY_POINT)
349 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
350 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
351 for (; anIt2 != aPoints2.end(); ++anIt2)
352 if ((*anIt2)->type() == ENTITY_POINT)
355 std::list<ConstraintWrapperPtr> aMrrList =
356 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
357 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
359 // Additional constraint for equal radii
360 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
361 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
362 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
364 else if (theEntity1->type() == ENTITY_ARC) {
365 // Do not allow mirrored arc recalculate its position until coordinated of all points recalculated
366 FeaturePtr aMirrArc = theEntity2->baseFeature();
367 aMirrArc->data()->blockSendAttributeUpdated(true);
369 // Make mirror for center and start point of original arc
370 std::list<ConstraintWrapperPtr> aMrrList;
371 std::list<EntityWrapperPtr>::const_iterator anIt1 = theEntity1->subEntities().begin();
372 std::list<EntityWrapperPtr>::const_iterator anIt2 = theEntity2->subEntities().begin();
373 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
374 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
378 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
379 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
381 // make symmetric last point of original arc and first point of mirrored arc without additional constraint
384 makeMirrorPoints(*anIt1, *anIt2, theMirrorLine);
386 // Additionally, make equal radii...
387 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
388 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
389 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
390 // ... and make parametric length of arcs the same
391 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt1 =
392 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity1);
393 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt2 =
394 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity2);
395 std::shared_ptr<GCS::Arc> anArc1 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt1->entity());
396 std::shared_ptr<GCS::Arc> anArc2 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt2->entity());
397 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> anIntermed =
398 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(
399 createParameter(theGroupID, *(anArc1->endAngle) - *(anArc1->startAngle)));
400 // By the way, recalculate start and end angles of mirrored arc
401 std::shared_ptr<GeomAPI_Dir2d> anOX(new GeomAPI_Dir2d(1.0, 0.0));
402 std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(
403 *(anArc2->start.x) - *(anArc2->center.x), *(anArc2->start.y) - *(anArc2->center.y)));
404 std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(
405 *(anArc2->end.x) - *(anArc2->center.x), *(anArc2->end.y) - *(anArc2->center.y)));
406 *anArc2->startAngle = anOX->angle(aStartDir);
407 *anArc2->endAngle = anOX->angle(aEndDir);
409 std::list<GCSConstraintPtr> aConstrList;
410 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
411 anArc1->endAngle, anArc1->startAngle, anIntermed->parameter())));
412 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
413 anArc2->endAngle, anArc2->startAngle, anIntermed->parameter())));
415 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aSubResult(
416 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
417 aSubResult->setGroup(theGroupID);
418 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
419 aSubs.push_back(theEntity2);
420 aSubs.push_back(theMirrorLine);
421 aSubResult->setEntities(aSubs);
422 aSubResult->setValueParameter(anIntermed);
423 aResult.push_back(aSubResult);
425 // Restore event sending
426 aMirrArc->data()->blockSendAttributeUpdated(false);
431 void PlaneGCSSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstraint) const
433 SketchSolver_ConstraintType aType = theConstraint->type();
434 // Update flags and parameters in constraints
435 if (aType == CONSTRAINT_ANGLE)
436 adjustAngle(theConstraint);
437 //// else if (aType == CONSTRAINT_SYMMETRIC)
438 //// adjustMirror(theConstraint);
439 else if (aType == CONSTRAINT_MULTI_ROTATION)
440 adjustMultiRotation(theConstraint);
441 else if (aType == CONSTRAINT_MULTI_TRANSLATION)
442 adjustMultiTranslation(theConstraint);
445 EntityWrapperPtr PlaneGCSSolver_Builder::createFeature(
446 FeaturePtr theFeature,
447 const std::list<EntityWrapperPtr>& theAttributes,
448 const GroupID& theGroupID,
449 const EntityID& /*theSketchID*/) const
451 static EntityWrapperPtr aDummy;
452 if (!theFeature->data()->isValid())
456 CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
458 return createSketchEntity(aSketch, theGroupID);
460 // SketchPlugin features
461 std::shared_ptr<SketchPlugin_Feature> aFeature =
462 std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
466 // Verify the feature by its kind
467 const std::string& aFeatureKind = aFeature->getKind();
469 if (aFeatureKind == SketchPlugin_Line::ID())
470 return createLine(theFeature, theAttributes, theGroupID);
472 else if (aFeatureKind == SketchPlugin_Circle::ID())
473 return createCircle(theFeature, theAttributes, theGroupID);
475 else if (aFeatureKind == SketchPlugin_Arc::ID())
476 return createArc(theFeature, theAttributes, theGroupID);
477 // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
478 else if (aFeatureKind == SketchPlugin_Point::ID()) {
479 AttributePtr aPoint = theFeature->attribute(SketchPlugin_Point::COORD_ID());
480 if (!aPoint->isInitialized())
482 EntityWrapperPtr aSub = createAttribute(aPoint, theGroupID);
486 GCSPointPtr aSubEnt =
487 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aSub)->point();
488 EntityWrapperPtr aNewEntity(new PlaneGCSSolver_EntityWrapper(theFeature));
489 aNewEntity->setSubEntities(std::list<EntityWrapperPtr>(1, aSub));
497 EntityWrapperPtr PlaneGCSSolver_Builder::createAttribute(
498 AttributePtr theAttribute,
499 const GroupID& theGroupID,
500 const EntityID& theSketchID) const
502 AttributePtr anAttribute = theAttribute;
503 AttributeRefAttrPtr aRefAttr =
504 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
506 if (aRefAttr->isObject()) {
507 // do not create features here
508 return EntityWrapperPtr();
510 anAttribute = aRefAttr->attr();
513 std::list<ParameterWrapperPtr> aParameters;
514 EntityWrapperPtr aResult;
517 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
518 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
520 aParameters.push_back(::createParameter(theGroupID, aPoint2D->x(), !aPoint2D->textX().empty()));
521 aParameters.push_back(::createParameter(theGroupID, aPoint2D->y(), !aPoint2D->textY().empty()));
522 GCSPointPtr aGCSPoint(new GCS::Point);
523 aGCSPoint->x = std::dynamic_pointer_cast<
524 PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
525 aGCSPoint->y = std::dynamic_pointer_cast<
526 PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
527 // Create entity (parameters are not filled)
528 aResult = EntityWrapperPtr(new PlaneGCSSolver_PointWrapper(theAttribute, aGCSPoint));
530 // Scalar value (used for the distance entities)
531 AttributeDoublePtr aScalar =
532 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
534 return createScalar(theGroupID, aScalar);
538 // unknown attribute type
539 return EntityWrapperPtr();
542 aResult->setGroup(theGroupID);
543 aResult->setParameters(aParameters);
547 ParameterWrapperPtr PlaneGCSSolver_Builder::createParameter(
548 const GroupID& theGroupID, double theValue) const
550 return ::createParameter(theGroupID, theValue);
554 EntityWrapperPtr PlaneGCSSolver_Builder::createSketchEntity(
555 CompositeFeaturePtr theSketch,
556 const GroupID& theGroupID) const
558 DataPtr aSketchData = theSketch->data();
559 if (!aSketchData || !aSketchData->isValid())
560 return EntityWrapperPtr(); // the sketch is incorrect
562 // Create dummy wrapper representing workplane
563 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aSketchEnt(
564 new PlaneGCSSolver_EntityWrapper(FeaturePtr(theSketch)));
565 aSketchEnt->setGroup(theGroupID);
566 aSketchEnt->setId(EID_SKETCH);
572 ////EntityWrapperPtr PlaneGCSSolver_Builder::createNormal(
573 //// AttributePtr theNormal,
574 //// AttributePtr theDirX,
575 //// const GroupID& theGroupID) const
577 //// std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(theNormal);
578 //// std::shared_ptr<GeomDataAPI_Dir> aDirX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(theDirX);
579 //// if (!aDirX || !aNorm ||
580 //// (fabs(aDirX->x()) + fabs(aDirX->y()) + fabs(aDirX->z()) < tolerance) ||
581 //// !aNorm->isInitialized())
582 //// return EntityWrapperPtr();
583 //// // calculate Y direction
584 //// std::shared_ptr<GeomAPI_Dir> aDirY(new GeomAPI_Dir(aNorm->dir()->cross(aDirX->dir())));
586 //// // quaternion parameters of normal vector
587 //// double qw, qx, qy, qz;
588 //// Slvs_MakeQuaternion(aDirX->x(), aDirX->y(), aDirX->z(), aDirY->x(), aDirY->y(), aDirY->z(), &qw,
590 //// double aNormCoord[4] = { qw, qx, qy, qz };
592 //// // Create parameters of the normal
593 //// std::list<ParameterWrapperPtr> aParameters;
594 //// for (int i = 0; i < 4; i++)
595 //// aParameters.push_back(createParameter(theGroupID, aNormCoord[i]));
597 //// // Create a normal with empty parameters
598 //// Slvs_Entity aNormalEnt = Slvs_MakeNormal3d(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
599 //// SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
600 //// EntityWrapperPtr aNormal(new SolveSpaceSolver_EntityWrapper(theNormal, aNormalEnt));
601 //// aNormal->setParameters(aParameters);
609 // ================ Auxiliary functions ==========================
610 ParameterWrapperPtr createParameter(
611 const GroupID& theGroup, const double theValue, const bool theExpr)
613 double* aParam = new double(theValue);
614 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_ParameterWrapper(aParam));
615 aWrapper->setGroup(theGroup);
616 aWrapper->setIsParametric(theExpr);
620 ParameterWrapperPtr createParamAngle(const GroupID& theGroup, const double& theValue)
622 double* aParam = new double(theValue);
623 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_AngleWrapper(aParam));
624 aWrapper->setGroup(theGroup);
628 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> createScalar(
629 const GroupID& theGroupID,
630 AttributeDoublePtr theDoubleAttr)
632 ParameterWrapperPtr aParam = createParameter(theGroupID, theDoubleAttr ? theDoubleAttr->value() : 0.0);
633 return std::shared_ptr<PlaneGCSSolver_ScalarWrapper>(
634 new PlaneGCSSolver_ScalarWrapper(theDoubleAttr, aParam));
637 EntityWrapperPtr createLine(FeaturePtr theFeature,
638 const std::list<EntityWrapperPtr>& theAttributes,
639 const GroupID& theGroupID)
641 EntityWrapperPtr aNewEntity;
642 std::list<EntityWrapperPtr> aSubs;
644 AttributePtr aStart = theFeature->attribute(SketchPlugin_Line::START_ID());
645 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Line::END_ID());
646 if (!aStart->isInitialized() || !aEnd->isInitialized())
649 std::shared_ptr<PlaneGCSSolver_PointWrapper> aStartEnt, aEndEnt;
650 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
651 for (; anIt != theAttributes.end(); ++anIt) {
652 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
653 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
656 if (aWrapper->isBase(aStart))
657 aStartEnt = aWrapper;
658 else if (aWrapper->isBase(aEnd))
661 if (!aStartEnt || !aEndEnt)
664 aSubs.push_back(aStartEnt);
665 aSubs.push_back(aEndEnt);
667 std::shared_ptr<GCS::Line> aLine(new GCS::Line);
668 aLine->p1 = *(aStartEnt->point());
669 aLine->p2 = *(aEndEnt->point());
671 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aLine));
672 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
673 aNewEntity->setSubEntities(aSubs);
677 EntityWrapperPtr createCircle(FeaturePtr theFeature,
678 const std::list<EntityWrapperPtr>& theAttributes,
679 const GroupID& theGroupID)
681 EntityWrapperPtr aNewEntity;
682 std::list<EntityWrapperPtr> aSubs;
684 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Circle::CENTER_ID());
685 AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
686 if (!aCenter->isInitialized() || !aRadius->isInitialized())
689 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt;
690 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aRadiusEnt;
691 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
692 for (; anIt != theAttributes.end(); ++anIt) {
693 if ((*anIt)->isBase(aCenter))
694 aCenterEnt = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
695 else if ((*anIt)->isBase(aRadius))
696 aRadiusEnt = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*anIt);
698 if (!aCenterEnt || !aRadiusEnt)
701 aSubs.push_back(aCenterEnt);
702 aSubs.push_back(aRadiusEnt);
704 std::shared_ptr<GCS::Circle> aCircle(new GCS::Circle);
705 aCircle->center = *(aCenterEnt->point());
706 aCircle->rad = aRadiusEnt->scalar();
708 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aCircle));
709 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
710 aNewEntity->setSubEntities(aSubs);
714 EntityWrapperPtr createArc(FeaturePtr theFeature,
715 const std::list<EntityWrapperPtr>& theAttributes,
716 const GroupID& theGroupID)
718 EntityWrapperPtr aNewEntity;
719 std::list<EntityWrapperPtr> aSubs;
721 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Arc::CENTER_ID());
722 AttributePtr aStart = theFeature->attribute(SketchPlugin_Arc::START_ID());
723 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Arc::END_ID());
724 if (!aCenter->isInitialized() || !aStart->isInitialized() || !aEnd->isInitialized())
727 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt, aStartEnt, aEndEnt;
728 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
729 for (; anIt != theAttributes.end(); ++anIt) {
730 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
731 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
734 if (aWrapper->isBase(aCenter))
735 aCenterEnt = aWrapper;
736 else if (aWrapper->isBase(aStart))
737 aStartEnt = aWrapper;
738 else if (aWrapper->isBase(aEnd))
741 if (!aCenterEnt || !aStartEnt || !aEndEnt)
744 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aStartAng, aEndAng, aRadius;
745 aStartAng = createScalar(theGroupID);
746 aEndAng = createScalar(theGroupID);
747 aRadius = createScalar(theGroupID);
749 aSubs.push_back(aCenterEnt);
750 aSubs.push_back(aStartEnt);
751 aSubs.push_back(aEndEnt);
752 aSubs.push_back(aStartAng);
753 aSubs.push_back(aEndAng);
754 aSubs.push_back(aRadius);
756 std::shared_ptr<GCS::Arc> anArc(new GCS::Arc);
757 anArc->center = *(aCenterEnt->point());
758 anArc->start = *(aStartEnt->point());
759 anArc->end = *(aEndEnt->point());
760 anArc->startAngle = aStartAng->scalar();
761 anArc->endAngle = aEndAng->scalar();
762 anArc->rad = aRadius->scalar();
764 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, anArc));
765 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
766 aNewEntity->setSubEntities(aSubs);
772 ConstraintWrapperPtr createConstraintCoincidence(
773 ConstraintPtr theConstraint,
774 const GroupID& theGroupID,
775 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
776 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
778 // Create equality constraint for corresponding attributes of the points
779 std::list<GCSConstraintPtr> aConstrList;
780 std::list<ParameterWrapperPtr>::const_iterator anIt1 = thePoint1->parameters().begin();
781 std::list<ParameterWrapperPtr>::const_iterator anIt2 = thePoint2->parameters().begin();
782 for (; anIt1 != thePoint1->parameters().end(); ++anIt1, ++anIt2) {
783 if (*anIt1 == *anIt2)
784 continue; // points use same parameters, no need additional constraints
785 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam1 =
786 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt1);
787 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam2 =
788 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt2);
789 aConstrList.push_back(
790 GCSConstraintPtr(new GCS::ConstraintEqual(aParam1->parameter(), aParam2->parameter())));
793 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
794 theConstraint, aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
795 aResult->setGroup(theGroupID);
796 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
797 aSubs.push_back(thePoint2);
798 aResult->setEntities(aSubs);
802 ConstraintWrapperPtr createConstraintPointOnEntity(
803 ConstraintPtr theConstraint,
804 const GroupID& theGroupID,
805 const SketchSolver_ConstraintType& theType,
806 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
807 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
809 GCSConstraintPtr aNewConstr;
811 switch (theEntity->type()) {
813 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
814 aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnLine(*(thePoint->point()), *aLine));
818 case ENTITY_CIRCLE: {
819 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
820 aNewConstr = GCSConstraintPtr(
821 new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
825 return ConstraintWrapperPtr();
828 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
829 theConstraint, aNewConstr, theType));
830 aResult->setGroup(theGroupID);
831 std::list<EntityWrapperPtr> aSubs(1, thePoint);
832 aSubs.push_back(theEntity);
833 aResult->setEntities(aSubs);
837 ConstraintWrapperPtr createConstraintDistancePointPoint(
838 ConstraintPtr theConstraint,
839 const GroupID& theGroupID,
840 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
841 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
842 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
844 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
845 *(thePoint1->point()), *(thePoint2->point()), theValue->parameter()));
847 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
848 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
849 aResult->setGroup(theGroupID);
850 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
851 aSubs.push_back(thePoint2);
852 aResult->setEntities(aSubs);
853 aResult->setValueParameter(theValue);
857 ConstraintWrapperPtr createConstraintDistancePointLine(
858 ConstraintPtr theConstraint,
859 const GroupID& theGroupID,
860 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
861 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
862 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
864 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
865 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
866 *(thePoint->point()), *(aLine), theValue->parameter()));
868 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
869 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
870 aResult->setGroup(theGroupID);
871 std::list<EntityWrapperPtr> aSubs(1, thePoint);
872 aSubs.push_back(theEntity);
873 aResult->setEntities(aSubs);
874 aResult->setValueParameter(theValue);
878 ConstraintWrapperPtr createConstraintRadius(
879 ConstraintPtr theConstraint,
880 const GroupID& theGroupID,
881 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
882 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
884 std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
885 GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->parameter()));
887 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
888 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_RADIUS));
889 aResult->setGroup(theGroupID);
890 std::list<EntityWrapperPtr> aSubs(1, theEntity);
891 aResult->setEntities(aSubs);
892 aResult->setValueParameter(theValue);
896 ConstraintWrapperPtr createConstraintAngle(
897 ConstraintPtr theConstraint,
898 const GroupID& theGroupID,
899 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
900 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
901 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
903 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
904 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
905 GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
906 *(aLine1), *(aLine2), theValue->parameter()));
908 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
909 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_ANGLE));
910 aResult->setGroup(theGroupID);
911 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
912 aSubs.push_back(theEntity2);
913 aResult->setEntities(aSubs);
914 aResult->setValueParameter(theValue);
918 ConstraintWrapperPtr createConstraintHorizVert(
919 ConstraintPtr theConstraint,
920 const GroupID& theGroupID,
921 const SketchSolver_ConstraintType& theType,
922 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
924 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
925 GCSConstraintPtr aNewConstr;
926 if (theType == CONSTRAINT_HORIZONTAL)
927 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.y, aLine->p2.y));
929 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
931 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
932 theConstraint, aNewConstr, theType));
933 aResult->setGroup(theGroupID);
934 std::list<EntityWrapperPtr> aSubs(1, theEntity);
935 aResult->setEntities(aSubs);
939 ConstraintWrapperPtr createConstraintParallel(
940 ConstraintPtr theConstraint,
941 const GroupID& theGroupID,
942 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
943 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
945 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
946 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
947 GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
949 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
950 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PARALLEL));
951 aResult->setGroup(theGroupID);
952 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
953 aSubs.push_back(theEntity2);
954 aResult->setEntities(aSubs);
958 ConstraintWrapperPtr createConstraintPerpendicular(
959 ConstraintPtr theConstraint,
960 const GroupID& theGroupID,
961 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
962 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
964 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
965 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
966 GCSConstraintPtr aNewConstr(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
968 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
969 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PERPENDICULAR));
970 aResult->setGroup(theGroupID);
971 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
972 aSubs.push_back(theEntity2);
973 aResult->setEntities(aSubs);
977 ConstraintWrapperPtr createConstraintEqual(
978 ConstraintPtr theConstraint,
979 const GroupID& theGroupID,
980 const SketchSolver_ConstraintType& theType,
981 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
982 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
983 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed)
985 if (theType == CONSTRAINT_EQUAL_LINE_ARC)
986 return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
988 std::list<GCSConstraintPtr> aConstrList;
989 if (theType == CONSTRAINT_EQUAL_LINES) {
990 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
991 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
993 aConstrList.push_back(GCSConstraintPtr(
994 new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->parameter())));
995 aConstrList.push_back(GCSConstraintPtr(
996 new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->parameter())));
998 std::shared_ptr<GCS::Circle> aCirc1 =
999 std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1000 std::shared_ptr<GCS::Circle> aCirc2 =
1001 std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
1003 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
1006 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1007 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, theType));
1008 aResult->setGroup(theGroupID);
1009 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1010 aSubs.push_back(theEntity2);
1011 aResult->setEntities(aSubs);
1013 aResult->setValueParameter(theIntermed);
1017 ConstraintWrapperPtr createConstraintTangent(
1018 ConstraintPtr theConstraint,
1019 const GroupID& theGroupID,
1020 const SketchSolver_ConstraintType& theType,
1021 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1022 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
1024 GCSConstraintPtr aNewConstr;
1025 if (theType == CONSTRAINT_TANGENT_ARC_LINE) {
1026 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1027 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1029 aNewConstr = GCSConstraintPtr(new GCS::ConstraintP2LDistance(aCirc->center, *aLine, aCirc->rad));
1031 std::shared_ptr<GCS::Circle> aCirc1 = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1032 std::shared_ptr<GCS::Circle> aCirc2 = std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
1034 double aDX = *(aCirc1->center.x) - *(aCirc2->center.x);
1035 double aDY = *(aCirc1->center.y) - *(aCirc2->center.y);
1036 double aDist = sqrt(aDX * aDX + aDY * aDY);
1037 aNewConstr = GCSConstraintPtr(new GCS::ConstraintTangentCircumf(aCirc1->center, aCirc2->center,
1038 aCirc1->rad, aCirc2->rad, (aDist < *(aCirc1->rad) || aDist < *(aCirc2->rad))));
1041 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1042 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, theType));
1043 aResult->setGroup(theGroupID);
1044 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1045 aSubs.push_back(theEntity2);
1046 aResult->setEntities(aSubs);
1054 void adjustAngle(ConstraintWrapperPtr theConstraint)
1056 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1058 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
1059 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
1061 std::shared_ptr<GeomAPI_Pnt2d> aPoints[2][2]; // start and end points of lines
1062 const std::list<EntityWrapperPtr>& aConstrLines = aConstraint->entities();
1063 std::list<EntityWrapperPtr>::const_iterator aCLIt = aConstrLines.begin();
1064 for (int i = 0; aCLIt != aConstrLines.end(); ++i, ++aCLIt) {
1065 const std::list<EntityWrapperPtr>& aLinePoints = (*aCLIt)->subEntities();
1066 std::list<EntityWrapperPtr>::const_iterator aLPIt = aLinePoints.begin();
1067 for (int j = 0; aLPIt != aLinePoints.end(); ++j, ++aLPIt)
1068 aPoints[i][j] = aBuilder->point(*aLPIt);
1071 std::shared_ptr<GeomAPI_Lin2d> aLine[2] = {
1072 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[0][0], aPoints[0][1])),
1073 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[1][0], aPoints[1][1]))
1075 std::shared_ptr<GeomAPI_Pnt2d> anIntersection = aLine[0]->intersect(aLine[1]);
1076 if (!anIntersection)
1079 for (int i = 0; i < 2; i++) {
1080 for (int j = 0; j < 2; j++) {
1081 aDist[i][j] = anIntersection->distance(aPoints[i][j]);
1082 if (fabs(aDist[i][j]) <= tolerance)
1085 if (aDist[i][0] > tolerance && aDist[i][1] > tolerance &&
1086 aDist[i][0] + aDist[i][1] < aPoints[i][0]->distance(aPoints[i][1]) + 2.0 * tolerance) {
1087 // the intersection point is an inner point of the line,
1088 // we change the sign of distance till start point to calculate correct coordinates
1090 aDist[i][0] *= -1.0;
1093 std::shared_ptr<GeomAPI_Dir2d> aDir[2];
1094 for (int i = 0; i < 2; i++) {
1095 if (aDist[i][1] > fabs(aDist[i][0]))
1096 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1097 aPoints[i][1]->xy()->decreased(anIntersection->xy())));
1099 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1100 aPoints[i][0]->xy()->decreased(anIntersection->xy())));
1101 // main direction is opposite => change signs
1102 if (aDist[i][0] < 0.0) {
1103 aDist[i][0] *= -1.0;
1104 aDist[i][1] *= -1.0;
1109 bool isChange = false;
1110 for (int i = 0; i < 2; i++)
1111 if (aLine[i]->direction()->dot(aDir[i]) < 0.0)
1112 isChange = !isChange;
1114 aConstraint->setValue(180.0 - aConstraint->value());
1117 ////void adjustMirror(ConstraintWrapperPtr theConstraint)
1119 //// std::vector<EntityWrapperPtr> aPoints;
1120 //// EntityWrapperPtr aMirrorLine;
1122 //// const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
1123 //// std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
1124 //// for (; anIt != aSubs.end(); ++anIt) {
1125 //// if ((*anIt)->type() == ENTITY_POINT)
1126 //// aPoints.push_back(*anIt);
1127 //// else if ((*anIt)->type() == ENTITY_LINE)
1128 //// aMirrorLine = *anIt;
1131 //// makeMirrorPoints(aPoints[0], aPoints[1], aMirrorLine);
1134 void makeMirrorPoints(EntityWrapperPtr theOriginal,
1135 EntityWrapperPtr theMirrored,
1136 EntityWrapperPtr theMirrorLine)
1138 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1140 std::shared_ptr<GeomAPI_Lin2d> aMirrorLine = aBuilder->line(theMirrorLine);
1141 std::shared_ptr<GeomAPI_Dir2d> aMLDir = aMirrorLine->direction();
1142 // orthogonal direction
1143 aMLDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aMLDir->y(), -aMLDir->x()));
1145 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(theOriginal);
1146 std::shared_ptr<GeomAPI_XY> aVec = aPoint->xy()->decreased(aMirrorLine->location()->xy());
1147 double aDist = aVec->dot(aMLDir->xy());
1148 aVec = aPoint->xy()->added(aMLDir->xy()->multiplied(-2.0 * aDist));
1149 double aCoord[2] = {aVec->x(), aVec->y()};
1150 std::list<ParameterWrapperPtr>::const_iterator aMIt = theMirrored->parameters().begin();
1151 for (int i = 0; aMIt != theMirrored->parameters().end(); ++aMIt, ++i)
1152 (*aMIt)->setValue(aCoord[i]);
1154 // update corresponding attribute
1155 AttributePtr anAttr = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theMirrored)->baseAttribute();
1157 std::shared_ptr<GeomDataAPI_Point2D> aMirroredPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
1158 aMirroredPnt->setValue(aCoord[0], aCoord[1]);
1162 static void rotate(EntityWrapperPtr theSource, EntityWrapperPtr theDest,
1163 std::shared_ptr<GeomAPI_Pnt2d> theCenter,
1164 double theSin, double theCos)
1166 if (theSource->type() == ENTITY_POINT) {
1167 // Rotate single point
1168 std::shared_ptr<GeomDataAPI_Point2D> aSrcAttr =
1169 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theSource->baseAttribute());
1170 std::shared_ptr<GeomDataAPI_Point2D> aDstAttr =
1171 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theDest->baseAttribute());
1172 if (aSrcAttr && aDstAttr) {
1173 std::shared_ptr<GeomAPI_XY> aVec = aSrcAttr->pnt()->xy()->decreased(theCenter->xy());
1174 double aNewX = aVec->x() * theCos - aVec->y() * theSin;
1175 double aNewY = aVec->x() * theSin + aVec->y() * theCos;
1176 aDstAttr->setValue(theCenter->x() + aNewX, theCenter->y() + aNewY);
1181 FeaturePtr aDestFeature = theDest->baseFeature();
1183 aDestFeature->data()->blockSendAttributeUpdated(true);
1185 // Rotate points of the feature
1186 const std::list<EntityWrapperPtr>& aSrcSubs = theSource->subEntities();
1187 const std::list<EntityWrapperPtr>& aDstSubs = theDest->subEntities();
1188 std::list<EntityWrapperPtr>::const_iterator aSrcIt, aDstIt;
1189 for (aSrcIt = aSrcSubs.begin(), aDstIt = aDstSubs.begin();
1190 aSrcIt != aSrcSubs.end() && aDstIt != aDstSubs.end(); ++aSrcIt, ++aDstIt)
1191 rotate(*aSrcIt, *aDstIt, theCenter, theSin, theCos);
1194 aDestFeature->data()->blockSendAttributeUpdated(false);
1197 static void translate(EntityWrapperPtr theSource, EntityWrapperPtr theDest,
1198 std::shared_ptr<GeomAPI_XY> theDelta)
1200 if (theSource->type() == ENTITY_POINT) {
1201 // Translate single point
1202 std::shared_ptr<GeomDataAPI_Point2D> aSrcAttr =
1203 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theSource->baseAttribute());
1204 std::shared_ptr<GeomDataAPI_Point2D> aDstAttr =
1205 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theDest->baseAttribute());
1206 if (aSrcAttr && aDstAttr)
1207 aDstAttr->setValue(aSrcAttr->x() + theDelta->x(), aSrcAttr->y() + theDelta->y());
1211 FeaturePtr aDestFeature = theDest->baseFeature();
1213 aDestFeature->data()->blockSendAttributeUpdated(true);
1215 // Translate points of the feature
1216 const std::list<EntityWrapperPtr>& aSrcSubs = theSource->subEntities();
1217 const std::list<EntityWrapperPtr>& aDstSubs = theDest->subEntities();
1218 std::list<EntityWrapperPtr>::const_iterator aSrcIt, aDstIt;
1219 for (aSrcIt = aSrcSubs.begin(), aDstIt = aDstSubs.begin();
1220 aSrcIt != aSrcSubs.end() && aDstIt != aDstSubs.end(); ++aSrcIt, ++aDstIt)
1221 translate(*aSrcIt, *aDstIt, theDelta);
1224 aDestFeature->data()->blockSendAttributeUpdated(false);
1227 void adjustMultiRotation(ConstraintWrapperPtr theConstraint)
1229 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1231 double anAngleRad = theConstraint->value() * PI / 180.0;
1232 double aSin = sin(anAngleRad);
1233 double aCos = cos(anAngleRad);
1235 const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
1236 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
1238 std::shared_ptr<GeomAPI_Pnt2d> aCenter = aBuilder->point(*aSIt++);
1239 std::list<EntityWrapperPtr>::const_iterator aPrevIt = aSIt++;
1240 for (; aSIt != aSubs.end(); ++aPrevIt, ++aSIt)
1241 rotate(*aPrevIt, *aSIt, aCenter, aSin, aCos);
1244 void adjustMultiTranslation(ConstraintWrapperPtr theConstraint)
1246 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1248 const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
1249 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
1251 std::shared_ptr<GeomAPI_Pnt2d> aStartPnt = aBuilder->point(*aSIt++);
1252 std::shared_ptr<GeomAPI_Pnt2d> aEndPnt = aBuilder->point(*aSIt++);
1253 std::shared_ptr<GeomAPI_XY> aDelta = aEndPnt->xy()->decreased(aStartPnt->xy());
1255 std::list<EntityWrapperPtr>::const_iterator aPrevIt = aSIt++;
1256 for (; aSIt != aSubs.end(); ++aPrevIt, ++aSIt)
1257 translate(*aPrevIt, *aSIt, aDelta);