567cb885d80816a89483268981ad10f3edbc3a9b
[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 #define DIVISION 8
32 #define MYFACTOR 50.
33
34 //! Dummy implementation of Graphic3d_Structure overriding ::Compute() method for handling Device Lost.
35 class V3d_CircularGrid::CircularGridStructure : public Graphic3d_Structure
36 {
37 public:
38   //! Main constructor.
39   CircularGridStructure (const Handle(Graphic3d_StructureManager)& theManager, V3d_CircularGrid* theGrid)
40   : Graphic3d_Structure (theManager), myGrid (theGrid) {}
41
42   //! Override method initiating recomputing in V3d_CircularGrid.
43   virtual void Compute() Standard_OVERRIDE
44   {
45     GraphicClear (Standard_False);
46     myGrid->myGroup = NewGroup();
47     myGrid->myCurAreDefined = Standard_False;
48     myGrid->UpdateDisplay();
49   }
50
51 private:
52   V3d_CircularGrid* myGrid;
53 };
54
55 /*----------------------------------------------------------------------*/
56
57 V3d_CircularGrid::V3d_CircularGrid (const V3d_ViewerPointer& aViewer, const Quantity_Color& aColor, const Quantity_Color& aTenthColor)
58 : Aspect_CircularGrid (1.,8),
59   myViewer (aViewer),
60   myCurAreDefined (Standard_False),
61   myToComputePrs (Standard_False)
62 {
63   myColor = aColor;
64   myTenthColor = aTenthColor;
65
66   myStructure = new CircularGridStructure (aViewer->StructureManager(), this);
67   myGroup = myStructure->NewGroup();
68   myStructure->SetInfiniteState (Standard_True);
69
70   const Standard_Real step = 10.;
71   const Standard_Real size = 0.5*myViewer->DefaultViewSize();
72   SetGraphicValues (size, step/MYFACTOR);
73   SetRadiusStep (step);
74 }
75
76 V3d_CircularGrid::~V3d_CircularGrid()
77 {
78   myGroup.Nullify();
79   if (!myStructure.IsNull())
80   {
81     myStructure->Erase();
82   }
83 }
84
85 void V3d_CircularGrid::SetColors (const Quantity_Color& aColor, const Quantity_Color& aTenthColor)
86 {
87   if( myColor != aColor || myTenthColor != aTenthColor ) {
88     myColor = aColor;
89     myTenthColor = aTenthColor;
90     myCurAreDefined = Standard_False;
91     UpdateDisplay();
92   }
93 }
94
95 void V3d_CircularGrid::Display ()
96 {
97   myStructure->SetDisplayPriority (1);
98   myStructure->Display();
99   UpdateDisplay();
100 }
101
102 void V3d_CircularGrid::Erase () const
103 {
104   myStructure->Erase ();
105 }
106
107 Standard_Boolean V3d_CircularGrid::IsDisplayed () const
108 {
109   return myStructure->IsDisplayed ();
110 }
111
112 void V3d_CircularGrid::UpdateDisplay ()
113 {
114   gp_Ax3 ThePlane = myViewer->PrivilegedPlane();
115
116   Standard_Real xl, yl, zl;
117   Standard_Real xdx, xdy, xdz;
118   Standard_Real ydx, ydy, ydz;
119   Standard_Real dx, dy, dz;
120   ThePlane.Location ().Coord (xl, yl, zl);
121   ThePlane.XDirection ().Coord (xdx, xdy, xdz);
122   ThePlane.YDirection ().Coord (ydx, ydy, ydz);
123   ThePlane.Direction ().Coord (dx, dy, dz);
124
125   Standard_Boolean MakeTransform = !myCurAreDefined;
126   if (!MakeTransform)
127   {
128     MakeTransform = (RotationAngle() != myCurAngle || XOrigin() != myCurXo || YOrigin() != myCurYo);
129     if (!MakeTransform)
130     {
131       Standard_Real curxl, curyl, curzl;
132       Standard_Real curxdx, curxdy, curxdz;
133       Standard_Real curydx, curydy, curydz;
134       Standard_Real curdx, curdy, curdz;
135       myCurViewPlane.Location ().Coord (curxl, curyl, curzl);
136       myCurViewPlane.XDirection ().Coord (curxdx, curxdy, curxdz);
137       myCurViewPlane.YDirection ().Coord (curydx, curydy, curydz);
138       myCurViewPlane.Direction ().Coord (curdx, curdy, curdz);
139       if (xl != curxl || yl != curyl || zl != curzl ||
140           xdx != curxdx || xdy != curxdy || xdz != curxdz ||
141           ydx != curydx || ydy != curydy || ydz != curydz ||
142           dx != curdx || dy != curdy || dz != curdz)
143         MakeTransform = Standard_True;
144     }
145   }
146
147   if (MakeTransform)
148   {
149     const Standard_Real CosAlpha = Cos (RotationAngle ());
150     const Standard_Real SinAlpha = Sin (RotationAngle ());
151
152     gp_Trsf aTrsf;
153     // Translation
154     // Transformation of change of marker
155     aTrsf.SetValues (xdx, ydx, dx, xl,
156                      xdy, ydy, dy, yl,
157                      xdz, ydz, dz, zl);
158
159     // Translation of the origin
160     // Rotation Alpha around axis -Z
161     gp_Trsf aTrsf2;
162     aTrsf2.SetValues ( CosAlpha, SinAlpha, 0.0, -XOrigin(),
163                       -SinAlpha, CosAlpha, 0.0, -YOrigin(),
164                             0.0,      0.0, 1.0, 0.0);
165     aTrsf.Multiply (aTrsf2);
166     myStructure->SetTransformation (new Geom_Transformation (aTrsf));
167
168     myCurAngle = RotationAngle ();
169     myCurXo = XOrigin (), myCurYo = YOrigin ();
170     myCurViewPlane = ThePlane;
171   }
172
173   switch (myDrawMode)
174   {
175     case Aspect_GDM_Points:
176       DefinePoints ();
177       myCurDrawMode = Aspect_GDM_Points;
178       break;
179     case Aspect_GDM_Lines:
180       DefineLines ();
181       myCurDrawMode = Aspect_GDM_Lines;
182       break;
183     case Aspect_GDM_None:
184       myCurDrawMode = Aspect_GDM_None;
185       break;
186   }
187   myCurAreDefined = Standard_True;
188 }
189
190 void V3d_CircularGrid::DefineLines ()
191 {
192   const Standard_Real    aStep     = RadiusStep ();
193   const Standard_Real    aDivision = DivisionNumber ();
194   const Standard_Boolean toUpdate  = !myCurAreDefined
195                                   || myCurDrawMode != Aspect_GDM_Lines
196                                   || aDivision != myCurDivi
197                                   || aStep     != myCurStep;
198   if (!toUpdate
199    && !myToComputePrs)
200   {
201     return;
202   }
203   else if (!myStructure->IsDisplayed())
204   {
205     myToComputePrs = Standard_True;
206     return;
207   }
208
209   myToComputePrs = Standard_False;
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   // update bounding box
270   myStructure->CalculateBoundBox();
271   myViewer->StructureManager()->Update (myStructure->GetZLayer());
272 }
273
274 void V3d_CircularGrid::DefinePoints ()
275 {
276   const Standard_Real    aStep     = RadiusStep();
277   const Standard_Real    aDivision = DivisionNumber();
278   const Standard_Boolean toUpdate  = !myCurAreDefined
279                                   || myCurDrawMode != Aspect_GDM_Points
280                                   || aDivision != myCurDivi
281                                   || aStep     != myCurStep;
282   if (!toUpdate
283    && !myToComputePrs)
284   {
285     return;
286   }
287   else if (!myStructure->IsDisplayed())
288   {
289     myToComputePrs = Standard_True;
290     return;
291   }
292
293   myToComputePrs = Standard_False;
294   myGroup->Clear ();
295
296   Handle(Graphic3d_AspectMarker3d) MarkerAttrib = new Graphic3d_AspectMarker3d ();
297   MarkerAttrib->SetColor (myColor);
298   MarkerAttrib->SetType (Aspect_TOM_POINT);
299   MarkerAttrib->SetScale (3.);
300
301   const Standard_Integer nbpnts = Standard_Integer (2*aDivision);
302   Standard_Real r, alpha = M_PI / aDivision;
303
304   // diameters
305   TColgp_SequenceOfPnt aSeqPnts;
306   aSeqPnts.Append(gp_Pnt(0.0, 0.0, -myOffSet));
307   for (r=aStep; r<=myRadius; r+=aStep) {
308     for (Standard_Integer i=0; i<nbpnts; i++)
309       aSeqPnts.Append(gp_Pnt(Cos(alpha*i)*r, Sin(alpha*i)*r, -myOffSet));
310   }
311   myGroup->SetGroupPrimitivesAspect (MarkerAttrib);
312   if (aSeqPnts.Length())
313   {
314     Standard_Real X,Y,Z;
315     const Standard_Integer nbv = aSeqPnts.Length();
316     Handle(Graphic3d_ArrayOfPoints) Cercle = new Graphic3d_ArrayOfPoints (nbv);
317     for (Standard_Integer i=1; i<=nbv; i++)
318     {
319       aSeqPnts(i).Coord(X,Y,Z);
320       Cercle->AddVertex (X,Y,Z);
321     }
322     myGroup->AddPrimitiveArray (Cercle, Standard_False);
323   }
324   myGroup->SetMinMaxValues(-myRadius, -myRadius, 0.0, myRadius, myRadius, 0.0);
325
326   myCurStep = aStep, myCurDivi = (Standard_Integer ) aDivision;
327
328   // update bounding box
329   myStructure->CalculateBoundBox();
330   myViewer->StructureManager()->Update (myStructure->GetZLayer());
331 }
332
333 void V3d_CircularGrid::GraphicValues (Standard_Real& theRadius, Standard_Real& theOffSet) const
334 {
335   theRadius = myRadius;
336   theOffSet = myOffSet;
337 }
338
339 void V3d_CircularGrid::SetGraphicValues (const Standard_Real theRadius, const Standard_Real theOffSet)
340 {
341   if (! myCurAreDefined) {
342     myRadius = theRadius;
343     myOffSet = theOffSet;
344   }
345   if (myRadius != theRadius) {
346     myRadius = theRadius;
347     myCurAreDefined = Standard_False;
348   }
349   if (myOffSet != theOffSet) {
350     myOffSet = theOffSet;
351     myCurAreDefined = Standard_False;
352   }
353   if( !myCurAreDefined ) UpdateDisplay();
354 }