Salome HOME
Copyright update 2021
[modules/shaper.git] / src / PartSet / PartSet_PreviewSketchPlane.cpp
1 // Copyright (C) 2014-2021  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 email : webmaster.salome@opencascade.com
18 //
19
20 #include "PartSet_PreviewSketchPlane.h"
21 #include "PartSet_Tools.h"
22
23 #include <ModuleBase_IWorkshop.h>
24
25 #include <ModelAPI_ResultBody.h>
26 #include <ModelAPI_ResultConstruction.h>
27 #include <ModelAPI_CompositeFeature.h>
28 #include <ModelAPI_Tools.h>
29
30 #include <GeomAPI_AISObject.h>
31 #include <GeomAPI_Pnt.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 PartSet_PreviewSketchPlane::PartSet_PreviewSketchPlane()
46  : myPreviewIsDisplayed(false), mySizeOfView(0), myIsUseSizeOfView(false)
47 {
48 }
49
50 void PartSet_PreviewSketchPlane::eraseSketchPlane(ModuleBase_IWorkshop* theWorkshop,
51                                                   const bool isClearPlane)
52 {
53   if (myPreviewIsDisplayed) {
54     XGUI_Displayer* aDisp = XGUI_Tools::workshop(theWorkshop)->displayer();
55     aDisp->eraseAIS(myPlane, false);
56     if (isClearPlane) {
57       myPlane = std::shared_ptr<GeomAPI_AISObject>();
58       myShape = std::shared_ptr<GeomAPI_Shape>();
59     }
60     myPreviewIsDisplayed = false;
61   }
62 }
63
64 void PartSet_PreviewSketchPlane::displaySketchPlane(ModuleBase_IWorkshop* theWorkshop)
65 {
66   if (myPlane.get() && (!myPreviewIsDisplayed)) {
67     XGUI_Displayer* aDisp = XGUI_Tools::workshop(theWorkshop)->displayer();
68     aDisp->displayAIS(myPlane, false/*load object in selection*/, 1/*shaded*/, false);
69     myPreviewIsDisplayed = true;
70   }
71 }
72
73
74 void PartSet_PreviewSketchPlane::clearPlanePreview()
75 {
76   myPlane = std::shared_ptr<GeomAPI_AISObject>();
77   myShape = std::shared_ptr<GeomAPI_Shape>();
78 }
79
80
81 void PartSet_PreviewSketchPlane::createSketchPlane(const CompositeFeaturePtr& theSketch,
82                                                    ModuleBase_IWorkshop* theWorkshop)
83 {
84   // plane is visualized only if sketch plane is filled
85   if (!PartSet_Tools::sketchPlane(theSketch).get())
86     return;
87
88   AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
89     (theSketch->data()->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
90   if (!aSelAttr)
91     return;
92
93   if (myShape.get() && myShape->isSame(aSelAttr->value()) && myPlane.get())
94     return;
95
96   XGUI_Displayer* aDisp = XGUI_Tools::workshop(theWorkshop)->displayer();
97   if (myPreviewIsDisplayed) {
98     aDisp->eraseAIS(myPlane, false);
99   }
100
101   // Create Preview
102   // selected linear face parameters
103   myShape = aSelAttr->value();
104   // this case is needed by constructing sketch on a plane, where result shape is equal
105   // to context result, therefore value() returns NULL and we should use shape of context.
106   if (!myShape.get() && aSelAttr->context().get())
107     myShape = aSelAttr->context()->shape();
108
109   if (!myShape.get()) {
110     // Create Preview for default planes
111     std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
112         theSketch->data()->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
113     std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
114         theSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
115
116     double aFaceSize = myIsUseSizeOfView ? mySizeOfView
117       : Config_PropManager::real(SKETCH_TAB_NAME, "planes_size");
118     if (aFaceSize <= Precision::Confusion())
119       aFaceSize = 200;   // Set default value
120
121     myShape = GeomAlgoAPI_FaceBuilder::squareFace(
122       myViewCentralPoint.get() ? myViewCentralPoint : anOrigin->pnt(), aNormal->dir(), aFaceSize);
123   }
124   else if (myIsUseSizeOfView && (mySizeOfView > 0)) {
125     std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(myShape));
126     std::shared_ptr<GeomAPI_Pln> aPlane = aFace->getPlane();
127     if (aPlane.get()) {
128       double anA, aB, aC, aD;
129       aPlane->coefficients(anA, aB, aC, aD);
130       std::shared_ptr<GeomAPI_Dir> aNormDir(new GeomAPI_Dir(anA, aB, aC));
131       std::shared_ptr<GeomAPI_XYZ> aCoords = aNormDir->xyz();
132       std::shared_ptr<GeomAPI_XYZ> aZero(new GeomAPI_XYZ(0, 0, 0));
133       aCoords = aCoords->multiplied(-aD * aCoords->distance(aZero));
134       std::shared_ptr<GeomAPI_Pnt> anOrigPnt(new GeomAPI_Pnt(aCoords));
135       myShape = GeomAlgoAPI_FaceBuilder::squareFace(
136         myViewCentralPoint.get() ? myViewCentralPoint : anOrigPnt, aNormDir, mySizeOfView);
137     }
138   }
139   myPlane = createPreviewPlane();
140
141   aDisp->displayAIS(myPlane, false/*load object in selection*/, 1/*shaded*/, false);
142   myPreviewIsDisplayed = true;
143 }
144
145 double maximumSize(double theXmin, double theYmin, double theZmin,
146                    double theXmax, double theYmax, double theZmax)
147 {
148   double aSize = fabs(theXmax - theXmin);
149   double aSizeToCompare = fabs(theYmax - theYmin);
150   if (aSizeToCompare > aSize)
151     aSize = aSizeToCompare;
152   aSizeToCompare = fabs(theZmax - theZmin);
153   if (aSizeToCompare > aSize)
154     aSize = aSizeToCompare;
155
156   return aSize;
157 }
158
159 bool PartSet_PreviewSketchPlane::getDefaultSizeOfView(
160   const CompositeFeaturePtr& theSketch, double& theSizeOfView,
161   std::shared_ptr<GeomAPI_Pnt>& theCentralPnt)
162 {
163   if (!PartSet_Tools::sketchPlane(theSketch).get())
164     return false;
165
166   AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
167     (theSketch->data()->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
168   if (aSelAttr) {
169     myShape = aSelAttr->value();
170     // this case is needed by constructing sketch on a plane, where result shape is equal
171     // to context result, therefore value() returns NULL and we should use shape of context.
172     if (!myShape.get() && aSelAttr->context().get())
173       myShape = aSelAttr->context()->shape();
174   }
175
176   if (myShape.get())
177     return false;
178
179   Bnd_Box aBox;
180   int aNumberOfSubs = theSketch->numberOfSubs();
181   for (int aSubFeatureId = 0; aSubFeatureId < aNumberOfSubs; aSubFeatureId++) {
182     FeaturePtr aFeature = theSketch->subFeature(aSubFeatureId);
183     if (!aFeature.get())
184       continue;
185
186     std::list<ResultPtr> aResults = aFeature->results();
187     std::list<ResultPtr>::const_iterator aResultIt;
188     for (aResultIt = aResults.begin(); aResultIt != aResults.end(); ++aResultIt) {
189       ResultPtr aResult = *aResultIt;
190       std::shared_ptr<GeomAPI_Shape> aShapePtr = aResult->shape();
191       if (aShapePtr.get()) {
192         TopoDS_Shape aShape = aShapePtr->impl<TopoDS_Shape>();
193         if (aShape.IsNull())
194           continue;
195         BRepBndLib::Add(aShape, aBox);
196       }
197     }
198   }
199   if (aBox.IsVoid())
200     return 0;
201
202   double aXmin, aXmax, anYmin, anYmax, aZmin, aZmax;
203   aBox.Get(aXmin, anYmin, aZmin, aXmax, anYmax, aZmax);
204
205   theSizeOfView = maximumSize(aXmin, anYmin, aZmin, aXmax, anYmax, aZmax);
206   if (theSizeOfView > 0) {
207     gp_Pnt aCentre(aXmax-fabs(aXmax-aXmin)/2., anYmax-fabs(anYmax-anYmin)/2.,
208                    aZmax - fabs(aZmax-aZmin)/2.);
209     theCentralPnt = std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aCentre.X(), aCentre.Y(),
210                                                                  aCentre.Z()));
211   }
212   return true;
213 }
214
215 void PartSet_PreviewSketchPlane::setSizeOfView(double theSizeOfView, bool isUseSizeOfView,
216   const std::shared_ptr<GeomAPI_Pnt>& theCentralPoint)
217 {
218   mySizeOfView = theSizeOfView;
219   myIsUseSizeOfView = isUseSizeOfView;
220
221   myViewCentralPoint = theCentralPoint;
222 }
223
224 AISObjectPtr PartSet_PreviewSketchPlane::createPreviewPlane()
225 {
226   if (myPlane.get()) {
227     myPlane->createShape(myShape);
228     return myPlane;
229   }
230   else {
231     AISObjectPtr aAIS = AISObjectPtr(new GeomAPI_AISObject());
232     aAIS->createShape(myShape);
233     std::vector<int> aColor = Config_PropManager::color("Visualization", "sketch_preview_plane");
234     if (aColor.size() == 3)
235       aAIS->setColor(aColor[0], aColor[1], aColor[2]);
236     aAIS->setTransparensy(0.8);
237
238     int aDispMode = 1; // shading
239     Handle(AIS_InteractiveObject) anAISIO = aAIS->impl<Handle(AIS_InteractiveObject)>();
240     if (!anAISIO.IsNull()) {
241       //anAISIO->SetInfiniteState(Standard_True);
242       anAISIO->Attributes()->SetFaceBoundaryDraw( Standard_True );
243       anAISIO->SetDisplayMode(aDispMode);
244     }
245     return aAIS;
246   }
247 }