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