0024394: Visualization - implement more general way for rendering of immediate objects
[occt.git] / src / V3d / V3d_CircularGrid.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 /***********************************************************************
15  
16      FONCTION :
17      ----------
18         Classe V3d_CircularGrid :
19  
20      VERSION HISTORY  :
21      --------------------------------
22       IMP230300: GG The color fields and methods have moved in Aspect_Grid
23
24
25 ************************************************************************/
26
27 #define IMP200100       //GG
28 //                      -> Compute the case Aspect_GDM_None
29 //                      -> Initialize the grid size according to the
30 //                        viewer default size.
31
32 #define IMP200300       //GG
33 //                      -> Recompute the grid when any graphic parameter is
34 //                        modified.
35
36 #define IMP300300       //GG
37 //                      -> Draw circles with 2 colors (tenth and normal colors)
38
39 /*----------------------------------------------------------------------*/
40 /*
41  * Includes
42  */
43
44 #include <V3d_CircularGrid.ixx>
45
46 #include <TColStd_Array2OfReal.hxx>
47 #include <Graphic3d_AspectLine3d.hxx>
48 #include <Graphic3d_AspectMarker3d.hxx>
49 #include <Graphic3d_Vertex.hxx>
50 #include <Graphic3d_Array1OfVertex.hxx>
51 #include <Graphic3d_ArrayOfSegments.hxx>
52 #include <Graphic3d_ArrayOfPoints.hxx>
53 #include <Graphic3d_ArrayOfPolylines.hxx>
54 #include <Visual3d_ViewManager.hxx>
55 #include <V3d_Viewer.hxx>
56 #include <TColgp_SequenceOfPnt.hxx>
57
58 /*----------------------------------------------------------------------*/
59 /*
60  * Constant
61  */
62
63 #define DIVISION 8
64 #define MYMINMAX 25.
65 #define MYFACTOR 50.
66
67 /*----------------------------------------------------------------------*/
68
69 V3d_CircularGrid::V3d_CircularGrid (const V3d_ViewerPointer& aViewer, const Quantity_Color& aColor, const Quantity_Color& aTenthColor)
70 : Aspect_CircularGrid (1.,8),
71   myStructure (new Graphic3d_Structure (aViewer->Viewer ())),
72   myGroup (myStructure->NewGroup()),
73   myViewer (aViewer),
74   myCurAreDefined (Standard_False)
75 {
76   myColor = aColor;
77   myTenthColor = aTenthColor;
78
79   myStructure->SetInfiniteState (Standard_True);
80
81   const Standard_Real step = 10.;
82   const Standard_Real size = 0.5*myViewer->DefaultViewSize();
83   SetGraphicValues (size, step/MYFACTOR);
84   SetRadiusStep (step);
85 }
86
87 void V3d_CircularGrid::SetColors (const Quantity_Color& aColor, const Quantity_Color& aTenthColor)
88 {
89   if( myColor != aColor || myTenthColor != aTenthColor ) {
90     myColor = aColor;
91     myTenthColor = aTenthColor;
92     myCurAreDefined = Standard_False;
93     UpdateDisplay();
94   }
95 }
96
97 void V3d_CircularGrid::Display ()
98 {
99   myStructure->SetDisplayPriority (1);
100   myStructure->Display();
101 }
102
103 void V3d_CircularGrid::Erase () const
104 {
105   myStructure->Erase ();
106 }
107
108 Standard_Boolean V3d_CircularGrid::IsDisplayed () const
109 {
110   return myStructure->IsDisplayed ();
111 }
112
113 void V3d_CircularGrid::UpdateDisplay ()
114 {
115   gp_Ax3 ThePlane = myViewer->PrivilegedPlane();
116
117   Standard_Real xl, yl, zl;
118   Standard_Real xdx, xdy, xdz;
119   Standard_Real ydx, ydy, ydz;
120   Standard_Real dx, dy, dz;
121   ThePlane.Location ().Coord (xl, yl, zl);
122   ThePlane.XDirection ().Coord (xdx, xdy, xdz);
123   ThePlane.YDirection ().Coord (ydx, ydy, ydz);
124   ThePlane.Direction ().Coord (dx, dy, dz);
125
126   Standard_Boolean MakeTransform = !myCurAreDefined;
127   if (!MakeTransform)
128   {
129     MakeTransform = (RotationAngle() != myCurAngle || XOrigin() != myCurXo || YOrigin() != myCurYo);
130     if (!MakeTransform)
131     {
132       Standard_Real curxl, curyl, curzl;
133       Standard_Real curxdx, curxdy, curxdz;
134       Standard_Real curydx, curydy, curydz;
135       Standard_Real curdx, curdy, curdz;
136       myCurViewPlane.Location ().Coord (curxl, curyl, curzl);
137       myCurViewPlane.XDirection ().Coord (curxdx, curxdy, curxdz);
138       myCurViewPlane.YDirection ().Coord (curydx, curydy, curydz);
139       myCurViewPlane.Direction ().Coord (curdx, curdy, curdz);
140       if (xl != curxl || yl != curyl || zl != curzl ||
141           xdx != curxdx || xdy != curxdy || xdz != curxdz ||
142           ydx != curydx || ydy != curydy || ydz != curydz ||
143           dx != curdx || dy != curdy || dz != curdz)
144         MakeTransform = Standard_True;
145     }
146   }
147
148   if (MakeTransform)
149   {
150     const Standard_Real CosAlpha = Cos (RotationAngle ());
151     const Standard_Real SinAlpha = Sin (RotationAngle ());
152     TColStd_Array2OfReal Trsf (1, 4, 1, 4);
153     Trsf (4, 4) = 1.0;
154     Trsf (4, 1) = Trsf (4, 2) = Trsf (4, 3) = 0.0;
155     // Translation
156     Trsf (1, 4) = xl,
157     Trsf (2, 4) = yl,
158     Trsf (3, 4) = zl;
159     // Transformation  change of marker
160     Trsf (1, 1) = xdx,
161     Trsf (2, 1) = xdy,
162     Trsf (3, 1) = xdz,
163     Trsf (1, 2) = ydx,
164     Trsf (2, 2) = ydy,
165     Trsf (3, 2) = ydz,
166     Trsf (1, 3) = dx,
167     Trsf (2, 3) = dy,
168     Trsf (3, 3) = dz;
169     myStructure->SetTransform (Trsf, Graphic3d_TOC_REPLACE);
170
171     // Translation of the origin
172     Trsf (1, 4) = -XOrigin (),
173     Trsf (2, 4) = -YOrigin (),
174     Trsf (3, 4) = 0.0;
175     // Rotation Alpha around axis -Z
176     Trsf (1, 1) = CosAlpha,
177     Trsf (2, 1) = -SinAlpha,
178     Trsf (3, 1) = 0.0,
179     Trsf (1, 2) = SinAlpha,
180     Trsf (2, 2) = CosAlpha,
181     Trsf (3, 2) = 0.0,
182     Trsf (1, 3) = 0.0,
183     Trsf (2, 3) = 0.0,
184     Trsf (3, 3) = 1.0;
185     myStructure->SetTransform (Trsf,Graphic3d_TOC_POSTCONCATENATE);
186
187     myCurAngle = RotationAngle ();
188     myCurXo = XOrigin (), myCurYo = YOrigin ();
189     myCurViewPlane = ThePlane;
190   }
191
192   switch (DrawMode())
193   {
194     default:
195     //case Aspect_GDM_Points:
196       DefinePoints ();
197       myCurDrawMode = Aspect_GDM_Points;
198       break;
199     case Aspect_GDM_Lines:
200       DefineLines ();
201       myCurDrawMode = Aspect_GDM_Lines;
202       break;
203 #ifdef IMP210100
204     case Aspect_GDM_None:
205       myCurDrawMode = Aspect_GDM_None;
206       break;
207 #endif
208   }
209   myCurAreDefined = Standard_True;
210 }
211
212 void V3d_CircularGrid::DefineLines ()
213 {
214   const Standard_Real    aStep     = RadiusStep ();
215   const Standard_Real    aDivision = DivisionNumber ();
216   const Standard_Boolean toUpdate  = !myCurAreDefined
217                                   || myCurDrawMode != Aspect_GDM_Lines
218                                   || aDivision != myCurDivi
219                                   || aStep     != myCurStep;
220   if (!toUpdate)
221   {
222     return;
223   }
224
225   myGroup->Clear ();
226
227   Handle(Graphic3d_AspectLine3d) LineAttrib = new Graphic3d_AspectLine3d ();
228   LineAttrib->SetColor (myColor);
229   LineAttrib->SetType (Aspect_TOL_SOLID);
230   LineAttrib->SetWidth (1.0);
231
232   const Standard_Integer Division = (Standard_Integer )( (aDivision >= DIVISION ? aDivision : DIVISION));
233
234   Standard_Integer nbpnts = 2 * Division;
235   // diametres
236   Standard_Real alpha = M_PI / aDivision;
237   LineAttrib->SetColor (myTenthColor);
238   myGroup->SetGroupPrimitivesAspect (LineAttrib);
239   Handle(Graphic3d_ArrayOfSegments) aPrims = new Graphic3d_ArrayOfSegments(2*nbpnts);
240   const gp_Pnt p0(0., 0., -myOffSet);
241   for (Standard_Integer i=1; i<=nbpnts; i++) {
242     aPrims->AddVertex(p0);
243     aPrims->AddVertex(Cos(alpha*i)*myRadius, Sin(alpha*i)*myRadius, -myOffSet);
244   }
245   myGroup->AddPrimitiveArray(aPrims, Standard_False);
246
247   // circles
248   nbpnts = 2 * Division + 1;
249   alpha = M_PI / Division;
250   Standard_Integer nblines = 0;
251   TColgp_SequenceOfPnt aSeqLines, aSeqTenth;
252   for (Standard_Real r=aStep; r<=myRadius; r+=aStep, nblines++) {
253     const Standard_Boolean isTenth = (Modulus(nblines, 10) == 0);
254     for (Standard_Integer i=0; i<nbpnts; i++) {
255       const gp_Pnt pt(Cos(alpha*i)*r,Sin(alpha*i)*r,-myOffSet);
256       (isTenth? aSeqTenth : aSeqLines).Append(pt);
257     }
258   }
259   if (aSeqTenth.Length())
260   {
261     LineAttrib->SetColor (myTenthColor);
262     myGroup->SetGroupPrimitivesAspect (LineAttrib);
263     Standard_Integer n, np;
264     const Standard_Integer nbl = aSeqTenth.Length() / nbpnts;
265     Handle(Graphic3d_ArrayOfPolylines) aPrims = new Graphic3d_ArrayOfPolylines(aSeqTenth.Length(),nbl);
266     for (np = 1, n=0; n<nbl; n++) {
267       aPrims->AddBound(nbpnts);
268       for (Standard_Integer i=0; i<nbpnts; i++, np++)
269         aPrims->AddVertex(aSeqTenth(np));
270   }
271     myGroup->AddPrimitiveArray(aPrims, Standard_False);
272   }
273   if (aSeqLines.Length())
274   {
275     LineAttrib->SetColor (myColor);
276     myGroup->SetPrimitivesAspect (LineAttrib);
277     Standard_Integer n, np;
278     const Standard_Integer nbl = aSeqLines.Length() / nbpnts;
279     Handle(Graphic3d_ArrayOfPolylines) aPrims = new Graphic3d_ArrayOfPolylines(aSeqLines.Length(),nbl);
280     for (np = 1, n=0; n<nbl; n++) {
281       aPrims->AddBound(nbpnts);
282       for (Standard_Integer i=0; i<nbpnts; i++, np++)
283         aPrims->AddVertex(aSeqLines(np));
284   }
285     myGroup->AddPrimitiveArray(aPrims, Standard_False);
286   }
287
288   myGroup->SetMinMaxValues(-myRadius, -myRadius, 0.0, myRadius, myRadius, 0.0);
289   myCurStep = aStep, myCurDivi = (Standard_Integer ) aDivision;
290 }
291
292 void V3d_CircularGrid::DefinePoints ()
293 {
294   const Standard_Real    aStep     = RadiusStep();
295   const Standard_Real    aDivision = DivisionNumber();
296   const Standard_Boolean toUpdate  = !myCurAreDefined
297                                   || myCurDrawMode != Aspect_GDM_Points
298                                   || aDivision != myCurDivi
299                                   || aStep     != myCurStep;
300   if (!toUpdate)
301   {
302     return;
303   }
304
305   myGroup->Clear ();
306
307   Handle(Graphic3d_AspectMarker3d) MarkerAttrib = new Graphic3d_AspectMarker3d ();
308   MarkerAttrib->SetColor (myColor);
309   MarkerAttrib->SetType (Aspect_TOM_POINT);
310   MarkerAttrib->SetScale (3.);
311
312   const Standard_Integer nbpnts = Standard_Integer (2*aDivision);
313   Standard_Real r, alpha = M_PI / aDivision;
314
315   // diameters
316   TColgp_SequenceOfPnt aSeqPnts;
317   aSeqPnts.Append(gp_Pnt(0.0, 0.0, -myOffSet));
318   for (r=aStep; r<=myRadius; r+=aStep) {
319     for (Standard_Integer i=0; i<nbpnts; i++)
320       aSeqPnts.Append(gp_Pnt(Cos(alpha*i)*r, Sin(alpha*i)*r, -myOffSet));
321   }
322   myGroup->SetGroupPrimitivesAspect (MarkerAttrib);
323   if (aSeqPnts.Length())
324   {
325     Standard_Real X,Y,Z;
326     const Standard_Integer nbv = aSeqPnts.Length();
327     Handle(Graphic3d_ArrayOfPoints) Cercle = new Graphic3d_ArrayOfPoints (nbv);
328     for (Standard_Integer i=1; i<=nbv; i++)
329     {
330       aSeqPnts(i).Coord(X,Y,Z);
331       Cercle->AddVertex (X,Y,Z);
332     }
333     myGroup->AddPrimitiveArray (Cercle, Standard_False);
334   }
335   myGroup->SetMinMaxValues(-myRadius, -myRadius, 0.0, myRadius, myRadius, 0.0);
336
337   myCurStep = aStep, myCurDivi = (Standard_Integer ) aDivision;
338 }
339
340 void V3d_CircularGrid::GraphicValues (Standard_Real& theRadius, Standard_Real& theOffSet) const
341 {
342   theRadius = myRadius;
343   theOffSet = myOffSet;
344 }
345
346 void V3d_CircularGrid::SetGraphicValues (const Standard_Real theRadius, const Standard_Real theOffSet)
347 {
348   if (! myCurAreDefined) {
349     myRadius = theRadius;
350     myOffSet = theOffSet;
351   }
352   if (myRadius != theRadius) {
353     myRadius = theRadius;
354     myCurAreDefined = Standard_False;
355   }
356   if (myOffSet != theOffSet) {
357     myOffSet = theOffSet;
358     myCurAreDefined = Standard_False;
359   }
360   if( !myCurAreDefined ) UpdateDisplay();
361 }