Salome HOME
Updated copyright comment
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_FeatureBuilder.cpp
1 // Copyright (C) 2014-2024  CEA, EDF
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_FeatureBuilder.h>
21 #include <PlaneGCSSolver_BooleanWrapper.h>
22 #include <PlaneGCSSolver_EdgeWrapper.h>
23 #include <PlaneGCSSolver_GeoExtensions.h>
24 #include <PlaneGCSSolver_PointWrapper.h>
25 #include <PlaneGCSSolver_PointArrayWrapper.h>
26 #include <PlaneGCSSolver_ScalarWrapper.h>
27 #include <PlaneGCSSolver_ScalarArrayWrapper.h>
28 #include <PlaneGCSSolver_Tools.h>
29
30 #include <SketchPlugin_Arc.h>
31 #include <SketchPlugin_BSpline.h>
32 #include <SketchPlugin_BSplinePeriodic.h>
33 #include <SketchPlugin_Circle.h>
34 #include <SketchPlugin_Ellipse.h>
35 #include <SketchPlugin_EllipticArc.h>
36 #include <SketchPlugin_IntersectionPoint.h>
37 #include <SketchPlugin_Line.h>
38 #include <SketchPlugin_Point.h>
39
40 #include <GeomAPI_Dir2d.h>
41 #include <GeomAPI_Pnt2d.h>
42 #include <GeomAPI_XY.h>
43
44
45 static EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes);
46 static EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes);
47 static EntityWrapperPtr createArc(const AttributeEntityMap&    theAttributes,
48                                   PlaneGCSSolver_Storage*      theStorage);
49 static EntityWrapperPtr createEllipse(const AttributeEntityMap& theAttributes);
50 static EntityWrapperPtr createEllipticArc(const AttributeEntityMap& theAttributes,
51                                           PlaneGCSSolver_Storage*   theStorage);
52 template <typename TYPE>
53 static EntityWrapperPtr createBSpline(const AttributeEntityMap& theAttributes);
54
55
56 PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(
57     PlaneGCSSolver_Storage* theStorage)
58   : PlaneGCSSolver_AttributeBuilder(theStorage)
59 {
60 }
61
62 PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(const StoragePtr& theStorage)
63   : PlaneGCSSolver_AttributeBuilder(theStorage)
64 {
65 }
66
67 EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createAttribute(
68     AttributePtr theAttribute)
69 {
70   FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
71   EntityWrapperPtr anAttr;
72   if (PlaneGCSSolver_Tools::isAttributeApplicable(theAttribute->id(), anOwner->getKind()))
73     anAttr = PlaneGCSSolver_AttributeBuilder::createAttribute(theAttribute);
74   if (anAttr)
75     myAttributes[theAttribute] = anAttr;
76   return anAttr;
77 }
78
79 EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createFeature(FeaturePtr theFeature)
80 {
81   EntityWrapperPtr aResult;
82   if (myStorage)
83     aResult = myStorage->entity(theFeature);
84   if (aResult)
85     return aResult;
86
87   // Process SketchPlugin features only
88   std::shared_ptr<SketchPlugin_Feature> aFeature =
89       std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
90   if (!aFeature)
91     return aResult;
92
93   // Verify the feature by its kind
94   const std::string& aFeatureKind = aFeature->getKind();
95   // Line
96   if (aFeatureKind == SketchPlugin_Line::ID())
97     aResult = createLine(myAttributes);
98   // Circle
99   else if (aFeatureKind == SketchPlugin_Circle::ID())
100     aResult = createCircle(myAttributes);
101   // Arc
102   else if (aFeatureKind == SketchPlugin_Arc::ID())
103     aResult = createArc(myAttributes, myStorage);
104   // Ellipse
105   else if (aFeatureKind == SketchPlugin_Ellipse::ID())
106     aResult = createEllipse(myAttributes);
107   // Arc of ellipse
108   else if (aFeatureKind == SketchPlugin_EllipticArc::ID())
109     aResult = createEllipticArc(myAttributes, myStorage);
110   // B-spline curve
111   else if (aFeatureKind == SketchPlugin_BSpline::ID())
112     aResult = createBSpline<SketchPlugin_BSpline>(myAttributes);
113   else if (aFeatureKind == SketchPlugin_BSplinePeriodic::ID())
114     aResult = createBSpline<SketchPlugin_BSplinePeriodic>(myAttributes);
115   // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
116   else if (aFeatureKind == SketchPlugin_Point::ID() ||
117            aFeatureKind == SketchPlugin_IntersectionPoint::ID()) {
118     AttributeEntityMap::const_iterator anIt = myAttributes.begin();
119     for (; anIt != myAttributes.end(); ++anIt)
120       if (anIt->first->id() == SketchPlugin_Point::COORD_ID()) {
121         aResult = anIt->second;
122         break;
123       }
124   }
125
126   if (aResult && !myStorage)
127     aResult->setExternal(true);
128
129   myAttributes.clear();
130   return aResult;
131 }
132
133
134
135
136
137 // ==============   Auxiliary functions   =====================================
138 EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes)
139 {
140   std::shared_ptr<GCS::Line> aNewLine(new GCS::Line);
141
142   AttributeEntityMap::const_iterator anIt = theAttributes.begin();
143   for (; anIt != theAttributes.end(); ++anIt) {
144     std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
145         std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
146     if (!aPoint)
147       continue;
148
149     if (anIt->first->id() == SketchPlugin_Line::START_ID())
150       aNewLine->p1 = *(aPoint->point());
151     else if (anIt->first->id() == SketchPlugin_Line::END_ID())
152       aNewLine->p2 = *(aPoint->point());
153   }
154
155   return EntityWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewLine));
156 }
157
158 EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes)
159 {
160   std::shared_ptr<GCS::Circle> aNewCircle(new GCS::Circle);
161
162   AttributeEntityMap::const_iterator anIt = theAttributes.begin();
163   for (; anIt != theAttributes.end(); ++anIt) {
164     if (anIt->first->id() == SketchPlugin_Circle::CENTER_ID()) {
165       std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
166           std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
167       aNewCircle->center = *(aPoint->point());
168     }
169     else if(anIt->first->id() == SketchPlugin_Circle::RADIUS_ID()) {
170       ScalarWrapperPtr aScalar =
171           std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
172       aNewCircle->rad = aScalar->scalar();
173     }
174   }
175
176   return EntityWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewCircle));
177 }
178
179 static double* createParameter(PlaneGCSSolver_Storage* theStorage)
180 {
181   return theStorage ? theStorage->createParameter() : (new double(0));
182 }
183
184 EntityWrapperPtr createArc(const AttributeEntityMap&    theAttributes,
185                            PlaneGCSSolver_Storage*      theStorage)
186 {
187   std::shared_ptr<GCS::Arc> aNewArc(new GCS::Arc);
188   BooleanWrapperPtr isReversed;
189
190   // Base attributes of arc (center, start and end points)
191   AttributeEntityMap::const_iterator anIt = theAttributes.begin();
192   for (; anIt != theAttributes.end(); ++anIt) {
193     std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
194         std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
195     if (aPoint) {
196       if (anIt->first->id() == SketchPlugin_Arc::CENTER_ID())
197         aNewArc->center = *(aPoint->point());
198       else if (anIt->first->id() == SketchPlugin_Arc::START_ID())
199         aNewArc->start = *(aPoint->point());
200       else if (anIt->first->id() == SketchPlugin_Arc::END_ID())
201         aNewArc->end = *(aPoint->point());
202     }
203     else {
204       // reversed flag
205       isReversed = std::dynamic_pointer_cast<PlaneGCSSolver_BooleanWrapper>(anIt->second);
206     }
207   }
208
209   // Additional attributes of arc necessary for PlaneGCS solver
210   // (start and end angles, radius)
211   aNewArc->startAngle = createParameter(theStorage);
212   aNewArc->endAngle   = createParameter(theStorage);
213   aNewArc->rad        = createParameter(theStorage);
214
215   EdgeWrapperPtr anArcWrapper(new PlaneGCSSolver_EdgeWrapper(aNewArc));
216   anArcWrapper->setReversed(isReversed);
217   PlaneGCSSolver_Tools::recalculateArcParameters(anArcWrapper);
218
219   return anArcWrapper;
220 }
221
222 EntityWrapperPtr createEllipse(const AttributeEntityMap& theAttributes)
223 {
224   std::shared_ptr<GCS::Ellipse> aNewEllipse(new GCS::Ellipse);
225
226   std::map<std::string, EntityWrapperPtr> anAdditionalAttributes;
227
228   AttributeEntityMap::const_iterator anIt = theAttributes.begin();
229   for (; anIt != theAttributes.end(); ++anIt) {
230     std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
231         std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
232     if (aPoint) {
233       if (anIt->first->id() == SketchPlugin_Ellipse::CENTER_ID())
234         aNewEllipse->center = *(aPoint->point());
235       else if (anIt->first->id() == SketchPlugin_Ellipse::FIRST_FOCUS_ID())
236         aNewEllipse->focus1 = *(aPoint->point());
237       else
238         anAdditionalAttributes[anIt->first->id()] = anIt->second;
239     }
240     else if (anIt->first->id() == SketchPlugin_Ellipse::MINOR_RADIUS_ID()) {
241       ScalarWrapperPtr aScalar =
242           std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
243       aNewEllipse->radmin = aScalar->scalar();
244     }
245     else
246       anAdditionalAttributes[anIt->first->id()] = anIt->second;
247   }
248
249   EntityWrapperPtr anEllipseWrapper(new PlaneGCSSolver_EdgeWrapper(aNewEllipse));
250   anEllipseWrapper->setAdditionalAttributes(anAdditionalAttributes);
251   return anEllipseWrapper;
252 }
253
254 EntityWrapperPtr createEllipticArc(const AttributeEntityMap& theAttributes,
255                                    PlaneGCSSolver_Storage*   theStorage)
256 {
257   std::shared_ptr<GCS::ArcOfEllipse> aNewArc(new GCS::ArcOfEllipse);
258
259   BooleanWrapperPtr isReversed;
260   std::map<std::string, EntityWrapperPtr> anAdditionalAttributes;
261
262   AttributeEntityMap::const_iterator anIt = theAttributes.begin();
263   for (; anIt != theAttributes.end(); ++anIt) {
264     std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
265         std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
266     if (aPoint) {
267       if (anIt->first->id() == SketchPlugin_EllipticArc::CENTER_ID())
268         aNewArc->center = *(aPoint->point());
269       else if (anIt->first->id() == SketchPlugin_EllipticArc::FIRST_FOCUS_ID())
270         aNewArc->focus1 = *(aPoint->point());
271       else if (anIt->first->id() == SketchPlugin_EllipticArc::START_POINT_ID())
272         aNewArc->start = *(aPoint->point());
273       else if (anIt->first->id() == SketchPlugin_EllipticArc::END_POINT_ID())
274         aNewArc->end = *(aPoint->point());
275       else
276         anAdditionalAttributes[anIt->first->id()] = anIt->second;
277     }
278     else if (anIt->first->id() == SketchPlugin_EllipticArc::MINOR_RADIUS_ID()) {
279       ScalarWrapperPtr aScalar =
280           std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
281       aNewArc->radmin = aScalar->scalar();
282     }
283     else if (anIt->first->id() == SketchPlugin_EllipticArc::REVERSED_ID())
284       isReversed = std::dynamic_pointer_cast<PlaneGCSSolver_BooleanWrapper>(anIt->second);
285     else
286       anAdditionalAttributes[anIt->first->id()] = anIt->second;
287   }
288
289   // Additional attributes of elliptic arc necessary for PlaneGCS solver (start and end angles)
290   aNewArc->startAngle = createParameter(theStorage);
291   aNewArc->endAngle = createParameter(theStorage);
292
293   EdgeWrapperPtr anEllipseWrapper(new PlaneGCSSolver_EdgeWrapper(aNewArc));
294   anEllipseWrapper->setReversed(isReversed);
295   anEllipseWrapper->setAdditionalAttributes(anAdditionalAttributes);
296   PlaneGCSSolver_Tools::recalculateArcParameters(anEllipseWrapper);
297
298   return anEllipseWrapper;
299 }
300
301 template <typename TYPE>
302 EntityWrapperPtr createBSpline(const AttributeEntityMap& theAttributes)
303 {
304   std::shared_ptr<GCS::BSplineImpl> aNewSpline(new GCS::BSplineImpl);
305
306   aNewSpline->degree = 3;
307   aNewSpline->periodic = std::is_same<TYPE, SketchPlugin_BSplinePeriodic>();
308
309   std::map<std::string, EntityWrapperPtr> anAdditionalAttributes;
310
311   AttributeEntityMap::const_iterator anIt = theAttributes.begin();
312   for (; anIt != theAttributes.end(); ++anIt) {
313     const std::string& anAttrID = anIt->first->id();
314     if (anAttrID == TYPE::POLES_ID()) {
315       PointArrayWrapperPtr anArray =
316           std::dynamic_pointer_cast<PlaneGCSSolver_PointArrayWrapper>(anIt->second);
317
318       int aSize = anArray->size();
319       aNewSpline->poles.reserve(aSize);
320       for (int anIndex = 0; anIndex < aSize; ++anIndex)
321         aNewSpline->poles.push_back(*anArray->value(anIndex)->point());
322
323       aNewSpline->start = aNewSpline->poles.front();
324       aNewSpline->end = aNewSpline->poles.back();
325     }
326     else if (anAttrID == TYPE::DEGREE_ID()) {
327       ScalarWrapperPtr aScalar =
328           std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
329       aNewSpline->degree = (int)aScalar->value();
330     }
331     else if (anAttrID == SketchPlugin_BSpline::START_ID() ||
332              anAttrID == SketchPlugin_BSpline::END_ID()) {
333       anAdditionalAttributes[anAttrID] = anIt->second;
334     }
335     else {
336       ScalarArrayWrapperPtr anArray =
337           std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(anIt->second);
338       if (anAttrID == TYPE::WEIGHTS_ID())
339         aNewSpline->weights = anArray->array();
340       else if (anAttrID == TYPE::KNOTS_ID())
341         aNewSpline->knots = anArray->array();
342       else if (anAttrID == TYPE::MULTS_ID()) {
343         const GCS::VEC_pD& aValues = anArray->array();
344         aNewSpline->mult.reserve(aValues.size());
345         for (GCS::VEC_pD::const_iterator anIt = aValues.begin(); anIt != aValues.end(); ++anIt)
346           aNewSpline->mult.push_back((int)(**anIt));
347       }
348     }
349   }
350
351   EdgeWrapperPtr aWrapper(new PlaneGCSSolver_EdgeWrapper(aNewSpline));
352   aWrapper->setAdditionalAttributes(anAdditionalAttributes);
353   return aWrapper;
354 }