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