Salome HOME
Task 2.7. Horizontal and Vertical Distance constraint
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_Tools.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:    SketchSolver_Builder.cpp
4 // Created: 25 Mar 2015
5 // Author:  Artem ZHIDKOV
6
7 #include <PlaneGCSSolver_Tools.h>
8 #include <PlaneGCSSolver_EdgeWrapper.h>
9 #include <PlaneGCSSolver_PointWrapper.h>
10 #include <PlaneGCSSolver_ScalarWrapper.h>
11 #include <PlaneGCSSolver_ConstraintWrapper.h>
12
13 #include <SketchSolver_Constraint.h>
14 #include <SketchSolver_ConstraintAngle.h>
15 #include <SketchSolver_ConstraintCoincidence.h>
16 #include <SketchSolver_ConstraintCollinear.h>
17 #include <SketchSolver_ConstraintDistance.h>
18 #include <SketchSolver_ConstraintEqual.h>
19 #include <SketchSolver_ConstraintFixed.h>
20 #include <SketchSolver_ConstraintLength.h>
21 #include <SketchSolver_ConstraintMiddle.h>
22 #include <SketchSolver_ConstraintMirror.h>
23 #include <SketchSolver_ConstraintTangent.h>
24 #include <SketchSolver_ConstraintMultiRotation.h>
25 #include <SketchSolver_ConstraintMultiTranslation.h>
26
27 #include <SketchPlugin_ConstraintAngle.h>
28 #include <SketchPlugin_ConstraintCoincidence.h>
29 #include <SketchPlugin_ConstraintCollinear.h>
30 #include <SketchPlugin_ConstraintDistance.h>
31 #include <SketchPlugin_ConstraintDistanceHorizontal.h>
32 #include <SketchPlugin_ConstraintDistanceVertical.h>
33 #include <SketchPlugin_ConstraintEqual.h>
34 #include <SketchPlugin_ConstraintLength.h>
35 #include <SketchPlugin_ConstraintMiddle.h>
36 #include <SketchPlugin_ConstraintMirror.h>
37 #include <SketchPlugin_ConstraintRigid.h>
38 #include <SketchPlugin_ConstraintTangent.h>
39 #include <SketchPlugin_Line.h>
40 #include <SketchPlugin_MultiRotation.h>
41 #include <SketchPlugin_MultiTranslation.h>
42
43 #include <cmath>
44
45
46 #define GCS_EDGE_WRAPPER(x)   std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(x)
47 #define GCS_POINT_WRAPPER(x)  std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(x)
48 #define GCS_SCALAR_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(x)
49
50
51
52 static ConstraintWrapperPtr
53   createConstraintCoincidence(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
54                               std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
55 static ConstraintWrapperPtr
56   createConstraintPointOnEntity(const SketchSolver_ConstraintType& theType,
57                                 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
58                                 std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
59 static ConstraintWrapperPtr
60   createConstraintDistancePointPoint(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
61                                      std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
62                                      std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
63 static ConstraintWrapperPtr
64   createConstraintDistancePointLine(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
65                                     std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint,
66                                     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
67 static ConstraintWrapperPtr
68   createConstraintHVDistance(const SketchSolver_ConstraintType& theType,
69                              std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
70                              std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
71                              std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
72 static ConstraintWrapperPtr
73   createConstraintRadius(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
74                          std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
75 static ConstraintWrapperPtr
76   createConstraintAngle(ConstraintPtr theConstraint,
77                         std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
78                         std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
79                         std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2);
80 static ConstraintWrapperPtr
81   createConstraintHorizVert(const SketchSolver_ConstraintType& theType,
82                             std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
83 static ConstraintWrapperPtr
84   createConstraintParallel(std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
85                            std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2);
86 static ConstraintWrapperPtr
87   createConstraintPerpendicular(std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
88                                 std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2);
89 static ConstraintWrapperPtr
90   createConstraintEqual(const SketchSolver_ConstraintType& theType,
91                         std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
92                         std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2,
93                         std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theIntermed);
94 static ConstraintWrapperPtr
95   createConstraintMiddlePoint(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
96                               std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
97
98
99
100
101
102 SolverConstraintPtr PlaneGCSSolver_Tools::createConstraint(ConstraintPtr theConstraint)
103 {
104   if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
105     return SolverConstraintPtr(new SketchSolver_ConstraintCoincidence(theConstraint));
106   } else if (theConstraint->getKind() == SketchPlugin_ConstraintCollinear::ID()) {
107     return SolverConstraintPtr(new SketchSolver_ConstraintCollinear(theConstraint));
108   } else if (theConstraint->getKind() == SketchPlugin_ConstraintDistance::ID() ||
109              theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() ||
110              theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID()) {
111     return SolverConstraintPtr(new SketchSolver_ConstraintDistance(theConstraint));
112   } else if (theConstraint->getKind() == SketchPlugin_ConstraintEqual::ID()) {
113     return SolverConstraintPtr(new SketchSolver_ConstraintEqual(theConstraint));
114   } else if (theConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) {
115     return SolverConstraintPtr(new SketchSolver_ConstraintLength(theConstraint));
116   } else if (theConstraint->getKind() == SketchPlugin_ConstraintMiddle::ID()) {
117     return SolverConstraintPtr(new SketchSolver_ConstraintMiddle(theConstraint));
118   } else if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
119     return SolverConstraintPtr(new SketchSolver_ConstraintMirror(theConstraint));
120   } else if (theConstraint->getKind() == SketchPlugin_ConstraintTangent::ID()) {
121     return SolverConstraintPtr(new SketchSolver_ConstraintTangent(theConstraint));
122   } else if (theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID()) {
123     return SolverConstraintPtr(new SketchSolver_ConstraintFixed(theConstraint));
124   } else if (theConstraint->getKind() == SketchPlugin_MultiTranslation::ID()) {
125     return SolverConstraintPtr(new SketchSolver_ConstraintMultiTranslation(theConstraint));
126   } else if (theConstraint->getKind() == SketchPlugin_MultiRotation::ID()) {
127     return SolverConstraintPtr(new SketchSolver_ConstraintMultiRotation(theConstraint));
128   } else if (theConstraint->getKind() == SketchPlugin_ConstraintAngle::ID()) {
129     return SolverConstraintPtr(new SketchSolver_ConstraintAngle(theConstraint));
130   }
131   // All other types of constraints
132   return SolverConstraintPtr(new SketchSolver_Constraint(theConstraint));
133 }
134
135 std::shared_ptr<SketchSolver_ConstraintMovement> PlaneGCSSolver_Tools::createMovementConstraint(
136     FeaturePtr theMovedFeature)
137 {
138   return std::shared_ptr<SketchSolver_ConstraintMovement>(
139       new SketchSolver_ConstraintMovement(theMovedFeature));
140 }
141
142 std::shared_ptr<SketchSolver_ConstraintMovement> PlaneGCSSolver_Tools::createMovementConstraint(
143     AttributePtr theMovedAttribute)
144 {
145   return std::shared_ptr<SketchSolver_ConstraintMovement>(
146       new SketchSolver_ConstraintMovement(theMovedAttribute));
147 }
148
149
150
151 ConstraintWrapperPtr PlaneGCSSolver_Tools::createConstraint(
152     ConstraintPtr theConstraint,
153     const SketchSolver_ConstraintType& theType,
154     const EntityWrapperPtr& theValue,
155     const EntityWrapperPtr& thePoint1,
156     const EntityWrapperPtr& thePoint2,
157     const EntityWrapperPtr& theEntity1,
158     const EntityWrapperPtr& theEntity2)
159 {
160   ConstraintWrapperPtr aResult;
161   ScalarWrapperPtr anIntermediate;
162
163   std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(thePoint1);
164   std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(thePoint2);
165
166   switch (theType) {
167   case CONSTRAINT_PT_PT_COINCIDENT:
168     aResult = createConstraintCoincidence(aPoint1, aPoint2);
169     break;
170   case CONSTRAINT_PT_ON_LINE:
171   case CONSTRAINT_PT_ON_CIRCLE:
172     aResult = createConstraintPointOnEntity(theType, aPoint1, GCS_EDGE_WRAPPER(theEntity1));
173     break;
174   case CONSTRAINT_MIDDLE_POINT:
175     aResult = createConstraintMiddlePoint(aPoint1, GCS_EDGE_WRAPPER(theEntity1));
176     break;
177   case CONSTRAINT_PT_PT_DISTANCE:
178     aResult = createConstraintDistancePointPoint(GCS_SCALAR_WRAPPER(theValue), aPoint1, aPoint2);
179     break;
180   case CONSTRAINT_PT_LINE_DISTANCE:
181     aResult = createConstraintDistancePointLine(GCS_SCALAR_WRAPPER(theValue),
182                                                 aPoint1,
183                                                 GCS_EDGE_WRAPPER(theEntity1));
184     break;
185   case CONSTRAINT_HORIZONTAL_DISTANCE:
186   case CONSTRAINT_VERTICAL_DISTANCE:
187     aResult = createConstraintHVDistance(theType, GCS_SCALAR_WRAPPER(theValue), aPoint1, aPoint2);
188     break;
189   case CONSTRAINT_RADIUS:
190     aResult = createConstraintRadius(GCS_SCALAR_WRAPPER(theValue),
191                                      GCS_EDGE_WRAPPER(theEntity1));
192     break;
193   case CONSTRAINT_ANGLE:
194     aResult = createConstraintAngle(theConstraint,
195                   GCS_SCALAR_WRAPPER(theValue),
196                   GCS_EDGE_WRAPPER(theEntity1), GCS_EDGE_WRAPPER(theEntity2));
197     break;
198   case CONSTRAINT_FIXED:
199     break;
200   case CONSTRAINT_HORIZONTAL:
201   case CONSTRAINT_VERTICAL:
202     aResult = createConstraintHorizVert(theType, GCS_EDGE_WRAPPER(theEntity1));
203     break;
204   case CONSTRAINT_PARALLEL:
205     aResult = createConstraintParallel(GCS_EDGE_WRAPPER(theEntity1),
206                                        GCS_EDGE_WRAPPER(theEntity2));
207     break;
208   case CONSTRAINT_PERPENDICULAR:
209     aResult = createConstraintPerpendicular(GCS_EDGE_WRAPPER(theEntity1),
210                                             GCS_EDGE_WRAPPER(theEntity2));
211     break;
212   case CONSTRAINT_EQUAL_LINES:
213     anIntermediate = GCS_SCALAR_WRAPPER(theValue); // parameter is used to store length of lines
214   case CONSTRAINT_EQUAL_LINE_ARC:
215   case CONSTRAINT_EQUAL_RADIUS:
216     aResult = createConstraintEqual(theType,
217                                     GCS_EDGE_WRAPPER(theEntity1),
218                                     GCS_EDGE_WRAPPER(theEntity2),
219                                     anIntermediate);
220     break;
221   default:
222     break;
223   }
224
225   return aResult;
226 }
227
228 std::shared_ptr<GeomAPI_Pnt2d> PlaneGCSSolver_Tools::point(EntityWrapperPtr theEntity)
229 {
230   if (theEntity->type() != ENTITY_POINT)
231     return std::shared_ptr<GeomAPI_Pnt2d>();
232
233   std::shared_ptr<PlaneGCSSolver_PointWrapper> aPointWrapper =
234       std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
235   const GCSPointPtr& aPoint = aPointWrapper->point();
236   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(*aPoint->x, *aPoint->y));
237 }
238
239 std::shared_ptr<GeomAPI_Lin2d> PlaneGCSSolver_Tools::line(EntityWrapperPtr theEntity)
240 {
241   if (theEntity->type() != ENTITY_LINE)
242     return std::shared_ptr<GeomAPI_Lin2d>();
243
244   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
245       std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
246   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
247   return std::shared_ptr<GeomAPI_Lin2d>(
248       new GeomAPI_Lin2d(*(aLine->p1.x), *(aLine->p1.y), *(aLine->p2.x), *(aLine->p2.y)));
249 }
250
251 std::shared_ptr<GeomAPI_Lin2d> PlaneGCSSolver_Tools::line(FeaturePtr theFeature)
252 {
253   if (theFeature->getKind() != SketchPlugin_Line::ID())
254     return std::shared_ptr<GeomAPI_Lin2d>();
255
256   AttributePoint2DPtr aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
257       theFeature->attribute(SketchPlugin_Line::START_ID()));
258   AttributePoint2DPtr aEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
259       theFeature->attribute(SketchPlugin_Line::END_ID()));
260
261   return std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aStart->pnt(), aEnd->pnt()));
262 }
263
264
265
266
267
268 // ================   Auxiliary functions   ==========================
269 ConstraintWrapperPtr createConstraintCoincidence(
270     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
271     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
272 {
273   GCSPointPtr aPoint1 = thePoint1->point();
274   GCSPointPtr aPoint2 = thePoint2->point();
275
276   // Create equality constraint for corresponding attributes of the points
277   std::list<GCSConstraintPtr> aConstrList;
278   aConstrList.push_back(
279       GCSConstraintPtr(new GCS::ConstraintEqual(aPoint1->x, aPoint2->x)));
280   aConstrList.push_back(
281       GCSConstraintPtr(new GCS::ConstraintEqual(aPoint1->y, aPoint2->y)));
282
283   return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(
284       aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
285 }
286
287 ConstraintWrapperPtr createConstraintPointOnEntity(
288     const SketchSolver_ConstraintType& theType,
289     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
290     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
291 {
292   GCSConstraintPtr aNewConstr;
293
294   switch (theEntity->type()) {
295   case ENTITY_LINE: {
296     std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
297     aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnLine(*(thePoint->point()), *aLine));
298     break;
299     }
300   case ENTITY_ARC:
301   case ENTITY_CIRCLE: {
302     std::shared_ptr<GCS::Circle> aCirc =
303       std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
304     aNewConstr = GCSConstraintPtr(
305         new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
306     break;
307     }
308   default:
309     return ConstraintWrapperPtr();
310   }
311
312   return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
313 }
314
315 ConstraintWrapperPtr createConstraintMiddlePoint(
316     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
317     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
318 {
319   GCSPointPtr aPoint = thePoint->point();
320   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
321   if (!aLine)
322     return ConstraintWrapperPtr();
323
324   std::list<GCSConstraintPtr> aConstrList;
325   aConstrList.push_back(
326       GCSConstraintPtr(new GCS::ConstraintPointOnPerpBisector(*aPoint, aLine->p1, aLine->p2)));
327   aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPointOnLine(*aPoint, *aLine)));
328
329   return ConstraintWrapperPtr(
330       new PlaneGCSSolver_ConstraintWrapper(aConstrList, CONSTRAINT_MIDDLE_POINT));
331 }
332
333
334 ConstraintWrapperPtr createConstraintDistancePointPoint(
335     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
336     std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint1,
337     std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint2)
338 {
339   GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
340       *(thePoint1->point()), *(thePoint2->point()), theValue->scalar()));
341   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
342       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
343   aResult->setValueParameter(theValue);
344   return aResult;
345 }
346
347 ConstraintWrapperPtr createConstraintDistancePointLine(
348     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
349     std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint,
350     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
351 {
352   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
353   GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
354       *(thePoint->point()), *(aLine), theValue->scalar()));
355   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
356       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
357   aResult->setValueParameter(theValue);
358   return aResult;
359 }
360
361 ConstraintWrapperPtr createConstraintHVDistance(
362     const SketchSolver_ConstraintType& theType,
363     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
364     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
365     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
366 {
367   GCSPointPtr aPoint1 = thePoint1->point();
368   GCSPointPtr aPoint2 = thePoint2->point();
369
370   double *aParam1, *aParam2;
371   if (theType == CONSTRAINT_HORIZONTAL_DISTANCE) {
372     aParam1 = aPoint1->x;
373     aParam2 = aPoint2->x;
374   } else if (theType == CONSTRAINT_VERTICAL_DISTANCE) {
375     aParam1 = aPoint1->y;
376     aParam2 = aPoint2->y;
377   }
378
379   GCSConstraintPtr aNewConstr(new GCS::ConstraintDifference(aParam1, aParam2, theValue->scalar()));
380
381   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
382       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
383   aResult->setValueParameter(theValue);
384   return aResult;
385 }
386
387 ConstraintWrapperPtr createConstraintRadius(
388     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
389     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
390 {
391   std::shared_ptr<GCS::Circle> aCircle =
392     std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
393   GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->scalar()));
394   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
395       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_RADIUS));
396   aResult->setValueParameter(theValue);
397   return aResult;
398 }
399
400 ConstraintWrapperPtr createConstraintAngle(
401     ConstraintPtr theConstraint,
402     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
403     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
404     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
405 {
406   std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
407   bool isLine1Rev = theConstraint->boolean(
408       SketchPlugin_ConstraintAngle::ANGLE_REVERSED_FIRST_LINE_ID())->value();
409   GCS::Point aLine1Pt1 = isLine1Rev ? aLine1->p2 : aLine1->p1;
410   GCS::Point aLine1Pt2 = isLine1Rev ? aLine1->p1 : aLine1->p2;
411
412   std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
413   bool isLine2Rev = theConstraint->boolean(
414       SketchPlugin_ConstraintAngle::ANGLE_REVERSED_SECOND_LINE_ID())->value();
415   GCS::Point aLine2Pt1 = isLine2Rev ? aLine2->p2 : aLine2->p1;
416   GCS::Point aLine2Pt2 = isLine2Rev ? aLine2->p1 : aLine2->p2;
417
418   GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
419       aLine1Pt1, aLine1Pt2, aLine2Pt1, aLine2Pt2, theValue->scalar()));
420
421   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
422       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_ANGLE));
423   aResult->setValueParameter(theValue);
424   return aResult;
425 }
426
427 ConstraintWrapperPtr createConstraintHorizVert(
428     const SketchSolver_ConstraintType& theType,
429     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
430 {
431   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
432   GCSConstraintPtr aNewConstr;
433   if (theType == CONSTRAINT_HORIZONTAL)
434     aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.y, aLine->p2.y));
435   else
436     aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
437
438   return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
439 }
440
441 ConstraintWrapperPtr createConstraintParallel(
442     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
443     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
444 {
445   std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
446   std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
447   GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
448
449   return ConstraintWrapperPtr(
450       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PARALLEL));
451 }
452
453 ConstraintWrapperPtr createConstraintPerpendicular(
454     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
455     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
456 {
457   std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
458   std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
459   GCSConstraintPtr aNewConstr(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
460
461   return ConstraintWrapperPtr(
462       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PERPENDICULAR));
463 }
464
465 ConstraintWrapperPtr createConstraintEqual(
466     const SketchSolver_ConstraintType& theType,
467     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
468     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2,
469     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theIntermed)
470 {
471   if (theType == CONSTRAINT_EQUAL_LINE_ARC)
472     return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
473
474   std::list<GCSConstraintPtr> aConstrList;
475   if (theType == CONSTRAINT_EQUAL_LINES) {
476     std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
477     std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
478
479     aConstrList.push_back(GCSConstraintPtr(
480         new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->scalar())));
481     aConstrList.push_back(GCSConstraintPtr(
482         new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->scalar())));
483     // update value of intermediate parameter
484     double x = *aLine1->p1.x - *aLine1->p2.x;
485     double y = *aLine1->p1.y - *aLine1->p2.y;
486     double aLen = sqrt(x*x + y*y);
487     theIntermed->setValue(aLen);
488   } else {
489     std::shared_ptr<GCS::Circle> aCirc1 =
490         std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
491     std::shared_ptr<GCS::Circle> aCirc2 =
492         std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
493
494     aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
495   }
496
497   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
498       new PlaneGCSSolver_ConstraintWrapper(aConstrList, theType));
499   if (theIntermed)
500     aResult->setValueParameter(theIntermed);
501   return aResult;
502 }