]> SALOME platform Git repositories - modules/shaper.git/blob - src/ConstructionPlugin/ConstructionPlugin_Plane.cpp
Salome HOME
Issue #1649: Added options to create plane by three points;
[modules/shaper.git] / src / ConstructionPlugin / ConstructionPlugin_Plane.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        ConstructionPlugin_Plane.cpp
4 // Created:     12 Dec 2014
5 // Author:      Vitaly Smetannikov
6
7 #include "ConstructionPlugin_Plane.h"
8
9 #include <Config_PropManager.h>
10
11 #include <GeomAlgoAPI_FaceBuilder.h>
12 #include <GeomAlgoAPI_ShapeTools.h>
13
14 #include <GeomAPI_Edge.h>
15 #include <GeomAPI_Pln.h>
16 #include <GeomAPI_Pnt.h>
17 #include <GeomAPI_Pnt2d.h>
18 #include <GeomAPI_Vertex.h>
19
20 #include <ModelAPI_AttributeDouble.h>
21 #include <ModelAPI_AttributeIntArray.h>
22 #include <ModelAPI_AttributeSelection.h>
23 #include <ModelAPI_AttributeString.h>
24 #include <ModelAPI_ResultConstruction.h>
25 #include <ModelAPI_Session.h>
26 #include <ModelAPI_Validator.h>
27
28 static GeomShapePtr faceByThreeVertices(const std::shared_ptr<GeomAPI_Vertex> theV1,
29                                         const std::shared_ptr<GeomAPI_Vertex> theV2,
30                                         const std::shared_ptr<GeomAPI_Vertex> theV3);
31
32 //==================================================================================================
33 ConstructionPlugin_Plane::ConstructionPlugin_Plane()
34 {
35 }
36
37 //==================================================================================================
38 void ConstructionPlugin_Plane::initAttributes()
39 {
40   data()->addAttribute(ConstructionPlugin_Plane::CREATION_METHOD(), ModelAPI_AttributeString::typeId());
41
42   // By general equation.
43   data()->addAttribute(A(), ModelAPI_AttributeDouble::typeId());
44   data()->addAttribute(B(), ModelAPI_AttributeDouble::typeId());
45   data()->addAttribute(C(), ModelAPI_AttributeDouble::typeId());
46   data()->addAttribute(D(), ModelAPI_AttributeDouble::typeId());
47   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), A());
48   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), B());
49   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), C());
50   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), D());
51
52   // By three points.
53   data()->addAttribute(POINT1(), ModelAPI_AttributeSelection::typeId());
54   data()->addAttribute(POINT2(), ModelAPI_AttributeSelection::typeId());
55   data()->addAttribute(POINT3(), ModelAPI_AttributeSelection::typeId());
56
57   // By line and point.
58   data()->addAttribute(LINE(), ModelAPI_AttributeSelection::typeId());
59   data()->addAttribute(POINT(), ModelAPI_AttributeSelection::typeId());
60
61   // By other plane.
62   data()->addAttribute(CREATION_METHOD_BY_OTHER_PLANE_OPTION(), ModelAPI_AttributeString::typeId());
63   data()->addAttribute(PLANE(), ModelAPI_AttributeSelection::typeId());
64   data()->addAttribute(DISTANCE(), ModelAPI_AttributeDouble::typeId());
65 }
66
67 //==================================================================================================
68 void ConstructionPlugin_Plane::execute()
69 {
70   GeomShapePtr aShape;
71
72   std::string aCreationMethod = string(CREATION_METHOD())->value();
73   if(aCreationMethod == CREATION_METHOD_BY_GENERAL_EQUATION()) {
74     aShape = createByGeneralEquation();
75   } else if(aCreationMethod == CREATION_METHOD_BY_THREE_POINTS()) {
76     aShape = createByThreePoints();
77   } else if(aCreationMethod == CREATION_METHOD_BY_LINE_AND_POINT()) {
78     aShape = createByLineAndPoint();
79   } else if(aCreationMethod == CREATION_METHOD_BY_OTHER_PLANE()) {
80     std::string aCreationMethodOption = string(CREATION_METHOD_BY_OTHER_PLANE_OPTION())->value();
81     if(aCreationMethodOption == CREATION_METHOD_BY_DISTANCE_FROM_OTHER()) {
82       aShape = createByDistanceFromOther();
83     }
84   }
85
86
87   if(!aShape.get()) {
88     return;
89   }
90
91   ResultConstructionPtr aConstr = document()->createConstruction(data());
92   aConstr->setInfinite(true);
93   aConstr->setShape(aShape);
94   setResult(aConstr);
95 }
96
97 //==================================================================================================
98 bool ConstructionPlugin_Plane::customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
99                                                      std::shared_ptr<GeomAPI_ICustomPrs> theDefaultPrs)
100 {
101   std::vector<int> aColor;
102   // get color from the attribute of the result
103   if (theResult.get() != NULL && theResult->data()->attribute(ModelAPI_Result::COLOR_ID()).get() != NULL) {
104     AttributeIntArrayPtr aColorAttr = theResult->data()->intArray(ModelAPI_Result::COLOR_ID());
105     if (aColorAttr.get() && aColorAttr->size()) {
106       aColor.push_back(aColorAttr->value(0));
107       aColor.push_back(aColorAttr->value(1));
108       aColor.push_back(aColorAttr->value(2));
109     }
110   }
111   if (aColor.empty())
112     aColor = Config_PropManager::color("Visualization", "construction_plane_color",
113                                        ConstructionPlugin_Plane::DEFAULT_COLOR());
114
115   bool isCustomized = false;
116   if (aColor.size() == 3)
117     isCustomized = thePrs->setColor(aColor[0], aColor[1], aColor[2]);
118
119   isCustomized = thePrs->setTransparensy(0.6) || isCustomized;
120
121   return isCustomized;
122 }
123
124 //==================================================================================================
125 std::shared_ptr<GeomAPI_Shape> ConstructionPlugin_Plane::createByGeneralEquation()
126 {
127   AttributeDoublePtr anAttrA = real(ConstructionPlugin_Plane::A());
128   AttributeDoublePtr anAttrB = real(ConstructionPlugin_Plane::B());
129   AttributeDoublePtr anAttrC = real(ConstructionPlugin_Plane::C());
130   AttributeDoublePtr anAttrD = real(ConstructionPlugin_Plane::D());
131   std::shared_ptr<GeomAPI_Shape> aPlaneFace;
132   if ((anAttrA.get() != NULL) && (anAttrB.get() != NULL) &&
133       (anAttrC.get() != NULL) && (anAttrD.get() != NULL) &&
134       anAttrA->isInitialized() && anAttrB->isInitialized() &&
135       anAttrC->isInitialized() && anAttrD->isInitialized() ) {
136     double aA = anAttrA->value(), aB = anAttrB->value(),
137            aC = anAttrC->value(), aD = anAttrD->value();
138     std::shared_ptr<GeomAPI_Pln> aPlane = 
139       std::shared_ptr<GeomAPI_Pln>(new GeomAPI_Pln(aA, aB, aC, aD));
140     std::string kDefaultPlaneSize = "200";
141     double aSize = Config_PropManager::integer("Sketch planes", "planes_size", kDefaultPlaneSize);
142     aSize *= 4.;
143     aPlaneFace = GeomAlgoAPI_FaceBuilder::squareFace(aPlane, aSize);
144   }
145   return aPlaneFace;
146 }
147
148 //==================================================================================================
149 std::shared_ptr<GeomAPI_Shape> ConstructionPlugin_Plane::createByThreePoints()
150 {
151   // Get first point.
152   AttributeSelectionPtr aPointSelection1 = selection(POINT1());
153   GeomShapePtr aPointShape1 = aPointSelection1->value();
154   if(!aPointShape1.get()) {
155     aPointShape1 = aPointSelection1->context()->shape();
156   }
157   std::shared_ptr<GeomAPI_Vertex> aVertex1(new GeomAPI_Vertex(aPointShape1));
158
159   // Get second point.
160   AttributeSelectionPtr aPointSelection2 = selection(POINT2());
161   GeomShapePtr aPointShape2 = aPointSelection2->value();
162   if(!aPointShape2.get()) {
163     aPointShape2 = aPointSelection2->context()->shape();
164   }
165   std::shared_ptr<GeomAPI_Vertex> aVertex2(new GeomAPI_Vertex(aPointShape2));
166
167   // Get third point.
168   AttributeSelectionPtr aPointSelection3 = selection(POINT3());
169   GeomShapePtr aPointShape3 = aPointSelection3->value();
170   if(!aPointShape3.get()) {
171     aPointShape3 = aPointSelection3->context()->shape();
172   }
173   std::shared_ptr<GeomAPI_Vertex> aVertex3(new GeomAPI_Vertex(aPointShape3));
174
175   GeomShapePtr aRes = faceByThreeVertices(aVertex1, aVertex2, aVertex3);
176
177   return aRes;
178 }
179
180 //==================================================================================================
181 std::shared_ptr<GeomAPI_Shape> ConstructionPlugin_Plane::createByLineAndPoint()
182 {
183   // Get edge.
184   AttributeSelectionPtr anEdgeSelection = selection(LINE());
185   GeomShapePtr aLineShape = anEdgeSelection->value();
186   if(!aLineShape.get()) {
187     aLineShape = anEdgeSelection->context()->shape();
188   }
189   std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aLineShape));
190   std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
191   GeomAlgoAPI_ShapeTools::findBounds(anEdge, aV1, aV2);
192
193
194   // Get point.
195   AttributeSelectionPtr aPointSelection = selection(POINT());
196   GeomShapePtr aPointShape = aPointSelection->value();
197   if(!aPointShape.get()) {
198     aPointShape = aPointSelection->context()->shape();
199   }
200   std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(aPointShape));
201
202   GeomShapePtr aRes = faceByThreeVertices(aV1, aV2, aVertex);
203
204   return aRes;
205 }
206
207 //==================================================================================================
208 std::shared_ptr<GeomAPI_Shape>  ConstructionPlugin_Plane::createByDistanceFromOther()
209 {
210   AttributeSelectionPtr aFaceAttr = data()->selection(ConstructionPlugin_Plane::PLANE());
211   AttributeDoublePtr aDistAttr = data()->real(ConstructionPlugin_Plane::DISTANCE());
212   std::shared_ptr<GeomAPI_Shape> aPlane;
213   if ((aFaceAttr.get() != NULL) &&
214       (aDistAttr.get() != NULL) &&
215       aFaceAttr->isInitialized() && aDistAttr->isInitialized()) {
216
217     double aDist = aDistAttr->value();
218     GeomShapePtr aShape = aFaceAttr->value();
219     if (!aShape.get()) {
220       aShape = aFaceAttr->context()->shape();
221     }
222
223     if(!aShape.get()) {
224       return aPlane;
225     }
226
227     std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(aShape));
228
229     std::shared_ptr<GeomAPI_Pln> aPln = GeomAlgoAPI_FaceBuilder::plane(aFace);
230     std::shared_ptr<GeomAPI_Pnt> aOrig = aPln->location();
231     std::shared_ptr<GeomAPI_Dir> aDir = aPln->direction();
232
233     aOrig->translate(aDir, aDist);
234     std::shared_ptr<GeomAPI_Pln> aNewPln(new GeomAPI_Pln(aOrig, aDir));
235
236     // Create rectangular face close to the selected
237     double aXmin, aYmin, Zmin, aXmax, aYmax, Zmax;
238     aFace->computeSize(aXmin, aYmin, Zmin, aXmax, aYmax, Zmax);
239
240     // use all 8 points of the bounding box to find the 2D bounds
241     bool isFirst = true;
242     double aMinX2d, aMaxX2d, aMinY2d, aMaxY2d;
243     for(int aXIsMin = 0; aXIsMin < 2; aXIsMin++) {
244       for(int aYIsMin = 0; aYIsMin < 2; aYIsMin++) {
245         for(int aZIsMin = 0; aZIsMin < 2; aZIsMin++) {
246           std::shared_ptr<GeomAPI_Pnt> aPnt(new GeomAPI_Pnt(
247             aXIsMin ? aXmin : aXmax, aYIsMin ? aYmin : aYmax, aZIsMin ? Zmin : Zmax));
248           std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = aPnt->to2D(aNewPln);
249           if (isFirst || aPnt2d->x() < aMinX2d)
250             aMinX2d = aPnt2d->x();
251           if (isFirst || aPnt2d->y() < aMinY2d)
252             aMinY2d = aPnt2d->y();
253           if (isFirst || aPnt2d->x() > aMaxX2d)
254             aMaxX2d = aPnt2d->x();
255           if (isFirst || aPnt2d->y() > aMaxY2d)
256             aMaxY2d = aPnt2d->y();
257           if (isFirst)
258             isFirst = !isFirst;
259         }
260       }
261     }
262     double aWgap = (aMaxX2d - aMinX2d) * 0.1;
263     double aHgap = (aMaxY2d - aMinY2d) * 0.1;
264     aPlane = GeomAlgoAPI_FaceBuilder::planarFace(aNewPln,
265       aMinX2d - aWgap, aMinY2d - aHgap, aMaxX2d - aMinX2d + 2. * aWgap, aMaxY2d - aMinY2d + 2. * aHgap);
266
267   }
268   return aPlane;
269 }
270
271 //==================================================================================================
272 GeomShapePtr faceByThreeVertices(const std::shared_ptr<GeomAPI_Vertex> theV1,
273                                  const std::shared_ptr<GeomAPI_Vertex> theV2,
274                                  const std::shared_ptr<GeomAPI_Vertex> theV3)
275 {
276   std::shared_ptr<GeomAPI_Face> aFace = GeomAlgoAPI_FaceBuilder::planarFaceByThreeVertices(theV1, theV2, theV3);
277
278   ListOfShape anObjects;
279   anObjects.push_back(theV1);
280   anObjects.push_back(theV2);
281   anObjects.push_back(theV3);
282   std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints = GeomAlgoAPI_ShapeTools::getBoundingBox(anObjects, 1.0);
283   GeomShapePtr aRes = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aFace, aBoundingPoints);
284
285   return aRes;
286 }