Salome HOME
fd4ebcf0d4ab73f97a1d6109445a1aea8cdcae6e
[modules/shaper.git] / src / BuildPlugin / BuildPlugin_Interpolation.cpp
1 // Copyright (C) 2014-2021  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 "BuildPlugin_Interpolation.h"
21
22 #include <ModelAPI_AttributeBoolean.h>
23 #include <ModelAPI_AttributeDouble.h>
24 #include <ModelAPI_AttributeInteger.h>
25 #include <ModelAPI_AttributeRefList.h>
26 #include <ModelAPI_AttributeSelectionList.h>
27 #include <ModelAPI_AttributeString.h>
28 #include <ModelAPI_AttributeTables.h>
29 #include <ModelAPI_Events.h>
30 #include <ModelAPI_ResultBody.h>
31 #include <ModelAPI_ResultParameter.h>
32 #include <ModelAPI_Session.h>
33 #include <ModelAPI_Validator.h>
34
35 #include <Events_InfoMessage.h>
36
37 #include <Locale_Convert.h>
38
39 #include <GeomAlgoAPI_ShapeTools.h>
40 #include <GeomAlgoAPI_CurveBuilder.h>
41 #include <GeomAlgoAPI_PointBuilder.h>
42
43 #include <GeomAPI_Edge.h>
44 #include <GeomAPI_Lin.h>
45 #include <GeomAPI_ShapeExplorer.h>
46
47 #include <algorithm>
48 #include <sstream>
49
50 //=================================================================================================
51 BuildPlugin_Interpolation::BuildPlugin_Interpolation()
52 {
53 }
54
55 //=================================================================================================
56 void BuildPlugin_Interpolation::initAttributes()
57 {
58   data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
59   data()->addAttribute(CLOSED_ID(), ModelAPI_AttributeBoolean::typeId());
60   data()->addAttribute(REORDER_ID(), ModelAPI_AttributeBoolean::typeId());
61   data()->addAttribute(USE_TANGENTS_ID(), ModelAPI_AttributeString::typeId());
62   data()->addAttribute(TANGENT_START_ID(), ModelAPI_AttributeSelection::typeId());
63   data()->addAttribute(TANGENT_END_ID(), ModelAPI_AttributeSelection::typeId());
64
65   data()->addAttribute(CREATION_METHOD_ID(), ModelAPI_AttributeString::typeId());
66   data()->addAttribute(CREATION_METHOD_BY_SELECTION_ID(), ModelAPI_AttributeString::typeId());
67   data()->addAttribute(CREATION_METHOD_ANALYTICAL_ID(), ModelAPI_AttributeString::typeId());
68   data()->addAttribute(EXPRESSION_ERROR_ID(), ModelAPI_AttributeString::typeId());
69   data()->addAttribute(VARIABLE_ID(), ModelAPI_AttributeString::typeId());
70   data()->addAttribute(VALUE_ID(), ModelAPI_AttributeTables::typeId());
71   data()->string(EXPRESSION_ERROR_ID())->setIsArgument(false);
72   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXPRESSION_ERROR_ID());
73
74   data()->addAttribute(XT_ID(), ModelAPI_AttributeString::typeId());
75   data()->addAttribute(YT_ID(), ModelAPI_AttributeString::typeId());
76   data()->addAttribute(ZT_ID(), ModelAPI_AttributeString::typeId());
77   data()->addAttribute(MINT_ID(), ModelAPI_AttributeDouble::typeId());
78   data()->addAttribute(MAXT_ID(), ModelAPI_AttributeDouble::typeId());
79   data()->addAttribute(NUMSTEP_ID(), ModelAPI_AttributeInteger::typeId());
80
81   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(),
82                                                  CREATION_METHOD_ANALYTICAL_ID());
83   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(),
84                                                  CREATION_METHOD_BY_SELECTION_ID());
85   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), VARIABLE_ID());
86   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), VALUE_ID());
87   data()->addAttribute(ARGUMENTS_ID(), ModelAPI_AttributeRefList::typeId());
88   data()->reflist(ARGUMENTS_ID())->setIsArgument(false);
89   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), ARGUMENTS_ID());
90
91   if (string(XT_ID())->value() == ""
92      && string(YT_ID())->value() == ""
93      && string(ZT_ID())->value() == "") {
94       string(XT_ID())->setValue("t");
95       string(YT_ID())->setValue("t");
96       string(ZT_ID())->setValue("t");
97       real(MINT_ID())->setValue(0);
98       real(MAXT_ID())->setValue(100);
99       integer(NUMSTEP_ID())->setValue(10);
100       updateCoordinates();
101   }
102 }
103
104 //=================================================================================================
105 void BuildPlugin_Interpolation::attributeChanged(const std::string& theID)
106 {
107   if ((theID == XT_ID()
108     || theID == YT_ID()
109     || theID == ZT_ID()
110     || theID == MINT_ID()
111     || theID == MAXT_ID()
112     || theID == NUMSTEP_ID())
113     && string(XT_ID())->value() !=""
114     && string(YT_ID())->value() !=""
115     && string(ZT_ID())->value() !=""
116     && string(CREATION_METHOD_ID())->value() == CREATION_METHOD_ANALYTICAL_ID()) {
117     updateCoordinates();
118   }
119 }
120
121 //=================================================================================================
122 void BuildPlugin_Interpolation::updateCoordinates()
123 {
124     std::wstring exp;
125     double aMint = real(MINT_ID())->value();
126     double aMaxt = real(MAXT_ID())->value();
127     int aNbrStep = integer(NUMSTEP_ID())->value();
128
129     if (aMaxt < aMint) {
130       setError("The minimum value of the parameter must be less than maximum value !!!");
131     }
132
133     double aScale = (aMaxt - aMint)/aNbrStep;
134     string(VARIABLE_ID())->setValue("t");
135
136     tables(VALUE_ID())->setSize(aNbrStep+1,4);
137     for (int step = 0; step <= aNbrStep; step++) {
138       ModelAPI_AttributeTables::Value aVal;
139       aVal.myDouble = step * aScale + aMint;
140       tables(VALUE_ID())->setValue(aVal,step,0);
141     }
142
143     outErrorMessage="";
144     evaluate(outErrorMessage);
145     data()->string(EXPRESSION_ERROR_ID())->setValue(outErrorMessage);
146     if (!outErrorMessage.empty()) {
147       setError("Error: Python interpreter ");
148       return;
149     }
150 }
151
152 //=================================================================================================
153 static GeomDirPtr selectionToDir(const AttributeSelectionPtr& theSelection)
154 {
155   GeomDirPtr aDir;
156   GeomEdgePtr anEdge;
157
158   GeomShapePtr aShape = theSelection->value();
159   if (!aShape && theSelection->context()) {
160     aShape = theSelection->context()->shape();
161   }
162
163   if (aShape && aShape->isEdge()) {
164     anEdge = GeomEdgePtr(new GeomAPI_Edge(aShape));
165   }
166
167   if (anEdge && anEdge->isLine()) {
168     aDir = anEdge->line()->direction();
169   }
170
171   return aDir;
172 }
173
174 //=================================================================================================
175 void BuildPlugin_Interpolation::execute()
176 {
177   if (string(CREATION_METHOD_ID())->value() == CREATION_METHOD_BY_SELECTION_ID()) {
178     // Get closed flag value
179     bool isClosed = boolean(CLOSED_ID())->value();
180
181     // Get reorder flag value
182     bool isToReorder = boolean(REORDER_ID())->value();
183
184     // Get use tangents flag value
185     bool isToUseTangents = isClosed? false : (!string(USE_TANGENTS_ID())->value().empty());
186
187     // Get tangent for start and end points
188     GeomDirPtr aDirStart, aDirEnd;
189     if (isToUseTangents) {
190       aDirStart = selectionToDir(selection(TANGENT_START_ID()));
191       aDirEnd = selectionToDir(selection(TANGENT_END_ID()));
192     }
193
194     // Get base objects list.
195     AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
196
197     // Collect points.
198     std::list<GeomPointPtr> aPoints;
199     std::set<GeomShapePtr> aContexts;
200     for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
201       AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
202
203       GeomShapePtr aContextShape = aSelection->context()->shape();
204       aContexts.insert(aContextShape);
205
206       GeomShapePtr aShape = aSelection->value();
207       if (!aShape.get()) {
208         aShape = aContextShape;
209       }
210
211       GeomPointPtr aPoint = GeomAlgoAPI_PointBuilder::point(aShape);
212       aPoints.push_back(aPoint);
213     }
214
215     // Create curve from points
216     GeomEdgePtr anEdge =
217       GeomAlgoAPI_CurveBuilder::edge(aPoints, isClosed, isToReorder, aDirStart, aDirEnd);
218     if (!anEdge.get()) {
219       setError("Error: Result curve is empty.");
220       return;
221     }
222
223     // Store result.
224     ResultBodyPtr aResultBody = document()->createBody(data());
225     std::set<GeomShapePtr>::const_iterator aContextIt = aContexts.begin();
226     for (; aContextIt != aContexts.end(); aContextIt++) {
227       aResultBody->storeModified(*aContextIt, anEdge, aContextIt == aContexts.begin());
228     }
229     int aVertexIndex = 1;
230     for (GeomAPI_ShapeExplorer anExp(anEdge, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) {
231       std::string aVertexName = "Vertex_" + std::to_string((long long)aVertexIndex);
232       aResultBody->generated(anExp.current(), aVertexName);
233     }
234
235     setResult(aResultBody);
236
237   } else {
238     if (string(XT_ID())->value() == ""
239         ||string(YT_ID())->value() == ""
240         ||string(ZT_ID())->value() == ""
241         ||tables(VALUE_ID())->rows()== 0)
242       return;
243
244     bool aWasBlocked = data()->blockSendAttributeUpdated(true);
245     updateCoordinates();
246     data()->blockSendAttributeUpdated(aWasBlocked, false);
247
248     AttributeTablesPtr aTable = tables(VALUE_ID());
249     std::list<std::vector<double>> aCoordPoints;
250     for (int step = 0; step < aTable->rows(); step++) {
251       std::vector<double> aCoordPoint;
252       ModelAPI_AttributeTables::Value aValue;
253       //x
254       aValue = aTable->value(step, 1);
255       aCoordPoint.push_back(aValue.myDouble);
256       //y
257       aValue = aTable->value(step, 2);
258       aCoordPoint.push_back(aValue.myDouble);
259       //
260       aValue = aTable->value(step, 3);
261       aCoordPoint.push_back(aValue.myDouble);
262
263       aCoordPoints.push_back(aCoordPoint);
264     }
265
266     std::list<GeomPointPtr> aPoints;
267     std::list<std::vector<double>>::const_iterator anItCoordPoints = aCoordPoints.begin();
268
269     for (; anItCoordPoints!=aCoordPoints.end(); ++anItCoordPoints) {
270
271       GeomVertexPtr aVertex = GeomAlgoAPI_PointBuilder::vertex((*anItCoordPoints)[0],
272                                                                (*anItCoordPoints)[1],
273                                                                (*anItCoordPoints)[2]);
274       aPoints.push_back(aVertex->point());
275     }
276
277     // test if some points are identical
278     std::list<GeomPointPtr>::const_iterator anItPoint1 = aPoints.begin();
279     std::list<GeomPointPtr>::const_iterator anItPoint2;
280     for(; anItPoint1 != aPoints.end(); ++ anItPoint1) {
281       anItPoint2 = anItPoint1;
282       ++anItPoint2;
283       for(; anItPoint2 != aPoints.end(); ++ anItPoint2)
284           if ((*anItPoint2)->isEqual(*anItPoint1)) {
285             setError("Error: Several points are identical");
286             return;
287           }
288     }
289
290     // Create curve from points
291     GeomEdgePtr anEdge =
292       GeomAlgoAPI_CurveBuilder::edge(aPoints, false, false,GeomDirPtr(),GeomDirPtr());
293     if (!anEdge.get()) {
294       setError("Error: Result curve is empty.");
295       return;
296     }
297
298     ResultBodyPtr aResultBody = document()->createBody(data());
299     // Load the result
300     aResultBody->store(anEdge);
301     int aVertexIndex = 1;
302     for (GeomAPI_ShapeExplorer anExp(anEdge, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) {
303       std::string aVertexName = "Vertex_" + std::to_string((long long)aVertexIndex);
304       aResultBody->generated(anExp.current(), aVertexName);
305       aVertexIndex++;
306     }
307     setResult(aResultBody);
308   }
309 }
310
311 //=================================================================================================
312 void BuildPlugin_Interpolation::evaluate(std::string& theError)
313 {
314   FeaturePtr aMyPtr = std::dynamic_pointer_cast<ModelAPI_Feature>(data()->owner());
315   std::shared_ptr<ModelAPI_BuildEvalMessage> aProcessMessage =
316     ModelAPI_BuildEvalMessage::send(aMyPtr, this);
317
318   if (aProcessMessage->isProcessed()) {
319     theError = aProcessMessage->error();
320
321     const std::list<ResultParameterPtr>& aParamsList = aProcessMessage->params();
322     //store the list of parameters to store if changed
323     AttributeRefListPtr aParams = reflist(ARGUMENTS_ID());
324     aParams->clear();
325     std::list<ResultParameterPtr>::const_iterator aNewIter = aParamsList.begin();
326     for (; aNewIter != aParamsList.end(); aNewIter++) {
327       aParams->append(*aNewIter);
328     }
329   } else { // error: python interpreter is not active
330     theError = "Python interpreter is not available";
331   }
332 }