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 EntityWrapperPtr& thePoint1,
267 const EntityWrapperPtr& thePoint2,
268 const std::list<EntityWrapperPtr>& theTrsfEnt) const
270 ParameterWrapperPtr anAngleParam;
271 if (theType == CONSTRAINT_MULTI_ROTATION)
272 anAngleParam = createParamAngle(theGroupID, theValue);
273 else if (theType != CONSTRAINT_MULTI_TRANSLATION)
274 return std::list<ConstraintWrapperPtr>();
276 std::list<EntityWrapperPtr> aConstrAttrList = theTrsfEnt;
278 aConstrAttrList.push_front(thePoint2);
279 aConstrAttrList.push_front(thePoint1);
281 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
282 new PlaneGCSSolver_ConstraintWrapper(theConstraint, std::list<GCSConstraintPtr>(), theType));
283 aResult->setGroup(theGroupID);
284 aResult->setEntities(aConstrAttrList);
286 aResult->setValueParameter(anAngleParam);
287 return std::list<ConstraintWrapperPtr>(1, aResult);
291 std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createMirror(
292 ConstraintPtr theConstraint,
293 const GroupID& theGroupID,
294 const EntityID& theSketchID,
295 const EntityWrapperPtr& theEntity1,
296 const EntityWrapperPtr& theEntity2,
297 const EntityWrapperPtr& theMirrorLine) const
299 std::list<ConstraintWrapperPtr> aResult;
300 std::list<EntityWrapperPtr> aConstrAttrList;
301 if (theEntity1->type() == ENTITY_POINT) {
302 if (theEntity2->group() == theGroupID) // theEntity2 is not fixed
303 makeMirrorPoints(theEntity1, theEntity2, theMirrorLine);
305 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 =
306 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity1);
307 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 =
308 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity2);
310 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aMirrorLine =
311 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMirrorLine);
312 std::shared_ptr<GCS::Line> aLine =
313 std::dynamic_pointer_cast<GCS::Line>(aMirrorLine->entity());
315 std::list<GCSConstraintPtr> aConstrList;
316 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
317 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
318 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintMidpointOnLine(
319 *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
321 ConstraintWrapperPtr aSubResult(new PlaneGCSSolver_ConstraintWrapper(
322 theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
323 aSubResult->setGroup(theGroupID);
324 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
325 aSubs.push_back(theEntity2);
326 aSubs.push_back(theMirrorLine);
327 aSubResult->setEntities(aSubs);
328 aResult.push_back(aSubResult);
330 else if (theEntity1->type() == ENTITY_LINE) {
331 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
332 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
333 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
334 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
335 for (; anIt1 != aPoints1.end() && anIt2 != aPoints2.end(); ++anIt1, ++anIt2) {
336 std::list<ConstraintWrapperPtr> aMrrList =
337 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
338 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
341 else if (theEntity1->type() == ENTITY_CIRCLE) {
342 const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
343 std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
344 for (; anIt1 != aPoints1.end(); ++anIt1)
345 if ((*anIt1)->type() == ENTITY_POINT)
347 const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
348 std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
349 for (; anIt2 != aPoints2.end(); ++anIt2)
350 if ((*anIt2)->type() == ENTITY_POINT)
353 std::list<ConstraintWrapperPtr> aMrrList =
354 createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
355 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
357 // Additional constraint for equal radii
358 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
359 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
360 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
362 else if (theEntity1->type() == ENTITY_ARC) {
363 // Do not allow mirrored arc recalculate its position until coordinated of all points recalculated
364 FeaturePtr aMirrArc = theEntity2->baseFeature();
365 aMirrArc->data()->blockSendAttributeUpdated(true);
367 // Make mirror for center and start point of original arc
368 std::list<ConstraintWrapperPtr> aMrrList;
369 std::list<EntityWrapperPtr>::const_iterator anIt1 = theEntity1->subEntities().begin();
370 std::list<EntityWrapperPtr>::const_iterator anIt2 = theEntity2->subEntities().begin();
371 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
372 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
376 aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
377 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
379 // make symmetric last point of original arc and first point of mirrored arc without additional constraint
382 makeMirrorPoints(*anIt1, *anIt2, theMirrorLine);
384 // Additionally, make equal radii...
385 aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
386 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
387 aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
388 // ... and make parametric length of arcs the same
389 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt1 =
390 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity1);
391 std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt2 =
392 std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity2);
393 std::shared_ptr<GCS::Arc> anArc1 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt1->entity());
394 std::shared_ptr<GCS::Arc> anArc2 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt2->entity());
395 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> anIntermed =
396 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(
397 createParameter(theGroupID, *(anArc1->endAngle) - *(anArc1->startAngle)));
398 // By the way, recalculate start and end angles of mirrored arc
399 std::shared_ptr<GeomAPI_Dir2d> anOX(new GeomAPI_Dir2d(1.0, 0.0));
400 std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(
401 *(anArc2->start.x) - *(anArc2->center.x), *(anArc2->start.y) - *(anArc2->center.y)));
402 std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(
403 *(anArc2->end.x) - *(anArc2->center.x), *(anArc2->end.y) - *(anArc2->center.y)));
404 *anArc2->startAngle = anOX->angle(aStartDir);
405 *anArc2->endAngle = anOX->angle(aEndDir);
407 std::list<GCSConstraintPtr> aConstrList;
408 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
409 anArc1->endAngle, anArc1->startAngle, anIntermed->parameter())));
410 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
411 anArc2->endAngle, anArc2->startAngle, anIntermed->parameter())));
413 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aSubResult(
414 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
415 aSubResult->setGroup(theGroupID);
416 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
417 aSubs.push_back(theEntity2);
418 aSubs.push_back(theMirrorLine);
419 aSubResult->setEntities(aSubs);
420 aSubResult->setValueParameter(anIntermed);
421 aResult.push_back(aSubResult);
423 // Restore event sending
424 aMirrArc->data()->blockSendAttributeUpdated(false);
429 void PlaneGCSSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstraint) const
431 SketchSolver_ConstraintType aType = theConstraint->type();
432 // Update flags and parameters in constraints
433 if (aType == CONSTRAINT_ANGLE)
434 adjustAngle(theConstraint);
435 //// else if (aType == CONSTRAINT_SYMMETRIC)
436 //// adjustMirror(theConstraint);
437 else if (aType == CONSTRAINT_MULTI_ROTATION)
438 adjustMultiRotation(theConstraint);
439 else if (aType == CONSTRAINT_MULTI_TRANSLATION)
440 adjustMultiTranslation(theConstraint);
443 EntityWrapperPtr PlaneGCSSolver_Builder::createFeature(
444 FeaturePtr theFeature,
445 const std::list<EntityWrapperPtr>& theAttributes,
446 const GroupID& theGroupID,
447 const EntityID& /*theSketchID*/) const
449 static EntityWrapperPtr aDummy;
450 if (!theFeature->data()->isValid())
454 CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
456 return createSketchEntity(aSketch, theGroupID);
458 // SketchPlugin features
459 std::shared_ptr<SketchPlugin_Feature> aFeature =
460 std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
464 // Verify the feature by its kind
465 const std::string& aFeatureKind = aFeature->getKind();
467 if (aFeatureKind == SketchPlugin_Line::ID())
468 return createLine(theFeature, theAttributes, theGroupID);
470 else if (aFeatureKind == SketchPlugin_Circle::ID())
471 return createCircle(theFeature, theAttributes, theGroupID);
473 else if (aFeatureKind == SketchPlugin_Arc::ID())
474 return createArc(theFeature, theAttributes, theGroupID);
475 // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
476 else if (aFeatureKind == SketchPlugin_Point::ID()) {
477 AttributePtr aPoint = theFeature->attribute(SketchPlugin_Point::COORD_ID());
478 if (!aPoint->isInitialized())
480 EntityWrapperPtr aSub = createAttribute(aPoint, theGroupID);
484 GCSPointPtr aSubEnt =
485 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aSub)->point();
486 EntityWrapperPtr aNewEntity(new PlaneGCSSolver_EntityWrapper(theFeature));
487 aNewEntity->setSubEntities(std::list<EntityWrapperPtr>(1, aSub));
495 EntityWrapperPtr PlaneGCSSolver_Builder::createAttribute(
496 AttributePtr theAttribute,
497 const GroupID& theGroupID,
498 const EntityID& theSketchID) const
500 AttributePtr anAttribute = theAttribute;
501 AttributeRefAttrPtr aRefAttr =
502 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
504 if (aRefAttr->isObject()) {
505 // do not create features here
506 return EntityWrapperPtr();
508 anAttribute = aRefAttr->attr();
511 std::list<ParameterWrapperPtr> aParameters;
512 EntityWrapperPtr aResult;
515 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
516 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
518 aParameters.push_back(::createParameter(theGroupID, aPoint2D->x(), !aPoint2D->textX().empty()));
519 aParameters.push_back(::createParameter(theGroupID, aPoint2D->y(), !aPoint2D->textY().empty()));
520 GCSPointPtr aGCSPoint(new GCS::Point);
521 aGCSPoint->x = std::dynamic_pointer_cast<
522 PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
523 aGCSPoint->y = std::dynamic_pointer_cast<
524 PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
525 // Create entity (parameters are not filled)
526 aResult = EntityWrapperPtr(new PlaneGCSSolver_PointWrapper(theAttribute, aGCSPoint));
528 // Scalar value (used for the distance entities)
529 AttributeDoublePtr aScalar =
530 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
532 return createScalar(theGroupID, aScalar);
536 // unknown attribute type
537 return EntityWrapperPtr();
540 aResult->setGroup(theGroupID);
541 aResult->setParameters(aParameters);
545 ParameterWrapperPtr PlaneGCSSolver_Builder::createParameter(
546 const GroupID& theGroupID, double theValue) const
548 return ::createParameter(theGroupID, theValue);
552 EntityWrapperPtr PlaneGCSSolver_Builder::createSketchEntity(
553 CompositeFeaturePtr theSketch,
554 const GroupID& theGroupID) const
556 DataPtr aSketchData = theSketch->data();
557 if (!aSketchData || !aSketchData->isValid())
558 return EntityWrapperPtr(); // the sketch is incorrect
560 // Create dummy wrapper representing workplane
561 std::shared_ptr<PlaneGCSSolver_EntityWrapper> aSketchEnt(
562 new PlaneGCSSolver_EntityWrapper(FeaturePtr(theSketch)));
563 aSketchEnt->setGroup(theGroupID);
564 aSketchEnt->setId(EID_SKETCH);
570 ////EntityWrapperPtr PlaneGCSSolver_Builder::createNormal(
571 //// AttributePtr theNormal,
572 //// AttributePtr theDirX,
573 //// const GroupID& theGroupID) const
575 //// std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(theNormal);
576 //// std::shared_ptr<GeomDataAPI_Dir> aDirX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(theDirX);
577 //// if (!aDirX || !aNorm ||
578 //// (fabs(aDirX->x()) + fabs(aDirX->y()) + fabs(aDirX->z()) < tolerance) ||
579 //// !aNorm->isInitialized())
580 //// return EntityWrapperPtr();
581 //// // calculate Y direction
582 //// std::shared_ptr<GeomAPI_Dir> aDirY(new GeomAPI_Dir(aNorm->dir()->cross(aDirX->dir())));
584 //// // quaternion parameters of normal vector
585 //// double qw, qx, qy, qz;
586 //// Slvs_MakeQuaternion(aDirX->x(), aDirX->y(), aDirX->z(), aDirY->x(), aDirY->y(), aDirY->z(), &qw,
588 //// double aNormCoord[4] = { qw, qx, qy, qz };
590 //// // Create parameters of the normal
591 //// std::list<ParameterWrapperPtr> aParameters;
592 //// for (int i = 0; i < 4; i++)
593 //// aParameters.push_back(createParameter(theGroupID, aNormCoord[i]));
595 //// // Create a normal with empty parameters
596 //// Slvs_Entity aNormalEnt = Slvs_MakeNormal3d(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
597 //// SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
598 //// EntityWrapperPtr aNormal(new SolveSpaceSolver_EntityWrapper(theNormal, aNormalEnt));
599 //// aNormal->setParameters(aParameters);
607 // ================ Auxiliary functions ==========================
608 ParameterWrapperPtr createParameter(
609 const GroupID& theGroup, const double theValue, const bool theExpr)
611 double* aParam = new double(theValue);
612 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_ParameterWrapper(aParam));
613 aWrapper->setGroup(theGroup);
614 aWrapper->setIsParametric(theExpr);
618 ParameterWrapperPtr createParamAngle(const GroupID& theGroup, const double& theValue)
620 double* aParam = new double(theValue);
621 ParameterWrapperPtr aWrapper(new PlaneGCSSolver_AngleWrapper(aParam));
622 aWrapper->setGroup(theGroup);
626 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> createScalar(
627 const GroupID& theGroupID,
628 AttributeDoublePtr theDoubleAttr)
630 ParameterWrapperPtr aParam = createParameter(theGroupID, theDoubleAttr ? theDoubleAttr->value() : 0.0);
631 return std::shared_ptr<PlaneGCSSolver_ScalarWrapper>(
632 new PlaneGCSSolver_ScalarWrapper(theDoubleAttr, aParam));
635 EntityWrapperPtr createLine(FeaturePtr theFeature,
636 const std::list<EntityWrapperPtr>& theAttributes,
637 const GroupID& theGroupID)
639 EntityWrapperPtr aNewEntity;
640 std::list<EntityWrapperPtr> aSubs;
642 AttributePtr aStart = theFeature->attribute(SketchPlugin_Line::START_ID());
643 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Line::END_ID());
644 if (!aStart->isInitialized() || !aEnd->isInitialized())
647 std::shared_ptr<PlaneGCSSolver_PointWrapper> aStartEnt, aEndEnt;
648 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
649 for (; anIt != theAttributes.end(); ++anIt) {
650 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
651 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
654 if (aWrapper->isBase(aStart))
655 aStartEnt = aWrapper;
656 else if (aWrapper->isBase(aEnd))
659 if (!aStartEnt || !aEndEnt)
662 aSubs.push_back(aStartEnt);
663 aSubs.push_back(aEndEnt);
665 std::shared_ptr<GCS::Line> aLine(new GCS::Line);
666 aLine->p1 = *(aStartEnt->point());
667 aLine->p2 = *(aEndEnt->point());
669 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aLine));
670 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
671 aNewEntity->setSubEntities(aSubs);
675 EntityWrapperPtr createCircle(FeaturePtr theFeature,
676 const std::list<EntityWrapperPtr>& theAttributes,
677 const GroupID& theGroupID)
679 EntityWrapperPtr aNewEntity;
680 std::list<EntityWrapperPtr> aSubs;
682 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Circle::CENTER_ID());
683 AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
684 if (!aCenter->isInitialized() || !aRadius->isInitialized())
687 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt;
688 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aRadiusEnt;
689 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
690 for (; anIt != theAttributes.end(); ++anIt) {
691 if ((*anIt)->isBase(aCenter))
692 aCenterEnt = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
693 else if ((*anIt)->isBase(aRadius))
694 aRadiusEnt = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*anIt);
696 if (!aCenterEnt || !aRadiusEnt)
699 aSubs.push_back(aCenterEnt);
700 aSubs.push_back(aRadiusEnt);
702 std::shared_ptr<GCS::Circle> aCircle(new GCS::Circle);
703 aCircle->center = *(aCenterEnt->point());
704 aCircle->rad = aRadiusEnt->scalar();
706 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aCircle));
707 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
708 aNewEntity->setSubEntities(aSubs);
712 EntityWrapperPtr createArc(FeaturePtr theFeature,
713 const std::list<EntityWrapperPtr>& theAttributes,
714 const GroupID& theGroupID)
716 EntityWrapperPtr aNewEntity;
717 std::list<EntityWrapperPtr> aSubs;
719 AttributePtr aCenter = theFeature->attribute(SketchPlugin_Arc::CENTER_ID());
720 AttributePtr aStart = theFeature->attribute(SketchPlugin_Arc::START_ID());
721 AttributePtr aEnd = theFeature->attribute(SketchPlugin_Arc::END_ID());
722 if (!aCenter->isInitialized() || !aStart->isInitialized() || !aEnd->isInitialized())
725 std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt, aStartEnt, aEndEnt;
726 std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
727 for (; anIt != theAttributes.end(); ++anIt) {
728 std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
729 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
732 if (aWrapper->isBase(aCenter))
733 aCenterEnt = aWrapper;
734 else if (aWrapper->isBase(aStart))
735 aStartEnt = aWrapper;
736 else if (aWrapper->isBase(aEnd))
739 if (!aCenterEnt || !aStartEnt || !aEndEnt)
742 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aStartAng, aEndAng, aRadius;
743 aStartAng = createScalar(theGroupID);
744 aEndAng = createScalar(theGroupID);
745 aRadius = createScalar(theGroupID);
747 aSubs.push_back(aCenterEnt);
748 aSubs.push_back(aStartEnt);
749 aSubs.push_back(aEndEnt);
750 aSubs.push_back(aStartAng);
751 aSubs.push_back(aEndAng);
752 aSubs.push_back(aRadius);
754 std::shared_ptr<GCS::Arc> anArc(new GCS::Arc);
755 anArc->center = *(aCenterEnt->point());
756 anArc->start = *(aStartEnt->point());
757 anArc->end = *(aEndEnt->point());
758 anArc->startAngle = aStartAng->scalar();
759 anArc->endAngle = aEndAng->scalar();
760 anArc->rad = aRadius->scalar();
762 aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, anArc));
763 aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
764 aNewEntity->setSubEntities(aSubs);
770 ConstraintWrapperPtr createConstraintCoincidence(
771 ConstraintPtr theConstraint,
772 const GroupID& theGroupID,
773 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
774 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
776 // Create equality constraint for corresponding attributes of the points
777 std::list<GCSConstraintPtr> aConstrList;
778 std::list<ParameterWrapperPtr>::const_iterator anIt1 = thePoint1->parameters().begin();
779 std::list<ParameterWrapperPtr>::const_iterator anIt2 = thePoint2->parameters().begin();
780 for (; anIt1 != thePoint1->parameters().end(); ++anIt1, ++anIt2) {
781 if (*anIt1 == *anIt2)
782 continue; // points use same parameters, no need additional constraints
783 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam1 =
784 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt1);
785 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam2 =
786 std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt2);
787 aConstrList.push_back(
788 GCSConstraintPtr(new GCS::ConstraintEqual(aParam1->parameter(), aParam2->parameter())));
791 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
792 theConstraint, aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
793 aResult->setGroup(theGroupID);
794 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
795 aSubs.push_back(thePoint2);
796 aResult->setEntities(aSubs);
800 ConstraintWrapperPtr createConstraintPointOnEntity(
801 ConstraintPtr theConstraint,
802 const GroupID& theGroupID,
803 const SketchSolver_ConstraintType& theType,
804 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
805 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
807 GCSConstraintPtr aNewConstr;
809 switch (theEntity->type()) {
811 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
812 aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnLine(*(thePoint->point()), *aLine));
816 case ENTITY_CIRCLE: {
817 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
818 aNewConstr = GCSConstraintPtr(
819 new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
823 return ConstraintWrapperPtr();
826 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
827 theConstraint, aNewConstr, theType));
828 aResult->setGroup(theGroupID);
829 std::list<EntityWrapperPtr> aSubs(1, thePoint);
830 aSubs.push_back(theEntity);
831 aResult->setEntities(aSubs);
835 ConstraintWrapperPtr createConstraintDistancePointPoint(
836 ConstraintPtr theConstraint,
837 const GroupID& theGroupID,
838 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
839 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
840 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
842 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
843 *(thePoint1->point()), *(thePoint2->point()), theValue->parameter()));
845 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
846 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
847 aResult->setGroup(theGroupID);
848 std::list<EntityWrapperPtr> aSubs(1, thePoint1);
849 aSubs.push_back(thePoint2);
850 aResult->setEntities(aSubs);
851 aResult->setValueParameter(theValue);
855 ConstraintWrapperPtr createConstraintDistancePointLine(
856 ConstraintPtr theConstraint,
857 const GroupID& theGroupID,
858 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
859 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
860 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
862 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
863 GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
864 *(thePoint->point()), *(aLine), theValue->parameter()));
866 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
867 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
868 aResult->setGroup(theGroupID);
869 std::list<EntityWrapperPtr> aSubs(1, thePoint);
870 aSubs.push_back(theEntity);
871 aResult->setEntities(aSubs);
872 aResult->setValueParameter(theValue);
876 ConstraintWrapperPtr createConstraintRadius(
877 ConstraintPtr theConstraint,
878 const GroupID& theGroupID,
879 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
880 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
882 std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
883 GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->parameter()));
885 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
886 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_RADIUS));
887 aResult->setGroup(theGroupID);
888 std::list<EntityWrapperPtr> aSubs(1, theEntity);
889 aResult->setEntities(aSubs);
890 aResult->setValueParameter(theValue);
894 ConstraintWrapperPtr createConstraintAngle(
895 ConstraintPtr theConstraint,
896 const GroupID& theGroupID,
897 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
898 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
899 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
901 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
902 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
903 GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
904 *(aLine1), *(aLine2), theValue->parameter()));
906 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
907 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_ANGLE));
908 aResult->setGroup(theGroupID);
909 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
910 aSubs.push_back(theEntity2);
911 aResult->setEntities(aSubs);
912 aResult->setValueParameter(theValue);
916 ConstraintWrapperPtr createConstraintHorizVert(
917 ConstraintPtr theConstraint,
918 const GroupID& theGroupID,
919 const SketchSolver_ConstraintType& theType,
920 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
922 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
923 GCSConstraintPtr aNewConstr;
924 if (theType == CONSTRAINT_HORIZONTAL)
925 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.y, aLine->p2.y));
927 aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
929 ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
930 theConstraint, aNewConstr, theType));
931 aResult->setGroup(theGroupID);
932 std::list<EntityWrapperPtr> aSubs(1, theEntity);
933 aResult->setEntities(aSubs);
937 ConstraintWrapperPtr createConstraintParallel(
938 ConstraintPtr theConstraint,
939 const GroupID& theGroupID,
940 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
941 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
943 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
944 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
945 GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
947 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
948 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PARALLEL));
949 aResult->setGroup(theGroupID);
950 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
951 aSubs.push_back(theEntity2);
952 aResult->setEntities(aSubs);
956 ConstraintWrapperPtr createConstraintPerpendicular(
957 ConstraintPtr theConstraint,
958 const GroupID& theGroupID,
959 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
960 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
962 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
963 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
964 GCSConstraintPtr aNewConstr(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
966 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
967 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PERPENDICULAR));
968 aResult->setGroup(theGroupID);
969 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
970 aSubs.push_back(theEntity2);
971 aResult->setEntities(aSubs);
975 ConstraintWrapperPtr createConstraintEqual(
976 ConstraintPtr theConstraint,
977 const GroupID& theGroupID,
978 const SketchSolver_ConstraintType& theType,
979 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
980 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
981 std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed)
983 if (theType == CONSTRAINT_EQUAL_LINE_ARC)
984 return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
986 std::list<GCSConstraintPtr> aConstrList;
987 if (theType == CONSTRAINT_EQUAL_LINES) {
988 std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
989 std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
991 aConstrList.push_back(GCSConstraintPtr(
992 new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->parameter())));
993 aConstrList.push_back(GCSConstraintPtr(
994 new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->parameter())));
996 std::shared_ptr<GCS::Circle> aCirc1 =
997 std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
998 std::shared_ptr<GCS::Circle> aCirc2 =
999 std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
1001 aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
1004 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1005 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, theType));
1006 aResult->setGroup(theGroupID);
1007 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1008 aSubs.push_back(theEntity2);
1009 aResult->setEntities(aSubs);
1011 aResult->setValueParameter(theIntermed);
1015 ConstraintWrapperPtr createConstraintTangent(
1016 ConstraintPtr theConstraint,
1017 const GroupID& theGroupID,
1018 const SketchSolver_ConstraintType& theType,
1019 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
1020 std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
1022 GCSConstraintPtr aNewConstr;
1023 if (theType == CONSTRAINT_TANGENT_ARC_LINE) {
1024 std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1025 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
1027 aNewConstr = GCSConstraintPtr(new GCS::ConstraintP2LDistance(aCirc->center, *aLine, aCirc->rad));
1029 std::shared_ptr<GCS::Circle> aCirc1 = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
1030 std::shared_ptr<GCS::Circle> aCirc2 = std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
1032 double aDX = *(aCirc1->center.x) - *(aCirc2->center.x);
1033 double aDY = *(aCirc1->center.y) - *(aCirc2->center.y);
1034 double aDist = sqrt(aDX * aDX + aDY * aDY);
1035 aNewConstr = GCSConstraintPtr(new GCS::ConstraintTangentCircumf(aCirc1->center, aCirc2->center,
1036 aCirc1->rad, aCirc2->rad, (aDist < *(aCirc1->rad) || aDist < *(aCirc2->rad))));
1039 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
1040 new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, theType));
1041 aResult->setGroup(theGroupID);
1042 std::list<EntityWrapperPtr> aSubs(1, theEntity1);
1043 aSubs.push_back(theEntity2);
1044 aResult->setEntities(aSubs);
1052 void adjustAngle(ConstraintWrapperPtr theConstraint)
1054 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1056 std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
1057 std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
1059 std::shared_ptr<GeomAPI_Pnt2d> aPoints[2][2]; // start and end points of lines
1060 const std::list<EntityWrapperPtr>& aConstrLines = aConstraint->entities();
1061 std::list<EntityWrapperPtr>::const_iterator aCLIt = aConstrLines.begin();
1062 for (int i = 0; aCLIt != aConstrLines.end(); ++i, ++aCLIt) {
1063 const std::list<EntityWrapperPtr>& aLinePoints = (*aCLIt)->subEntities();
1064 std::list<EntityWrapperPtr>::const_iterator aLPIt = aLinePoints.begin();
1065 for (int j = 0; aLPIt != aLinePoints.end(); ++j, ++aLPIt)
1066 aPoints[i][j] = aBuilder->point(*aLPIt);
1069 std::shared_ptr<GeomAPI_Lin2d> aLine[2] = {
1070 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[0][0], aPoints[0][1])),
1071 std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[1][0], aPoints[1][1]))
1073 std::shared_ptr<GeomAPI_Pnt2d> anIntersection = aLine[0]->intersect(aLine[1]);
1074 if (!anIntersection)
1077 for (int i = 0; i < 2; i++) {
1078 for (int j = 0; j < 2; j++) {
1079 aDist[i][j] = anIntersection->distance(aPoints[i][j]);
1080 if (fabs(aDist[i][j]) <= tolerance)
1083 if (aDist[i][0] > tolerance && aDist[i][1] > tolerance &&
1084 aDist[i][0] + aDist[i][1] < aPoints[i][0]->distance(aPoints[i][1]) + 2.0 * tolerance) {
1085 // the intersection point is an inner point of the line,
1086 // we change the sign of distance till start point to calculate correct coordinates
1088 aDist[i][0] *= -1.0;
1091 std::shared_ptr<GeomAPI_Dir2d> aDir[2];
1092 for (int i = 0; i < 2; i++) {
1093 if (aDist[i][1] > fabs(aDist[i][0]))
1094 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1095 aPoints[i][1]->xy()->decreased(anIntersection->xy())));
1097 aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
1098 aPoints[i][0]->xy()->decreased(anIntersection->xy())));
1099 // main direction is opposite => change signs
1100 if (aDist[i][0] < 0.0) {
1101 aDist[i][0] *= -1.0;
1102 aDist[i][1] *= -1.0;
1107 bool isChange = false;
1108 for (int i = 0; i < 2; i++)
1109 if (aLine[i]->direction()->dot(aDir[i]) < 0.0)
1110 isChange = !isChange;
1112 aConstraint->setValue(180.0 - aConstraint->value());
1115 ////void adjustMirror(ConstraintWrapperPtr theConstraint)
1117 //// std::vector<EntityWrapperPtr> aPoints;
1118 //// EntityWrapperPtr aMirrorLine;
1120 //// const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
1121 //// std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
1122 //// for (; anIt != aSubs.end(); ++anIt) {
1123 //// if ((*anIt)->type() == ENTITY_POINT)
1124 //// aPoints.push_back(*anIt);
1125 //// else if ((*anIt)->type() == ENTITY_LINE)
1126 //// aMirrorLine = *anIt;
1129 //// makeMirrorPoints(aPoints[0], aPoints[1], aMirrorLine);
1132 void makeMirrorPoints(EntityWrapperPtr theOriginal,
1133 EntityWrapperPtr theMirrored,
1134 EntityWrapperPtr theMirrorLine)
1136 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1138 std::shared_ptr<GeomAPI_Lin2d> aMirrorLine = aBuilder->line(theMirrorLine);
1139 std::shared_ptr<GeomAPI_Dir2d> aMLDir = aMirrorLine->direction();
1140 // orthogonal direction
1141 aMLDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aMLDir->y(), -aMLDir->x()));
1143 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(theOriginal);
1144 std::shared_ptr<GeomAPI_XY> aVec = aPoint->xy()->decreased(aMirrorLine->location()->xy());
1145 double aDist = aVec->dot(aMLDir->xy());
1146 aVec = aPoint->xy()->added(aMLDir->xy()->multiplied(-2.0 * aDist));
1147 double aCoord[2] = {aVec->x(), aVec->y()};
1148 std::list<ParameterWrapperPtr>::const_iterator aMIt = theMirrored->parameters().begin();
1149 for (int i = 0; aMIt != theMirrored->parameters().end(); ++aMIt, ++i)
1150 (*aMIt)->setValue(aCoord[i]);
1152 // update corresponding attribute
1153 AttributePtr anAttr = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theMirrored)->baseAttribute();
1155 std::shared_ptr<GeomDataAPI_Point2D> aMirroredPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
1156 aMirroredPnt->setValue(aCoord[0], aCoord[1]);
1160 static void rotate(EntityWrapperPtr theSource, EntityWrapperPtr theDest,
1161 std::shared_ptr<GeomAPI_Pnt2d> theCenter,
1162 double theSin, double theCos)
1164 if (theSource->type() == ENTITY_POINT) {
1165 // Rotate single point
1166 std::shared_ptr<GeomDataAPI_Point2D> aSrcAttr =
1167 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theSource->baseAttribute());
1168 std::shared_ptr<GeomDataAPI_Point2D> aDstAttr =
1169 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theDest->baseAttribute());
1170 if (aSrcAttr && aDstAttr) {
1171 std::shared_ptr<GeomAPI_XY> aVec = aSrcAttr->pnt()->xy()->decreased(theCenter->xy());
1172 double aNewX = aVec->x() * theCos - aVec->y() * theSin;
1173 double aNewY = aVec->x() * theSin + aVec->y() * theCos;
1174 aDstAttr->setValue(theCenter->x() + aNewX, theCenter->y() + aNewY);
1179 FeaturePtr aDestFeature = theDest->baseFeature();
1181 aDestFeature->data()->blockSendAttributeUpdated(true);
1183 // Rotate points of the feature
1184 const std::list<EntityWrapperPtr>& aSrcSubs = theSource->subEntities();
1185 const std::list<EntityWrapperPtr>& aDstSubs = theDest->subEntities();
1186 std::list<EntityWrapperPtr>::const_iterator aSrcIt, aDstIt;
1187 for (aSrcIt = aSrcSubs.begin(), aDstIt = aDstSubs.begin();
1188 aSrcIt != aSrcSubs.end() && aDstIt != aDstSubs.end(); ++aSrcIt, ++aDstIt)
1189 rotate(*aSrcIt, *aDstIt, theCenter, theSin, theCos);
1192 aDestFeature->data()->blockSendAttributeUpdated(false);
1195 static void translate(EntityWrapperPtr theSource, EntityWrapperPtr theDest,
1196 std::shared_ptr<GeomAPI_XY> theDelta)
1198 if (theSource->type() == ENTITY_POINT) {
1199 // Translate single point
1200 std::shared_ptr<GeomDataAPI_Point2D> aSrcAttr =
1201 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theSource->baseAttribute());
1202 std::shared_ptr<GeomDataAPI_Point2D> aDstAttr =
1203 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theDest->baseAttribute());
1204 if (aSrcAttr && aDstAttr)
1205 aDstAttr->setValue(aSrcAttr->x() + theDelta->x(), aSrcAttr->y() + theDelta->y());
1209 FeaturePtr aDestFeature = theDest->baseFeature();
1211 aDestFeature->data()->blockSendAttributeUpdated(true);
1213 // Translate points of the feature
1214 const std::list<EntityWrapperPtr>& aSrcSubs = theSource->subEntities();
1215 const std::list<EntityWrapperPtr>& aDstSubs = theDest->subEntities();
1216 std::list<EntityWrapperPtr>::const_iterator aSrcIt, aDstIt;
1217 for (aSrcIt = aSrcSubs.begin(), aDstIt = aDstSubs.begin();
1218 aSrcIt != aSrcSubs.end() && aDstIt != aDstSubs.end(); ++aSrcIt, ++aDstIt)
1219 translate(*aSrcIt, *aDstIt, theDelta);
1222 aDestFeature->data()->blockSendAttributeUpdated(false);
1225 void adjustMultiRotation(ConstraintWrapperPtr theConstraint)
1227 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1229 double anAngleRad = theConstraint->value() * PI / 180.0;
1230 double aSin = sin(anAngleRad);
1231 double aCos = cos(anAngleRad);
1233 const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
1234 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
1236 std::shared_ptr<GeomAPI_Pnt2d> aCenter = aBuilder->point(*aSIt++);
1237 std::list<EntityWrapperPtr>::const_iterator aPrevIt = aSIt++;
1238 for (; aSIt != aSubs.end(); ++aPrevIt, ++aSIt)
1239 rotate(*aPrevIt, *aSIt, aCenter, aSin, aCos);
1242 void adjustMultiTranslation(ConstraintWrapperPtr theConstraint)
1244 BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
1246 const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
1247 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
1249 std::shared_ptr<GeomAPI_Pnt2d> aStartPnt = aBuilder->point(*aSIt++);
1250 std::shared_ptr<GeomAPI_Pnt2d> aEndPnt = aBuilder->point(*aSIt++);
1251 std::shared_ptr<GeomAPI_XY> aDelta = aEndPnt->xy()->decreased(aStartPnt->xy());
1253 std::list<EntityWrapperPtr>::const_iterator aPrevIt = aSIt++;
1254 for (; aSIt != aSubs.end(); ++aPrevIt, ++aSIt)
1255 translate(*aPrevIt, *aSIt, aDelta);