Salome HOME
1645e73f897c244016d425a6b91d1bc989f2b2ac
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_Tools.cpp
1 // Copyright (C) 2014-2023  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_PointArrayWrapper.h>
23 #include <PlaneGCSSolver_PointWrapper.h>
24 #include <PlaneGCSSolver_ScalarArrayWrapper.h>
25 #include <PlaneGCSSolver_ScalarWrapper.h>
26 #include <PlaneGCSSolver_ConstraintWrapper.h>
27
28 #include <SketchSolver_Constraint.h>
29 #include <SketchSolver_ConstraintAngle.h>
30 #include <SketchSolver_ConstraintCoincidence.h>
31 #include <SketchPlugin_ConstraintCoincidenceInternal.h>
32 #include <SketchSolver_ConstraintCollinear.h>
33 #include <SketchSolver_ConstraintDistance.h>
34 #include <SketchSolver_ConstraintEqual.h>
35 #include <SketchSolver_ConstraintFixed.h>
36 #include <SketchSolver_ConstraintLength.h>
37 #include <SketchSolver_ConstraintMiddle.h>
38 #include <SketchSolver_ConstraintMirror.h>
39 #include <SketchSolver_ConstraintPerpendicular.h>
40 #include <SketchSolver_ConstraintTangent.h>
41 #include <SketchSolver_ConstraintMultiRotation.h>
42 #include <SketchSolver_ConstraintMultiTranslation.h>
43 #include <SketchSolver_ConstraintOffset.h>
44
45 #include <SketchPlugin_Arc.h>
46 #include <SketchPlugin_BSpline.h>
47 #include <SketchPlugin_BSplinePeriodic.h>
48 #include <SketchPlugin_Circle.h>
49 #include <SketchPlugin_ConstraintAngle.h>
50 #include <SketchPlugin_ConstraintCoincidence.h>
51 #include <SketchPlugin_ConstraintCollinear.h>
52 #include <SketchPlugin_ConstraintDistance.h>
53 #include <SketchPlugin_ConstraintDistanceHorizontal.h>
54 #include <SketchPlugin_ConstraintDistanceVertical.h>
55 #include <SketchPlugin_ConstraintEqual.h>
56 #include <SketchPlugin_ConstraintLength.h>
57 #include <SketchPlugin_ConstraintMiddle.h>
58 #include <SketchPlugin_ConstraintMirror.h>
59 #include <SketchPlugin_ConstraintRigid.h>
60 #include <SketchPlugin_ConstraintPerpendicular.h>
61 #include <SketchPlugin_ConstraintTangent.h>
62 #include <SketchPlugin_Ellipse.h>
63 #include <SketchPlugin_EllipticArc.h>
64 #include <SketchPlugin_Line.h>
65 #include <SketchPlugin_MultiRotation.h>
66 #include <SketchPlugin_MultiTranslation.h>
67 #include <SketchPlugin_Offset.h>
68 #include <SketchPlugin_Point.h>
69
70 #include <GeomAPI_BSpline2d.h>
71 #include <GeomAPI_Circ2d.h>
72 #include <GeomAPI_Dir2d.h>
73 #include <GeomAPI_Ellipse2d.h>
74 #include <GeomAPI_Lin2d.h>
75 #include <GeomAPI_Pnt2d.h>
76
77 #include <ModelAPI_AttributeDoubleArray.h>
78 #include <ModelAPI_AttributeIntArray.h>
79
80 #include <cmath>
81
82
83 #define GCS_EDGE_WRAPPER(x)   std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(x)
84 #define GCS_POINT_WRAPPER(x)  std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(x)
85 #define GCS_SCALAR_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(x)
86
87
88
89 static ConstraintWrapperPtr
90   createConstraintCoincidence(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
91                               std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
92 static ConstraintWrapperPtr
93   createConstraintPointOnEntity(const SketchSolver_ConstraintType& theType,
94                                 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
95                                 std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity,
96                                 std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue);
97 static ConstraintWrapperPtr
98   createConstraintPointsCollinear(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
99                                   std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2,
100                                   std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint3);
101 static ConstraintWrapperPtr
102   createConstraintDistancePointPoint(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
103                                      std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
104                                      std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
105 static ConstraintWrapperPtr
106   createConstraintDistancePointLine(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
107                                     std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint,
108                                     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
109 static ConstraintWrapperPtr
110   createConstraintHVDistance(const SketchSolver_ConstraintType& theType,
111                              std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
112                              std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
113                              std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
114 static ConstraintWrapperPtr
115   createConstraintRadius(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
116                          std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
117 static ConstraintWrapperPtr
118   createConstraintAngle(ConstraintPtr theConstraint,
119                         std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
120                         std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
121                         std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2);
122 static ConstraintWrapperPtr
123   createConstraintHorizVert(const SketchSolver_ConstraintType& theType,
124                             std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
125 static ConstraintWrapperPtr
126   createConstraintParallel(std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
127                            std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2);
128 static ConstraintWrapperPtr
129   createConstraintPerpendicular(std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
130                                 std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2);
131 static ConstraintWrapperPtr
132   createConstraintEqual(const SketchSolver_ConstraintType& theType,
133                         std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
134                         std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2,
135                         std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theIntermed);
136 static ConstraintWrapperPtr
137   createConstraintMiddlePoint(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
138                               std::shared_ptr<PlaneGCSSolver_EdgeWrapper>  theEntity,
139                               std::shared_ptr<PlaneGCSSolver_PointWrapper> theAuxParameters);
140 static ConstraintWrapperPtr
141   createConstraintAngleBetweenCurves(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
142                                      std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
143                                      std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
144                                      std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2);
145
146 static GCS::SET_pD scalarParameters(const ScalarWrapperPtr& theScalar);
147 static GCS::SET_pD scalarArrayParameters(const EntityWrapperPtr& theArray);
148 static GCS::SET_pD pointParameters(const PointWrapperPtr& thePoint);
149 static GCS::SET_pD pointArrayParameters(const EntityWrapperPtr& theArray);
150 static GCS::SET_pD lineParameters(const EdgeWrapperPtr& theLine);
151 static GCS::SET_pD circleParameters(const EdgeWrapperPtr& theCircle);
152 static GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc);
153 static GCS::SET_pD ellipseParameters(const EdgeWrapperPtr& theEllipse);
154 static GCS::SET_pD ellipticArcParameters(const EdgeWrapperPtr& theEllipticArc);
155 static GCS::SET_pD bsplineParameters(const EdgeWrapperPtr& theEdge);
156
157
158
159
160 SolverConstraintPtr PlaneGCSSolver_Tools::createConstraint(ConstraintPtr theConstraint)
161 {
162   if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
163       theConstraint->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
164     return SolverConstraintPtr(new SketchSolver_ConstraintCoincidence(theConstraint));
165   } else if (theConstraint->getKind() == SketchPlugin_ConstraintCollinear::ID()) {
166     return SolverConstraintPtr(new SketchSolver_ConstraintCollinear(theConstraint));
167   } else if (theConstraint->getKind() == SketchPlugin_ConstraintDistance::ID() ||
168              theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() ||
169              theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID()) {
170     return SolverConstraintPtr(new SketchSolver_ConstraintDistance(theConstraint));
171   } else if (theConstraint->getKind() == SketchPlugin_ConstraintEqual::ID()) {
172     return SolverConstraintPtr(new SketchSolver_ConstraintEqual(theConstraint));
173   } else if (theConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) {
174     return SolverConstraintPtr(new SketchSolver_ConstraintLength(theConstraint));
175   } else if (theConstraint->getKind() == SketchPlugin_ConstraintMiddle::ID()) {
176     return SolverConstraintPtr(new SketchSolver_ConstraintMiddle(theConstraint));
177   } else if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
178     return SolverConstraintPtr(new SketchSolver_ConstraintMirror(theConstraint));
179   } else if (theConstraint->getKind() == SketchPlugin_ConstraintTangent::ID()) {
180     return SolverConstraintPtr(new SketchSolver_ConstraintTangent(theConstraint));
181   } else if (theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID()) {
182     return SolverConstraintPtr(new SketchSolver_ConstraintFixed(theConstraint));
183   } else if (theConstraint->getKind() == SketchPlugin_MultiTranslation::ID()) {
184     return SolverConstraintPtr(new SketchSolver_ConstraintMultiTranslation(theConstraint));
185   } else if (theConstraint->getKind() == SketchPlugin_MultiRotation::ID()) {
186     return SolverConstraintPtr(new SketchSolver_ConstraintMultiRotation(theConstraint));
187   } else if (theConstraint->getKind() == SketchPlugin_ConstraintAngle::ID()) {
188     return SolverConstraintPtr(new SketchSolver_ConstraintAngle(theConstraint));
189   } else if (theConstraint->getKind() == SketchPlugin_ConstraintPerpendicular::ID()) {
190     return SolverConstraintPtr(new SketchSolver_ConstraintPerpendicular(theConstraint));
191   } else if (theConstraint->getKind() == SketchPlugin_Offset::ID()) {
192     return SolverConstraintPtr(new SketchSolver_ConstraintOffset(theConstraint));
193   }
194   // All other types of constraints
195   return SolverConstraintPtr(new SketchSolver_Constraint(theConstraint));
196 }
197
198 std::shared_ptr<SketchSolver_ConstraintMovement> PlaneGCSSolver_Tools::createMovementConstraint(
199     FeaturePtr theMovedFeature)
200 {
201   return std::shared_ptr<SketchSolver_ConstraintMovement>(
202       new SketchSolver_ConstraintMovement(theMovedFeature));
203 }
204
205 std::shared_ptr<SketchSolver_ConstraintMovement> PlaneGCSSolver_Tools::createMovementConstraint(
206     AttributePtr theMovedAttribute)
207 {
208   return std::shared_ptr<SketchSolver_ConstraintMovement>(
209       new SketchSolver_ConstraintMovement(theMovedAttribute));
210 }
211
212 std::shared_ptr<SketchSolver_ConstraintMovement> PlaneGCSSolver_Tools::createMovementConstraint(
213     const std::pair<AttributePtr, int>& theMovedPointInArray)
214 {
215   return std::shared_ptr<SketchSolver_ConstraintMovement>(
216       new SketchSolver_ConstraintMovement(theMovedPointInArray.first, theMovedPointInArray.second));
217 }
218
219
220
221 ConstraintWrapperPtr PlaneGCSSolver_Tools::createConstraint(
222     ConstraintPtr theConstraint,
223     const SketchSolver_ConstraintType& theType,
224     const EntityWrapperPtr& theValue,
225     const EntityWrapperPtr& thePoint1,
226     const EntityWrapperPtr& thePoint2,
227     const EntityWrapperPtr& theEntity1,
228     const EntityWrapperPtr& theEntity2)
229 {
230   ConstraintWrapperPtr aResult;
231   ScalarWrapperPtr anIntermediate;
232
233   std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(thePoint1);
234   std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(thePoint2);
235   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity1 = GCS_EDGE_WRAPPER(theEntity1);
236
237   switch (theType) {
238   case CONSTRAINT_PT_PT_COINCIDENT:
239     aResult = createConstraintCoincidence(aPoint1, aPoint2);
240     break;
241   case CONSTRAINT_PT_ON_CURVE:
242     aResult = anEntity1 ?
243         createConstraintPointOnEntity(theType, aPoint1, anEntity1, GCS_SCALAR_WRAPPER(theValue)) :
244         createConstraintPointsCollinear(aPoint1, aPoint2, GCS_POINT_WRAPPER(theEntity1));
245     break;
246   case CONSTRAINT_MIDDLE_POINT:
247     aResult = createConstraintMiddlePoint(aPoint1, GCS_EDGE_WRAPPER(theEntity1), aPoint2);
248     break;
249   case CONSTRAINT_PT_PT_DISTANCE:
250     aResult = createConstraintDistancePointPoint(GCS_SCALAR_WRAPPER(theValue), aPoint1, aPoint2);
251     break;
252   case CONSTRAINT_PT_LINE_DISTANCE:
253     aResult = createConstraintDistancePointLine(GCS_SCALAR_WRAPPER(theValue),
254                                                 aPoint1,
255                                                 anEntity1);
256     break;
257   case CONSTRAINT_HORIZONTAL_DISTANCE:
258   case CONSTRAINT_VERTICAL_DISTANCE:
259     aResult = createConstraintHVDistance(theType, GCS_SCALAR_WRAPPER(theValue), aPoint1, aPoint2);
260     break;
261   case CONSTRAINT_RADIUS:
262     aResult = createConstraintRadius(GCS_SCALAR_WRAPPER(theValue), anEntity1);
263     break;
264   case CONSTRAINT_ANGLE:
265     aResult = createConstraintAngle(theConstraint,
266                   GCS_SCALAR_WRAPPER(theValue),
267                   anEntity1, GCS_EDGE_WRAPPER(theEntity2));
268     break;
269   case CONSTRAINT_FIXED:
270     break;
271   case CONSTRAINT_HORIZONTAL:
272   case CONSTRAINT_VERTICAL:
273     aResult = createConstraintHorizVert(theType, anEntity1);
274     break;
275   case CONSTRAINT_PARALLEL:
276     aResult = createConstraintParallel(anEntity1, GCS_EDGE_WRAPPER(theEntity2));
277     break;
278   case CONSTRAINT_PERPENDICULAR:
279     aResult = createConstraintPerpendicular(anEntity1, GCS_EDGE_WRAPPER(theEntity2));
280     break;
281   case CONSTRAINT_PERPENDICULAR_CURVES:
282     aResult = createConstraintAngleBetweenCurves(GCS_SCALAR_WRAPPER(theValue),
283                   aPoint1, anEntity1, GCS_EDGE_WRAPPER(theEntity2));
284     break;
285   case CONSTRAINT_EQUAL_LINES:
286   case CONSTRAINT_EQUAL_ELLIPSES:
287     anIntermediate = GCS_SCALAR_WRAPPER(theValue); // parameter is used to store length of lines
288   case CONSTRAINT_EQUAL_LINE_ARC:
289   case CONSTRAINT_EQUAL_RADIUS:
290     aResult = createConstraintEqual(theType,
291                                     anEntity1,
292                                     GCS_EDGE_WRAPPER(theEntity2),
293                                     anIntermediate);
294     break;
295   default:
296     break;
297   }
298
299   return aResult;
300 }
301
302 std::shared_ptr<GeomAPI_Pnt2d> PlaneGCSSolver_Tools::point(EntityWrapperPtr theEntity)
303 {
304   if (theEntity->type() != ENTITY_POINT)
305     return std::shared_ptr<GeomAPI_Pnt2d>();
306
307   std::shared_ptr<PlaneGCSSolver_PointWrapper> aPointWrapper =
308       std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
309   const GCSPointPtr& aPoint = aPointWrapper->point();
310   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(*aPoint->x, *aPoint->y));
311 }
312
313 std::shared_ptr<GeomAPI_Lin2d> PlaneGCSSolver_Tools::line(EntityWrapperPtr theEntity)
314 {
315   if (theEntity->type() != ENTITY_LINE)
316     return std::shared_ptr<GeomAPI_Lin2d>();
317
318   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
319       std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
320   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
321   return std::shared_ptr<GeomAPI_Lin2d>(
322       new GeomAPI_Lin2d(*(aLine->p1.x), *(aLine->p1.y), *(aLine->p2.x), *(aLine->p2.y)));
323 }
324
325 std::shared_ptr<GeomAPI_Lin2d> PlaneGCSSolver_Tools::line(FeaturePtr theFeature)
326 {
327   if (theFeature->getKind() != SketchPlugin_Line::ID())
328     return std::shared_ptr<GeomAPI_Lin2d>();
329
330   AttributePoint2DPtr aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
331       theFeature->attribute(SketchPlugin_Line::START_ID()));
332   AttributePoint2DPtr aEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
333       theFeature->attribute(SketchPlugin_Line::END_ID()));
334
335   return std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aStart->pnt(), aEnd->pnt()));
336 }
337
338 std::shared_ptr<GeomAPI_Circ2d> PlaneGCSSolver_Tools::circle(EntityWrapperPtr theEntity)
339 {
340   if (theEntity->type() != ENTITY_CIRCLE && theEntity->type() != ENTITY_ARC)
341     return std::shared_ptr<GeomAPI_Circ2d>();
342
343   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
344     std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
345   std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(anEntity->entity());
346   return std::shared_ptr<GeomAPI_Circ2d>(
347     new GeomAPI_Circ2d(*(aCirc->center.x), *(aCirc->center.y), *(aCirc->rad)));
348 }
349
350 std::shared_ptr<GeomAPI_Ellipse2d> PlaneGCSSolver_Tools::ellipse(EntityWrapperPtr theEntity)
351 {
352   if (theEntity->type() != ENTITY_ELLIPSE && theEntity->type() != ENTITY_ELLIPTIC_ARC)
353     return std::shared_ptr<GeomAPI_Ellipse2d>();
354
355   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
356     std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
357   std::shared_ptr<GCS::Ellipse> anEllipse =
358       std::dynamic_pointer_cast<GCS::Ellipse>(anEntity->entity());
359
360   std::shared_ptr<GeomAPI_Pnt2d> aCenter(
361       new GeomAPI_Pnt2d(*(anEllipse->center.x), *(anEllipse->center.y)));
362   std::shared_ptr<GeomAPI_Dir2d> anAxis(new GeomAPI_Dir2d(
363       *(anEllipse->focus1.x) - *(anEllipse->center.x),
364       *(anEllipse->focus1.y) - *(anEllipse->center.y)));
365
366   return std::shared_ptr<GeomAPI_Ellipse2d>(
367       new GeomAPI_Ellipse2d(aCenter, anAxis, anEllipse->getRadMaj(), *anEllipse->radmin));
368 }
369
370 std::shared_ptr<GeomAPI_BSpline2d> PlaneGCSSolver_Tools::bspline(EntityWrapperPtr theEntity)
371 {
372   if (theEntity->type() != ENTITY_BSPLINE)
373     return std::shared_ptr<GeomAPI_BSpline2d>();
374
375   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
376       std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
377   std::shared_ptr<GCS::BSpline> aSpline =
378       std::dynamic_pointer_cast<GCS::BSpline>(anEntity->entity());
379
380   std::list<GeomPnt2dPtr> aPoles;
381   for (GCS::VEC_P::iterator anIt = aSpline->poles.begin(); anIt != aSpline->poles.end(); ++anIt)
382     aPoles.push_back(GeomPnt2dPtr(new GeomAPI_Pnt2d(*anIt->x, *anIt->y)));
383
384   std::list<double> aWeights;
385   for (GCS::VEC_pD::iterator anIt = aSpline->weights.begin();
386        anIt != aSpline->weights.end(); ++anIt)
387     aWeights.push_back(**anIt);
388
389   std::list<double> aKnots;
390   for (GCS::VEC_pD::iterator anIt = aSpline->knots.begin(); anIt != aSpline->knots.end(); ++anIt)
391     aKnots.push_back(**anIt);
392
393   std::list<int> aMultiplicities;
394   aMultiplicities.assign(aSpline->mult.begin(), aSpline->mult.end());
395
396   return std::shared_ptr<GeomAPI_BSpline2d>(
397          new GeomAPI_BSpline2d(aSpline->degree, aPoles, aWeights,
398                                aKnots, aMultiplicities, aSpline->periodic));
399 }
400
401 void PlaneGCSSolver_Tools::recalculateArcParameters(EntityWrapperPtr theArc)
402 {
403   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEdge =
404       std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theArc);
405   if (!anEdge)
406     return;
407
408   if (anEdge->type() == ENTITY_ARC) {
409     std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEdge->entity());
410
411     GCS::Point aCenter = anArc->center;
412     GCS::Point aStartPnt = anArc->start;
413     GCS::Point aEndPnt = anArc->end;
414
415     *anArc->rad = distance(aCenter, aStartPnt);
416
417     static GeomDir2dPtr OX(new GeomAPI_Dir2d(1.0, 0.0));
418
419     GeomDir2dPtr aDir(new GeomAPI_Dir2d(*aStartPnt.x - *aCenter.x, *aStartPnt.y - *aCenter.y));
420     *anArc->startAngle = OX->angle(aDir);
421
422     aDir.reset(new GeomAPI_Dir2d(*aEndPnt.x - *aCenter.x, *aEndPnt.y - *aCenter.y));
423     *anArc->endAngle = OX->angle(aDir);
424   }
425   else if (anEdge->type() == ENTITY_ELLIPTIC_ARC) {
426     std::shared_ptr<GCS::ArcOfEllipse> aEllArc =
427         std::dynamic_pointer_cast<GCS::ArcOfEllipse>(anEdge->entity());
428
429     GeomPnt2dPtr aCenter(new GeomAPI_Pnt2d(*aEllArc->center.x, *aEllArc->center.y));
430     GeomPnt2dPtr aStartPnt(new GeomAPI_Pnt2d(*aEllArc->start.x, *aEllArc->start.y));
431     GeomPnt2dPtr aEndPnt(new GeomAPI_Pnt2d(*aEllArc->end.x, *aEllArc->end.y));
432
433     GeomDir2dPtr anAxis(new GeomAPI_Dir2d(*aEllArc->focus1.x - aCenter->x(),
434                                           *aEllArc->focus1.y - aCenter->y()));
435     GeomAPI_Ellipse2d anEllipse(aCenter, anAxis, aEllArc->getRadMaj(), *aEllArc->radmin);
436     anEllipse.parameter(aStartPnt, 1.e-4, *aEllArc->startAngle);
437     anEllipse.parameter(aEndPnt, 1.e-4, *aEllArc->endAngle);
438   }
439 }
440
441
442
443 GCS::SET_pD PlaneGCSSolver_Tools::parameters(const EntityWrapperPtr& theEntity)
444 {
445   switch (theEntity->type()) {
446   case ENTITY_SCALAR:
447   case ENTITY_ANGLE:
448     return scalarParameters(GCS_SCALAR_WRAPPER(theEntity));
449   case ENTITY_SCALAR_ARRAY:
450     return scalarArrayParameters(theEntity);
451   case ENTITY_POINT:
452     return pointParameters(GCS_POINT_WRAPPER(theEntity));
453   case ENTITY_POINT_ARRAY:
454     return pointArrayParameters(theEntity);
455   case ENTITY_LINE:
456     return lineParameters(GCS_EDGE_WRAPPER(theEntity));
457   case ENTITY_CIRCLE:
458     return circleParameters(GCS_EDGE_WRAPPER(theEntity));
459   case ENTITY_ARC:
460     return arcParameters(GCS_EDGE_WRAPPER(theEntity));
461   case ENTITY_ELLIPSE:
462     return ellipseParameters(GCS_EDGE_WRAPPER(theEntity));
463   case ENTITY_ELLIPTIC_ARC:
464     return ellipticArcParameters(GCS_EDGE_WRAPPER(theEntity));
465   case ENTITY_BSPLINE:
466     return bsplineParameters(GCS_EDGE_WRAPPER(theEntity));
467   default: break;
468   }
469   return GCS::SET_pD();
470 }
471
472 bool PlaneGCSSolver_Tools::isAttributeApplicable(const std::string& theAttrName,
473                                                  const std::string& theOwnerName)
474 {
475   if (theOwnerName == SketchPlugin_Arc::ID()) {
476     return theAttrName == SketchPlugin_Arc::CENTER_ID() ||
477            theAttrName == SketchPlugin_Arc::START_ID() ||
478            theAttrName == SketchPlugin_Arc::END_ID() ||
479            theAttrName == SketchPlugin_Arc::REVERSED_ID();
480   }
481   else if (theOwnerName == SketchPlugin_Circle::ID()) {
482     return theAttrName == SketchPlugin_Circle::CENTER_ID() ||
483            theAttrName == SketchPlugin_Circle::RADIUS_ID();
484   }
485   else if (theOwnerName == SketchPlugin_Line::ID()) {
486     return theAttrName == SketchPlugin_Line::START_ID() ||
487            theAttrName == SketchPlugin_Line::END_ID();
488   }
489   else if (theOwnerName == SketchPlugin_Ellipse::ID()) {
490     return theAttrName == SketchPlugin_Ellipse::CENTER_ID() ||
491            theAttrName == SketchPlugin_Ellipse::FIRST_FOCUS_ID() ||
492            theAttrName == SketchPlugin_Ellipse::SECOND_FOCUS_ID() ||
493            theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ||
494            theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID() ||
495            theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_START_ID() ||
496            theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_END_ID() ||
497            theAttrName == SketchPlugin_Ellipse::MAJOR_RADIUS_ID() ||
498            theAttrName == SketchPlugin_Ellipse::MINOR_RADIUS_ID();
499   }
500   else if (theOwnerName == SketchPlugin_EllipticArc::ID()) {
501     return theAttrName == SketchPlugin_EllipticArc::CENTER_ID() ||
502            theAttrName == SketchPlugin_EllipticArc::FIRST_FOCUS_ID() ||
503            theAttrName == SketchPlugin_EllipticArc::SECOND_FOCUS_ID() ||
504            theAttrName == SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID() ||
505            theAttrName == SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID() ||
506            theAttrName == SketchPlugin_EllipticArc::MINOR_AXIS_START_ID() ||
507            theAttrName == SketchPlugin_EllipticArc::MINOR_AXIS_END_ID() ||
508            theAttrName == SketchPlugin_EllipticArc::MAJOR_RADIUS_ID() ||
509            theAttrName == SketchPlugin_EllipticArc::MINOR_RADIUS_ID() ||
510            theAttrName == SketchPlugin_EllipticArc::START_POINT_ID() ||
511            theAttrName == SketchPlugin_EllipticArc::END_POINT_ID() ||
512            theAttrName == SketchPlugin_EllipticArc::REVERSED_ID();
513   }
514   else if (theOwnerName == SketchPlugin_BSpline::ID()) {
515     return theAttrName == SketchPlugin_BSpline::POLES_ID() ||
516            theAttrName == SketchPlugin_BSpline::WEIGHTS_ID() ||
517            theAttrName == SketchPlugin_BSpline::KNOTS_ID() ||
518            theAttrName == SketchPlugin_BSpline::MULTS_ID() ||
519            theAttrName == SketchPlugin_BSpline::DEGREE_ID() ||
520            theAttrName == SketchPlugin_BSpline::START_ID() ||
521            theAttrName == SketchPlugin_BSpline::END_ID();
522   }
523   else if (theOwnerName == SketchPlugin_BSplinePeriodic::ID()) {
524     return theAttrName == SketchPlugin_BSplinePeriodic::POLES_ID() ||
525            theAttrName == SketchPlugin_BSplinePeriodic::WEIGHTS_ID() ||
526            theAttrName == SketchPlugin_BSplinePeriodic::KNOTS_ID() ||
527            theAttrName == SketchPlugin_BSplinePeriodic::MULTS_ID() ||
528            theAttrName == SketchPlugin_BSplinePeriodic::DEGREE_ID();
529   }
530
531   // suppose that all remaining features are points
532   return theAttrName == SketchPlugin_Point::COORD_ID();
533 }
534
535 /// \brief Update value
536 bool PlaneGCSSolver_Tools::updateValue(const double& theSource, double& theDest,
537                                        const double theTolerance)
538 {
539   bool isUpdated = fabs(theSource - theDest) > theTolerance;
540   if (isUpdated)
541     theDest = theSource;
542   return isUpdated;
543 }
544
545
546 double PlaneGCSSolver_Tools::distance(const GCS::Point& thePnt1, const GCS::Point& thePnt2)
547 {
548   double x = *thePnt1.x - *thePnt2.x;
549   double y = *thePnt1.y - *thePnt2.y;
550   return sqrt(x*x + y*y);
551 }
552
553
554
555
556 // ================   AttributeArray methods   ==========================
557 PlaneGCSSolver_Tools::AttributeArray::AttributeArray(AttributePtr theAttribute)
558 {
559   myDouble = std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(theAttribute);
560   myInteger = std::dynamic_pointer_cast<ModelAPI_AttributeIntArray>(theAttribute);
561 }
562
563 bool PlaneGCSSolver_Tools::AttributeArray::isInitialized() const
564 {
565   return (myDouble && myDouble->isInitialized()) || (myInteger && myInteger->isInitialized());
566 }
567
568 int PlaneGCSSolver_Tools::AttributeArray::size() const
569 {
570   return myDouble.get() ? myDouble->size() : myInteger->size();
571 }
572
573 double PlaneGCSSolver_Tools::AttributeArray::value(const int theIndex) const
574 {
575   return myDouble.get() ? myDouble->value(theIndex) : myInteger->value(theIndex);
576 }
577
578
579
580
581
582
583 // ================   Auxiliary functions   ==========================
584 ConstraintWrapperPtr createConstraintCoincidence(
585     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
586     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
587 {
588   GCSPointPtr aPoint1 = thePoint1->point();
589   GCSPointPtr aPoint2 = thePoint2->point();
590
591   // Create equality constraint for corresponding attributes of the points
592   std::list<GCSConstraintPtr> aConstrList;
593   aConstrList.push_back(
594       GCSConstraintPtr(new GCS::ConstraintEqual(aPoint1->x, aPoint2->x)));
595   aConstrList.push_back(
596       GCSConstraintPtr(new GCS::ConstraintEqual(aPoint1->y, aPoint2->y)));
597
598   return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(
599       aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
600 }
601
602 ConstraintWrapperPtr createConstraintPointOnEntity(
603     const SketchSolver_ConstraintType& theType,
604     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
605     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity,
606     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue)
607 {
608   GCSConstraintPtr aNewConstr;
609
610   switch (theEntity->type()) {
611   case ENTITY_LINE: {
612     std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
613     aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnLine(*(thePoint->point()), *aLine));
614     break;
615     }
616   case ENTITY_ARC:
617   case ENTITY_CIRCLE: {
618     std::shared_ptr<GCS::Circle> aCirc =
619       std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
620     aNewConstr = GCSConstraintPtr(
621         new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
622     break;
623     }
624   case ENTITY_ELLIPSE:
625   case ENTITY_ELLIPTIC_ARC: {
626     std::shared_ptr<GCS::Ellipse> anEllipse =
627         std::dynamic_pointer_cast<GCS::Ellipse>(theEntity->entity());
628     aNewConstr = GCSConstraintPtr(
629         new GCS::ConstraintPointOnEllipse(*(thePoint->point()), *anEllipse));
630     break;
631     }
632   case ENTITY_BSPLINE: {
633     std::list<GCSConstraintPtr> aConstraints;
634     aConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintCurveValue(
635         *thePoint->point(), thePoint->point()->x, *theEntity->entity(), theValue->scalar())));
636     aConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintCurveValue(
637         *thePoint->point(), thePoint->point()->y, *theEntity->entity(), theValue->scalar())));
638     return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aConstraints, theType));
639   }
640   default:
641     return ConstraintWrapperPtr();
642   }
643
644   return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
645 }
646
647 ConstraintWrapperPtr createConstraintPointsCollinear(
648     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
649     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2,
650     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint3)
651 {
652   GCSConstraintPtr aNewConstr(new GCS::ConstraintPointOnLine(
653       *(thePoint1->point()), *(thePoint2->point()), *(thePoint3->point())));
654   return ConstraintWrapperPtr(
655       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PT_ON_CURVE));
656 }
657
658 template <typename ARCTYPE>
659 void createConstraintMiddlePointOnArc(ARCTYPE theArc,
660                                       GCSPointPtr thePoint,
661                                       std::shared_ptr<PlaneGCSSolver_PointWrapper> theAuxParameters,
662                                       std::list<GCSConstraintPtr>& theConstraints)
663 {
664   double* u = theAuxParameters->point()->x;
665   double* diff = theAuxParameters->point()->y;
666   *u = (*theArc->startAngle + *theArc->endAngle) * 0.5;
667   *diff = (*theArc->endAngle - *theArc->startAngle) * 0.5;
668
669   theConstraints.push_back(GCSConstraintPtr(
670       new GCS::ConstraintCurveValue(*thePoint, thePoint->x, *theArc, u)));
671   theConstraints.push_back(GCSConstraintPtr(
672       new GCS::ConstraintCurveValue(*thePoint, thePoint->y, *theArc, u)));
673   theConstraints.push_back(GCSConstraintPtr(
674       new GCS::ConstraintDifference(theArc->startAngle, u, diff)));
675   theConstraints.push_back(GCSConstraintPtr(
676       new GCS::ConstraintDifference(u, theArc->endAngle, diff)));
677 }
678
679 ConstraintWrapperPtr createConstraintMiddlePoint(
680     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
681     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity,
682     std::shared_ptr<PlaneGCSSolver_PointWrapper> theAuxParameters)
683 {
684   std::list<GCSConstraintPtr> aConstrList;
685
686   GCSPointPtr aPoint = thePoint->point();
687   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
688   if (aLine) {
689     aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPointOnLine(*aPoint, *aLine)));
690     aConstrList.push_back(
691         GCSConstraintPtr(new GCS::ConstraintPointOnPerpBisector(*aPoint, aLine->p1, aLine->p2)));
692   }
693   else {
694     std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(theEntity->entity());
695     if (anArc)
696       createConstraintMiddlePointOnArc(anArc, aPoint, theAuxParameters, aConstrList);
697     else {
698       std::shared_ptr<GCS::ArcOfEllipse> aEllArc =
699           std::dynamic_pointer_cast<GCS::ArcOfEllipse>(theEntity->entity());
700       if (aEllArc)
701         createConstraintMiddlePointOnArc(aEllArc, aPoint, theAuxParameters, aConstrList);
702     }
703   }
704
705   return aConstrList.empty() ? ConstraintWrapperPtr() : ConstraintWrapperPtr(
706       new PlaneGCSSolver_ConstraintWrapper(aConstrList, CONSTRAINT_MIDDLE_POINT));
707 }
708
709
710 ConstraintWrapperPtr createConstraintDistancePointPoint(
711     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
712     std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint1,
713     std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint2)
714 {
715   GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
716       *(thePoint1->point()), *(thePoint2->point()), theValue->scalar()));
717   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
718       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
719   aResult->setValueParameter(theValue);
720   return aResult;
721 }
722
723 ConstraintWrapperPtr createConstraintDistancePointLine(
724     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
725     std::shared_ptr<PlaneGCSSolver_PointWrapper>  thePoint,
726     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
727 {
728   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
729   GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
730       *(thePoint->point()), *(aLine), theValue->scalar()));
731   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
732       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
733   aResult->setValueParameter(theValue);
734   return aResult;
735 }
736
737 ConstraintWrapperPtr createConstraintHVDistance(
738     const SketchSolver_ConstraintType& theType,
739     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
740     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
741     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
742 {
743   GCSPointPtr aPoint1 = thePoint1->point();
744   GCSPointPtr aPoint2 = thePoint2->point();
745
746   double *aParam1, *aParam2;
747   if (theType == CONSTRAINT_HORIZONTAL_DISTANCE) {
748     aParam1 = aPoint1->x;
749     aParam2 = aPoint2->x;
750   } else if (theType == CONSTRAINT_VERTICAL_DISTANCE) {
751     aParam1 = aPoint1->y;
752     aParam2 = aPoint2->y;
753   }
754
755   GCSConstraintPtr aNewConstr(new GCS::ConstraintDifference(aParam1, aParam2, theValue->scalar()));
756
757   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
758       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
759   aResult->setValueParameter(theValue);
760   return aResult;
761 }
762
763 ConstraintWrapperPtr createConstraintRadius(
764     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
765     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
766 {
767   std::shared_ptr<GCS::Circle> aCircle =
768     std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
769   GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->scalar()));
770   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
771       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_RADIUS));
772   aResult->setValueParameter(theValue);
773   return aResult;
774 }
775
776 ConstraintWrapperPtr createConstraintAngle(
777     ConstraintPtr theConstraint,
778     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
779     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
780     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
781 {
782   std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
783   std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
784
785   GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
786       aLine1->p1, aLine1->p2, aLine2->p1, aLine2->p2, theValue->scalar()));
787
788   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
789       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_ANGLE));
790   aResult->setValueParameter(theValue);
791   return aResult;
792 }
793
794 ConstraintWrapperPtr createConstraintHorizVert(
795     const SketchSolver_ConstraintType& theType,
796     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
797 {
798   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
799   GCSConstraintPtr aNewConstr;
800   if (theType == CONSTRAINT_HORIZONTAL)
801     aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.y, aLine->p2.y));
802   else
803     aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
804
805   return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
806 }
807
808 ConstraintWrapperPtr createConstraintParallel(
809     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
810     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
811 {
812   std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
813   std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
814   GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
815
816   return ConstraintWrapperPtr(
817       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PARALLEL));
818 }
819
820 ConstraintWrapperPtr createConstraintPerpendicular(
821     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
822     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
823 {
824   std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
825   std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
826
827   std::shared_ptr<GCS::Circle> aCirc1 =
828       std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
829   std::shared_ptr<GCS::Circle> aCirc2 =
830       std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
831
832   GCSConstraintPtr aNewConstr;
833   if (aLine1 && aLine2)
834     aNewConstr.reset(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
835   else {
836     if (aLine1 && aCirc2)
837       aCirc1 = aCirc2;
838     else if (aLine2 && aCirc1)
839       aLine1 = aLine2;
840
841     aNewConstr.reset(new GCS::ConstraintPointOnLine(aCirc1->center, *aLine1));
842   }
843
844   return ConstraintWrapperPtr(
845       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PERPENDICULAR));
846 }
847
848 ConstraintWrapperPtr createConstraintAngleBetweenCurves(
849     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
850     std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
851     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
852     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
853 {
854   GCSConstraintPtr aNewConstr(new GCS::ConstraintAngleViaPoint(
855       *theEntity1->entity(), *theEntity2->entity(), *thePoint->point(), theValue->scalar()));
856   return ConstraintWrapperPtr(
857       new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PERPENDICULAR_CURVES));
858 }
859
860 ConstraintWrapperPtr createConstraintEqual(
861     const SketchSolver_ConstraintType& theType,
862     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
863     std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2,
864     std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theIntermed)
865 {
866   if (theType == CONSTRAINT_EQUAL_LINE_ARC)
867     return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
868
869   std::list<GCSConstraintPtr> aConstrList;
870   if (theType == CONSTRAINT_EQUAL_LINES) {
871     std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
872     std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
873
874     aConstrList.push_back(GCSConstraintPtr(
875         new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->scalar())));
876     aConstrList.push_back(GCSConstraintPtr(
877         new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->scalar())));
878     // update value of intermediate parameter
879     theIntermed->setValue(PlaneGCSSolver_Tools::distance(aLine1->p1, aLine1->p2));
880   }
881   else if (theType == CONSTRAINT_EQUAL_ELLIPSES) {
882     std::shared_ptr<GCS::Ellipse> anEllipse1 =
883         std::dynamic_pointer_cast<GCS::Ellipse>(theEntity1->entity());
884     std::shared_ptr<GCS::Ellipse> anEllipse2 =
885         std::dynamic_pointer_cast<GCS::Ellipse>(theEntity2->entity());
886
887     aConstrList.push_back(GCSConstraintPtr(
888         new GCS::ConstraintEqual(anEllipse1->radmin, anEllipse2->radmin)));
889     aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
890         anEllipse1->center, anEllipse1->focus1, theIntermed->scalar())));
891     aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
892         anEllipse2->center, anEllipse2->focus1, theIntermed->scalar())));
893     // update value of intermediate parameter
894     theIntermed->setValue(PlaneGCSSolver_Tools::distance(anEllipse1->center, anEllipse1->focus1));
895   }
896   else {
897     std::shared_ptr<GCS::Circle> aCirc1 =
898         std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
899     std::shared_ptr<GCS::Circle> aCirc2 =
900         std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
901     aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
902   }
903
904   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
905       new PlaneGCSSolver_ConstraintWrapper(aConstrList, theType));
906   if (theIntermed)
907     aResult->setValueParameter(theIntermed);
908   return aResult;
909 }
910
911 GCS::SET_pD scalarParameters(const ScalarWrapperPtr& theScalar)
912 {
913   GCS::SET_pD aParams;
914   aParams.insert(theScalar->scalar());
915   return aParams;
916 }
917
918 GCS::SET_pD scalarArrayParameters(const EntityWrapperPtr& theArray)
919 {
920   ScalarArrayWrapperPtr anArray =
921       std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(theArray);
922   return GCS::SET_pD(anArray->array().begin(), anArray->array().end());
923 }
924
925 GCS::SET_pD pointParameters(const PointWrapperPtr& thePoint)
926 {
927   GCS::SET_pD aParams;
928   aParams.insert(thePoint->point()->x);
929   aParams.insert(thePoint->point()->y);
930   return aParams;
931 }
932
933 GCS::SET_pD pointArrayParameters(const EntityWrapperPtr& theArray)
934 {
935   GCS::SET_pD aParams;
936   PointArrayWrapperPtr aPoints =
937       std::dynamic_pointer_cast<PlaneGCSSolver_PointArrayWrapper>(theArray);
938   for (std::vector<PointWrapperPtr>::const_iterator anIt = aPoints->array().begin();
939        anIt != aPoints->array().end(); ++anIt) {
940     GCS::SET_pD aPointParams = PlaneGCSSolver_Tools::parameters(*anIt);
941     aParams.insert(aPointParams.begin(), aPointParams.end());
942   }
943   return aParams;
944 }
945
946 GCS::SET_pD lineParameters(const EdgeWrapperPtr& theLine)
947 {
948   GCS::SET_pD aParams;
949   std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theLine->entity());
950   aParams.insert(aLine->p1.x);
951   aParams.insert(aLine->p1.y);
952   aParams.insert(aLine->p2.x);
953   aParams.insert(aLine->p2.y);
954   return aParams;
955 }
956
957 GCS::SET_pD circleParameters(const EdgeWrapperPtr& theCircle)
958 {
959   GCS::SET_pD aParams;
960   std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theCircle->entity());
961   aParams.insert(aCirc->center.x);
962   aParams.insert(aCirc->center.y);
963   aParams.insert(aCirc->rad);
964   return aParams;
965 }
966
967 GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc)
968 {
969   GCS::SET_pD aParams = circleParameters(theArc);
970   std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(theArc->entity());
971   aParams.insert(anArc->start.x);
972   aParams.insert(anArc->start.y);
973   aParams.insert(anArc->end.x);
974   aParams.insert(anArc->end.y);
975   aParams.insert(anArc->startAngle);
976   aParams.insert(anArc->endAngle);
977   return aParams;
978 }
979
980 GCS::SET_pD ellipseParameters(const EdgeWrapperPtr& theEllipse)
981 {
982   GCS::SET_pD aParams;
983   std::shared_ptr<GCS::Ellipse> anEllipse =
984       std::dynamic_pointer_cast<GCS::Ellipse>(theEllipse->entity());
985   aParams.insert(anEllipse->center.x);
986   aParams.insert(anEllipse->center.y);
987   aParams.insert(anEllipse->focus1.x);
988   aParams.insert(anEllipse->focus1.y);
989   aParams.insert(anEllipse->radmin);
990   return aParams;
991 }
992
993 GCS::SET_pD ellipticArcParameters(const EdgeWrapperPtr& theEllipticArc)
994 {
995   GCS::SET_pD aParams = ellipseParameters(theEllipticArc);
996   std::shared_ptr<GCS::ArcOfEllipse> anArc =
997       std::dynamic_pointer_cast<GCS::ArcOfEllipse>(theEllipticArc->entity());
998   aParams.insert(anArc->start.x);
999   aParams.insert(anArc->start.y);
1000   aParams.insert(anArc->end.x);
1001   aParams.insert(anArc->end.y);
1002   aParams.insert(anArc->startAngle);
1003   aParams.insert(anArc->endAngle);
1004   return aParams;
1005 }
1006
1007 GCS::SET_pD bsplineParameters(const EdgeWrapperPtr& theEdge)
1008 {
1009   GCS::SET_pD aParams;
1010
1011   std::shared_ptr<GCS::BSpline> aBSpline =
1012     std::dynamic_pointer_cast<GCS::BSpline>(theEdge->entity());
1013
1014   for (GCS::VEC_P::iterator it = aBSpline->poles.begin(); it != aBSpline->poles.end(); ++it) {
1015     aParams.insert(it->x);
1016     aParams.insert(it->y);
1017   }
1018   for (GCS::VEC_pD::iterator it = aBSpline->weights.begin(); it != aBSpline->weights.end(); ++it)
1019     aParams.insert(*it);
1020
1021   return aParams;
1022 }