1 // Copyright (C) 2014-2019 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_Circle.h>
33 #include <SketchPlugin_Ellipse.h>
34 #include <SketchPlugin_EllipticArc.h>
35 #include <SketchPlugin_IntersectionPoint.h>
36 #include <SketchPlugin_Line.h>
37 #include <SketchPlugin_Point.h>
39 #include <GeomAPI_Dir2d.h>
40 #include <GeomAPI_Pnt2d.h>
41 #include <GeomAPI_XY.h>
43 static bool isAttributeApplicable(const std::string& theAttrName,
44 const std::string& theOwnerName);
46 static EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes);
47 static EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes);
48 static EntityWrapperPtr createArc(const AttributeEntityMap& theAttributes,
49 PlaneGCSSolver_Storage* theStorage);
50 static EntityWrapperPtr createEllipse(const AttributeEntityMap& theAttributes);
51 static EntityWrapperPtr createEllipticArc(const AttributeEntityMap& theAttributes,
52 PlaneGCSSolver_Storage* theStorage);
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 (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(myAttributes);
113 // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
114 else if (aFeatureKind == SketchPlugin_Point::ID() ||
115 aFeatureKind == SketchPlugin_IntersectionPoint::ID()) {
116 AttributeEntityMap::const_iterator anIt = myAttributes.begin();
117 for (; anIt != myAttributes.end(); ++anIt)
118 if (anIt->first->id() == SketchPlugin_Point::COORD_ID()) {
119 aResult = anIt->second;
124 if (aResult && !myStorage)
125 aResult->setExternal(true);
127 myAttributes.clear();
135 // ============== Auxiliary functions =====================================
136 EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes)
138 std::shared_ptr<GCS::Line> aNewLine(new GCS::Line);
140 AttributeEntityMap::const_iterator anIt = theAttributes.begin();
141 for (; anIt != theAttributes.end(); ++anIt) {
142 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
143 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
147 if (anIt->first->id() == SketchPlugin_Line::START_ID())
148 aNewLine->p1 = *(aPoint->point());
149 else if (anIt->first->id() == SketchPlugin_Line::END_ID())
150 aNewLine->p2 = *(aPoint->point());
153 return EntityWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewLine));
156 EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes)
158 std::shared_ptr<GCS::Circle> aNewCircle(new GCS::Circle);
160 AttributeEntityMap::const_iterator anIt = theAttributes.begin();
161 for (; anIt != theAttributes.end(); ++anIt) {
162 if (anIt->first->id() == SketchPlugin_Circle::CENTER_ID()) {
163 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
164 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
165 aNewCircle->center = *(aPoint->point());
167 else if(anIt->first->id() == SketchPlugin_Circle::RADIUS_ID()) {
168 ScalarWrapperPtr aScalar =
169 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
170 aNewCircle->rad = aScalar->scalar();
174 return EntityWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewCircle));
177 static double* createParameter(PlaneGCSSolver_Storage* theStorage)
179 return theStorage ? theStorage->createParameter() : (new double(0));
182 EntityWrapperPtr createArc(const AttributeEntityMap& theAttributes,
183 PlaneGCSSolver_Storage* theStorage)
185 std::shared_ptr<GCS::Arc> aNewArc(new GCS::Arc);
186 BooleanWrapperPtr isReversed;
188 // Base attributes of arc (center, start and end points)
189 AttributeEntityMap::const_iterator anIt = theAttributes.begin();
190 for (; anIt != theAttributes.end(); ++anIt) {
191 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
192 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
194 if (anIt->first->id() == SketchPlugin_Arc::CENTER_ID())
195 aNewArc->center = *(aPoint->point());
196 else if (anIt->first->id() == SketchPlugin_Arc::START_ID())
197 aNewArc->start = *(aPoint->point());
198 else if (anIt->first->id() == SketchPlugin_Arc::END_ID())
199 aNewArc->end = *(aPoint->point());
203 isReversed = std::dynamic_pointer_cast<PlaneGCSSolver_BooleanWrapper>(anIt->second);
207 // Additional attributes of arc necessary for PlaneGCS solver
208 // (start and end angles, radius)
209 aNewArc->startAngle = createParameter(theStorage);
210 aNewArc->endAngle = createParameter(theStorage);
211 aNewArc->rad = createParameter(theStorage);
213 EdgeWrapperPtr anArcWrapper(new PlaneGCSSolver_EdgeWrapper(aNewArc));
214 anArcWrapper->setReversed(isReversed);
215 PlaneGCSSolver_Tools::recalculateArcParameters(anArcWrapper);
220 EntityWrapperPtr createEllipse(const AttributeEntityMap& theAttributes)
222 std::shared_ptr<GCS::Ellipse> aNewEllipse(new GCS::Ellipse);
224 std::map<std::string, EntityWrapperPtr> anAdditionalAttributes;
226 AttributeEntityMap::const_iterator anIt = theAttributes.begin();
227 for (; anIt != theAttributes.end(); ++anIt) {
228 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
229 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
231 if (anIt->first->id() == SketchPlugin_Ellipse::CENTER_ID())
232 aNewEllipse->center = *(aPoint->point());
233 else if (anIt->first->id() == SketchPlugin_Ellipse::FIRST_FOCUS_ID())
234 aNewEllipse->focus1 = *(aPoint->point());
236 anAdditionalAttributes[anIt->first->id()] = anIt->second;
238 else if (anIt->first->id() == SketchPlugin_Ellipse::MINOR_RADIUS_ID()) {
239 ScalarWrapperPtr aScalar =
240 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
241 aNewEllipse->radmin = aScalar->scalar();
244 anAdditionalAttributes[anIt->first->id()] = anIt->second;
247 EntityWrapperPtr anEllipseWrapper(new PlaneGCSSolver_EdgeWrapper(aNewEllipse));
248 anEllipseWrapper->setAdditionalAttributes(anAdditionalAttributes);
249 return anEllipseWrapper;
252 EntityWrapperPtr createEllipticArc(const AttributeEntityMap& theAttributes,
253 PlaneGCSSolver_Storage* theStorage)
255 std::shared_ptr<GCS::ArcOfEllipse> aNewArc(new GCS::ArcOfEllipse);
257 BooleanWrapperPtr isReversed;
258 std::map<std::string, EntityWrapperPtr> anAdditionalAttributes;
260 AttributeEntityMap::const_iterator anIt = theAttributes.begin();
261 for (; anIt != theAttributes.end(); ++anIt) {
262 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
263 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
265 if (anIt->first->id() == SketchPlugin_EllipticArc::CENTER_ID())
266 aNewArc->center = *(aPoint->point());
267 else if (anIt->first->id() == SketchPlugin_EllipticArc::FIRST_FOCUS_ID())
268 aNewArc->focus1 = *(aPoint->point());
269 else if (anIt->first->id() == SketchPlugin_EllipticArc::START_POINT_ID())
270 aNewArc->start = *(aPoint->point());
271 else if (anIt->first->id() == SketchPlugin_EllipticArc::END_POINT_ID())
272 aNewArc->end = *(aPoint->point());
274 anAdditionalAttributes[anIt->first->id()] = anIt->second;
276 else if (anIt->first->id() == SketchPlugin_EllipticArc::MINOR_RADIUS_ID()) {
277 ScalarWrapperPtr aScalar =
278 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
279 aNewArc->radmin = aScalar->scalar();
281 else if (anIt->first->id() == SketchPlugin_EllipticArc::REVERSED_ID())
282 isReversed = std::dynamic_pointer_cast<PlaneGCSSolver_BooleanWrapper>(anIt->second);
284 anAdditionalAttributes[anIt->first->id()] = anIt->second;
287 // Additional attributes of elliptic arc necessary for PlaneGCS solver (start and end angles)
288 aNewArc->startAngle = createParameter(theStorage);
289 aNewArc->endAngle = createParameter(theStorage);
291 EdgeWrapperPtr anEllipseWrapper(new PlaneGCSSolver_EdgeWrapper(aNewArc));
292 anEllipseWrapper->setReversed(isReversed);
293 anEllipseWrapper->setAdditionalAttributes(anAdditionalAttributes);
294 PlaneGCSSolver_Tools::recalculateArcParameters(anEllipseWrapper);
296 return anEllipseWrapper;
299 EntityWrapperPtr createBSpline(const AttributeEntityMap& theAttributes)
301 std::shared_ptr<GCS::BSplineImpl> aNewSpline(new GCS::BSplineImpl);
303 aNewSpline->degree = 3;
304 aNewSpline->periodic = false;
306 AttributeEntityMap::const_iterator anIt = theAttributes.begin();
307 for (; anIt != theAttributes.end(); ++anIt) {
308 const std::string& anAttrID = anIt->first->id();
309 if (anAttrID == SketchPlugin_BSpline::POLES_ID()) {
310 PointArrayWrapperPtr anArray =
311 std::dynamic_pointer_cast<PlaneGCSSolver_PointArrayWrapper>(anIt->second);
313 int aSize = anArray->size();
314 aNewSpline->poles.reserve(aSize);
315 for (int anIndex = 0; anIndex < aSize; ++anIndex)
316 aNewSpline->poles.push_back(*anArray->value(anIndex)->point());
318 aNewSpline->start = aNewSpline->poles.front();
319 aNewSpline->end = aNewSpline->poles.back();
321 else if (anAttrID == SketchPlugin_BSpline::WEIGHTS_ID()) {
322 ScalarArrayWrapperPtr anArray =
323 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(anIt->second);
324 aNewSpline->weights = anArray->array();
326 else if (anAttrID == SketchPlugin_BSpline::DEGREE_ID()) {
327 ScalarWrapperPtr aScalar =
328 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
329 aNewSpline->degree = (int)aScalar->value();
333 return EdgeWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewSpline));
336 bool isAttributeApplicable(const std::string& theAttrName, const std::string& theOwnerName)
338 if (theOwnerName == SketchPlugin_Arc::ID()) {
339 return theAttrName == SketchPlugin_Arc::CENTER_ID() ||
340 theAttrName == SketchPlugin_Arc::START_ID() ||
341 theAttrName == SketchPlugin_Arc::END_ID() ||
342 theAttrName == SketchPlugin_Arc::REVERSED_ID();
344 else if (theOwnerName == SketchPlugin_Circle::ID()) {
345 return theAttrName == SketchPlugin_Circle::CENTER_ID() ||
346 theAttrName == SketchPlugin_Circle::RADIUS_ID();
348 else if (theOwnerName == SketchPlugin_Line::ID()) {
349 return theAttrName == SketchPlugin_Line::START_ID() ||
350 theAttrName == SketchPlugin_Line::END_ID();
352 else if (theOwnerName == SketchPlugin_Ellipse::ID()) {
353 return theAttrName == SketchPlugin_Ellipse::CENTER_ID() ||
354 theAttrName == SketchPlugin_Ellipse::FIRST_FOCUS_ID() ||
355 theAttrName == SketchPlugin_Ellipse::SECOND_FOCUS_ID() ||
356 theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ||
357 theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID() ||
358 theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_START_ID() ||
359 theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_END_ID() ||
360 theAttrName == SketchPlugin_Ellipse::MAJOR_RADIUS_ID() ||
361 theAttrName == SketchPlugin_Ellipse::MINOR_RADIUS_ID();
363 else if (theOwnerName == SketchPlugin_EllipticArc::ID()) {
364 return theAttrName == SketchPlugin_EllipticArc::CENTER_ID() ||
365 theAttrName == SketchPlugin_EllipticArc::FIRST_FOCUS_ID() ||
366 theAttrName == SketchPlugin_EllipticArc::SECOND_FOCUS_ID() ||
367 theAttrName == SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID() ||
368 theAttrName == SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID() ||
369 theAttrName == SketchPlugin_EllipticArc::MINOR_AXIS_START_ID() ||
370 theAttrName == SketchPlugin_EllipticArc::MINOR_AXIS_END_ID() ||
371 theAttrName == SketchPlugin_EllipticArc::MAJOR_RADIUS_ID() ||
372 theAttrName == SketchPlugin_EllipticArc::MINOR_RADIUS_ID() ||
373 theAttrName == SketchPlugin_EllipticArc::START_POINT_ID() ||
374 theAttrName == SketchPlugin_EllipticArc::END_POINT_ID() ||
375 theAttrName == SketchPlugin_EllipticArc::REVERSED_ID();
377 else if (theOwnerName == SketchPlugin_BSpline::ID()) {
378 return theAttrName == SketchPlugin_BSpline::POLES_ID() ||
379 theAttrName == SketchPlugin_BSpline::WEIGHTS_ID() ||
380 theAttrName == SketchPlugin_BSpline::DEGREE_ID();
383 // suppose that all remaining features are points
384 return theAttrName == SketchPlugin_Point::COORD_ID();