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