Salome HOME
Issue #2593: CEA 2018-2 Geometrical Naming
[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
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     return;
91   }
92   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
93     std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
94       anObjectsSelList->value(anObjectsIndex);
95     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
96     if(!anObject.get()) { // may be for not-activated parts
97       eraseResults();
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   else
129   {
130     setError(aSelectionError);
131     return;
132   }
133
134   if (!anEdge.get())
135   {
136     setError(aSelectionError);
137     return;
138   }
139
140   std::shared_ptr<GeomAPI_Ax1> anAxis (new GeomAPI_Ax1(anEdge->line()->location(),
141                                                        anEdge->line()->direction()));
142
143   // Getting step.
144   double aStep = real(FeaturesPlugin_MultiTranslation::STEP_FIRST_DIR_ID())->value();
145
146   // Getting number of copies.
147   int nbCopies =
148     integer(FeaturesPlugin_MultiTranslation::NB_COPIES_FIRST_DIR_ID())->value();
149
150   if (nbCopies <=0) {
151     std::string aFeatureError = "Multitranslation builder ";
152     aFeatureError+=":: the number of copies for the first direction is null or negative.";
153     setError(aFeatureError);
154     return;
155   }
156
157   // Moving each object.
158   int aResultIndex = 0;
159   std::list<ResultPtr>::iterator aContext = aContextes.begin();
160   for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
161         anObjectsIt++, aContext++) {
162     std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
163     bool isPart = aContext->get() && (*aContext)->groupName() == ModelAPI_ResultPart::group();
164
165     // Setting result.
166     if (isPart) {
167       ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
168       std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
169       for (int i=0; i<nbCopies; i++) {
170         aTrsf->setTranslation(anAxis, i*aStep);
171         ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
172         aResultPart->setTrsf(*aContext, aTrsf);
173         setResult(aResultPart, aResultIndex);
174         aResultIndex++;
175       }
176     } else {
177       ListOfShape aListOfShape;
178       std::list<std::shared_ptr<GeomAlgoAPI_Translation> > aListOfTranslationAlgo;
179
180       for (int i=0; i<nbCopies; i++) {
181         std::shared_ptr<GeomAlgoAPI_Translation> aTranslationAlgo(
182           new GeomAlgoAPI_Translation(aBaseShape, anAxis, i*aStep));
183
184         if (!aTranslationAlgo->check()) {
185           setError(aTranslationAlgo->getError());
186           break;
187         }
188
189         aTranslationAlgo->build();
190
191         // Checking that the algorithm worked properly.
192         if (!aTranslationAlgo->isDone()) {
193           static const std::string aFeatureError = "Error : Multitranslation algorithm failed.";
194           setError(aFeatureError);
195           break;
196         }
197         if (aTranslationAlgo->shape()->isNull()) {
198           static const std::string aShapeError = "Error : Resulting shape is null.";
199           setError(aShapeError);
200           break;
201         }
202         if (!aTranslationAlgo->isValid()) {
203           static const std::string aFeatureError = "Error : Resulting shape in not valid.";
204           setError(aFeatureError);
205           break;
206         }
207         aListOfShape.push_back(aTranslationAlgo->shape());
208         aListOfTranslationAlgo.push_back(aTranslationAlgo);
209       }
210       std::shared_ptr<GeomAPI_Shape> aCompound =
211         GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
212       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
213       aResultBody->storeModified(aBaseShape, aCompound);
214       loadNamingDS(aListOfTranslationAlgo, aResultBody, aBaseShape);
215
216       setResult(aResultBody, aResultIndex);
217     }
218     aResultIndex++;
219   }
220
221   // Remove the rest results if there were produced in the previous pass.
222   removeResults(aResultIndex);
223 }
224
225 //=================================================================================================
226 void FeaturesPlugin_MultiTranslation::performTwoDirection()
227 {
228   // Getting objects.
229   ListOfShape anObjects;
230   std::list<ResultPtr> aContextes;
231   AttributeSelectionListPtr anObjectsSelList =
232     selectionList(FeaturesPlugin_MultiTranslation::OBJECTS_LIST_ID());
233   if (anObjectsSelList->size() == 0) {
234     return;
235   }
236   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
237     std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
238       anObjectsSelList->value(anObjectsIndex);
239     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
240     if(!anObject.get()) { // may be for not-activated parts
241       eraseResults();
242       return;
243     }
244     anObjects.push_back(anObject);
245     aContextes.push_back(anObjectAttr->context());
246   }
247
248   //Getting axis.
249   static const std::string aSelectionError = "Error: The axis shape selection is bad.";
250   AttributeSelectionPtr anObjRef = selection(AXIS_FIRST_DIR_ID());
251   GeomShapePtr aShape = anObjRef->value();
252   if (!aShape.get()) {
253     if (anObjRef->context().get()) {
254       aShape = anObjRef->context()->shape();
255     }
256   }
257   if (!aShape.get()) {
258     setError(aSelectionError);
259     return;
260   }
261
262   GeomEdgePtr anEdge;
263   if (aShape->isEdge())
264   {
265     anEdge = aShape->edge();
266   }
267   else if (aShape->isCompound())
268   {
269     GeomAPI_ShapeIterator anIt(aShape);
270     anEdge = anIt.current()->edge();
271   }
272   else
273   {
274     setError(aSelectionError);
275     return;
276   }
277
278   if (!anEdge.get())
279   {
280     setError(aSelectionError);
281     return;
282   }
283
284   std::shared_ptr<GeomAPI_Ax1> aFirstAxis(new GeomAPI_Ax1(anEdge->line()->location(),
285                                                           anEdge->line()->direction()));
286
287   //Getting axis.
288   anObjRef = selection(AXIS_SECOND_DIR_ID());
289   aShape = anObjRef->value();
290   if (!aShape.get()) {
291     if (anObjRef->context().get()) {
292       aShape = anObjRef->context()->shape();
293     }
294   }
295   if (!aShape.get()) {
296     setError(aSelectionError);
297     return;
298   }
299
300   if (aShape->isEdge())
301   {
302     anEdge = aShape->edge();
303   }
304   else if (aShape->isCompound())
305   {
306     GeomAPI_ShapeIterator anIt(aShape);
307     anEdge = anIt.current()->edge();
308   }
309   else
310   {
311     setError(aSelectionError);
312     return;
313   }
314
315   if (!anEdge.get())
316   {
317     setError(aSelectionError);
318     return;
319   }
320
321   std::shared_ptr<GeomAPI_Ax1> aSecondAxis(new GeomAPI_Ax1(anEdge->line()->location(),
322                                                            anEdge->line()->direction()));
323
324   // Getting step.
325   double aFirstStep = real(FeaturesPlugin_MultiTranslation::STEP_FIRST_DIR_ID())->value();
326   double aSecondStep = real(FeaturesPlugin_MultiTranslation::STEP_SECOND_DIR_ID())->value();
327
328   // Getting number of copies.
329   int aFirstNbCopies =
330     integer(FeaturesPlugin_MultiTranslation::NB_COPIES_FIRST_DIR_ID())->value();
331   int aSecondNbCopies =
332     integer(FeaturesPlugin_MultiTranslation::NB_COPIES_SECOND_DIR_ID())->value();
333
334   if (aFirstNbCopies <=0) {
335     std::string aFeatureError = "Multitranslation builder ";
336     aFeatureError+=":: the number of copies for the first direction is null or negative.";
337     setError(aFeatureError);
338     return;
339   }
340
341   if (aSecondNbCopies <=0) {
342     std::string aFeatureError = "Multitranslation builder ";
343     aFeatureError+=":: the number of copies for the second direction is null or negative.";
344     setError(aFeatureError);
345     return;
346   }
347
348   // Coord aFirstAxis
349   double x1 = aFirstAxis->dir()->x();
350   double y1 = aFirstAxis->dir()->y();
351   double z1 = aFirstAxis->dir()->z();
352   double norm1 = sqrt(x1*x1 + y1*y1 + z1*z1);
353
354   // Coord aSecondAxis
355   double x2 = aSecondAxis->dir()->x();
356   double y2 = aSecondAxis->dir()->y();
357   double z2 = aSecondAxis->dir()->z();
358   double norm2 = sqrt(x2*x2 + y2*y2 + z2*z2);
359
360   // Moving each object.
361   int aResultIndex = 0;
362   std::list<ResultPtr>::iterator aContext = aContextes.begin();
363   for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
364         anObjectsIt++, aContext++) {
365     std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
366     bool isPart = aContext->get() && (*aContext)->groupName() == ModelAPI_ResultPart::group();
367
368     // Setting result.
369     if (isPart) {
370       ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
371       std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
372       for (int j=0; j<aSecondNbCopies; j++) {
373         for (int i=0; i<aFirstNbCopies; i++) {
374           double dx = i*aFirstStep*x1/norm1+j*aSecondStep*x2/norm2;
375           double dy = i*aFirstStep*y1/norm1+j*aSecondStep*y2/norm2;
376           double dz = i*aFirstStep*z1/norm1+j*aSecondStep*z2/norm2;
377           aTrsf->setTranslation(dx, dy, dz);
378           ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
379           aResultPart->setTrsf(*aContext, aTrsf);
380           setResult(aResultPart, aResultIndex);
381           aResultIndex++;
382         }
383       }
384     } else {
385       ListOfShape aListOfShape;
386       std::list<std::shared_ptr<GeomAlgoAPI_Translation> > aListOfTranslationAlgo;
387
388       for (int j=0; j<aSecondNbCopies; j++) {
389         for (int i=0; i<aFirstNbCopies; i++) {
390           double dx = i*aFirstStep*x1/norm1+j*aSecondStep*x2/norm2;
391           double dy = i*aFirstStep*y1/norm1+j*aSecondStep*y2/norm2;
392           double dz = i*aFirstStep*z1/norm1+j*aSecondStep*z2/norm2;
393           std::shared_ptr<GeomAlgoAPI_Translation> aTranslationAlgo(
394             new GeomAlgoAPI_Translation(aBaseShape, dx, dy, dz));
395
396           if (!aTranslationAlgo->check()) {
397             setError(aTranslationAlgo->getError());
398             break;
399           }
400
401           aTranslationAlgo->build();
402
403           // Checking that the algorithm worked properly.
404           if (!aTranslationAlgo->isDone()) {
405             static const std::string aFeatureError = "Error : Multitranslation algorithm failed.";
406             setError(aFeatureError);
407             break;
408           }
409           if (aTranslationAlgo->shape()->isNull()) {
410             static const std::string aShapeError = "Error : Resulting shape is null.";
411             setError(aShapeError);
412             break;
413           }
414           if (!aTranslationAlgo->isValid()) {
415             static const std::string aFeatureError = "Error : Resulting shape in not valid.";
416             setError(aFeatureError);
417            break;
418           }
419           aListOfShape.push_back(aTranslationAlgo->shape());
420           aListOfTranslationAlgo.push_back(aTranslationAlgo);
421         }
422       }
423       std::shared_ptr<GeomAPI_Shape> aCompound =
424         GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
425       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
426       aResultBody->storeModified(aBaseShape, aCompound);
427       loadNamingDS(aListOfTranslationAlgo, aResultBody, aBaseShape);
428       setResult(aResultBody, aResultIndex);
429     }
430     aResultIndex++;
431   }
432
433   // Remove the rest results if there were produced in the previous pass.
434   removeResults(aResultIndex);
435 }
436
437 //=================================================================================================
438 void FeaturesPlugin_MultiTranslation::loadNamingDS(
439     std::list<std::shared_ptr<GeomAlgoAPI_Translation> > theListOfTranslationAlgo,
440     std::shared_ptr<ModelAPI_ResultBody> theResultBody,
441     std::shared_ptr<GeomAPI_Shape> theBaseShape)
442 {
443   int aTag = 1;
444   int anIndex = 1;
445   std::string aTranslatedName;
446
447   for (std::list<std::shared_ptr<GeomAlgoAPI_Translation> >::const_iterator anIt =
448     theListOfTranslationAlgo.begin(); anIt != theListOfTranslationAlgo.cend(); ++anIt) {
449     std::shared_ptr<GeomAPI_DataMapOfShapeShape> aSubShapes = (*anIt)->mapOfSubShapes();
450
451     // naming of faces
452     aTranslatedName = "Translated_Face_" + std::to_string((long long) anIndex);
453     theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::FACE,
454                                                aTag++, aTranslatedName, *aSubShapes.get(),
455                                                false, true);
456
457     // naming of edges
458     aTranslatedName = "Translated_Edge_" + std::to_string((long long) anIndex);
459     theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::EDGE,
460                                                aTag++, aTranslatedName, *aSubShapes.get(),
461                                                false, true);
462
463     // naming of vertex
464     aTranslatedName = "Translated_Vertex_" + std::to_string((long long) anIndex);
465     theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::VERTEX,
466                                                aTag++, aTranslatedName, *aSubShapes.get(),
467                                                false, true);
468
469     ++anIndex;
470   }
471 }