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