]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp
Salome HOME
11c265dd0eed1751bafd9071abe41181595a0b31
[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
126
127
128
129
130 SolverConstraintPtr PlaneGCSSolver_Tools::createConstraint(ConstraintPtr theConstraint)
131 {
132   if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
133       theConstraint->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
134     return SolverConstraintPtr(new SketchSolver_ConstraintCoincidence(theConstraint));
135   } else if (theConstraint->getKind() == SketchPlugin_ConstraintCollinear::ID()) {
136     return SolverConstraintPtr(new SketchSolver_ConstraintCollinear(theConstraint));
137   } else if (theConstraint->getKind() == SketchPlugin_ConstraintDistance::ID() ||
138              theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() ||
139              theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID()) {
140     return SolverConstraintPtr(new SketchSolver_ConstraintDistance(theConstraint));
141   } else if (theConstraint->getKind() == SketchPlugin_ConstraintEqual::ID()) {
142     return SolverConstraintPtr(new SketchSolver_ConstraintEqual(theConstraint));
143   } else if (theConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) {
144     return SolverConstraintPtr(new SketchSolver_ConstraintLength(theConstraint));
145   } else if (theConstraint->getKind() == SketchPlugin_ConstraintMiddle::ID()) {
146     return SolverConstraintPtr(new SketchSolver_ConstraintMiddle(theConstraint));
147   } else if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
148     return SolverConstraintPtr(new SketchSolver_ConstraintMirror(theConstraint));
149   } else if (theConstraint->getKind() == SketchPlugin_ConstraintTangent::ID()) {
150     return SolverConstraintPtr(new SketchSolver_ConstraintTangent(theConstraint));
151   } else if (theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID()) {
152     return SolverConstraintPtr(new SketchSolver_ConstraintFixed(theConstraint));
153   } else if (theConstraint->getKind() == SketchPlugin_MultiTranslation::ID()) {
154     return SolverConstraintPtr(new SketchSolver_ConstraintMultiTranslation(theConstraint));
155   } else if (theConstraint->getKind() == SketchPlugin_MultiRotation::ID()) {
156     return SolverConstraintPtr(new SketchSolver_ConstraintMultiRotation(theConstraint));
157   } else if (theConstraint->getKind() == SketchPlugin_ConstraintAngle::ID()) {
158     return SolverConstraintPtr(new SketchSolver_ConstraintAngle(theConstraint));
159   }
160   // All other types of constraints
161   return SolverConstraintPtr(new SketchSolver_Constraint(theConstraint));
162 }
163
164 std::shared_ptr<SketchSolver_ConstraintMovement> PlaneGCSSolver_Tools::createMovementConstraint(
165     FeaturePtr theMovedFeature)
166 {
167   return std::shared_ptr<SketchSolver_ConstraintMovement>(
168       new SketchSolver_ConstraintMovement(theMovedFeature));
169 }
170
171 std::shared_ptr<SketchSolver_ConstraintMovement> PlaneGCSSolver_Tools::createMovementConstraint(
172     AttributePtr theMovedAttribute)
173 {
174   return std::shared_ptr<SketchSolver_ConstraintMovement>(
175       new SketchSolver_ConstraintMovement(theMovedAttribute));
176 }
177
178
179
180 ConstraintWrapperPtr PlaneGCSSolver_Tools::createConstraint(
181     ConstraintPtr theConstraint,
182     const SketchSolver_ConstraintType& theType,
183     const EntityWrapperPtr& theValue,
184     const EntityWrapperPtr& thePoint1,
185     const EntityWrapperPtr& thePoint2,
186     const EntityWrapperPtr& theEntity1,
187     const EntityWrapperPtr& theEntity2)
188 {
189   ConstraintWrapperPtr aResult;
190   ScalarWrapperPtr anIntermediate;
191
192   std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(thePoint1);
193   std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(thePoint2);
194
195   switch (theType) {
196   case CONSTRAINT_PT_PT_COINCIDENT:
197     aResult = createConstraintCoincidence(aPoint1, aPoint2);
198     break;
199   case CONSTRAINT_PT_ON_CURVE:
200     aResult = createConstraintPointOnEntity(theType, aPoint1, GCS_EDGE_WRAPPER(theEntity1));
201     break;
202   case CONSTRAINT_MIDDLE_POINT:
203     aResult = createConstraintMiddlePoint(aPoint1, GCS_EDGE_WRAPPER(theEntity1), aPoint2);
204     break;
205   case CONSTRAINT_PT_PT_DISTANCE:
206     aResult = createConstraintDistancePointPoint(GCS_SCALAR_WRAPPER(theValue), aPoint1, aPoint2);
207     break;
208   case CONSTRAINT_PT_LINE_DISTANCE:
209     aResult = createConstraintDistancePointLine(GCS_SCALAR_WRAPPER(theValue),
210                                                 aPoint1,
211                                                 GCS_EDGE_WRAPPER(theEntity1));
212     break;
213   case CONSTRAINT_HORIZONTAL_DISTANCE:
214   case CONSTRAINT_VERTICAL_DISTANCE:
215     aResult = createConstraintHVDistance(theType, GCS_SCALAR_WRAPPER(theValue), aPoint1, aPoint2);
216     break;
217   case CONSTRAINT_RADIUS:
218     aResult = createConstraintRadius(GCS_SCALAR_WRAPPER(theValue),
219                                      GCS_EDGE_WRAPPER(theEntity1));
220     break;
221   case CONSTRAINT_ANGLE:
222     aResult = createConstraintAngle(theConstraint,
223                   GCS_SCALAR_WRAPPER(theValue),
224                   GCS_EDGE_WRAPPER(theEntity1), GCS_EDGE_WRAPPER(theEntity2));
225     break;
226   case CONSTRAINT_FIXED:
227     break;
228   case CONSTRAINT_HORIZONTAL:
229   case CONSTRAINT_VERTICAL:
230     aResult = createConstraintHorizVert(theType, GCS_EDGE_WRAPPER(theEntity1));
231     break;
232   case CONSTRAINT_PARALLEL:
233     aResult = createConstraintParallel(GCS_EDGE_WRAPPER(theEntity1),
234                                        GCS_EDGE_WRAPPER(theEntity2));
235     break;
236   case CONSTRAINT_PERPENDICULAR:
237     aResult = createConstraintPerpendicular(GCS_EDGE_WRAPPER(theEntity1),
238                                             GCS_EDGE_WRAPPER(theEntity2));
239     break;
240   case CONSTRAINT_EQUAL_LINES:
241     anIntermediate = GCS_SCALAR_WRAPPER(theValue); // parameter is used to store length of lines
242   case CONSTRAINT_EQUAL_LINE_ARC:
243   case CONSTRAINT_EQUAL_RADIUS:
244     aResult = createConstraintEqual(theType,
245                                     GCS_EDGE_WRAPPER(theEntity1),
246                                     GCS_EDGE_WRAPPER(theEntity2),
247                                     anIntermediate);
248     break;
249   default:
250     break;
251   }
252
253   return aResult;
254 }
255
256 std::shared_ptr<GeomAPI_Pnt2d> PlaneGCSSolver_Tools::point(EntityWrapperPtr theEntity)
257 {
258   if (theEntity->type() != ENTITY_POINT)
259     return std::shared_ptr<GeomAPI_Pnt2d>();
260
261   std::shared_ptr<PlaneGCSSolver_PointWrapper> aPointWrapper =
262       std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
263   const GCSPointPtr& aPoint = aPointWrapper->point();
264   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(*aPoint->x, *aPoint->y));
265 }
266
267 std::shared_ptr<GeomAPI_Lin2d> PlaneGCSSolver_Tools::line(EntityWrapperPtr theEntity)
268 {
269   if (theEntity->type() != ENTITY_LINE)
270     return std::shared_ptr<GeomAPI_Lin2d>();
271
272   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
273       std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
274   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
275   return std::shared_ptr<GeomAPI_Lin2d>(
276       new GeomAPI_Lin2d(*(aLine->p1.x), *(aLine->p1.y), *(aLine->p2.x), *(aLine->p2.y)));
277 }
278
279 std::shared_ptr<GeomAPI_Lin2d> PlaneGCSSolver_Tools::line(FeaturePtr theFeature)
280 {
281   if (theFeature->getKind() != SketchPlugin_Line::ID())
282     return std::shared_ptr<GeomAPI_Lin2d>();
283
284   AttributePoint2DPtr aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
285       theFeature->attribute(SketchPlugin_Line::START_ID()));
286   AttributePoint2DPtr aEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
287       theFeature->attribute(SketchPlugin_Line::END_ID()));
288
289   return std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aStart->pnt(), aEnd->pnt()));
290 }
291
292 std::shared_ptr<GeomAPI_Circ2d> PlaneGCSSolver_Tools::circle(EntityWrapperPtr theEntity)
293 {
294   if (theEntity->type() != ENTITY_CIRCLE && theEntity->type() != ENTITY_ARC)
295     return std::shared_ptr<GeomAPI_Circ2d>();
296
297   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
298     std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
299   std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(anEntity->entity());
300   return std::shared_ptr<GeomAPI_Circ2d>(
301     new GeomAPI_Circ2d(*(aCirc->center.x), *(aCirc->center.y), *(aCirc->rad)));
302 }
303
304 std::shared_ptr<GeomAPI_Ellipse2d> PlaneGCSSolver_Tools::ellipse(EntityWrapperPtr theEntity)
305 {
306   if (theEntity->type() != ENTITY_ELLIPSE && theEntity->type() != ENTITY_ELLIPTICAL_ARC)
307     return std::shared_ptr<GeomAPI_Ellipse2d>();
308
309   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
310     std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
311   std::shared_ptr<GCS::Ellipse> anEllipse =
312       std::dynamic_pointer_cast<GCS::Ellipse>(anEntity->entity());
313
314   std::shared_ptr<GeomAPI_Pnt2d> aCenter(
315       new GeomAPI_Pnt2d(*(anEllipse->center.x), *(anEllipse->center.y)));
316   std::shared_ptr<GeomAPI_Dir2d> anAxis(new GeomAPI_Dir2d(
317       *(anEllipse->focus1.x) - *(anEllipse->center.x),
318       *(anEllipse->focus1.y) - *(anEllipse->center.y)));
319
320   return std::shared_ptr<GeomAPI_Ellipse2d>(
321       new GeomAPI_Ellipse2d(aCenter, anAxis, anEllipse->getRadMaj(), *anEllipse->radmin));
322 }
323
324
325
326 GCS::SET_pD PlaneGCSSolver_Tools::parameters(const EntityWrapperPtr& theEntity)
327 {
328   switch (theEntity->type()) {
329   case ENTITY_SCALAR:
330   case ENTITY_ANGLE:
331     return scalarParameters(GCS_SCALAR_WRAPPER(theEntity));
332   case ENTITY_POINT:
333     return pointParameters(GCS_POINT_WRAPPER(theEntity));
334   case ENTITY_LINE:
335     return lineParameters(GCS_EDGE_WRAPPER(theEntity));
336   case ENTITY_CIRCLE:
337     return circleParameters(GCS_EDGE_WRAPPER(theEntity));
338   case ENTITY_ARC:
339     return arcParameters(GCS_EDGE_WRAPPER(theEntity));
340   case ENTITY_ELLIPSE:
341     return ellipseParameters(GCS_EDGE_WRAPPER(theEntity));
342   default: break;
343   }
344   return GCS::SET_pD();
345 }
346
347
348
349
350
351
352 // ================   Auxiliary functions   ==========================
353 ConstraintWrapperPtr createConstraintCoincidence(
354     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
355     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
356 {
357   GCSPointPtr aPoint1 = thePoint1->point();
358   GCSPointPtr aPoint2 = thePoint2->point();
359
360   // Create equality constraint for corresponding attributes of the points
361   std::list<GCSConstraintPtr> aConstrList;
362   aConstrList.push_back(
363       GCSConstraintPtr(new GCS::ConstraintEqual(aPoint1->x, aPoint2->x)));
364   aConstrList.push_back(
365       GCSConstraintPtr(new GCS::ConstraintEqual(aPoint1->y, aPoint2->y)));
366
367   return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(
368       aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
369 }
370
371 ConstraintWrapperPtr createConstraintPointOnEntity(
372     const SketchSolver_ConstraintType& theType,
373     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
374     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
375 {
376   GCSConstraintPtr aNewConstr;
377
378   switch (theEntity->type()) {
379   case ENTITY_LINE: {
380     std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
381     aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnLine(*(thePoint->point()), *aLine));
382     break;
383     }
384   case ENTITY_ARC:
385   case ENTITY_CIRCLE: {
386     std::shared_ptr<GCS::Circle> aCirc =
387       std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
388     aNewConstr = GCSConstraintPtr(
389         new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
390     break;
391     }
392   case ENTITY_ELLIPSE:
393   case ENTITY_ELLIPTICAL_ARC: {
394     std::shared_ptr<GCS::Ellipse> anEllipse =
395         std::dynamic_pointer_cast<GCS::Ellipse>(theEntity->entity());
396     aNewConstr = GCSConstraintPtr(
397         new GCS::ConstraintPointOnEllipse(*(thePoint->point()), *anEllipse));
398     break;
399     }
400   default:
401     return ConstraintWrapperPtr();
402   }
403
404   return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
405 }
406
407 ConstraintWrapperPtr createConstraintMiddlePoint(
408     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
409     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity,
410     std::shared_ptr<PlaneGCSSolver_PointWrapper> theAuxParameters)
411 {
412   std::list<GCSConstraintPtr> aConstrList;
413
414   GCSPointPtr aPoint = thePoint->point();
415   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
416   if (aLine) {
417     aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPointOnLine(*aPoint, *aLine)));
418     aConstrList.push_back(
419         GCSConstraintPtr(new GCS::ConstraintPointOnPerpBisector(*aPoint, aLine->p1, aLine->p2)));
420   }
421   else {
422     std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(theEntity->entity());
423     if (anArc) {
424       double* u = theAuxParameters->point()->x;
425       double* diff = theAuxParameters->point()->y;
426       *u = (*anArc->startAngle + *anArc->endAngle) * 0.5;
427       *diff = (*anArc->endAngle - *anArc->startAngle) * 0.5;
428
429       aConstrList.push_back(GCSConstraintPtr(
430           new GCS::ConstraintCurveValue(*aPoint, aPoint->x, *anArc, u)));
431       aConstrList.push_back(GCSConstraintPtr(
432           new GCS::ConstraintCurveValue(*aPoint, aPoint->y, *anArc, u)));
433       aConstrList.push_back(GCSConstraintPtr(
434           new GCS::ConstraintDifference(anArc->startAngle, u, diff)));
435       aConstrList.push_back(GCSConstraintPtr(
436           new GCS::ConstraintDifference(u, anArc->endAngle, diff)));
437     }
438   }
439
440   return aConstrList.empty() ? ConstraintWrapperPtr() : ConstraintWrapperPtr(
441       new PlaneGCSSolver_ConstraintWrapper(aConstrList, CONSTRAINT_MIDDLE_POINT));
442 }
443
444
445 ConstraintWrapperPtr createConstraintDistancePointPoint(
446     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
447     std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint1,
448     std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint2)
449 {
450   GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
451       *(thePoint1->point()), *(thePoint2->point()), theValue->scalar()));
452   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
453       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
454   aResult->setValueParameter(theValue);
455   return aResult;
456 }
457
458 ConstraintWrapperPtr createConstraintDistancePointLine(
459     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
460     std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint,
461     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
462 {
463   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
464   GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
465       *(thePoint->point()), *(aLine), theValue->scalar()));
466   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
467       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
468   aResult->setValueParameter(theValue);
469   return aResult;
470 }
471
472 ConstraintWrapperPtr createConstraintHVDistance(
473     const SketchSolver_ConstraintType& theType,
474     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
475     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
476     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
477 {
478   GCSPointPtr aPoint1 = thePoint1->point();
479   GCSPointPtr aPoint2 = thePoint2->point();
480
481   double *aParam1, *aParam2;
482   if (theType == CONSTRAINT_HORIZONTAL_DISTANCE) {
483     aParam1 = aPoint1->x;
484     aParam2 = aPoint2->x;
485   } else if (theType == CONSTRAINT_VERTICAL_DISTANCE) {
486     aParam1 = aPoint1->y;
487     aParam2 = aPoint2->y;
488   }
489
490   GCSConstraintPtr aNewConstr(new GCS::ConstraintDifference(aParam1, aParam2, theValue->scalar()));
491
492   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
493       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
494   aResult->setValueParameter(theValue);
495   return aResult;
496 }
497
498 ConstraintWrapperPtr createConstraintRadius(
499     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
500     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
501 {
502   std::shared_ptr<GCS::Circle> aCircle =
503     std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
504   GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->scalar()));
505   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
506       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_RADIUS));
507   aResult->setValueParameter(theValue);
508   return aResult;
509 }
510
511 ConstraintWrapperPtr createConstraintAngle(
512     ConstraintPtr theConstraint,
513     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
514     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
515     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
516 {
517   std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
518   bool isLine1Rev = theConstraint->boolean(
519       SketchPlugin_ConstraintAngle::ANGLE_REVERSED_FIRST_LINE_ID())->value();
520   GCS::Point aLine1Pt1 = isLine1Rev ? aLine1->p2 : aLine1->p1;
521   GCS::Point aLine1Pt2 = isLine1Rev ? aLine1->p1 : aLine1->p2;
522
523   std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
524   bool isLine2Rev = theConstraint->boolean(
525       SketchPlugin_ConstraintAngle::ANGLE_REVERSED_SECOND_LINE_ID())->value();
526   GCS::Point aLine2Pt1 = isLine2Rev ? aLine2->p2 : aLine2->p1;
527   GCS::Point aLine2Pt2 = isLine2Rev ? aLine2->p1 : aLine2->p2;
528
529   GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
530       aLine1Pt1, aLine1Pt2, aLine2Pt1, aLine2Pt2, theValue->scalar()));
531
532   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
533       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_ANGLE));
534   aResult->setValueParameter(theValue);
535   return aResult;
536 }
537
538 ConstraintWrapperPtr createConstraintHorizVert(
539     const SketchSolver_ConstraintType& theType,
540     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
541 {
542   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
543   GCSConstraintPtr aNewConstr;
544   if (theType == CONSTRAINT_HORIZONTAL)
545     aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.y, aLine->p2.y));
546   else
547     aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
548
549   return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
550 }
551
552 ConstraintWrapperPtr createConstraintParallel(
553     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
554     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
555 {
556   std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
557   std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
558   GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
559
560   return ConstraintWrapperPtr(
561       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PARALLEL));
562 }
563
564 ConstraintWrapperPtr createConstraintPerpendicular(
565     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
566     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
567 {
568   std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
569   std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
570
571   std::shared_ptr<GCS::Circle> aCirc1 =
572       std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
573   std::shared_ptr<GCS::Circle> aCirc2 =
574       std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
575
576   GCSConstraintPtr aNewConstr;
577   if (aLine1 && aLine2)
578     aNewConstr.reset(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
579   else {
580     if (aLine1 && aCirc2)
581       aCirc1 = aCirc2;
582     else if (aLine2 && aCirc1)
583       aLine1 = aLine2;
584
585     aNewConstr.reset(new GCS::ConstraintPointOnLine(aCirc1->center, *aLine1));
586   }
587
588   return ConstraintWrapperPtr(
589       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PERPENDICULAR));
590 }
591
592 ConstraintWrapperPtr createConstraintEqual(
593     const SketchSolver_ConstraintType& theType,
594     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
595     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2,
596     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theIntermed)
597 {
598   if (theType == CONSTRAINT_EQUAL_LINE_ARC)
599     return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
600
601   std::list<GCSConstraintPtr> aConstrList;
602   if (theType == CONSTRAINT_EQUAL_LINES) {
603     std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
604     std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
605
606     aConstrList.push_back(GCSConstraintPtr(
607         new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->scalar())));
608     aConstrList.push_back(GCSConstraintPtr(
609         new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->scalar())));
610     // update value of intermediate parameter
611     double x = *aLine1->p1.x - *aLine1->p2.x;
612     double y = *aLine1->p1.y - *aLine1->p2.y;
613     double aLen = sqrt(x*x + y*y);
614     theIntermed->setValue(aLen);
615   } else {
616     std::shared_ptr<GCS::Circle> aCirc1 =
617         std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
618     std::shared_ptr<GCS::Circle> aCirc2 =
619         std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
620
621     if (aCirc1 && aCirc2)
622       aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
623     else {
624       std::shared_ptr<GCS::Ellipse> anEllipse1 =
625           std::dynamic_pointer_cast<GCS::Ellipse>(theEntity1->entity());
626       std::shared_ptr<GCS::Ellipse> anEllipse2 =
627           std::dynamic_pointer_cast<GCS::Ellipse>(theEntity2->entity());
628
629       aConstrList.push_back(GCSConstraintPtr(
630           new GCS::ConstraintEqual(anEllipse1->radmin, anEllipse2->radmin)));
631       aConstrList.push_back(GCSConstraintPtr(
632           new GCS::ConstraintEqualMajorAxesConic(anEllipse1.get(), anEllipse2.get())));
633     }
634   }
635
636   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
637       new PlaneGCSSolver_ConstraintWrapper(aConstrList, theType));
638   if (theIntermed)
639     aResult->setValueParameter(theIntermed);
640   return aResult;
641 }
642
643 GCS::SET_pD scalarParameters(const ScalarWrapperPtr& theScalar)
644 {
645   GCS::SET_pD aParams;
646   aParams.insert(theScalar->scalar());
647   return aParams;
648 }
649
650 GCS::SET_pD pointParameters(const PointWrapperPtr& thePoint)
651 {
652   GCS::SET_pD aParams;
653   aParams.insert(thePoint->point()->x);
654   aParams.insert(thePoint->point()->y);
655   return aParams;
656 }
657
658 GCS::SET_pD lineParameters(const EdgeWrapperPtr& theLine)
659 {
660   GCS::SET_pD aParams;
661   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theLine->entity());
662   aParams.insert(aLine->p1.x);
663   aParams.insert(aLine->p1.y);
664   aParams.insert(aLine->p2.x);
665   aParams.insert(aLine->p2.y);
666   return aParams;
667 }
668
669 GCS::SET_pD circleParameters(const EdgeWrapperPtr& theCircle)
670 {
671   GCS::SET_pD aParams;
672   std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theCircle->entity());
673   aParams.insert(aCirc->center.x);
674   aParams.insert(aCirc->center.y);
675   aParams.insert(aCirc->rad);
676   return aParams;
677 }
678
679 GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc)
680 {
681   GCS::SET_pD aParams;
682   std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(theArc->entity());
683   aParams.insert(anArc->center.x);
684   aParams.insert(anArc->center.y);
685   aParams.insert(anArc->start.x);
686   aParams.insert(anArc->start.y);
687   aParams.insert(anArc->end.x);
688   aParams.insert(anArc->end.y);
689   aParams.insert(anArc->startAngle);
690   aParams.insert(anArc->endAngle);
691   aParams.insert(anArc->rad);
692   return aParams;
693 }
694
695 GCS::SET_pD ellipseParameters(const EdgeWrapperPtr& theEllipse)
696 {
697   GCS::SET_pD aParams;
698   std::shared_ptr<GCS::Ellipse> anEllipse =
699       std::dynamic_pointer_cast<GCS::Ellipse>(theEllipse->entity());
700   aParams.insert(anEllipse->center.x);
701   aParams.insert(anEllipse->center.y);
702   aParams.insert(anEllipse->focus1.x);
703   aParams.insert(anEllipse->focus1.y);
704   aParams.insert(anEllipse->radmin);
705   return aParams;
706 }