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