Salome HOME
Issue #2206 Avoid the ability to cancel the current sketch when saving,
[modules/shaper.git] / src / PartSet / PartSet_PreviewSketchPlane.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 "PartSet_PreviewSketchPlane.h"
22 #include "PartSet_Tools.h"
23
24 #include <ModuleBase_IWorkshop.h>
25
26 #include <ModelAPI_ResultBody.h>
27 #include <ModelAPI_ResultConstruction.h>
28 #include <ModelAPI_CompositeFeature.h>
29 #include <ModelAPI_Tools.h>
30
31 #include <GeomAlgoAPI_ShapeTools.h>
32
33 #include <XGUI_Tools.h>
34 #include <XGUI_Displayer.h>
35 #include <XGUI_Workshop.h>
36
37 #include <Config_PropManager.h>
38 #include <GeomAlgoAPI_FaceBuilder.h>
39
40 #include <SketchPlugin_Sketch.h>
41 #include <SketchPlugin_SketchEntity.h>
42
43 #include <BRepBndLib.hxx>
44
45 double maximumSize(double theXmin, double theYmin, double theZmin,
46                    double theXmax, double theYmax, double theZmax)
47 {
48   double aSize = fabs(theXmax - theXmin);
49   double aSizeToCompare = fabs(theYmax - theYmin);
50   if (aSizeToCompare > aSize)
51     aSize = aSizeToCompare;
52   aSizeToCompare = fabs(theZmax - theZmin);
53   if (aSizeToCompare > aSize)
54     aSize = aSizeToCompare;
55
56   return aSize;
57 }
58
59 PartSet_PreviewSketchPlane::PartSet_PreviewSketchPlane()
60  : mySketchDisplayed(false), myOtherSketchSize(0)
61 {
62 }
63
64 void PartSet_PreviewSketchPlane::setOtherSketchParameters(const GeomShapePtr& theOtherSketchFace)
65 {
66   myOtherSketchOrigin = std::shared_ptr<GeomAPI_Pnt>();
67   myOtherSketchSize = 0;
68   if (!theOtherSketchFace)
69     return;
70
71   getShapeParameters(theOtherSketchFace, myOtherSketchOrigin, myOtherSketchSize);
72 }
73
74 void PartSet_PreviewSketchPlane::eraseSketchPlane(ModuleBase_IWorkshop* theWorkshop,
75                                                   const bool isClearPlane)
76 {
77   if (mySketchDisplayed) {
78     XGUI_Displayer* aDisp = XGUI_Tools::workshop(theWorkshop)->displayer();
79     aDisp->eraseAIS(myPlane, false);
80     if (isClearPlane) {
81       myPlane = NULL;
82       myOrigin = NULL;
83       myNormal = NULL;
84     }
85     mySketchDisplayed = false;
86   }
87 }
88
89 void PartSet_PreviewSketchPlane::createSketchPlane(const CompositeFeaturePtr& theSketch,
90                                                    ModuleBase_IWorkshop* theWorkshop)
91 {
92   if (mySketchDisplayed)
93     return;
94
95   // plane is visualized only if sketch plane is filled
96   std::shared_ptr<GeomAPI_Pln> aPlane = PartSet_Tools::sketchPlane(theSketch);
97   if (!aPlane.get())
98     return;
99
100   if (!myPlane) { // If planes are not created
101     std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
102         theSketch->data()->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
103     std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
104         theSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
105
106     // Create Preview
107     // default planes parameters
108     std::shared_ptr<GeomAPI_Pnt> anOriginPnt = anOrigin->pnt();
109     double aSize = 10;//Config_PropManager::integer(SKETCH_TAB_NAME, "planes_size");
110     // another sketch parameters
111     if (myOtherSketchOrigin) {
112       anOriginPnt = myOtherSketchOrigin;
113       aSize = myOtherSketchSize;
114       setOtherSketchParameters(GeomShapePtr());
115     }
116     else {
117       // selected linear face parameters
118       AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
119                                 (theSketch->data()->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
120       if (aSelAttr) {
121         std::shared_ptr<GeomAPI_Shape> aSketchExternalFace = aSelAttr->value();
122         if (aSketchExternalFace)
123           getShapeParameters(aSketchExternalFace, anOriginPnt, aSize);
124       }
125     }
126     double aSketchSize = getSketchBoundingBoxSize(theSketch, anOriginPnt);
127     if (aSketchSize > 0)
128       aSize = aSketchSize;
129
130     myOrigin = anOriginPnt;
131     myNormal = aNormal->dir();
132     myPlane = createPreviewPlane(aSize);
133   }
134
135   XGUI_Displayer* aDisp = XGUI_Tools::workshop(theWorkshop)->displayer();
136   aDisp->displayAIS(myPlane, true, 1/*shaded*/, false);
137   mySketchDisplayed = true;
138 }
139
140 void PartSet_PreviewSketchPlane::updatePlaneSize(const CompositeFeaturePtr& theSketch,
141                                                  ModuleBase_IWorkshop* theWorkshop)
142 {
143   std::shared_ptr<GeomAPI_Pnt> anOriginPnt;
144   double aSize = getSketchBoundingBoxSize(theSketch, anOriginPnt);
145   if (aSize <= 0)
146     return;
147   myOrigin = anOriginPnt;
148   createPreviewPlane(aSize);
149 }
150
151 AISObjectPtr PartSet_PreviewSketchPlane::createPreviewPlane(double theSize)
152 {
153   std::vector<int> aYZRGB(3, 0);
154 #ifdef SET_PLANES_COLOR_IN_PREFERENCES
155     aYZRGB = Config_PropManager::color("Visualization", "yz_plane_color");
156 #else
157     aYZRGB[0] = 225;
158 #endif
159     int aR[] = {aYZRGB[0], aYZRGB[1], aYZRGB[2]};
160
161   std::shared_ptr<GeomAPI_Shape> aFace =
162     GeomAlgoAPI_FaceBuilder::squareFace(myOrigin, myNormal, theSize);
163
164   if (myPlane.get()) {
165     myPlane->createShape(aFace);
166     return myPlane;
167   }
168   else {
169     AISObjectPtr aAIS = AISObjectPtr(new GeomAPI_AISObject());
170     aAIS->createShape(aFace);
171     std::vector<int> aColor = Config_PropManager::color("Visualization", "sketch_preview_plane");
172     if (aColor.size() == 3)
173       aAIS->setColor(aColor[0], aColor[1], aColor[2]);
174     aAIS->setTransparensy(0.8);
175
176     int aDispMode = 1; // shading
177     Handle(AIS_InteractiveObject) anAISIO = aAIS->impl<Handle(AIS_InteractiveObject)>();
178     if (!anAISIO.IsNull()) {
179       anAISIO->Attributes()->SetFaceBoundaryDraw( Standard_True );
180       anAISIO->SetDisplayMode(aDispMode);
181     }
182     return aAIS;
183   }
184 }
185
186 void PartSet_PreviewSketchPlane::getShapeParameters(const GeomShapePtr& theShape,
187                                                     std::shared_ptr<GeomAPI_Pnt>& theOrigin,
188                                                     double& theSize)
189 {
190   theOrigin = GeomAlgoAPI_ShapeTools::centreOfMass(theShape);
191
192   // Create rectangular face close to the selected
193   double aXmin, anYmin, aZmin, aXmax, anYmax, aZmax;
194   theShape->computeSize(aXmin, anYmin, aZmin, aXmax, anYmax, aZmax);
195
196   theSize = maximumSize(aXmin, anYmin, aZmin, aXmax, anYmax, aZmax);
197 }
198
199 double PartSet_PreviewSketchPlane::getSketchBoundingBoxSize(
200                                  const std::shared_ptr<ModelAPI_CompositeFeature>& theSketch,
201                                  std::shared_ptr<GeomAPI_Pnt>& theCentralPnt)
202 {
203   if (!theSketch.get() || theSketch->numberOfSubs() == 0)
204     return 0;
205
206   Bnd_Box aBox;
207   for (int aSubFeatureId = 0; aSubFeatureId < theSketch->numberOfSubs(); aSubFeatureId++) {
208     FeaturePtr aFeature = theSketch->subFeature(aSubFeatureId);
209     if (!aFeature.get())
210       continue;
211
212     std::list<ResultPtr> aResults = aFeature->results();
213     std::list<ResultPtr>::const_iterator aResultIt;
214     for (aResultIt = aResults.begin(); aResultIt != aResults.end(); ++aResultIt) {
215       ResultPtr aResult = *aResultIt;
216       std::shared_ptr<GeomAPI_Shape> aShapePtr = aResult->shape();
217       if (aShapePtr.get()) {
218         TopoDS_Shape aShape = aShapePtr->impl<TopoDS_Shape>();
219         if (aShape.IsNull())
220           continue;
221         BRepBndLib::Add(aShape, aBox);
222       }
223     }
224   }
225   if (aBox.IsVoid())
226     return 0;
227
228   double aXmin, aXmax, anYmin, anYmax, aZmin, aZmax;
229   aBox.Get(aXmin, anYmin, aZmin, aXmax, anYmax, aZmax);
230
231   double aSize = maximumSize(aXmin, anYmin, aZmin, aXmax, anYmax, aZmax);
232   if (aSize > 0) {
233     gp_Pnt aCentre(aXmax-fabs(aXmax-aXmin)/2., anYmax-fabs(anYmax-anYmin)/2.,
234                    aZmax - fabs(aZmax-aZmin)/2.);
235     theCentralPnt = std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aCentre.X(), aCentre.Y(),
236                                                                  aCentre.Z()));
237   }
238   return aSize;
239 }