0026154: Visualization - v3d viewer grid disappears due to automatic z-fit
[occt.git] / src / V3d / V3d_RectangularGrid.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <V3d_RectangularGrid.hxx>
15
16 #include <Graphic3d_ArrayOfPoints.hxx>
17 #include <Graphic3d_ArrayOfSegments.hxx>
18 #include <Graphic3d_AspectLine3d.hxx>
19 #include <Graphic3d_AspectMarker3d.hxx>
20 #include <Graphic3d_AspectText3d.hxx>
21 #include <Graphic3d_Group.hxx>
22 #include <Graphic3d_Structure.hxx>
23 #include <Quantity_Color.hxx>
24 #include <Standard_Type.hxx>
25 #include <TColgp_SequenceOfPnt.hxx>
26 #include <TColStd_Array2OfReal.hxx>
27 #include <V3d_Viewer.hxx>
28
29 IMPLEMENT_STANDARD_RTTIEXT(V3d_RectangularGrid,Aspect_RectangularGrid)
30
31 namespace
32 {
33   static const Standard_Real THE_DEFAULT_GRID_STEP = 10.0;
34   #define MYFACTOR 50.
35 }
36
37 //! Dummy implementation of Graphic3d_Structure overriding ::Compute() method for handling Device Lost.
38 class V3d_RectangularGrid::RectangularGridStructure : public Graphic3d_Structure
39 {
40 public:
41   //! Main constructor.
42   RectangularGridStructure (const Handle(Graphic3d_StructureManager)& theManager, V3d_RectangularGrid* theGrid)
43   : Graphic3d_Structure (theManager), myGrid (theGrid) {}
44
45   //! Override method initiating recomputing in V3d_RectangularGrid.
46   virtual void Compute() Standard_OVERRIDE
47   {
48     GraphicClear (Standard_False);
49     myGrid->myGroup = NewGroup();
50     myGrid->myCurAreDefined = Standard_False;
51     myGrid->UpdateDisplay();
52   }
53
54 private:
55   V3d_RectangularGrid* myGrid;
56 };
57
58 /*----------------------------------------------------------------------*/
59
60 V3d_RectangularGrid::V3d_RectangularGrid (const V3d_ViewerPointer& aViewer, const Quantity_Color& aColor, const Quantity_Color& aTenthColor)
61 : Aspect_RectangularGrid (1.,1.),
62   myViewer (aViewer),
63   myCurAreDefined (Standard_False),
64   myToComputePrs (Standard_True),
65   myCurDrawMode (Aspect_GDM_Lines),
66   myCurXo (0.0),
67   myCurYo (0.0),
68   myCurAngle (0.0),
69   myCurXStep (0.0),
70   myCurYStep (0.0),
71   myXSize  (0.5 * aViewer->DefaultViewSize()),
72   myYSize  (0.5 * aViewer->DefaultViewSize()),
73   myOffSet (THE_DEFAULT_GRID_STEP / MYFACTOR)
74 {
75   myColor = aColor;
76   myTenthColor = aTenthColor;
77
78   myStructure = new RectangularGridStructure (aViewer->StructureManager(), this);
79   myGroup = myStructure->NewGroup();
80   myStructure->SetInfiniteState (Standard_True);
81
82   SetXStep (THE_DEFAULT_GRID_STEP);
83   SetYStep (THE_DEFAULT_GRID_STEP);
84 }
85
86 V3d_RectangularGrid::~V3d_RectangularGrid()
87 {
88   myGroup.Nullify();
89   if (!myStructure.IsNull())
90   {
91     myStructure->Erase();
92   }
93 }
94
95 void V3d_RectangularGrid::SetColors (const Quantity_Color& aColor, const Quantity_Color& aTenthColor)
96 {
97   if( myColor != aColor || myTenthColor != aTenthColor ) {
98     myColor = aColor;
99     myTenthColor = aTenthColor;
100     myCurAreDefined = Standard_False;
101     UpdateDisplay();
102   }
103 }
104
105 void V3d_RectangularGrid::Display ()
106 {
107   myStructure->SetDisplayPriority (1);
108   myStructure->Display();
109   UpdateDisplay();
110 }
111
112 void V3d_RectangularGrid::Erase () const
113 {
114   myStructure->Erase ();
115 }
116
117 Standard_Boolean V3d_RectangularGrid::IsDisplayed () const
118 {
119   return myStructure->IsDisplayed ();
120 }
121
122 void V3d_RectangularGrid::UpdateDisplay ()
123 {
124   gp_Ax3 ThePlane = myViewer->PrivilegedPlane ();
125
126   Standard_Boolean MakeTransform = Standard_False;
127   Standard_Real xl, yl, zl;
128   Standard_Real xdx, xdy, xdz;
129   Standard_Real ydx, ydy, ydz;
130   Standard_Real dx, dy, dz;
131   ThePlane.Location ().Coord (xl, yl, zl);
132   ThePlane.XDirection ().Coord (xdx, xdy, xdz);
133   ThePlane.YDirection ().Coord (ydx, ydy, ydz);
134   ThePlane.Direction ().Coord (dx, dy, dz);
135   if (! myCurAreDefined)
136     MakeTransform = Standard_True;
137   else {
138     if (RotationAngle() != myCurAngle || XOrigin() != myCurXo || YOrigin() != myCurYo)
139       MakeTransform = Standard_True;
140     if (! MakeTransform) {
141       Standard_Real curxl, curyl, curzl;
142       Standard_Real curxdx, curxdy, curxdz;
143       Standard_Real curydx, curydy, curydz;
144       Standard_Real curdx, curdy, curdz;
145       myCurViewPlane.Location ().Coord (curxl, curyl, curzl);
146       myCurViewPlane.XDirection ().Coord (curxdx, curxdy, curxdz);
147       myCurViewPlane.YDirection ().Coord (curydx, curydy, curydz);
148       myCurViewPlane.Direction ().Coord (curdx, curdy, curdz);
149       if (xl != curxl || yl != curyl || zl != curzl ||
150           xdx != curxdx || xdy != curxdy || xdz != curxdz ||
151           ydx != curydx || ydy != curydy || ydz != curydz ||
152           dx != curdx || dy != curdy || dz != curdz)
153         MakeTransform = Standard_True;
154     }
155   }
156
157   if (MakeTransform) {
158     const Standard_Real CosAlpha = Cos (RotationAngle ());
159     const Standard_Real SinAlpha = Sin (RotationAngle ());
160
161     gp_Trsf aTrsf;
162     // Translation
163     // Transformation of change of marker
164     aTrsf.SetValues (xdx, ydx, dx, xl,
165                      xdy, ydy, dy, yl,
166                      xdz, ydz, dz, zl);
167
168     // Translation of the origin
169     // Rotation Alpha around axis -Z
170     gp_Trsf aTrsf2;
171     aTrsf2.SetValues ( CosAlpha, SinAlpha, 0.0, -XOrigin(),
172                       -SinAlpha, CosAlpha, 0.0, -YOrigin(),
173                             0.0,      0.0, 1.0, 0.0);
174     aTrsf.Multiply (aTrsf2);
175     myStructure->SetTransformation (new Geom_Transformation (aTrsf));
176
177     myCurAngle = RotationAngle ();
178     myCurXo = XOrigin (), myCurYo = YOrigin ();
179     myCurViewPlane = ThePlane;
180   }
181
182   switch (myDrawMode)
183   {
184     case Aspect_GDM_Points:
185       DefinePoints ();
186       myCurDrawMode = Aspect_GDM_Points;
187       break;
188     case Aspect_GDM_Lines:
189       DefineLines ();
190       myCurDrawMode = Aspect_GDM_Lines;
191       break;
192     case Aspect_GDM_None:
193       myCurDrawMode = Aspect_GDM_None;
194       break;
195         }
196         myCurAreDefined = Standard_True;
197 }
198
199 void V3d_RectangularGrid::DefineLines ()
200 {
201   const Standard_Real aXStep = XStep();
202   const Standard_Real aYStep = YStep();
203   const Standard_Boolean toUpdate = !myCurAreDefined
204                                  || myCurDrawMode != Aspect_GDM_Lines
205                                  || aXStep != myCurXStep
206                                  || aYStep != myCurYStep;
207   if (!toUpdate
208    && !myToComputePrs)
209   {
210     return;
211   }
212   else if (!myStructure->IsDisplayed())
213   {
214     myToComputePrs = Standard_True;
215     return;
216   }
217
218   myToComputePrs = Standard_False;
219   myGroup->Clear();
220
221   Standard_Integer nblines;
222   Standard_Real xl, yl, zl = myOffSet;
223
224   TColgp_SequenceOfPnt aSeqLines, aSeqTenth;
225
226   // verticals
227   aSeqTenth.Append(gp_Pnt(0., -myYSize, -zl));
228   aSeqTenth.Append(gp_Pnt(0.,  myYSize, -zl));
229   for (nblines = 1, xl = aXStep; xl < myXSize; xl += aXStep, nblines++)
230   {
231     TColgp_SequenceOfPnt &aSeq = (Modulus(nblines, 10) != 0)? aSeqLines : aSeqTenth;
232     aSeq.Append(gp_Pnt( xl, -myYSize, -zl));
233     aSeq.Append(gp_Pnt( xl,  myYSize, -zl));
234     aSeq.Append(gp_Pnt(-xl, -myYSize, -zl));
235     aSeq.Append(gp_Pnt(-xl,  myYSize, -zl));
236   }
237
238   // horizontals
239   aSeqTenth.Append(gp_Pnt(-myXSize, 0., -zl));
240   aSeqTenth.Append(gp_Pnt( myXSize, 0., -zl));
241   for (nblines = 1, yl = aYStep; yl < myYSize; yl += aYStep, nblines++)
242   {
243     TColgp_SequenceOfPnt &aSeq = (Modulus(nblines, 10) != 0)? aSeqLines : aSeqTenth;
244     aSeq.Append(gp_Pnt(-myXSize,  yl, -zl));
245     aSeq.Append(gp_Pnt( myXSize,  yl, -zl));
246     aSeq.Append(gp_Pnt(-myXSize, -yl, -zl));
247     aSeq.Append(gp_Pnt( myXSize, -yl, -zl));
248   }
249
250   if (aSeqLines.Length())
251   {
252     Handle(Graphic3d_AspectLine3d) aLineAspect = new Graphic3d_AspectLine3d (myColor, Aspect_TOL_SOLID, 1.0);
253     myGroup->SetPrimitivesAspect (aLineAspect);
254     const Standard_Integer nbv = aSeqLines.Length();
255     Handle(Graphic3d_ArrayOfSegments) aPrims = new Graphic3d_ArrayOfSegments(nbv);
256     Standard_Integer n = 1;
257     while (n<=nbv)
258       aPrims->AddVertex(aSeqLines(n++));
259     myGroup->AddPrimitiveArray(aPrims, Standard_False);
260   }
261   if (aSeqTenth.Length())
262   {
263     Handle(Graphic3d_AspectLine3d) aLineAspect = new Graphic3d_AspectLine3d (myTenthColor, Aspect_TOL_SOLID, 1.0);
264     myGroup->SetPrimitivesAspect (aLineAspect);
265     const Standard_Integer nbv = aSeqTenth.Length();
266     Handle(Graphic3d_ArrayOfSegments) aPrims = new Graphic3d_ArrayOfSegments(nbv);
267     Standard_Integer n = 1;
268     while (n<=nbv)
269       aPrims->AddVertex(aSeqTenth(n++));
270     myGroup->AddPrimitiveArray(aPrims, Standard_False);
271   }
272
273   myGroup->SetMinMaxValues(-myXSize, -myYSize, -myOffSet, myXSize, myYSize, -myOffSet);
274   myCurXStep = aXStep, myCurYStep = aYStep;
275
276   // update bounding box
277   myStructure->CalculateBoundBox();
278   myViewer->StructureManager()->Update (myStructure->GetZLayer());
279 }
280
281 void V3d_RectangularGrid::DefinePoints ()
282 {
283   const Standard_Real aXStep = XStep();
284   const Standard_Real aYStep = YStep();
285   const Standard_Boolean toUpdate = !myCurAreDefined
286                                   || myCurDrawMode != Aspect_GDM_Points
287                                   || aXStep != myCurXStep
288                                   || aYStep != myCurYStep;
289   if (!toUpdate
290    && !myToComputePrs)
291   {
292     return;
293   }
294   else if (!myStructure->IsDisplayed())
295   {
296     myToComputePrs = Standard_True;
297     return;
298   }
299
300   myToComputePrs = Standard_False;
301   myGroup->Clear();
302
303   // horizontals
304   Standard_Real xl, yl;
305   TColgp_SequenceOfPnt aSeqPnts;
306   for (xl = 0.0; xl <= myXSize; xl += aXStep) {
307     aSeqPnts.Append(gp_Pnt( xl, 0.0, -myOffSet));
308     aSeqPnts.Append(gp_Pnt(-xl, 0.0, -myOffSet));
309     for (yl = aYStep; yl <= myYSize; yl += aYStep) {
310       aSeqPnts.Append(gp_Pnt( xl,  yl, -myOffSet));
311       aSeqPnts.Append(gp_Pnt( xl, -yl, -myOffSet));
312       aSeqPnts.Append(gp_Pnt(-xl,  yl, -myOffSet));
313       aSeqPnts.Append(gp_Pnt(-xl, -yl, -myOffSet));
314     }
315   }
316   if (aSeqPnts.Length())
317   {
318     Standard_Integer i;
319     Standard_Real X,Y,Z;
320     const Standard_Integer nbv = aSeqPnts.Length();
321     Handle(Graphic3d_ArrayOfPoints) Vertical = new Graphic3d_ArrayOfPoints (nbv);
322     for (i=1; i<=nbv; i++)
323     {
324       aSeqPnts(i).Coord(X,Y,Z);
325       Vertical->AddVertex (X,Y,Z);
326     }
327
328     Handle(Graphic3d_AspectMarker3d) aMarkerAspect = new Graphic3d_AspectMarker3d (Aspect_TOM_POINT, myColor, 3.0);
329     myGroup->SetGroupPrimitivesAspect (aMarkerAspect);
330     myGroup->AddPrimitiveArray (Vertical, Standard_False);
331   }
332
333   myGroup->SetMinMaxValues(-myXSize, -myYSize, -myOffSet, myXSize, myYSize, -myOffSet);
334   myCurXStep = aXStep, myCurYStep = aYStep;
335
336   // update bounding box
337   myStructure->CalculateBoundBox();
338   myViewer->StructureManager()->Update (myStructure->GetZLayer());
339 }
340
341 void V3d_RectangularGrid::GraphicValues (Standard_Real& theXSize, Standard_Real& theYSize, Standard_Real& theOffSet) const
342 {
343   theXSize = myXSize;
344   theYSize = myYSize;
345   theOffSet = myOffSet;
346 }
347
348 void V3d_RectangularGrid::SetGraphicValues (const Standard_Real theXSize, const Standard_Real theYSize, const Standard_Real theOffSet)
349 {
350   if (! myCurAreDefined) {
351     myXSize = theXSize;
352     myYSize = theYSize;
353     myOffSet = theOffSet;
354   }
355   if (myXSize != theXSize) {
356     myXSize = theXSize;
357     myCurAreDefined = Standard_False;
358   }
359   if (myYSize != theYSize) {
360     myYSize = theYSize;
361     myCurAreDefined = Standard_False;
362   }
363   if (myOffSet != theOffSet) {
364     myOffSet = theOffSet;
365     myCurAreDefined = Standard_False;
366   }
367   if( !myCurAreDefined ) UpdateDisplay();
368 }