Salome HOME
988a3c5a4d676b6e1a9041d7053dc44b98e2c79f
[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 #include <PlaneGCSSolver_Tools.h>
28
29 #include <GeomAPI_Pnt2d.h>
30 #include <GeomDataAPI_Point2D.h>
31 #include <GeomDataAPI_Point2DArray.h>
32 #include <ModelAPI_AttributeDouble.h>
33 #include <ModelAPI_AttributeDoubleArray.h>
34 #include <ModelAPI_AttributeInteger.h>
35 #include <SketchPlugin_BSpline.h>
36 #include <SketchPlugin_BSplinePeriodic.h>
37 #include <SketchPlugin_ConstraintAngle.h>
38 #include <SketchPlugin_MultiRotation.h>
39
40 PlaneGCSSolver_AttributeBuilder::PlaneGCSSolver_AttributeBuilder(
41     PlaneGCSSolver_Storage* theStorage)
42   : PlaneGCSSolver_EntityBuilder(theStorage)
43 {
44 }
45
46 PlaneGCSSolver_AttributeBuilder::PlaneGCSSolver_AttributeBuilder(const StoragePtr& theStorage)
47   : PlaneGCSSolver_EntityBuilder(
48         std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(theStorage).get())
49 {
50 }
51
52 static double* createParameter(PlaneGCSSolver_Storage* theStorage)
53 {
54   return theStorage ? theStorage->createParameter() : (new double(0));
55 }
56
57 static EntityWrapperPtr createBoolean(const AttributePtr& theAttribute)
58 {
59   BooleanWrapperPtr aWrapper;
60   AttributeBooleanPtr aBoolean =
61       std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(theAttribute);
62   if (aBoolean)
63     aWrapper = BooleanWrapperPtr(new PlaneGCSSolver_BooleanWrapper(aBoolean->value()));
64   return aWrapper;
65 }
66
67 static EntityWrapperPtr createScalar(const AttributePtr&     theAttribute,
68                                      PlaneGCSSolver_Storage* theStorage)
69 {
70   double aValue = 0.0;
71   AttributeDoublePtr aDouble = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
72   if (aDouble)
73     aValue = aDouble->isInitialized() ? aDouble->value() : 0.0;
74   else {
75     AttributeIntegerPtr anInt = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(theAttribute);
76     if (anInt)
77       aValue = anInt->isInitialized() ? anInt->value() : 0.0;
78     else
79       return EntityWrapperPtr();
80   }
81
82   ScalarWrapperPtr aWrapper;
83   // following attributes should be converted from degrees to radians
84   //  - value of the Angle constraint
85   //  - angle of the Multi-Rotation constraint
86   FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
87   if ((theAttribute->id() == SketchPlugin_Constraint::VALUE() &&
88       anOwner->getKind() == SketchPlugin_ConstraintAngle::ID()) ||
89      (theAttribute->id() == SketchPlugin_MultiRotation::ANGLE_ID() &&
90       anOwner->getKind() == SketchPlugin_MultiRotation::ID()))
91     aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_AngleWrapper(createParameter(theStorage)));
92   else if ((anOwner->getKind() == SketchPlugin_BSpline::ID() &&
93             theAttribute->id() == SketchPlugin_BSpline::DEGREE_ID()) ||
94            (anOwner->getKind() == SketchPlugin_BSplinePeriodic::ID() &&
95             theAttribute->id() == SketchPlugin_BSplinePeriodic::DEGREE_ID()))
96     // Degree of B-spline is not processed by the solver
97     aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(nullptr)));
98   else
99     aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(theStorage)));
100
101   aWrapper->setValue(aValue);
102   return aWrapper;
103 }
104
105 template <typename TYPE>
106 static bool nonSolverAttribute(const FeaturePtr theOwner, const std::string& theAttrId)
107 {
108   return theOwner->getKind() == TYPE::ID() && (theAttrId == TYPE::WEIGHTS_ID()
109       || theAttrId == TYPE::KNOTS_ID() || theAttrId == TYPE::MULTS_ID());
110 }
111
112 static EntityWrapperPtr createScalarArray(const AttributePtr&     theAttribute,
113                                           PlaneGCSSolver_Storage* theStorage)
114 {
115   PlaneGCSSolver_Tools::AttributeArray anArray(theAttribute);
116
117   if (!anArray.isInitialized())
118     return EntityWrapperPtr();
119
120   PlaneGCSSolver_Storage* aStorage = theStorage;
121   // Weights, knots and multiplicities of B-spline curve are not processed by the solver
122   FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
123   if (nonSolverAttribute<SketchPlugin_BSpline>(anOwner, theAttribute->id()) ||
124       nonSolverAttribute<SketchPlugin_BSplinePeriodic>(anOwner, theAttribute->id()))
125     aStorage = 0;
126
127   int aSize = anArray.size();
128   GCS::VEC_pD aParameters;
129   aParameters.reserve(aSize);
130   for (int index = 0; index < aSize; ++index) {
131     double* aParam = createParameter(aStorage);
132     *aParam = anArray.value(index);
133     aParameters.push_back(aParam);
134   }
135
136   return EntityWrapperPtr(new PlaneGCSSolver_ScalarArrayWrapper(aParameters));
137 }
138
139 static PointWrapperPtr createPoint(const GeomPnt2dPtr& thePoint, PlaneGCSSolver_Storage* theStorage)
140 {
141   GCSPointPtr aNewPoint(new GCS::Point);
142
143   aNewPoint->x = createParameter(theStorage);
144   aNewPoint->y = createParameter(theStorage);
145   if (thePoint) {
146     *(aNewPoint->x) = thePoint->x();
147     *(aNewPoint->y) = thePoint->y();
148   }
149
150   return PointWrapperPtr(new PlaneGCSSolver_PointWrapper(aNewPoint));
151 }
152
153 static EntityWrapperPtr createPoint(const AttributePtr&     theAttribute,
154                                     PlaneGCSSolver_Storage* theStorage)
155 {
156   std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
157       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
158   if (!aPoint2D)
159     return EntityWrapperPtr();
160
161   GeomPnt2dPtr aPnt;
162   if (aPoint2D->isInitialized())
163     aPnt = aPoint2D->pnt();
164
165   return createPoint(aPnt, theStorage);
166 }
167
168 static EntityWrapperPtr createPointArray(const AttributePtr& theAttribute,
169                                          PlaneGCSSolver_Storage* theStorage)
170 {
171   std::shared_ptr<GeomDataAPI_Point2DArray> aPointArray =
172       std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(theAttribute);
173   if (!aPointArray)
174     return EntityWrapperPtr();
175
176   int aSize = aPointArray->size();
177
178   std::vector<PointWrapperPtr> aPointWrappers;
179   aPointWrappers.reserve(aSize);
180   for (int index = 0; index < aSize; ++index)
181     aPointWrappers.push_back(createPoint(aPointArray->pnt(index), theStorage));
182
183   return EntityWrapperPtr(new PlaneGCSSolver_PointArrayWrapper(aPointWrappers));
184 }
185
186 EntityWrapperPtr PlaneGCSSolver_AttributeBuilder::createAttribute(
187     AttributePtr theAttribute)
188 {
189   EntityWrapperPtr aResult;
190   if (myStorage)
191     aResult = myStorage->entity(theAttribute);
192   if (!aResult)
193     aResult = createPoint(theAttribute, myStorage);
194   if (!aResult)
195     aResult = createScalar(theAttribute, myStorage);
196   if (!aResult)
197     aResult = createBoolean(theAttribute);
198   if (!aResult)
199     aResult = createPointArray(theAttribute, myStorage);
200   if (!aResult)
201     aResult = createScalarArray(theAttribute, myStorage);
202   if (aResult && !myStorage)
203     aResult->setExternal(true);
204   return aResult;
205 }
206
207 bool PlaneGCSSolver_AttributeBuilder::updateAttribute(
208     AttributePtr theAttribute,
209     EntityWrapperPtr theEntity)
210 {
211   bool isUpdated = false;
212   GCS::SET_pD aParamsToRemove;
213   // rebuild array if its size is changed
214   if (theEntity->type() == ENTITY_POINT_ARRAY) {
215     std::shared_ptr<PlaneGCSSolver_PointArrayWrapper> aWrapper =
216         std::dynamic_pointer_cast<PlaneGCSSolver_PointArrayWrapper>(theEntity);
217     std::shared_ptr<GeomDataAPI_Point2DArray> anAttribute =
218         std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(theAttribute);
219
220     if (aWrapper->size() != anAttribute->size()) {
221       std::vector<PointWrapperPtr> aPointsArray = aWrapper->array();
222       while (anAttribute->size() > (int)aPointsArray.size()) {
223         // add points to the middle of array
224         aPointsArray.insert(--aPointsArray.end(), createPoint(GeomPnt2dPtr(), myStorage));
225       }
226
227       while (anAttribute->size() < (int)aPointsArray.size()) {
228         // remove middle points
229         std::vector<PointWrapperPtr>::iterator anIt = --aPointsArray.end();
230         GCS::SET_pD aParams = PlaneGCSSolver_Tools::parameters(*anIt);
231         aParamsToRemove.insert(aParams.begin(), aParams.end());
232         aPointsArray.erase(anIt);
233       }
234
235       aWrapper->setArray(aPointsArray);
236     }
237   }
238   else if (theEntity->type() == ENTITY_SCALAR_ARRAY) {
239     std::shared_ptr<PlaneGCSSolver_ScalarArrayWrapper> aWrapper =
240         std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(theEntity);
241     if (aWrapper->size() != PlaneGCSSolver_Tools::AttributeArray(theAttribute).size()) {
242       aParamsToRemove = PlaneGCSSolver_Tools::parameters(aWrapper);
243       std::shared_ptr<PlaneGCSSolver_ScalarArrayWrapper> aNewArray =
244           std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(
245           createAttribute(theAttribute));
246       aWrapper->setArray(aNewArray->array());
247       isUpdated = true;
248     }
249   }
250
251   if (!aParamsToRemove.empty()) {
252     if (myStorage)
253       myStorage->removeParameters(aParamsToRemove);
254     else {
255       std::for_each(aParamsToRemove.begin(), aParamsToRemove.end(),
256                     [](double* theParam) { delete theParam; });
257     }
258   }
259
260   return isUpdated || theEntity->update(theAttribute);
261 }