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