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_BSplinePeriodic.h>
37 #include <SketchPlugin_ConstraintAngle.h>
38 #include <SketchPlugin_MultiRotation.h>
40 PlaneGCSSolver_AttributeBuilder::PlaneGCSSolver_AttributeBuilder(
41 PlaneGCSSolver_Storage* theStorage)
42 : PlaneGCSSolver_EntityBuilder(theStorage)
46 PlaneGCSSolver_AttributeBuilder::PlaneGCSSolver_AttributeBuilder(const StoragePtr& theStorage)
47 : PlaneGCSSolver_EntityBuilder(
48 std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(theStorage).get())
52 static double* createParameter(PlaneGCSSolver_Storage* theStorage)
54 return theStorage ? theStorage->createParameter() : (new double(0));
57 static EntityWrapperPtr createBoolean(const AttributePtr& theAttribute)
59 BooleanWrapperPtr aWrapper;
60 AttributeBooleanPtr aBoolean =
61 std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(theAttribute);
63 aWrapper = BooleanWrapperPtr(new PlaneGCSSolver_BooleanWrapper(aBoolean->value()));
67 static EntityWrapperPtr createScalar(const AttributePtr& theAttribute,
68 PlaneGCSSolver_Storage* theStorage)
71 AttributeDoublePtr aDouble = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
73 aValue = aDouble->isInitialized() ? aDouble->value() : 0.0;
75 AttributeIntegerPtr anInt = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(theAttribute);
77 aValue = anInt->isInitialized() ? anInt->value() : 0.0;
79 return EntityWrapperPtr();
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 anOwner->getKind() == SketchPlugin_BSplinePeriodic::ID()) &&
94 theAttribute->id() == SketchPlugin_BSplineBase::DEGREE_ID())
95 // Degree of B-spline is not processed by the solver
96 aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(nullptr)));
98 aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(theStorage)));
100 aWrapper->setValue(aValue);
104 template <typename TYPE>
105 static bool nonSolverAttribute(const FeaturePtr theOwner, const std::string& theAttrId)
107 return theOwner->getKind() == TYPE::ID() && (theAttrId == TYPE::WEIGHTS_ID()
108 || theAttrId == TYPE::KNOTS_ID() || theAttrId == TYPE::MULTS_ID());
111 static EntityWrapperPtr createScalarArray(const AttributePtr& theAttribute,
112 PlaneGCSSolver_Storage* theStorage)
114 PlaneGCSSolver_Tools::AttributeArray anArray(theAttribute);
116 if (!anArray.isInitialized())
117 return EntityWrapperPtr();
119 PlaneGCSSolver_Storage* aStorage = theStorage;
120 // Weights, knots and multiplicities of B-spline curve are not processed by the solver
121 FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
122 if (nonSolverAttribute<SketchPlugin_BSpline>(anOwner, theAttribute->id()) ||
123 nonSolverAttribute<SketchPlugin_BSplinePeriodic>(anOwner, theAttribute->id()))
126 int aSize = anArray.size();
127 GCS::VEC_pD aParameters;
128 aParameters.reserve(aSize);
129 for (int index = 0; index < aSize; ++index) {
130 double* aParam = createParameter(aStorage);
131 *aParam = anArray.value(index);
132 aParameters.push_back(aParam);
135 return EntityWrapperPtr(new PlaneGCSSolver_ScalarArrayWrapper(aParameters));
138 static PointWrapperPtr createPoint(const GeomPnt2dPtr& thePoint, PlaneGCSSolver_Storage* theStorage)
140 GCSPointPtr aNewPoint(new GCS::Point);
142 aNewPoint->x = createParameter(theStorage);
143 aNewPoint->y = createParameter(theStorage);
145 *(aNewPoint->x) = thePoint->x();
146 *(aNewPoint->y) = thePoint->y();
149 return PointWrapperPtr(new PlaneGCSSolver_PointWrapper(aNewPoint));
152 static EntityWrapperPtr createPoint(const AttributePtr& theAttribute,
153 PlaneGCSSolver_Storage* theStorage)
155 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
156 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
158 return EntityWrapperPtr();
161 if (aPoint2D->isInitialized())
162 aPnt = aPoint2D->pnt();
164 return createPoint(aPnt, theStorage);
167 static EntityWrapperPtr createPointArray(const AttributePtr& theAttribute,
168 PlaneGCSSolver_Storage* theStorage)
170 std::shared_ptr<GeomDataAPI_Point2DArray> aPointArray =
171 std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(theAttribute);
173 return EntityWrapperPtr();
175 int aSize = aPointArray->size();
177 std::vector<PointWrapperPtr> aPointWrappers;
178 aPointWrappers.reserve(aSize);
179 for (int index = 0; index < aSize; ++index)
180 aPointWrappers.push_back(createPoint(aPointArray->pnt(index), theStorage));
182 return EntityWrapperPtr(new PlaneGCSSolver_PointArrayWrapper(aPointWrappers));
185 EntityWrapperPtr PlaneGCSSolver_AttributeBuilder::createAttribute(
186 AttributePtr theAttribute)
188 EntityWrapperPtr aResult;
190 aResult = myStorage->entity(theAttribute);
192 aResult = createPoint(theAttribute, myStorage);
194 aResult = createScalar(theAttribute, myStorage);
196 aResult = createBoolean(theAttribute);
198 aResult = createPointArray(theAttribute, myStorage);
200 aResult = createScalarArray(theAttribute, myStorage);
201 if (aResult && !myStorage)
202 aResult->setExternal(true);
206 bool PlaneGCSSolver_AttributeBuilder::updateAttribute(
207 AttributePtr theAttribute,
208 EntityWrapperPtr theEntity)
210 bool isUpdated = false;
211 GCS::SET_pD aParamsToRemove;
212 // rebuild array if its size is changed
213 if (theEntity->type() == ENTITY_POINT_ARRAY) {
214 std::shared_ptr<PlaneGCSSolver_PointArrayWrapper> aWrapper =
215 std::dynamic_pointer_cast<PlaneGCSSolver_PointArrayWrapper>(theEntity);
216 std::shared_ptr<GeomDataAPI_Point2DArray> anAttribute =
217 std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(theAttribute);
219 std::vector<PointWrapperPtr> aPointsArray = aWrapper->array();
220 std::vector<PointWrapperPtr>::iterator aPos = aPointsArray.begin();
221 if (aWrapper->size() != anAttribute->size()) {
222 while (anAttribute->size() > (int)aPointsArray.size()) {
223 // add points to the middle of array
225 for (; aPos != aPointsArray.end(); ++aPos) {
226 aValue = anAttribute->pnt(aPos - aPointsArray.begin());
227 if (aValue->distance(PlaneGCSSolver_Tools::point(*aPos)) > tolerance)
230 int aShift = aPos - aPointsArray.begin();
231 aPointsArray.insert(aPos, createPoint(aValue, myStorage));
232 aPos = aPointsArray.begin() + aShift;
235 while (anAttribute->size() < (int)aPointsArray.size()) {
236 // remove middle points
237 std::vector<PointWrapperPtr>::iterator anIt = --aPointsArray.end();
238 GCS::SET_pD aParams = PlaneGCSSolver_Tools::parameters(*anIt);
239 aParamsToRemove.insert(aParams.begin(), aParams.end());
240 aPointsArray.erase(anIt);
243 aWrapper->setArray(aPointsArray);
246 // update coordinates of points
247 for (int anIndex = 0; aPos != aPointsArray.end(); ++aPos, ++anIndex) {
248 const GCSPointPtr& aGCSPoint = (*aPos)->point();
249 GeomPnt2dPtr aCoord = anAttribute->pnt(anIndex);
250 *aGCSPoint->x = aCoord->x();
251 *aGCSPoint->y = aCoord->y();
255 else if (theEntity->type() == ENTITY_SCALAR_ARRAY) {
256 std::shared_ptr<PlaneGCSSolver_ScalarArrayWrapper> aWrapper =
257 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(theEntity);
258 if (aWrapper->size() != PlaneGCSSolver_Tools::AttributeArray(theAttribute).size()) {
259 aParamsToRemove = PlaneGCSSolver_Tools::parameters(aWrapper);
260 std::shared_ptr<PlaneGCSSolver_ScalarArrayWrapper> aNewArray =
261 std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(
262 createScalarArray(theAttribute, myStorage));
263 aWrapper->setArray(aNewArray->array());
268 if (!aParamsToRemove.empty()) {
270 myStorage->removeParameters(aParamsToRemove);
272 std::for_each(aParamsToRemove.begin(), aParamsToRemove.end(),
273 [](double* theParam) { delete theParam; });
277 return isUpdated || theEntity->update(theAttribute);