]> SALOME platform Git repositories - modules/shaper.git/blob - src/ConstructionPlugin/ConstructionPlugin_Axis.cpp
Salome HOME
Fix for the Box With Fillet case from the "CEA Parametric" document.
[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   std::shared_ptr<GeomAPI_Pln> aPln = aFace->getPlane();
272
273   // Get point.
274   AttributeSelectionPtr aPointSelection = selection(POINT());
275   GeomShapePtr aPointShape = aPointSelection->value();
276   if(!aPointShape.get()) {
277     aPointShape = aPointSelection->context()->shape();
278   }
279   std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(aPointShape));
280   std::shared_ptr<GeomAPI_Pnt> aPnt = aVertex->point();
281
282   std::shared_ptr<GeomAPI_Pnt> aProjPnt = aPln->project(aPnt);
283
284   if(aProjPnt->isEqual(aPnt)) {
285     aPnt->translate(aPln->direction(), defaultAxisSize);
286   }
287
288   std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aPnt, aProjPnt);
289
290   ResultConstructionPtr aConstr = document()->createConstruction(data());
291   aConstr->setInfinite(true);
292   aConstr->setShape(anEdge);
293   setResult(aConstr);
294 }
295
296 void ConstructionPlugin_Axis::createAxisByTwoPlanes()
297 {
298   // Get face 1.
299   AttributeSelectionPtr aFaceSelection1 = selection(PLANE1());
300   GeomShapePtr aFaceShape1 = aFaceSelection1->value();
301   if(!aFaceShape1.get()) {
302     aFaceShape1 = aFaceSelection1->context()->shape();
303   }
304   std::shared_ptr<GeomAPI_Face> aFace1;
305   if (aFaceShape1->isFace()) {
306     aFace1 = aFaceShape1->face();
307   }
308   else if (aFaceShape1->isCompound()) {
309     GeomAPI_ShapeIterator anIt(aFaceShape1);
310     aFace1 = anIt.current()->face();
311   }
312   std::shared_ptr<GeomAPI_Pln> aPln1 = aFace1->getPlane();
313
314   std::string useOffset1 = string(USE_OFFSET1())->value();
315   if(!useOffset1.empty()) {
316     double anOffset1 = real(OFFSET1())->value();
317     bool reverseOffset1 = boolean(REVERSE_OFFSET1())->value();
318     if(reverseOffset1) {
319       anOffset1 = -anOffset1;
320     }
321     aPln1->translate(aPln1->direction(), anOffset1);
322   }
323
324   // Get face 2.
325   AttributeSelectionPtr aFaceSelection2 = selection(PLANE2());
326   GeomShapePtr aFaceShape2 = aFaceSelection2->value();
327   if(!aFaceShape2.get()) {
328     aFaceShape2 = aFaceSelection2->context()->shape();
329   }
330   std::shared_ptr<GeomAPI_Face> aFace2;
331   if (aFaceShape2->isFace()) {
332     aFace2 = aFaceShape2->face();
333   }
334   else if (aFaceShape2->isCompound()) {
335     GeomAPI_ShapeIterator anIt(aFaceShape2);
336     aFace2 = anIt.current()->face();
337   }
338   std::shared_ptr<GeomAPI_Pln> aPln2 = aFace2->getPlane();
339
340   std::string useOffset2 = string(USE_OFFSET2())->value();
341   if(!useOffset2.empty()) {
342     double anOffset2 = real(OFFSET2())->value();
343     bool reverseOffset2 = boolean(REVERSE_OFFSET2())->value();
344     if(reverseOffset2) {
345       anOffset2 = -anOffset2;
346     }
347     aPln2->translate(aPln2->direction(), anOffset2);
348   }
349
350   std::shared_ptr<GeomAPI_Lin> aLin = aPln1->intersect(aPln2);
351   std::shared_ptr<GeomAPI_Pnt> aPnt1 = aLin->location();
352   std::shared_ptr<GeomAPI_Pnt> aPnt2 = aLin->location();
353   aPnt2->translate(aLin->direction(), defaultAxisSize);
354
355   std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aPnt1, aPnt2);
356
357   ResultConstructionPtr aConstr = document()->createConstruction(data());
358   aConstr->setInfinite(true);
359   aConstr->setShape(anEdge);
360   setResult(aConstr);
361 }
362
363 void ConstructionPlugin_Axis::execute()
364 {
365   AttributeStringPtr aMethodTypeAttr = string(ConstructionPlugin_Axis::METHOD());
366   std::string aMethodType = aMethodTypeAttr->value();
367   if (aMethodType == CREATION_METHOD_BY_TWO_POINTS()) {
368     createAxisByTwoPoints();
369   } else if (aMethodType == CREATION_METHOD_BY_CYLINDRICAL_FACE()) {
370     createAxisByCylindricalFace();
371   } else if (aMethodType == CREATION_METHOD_BY_POINT_AND_DIRECTION()) {
372     createAxisByPointAndDirection();
373   } else if (aMethodType == CREATION_METHOD_BY_DIMENSIONS()) {
374     createAxisByDimensions();
375   } else if(aMethodType == CREATION_METHOD_BY_LINE()) {
376     createAxisByLine();
377   } else if(aMethodType == CREATION_METHOD_BY_PLANE_AND_POINT()) {
378     createAxisByPlaneAndPoint();
379   } else if(aMethodType == CREATION_METHOD_BY_TWO_PLANES()) {
380     createAxisByTwoPlanes();
381   }
382 }
383
384 bool ConstructionPlugin_Axis::customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
385   std::shared_ptr<GeomAPI_ICustomPrs> theDefaultPrs)
386 {
387   bool isCustomized = theDefaultPrs.get() != NULL &&
388                       theDefaultPrs->customisePresentation(theResult, thePrs, theDefaultPrs);
389
390   isCustomized = thePrs->setLineStyle(3) || isCustomized;
391   isCustomized = thePrs->setWidth(2) || isCustomized;
392
393   return isCustomized;
394 }