Salome HOME
Merge commit 'refs/tags/V9_2_0^{}'
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_MultiTranslation.cpp
1 // Copyright (C) 2014-2017  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
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include <FeaturesPlugin_MultiTranslation.h>
22
23 #include <GeomAlgoAPI_CompoundBuilder.h>
24 #include <GeomAlgoAPI_Tools.h>
25
26 #include <GeomAPI_Ax1.h>
27 #include <GeomAPI_Edge.h>
28 #include <GeomAPI_Lin.h>
29 #include <GeomAPI_ShapeIterator.h>
30 #include <GeomAPI_Trsf.h>
31
32 #include <ModelAPI_AttributeDouble.h>
33 #include <ModelAPI_AttributeInteger.h>
34 #include <ModelAPI_AttributeSelectionList.h>
35 #include <ModelAPI_AttributeString.h>
36 #include <ModelAPI_ResultBody.h>
37 #include <ModelAPI_ResultPart.h>
38
39 #include <math.h>
40
41 //=================================================================================================
42 FeaturesPlugin_MultiTranslation::FeaturesPlugin_MultiTranslation()
43 {
44 }
45
46 //=================================================================================================
47 void FeaturesPlugin_MultiTranslation::initAttributes()
48 {
49   AttributeSelectionListPtr aSelection =
50     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
51     FeaturesPlugin_MultiTranslation::OBJECTS_LIST_ID(),
52     ModelAPI_AttributeSelectionList::typeId()));
53
54   data()->addAttribute(FeaturesPlugin_MultiTranslation::AXIS_FIRST_DIR_ID(),
55                        ModelAPI_AttributeSelection::typeId());
56   data()->addAttribute(FeaturesPlugin_MultiTranslation::STEP_FIRST_DIR_ID(),
57                        ModelAPI_AttributeDouble::typeId());
58   data()->addAttribute(FeaturesPlugin_MultiTranslation::NB_COPIES_FIRST_DIR_ID(),
59                        ModelAPI_AttributeInteger::typeId());
60
61   data()->addAttribute(FeaturesPlugin_MultiTranslation::USE_SECOND_DIR_ID(),
62                        ModelAPI_AttributeString::typeId());
63   data()->addAttribute(FeaturesPlugin_MultiTranslation::AXIS_SECOND_DIR_ID(),
64                        ModelAPI_AttributeSelection::typeId());
65   data()->addAttribute(FeaturesPlugin_MultiTranslation::STEP_SECOND_DIR_ID(),
66                        ModelAPI_AttributeDouble::typeId());
67   data()->addAttribute(FeaturesPlugin_MultiTranslation::NB_COPIES_SECOND_DIR_ID(),
68                        ModelAPI_AttributeInteger::typeId());
69 }
70
71 //=================================================================================================
72 void FeaturesPlugin_MultiTranslation::execute()
73 {
74   std::string useSecondDir = string(FeaturesPlugin_MultiTranslation::USE_SECOND_DIR_ID())->value();
75   if(!useSecondDir.empty()) {
76     performTwoDirection();
77   } else {
78     performOneDirection();
79   }
80 }
81
82 //=================================================================================================
83 void FeaturesPlugin_MultiTranslation::performOneDirection()
84 {
85   // Getting objects.
86   ListOfShape anObjects;
87   std::list<ResultPtr> aContextes;
88   AttributeSelectionListPtr anObjectsSelList =
89     selectionList(FeaturesPlugin_MultiTranslation::OBJECTS_LIST_ID());
90   if (anObjectsSelList->size() == 0) {
91     setError("Error: empty selection list");
92     return;
93   }
94   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
95     std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
96       anObjectsSelList->value(anObjectsIndex);
97     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
98     if(!anObject.get()) { // may be for not-activated parts
99       return;
100     }
101     anObjects.push_back(anObject);
102     aContextes.push_back(anObjectAttr->context());
103   }
104
105   //Getting axis.
106   static const std::string aSelectionError = "Error: The axis shape selection is bad.";
107   AttributeSelectionPtr anObjRef = selection(AXIS_FIRST_DIR_ID());
108   GeomShapePtr aShape = anObjRef->value();
109   if (!aShape.get()) {
110     if (anObjRef->context().get()) {
111       aShape = anObjRef->context()->shape();
112     }
113   }
114   if (!aShape.get()) {
115     setError(aSelectionError);
116     return;
117   }
118
119   GeomEdgePtr anEdge;
120   if (aShape->isEdge())
121   {
122     anEdge = aShape->edge();
123   }
124   else if (aShape->isCompound())
125   {
126     GeomAPI_ShapeIterator anIt(aShape);
127     anEdge = anIt.current()->edge();
128   }
129
130   if (!anEdge.get())
131   {
132     setError(aSelectionError);
133     return;
134   }
135
136   std::shared_ptr<GeomAPI_Ax1> anAxis (new GeomAPI_Ax1(anEdge->line()->location(),
137                                                        anEdge->line()->direction()));
138
139   // Getting step.
140   double aStep = real(FeaturesPlugin_MultiTranslation::STEP_FIRST_DIR_ID())->value();
141
142   // Getting number of copies.
143   int nbCopies =
144     integer(FeaturesPlugin_MultiTranslation::NB_COPIES_FIRST_DIR_ID())->value();
145
146   if (nbCopies <=0) {
147     std::string aFeatureError = "Multitranslation builder ";
148     aFeatureError+=":: the number of copies for the first direction is null or negative.";
149     setError(aFeatureError);
150     return;
151   }
152
153   // Moving each object.
154   int aResultIndex = 0;
155   std::list<ResultPtr>::iterator aContext = aContextes.begin();
156   for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
157         anObjectsIt++, aContext++) {
158     std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
159     bool isPart = aContext->get() && (*aContext)->groupName() == ModelAPI_ResultPart::group();
160
161     // Setting result.
162     if (isPart) {
163       ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
164       std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
165       for (int i=0; i<nbCopies; i++) {
166         aTrsf->setTranslation(anAxis, i*aStep);
167         ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
168         aResultPart->setTrsf(*aContext, aTrsf);
169         setResult(aResultPart, aResultIndex);
170         aResultIndex++;
171       }
172     } else {
173       std::string anError;
174       ListOfShape aListOfShape;
175       std::list<std::shared_ptr<GeomAlgoAPI_Translation> > aListOfTranslationAlgo;
176
177       for (int i=0; i<nbCopies; i++) {
178         std::shared_ptr<GeomAlgoAPI_Translation> aTranslationAlgo(
179           new GeomAlgoAPI_Translation(aBaseShape, anAxis, i*aStep));
180
181         if (!aTranslationAlgo->check()) {
182           setError(aTranslationAlgo->getError());
183           break;
184         }
185
186         aTranslationAlgo->build();
187
188         // Checking that the algorithm worked properly.
189         if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(
190             aTranslationAlgo, getKind(), anError)) {
191           setError(anError);
192           break;
193         }
194         aListOfShape.push_back(aTranslationAlgo->shape());
195         aListOfTranslationAlgo.push_back(aTranslationAlgo);
196       }
197       std::shared_ptr<GeomAPI_Shape> aCompound =
198         GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
199       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
200       aResultBody->storeModified(aBaseShape, aCompound);
201       loadNamingDS(aListOfTranslationAlgo, aResultBody, aBaseShape);
202
203       setResult(aResultBody, aResultIndex);
204     }
205     aResultIndex++;
206   }
207
208   // Remove the rest results if there were produced in the previous pass.
209   removeResults(aResultIndex);
210 }
211
212 //=================================================================================================
213 void FeaturesPlugin_MultiTranslation::performTwoDirection()
214 {
215   // Getting objects.
216   ListOfShape anObjects;
217   std::list<ResultPtr> aContextes;
218   AttributeSelectionListPtr anObjectsSelList =
219     selectionList(FeaturesPlugin_MultiTranslation::OBJECTS_LIST_ID());
220   if (anObjectsSelList->size() == 0) {
221     setError("Error: empty selection list");
222     return;
223   }
224   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
225     std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
226       anObjectsSelList->value(anObjectsIndex);
227     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
228     if(!anObject.get()) { // may be for not-activated parts
229       return;
230     }
231     anObjects.push_back(anObject);
232     aContextes.push_back(anObjectAttr->context());
233   }
234
235   //Getting axis.
236   static const std::string aSelectionError = "Error: The axis shape selection is bad.";
237   AttributeSelectionPtr anObjRef = selection(AXIS_FIRST_DIR_ID());
238   GeomShapePtr aShape = anObjRef->value();
239   if (!aShape.get()) {
240     if (anObjRef->context().get()) {
241       aShape = anObjRef->context()->shape();
242     }
243   }
244   if (!aShape.get()) {
245     setError(aSelectionError);
246     return;
247   }
248
249   GeomEdgePtr anEdge;
250   if (aShape->isEdge())
251   {
252     anEdge = aShape->edge();
253   }
254   else if (aShape->isCompound())
255   {
256     GeomAPI_ShapeIterator anIt(aShape);
257     anEdge = anIt.current()->edge();
258   }
259
260   if (!anEdge.get())
261   {
262     setError(aSelectionError);
263     return;
264   }
265
266   std::shared_ptr<GeomAPI_Ax1> aFirstAxis(new GeomAPI_Ax1(anEdge->line()->location(),
267                                                           anEdge->line()->direction()));
268
269   //Getting axis.
270   anObjRef = selection(AXIS_SECOND_DIR_ID());
271   aShape = anObjRef->value();
272   if (!aShape.get()) {
273     if (anObjRef->context().get()) {
274       aShape = anObjRef->context()->shape();
275     }
276   }
277   if (!aShape.get()) {
278     setError(aSelectionError);
279     return;
280   }
281
282   if (aShape->isEdge())
283   {
284     anEdge = aShape->edge();
285   }
286   else if (aShape->isCompound())
287   {
288     GeomAPI_ShapeIterator anIt(aShape);
289     anEdge = anIt.current()->edge();
290   }
291
292   if (!anEdge.get())
293   {
294     setError(aSelectionError);
295     return;
296   }
297
298   std::shared_ptr<GeomAPI_Ax1> aSecondAxis(new GeomAPI_Ax1(anEdge->line()->location(),
299                                                            anEdge->line()->direction()));
300
301   // Getting step.
302   double aFirstStep = real(FeaturesPlugin_MultiTranslation::STEP_FIRST_DIR_ID())->value();
303   double aSecondStep = real(FeaturesPlugin_MultiTranslation::STEP_SECOND_DIR_ID())->value();
304
305   // Getting number of copies.
306   int aFirstNbCopies =
307     integer(FeaturesPlugin_MultiTranslation::NB_COPIES_FIRST_DIR_ID())->value();
308   int aSecondNbCopies =
309     integer(FeaturesPlugin_MultiTranslation::NB_COPIES_SECOND_DIR_ID())->value();
310
311   if (aFirstNbCopies <=0) {
312     std::string aFeatureError = "Multitranslation builder ";
313     aFeatureError+=":: the number of copies for the first direction is null or negative.";
314     setError(aFeatureError);
315     return;
316   }
317
318   if (aSecondNbCopies <=0) {
319     std::string aFeatureError = "Multitranslation builder ";
320     aFeatureError+=":: the number of copies for the second direction is null or negative.";
321     setError(aFeatureError);
322     return;
323   }
324
325   // Coord aFirstAxis
326   double x1 = aFirstAxis->dir()->x();
327   double y1 = aFirstAxis->dir()->y();
328   double z1 = aFirstAxis->dir()->z();
329   double norm1 = sqrt(x1*x1 + y1*y1 + z1*z1);
330
331   // Coord aSecondAxis
332   double x2 = aSecondAxis->dir()->x();
333   double y2 = aSecondAxis->dir()->y();
334   double z2 = aSecondAxis->dir()->z();
335   double norm2 = sqrt(x2*x2 + y2*y2 + z2*z2);
336
337   // Moving each object.
338   int aResultIndex = 0;
339   std::list<ResultPtr>::iterator aContext = aContextes.begin();
340   for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
341         anObjectsIt++, aContext++) {
342     std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
343     bool isPart = aContext->get() && (*aContext)->groupName() == ModelAPI_ResultPart::group();
344
345     // Setting result.
346     if (isPart) {
347       ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
348       std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
349       for (int j=0; j<aSecondNbCopies; j++) {
350         for (int i=0; i<aFirstNbCopies; i++) {
351           double dx = i*aFirstStep*x1/norm1+j*aSecondStep*x2/norm2;
352           double dy = i*aFirstStep*y1/norm1+j*aSecondStep*y2/norm2;
353           double dz = i*aFirstStep*z1/norm1+j*aSecondStep*z2/norm2;
354           aTrsf->setTranslation(dx, dy, dz);
355           ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
356           aResultPart->setTrsf(*aContext, aTrsf);
357           setResult(aResultPart, aResultIndex);
358           aResultIndex++;
359         }
360       }
361     } else {
362       std::string anError;
363       ListOfShape aListOfShape;
364       std::list<std::shared_ptr<GeomAlgoAPI_Translation> > aListOfTranslationAlgo;
365
366       for (int j=0; j<aSecondNbCopies; j++) {
367         for (int i=0; i<aFirstNbCopies; i++) {
368           double dx = i*aFirstStep*x1/norm1+j*aSecondStep*x2/norm2;
369           double dy = i*aFirstStep*y1/norm1+j*aSecondStep*y2/norm2;
370           double dz = i*aFirstStep*z1/norm1+j*aSecondStep*z2/norm2;
371           std::shared_ptr<GeomAlgoAPI_Translation> aTranslationAlgo(
372             new GeomAlgoAPI_Translation(aBaseShape, dx, dy, dz));
373
374           if (!aTranslationAlgo->check()) {
375             setError(aTranslationAlgo->getError());
376             break;
377           }
378
379           aTranslationAlgo->build();
380
381           // Checking that the algorithm worked properly.
382           if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(
383               aTranslationAlgo, getKind(), anError)) {
384             setError(anError);
385             break;
386           }
387           aListOfShape.push_back(aTranslationAlgo->shape());
388           aListOfTranslationAlgo.push_back(aTranslationAlgo);
389         }
390       }
391       std::shared_ptr<GeomAPI_Shape> aCompound =
392         GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
393       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
394       aResultBody->storeModified(aBaseShape, aCompound);
395       loadNamingDS(aListOfTranslationAlgo, aResultBody, aBaseShape);
396       setResult(aResultBody, aResultIndex);
397     }
398     aResultIndex++;
399   }
400
401   // Remove the rest results if there were produced in the previous pass.
402   removeResults(aResultIndex);
403 }
404
405 //=================================================================================================
406 void FeaturesPlugin_MultiTranslation::loadNamingDS(
407     std::list<std::shared_ptr<GeomAlgoAPI_Translation> > theListOfTranslationAlgo,
408     std::shared_ptr<ModelAPI_ResultBody> theResultBody,
409     std::shared_ptr<GeomAPI_Shape> theBaseShape)
410 {
411   for (std::list<std::shared_ptr<GeomAlgoAPI_Translation> >::const_iterator anIt =
412     theListOfTranslationAlgo.begin(); anIt != theListOfTranslationAlgo.cend(); ++anIt) {
413     // naming of faces
414     theResultBody->loadModifiedShapes(*anIt,
415                                       theBaseShape,
416                                       GeomAPI_Shape::FACE,
417                                       "Translated_Face");
418
419     // naming of edges
420     theResultBody->loadModifiedShapes(*anIt,
421                                       theBaseShape,
422                                       GeomAPI_Shape::EDGE,
423                                       "Translated_Edge");
424
425     // naming of vertex
426     theResultBody->loadModifiedShapes(*anIt,
427                                       theBaseShape,
428                                       GeomAPI_Shape::VERTEX,
429                                       "Translated_Vertex");
430   }
431 }