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