Salome HOME
Issue #17347: B-Splines in Sketcher
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_AttributeBuilder.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_AngleWrapper.h>
21 #include <PlaneGCSSolver_AttributeBuilder.h>
22 #include <PlaneGCSSolver_PointArrayWrapper.h>
23 #include <PlaneGCSSolver_PointWrapper.h>
24 #include <PlaneGCSSolver_ScalarWrapper.h>
25 #include <PlaneGCSSolver_ScalarArrayWrapper.h>
26 #include <PlaneGCSSolver_BooleanWrapper.h>
27
28 #include <GeomAPI_Pnt2d.h>
29 #include <GeomDataAPI_Point2D.h>
30 #include <GeomDataAPI_Point2DArray.h>
31 #include <ModelAPI_AttributeDouble.h>
32 #include <ModelAPI_AttributeDoubleArray.h>
33 #include <ModelAPI_AttributeInteger.h>
34 #include <SketchPlugin_BSpline.h>
35 #include <SketchPlugin_ConstraintAngle.h>
36 #include <SketchPlugin_MultiRotation.h>
37
38 PlaneGCSSolver_AttributeBuilder::PlaneGCSSolver_AttributeBuilder(
39     PlaneGCSSolver_Storage* theStorage)
40   : PlaneGCSSolver_EntityBuilder(theStorage)
41 {
42 }
43
44 PlaneGCSSolver_AttributeBuilder::PlaneGCSSolver_AttributeBuilder(const StoragePtr& theStorage)
45   : PlaneGCSSolver_EntityBuilder(
46         std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(theStorage).get())
47 {
48 }
49
50 static double* createParameter(PlaneGCSSolver_Storage* theStorage)
51 {
52   return theStorage ? theStorage->createParameter() : (new double(0));
53 }
54
55 static EntityWrapperPtr createBoolean(const AttributePtr& theAttribute)
56 {
57   BooleanWrapperPtr aWrapper;
58   AttributeBooleanPtr aBoolean =
59       std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(theAttribute);
60   if (aBoolean)
61     aWrapper = BooleanWrapperPtr(new PlaneGCSSolver_BooleanWrapper(aBoolean->value()));
62   return aWrapper;
63 }
64
65 static EntityWrapperPtr createScalar(const AttributePtr&     theAttribute,
66                                      PlaneGCSSolver_Storage* theStorage)
67 {
68   double aValue = 0.0;
69   AttributeDoublePtr aDouble = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
70   if (aDouble)
71     aValue = aDouble->isInitialized() ? aDouble->value() : 0.0;
72   else {
73     AttributeIntegerPtr anInt = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(theAttribute);
74     if (anInt)
75       aValue = anInt->isInitialized() ? anInt->value() : 0.0;
76     else
77       return EntityWrapperPtr();
78   }
79
80   ScalarWrapperPtr aWrapper;
81   // following attributes should be converted from degrees to radians
82   //  - value of the Angle constraint
83   //  - angle of the Multi-Rotation constraint
84   FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
85   if ((theAttribute->id() == SketchPlugin_Constraint::VALUE() &&
86       anOwner->getKind() == SketchPlugin_ConstraintAngle::ID()) ||
87      (theAttribute->id() == SketchPlugin_MultiRotation::ANGLE_ID() &&
88       anOwner->getKind() == SketchPlugin_MultiRotation::ID()))
89     aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_AngleWrapper(createParameter(theStorage)));
90   else if (anOwner->getKind() == SketchPlugin_BSpline::ID() &&
91            theAttribute->id() == SketchPlugin_BSpline::DEGREE_ID())
92     // Degree of B-spline is not processed by the solver
93     aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(nullptr)));
94   else
95     aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(theStorage)));
96
97   aWrapper->setValue(aValue);
98   return aWrapper;
99 }
100
101 static EntityWrapperPtr createScalarArray(const AttributePtr&     theAttribute,
102                                           PlaneGCSSolver_Storage* theStorage)
103 {
104   AttributeDoubleArrayPtr anArray =
105       std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(theAttribute);
106   if (!anArray || !anArray->isInitialized())
107     return EntityWrapperPtr();
108
109   PlaneGCSSolver_Storage* aStorage = theStorage;
110   // Weights of B-spline curve are not processed by the solver
111   FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
112   if (anOwner->getKind() == SketchPlugin_BSpline::ID() &&
113       theAttribute->id() == SketchPlugin_BSpline::WEIGHTS_ID())
114     aStorage = 0;
115
116   int aSize = anArray->size();
117   GCS::VEC_pD aParameters;
118   aParameters.reserve(aSize);
119   for (int index = 0; index < aSize; ++index) {
120     double* aParam = createParameter(aStorage);
121     *aParam = anArray->value(index);
122     aParameters.push_back(aParam);
123   }
124
125   return EntityWrapperPtr(new PlaneGCSSolver_ScalarArrayWrapper(aParameters));
126 }
127
128 static PointWrapperPtr createPoint(const GeomPnt2dPtr& thePoint, PlaneGCSSolver_Storage* theStorage)
129 {
130   GCSPointPtr aNewPoint(new GCS::Point);
131
132   aNewPoint->x = createParameter(theStorage);
133   aNewPoint->y = createParameter(theStorage);
134   if (thePoint) {
135     *(aNewPoint->x) = thePoint->x();
136     *(aNewPoint->y) = thePoint->y();
137   }
138
139   return PointWrapperPtr(new PlaneGCSSolver_PointWrapper(aNewPoint));
140 }
141
142 static EntityWrapperPtr createPoint(const AttributePtr&     theAttribute,
143                                     PlaneGCSSolver_Storage* theStorage)
144 {
145   std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
146       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
147   if (!aPoint2D)
148     return EntityWrapperPtr();
149
150   GeomPnt2dPtr aPnt;
151   if (aPoint2D->isInitialized())
152     aPnt = aPoint2D->pnt();
153
154   return createPoint(aPnt, theStorage);
155 }
156
157 static EntityWrapperPtr createPointArray(const AttributePtr& theAttribute,
158                                          PlaneGCSSolver_Storage* theStorage)
159 {
160   std::shared_ptr<GeomDataAPI_Point2DArray> aPointArray =
161       std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(theAttribute);
162   if (!aPointArray)
163     return EntityWrapperPtr();
164
165   int aSize = aPointArray->size();
166
167   std::vector<PointWrapperPtr> aPointWrappers;
168   aPointWrappers.reserve(aSize);
169   for (int index = 0; index < aSize; ++index)
170     aPointWrappers.push_back(createPoint(aPointArray->pnt(index), theStorage));
171
172   return EntityWrapperPtr(new PlaneGCSSolver_PointArrayWrapper(aPointWrappers));
173 }
174
175 EntityWrapperPtr PlaneGCSSolver_AttributeBuilder::createAttribute(
176     AttributePtr theAttribute)
177 {
178   EntityWrapperPtr aResult;
179   if (myStorage)
180     aResult = myStorage->entity(theAttribute);
181   if (!aResult)
182     aResult = createPoint(theAttribute, myStorage);
183   if (!aResult)
184     aResult = createScalar(theAttribute, myStorage);
185   if (!aResult)
186     aResult = createBoolean(theAttribute);
187   if (!aResult)
188     aResult = createPointArray(theAttribute, myStorage);
189   if (!aResult)
190     aResult = createScalarArray(theAttribute, myStorage);
191   if (aResult && !myStorage)
192     aResult->setExternal(true);
193   return aResult;
194 }