Salome HOME
Merge commit 'refs/tags/V9_2_0^{}'
[modules/shaper.git] / src / ConstructionPlugin / ConstructionPlugin_Axis.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 "ConstructionPlugin_Axis.h"
22
23 #include <Config_PropManager.h>
24
25 #include <ModelAPI_AttributeBoolean.h>
26 #include <ModelAPI_AttributeSelection.h>
27 #include <ModelAPI_ResultConstruction.h>
28 #include <ModelAPI_AttributeString.h>
29 #include <ModelAPI_AttributeDouble.h>
30 #include <ModelAPI_Session.h>
31 #include <ModelAPI_Validator.h>
32
33 #include <GeomAPI_Edge.h>
34 #include <GeomAPI_Lin.h>
35 #include <GeomAPI_Pln.h>
36 #include <GeomAPI_ShapeIterator.h>
37 #include <GeomAPI_Vertex.h>
38 #include <GeomAPI_XYZ.h>
39 #include <GeomAlgoAPI_EdgeBuilder.h>
40 #include <GeomAlgoAPI_PointBuilder.h>
41
42 #include <math.h>
43
44 #ifdef _DEBUG
45 #include <iostream>
46 #endif
47
48 static const double defaultAxisSize = 100;
49
50 ConstructionPlugin_Axis::ConstructionPlugin_Axis()
51 {
52 }
53
54 void ConstructionPlugin_Axis::initAttributes()
55 {
56   data()->addAttribute(ConstructionPlugin_Axis::METHOD(),
57                        ModelAPI_AttributeString::typeId());
58
59   // Attributes needed to build the axis using the "two points" method
60   data()->addAttribute(ConstructionPlugin_Axis::POINT_FIRST(),
61                        ModelAPI_AttributeSelection::typeId());
62   data()->addAttribute(ConstructionPlugin_Axis::POINT_SECOND(),
63                        ModelAPI_AttributeSelection::typeId());
64
65   // Attributes needed to build the axis using the "cylindrical face" method"
66   data()->addAttribute(ConstructionPlugin_Axis::CYLINDRICAL_FACE(),
67                        ModelAPI_AttributeSelection::typeId());
68   data()->addAttribute(ConstructionPlugin_Axis::X_DIRECTION(),
69                        ModelAPI_AttributeDouble::typeId());
70   data()->addAttribute(ConstructionPlugin_Axis::Y_DIRECTION(),
71                        ModelAPI_AttributeDouble::typeId());
72   data()->addAttribute(ConstructionPlugin_Axis::Z_DIRECTION(),
73                        ModelAPI_AttributeDouble::typeId());
74   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(),
75       ConstructionPlugin_Axis::X_DIRECTION());
76   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(),
77       ConstructionPlugin_Axis::Y_DIRECTION());
78   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(),
79       ConstructionPlugin_Axis::Z_DIRECTION());
80
81   //Attributes needed to build the axis using the "three dimensions" method
82   data()->addAttribute(ConstructionPlugin_Axis::DX(),
83                        ModelAPI_AttributeDouble::typeId());
84   data()->addAttribute(ConstructionPlugin_Axis::DY(),
85                        ModelAPI_AttributeDouble::typeId());
86   data()->addAttribute(ConstructionPlugin_Axis::DZ(),
87                        ModelAPI_AttributeDouble::typeId());
88
89   /// Attributes for axis by line.
90   data()->addAttribute(LINE(), ModelAPI_AttributeSelection::typeId());
91
92   /// Attributes for axis by plane and point.
93   data()->addAttribute(PLANE(), ModelAPI_AttributeSelection::typeId());
94   data()->addAttribute(POINT(), ModelAPI_AttributeSelection::typeId());
95
96   /// Attributes for axis by two planes.
97   data()->addAttribute(PLANE1(), ModelAPI_AttributeSelection::typeId());
98   data()->addAttribute(USE_OFFSET1(), ModelAPI_AttributeString::typeId());
99   data()->addAttribute(OFFSET1(), ModelAPI_AttributeDouble::typeId());
100   data()->addAttribute(REVERSE_OFFSET1(), ModelAPI_AttributeBoolean::typeId());
101   data()->addAttribute(PLANE2(), ModelAPI_AttributeSelection::typeId());
102   data()->addAttribute(USE_OFFSET2(), ModelAPI_AttributeString::typeId());
103   data()->addAttribute(OFFSET2(), ModelAPI_AttributeDouble::typeId());
104   data()->addAttribute(REVERSE_OFFSET2(), ModelAPI_AttributeBoolean::typeId());
105 }
106
107 void ConstructionPlugin_Axis::createAxisByTwoPoints()
108 {
109   AttributeSelectionPtr aRef1 = data()->selection(ConstructionPlugin_Axis::POINT_FIRST());
110   AttributeSelectionPtr aRef2 = data()->selection(ConstructionPlugin_Axis::POINT_SECOND());
111   if ((aRef1.get() != NULL) && (aRef2.get() != NULL)) {
112     GeomShapePtr aShape1 = aRef1->value();
113     if (!aShape1.get())
114       aShape1 = aRef1->context()->shape();
115     GeomShapePtr aShape2 = aRef2->value();
116     if (!aShape2.get())
117       aShape2 = aRef2->context()->shape();
118     if (aShape1->isVertex() && aShape2->isVertex() && (!aShape1->isEqual(aShape2))) {
119       std::shared_ptr<GeomAPI_Pnt> aStart = GeomAlgoAPI_PointBuilder::point(aShape1);
120       std::shared_ptr<GeomAPI_Pnt> anEnd = GeomAlgoAPI_PointBuilder::point(aShape2);
121       if (aStart->distance(anEnd) > ConstructionPlugin_Axis::MINIMAL_LENGTH()) {
122         std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, anEnd);
123
124         ResultConstructionPtr aConstr = document()->createConstruction(data());
125         aConstr->setInfinite(true);
126         aConstr->setShape(anEdge);
127         setResult(aConstr);
128       }
129     }
130   }
131 }
132
133
134 void ConstructionPlugin_Axis::createAxisByPointAndDirection()
135 {
136   AttributeSelectionPtr aRef1 = data()->selection(ConstructionPlugin_Axis::POINT_FIRST());
137   AttributeDoublePtr aXAttr = data()->real(ConstructionPlugin_Axis::X_DIRECTION());
138   AttributeDoublePtr aYAttr = data()->real(ConstructionPlugin_Axis::Y_DIRECTION());
139   AttributeDoublePtr aZAttr = data()->real(ConstructionPlugin_Axis::Z_DIRECTION());
140   if ((aRef1.get() != NULL) && (aXAttr.get() != NULL) &&
141       (aYAttr.get() != NULL) && (aZAttr.get() != NULL)) {
142     GeomShapePtr aShape1 = aRef1->value();
143     if (!aShape1.get())
144       aShape1 = aRef1->context()->shape();
145
146     std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(aXAttr->value(),
147                                                                aYAttr->value(),
148                                                                aZAttr->value()));
149     if (aShape1->isVertex() && (!aShape1->isEqual(aVertex))) {
150       std::shared_ptr<GeomAPI_Pnt> aStart = GeomAlgoAPI_PointBuilder::point(aShape1);
151       std::shared_ptr<GeomAPI_Pnt> anEnd = aVertex->point();
152       if (aStart->distance(anEnd) > ConstructionPlugin_Axis::MINIMAL_LENGTH()) {
153         std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, anEnd);
154
155         ResultConstructionPtr aConstr = document()->createConstruction(data());
156         aConstr->setInfinite(true);
157         aConstr->setShape(anEdge);
158         setResult(aConstr);
159       }
160     }
161   }
162 }
163
164
165 void ConstructionPlugin_Axis::createAxisByCylindricalFace()
166 {
167   std::shared_ptr<GeomAPI_Shape> aSelection = data()->selection(CYLINDRICAL_FACE())->value();
168     // update arguments due to the selection value
169
170   if (!aSelection.get() || aSelection->isNull()) {
171     return;
172   }
173
174   if (aSelection->isCompound()) {
175     GeomAPI_ShapeIterator anIt(aSelection);
176     aSelection = anIt.current();
177   }
178
179   if (aSelection->isFace()) {
180     std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::cylinderAxis(aSelection);
181
182     ResultConstructionPtr aConstr = document()->createConstruction(data());
183     aConstr->setInfinite(true);
184     aConstr->setShape(anEdge);
185     setResult(aConstr);
186   }
187 }
188
189 void ConstructionPlugin_Axis::createAxisByDimensions()
190 {
191   // Start by getting these dimensions
192   double aDX = data()->real(DX())->value();
193   double aDY = data()->real(DY())->value();
194   double aDZ = data()->real(DZ())->value();
195
196   if (fabs(aDX) < MINIMAL_LENGTH()  && fabs(aDY) < MINIMAL_LENGTH() &&
197       fabs(aDZ) < MINIMAL_LENGTH()) {
198     setError("Axis builder with dimensions  :: all dimensions are null", false);
199     return ;
200   }
201
202   // Make the axis, build the ResultConstructionPtr and write it
203   std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aDX, aDY, aDZ);
204   ResultConstructionPtr aConstr = document()->createConstruction(data());
205   aConstr->setInfinite(true);
206   aConstr->setShape(anEdge);
207   setResult(aConstr);
208 }
209
210 void ConstructionPlugin_Axis::createAxisByLine()
211 {
212   // Get edge.
213   AttributeSelectionPtr anEdgeSelection = selection(LINE());
214   GeomShapePtr aLineShape = anEdgeSelection->value();
215   if(!aLineShape.get()) {
216     aLineShape = anEdgeSelection->context()->shape();
217   }
218   GeomEdgePtr anEdge;
219   if (aLineShape->isEdge()) {
220     anEdge = aLineShape->edge();
221   }
222   else if (aLineShape->isCompound()) {
223     // create an edge which covers all edges from compounds (they are on the same line)
224     GeomPointPtr aFirst, aLast;
225     GeomXYZPtr aLineVec;
226     for(GeomAPI_ShapeIterator anIt(aLineShape); anIt.more(); anIt.next()) {
227       GeomEdgePtr aSub = anIt.current()->edge();
228       if (aSub.get() && aSub->isLine()) {
229         if (!aLineVec.get()) {
230           aFirst = aSub->firstPoint();
231           aLast = aSub->lastPoint();
232         } else { // set aFirst and aLast by extreme points
233           GeomXYZPtr aFirstVec = aSub->firstPoint()->xyz()->decreased(aFirst->xyz());
234           bool aSameDirection =
235             aSub->lastPoint()->xyz()->decreased(aSub->firstPoint()->xyz())->dot(aLineVec) > 0;
236           if (aLineVec->dot(aFirstVec) < -1.e-7) { // first point is changed
237             aFirst = aSameDirection ? aSub->firstPoint() : aSub->lastPoint();
238           } else { // last point is changed
239             aLast = aSameDirection ? aSub->lastPoint() : aSub->firstPoint();
240           }
241         }
242         aLineVec = aLast->xyz()->decreased(aFirst->xyz());
243       }
244     }
245     if (aLineVec.get())
246       anEdge = GeomAlgoAPI_EdgeBuilder::line(aFirst, aLast);
247   }
248
249   ResultConstructionPtr aConstr = document()->createConstruction(data());
250   aConstr->setInfinite(true);
251   aConstr->setShape(anEdge);
252   setResult(aConstr);
253 }
254
255 void ConstructionPlugin_Axis::createAxisByPlaneAndPoint()
256 {
257   // Get face.
258   AttributeSelectionPtr aFaceSelection = selection(PLANE());
259   GeomShapePtr aFaceShape = aFaceSelection->value();
260   if(!aFaceShape.get()) {
261     aFaceShape = aFaceSelection->context()->shape();
262   }
263   GeomFacePtr aFace;
264   if (aFaceShape->isFace()) {
265     aFace = aFaceShape->face();
266   }
267   else if (aFaceShape->isCompound()) {
268     GeomAPI_ShapeIterator anIt(aFaceShape);
269     aFace = anIt.current()->face();
270   }
271   if (!aFace)
272     return;
273   std::shared_ptr<GeomAPI_Pln> aPln = aFace->getPlane();
274
275   // Get point.
276   AttributeSelectionPtr aPointSelection = selection(POINT());
277   GeomShapePtr aPointShape = aPointSelection->value();
278   if(!aPointShape.get()) {
279     aPointShape = aPointSelection->context()->shape();
280   }
281   std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(aPointShape));
282   std::shared_ptr<GeomAPI_Pnt> aPnt = aVertex->point();
283
284   std::shared_ptr<GeomAPI_Pnt> aProjPnt = aPln->project(aPnt);
285
286   if(aProjPnt->isEqual(aPnt)) {
287     aPnt->translate(aPln->direction(), defaultAxisSize);
288   }
289
290   std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aPnt, aProjPnt);
291
292   ResultConstructionPtr aConstr = document()->createConstruction(data());
293   aConstr->setInfinite(true);
294   aConstr->setShape(anEdge);
295   setResult(aConstr);
296 }
297
298 void ConstructionPlugin_Axis::createAxisByTwoPlanes()
299 {
300   // Get face 1.
301   AttributeSelectionPtr aFaceSelection1 = selection(PLANE1());
302   GeomShapePtr aFaceShape1 = aFaceSelection1->value();
303   if(!aFaceShape1.get()) {
304     aFaceShape1 = aFaceSelection1->context()->shape();
305   }
306   std::shared_ptr<GeomAPI_Face> aFace1;
307   if (aFaceShape1->isFace()) {
308     aFace1 = aFaceShape1->face();
309   }
310   else if (aFaceShape1->isCompound()) {
311     GeomAPI_ShapeIterator anIt(aFaceShape1);
312     aFace1 = anIt.current()->face();
313   }
314   if (!aFace1)
315     return;
316   std::shared_ptr<GeomAPI_Pln> aPln1 = aFace1->getPlane();
317
318   std::string useOffset1 = string(USE_OFFSET1())->value();
319   if(!useOffset1.empty()) {
320     double anOffset1 = real(OFFSET1())->value();
321     bool reverseOffset1 = boolean(REVERSE_OFFSET1())->value();
322     if(reverseOffset1) {
323       anOffset1 = -anOffset1;
324     }
325     aPln1->translate(aPln1->direction(), anOffset1);
326   }
327
328   // Get face 2.
329   AttributeSelectionPtr aFaceSelection2 = selection(PLANE2());
330   GeomShapePtr aFaceShape2 = aFaceSelection2->value();
331   if(!aFaceShape2.get()) {
332     aFaceShape2 = aFaceSelection2->context()->shape();
333   }
334   std::shared_ptr<GeomAPI_Face> aFace2;
335   if (aFaceShape2->isFace()) {
336     aFace2 = aFaceShape2->face();
337   }
338   else if (aFaceShape2->isCompound()) {
339     GeomAPI_ShapeIterator anIt(aFaceShape2);
340     aFace2 = anIt.current()->face();
341   }
342   if (!aFace2)
343     return;
344   std::shared_ptr<GeomAPI_Pln> aPln2 = aFace2->getPlane();
345
346   std::string useOffset2 = string(USE_OFFSET2())->value();
347   if(!useOffset2.empty()) {
348     double anOffset2 = real(OFFSET2())->value();
349     bool reverseOffset2 = boolean(REVERSE_OFFSET2())->value();
350     if(reverseOffset2) {
351       anOffset2 = -anOffset2;
352     }
353     aPln2->translate(aPln2->direction(), anOffset2);
354   }
355
356   std::shared_ptr<GeomAPI_Lin> aLin = aPln1->intersect(aPln2);
357   std::shared_ptr<GeomAPI_Pnt> aPnt1 = aLin->location();
358   std::shared_ptr<GeomAPI_Pnt> aPnt2 = aLin->location();
359   aPnt2->translate(aLin->direction(), defaultAxisSize);
360
361   std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aPnt1, aPnt2);
362
363   ResultConstructionPtr aConstr = document()->createConstruction(data());
364   aConstr->setInfinite(true);
365   aConstr->setShape(anEdge);
366   setResult(aConstr);
367 }
368
369 void ConstructionPlugin_Axis::execute()
370 {
371   AttributeStringPtr aMethodTypeAttr = string(ConstructionPlugin_Axis::METHOD());
372   std::string aMethodType = aMethodTypeAttr->value();
373   if (aMethodType == CREATION_METHOD_BY_TWO_POINTS()) {
374     createAxisByTwoPoints();
375   } else if (aMethodType == CREATION_METHOD_BY_CYLINDRICAL_FACE()) {
376     createAxisByCylindricalFace();
377   } else if (aMethodType == CREATION_METHOD_BY_POINT_AND_DIRECTION()) {
378     createAxisByPointAndDirection();
379   } else if (aMethodType == CREATION_METHOD_BY_DIMENSIONS()) {
380     createAxisByDimensions();
381   } else if(aMethodType == CREATION_METHOD_BY_LINE()) {
382     createAxisByLine();
383   } else if(aMethodType == CREATION_METHOD_BY_PLANE_AND_POINT()) {
384     createAxisByPlaneAndPoint();
385   } else if(aMethodType == CREATION_METHOD_BY_TWO_PLANES()) {
386     createAxisByTwoPlanes();
387   }
388 }
389
390 bool ConstructionPlugin_Axis::customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
391   std::shared_ptr<GeomAPI_ICustomPrs> theDefaultPrs)
392 {
393   bool isCustomized = theDefaultPrs.get() != NULL &&
394                       theDefaultPrs->customisePresentation(theResult, thePrs, theDefaultPrs);
395
396   isCustomized = thePrs->setLineStyle(3) || isCustomized;
397   isCustomized = thePrs->setWidth(2) || isCustomized;
398
399   return isCustomized;
400 }