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