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