]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp
Salome HOME
Task 2.12. New entities: ellipses and arcs of ellipses (issue #3003)
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_Tools.cpp
1 // Copyright (C) 2014-2019  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include <PlaneGCSSolver_Tools.h>
21 #include <PlaneGCSSolver_EdgeWrapper.h>
22 #include <PlaneGCSSolver_PointWrapper.h>
23 #include <PlaneGCSSolver_ScalarWrapper.h>
24 #include <PlaneGCSSolver_ConstraintWrapper.h>
25
26 #include <SketchSolver_Constraint.h>
27 #include <SketchSolver_ConstraintAngle.h>
28 #include <SketchSolver_ConstraintCoincidence.h>
29 #include <SketchPlugin_ConstraintCoincidenceInternal.h>
30 #include <SketchSolver_ConstraintCollinear.h>
31 #include <SketchSolver_ConstraintDistance.h>
32 #include <SketchSolver_ConstraintEqual.h>
33 #include <SketchSolver_ConstraintFixed.h>
34 #include <SketchSolver_ConstraintLength.h>
35 #include <SketchSolver_ConstraintMiddle.h>
36 #include <SketchSolver_ConstraintMirror.h>
37 #include <SketchSolver_ConstraintTangent.h>
38 #include <SketchSolver_ConstraintMultiRotation.h>
39 #include <SketchSolver_ConstraintMultiTranslation.h>
40
41 #include <SketchPlugin_ConstraintAngle.h>
42 #include <SketchPlugin_ConstraintCoincidence.h>
43 #include <SketchPlugin_ConstraintCollinear.h>
44 #include <SketchPlugin_ConstraintDistance.h>
45 #include <SketchPlugin_ConstraintDistanceHorizontal.h>
46 #include <SketchPlugin_ConstraintDistanceVertical.h>
47 #include <SketchPlugin_ConstraintEqual.h>
48 #include <SketchPlugin_ConstraintLength.h>
49 #include <SketchPlugin_ConstraintMiddle.h>
50 #include <SketchPlugin_ConstraintMirror.h>
51 #include <SketchPlugin_ConstraintRigid.h>
52 #include <SketchPlugin_ConstraintTangent.h>
53 #include <SketchPlugin_Line.h>
54 #include <SketchPlugin_MultiRotation.h>
55 #include <SketchPlugin_MultiTranslation.h>
56
57 #include <GeomAPI_Circ2d.h>
58 #include <GeomAPI_Dir2d.h>
59 #include <GeomAPI_Ellipse2d.h>
60 #include <GeomAPI_Lin2d.h>
61 #include <GeomAPI_Pnt2d.h>
62
63 #include <cmath>
64
65
66 #define GCS_EDGE_WRAPPER(x)   std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(x)
67 #define GCS_POINT_WRAPPER(x)  std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(x)
68 #define GCS_SCALAR_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(x)
69
70
71
72 static ConstraintWrapperPtr
73   createConstraintCoincidence(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
74                               std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
75 static ConstraintWrapperPtr
76   createConstraintPointOnEntity(const SketchSolver_ConstraintType& theType,
77                                 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
78                                 std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
79 static ConstraintWrapperPtr
80   createConstraintDistancePointPoint(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
81                                      std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
82                                      std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
83 static ConstraintWrapperPtr
84   createConstraintDistancePointLine(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
85                                     std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint,
86                                     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
87 static ConstraintWrapperPtr
88   createConstraintHVDistance(const SketchSolver_ConstraintType& theType,
89                              std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
90                              std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
91                              std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
92 static ConstraintWrapperPtr
93   createConstraintRadius(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
94                          std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
95 static ConstraintWrapperPtr
96   createConstraintAngle(ConstraintPtr theConstraint,
97                         std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
98                         std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
99                         std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2);
100 static ConstraintWrapperPtr
101   createConstraintHorizVert(const SketchSolver_ConstraintType& theType,
102                             std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
103 static ConstraintWrapperPtr
104   createConstraintParallel(std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
105                            std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2);
106 static ConstraintWrapperPtr
107   createConstraintPerpendicular(std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
108                                 std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2);
109 static ConstraintWrapperPtr
110   createConstraintEqual(const SketchSolver_ConstraintType& theType,
111                         std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
112                         std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2,
113                         std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theIntermed);
114 static ConstraintWrapperPtr
115   createConstraintMiddlePoint(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
116                               std::shared_ptr<PlaneGCSSolver_EdgeWrapper>  theEntity,
117                               std::shared_ptr<PlaneGCSSolver_PointWrapper> theAuxParameters);
118
119 static GCS::SET_pD scalarParameters(const ScalarWrapperPtr& theScalar);
120 static GCS::SET_pD pointParameters(const PointWrapperPtr& thePoint);
121 static GCS::SET_pD lineParameters(const EdgeWrapperPtr& theLine);
122 static GCS::SET_pD circleParameters(const EdgeWrapperPtr& theCircle);
123 static GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc);
124 static GCS::SET_pD ellipseParameters(const EdgeWrapperPtr& theEllipse);
125 static GCS::SET_pD ellipticArcParameters(const EdgeWrapperPtr& theEllipticArc);
126
127 static double distance(const GCS::Point& thePnt1, const GCS::Point& thePnt2);
128
129
130
131
132
133 SolverConstraintPtr PlaneGCSSolver_Tools::createConstraint(ConstraintPtr theConstraint)
134 {
135   if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
136       theConstraint->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
137     return SolverConstraintPtr(new SketchSolver_ConstraintCoincidence(theConstraint));
138   } else if (theConstraint->getKind() == SketchPlugin_ConstraintCollinear::ID()) {
139     return SolverConstraintPtr(new SketchSolver_ConstraintCollinear(theConstraint));
140   } else if (theConstraint->getKind() == SketchPlugin_ConstraintDistance::ID() ||
141              theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() ||
142              theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID()) {
143     return SolverConstraintPtr(new SketchSolver_ConstraintDistance(theConstraint));
144   } else if (theConstraint->getKind() == SketchPlugin_ConstraintEqual::ID()) {
145     return SolverConstraintPtr(new SketchSolver_ConstraintEqual(theConstraint));
146   } else if (theConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) {
147     return SolverConstraintPtr(new SketchSolver_ConstraintLength(theConstraint));
148   } else if (theConstraint->getKind() == SketchPlugin_ConstraintMiddle::ID()) {
149     return SolverConstraintPtr(new SketchSolver_ConstraintMiddle(theConstraint));
150   } else if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
151     return SolverConstraintPtr(new SketchSolver_ConstraintMirror(theConstraint));
152   } else if (theConstraint->getKind() == SketchPlugin_ConstraintTangent::ID()) {
153     return SolverConstraintPtr(new SketchSolver_ConstraintTangent(theConstraint));
154   } else if (theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID()) {
155     return SolverConstraintPtr(new SketchSolver_ConstraintFixed(theConstraint));
156   } else if (theConstraint->getKind() == SketchPlugin_MultiTranslation::ID()) {
157     return SolverConstraintPtr(new SketchSolver_ConstraintMultiTranslation(theConstraint));
158   } else if (theConstraint->getKind() == SketchPlugin_MultiRotation::ID()) {
159     return SolverConstraintPtr(new SketchSolver_ConstraintMultiRotation(theConstraint));
160   } else if (theConstraint->getKind() == SketchPlugin_ConstraintAngle::ID()) {
161     return SolverConstraintPtr(new SketchSolver_ConstraintAngle(theConstraint));
162   }
163   // All other types of constraints
164   return SolverConstraintPtr(new SketchSolver_Constraint(theConstraint));
165 }
166
167 std::shared_ptr<SketchSolver_ConstraintMovement> PlaneGCSSolver_Tools::createMovementConstraint(
168     FeaturePtr theMovedFeature)
169 {
170   return std::shared_ptr<SketchSolver_ConstraintMovement>(
171       new SketchSolver_ConstraintMovement(theMovedFeature));
172 }
173
174 std::shared_ptr<SketchSolver_ConstraintMovement> PlaneGCSSolver_Tools::createMovementConstraint(
175     AttributePtr theMovedAttribute)
176 {
177   return std::shared_ptr<SketchSolver_ConstraintMovement>(
178       new SketchSolver_ConstraintMovement(theMovedAttribute));
179 }
180
181
182
183 ConstraintWrapperPtr PlaneGCSSolver_Tools::createConstraint(
184     ConstraintPtr theConstraint,
185     const SketchSolver_ConstraintType& theType,
186     const EntityWrapperPtr& theValue,
187     const EntityWrapperPtr& thePoint1,
188     const EntityWrapperPtr& thePoint2,
189     const EntityWrapperPtr& theEntity1,
190     const EntityWrapperPtr& theEntity2)
191 {
192   ConstraintWrapperPtr aResult;
193   ScalarWrapperPtr anIntermediate;
194
195   std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(thePoint1);
196   std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(thePoint2);
197
198   switch (theType) {
199   case CONSTRAINT_PT_PT_COINCIDENT:
200     aResult = createConstraintCoincidence(aPoint1, aPoint2);
201     break;
202   case CONSTRAINT_PT_ON_CURVE:
203     aResult = createConstraintPointOnEntity(theType, aPoint1, GCS_EDGE_WRAPPER(theEntity1));
204     break;
205   case CONSTRAINT_MIDDLE_POINT:
206     aResult = createConstraintMiddlePoint(aPoint1, GCS_EDGE_WRAPPER(theEntity1), aPoint2);
207     break;
208   case CONSTRAINT_PT_PT_DISTANCE:
209     aResult = createConstraintDistancePointPoint(GCS_SCALAR_WRAPPER(theValue), aPoint1, aPoint2);
210     break;
211   case CONSTRAINT_PT_LINE_DISTANCE:
212     aResult = createConstraintDistancePointLine(GCS_SCALAR_WRAPPER(theValue),
213                                                 aPoint1,
214                                                 GCS_EDGE_WRAPPER(theEntity1));
215     break;
216   case CONSTRAINT_HORIZONTAL_DISTANCE:
217   case CONSTRAINT_VERTICAL_DISTANCE:
218     aResult = createConstraintHVDistance(theType, GCS_SCALAR_WRAPPER(theValue), aPoint1, aPoint2);
219     break;
220   case CONSTRAINT_RADIUS:
221     aResult = createConstraintRadius(GCS_SCALAR_WRAPPER(theValue),
222                                      GCS_EDGE_WRAPPER(theEntity1));
223     break;
224   case CONSTRAINT_ANGLE:
225     aResult = createConstraintAngle(theConstraint,
226                   GCS_SCALAR_WRAPPER(theValue),
227                   GCS_EDGE_WRAPPER(theEntity1), GCS_EDGE_WRAPPER(theEntity2));
228     break;
229   case CONSTRAINT_FIXED:
230     break;
231   case CONSTRAINT_HORIZONTAL:
232   case CONSTRAINT_VERTICAL:
233     aResult = createConstraintHorizVert(theType, GCS_EDGE_WRAPPER(theEntity1));
234     break;
235   case CONSTRAINT_PARALLEL:
236     aResult = createConstraintParallel(GCS_EDGE_WRAPPER(theEntity1),
237                                        GCS_EDGE_WRAPPER(theEntity2));
238     break;
239   case CONSTRAINT_PERPENDICULAR:
240     aResult = createConstraintPerpendicular(GCS_EDGE_WRAPPER(theEntity1),
241                                             GCS_EDGE_WRAPPER(theEntity2));
242     break;
243   case CONSTRAINT_EQUAL_LINES:
244   case CONSTRAINT_EQUAL_ELLIPSES:
245     anIntermediate = GCS_SCALAR_WRAPPER(theValue); // parameter is used to store length of lines
246   case CONSTRAINT_EQUAL_LINE_ARC:
247   case CONSTRAINT_EQUAL_RADIUS:
248     aResult = createConstraintEqual(theType,
249                                     GCS_EDGE_WRAPPER(theEntity1),
250                                     GCS_EDGE_WRAPPER(theEntity2),
251                                     anIntermediate);
252     break;
253   default:
254     break;
255   }
256
257   return aResult;
258 }
259
260 std::shared_ptr<GeomAPI_Pnt2d> PlaneGCSSolver_Tools::point(EntityWrapperPtr theEntity)
261 {
262   if (theEntity->type() != ENTITY_POINT)
263     return std::shared_ptr<GeomAPI_Pnt2d>();
264
265   std::shared_ptr<PlaneGCSSolver_PointWrapper> aPointWrapper =
266       std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
267   const GCSPointPtr& aPoint = aPointWrapper->point();
268   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(*aPoint->x, *aPoint->y));
269 }
270
271 std::shared_ptr<GeomAPI_Lin2d> PlaneGCSSolver_Tools::line(EntityWrapperPtr theEntity)
272 {
273   if (theEntity->type() != ENTITY_LINE)
274     return std::shared_ptr<GeomAPI_Lin2d>();
275
276   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
277       std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
278   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
279   return std::shared_ptr<GeomAPI_Lin2d>(
280       new GeomAPI_Lin2d(*(aLine->p1.x), *(aLine->p1.y), *(aLine->p2.x), *(aLine->p2.y)));
281 }
282
283 std::shared_ptr<GeomAPI_Lin2d> PlaneGCSSolver_Tools::line(FeaturePtr theFeature)
284 {
285   if (theFeature->getKind() != SketchPlugin_Line::ID())
286     return std::shared_ptr<GeomAPI_Lin2d>();
287
288   AttributePoint2DPtr aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
289       theFeature->attribute(SketchPlugin_Line::START_ID()));
290   AttributePoint2DPtr aEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
291       theFeature->attribute(SketchPlugin_Line::END_ID()));
292
293   return std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aStart->pnt(), aEnd->pnt()));
294 }
295
296 std::shared_ptr<GeomAPI_Circ2d> PlaneGCSSolver_Tools::circle(EntityWrapperPtr theEntity)
297 {
298   if (theEntity->type() != ENTITY_CIRCLE && theEntity->type() != ENTITY_ARC)
299     return std::shared_ptr<GeomAPI_Circ2d>();
300
301   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
302     std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
303   std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(anEntity->entity());
304   return std::shared_ptr<GeomAPI_Circ2d>(
305     new GeomAPI_Circ2d(*(aCirc->center.x), *(aCirc->center.y), *(aCirc->rad)));
306 }
307
308 std::shared_ptr<GeomAPI_Ellipse2d> PlaneGCSSolver_Tools::ellipse(EntityWrapperPtr theEntity)
309 {
310   if (theEntity->type() != ENTITY_ELLIPSE && theEntity->type() != ENTITY_ELLIPTIC_ARC)
311     return std::shared_ptr<GeomAPI_Ellipse2d>();
312
313   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
314     std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
315   std::shared_ptr<GCS::Ellipse> anEllipse =
316       std::dynamic_pointer_cast<GCS::Ellipse>(anEntity->entity());
317
318   std::shared_ptr<GeomAPI_Pnt2d> aCenter(
319       new GeomAPI_Pnt2d(*(anEllipse->center.x), *(anEllipse->center.y)));
320   std::shared_ptr<GeomAPI_Dir2d> anAxis(new GeomAPI_Dir2d(
321       *(anEllipse->focus1.x) - *(anEllipse->center.x),
322       *(anEllipse->focus1.y) - *(anEllipse->center.y)));
323
324   return std::shared_ptr<GeomAPI_Ellipse2d>(
325       new GeomAPI_Ellipse2d(aCenter, anAxis, anEllipse->getRadMaj(), *anEllipse->radmin));
326 }
327
328 void PlaneGCSSolver_Tools::recalculateArcParameters(EntityWrapperPtr theArc)
329 {
330   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEdge =
331       std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theArc);
332   if (!anEdge)
333     return;
334
335   if (anEdge->type() == ENTITY_ARC) {
336     std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEdge->entity());
337
338     GCS::Point aCenter = anArc->center;
339     GCS::Point aStartPnt = anArc->start;
340     GCS::Point aEndPnt = anArc->end;
341
342     *anArc->rad = distance(aCenter, aStartPnt);
343
344     static GeomDir2dPtr OX(new GeomAPI_Dir2d(1.0, 0.0));
345
346     GeomDir2dPtr aDir(new GeomAPI_Dir2d(*aStartPnt.x - *aCenter.x, *aStartPnt.y - *aCenter.y));
347     *anArc->startAngle = OX->angle(aDir);
348
349     aDir.reset(new GeomAPI_Dir2d(*aEndPnt.x - *aCenter.x, *aEndPnt.y - *aCenter.y));
350     *anArc->endAngle = OX->angle(aDir);
351   }
352   else if (anEdge->type() == ENTITY_ELLIPTIC_ARC) {
353     std::shared_ptr<GCS::ArcOfEllipse> aEllArc =
354         std::dynamic_pointer_cast<GCS::ArcOfEllipse>(anEdge->entity());
355
356     GeomPnt2dPtr aCenter(new GeomAPI_Pnt2d(*aEllArc->center.x, *aEllArc->center.y));
357     GeomPnt2dPtr aStartPnt(new GeomAPI_Pnt2d(*aEllArc->start.x, *aEllArc->start.y));
358     GeomPnt2dPtr aEndPnt(new GeomAPI_Pnt2d(*aEllArc->end.x, *aEllArc->end.y));
359
360     GeomDir2dPtr anAxis(new GeomAPI_Dir2d(*aEllArc->focus1.x - aCenter->x(),
361                                           *aEllArc->focus1.y - aCenter->y()));
362     GeomAPI_Ellipse2d anEllipse(aCenter, anAxis, aEllArc->getRadMaj(), *aEllArc->radmin);
363     anEllipse.parameter(aStartPnt, 1.e-4, *aEllArc->startAngle);
364     anEllipse.parameter(aEndPnt, 1.e-4, *aEllArc->endAngle);
365   }
366 }
367
368
369
370 GCS::SET_pD PlaneGCSSolver_Tools::parameters(const EntityWrapperPtr& theEntity)
371 {
372   switch (theEntity->type()) {
373   case ENTITY_SCALAR:
374   case ENTITY_ANGLE:
375     return scalarParameters(GCS_SCALAR_WRAPPER(theEntity));
376   case ENTITY_POINT:
377     return pointParameters(GCS_POINT_WRAPPER(theEntity));
378   case ENTITY_LINE:
379     return lineParameters(GCS_EDGE_WRAPPER(theEntity));
380   case ENTITY_CIRCLE:
381     return circleParameters(GCS_EDGE_WRAPPER(theEntity));
382   case ENTITY_ARC:
383     return arcParameters(GCS_EDGE_WRAPPER(theEntity));
384   case ENTITY_ELLIPSE:
385     return ellipseParameters(GCS_EDGE_WRAPPER(theEntity));
386   case ENTITY_ELLIPTIC_ARC:
387     return ellipticArcParameters(GCS_EDGE_WRAPPER(theEntity));
388   default: break;
389   }
390   return GCS::SET_pD();
391 }
392
393
394
395
396
397
398 // ================   Auxiliary functions   ==========================
399 ConstraintWrapperPtr createConstraintCoincidence(
400     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
401     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
402 {
403   GCSPointPtr aPoint1 = thePoint1->point();
404   GCSPointPtr aPoint2 = thePoint2->point();
405
406   // Create equality constraint for corresponding attributes of the points
407   std::list<GCSConstraintPtr> aConstrList;
408   aConstrList.push_back(
409       GCSConstraintPtr(new GCS::ConstraintEqual(aPoint1->x, aPoint2->x)));
410   aConstrList.push_back(
411       GCSConstraintPtr(new GCS::ConstraintEqual(aPoint1->y, aPoint2->y)));
412
413   return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(
414       aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
415 }
416
417 ConstraintWrapperPtr createConstraintPointOnEntity(
418     const SketchSolver_ConstraintType& theType,
419     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
420     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
421 {
422   GCSConstraintPtr aNewConstr;
423
424   switch (theEntity->type()) {
425   case ENTITY_LINE: {
426     std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
427     aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnLine(*(thePoint->point()), *aLine));
428     break;
429     }
430   case ENTITY_ARC:
431   case ENTITY_CIRCLE: {
432     std::shared_ptr<GCS::Circle> aCirc =
433       std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
434     aNewConstr = GCSConstraintPtr(
435         new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
436     break;
437     }
438   case ENTITY_ELLIPSE:
439   case ENTITY_ELLIPTIC_ARC: {
440     std::shared_ptr<GCS::Ellipse> anEllipse =
441         std::dynamic_pointer_cast<GCS::Ellipse>(theEntity->entity());
442     aNewConstr = GCSConstraintPtr(
443         new GCS::ConstraintPointOnEllipse(*(thePoint->point()), *anEllipse));
444     break;
445     }
446   default:
447     return ConstraintWrapperPtr();
448   }
449
450   return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
451 }
452
453 ConstraintWrapperPtr createConstraintMiddlePoint(
454     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
455     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity,
456     std::shared_ptr<PlaneGCSSolver_PointWrapper> theAuxParameters)
457 {
458   std::list<GCSConstraintPtr> aConstrList;
459
460   GCSPointPtr aPoint = thePoint->point();
461   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
462   if (aLine) {
463     aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPointOnLine(*aPoint, *aLine)));
464     aConstrList.push_back(
465         GCSConstraintPtr(new GCS::ConstraintPointOnPerpBisector(*aPoint, aLine->p1, aLine->p2)));
466   }
467   else {
468     std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(theEntity->entity());
469     if (anArc) {
470       double* u = theAuxParameters->point()->x;
471       double* diff = theAuxParameters->point()->y;
472       *u = (*anArc->startAngle + *anArc->endAngle) * 0.5;
473       *diff = (*anArc->endAngle - *anArc->startAngle) * 0.5;
474
475       aConstrList.push_back(GCSConstraintPtr(
476           new GCS::ConstraintCurveValue(*aPoint, aPoint->x, *anArc, u)));
477       aConstrList.push_back(GCSConstraintPtr(
478           new GCS::ConstraintCurveValue(*aPoint, aPoint->y, *anArc, u)));
479       aConstrList.push_back(GCSConstraintPtr(
480           new GCS::ConstraintDifference(anArc->startAngle, u, diff)));
481       aConstrList.push_back(GCSConstraintPtr(
482           new GCS::ConstraintDifference(u, anArc->endAngle, diff)));
483     }
484   }
485
486   return aConstrList.empty() ? ConstraintWrapperPtr() : ConstraintWrapperPtr(
487       new PlaneGCSSolver_ConstraintWrapper(aConstrList, CONSTRAINT_MIDDLE_POINT));
488 }
489
490
491 ConstraintWrapperPtr createConstraintDistancePointPoint(
492     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
493     std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint1,
494     std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint2)
495 {
496   GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
497       *(thePoint1->point()), *(thePoint2->point()), theValue->scalar()));
498   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
499       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
500   aResult->setValueParameter(theValue);
501   return aResult;
502 }
503
504 ConstraintWrapperPtr createConstraintDistancePointLine(
505     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
506     std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint,
507     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
508 {
509   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
510   GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
511       *(thePoint->point()), *(aLine), theValue->scalar()));
512   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
513       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
514   aResult->setValueParameter(theValue);
515   return aResult;
516 }
517
518 ConstraintWrapperPtr createConstraintHVDistance(
519     const SketchSolver_ConstraintType& theType,
520     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
521     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
522     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
523 {
524   GCSPointPtr aPoint1 = thePoint1->point();
525   GCSPointPtr aPoint2 = thePoint2->point();
526
527   double *aParam1, *aParam2;
528   if (theType == CONSTRAINT_HORIZONTAL_DISTANCE) {
529     aParam1 = aPoint1->x;
530     aParam2 = aPoint2->x;
531   } else if (theType == CONSTRAINT_VERTICAL_DISTANCE) {
532     aParam1 = aPoint1->y;
533     aParam2 = aPoint2->y;
534   }
535
536   GCSConstraintPtr aNewConstr(new GCS::ConstraintDifference(aParam1, aParam2, theValue->scalar()));
537
538   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
539       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
540   aResult->setValueParameter(theValue);
541   return aResult;
542 }
543
544 ConstraintWrapperPtr createConstraintRadius(
545     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
546     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
547 {
548   std::shared_ptr<GCS::Circle> aCircle =
549     std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
550   GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->scalar()));
551   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
552       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_RADIUS));
553   aResult->setValueParameter(theValue);
554   return aResult;
555 }
556
557 ConstraintWrapperPtr createConstraintAngle(
558     ConstraintPtr theConstraint,
559     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
560     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
561     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
562 {
563   std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
564   bool isLine1Rev = theConstraint->boolean(
565       SketchPlugin_ConstraintAngle::ANGLE_REVERSED_FIRST_LINE_ID())->value();
566   GCS::Point aLine1Pt1 = isLine1Rev ? aLine1->p2 : aLine1->p1;
567   GCS::Point aLine1Pt2 = isLine1Rev ? aLine1->p1 : aLine1->p2;
568
569   std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
570   bool isLine2Rev = theConstraint->boolean(
571       SketchPlugin_ConstraintAngle::ANGLE_REVERSED_SECOND_LINE_ID())->value();
572   GCS::Point aLine2Pt1 = isLine2Rev ? aLine2->p2 : aLine2->p1;
573   GCS::Point aLine2Pt2 = isLine2Rev ? aLine2->p1 : aLine2->p2;
574
575   GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
576       aLine1Pt1, aLine1Pt2, aLine2Pt1, aLine2Pt2, theValue->scalar()));
577
578   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
579       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_ANGLE));
580   aResult->setValueParameter(theValue);
581   return aResult;
582 }
583
584 ConstraintWrapperPtr createConstraintHorizVert(
585     const SketchSolver_ConstraintType& theType,
586     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
587 {
588   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
589   GCSConstraintPtr aNewConstr;
590   if (theType == CONSTRAINT_HORIZONTAL)
591     aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.y, aLine->p2.y));
592   else
593     aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
594
595   return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
596 }
597
598 ConstraintWrapperPtr createConstraintParallel(
599     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
600     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
601 {
602   std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
603   std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
604   GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
605
606   return ConstraintWrapperPtr(
607       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PARALLEL));
608 }
609
610 ConstraintWrapperPtr createConstraintPerpendicular(
611     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
612     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
613 {
614   std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
615   std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
616
617   std::shared_ptr<GCS::Circle> aCirc1 =
618       std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
619   std::shared_ptr<GCS::Circle> aCirc2 =
620       std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
621
622   GCSConstraintPtr aNewConstr;
623   if (aLine1 && aLine2)
624     aNewConstr.reset(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
625   else {
626     if (aLine1 && aCirc2)
627       aCirc1 = aCirc2;
628     else if (aLine2 && aCirc1)
629       aLine1 = aLine2;
630
631     aNewConstr.reset(new GCS::ConstraintPointOnLine(aCirc1->center, *aLine1));
632   }
633
634   return ConstraintWrapperPtr(
635       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PERPENDICULAR));
636 }
637
638 ConstraintWrapperPtr createConstraintEqual(
639     const SketchSolver_ConstraintType& theType,
640     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
641     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2,
642     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theIntermed)
643 {
644   if (theType == CONSTRAINT_EQUAL_LINE_ARC)
645     return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
646
647   std::list<GCSConstraintPtr> aConstrList;
648   if (theType == CONSTRAINT_EQUAL_LINES) {
649     std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
650     std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
651
652     aConstrList.push_back(GCSConstraintPtr(
653         new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->scalar())));
654     aConstrList.push_back(GCSConstraintPtr(
655         new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->scalar())));
656     // update value of intermediate parameter
657     theIntermed->setValue(distance(aLine1->p1, aLine1->p2));
658   }
659   else if (theType == CONSTRAINT_EQUAL_ELLIPSES) {
660     std::shared_ptr<GCS::Ellipse> anEllipse1 =
661         std::dynamic_pointer_cast<GCS::Ellipse>(theEntity1->entity());
662     std::shared_ptr<GCS::Ellipse> anEllipse2 =
663         std::dynamic_pointer_cast<GCS::Ellipse>(theEntity2->entity());
664
665     aConstrList.push_back(GCSConstraintPtr(
666         new GCS::ConstraintEqual(anEllipse1->radmin, anEllipse2->radmin)));
667     aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
668         anEllipse1->center, anEllipse1->focus1, theIntermed->scalar())));
669     aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
670         anEllipse2->center, anEllipse2->focus1, theIntermed->scalar())));
671     // update value of intermediate parameter
672     theIntermed->setValue(distance(anEllipse1->center, anEllipse1->focus1));
673   }
674   else {
675     std::shared_ptr<GCS::Circle> aCirc1 =
676         std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
677     std::shared_ptr<GCS::Circle> aCirc2 =
678         std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
679     aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
680   }
681
682   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
683       new PlaneGCSSolver_ConstraintWrapper(aConstrList, theType));
684   if (theIntermed)
685     aResult->setValueParameter(theIntermed);
686   return aResult;
687 }
688
689 GCS::SET_pD scalarParameters(const ScalarWrapperPtr& theScalar)
690 {
691   GCS::SET_pD aParams;
692   aParams.insert(theScalar->scalar());
693   return aParams;
694 }
695
696 GCS::SET_pD pointParameters(const PointWrapperPtr& thePoint)
697 {
698   GCS::SET_pD aParams;
699   aParams.insert(thePoint->point()->x);
700   aParams.insert(thePoint->point()->y);
701   return aParams;
702 }
703
704 GCS::SET_pD lineParameters(const EdgeWrapperPtr& theLine)
705 {
706   GCS::SET_pD aParams;
707   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theLine->entity());
708   aParams.insert(aLine->p1.x);
709   aParams.insert(aLine->p1.y);
710   aParams.insert(aLine->p2.x);
711   aParams.insert(aLine->p2.y);
712   return aParams;
713 }
714
715 GCS::SET_pD circleParameters(const EdgeWrapperPtr& theCircle)
716 {
717   GCS::SET_pD aParams;
718   std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theCircle->entity());
719   aParams.insert(aCirc->center.x);
720   aParams.insert(aCirc->center.y);
721   aParams.insert(aCirc->rad);
722   return aParams;
723 }
724
725 GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc)
726 {
727   GCS::SET_pD aParams = circleParameters(theArc);
728   std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(theArc->entity());
729   aParams.insert(anArc->start.x);
730   aParams.insert(anArc->start.y);
731   aParams.insert(anArc->end.x);
732   aParams.insert(anArc->end.y);
733   aParams.insert(anArc->startAngle);
734   aParams.insert(anArc->endAngle);
735   return aParams;
736 }
737
738 GCS::SET_pD ellipseParameters(const EdgeWrapperPtr& theEllipse)
739 {
740   GCS::SET_pD aParams;
741   std::shared_ptr<GCS::Ellipse> anEllipse =
742       std::dynamic_pointer_cast<GCS::Ellipse>(theEllipse->entity());
743   aParams.insert(anEllipse->center.x);
744   aParams.insert(anEllipse->center.y);
745   aParams.insert(anEllipse->focus1.x);
746   aParams.insert(anEllipse->focus1.y);
747   aParams.insert(anEllipse->radmin);
748   return aParams;
749 }
750
751 GCS::SET_pD ellipticArcParameters(const EdgeWrapperPtr& theEllipticArc)
752 {
753   GCS::SET_pD aParams = ellipseParameters(theEllipticArc);
754   std::shared_ptr<GCS::ArcOfEllipse> anArc =
755       std::dynamic_pointer_cast<GCS::ArcOfEllipse>(theEllipticArc->entity());
756   aParams.insert(anArc->start.x);
757   aParams.insert(anArc->start.y);
758   aParams.insert(anArc->end.x);
759   aParams.insert(anArc->end.y);
760   aParams.insert(anArc->startAngle);
761   aParams.insert(anArc->endAngle);
762   return aParams;
763 }
764
765 double distance(const GCS::Point& thePnt1, const GCS::Point& thePnt2)
766 {
767   double x = *thePnt1.x - *thePnt2.x;
768   double y = *thePnt1.y - *thePnt2.y;
769   return sqrt(x*x + y*y);
770 }