1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include "ConstructionPlugin_Axis.h"
23 #include <Config_PropManager.h>
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>
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>
48 static const double defaultAxisSize = 100;
50 ConstructionPlugin_Axis::ConstructionPlugin_Axis()
54 void ConstructionPlugin_Axis::initAttributes()
56 data()->addAttribute(ConstructionPlugin_Axis::METHOD(),
57 ModelAPI_AttributeString::typeId());
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());
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());
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());
89 /// Attributes for axis by line.
90 data()->addAttribute(LINE(), ModelAPI_AttributeSelection::typeId());
92 /// Attributes for axis by plane and point.
93 data()->addAttribute(PLANE(), ModelAPI_AttributeSelection::typeId());
94 data()->addAttribute(POINT(), ModelAPI_AttributeSelection::typeId());
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());
107 void ConstructionPlugin_Axis::createAxisByTwoPoints()
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();
114 aShape1 = aRef1->context()->shape();
115 GeomShapePtr aShape2 = aRef2->value();
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);
124 ResultConstructionPtr aConstr = document()->createConstruction(data());
125 aConstr->setInfinite(true);
126 aConstr->setShape(anEdge);
134 void ConstructionPlugin_Axis::createAxisByPointAndDirection()
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();
144 aShape1 = aRef1->context()->shape();
146 std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(aXAttr->value(),
149 if (aShape1->isVertex() &&
150 (fabs(aXAttr->value()) > MINIMAL_LENGTH() ||
151 fabs(aYAttr->value()) > MINIMAL_LENGTH() ||
152 fabs(aZAttr->value()) > MINIMAL_LENGTH())) {
153 std::shared_ptr<GeomAPI_Pnt> aStart = GeomAlgoAPI_PointBuilder::point(aShape1);
154 std::shared_ptr<GeomAPI_Pnt> anEnd(new GeomAPI_Pnt(aStart->x() + aXAttr->value(),
155 aStart->y() + aYAttr->value(),
156 aStart->z() + aZAttr->value()));
158 std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, anEnd);
160 ResultConstructionPtr aConstr = document()->createConstruction(data());
161 aConstr->setInfinite(true);
162 aConstr->setShape(anEdge);
169 void ConstructionPlugin_Axis::createAxisByCylindricalFace()
171 std::shared_ptr<GeomAPI_Shape> aSelection = data()->selection(CYLINDRICAL_FACE())->value();
172 // update arguments due to the selection value
174 if (!aSelection.get() || aSelection->isNull()) {
178 if (aSelection->isCompound()) {
179 GeomAPI_ShapeIterator anIt(aSelection);
180 aSelection = anIt.current();
183 if (aSelection->isFace()) {
184 std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::cylinderAxis(aSelection);
186 ResultConstructionPtr aConstr = document()->createConstruction(data());
187 aConstr->setInfinite(true);
188 aConstr->setShape(anEdge);
193 void ConstructionPlugin_Axis::createAxisByDimensions()
195 // Start by getting these dimensions
196 double aDX = data()->real(DX())->value();
197 double aDY = data()->real(DY())->value();
198 double aDZ = data()->real(DZ())->value();
200 if (fabs(aDX) < MINIMAL_LENGTH() && fabs(aDY) < MINIMAL_LENGTH() &&
201 fabs(aDZ) < MINIMAL_LENGTH()) {
202 setError("Axis builder with dimensions :: all dimensions are null", false);
206 // Make the axis, build the ResultConstructionPtr and write it
207 std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aDX, aDY, aDZ);
208 ResultConstructionPtr aConstr = document()->createConstruction(data());
209 aConstr->setInfinite(true);
210 aConstr->setShape(anEdge);
214 void ConstructionPlugin_Axis::createAxisByLine()
217 AttributeSelectionPtr anEdgeSelection = selection(LINE());
218 GeomShapePtr aLineShape = anEdgeSelection->value();
219 if(!aLineShape.get()) {
220 aLineShape = anEdgeSelection->context()->shape();
223 if (aLineShape->isEdge()) {
224 anEdge = aLineShape->edge();
226 else if (aLineShape->isCompound()) {
227 // create an edge which covers all edges from compounds (they are on the same line)
228 GeomPointPtr aFirst, aLast;
230 for(GeomAPI_ShapeIterator anIt(aLineShape); anIt.more(); anIt.next()) {
231 GeomEdgePtr aSub = anIt.current()->edge();
232 if (aSub.get() && aSub->isLine()) {
233 if (!aLineVec.get()) {
234 aFirst = aSub->firstPoint();
235 aLast = aSub->lastPoint();
236 } else { // set aFirst and aLast by extreme points
237 GeomXYZPtr aFirstVec = aSub->firstPoint()->xyz()->decreased(aFirst->xyz());
238 bool aSameDirection =
239 aSub->lastPoint()->xyz()->decreased(aSub->firstPoint()->xyz())->dot(aLineVec) > 0;
240 if (aLineVec->dot(aFirstVec) < -1.e-7) { // first point is changed
241 aFirst = aSameDirection ? aSub->firstPoint() : aSub->lastPoint();
242 } else { // last point is changed
243 aLast = aSameDirection ? aSub->lastPoint() : aSub->firstPoint();
246 aLineVec = aLast->xyz()->decreased(aFirst->xyz());
250 anEdge = GeomAlgoAPI_EdgeBuilder::line(aFirst, aLast);
253 ResultConstructionPtr aConstr = document()->createConstruction(data());
254 aConstr->setInfinite(true);
255 aConstr->setShape(anEdge);
259 void ConstructionPlugin_Axis::createAxisByPlaneAndPoint()
262 AttributeSelectionPtr aFaceSelection = selection(PLANE());
263 GeomShapePtr aFaceShape = aFaceSelection->value();
264 if(!aFaceShape.get()) {
265 aFaceShape = aFaceSelection->context()->shape();
268 if (aFaceShape->isFace()) {
269 aFace = aFaceShape->face();
271 else if (aFaceShape->isCompound()) {
272 GeomAPI_ShapeIterator anIt(aFaceShape);
273 aFace = anIt.current()->face();
277 std::shared_ptr<GeomAPI_Pln> aPln = aFace->getPlane();
280 AttributeSelectionPtr aPointSelection = selection(POINT());
281 GeomShapePtr aPointShape = aPointSelection->value();
282 if(!aPointShape.get()) {
283 aPointShape = aPointSelection->context()->shape();
285 std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(aPointShape));
286 std::shared_ptr<GeomAPI_Pnt> aPnt = aVertex->point();
288 std::shared_ptr<GeomAPI_Pnt> aProjPnt = aPln->project(aPnt);
290 if(aProjPnt->isEqual(aPnt)) {
291 aPnt->translate(aPln->direction(), defaultAxisSize);
294 std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aPnt, aProjPnt);
296 ResultConstructionPtr aConstr = document()->createConstruction(data());
297 aConstr->setInfinite(true);
298 aConstr->setShape(anEdge);
302 void ConstructionPlugin_Axis::createAxisByTwoPlanes()
305 AttributeSelectionPtr aFaceSelection1 = selection(PLANE1());
306 GeomShapePtr aFaceShape1 = aFaceSelection1->value();
307 if(!aFaceShape1.get()) {
308 aFaceShape1 = aFaceSelection1->context()->shape();
310 std::shared_ptr<GeomAPI_Face> aFace1;
311 if (aFaceShape1->isFace()) {
312 aFace1 = aFaceShape1->face();
314 else if (aFaceShape1->isCompound()) {
315 GeomAPI_ShapeIterator anIt(aFaceShape1);
316 aFace1 = anIt.current()->face();
320 std::shared_ptr<GeomAPI_Pln> aPln1 = aFace1->getPlane();
322 std::string useOffset1 = string(USE_OFFSET1())->value();
323 if(!useOffset1.empty()) {
324 double anOffset1 = real(OFFSET1())->value();
325 bool reverseOffset1 = boolean(REVERSE_OFFSET1())->value();
327 anOffset1 = -anOffset1;
329 aPln1->translate(aPln1->direction(), anOffset1);
333 AttributeSelectionPtr aFaceSelection2 = selection(PLANE2());
334 GeomShapePtr aFaceShape2 = aFaceSelection2->value();
335 if(!aFaceShape2.get()) {
336 aFaceShape2 = aFaceSelection2->context()->shape();
338 std::shared_ptr<GeomAPI_Face> aFace2;
339 if (aFaceShape2->isFace()) {
340 aFace2 = aFaceShape2->face();
342 else if (aFaceShape2->isCompound()) {
343 GeomAPI_ShapeIterator anIt(aFaceShape2);
344 aFace2 = anIt.current()->face();
348 std::shared_ptr<GeomAPI_Pln> aPln2 = aFace2->getPlane();
350 std::string useOffset2 = string(USE_OFFSET2())->value();
351 if(!useOffset2.empty()) {
352 double anOffset2 = real(OFFSET2())->value();
353 bool reverseOffset2 = boolean(REVERSE_OFFSET2())->value();
355 anOffset2 = -anOffset2;
357 aPln2->translate(aPln2->direction(), anOffset2);
360 std::shared_ptr<GeomAPI_Lin> aLin = aPln1->intersect(aPln2);
361 std::shared_ptr<GeomAPI_Pnt> aPnt1 = aLin->location();
362 std::shared_ptr<GeomAPI_Pnt> aPnt2 = aLin->location();
363 aPnt2->translate(aLin->direction(), defaultAxisSize);
365 std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aPnt1, aPnt2);
367 ResultConstructionPtr aConstr = document()->createConstruction(data());
368 aConstr->setInfinite(true);
369 aConstr->setShape(anEdge);
373 void ConstructionPlugin_Axis::execute()
375 AttributeStringPtr aMethodTypeAttr = string(ConstructionPlugin_Axis::METHOD());
376 std::string aMethodType = aMethodTypeAttr->value();
377 if (aMethodType == CREATION_METHOD_BY_TWO_POINTS()) {
378 createAxisByTwoPoints();
379 } else if (aMethodType == CREATION_METHOD_BY_CYLINDRICAL_FACE()) {
380 createAxisByCylindricalFace();
381 } else if (aMethodType == CREATION_METHOD_BY_POINT_AND_DIRECTION()) {
382 createAxisByPointAndDirection();
383 } else if (aMethodType == CREATION_METHOD_BY_DIMENSIONS()) {
384 createAxisByDimensions();
385 } else if(aMethodType == CREATION_METHOD_BY_LINE()) {
387 } else if(aMethodType == CREATION_METHOD_BY_PLANE_AND_POINT()) {
388 createAxisByPlaneAndPoint();
389 } else if(aMethodType == CREATION_METHOD_BY_TWO_PLANES()) {
390 createAxisByTwoPlanes();
394 bool ConstructionPlugin_Axis::customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
395 std::shared_ptr<GeomAPI_ICustomPrs> theDefaultPrs)
397 bool isCustomized = theDefaultPrs.get() != NULL &&
398 theDefaultPrs->customisePresentation(theResult, thePrs, theDefaultPrs);
400 isCustomized = thePrs->setLineStyle(3) || isCustomized;
401 isCustomized = thePrs->setWidth(2) || isCustomized;