1 // Copyright (C) 2014-2022 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
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>
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>
40 #include <GeomAPI_Dir2d.h>
41 #include <GeomAPI_Pnt2d.h>
42 #include <GeomAPI_XY.h>
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);
56 PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(
57 PlaneGCSSolver_Storage* theStorage)
58 : PlaneGCSSolver_AttributeBuilder(theStorage)
62 PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(const StoragePtr& theStorage)
63 : PlaneGCSSolver_AttributeBuilder(theStorage)
67 EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createAttribute(
68 AttributePtr theAttribute)
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);
75 myAttributes[theAttribute] = anAttr;
79 EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createFeature(FeaturePtr theFeature)
81 EntityWrapperPtr aResult;
83 aResult = myStorage->entity(theFeature);
87 // Process SketchPlugin features only
88 std::shared_ptr<SketchPlugin_Feature> aFeature =
89 std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
93 // Verify the feature by its kind
94 const std::string& aFeatureKind = aFeature->getKind();
96 if (aFeatureKind == SketchPlugin_Line::ID())
97 aResult = createLine(myAttributes);
99 else if (aFeatureKind == SketchPlugin_Circle::ID())
100 aResult = createCircle(myAttributes);
102 else if (aFeatureKind == SketchPlugin_Arc::ID())
103 aResult = createArc(myAttributes, myStorage);
105 else if (aFeatureKind == SketchPlugin_Ellipse::ID())
106 aResult = createEllipse(myAttributes);
108 else if (aFeatureKind == SketchPlugin_EllipticArc::ID())
109 aResult = createEllipticArc(myAttributes, myStorage);
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;
126 if (aResult && !myStorage)
127 aResult->setExternal(true);
129 myAttributes.clear();
137 // ============== Auxiliary functions =====================================
138 EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes)
140 std::shared_ptr<GCS::Line> aNewLine(new GCS::Line);
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);
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());
155 return EntityWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewLine));
158 EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes)
160 std::shared_ptr<GCS::Circle> aNewCircle(new GCS::Circle);
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());
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();
176 return EntityWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewCircle));
179 static double* createParameter(PlaneGCSSolver_Storage* theStorage)
181 return theStorage ? theStorage->createParameter() : (new double(0));
184 EntityWrapperPtr createArc(const AttributeEntityMap& theAttributes,
185 PlaneGCSSolver_Storage* theStorage)
187 std::shared_ptr<GCS::Arc> aNewArc(new GCS::Arc);
188 BooleanWrapperPtr isReversed;
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);
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());
205 isReversed = std::dynamic_pointer_cast<PlaneGCSSolver_BooleanWrapper>(anIt->second);
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);
215 EdgeWrapperPtr anArcWrapper(new PlaneGCSSolver_EdgeWrapper(aNewArc));
216 anArcWrapper->setReversed(isReversed);
217 PlaneGCSSolver_Tools::recalculateArcParameters(anArcWrapper);
222 EntityWrapperPtr createEllipse(const AttributeEntityMap& theAttributes)
224 std::shared_ptr<GCS::Ellipse> aNewEllipse(new GCS::Ellipse);
226 std::map<std::string, EntityWrapperPtr> anAdditionalAttributes;
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);
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());
238 anAdditionalAttributes[anIt->first->id()] = anIt->second;
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();
246 anAdditionalAttributes[anIt->first->id()] = anIt->second;
249 EntityWrapperPtr anEllipseWrapper(new PlaneGCSSolver_EdgeWrapper(aNewEllipse));
250 anEllipseWrapper->setAdditionalAttributes(anAdditionalAttributes);
251 return anEllipseWrapper;
254 EntityWrapperPtr createEllipticArc(const AttributeEntityMap& theAttributes,
255 PlaneGCSSolver_Storage* theStorage)
257 std::shared_ptr<GCS::ArcOfEllipse> aNewArc(new GCS::ArcOfEllipse);
259 BooleanWrapperPtr isReversed;
260 std::map<std::string, EntityWrapperPtr> anAdditionalAttributes;
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);
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());
276 anAdditionalAttributes[anIt->first->id()] = anIt->second;
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();
283 else if (anIt->first->id() == SketchPlugin_EllipticArc::REVERSED_ID())
284 isReversed = std::dynamic_pointer_cast<PlaneGCSSolver_BooleanWrapper>(anIt->second);
286 anAdditionalAttributes[anIt->first->id()] = anIt->second;
289 // Additional attributes of elliptic arc necessary for PlaneGCS solver (start and end angles)
290 aNewArc->startAngle = createParameter(theStorage);
291 aNewArc->endAngle = createParameter(theStorage);
293 EdgeWrapperPtr anEllipseWrapper(new PlaneGCSSolver_EdgeWrapper(aNewArc));
294 anEllipseWrapper->setReversed(isReversed);
295 anEllipseWrapper->setAdditionalAttributes(anAdditionalAttributes);
296 PlaneGCSSolver_Tools::recalculateArcParameters(anEllipseWrapper);
298 return anEllipseWrapper;
301 template <typename TYPE>
302 EntityWrapperPtr createBSpline(const AttributeEntityMap& theAttributes)
304 std::shared_ptr<GCS::BSplineImpl> aNewSpline(new GCS::BSplineImpl);
306 aNewSpline->degree = 3;
307 aNewSpline->periodic = std::is_same<TYPE, SketchPlugin_BSplinePeriodic>();
309 std::map<std::string, EntityWrapperPtr> anAdditionalAttributes;
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);
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());
323 aNewSpline->start = aNewSpline->poles.front();
324 aNewSpline->end = aNewSpline->poles.back();
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();
331 else if (anAttrID == SketchPlugin_BSpline::START_ID() ||
332 anAttrID == SketchPlugin_BSpline::END_ID()) {
333 anAdditionalAttributes[anAttrID] = anIt->second;
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));
351 EdgeWrapperPtr aWrapper(new PlaneGCSSolver_EdgeWrapper(aNewSpline));
352 aWrapper->setAdditionalAttributes(anAdditionalAttributes);