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