ccf2092719f416490109194d7cc195d4b89702fc
[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 #include <V3d_CircularGrid.hxx>
15
16 #include <Graphic3d_ArrayOfPoints.hxx>
17 #include <Graphic3d_ArrayOfPolylines.hxx>
18 #include <Graphic3d_ArrayOfSegments.hxx>
19 #include <Graphic3d_AspectLine3d.hxx>
20 #include <Graphic3d_AspectMarker3d.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_CircularGrid,Aspect_CircularGrid)
30
31 namespace
32 {
33   static const Standard_Real THE_DEFAULT_GRID_STEP = 10.0;
34   #define DIVISION 8
35   #define MYFACTOR 50.
36 }
37
38 //! Dummy implementation of Graphic3d_Structure overriding ::Compute() method for handling Device Lost.
39 class V3d_CircularGrid::CircularGridStructure : public Graphic3d_Structure
40 {
41 public:
42   //! Main constructor.
43   CircularGridStructure (const Handle(Graphic3d_StructureManager)& theManager, V3d_CircularGrid* theGrid)
44   : Graphic3d_Structure (theManager), myGrid (theGrid) {}
45
46   //! Override method initiating recomputing in V3d_CircularGrid.
47   virtual void Compute() Standard_OVERRIDE
48   {
49     GraphicClear (Standard_False);
50     myGrid->myGroup = NewGroup();
51     myGrid->myCurAreDefined = Standard_False;
52     myGrid->UpdateDisplay();
53   }
54
55 private:
56   V3d_CircularGrid* myGrid;
57 };
58
59 /*----------------------------------------------------------------------*/
60
61 V3d_CircularGrid::V3d_CircularGrid (const V3d_ViewerPointer& aViewer, const Quantity_Color& aColor, const Quantity_Color& aTenthColor)
62 : Aspect_CircularGrid (1.,8),
63   myViewer (aViewer),
64   myCurAreDefined (Standard_False),
65   myToComputePrs (Standard_False),
66   myCurDrawMode (Aspect_GDM_Lines),
67   myCurXo (0.0),
68   myCurYo (0.0),
69   myCurAngle (0.0),
70   myCurStep (0.0),
71   myCurDivi (0),
72   myRadius (0.5 * aViewer->DefaultViewSize()),
73   myOffSet (THE_DEFAULT_GRID_STEP / MYFACTOR)
74 {
75   myColor = aColor;
76   myTenthColor = aTenthColor;
77
78   myStructure = new CircularGridStructure (aViewer->StructureManager(), this);
79   myGroup = myStructure->NewGroup();
80   myStructure->SetInfiniteState (Standard_True);
81
82   SetRadiusStep (THE_DEFAULT_GRID_STEP);
83 }
84
85 V3d_CircularGrid::~V3d_CircularGrid()
86 {
87   myGroup.Nullify();
88   if (!myStructure.IsNull())
89   {
90     myStructure->Erase();
91   }
92 }
93
94 void V3d_CircularGrid::SetColors (const Quantity_Color& aColor, const Quantity_Color& aTenthColor)
95 {
96   if( myColor != aColor || myTenthColor != aTenthColor ) {
97     myColor = aColor;
98     myTenthColor = aTenthColor;
99     myCurAreDefined = Standard_False;
100     UpdateDisplay();
101   }
102 }
103
104 void V3d_CircularGrid::Display ()
105 {
106   myStructure->SetDisplayPriority (1);
107   myStructure->Display();
108   UpdateDisplay();
109 }
110
111 void V3d_CircularGrid::Erase () const
112 {
113   myStructure->Erase ();
114 }
115
116 Standard_Boolean V3d_CircularGrid::IsDisplayed () const
117 {
118   return myStructure->IsDisplayed ();
119 }
120
121 void V3d_CircularGrid::UpdateDisplay ()
122 {
123   gp_Ax3 ThePlane = myViewer->PrivilegedPlane();
124
125   Standard_Real xl, yl, zl;
126   Standard_Real xdx, xdy, xdz;
127   Standard_Real ydx, ydy, ydz;
128   Standard_Real dx, dy, dz;
129   ThePlane.Location ().Coord (xl, yl, zl);
130   ThePlane.XDirection ().Coord (xdx, xdy, xdz);
131   ThePlane.YDirection ().Coord (ydx, ydy, ydz);
132   ThePlane.Direction ().Coord (dx, dy, dz);
133
134   Standard_Boolean MakeTransform = !myCurAreDefined;
135   if (!MakeTransform)
136   {
137     MakeTransform = (RotationAngle() != myCurAngle || XOrigin() != myCurXo || YOrigin() != myCurYo);
138     if (!MakeTransform)
139     {
140       Standard_Real curxl, curyl, curzl;
141       Standard_Real curxdx, curxdy, curxdz;
142       Standard_Real curydx, curydy, curydz;
143       Standard_Real curdx, curdy, curdz;
144       myCurViewPlane.Location ().Coord (curxl, curyl, curzl);
145       myCurViewPlane.XDirection ().Coord (curxdx, curxdy, curxdz);
146       myCurViewPlane.YDirection ().Coord (curydx, curydy, curydz);
147       myCurViewPlane.Direction ().Coord (curdx, curdy, curdz);
148       if (xl != curxl || yl != curyl || zl != curzl ||
149           xdx != curxdx || xdy != curxdy || xdz != curxdz ||
150           ydx != curydx || ydy != curydy || ydz != curydz ||
151           dx != curdx || dy != curdy || dz != curdz)
152         MakeTransform = Standard_True;
153     }
154   }
155
156   if (MakeTransform)
157   {
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_CircularGrid::DefineLines ()
200 {
201   const Standard_Real    aStep     = RadiusStep ();
202   const Standard_Real    aDivision = DivisionNumber ();
203   const Standard_Boolean toUpdate  = !myCurAreDefined
204                                   || myCurDrawMode != Aspect_GDM_Lines
205                                   || aDivision != myCurDivi
206                                   || aStep     != myCurStep;
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   const Standard_Integer Division = (Standard_Integer )( (aDivision >= DIVISION ? aDivision : DIVISION));
222
223   Standard_Integer nbpnts = 2 * Division;
224   // diametres
225   Standard_Real alpha = M_PI / aDivision;
226
227   myGroup->SetGroupPrimitivesAspect (new Graphic3d_AspectLine3d (myTenthColor, Aspect_TOL_SOLID, 1.0));
228   Handle(Graphic3d_ArrayOfSegments) aPrims1 = new Graphic3d_ArrayOfSegments(2*nbpnts);
229   const gp_Pnt p0(0., 0., -myOffSet);
230   for (Standard_Integer i=1; i<=nbpnts; i++) {
231     aPrims1->AddVertex(p0);
232     aPrims1->AddVertex(Cos(alpha*i)*myRadius, Sin(alpha*i)*myRadius, -myOffSet);
233   }
234   myGroup->AddPrimitiveArray(aPrims1, Standard_False);
235
236   // circles
237   nbpnts = 2 * Division + 1;
238   alpha = M_PI / Division;
239   Standard_Integer nblines = 0;
240   TColgp_SequenceOfPnt aSeqLines, aSeqTenth;
241   for (Standard_Real r=aStep; r<=myRadius; r+=aStep, nblines++) {
242     const Standard_Boolean isTenth = (Modulus(nblines, 10) == 0);
243     for (Standard_Integer i=0; i<nbpnts; i++) {
244       const gp_Pnt pt(Cos(alpha*i)*r,Sin(alpha*i)*r,-myOffSet);
245       (isTenth? aSeqTenth : aSeqLines).Append(pt);
246     }
247   }
248   if (aSeqTenth.Length())
249   {
250     myGroup->SetGroupPrimitivesAspect (new Graphic3d_AspectLine3d (myTenthColor, Aspect_TOL_SOLID, 1.0));
251     Standard_Integer n, np;
252     const Standard_Integer nbl = aSeqTenth.Length() / nbpnts;
253     Handle(Graphic3d_ArrayOfPolylines) aPrims2 = new Graphic3d_ArrayOfPolylines(aSeqTenth.Length(),nbl);
254     for (np = 1, n=0; n<nbl; n++) {
255       aPrims2->AddBound(nbpnts);
256       for (Standard_Integer i=0; i<nbpnts; i++, np++)
257         aPrims2->AddVertex(aSeqTenth(np));
258   }
259     myGroup->AddPrimitiveArray(aPrims2, Standard_False);
260   }
261   if (aSeqLines.Length())
262   {
263     myGroup->SetPrimitivesAspect (new Graphic3d_AspectLine3d (myColor, Aspect_TOL_SOLID, 1.0));
264     Standard_Integer n, np;
265     const Standard_Integer nbl = aSeqLines.Length() / nbpnts;
266     Handle(Graphic3d_ArrayOfPolylines) aPrims3 = new Graphic3d_ArrayOfPolylines(aSeqLines.Length(),nbl);
267     for (np = 1, n=0; n<nbl; n++) {
268       aPrims3->AddBound(nbpnts);
269       for (Standard_Integer i=0; i<nbpnts; i++, np++)
270         aPrims3->AddVertex(aSeqLines(np));
271   }
272     myGroup->AddPrimitiveArray(aPrims3, Standard_False);
273   }
274
275   myGroup->SetMinMaxValues (-myRadius, -myRadius, -myOffSet, myRadius, myRadius, -myOffSet);
276   myCurStep = aStep, myCurDivi = (Standard_Integer ) aDivision;
277
278   // update bounding box
279   myStructure->CalculateBoundBox();
280   myViewer->StructureManager()->Update (myStructure->GetZLayer());
281 }
282
283 void V3d_CircularGrid::DefinePoints ()
284 {
285   const Standard_Real    aStep     = RadiusStep();
286   const Standard_Real    aDivision = DivisionNumber();
287   const Standard_Boolean toUpdate  = !myCurAreDefined
288                                   || myCurDrawMode != Aspect_GDM_Points
289                                   || aDivision != myCurDivi
290                                   || aStep     != myCurStep;
291   if (!toUpdate
292    && !myToComputePrs)
293   {
294     return;
295   }
296   else if (!myStructure->IsDisplayed())
297   {
298     myToComputePrs = Standard_True;
299     return;
300   }
301
302   myToComputePrs = Standard_False;
303   myGroup->Clear ();
304
305   Handle(Graphic3d_AspectMarker3d) MarkerAttrib = new Graphic3d_AspectMarker3d ();
306   MarkerAttrib->SetColor (myColor);
307   MarkerAttrib->SetType (Aspect_TOM_POINT);
308   MarkerAttrib->SetScale (3.);
309
310   const Standard_Integer nbpnts = Standard_Integer (2*aDivision);
311   Standard_Real r, alpha = M_PI / aDivision;
312
313   // diameters
314   TColgp_SequenceOfPnt aSeqPnts;
315   aSeqPnts.Append(gp_Pnt(0.0, 0.0, -myOffSet));
316   for (r=aStep; r<=myRadius; r+=aStep) {
317     for (Standard_Integer i=0; i<nbpnts; i++)
318       aSeqPnts.Append(gp_Pnt(Cos(alpha*i)*r, Sin(alpha*i)*r, -myOffSet));
319   }
320   myGroup->SetGroupPrimitivesAspect (MarkerAttrib);
321   if (aSeqPnts.Length())
322   {
323     Standard_Real X,Y,Z;
324     const Standard_Integer nbv = aSeqPnts.Length();
325     Handle(Graphic3d_ArrayOfPoints) Cercle = new Graphic3d_ArrayOfPoints (nbv);
326     for (Standard_Integer i=1; i<=nbv; i++)
327     {
328       aSeqPnts(i).Coord(X,Y,Z);
329       Cercle->AddVertex (X,Y,Z);
330     }
331     myGroup->AddPrimitiveArray (Cercle, Standard_False);
332   }
333   myGroup->SetMinMaxValues (-myRadius, -myRadius, -myOffSet, myRadius, myRadius, -myOffSet);
334
335   myCurStep = aStep, myCurDivi = (Standard_Integer ) aDivision;
336
337   // update bounding box
338   myStructure->CalculateBoundBox();
339   myViewer->StructureManager()->Update (myStructure->GetZLayer());
340 }
341
342 void V3d_CircularGrid::GraphicValues (Standard_Real& theRadius, Standard_Real& theOffSet) const
343 {
344   theRadius = myRadius;
345   theOffSet = myOffSet;
346 }
347
348 void V3d_CircularGrid::SetGraphicValues (const Standard_Real theRadius, const Standard_Real theOffSet)
349 {
350   if (! myCurAreDefined) {
351     myRadius = theRadius;
352     myOffSet = theOffSet;
353   }
354   if (myRadius != theRadius) {
355     myRadius = theRadius;
356     myCurAreDefined = Standard_False;
357   }
358   if (myOffSet != theOffSet) {
359     myOffSet = theOffSet;
360     myCurAreDefined = Standard_False;
361   }
362   if( !myCurAreDefined ) UpdateDisplay();
363 }