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