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_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>
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_ConstraintAngle.h>
37 #include <SketchPlugin_MultiRotation.h>
39 PlaneGCSSolver_AttributeBuilder::PlaneGCSSolver_AttributeBuilder(
40 PlaneGCSSolver_Storage* theStorage)
41 : PlaneGCSSolver_EntityBuilder(theStorage)
45 PlaneGCSSolver_AttributeBuilder::PlaneGCSSolver_AttributeBuilder(const StoragePtr& theStorage)
46 : PlaneGCSSolver_EntityBuilder(
47 std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(theStorage).get())
51 static double* createParameter(PlaneGCSSolver_Storage* theStorage)
53 return theStorage ? theStorage->createParameter() : (new double(0));
56 static EntityWrapperPtr createBoolean(const AttributePtr& theAttribute)
58 BooleanWrapperPtr aWrapper;
59 AttributeBooleanPtr aBoolean =
60 std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(theAttribute);
62 aWrapper = BooleanWrapperPtr(new PlaneGCSSolver_BooleanWrapper(aBoolean->value()));
66 static EntityWrapperPtr createScalar(const AttributePtr& theAttribute,
67 PlaneGCSSolver_Storage* theStorage)
70 AttributeDoublePtr aDouble = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
72 aValue = aDouble->isInitialized() ? aDouble->value() : 0.0;
74 AttributeIntegerPtr anInt = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(theAttribute);
76 aValue = anInt->isInitialized() ? anInt->value() : 0.0;
78 return EntityWrapperPtr();
81 ScalarWrapperPtr aWrapper;
82 // following attributes should be converted from degrees to radians
83 // - value of the Angle constraint
84 // - angle of the Multi-Rotation constraint
85 FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
86 if ((theAttribute->id() == SketchPlugin_Constraint::VALUE() &&
87 anOwner->getKind() == SketchPlugin_ConstraintAngle::ID()) ||
88 (theAttribute->id() == SketchPlugin_MultiRotation::ANGLE_ID() &&
89 anOwner->getKind() == SketchPlugin_MultiRotation::ID()))
90 aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_AngleWrapper(createParameter(theStorage)));
91 else if (anOwner->getKind() == SketchPlugin_BSpline::ID() &&
92 theAttribute->id() == SketchPlugin_BSpline::DEGREE_ID())
93 // Degree of B-spline is not processed by the solver
94 aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(nullptr)));
96 aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(theStorage)));
98 aWrapper->setValue(aValue);
102 static EntityWrapperPtr createScalarArray(const AttributePtr& theAttribute,
103 PlaneGCSSolver_Storage* theStorage)
105 PlaneGCSSolver_Tools::AttributeArray anArray(theAttribute);
107 if (!anArray.isInitialized())
108 return EntityWrapperPtr();
110 PlaneGCSSolver_Storage* aStorage = theStorage;
111 // Weights, knots and multiplicities of B-spline curve are not processed by the solver
112 FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
113 if (anOwner->getKind() == SketchPlugin_BSpline::ID() &&
114 (theAttribute->id() == SketchPlugin_BSpline::WEIGHTS_ID() ||
115 theAttribute->id() == SketchPlugin_BSpline::KNOTS_ID() ||
116 theAttribute->id() == SketchPlugin_BSpline::MULTS_ID()))
119 int aSize = anArray.size();
120 GCS::VEC_pD aParameters;
121 aParameters.reserve(aSize);
122 for (int index = 0; index < aSize; ++index) {
123 double* aParam = createParameter(aStorage);
124 *aParam = anArray.value(index);
125 aParameters.push_back(aParam);
128 return EntityWrapperPtr(new PlaneGCSSolver_ScalarArrayWrapper(aParameters));
131 static PointWrapperPtr createPoint(const GeomPnt2dPtr& thePoint, PlaneGCSSolver_Storage* theStorage)
133 GCSPointPtr aNewPoint(new GCS::Point);
135 aNewPoint->x = createParameter(theStorage);
136 aNewPoint->y = createParameter(theStorage);
138 *(aNewPoint->x) = thePoint->x();
139 *(aNewPoint->y) = thePoint->y();
142 return PointWrapperPtr(new PlaneGCSSolver_PointWrapper(aNewPoint));
145 static EntityWrapperPtr createPoint(const AttributePtr& theAttribute,
146 PlaneGCSSolver_Storage* theStorage)
148 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
149 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
151 return EntityWrapperPtr();
154 if (aPoint2D->isInitialized())
155 aPnt = aPoint2D->pnt();
157 return createPoint(aPnt, theStorage);
160 static EntityWrapperPtr createPointArray(const AttributePtr& theAttribute,
161 PlaneGCSSolver_Storage* theStorage)
163 std::shared_ptr<GeomDataAPI_Point2DArray> aPointArray =
164 std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(theAttribute);
166 return EntityWrapperPtr();
168 int aSize = aPointArray->size();
170 std::vector<PointWrapperPtr> aPointWrappers;
171 aPointWrappers.reserve(aSize);
172 for (int index = 0; index < aSize; ++index)
173 aPointWrappers.push_back(createPoint(aPointArray->pnt(index), theStorage));
175 return EntityWrapperPtr(new PlaneGCSSolver_PointArrayWrapper(aPointWrappers));
178 EntityWrapperPtr PlaneGCSSolver_AttributeBuilder::createAttribute(
179 AttributePtr theAttribute)
181 EntityWrapperPtr aResult;
183 aResult = myStorage->entity(theAttribute);
185 aResult = createPoint(theAttribute, myStorage);
187 aResult = createScalar(theAttribute, myStorage);
189 aResult = createBoolean(theAttribute);
191 aResult = createPointArray(theAttribute, myStorage);
193 aResult = createScalarArray(theAttribute, myStorage);
194 if (aResult && !myStorage)
195 aResult->setExternal(true);
199 bool PlaneGCSSolver_AttributeBuilder::updateAttribute(
200 AttributePtr theAttribute,
201 EntityWrapperPtr theEntity)
203 bool isUpdated = false;
204 GCS::SET_pD aParamsToRemove;
205 // rebuild array if its size is changed
206 if (theEntity->type() == ENTITY_POINT_ARRAY) {
207 std::shared_ptr<PlaneGCSSolver_PointArrayWrapper> aWrapper =
208 std::dynamic_pointer_cast<PlaneGCSSolver_PointArrayWrapper>(theEntity);
209 std::shared_ptr<GeomDataAPI_Point2DArray> anAttribute =
210 std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(theAttribute);
212 if (aWrapper->size() != anAttribute->size()) {
213 std::vector<PointWrapperPtr> aPointsArray = aWrapper->array();
214 while (anAttribute->size() > (int)aPointsArray.size()) {
215 // add points to the middle of array
216 aPointsArray.insert(--aPointsArray.end(), createPoint(GeomPnt2dPtr(), myStorage));
219 while (anAttribute->size() < (int)aPointsArray.size()) {
220 // remove middle points
221 std::vector<PointWrapperPtr>::iterator anIt = --aPointsArray.end();
222 GCS::SET_pD aParams = PlaneGCSSolver_Tools::parameters(*anIt);
223 aParamsToRemove.insert(aParams.begin(), aParams.end());
224 aPointsArray.erase(anIt);
227 aWrapper->setArray(aPointsArray);
230 else if (theEntity->type() == ENTITY_SCALAR_ARRAY) {
231 std::shared_ptr<PlaneGCSSolver_ScalarArrayWrapper> aWrapper =
232 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(theEntity);
233 if (aWrapper->size() != PlaneGCSSolver_Tools::AttributeArray(theAttribute).size()) {
234 aParamsToRemove = PlaneGCSSolver_Tools::parameters(aWrapper);
235 std::shared_ptr<PlaneGCSSolver_ScalarArrayWrapper> aNewArray =
236 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(
237 createAttribute(theAttribute));
238 aWrapper->setArray(aNewArray->array());
243 if (!aParamsToRemove.empty()) {
245 myStorage->removeParameters(aParamsToRemove);
247 std::for_each(aParamsToRemove.begin(), aParamsToRemove.end(),
248 [](double* theParam) { delete theParam; });
252 return isUpdated || theEntity->update(theAttribute);