vtkPolarAxesActor.cxx 26.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPolarAxesActor.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

 =========================================================================*/
#include "vtkPolarAxesActor.h"

17
#include "vtkArcSource.h"
18
19
20
#include "vtkAxisActor.h"
#include "vtkAxisFollower.h"
#include "vtkCamera.h"
21
#include "vtkCellArray.h"
22
23
24
25
#include "vtkCoordinate.h"
#include "vtkFollower.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
26
27
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
28
29
#include "vtkProperty.h"
#include "vtkStringArray.h"
30
#include "vtkTextProperty.h"
31
32
#include "vtkViewport.h"

33
#include <vtksys/ios/sstream>
34

35
#define VTK_POLAR_AXES_ACTOR_RTOL ( 1. - 10. * VTK_DBL_EPSILON )
36

37
38
vtkStandardNewMacro(vtkPolarAxesActor);
vtkCxxSetObjectMacro(vtkPolarAxesActor, Camera,vtkCamera);
39
40
vtkCxxSetObjectMacro(vtkPolarAxesActor,PolarAxisLabelTextProperty,vtkTextProperty);
vtkCxxSetObjectMacro(vtkPolarAxesActor,PolarAxisTitleTextProperty,vtkTextProperty);
41

Aashish Chaudhary's avatar
Aashish Chaudhary committed
42
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
43
void vtkPolarAxesActor::PrintSelf( ostream& os, vtkIndent indent )
44
{
Philippe Pébay's avatar
Philippe Pébay committed
45
  this->Superclass::PrintSelf( os,indent );
46

47
48
  os << indent << "Bounds: \n";
  os << indent << "  Xmin,Xmax: (" << this->Bounds[0] << ", "
49
     << this->Bounds[1] << " )\n";
50
  os << indent << "  Ymin,Ymax: (" << this->Bounds[2] << ", "
51
     << this->Bounds[3] << " )\n";
52
  os << indent << "  Zmin,Zmax: (" << this->Bounds[4] << ", "
53
     << this->Bounds[5] << " )\n";
54

Philippe Pébay's avatar
Philippe Pébay committed
55
56
  os << indent << "ScreenSize: (" << this->ScreenSize << ")\n";

57
  os << indent << "Number Of Radial Axes" << this->NumberOfRadialAxes << endl;
58
59
60
  os << indent << "Number Of Polar Axis Ticks" << this->NumberOfPolarAxisTicks << endl;
  os << indent << "Auto Subdivide Polar Axis: "
     << ( this->AutoSubdividePolarAxis ? "On\n" : "Off\n" );
61

Aashish Chaudhary's avatar
Aashish Chaudhary committed
62
  os << indent << "Pole: ("
63
64
     << this->Pole[0] << ", "
     << this->Pole[1] << ", "
65
     << this->Pole[2] << " )\n";
66

67
  os << indent << "Maximum Radius" << this->MaximumRadius << endl;
68
  os << indent << "Auto-Scale Radius" << this->AutoScaleRadius << endl;
69
  os << indent << "Minimum Angle" << this->MinimumAngle << endl;
70
  os << indent << "Maximum Angle" << this->MaximumAngle << endl;
Philippe Pébay's avatar
Philippe Pébay committed
71
72
  os << indent << "Radial Units (degrees): "
     << ( this->RadialUnits ? "On\n" : "Off\n" ) << endl;
73

Philippe Pébay's avatar
Philippe Pébay committed
74
  if ( this->Camera )
75
76
    {
    os << indent << "Camera:\n";
Philippe Pébay's avatar
Philippe Pébay committed
77
    this->Camera->PrintSelf( os,indent.GetNextIndent() );
78
79
80
81
82
83
    }
  else
    {
    os << indent << "Camera: (none)\n";
    }

Philippe Pébay's avatar
Philippe Pébay committed
84
  os << indent << "Polar Axis Title: " << this->PolarAxisTitle << "\n";
85
  os << indent << "Polar Label Format: " << this->PolarLabelFormat << "\n";
Philippe Pébay's avatar
Philippe Pébay committed
86
87
  os << indent << "PolarAxisLabelTextProperty: " << this->PolarAxisLabelTextProperty << endl;
  os << indent << "PolarAxisTitleTextProperty: " << this->PolarAxisTitleTextProperty << endl;
88
89
90
91
92
93
94
95
  os << indent << "Polar Axis Visibility: "
     << ( this->PolarAxisVisibility ? "On\n" : "Off\n" );
  os << indent << "Polar Title Visibility: "
     << ( this->PolarTitleVisibility ? "On" : "Off" ) << endl;
  os << indent << "Polar Label Visibility: "
     << ( this->PolarLabelVisibility ? "On" : "Off" ) << endl;
  os << indent << "Polar Tick Visibility: "
     << ( this->PolarTickVisibility ? "On" : "Off" ) << endl;
96
97

  os << indent << "Radial Axes Visibility: "
98
     << ( this->RadialAxesVisibility ? "On\n" : "Off\n" );
99
100
  os << indent << "Radial Title Visibility: "
     << ( this->RadialTitleVisibility ? "On" : "Off" ) << endl;
101

102

103
104
105
  os << indent << "Polar Arcs Visibility: "
     << ( this->PolarArcsVisibility ? "On" : "Off" ) << endl;

106

107
  os << indent << "Tick Location: " << this->TickLocation << endl;
108
109
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
110
//-----------------------------------------------------------------------------
111
112
vtkPolarAxesActor::vtkPolarAxesActor() : vtkActor()
{
113
114
115
116
117
  // Default bounds
  this->Bounds[0] = -1.0; this->Bounds[1] = 1.0;
  this->Bounds[2] = -1.0; this->Bounds[3] = 1.0;
  this->Bounds[4] = -1.0; this->Bounds[5] = 1.0;

118
  // Default pole coordinates
119
120
121
  this->Pole[0] = VTK_DOUBLE_MAX;
  this->Pole[1] = VTK_DOUBLE_MAX;
  this->Pole[2] = VTK_DOUBLE_MAX;
122

123
  // Default number of radial axes
124
  this->NumberOfRadialAxes = VTK_MAXIMUM_NUMBER_OF_RADIAL_AXES;
125

126
127
128
129
  // Invalid default number of polar arcs, and auto-calculate by default
  this->NumberOfPolarAxisTicks = -1;
  this->AutoSubdividePolarAxis = true;

130
131
132
  // Default maximum polar radius
  this->MaximumRadius = VTK_DOUBLE_MAX;

133
134
135
  // Do not auto-scale radius by default
  this->AutoScaleRadius = false;

136
137
138
  // Default minimum polar angle
  this->MinimumAngle = 0.;

139
140
141
142
  // Default maximum polar angle
  this->MaximumAngle = VTK_DEFAULT_MAXIMUM_POLAR_ANGLE;

  // By default show angle units (degrees)
143
  this->RadialUnits = true;
144
145
146

  this->Camera = NULL;

147
  // Default text screen size
148
149
  this->ScreenSize = 10.0;

150
151
  // Screen offset for labels
  // Pivot point at center of the geometry hence this->ScreenSize * 0.5
Philippe Pébay's avatar
Philippe Pébay committed
152
  this->LabelScreenOffset = 15.0 + this->ScreenSize * 0.5;
153

154
  // Text properties of polar axis title and labels, with default color white
155
156
157
  // Properties of the radial axes, with default color black
  this->PolarAxisProperty = vtkProperty::New();
  this->PolarAxisProperty->SetColor( 0., 0., 0. );
Philippe Pébay's avatar
Philippe Pébay committed
158
  this->PolarAxisTitleTextProperty = vtkTextProperty::New();
159
  this->PolarAxisTitleTextProperty->SetColor( 1., 1. ,1. );
Philippe Pébay's avatar
Philippe Pébay committed
160
161
  this->PolarAxisTitleTextProperty->SetFontFamilyToArial();
  this->PolarAxisLabelTextProperty = vtkTextProperty::New();
162
  this->PolarAxisLabelTextProperty->SetColor( 1., 1. ,1. );
Philippe Pébay's avatar
Philippe Pébay committed
163
164
  this->PolarAxisLabelTextProperty->SetFontFamilyToArial();

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  // Create and set polar axis of type X
  this->PolarAxis = vtkAxisActor::New();
  this->PolarAxis->SetAxisTypeToX();
  this->PolarAxis->SetAxisPositionToMinMax();
  this->PolarAxis->SetCalculateTitleOffset( 0 );
  this->PolarAxis->SetCalculateLabelOffset( 0 );

  // Base offset for followers
  double offset = this->LabelScreenOffset + this->ScreenSize * 0.5;

  // Using twice the base offset and a little for the title of the polar axis.
  vtkAxisFollower* follower = this->PolarAxis->GetTitleActor();
  follower->SetAxis( this->PolarAxis );
  follower->SetScreenOffset( 2.0 * offset + 5 );

180
  vtkAxisFollower** labelActors = this->PolarAxis->GetLabelActors();
181
182
183
184
185
186
187
188
189
190
191
  int numberOfLabels = this->PolarAxis->GetNumberOfLabelsBuilt();
  for( int i = 0; i < numberOfLabels; ++ i )
    {
    labelActors[i]->SetScreenOffset( offset );
    }

  // Properties of the radial axes, with default color black
  this->RadialAxesProperty = vtkProperty::New();
  this->RadialAxesProperty->SetColor( 0., 0., 0. );

  // Create and set radial axes of type X
192
193
  this->RadialAxes = new vtkAxisActor*[VTK_MAXIMUM_NUMBER_OF_RADIAL_AXES];
  for ( int i = 0; i < VTK_MAXIMUM_NUMBER_OF_RADIAL_AXES; ++ i )
194
    {
195
    // Create axis of type X
196
    this->RadialAxes[i] = vtkAxisActor::New();
197
198
    vtkAxisActor* axis = this->RadialAxes[i];
    axis->SetAxisTypeToX();
199
200
    axis->SetAxisPositionToMinMax();
    axis->SetCalculateTitleOffset( 0 );
201
    axis->SetCalculateLabelOffset( 0 );
202

203
204
205
206
    // Using 2/3 of base offset if not for non-polar radial axes.
    axis->GetTitleActor()->SetAxis( axis );
    axis->GetTitleActor()->SetScreenOffset( .67 * offset );
    } // for ( int i = 0; i < VTK_MAXIMUM_NUMBER_OF_RADIAL_AXES; ++ i )
207
208

  // Default tick location, defined in vtkAxisActor
209
  this->TickLocation = VTK_TICKS_BOTH;
210

211
  // Create and set polar arcs and ancillary objects, with default color white
212
213
214
215
216
  this->PolarArcs = vtkPolyData::New();
  this->PolarArcsMapper = vtkPolyDataMapper::New();
  this->PolarArcsMapper->SetInput( this->PolarArcs );
  this->PolarArcsActor = vtkActor::New();
  this->PolarArcsActor->SetMapper( this->PolarArcsMapper );
217
  this->PolarArcsActor->GetProperty()->SetColor( 1., 1., 1. );
218

219
220
221
  // Default title for polar axis (can also be called "Radius")
  this->PolarAxisTitle = new char[16];
  sprintf(this->PolarAxisTitle, "%s", "Radial Distance");
222
223
  this->PolarLabelFormat = new char[8];
  sprintf( this->PolarLabelFormat, "%s", "%-#6.3g" );
224

225
226
227
228
229
230
231
232
233
234
235
236
  // By default all polar axis features are visible
  this->PolarAxisVisibility = 1;
  this->PolarTitleVisibility = 1;
  this->PolarLabelVisibility = 1;
  this->PolarTickVisibility = 1;

  // By default all radial axes features are visible
  this->RadialAxesVisibility = 1;
  this->RadialTitleVisibility = 1;

  // By default polar arcs are visible
  this->PolarArcsVisibility = 1;
237
238
239
240
241
242

  this->RenderCount = 0;

  this->RenderSomething = 0;

  this->LabelScale = -1.0;
243
  this->TitleScale = -1.0;
244
245
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
246
//-----------------------------------------------------------------------------
247
248
249
250
vtkPolarAxesActor::~vtkPolarAxesActor()
{
  this->SetCamera( NULL );

251
252
253
254
255
  if ( this->PolarAxisProperty )
    {
    this->PolarAxisProperty->Delete();
    }

Philippe Pébay's avatar
Philippe Pébay committed
256
  if ( this->RadialAxesProperty )
257
258
259
260
    {
    this->RadialAxesProperty->Delete();
    }

261
  if ( this->PolarLabelFormat )
262
    {
263
264
    delete [] this->PolarLabelFormat;
    this->PolarLabelFormat = NULL;
265
    }
Philippe Pébay's avatar
Philippe Pébay committed
266

Philippe Pébay's avatar
Philippe Pébay committed
267
  if ( this->PolarAxisTitle )
268
269
270
271
272
    {
    delete [] this->PolarAxisTitle;
    this->PolarAxisTitle = NULL;
    }

Philippe Pébay's avatar
Philippe Pébay committed
273
274
275
276
277
278
279
280
281
282
283
284
  if ( this->PolarAxisTitleTextProperty )
    {
    this->PolarAxisTitleTextProperty->Delete();
    this->PolarAxisTitleTextProperty = NULL;
    }

  if ( this->PolarAxisLabelTextProperty )
    {
    this->PolarAxisLabelTextProperty->Delete();
    this->PolarAxisLabelTextProperty = NULL;
    }

285
286
287
288
289
290
  if ( this->PolarAxis )
    {
    this->PolarAxis->Delete();
    this->PolarAxis = NULL;
    }

Philippe Pébay's avatar
Philippe Pébay committed
291
292
  if ( this->RadialAxes )
    {
293
    for ( int i = 0; i < VTK_MAXIMUM_NUMBER_OF_RADIAL_AXES; ++ i )
Philippe Pébay's avatar
Philippe Pébay committed
294
295
296
297
298
299
300
301
302
303
      {
      if ( this->RadialAxes[i] )
        {
        this->RadialAxes[i]->Delete();
        this->RadialAxes[i] = NULL;
        }
      }
    delete [] this->RadialAxes;
    this->RadialAxes = NULL;
    }
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320

  if (this->PolarArcs)
    {
    this->PolarArcs->Delete();
    this->PolarArcs = NULL;
    }
  if (this->PolarArcsMapper)
    {
    this->PolarArcsMapper->Delete();
    this->PolarArcsMapper = NULL;
    }
  if (this->PolarArcsActor)
    {
    this->PolarArcsActor->Delete();
    this->PolarArcsActor = NULL;
    }

321
322
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
323
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
324
int vtkPolarAxesActor::RenderOpaqueGeometry( vtkViewport *viewport )
325
326
327
{
  // Initialization
  static bool initialRender = true;
328
  if ( !this->Camera )
329
330
331
332
333
334
335
336
    {
    vtkErrorMacro( <<"No camera!" );
    this->RenderSomething = 0;
    return 0;
    }

  this->BuildAxes( viewport );

337
  if ( initialRender )
338
    {
339
340
    this->PolarAxis->BuildAxis( viewport, true );

341
342
    for ( int i = 0; i < this->NumberOfRadialAxes; ++ i )
      {
Philippe Pébay's avatar
Philippe Pébay committed
343
      this->RadialAxes[i]->BuildAxis( viewport, true );
344
345
346
347
348
      }
    }
  initialRender = false;

  int renderedSomething = 0;
349
350
351
352
353
354
355
356

  // Render the polar axis
  if ( this->PolarAxisVisibility )
    {
    renderedSomething += this->PolarAxis->RenderOpaqueGeometry( viewport );
    }

  // Render the radial axes
357
358
359
360
  if ( this->RadialAxesVisibility )
    {
    for ( int i = 0; i < this->NumberOfRadialAxes; ++ i )
      {
361
      renderedSomething += this->RadialAxes[i]->RenderOpaqueGeometry( viewport );
362
363
364
      }
    }

365
366
367
368
369
370
  // Render the polar arcs
  if ( this->PolarArcsVisibility )
    {
    renderedSomething += this->PolarArcsActor->RenderOpaqueGeometry(viewport);
    }

371
372
373
  return renderedSomething;
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
374
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
375
void vtkPolarAxesActor::SetScreenSize( double screenSize )
376
377
{
  this->ScreenSize = screenSize;
378
379
  // Considering pivot point at center of the geometry,
  // hence ( this->ScreenSize * 0.5 ).
Philippe Pébay's avatar
Philippe Pébay committed
380
  this->LabelScreenOffset = 15.0 + this->ScreenSize * 0.5;
381

382
383
384
  vtkAxisFollower** labelActors = this->PolarAxis->GetLabelActors();
  int numberOfLabels = this->PolarAxis->GetNumberOfLabelsBuilt();
  for( int i = 0; i < numberOfLabels; ++ i )
385
    {
386
    labelActors[i]->SetScreenOffset( this->LabelScreenOffset );
387
388
389
390
391
    }

  this->Modified();
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
392
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
393
void vtkPolarAxesActor::ReleaseGraphicsResources( vtkWindow *win )
394
{
395
  this->PolarAxis->ReleaseGraphicsResources(win);
396
397
  for ( int i = 0; i < this->NumberOfRadialAxes;  ++i )
    {
Philippe Pébay's avatar
Philippe Pébay committed
398
    this->RadialAxes[i]->ReleaseGraphicsResources( win );
399
    }
400
401
  this->PolarArcsActor->ReleaseGraphicsResources(win);

402
403
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
404
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
405
void vtkPolarAxesActor::GetBounds( double bounds[6])
406
{
Philippe Pébay's avatar
Philippe Pébay committed
407
  for ( int i=0; i< 6; i++)
408
409
410
411
412
    {
    bounds[i] = this->Bounds[i];
    }
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
413
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
414
void vtkPolarAxesActor::GetBounds( double& xmin, double& xmax,
415
                                 double& ymin, double& ymax,
Philippe Pébay's avatar
Philippe Pébay committed
416
                                 double& zmin, double& zmax )
417
418
419
420
421
422
423
424
425
{
  xmin = this->Bounds[0];
  xmax = this->Bounds[1];
  ymin = this->Bounds[2];
  ymax = this->Bounds[3];
  zmin = this->Bounds[4];
  zmax = this->Bounds[5];
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
426
//-----------------------------------------------------------------------------
427
428
429
430
431
double *vtkPolarAxesActor::GetBounds()
{
  return this->Bounds;
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
432
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
433
void vtkPolarAxesActor::TransformBounds( vtkViewport *viewport,
Philippe Pébay's avatar
Philippe Pébay committed
434
                                         double bounds[6] )
435
{
Philippe Pébay's avatar
Philippe Pébay committed
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
  double minPt[3], maxPt[3], transMinPt[3], transMaxPt[3];
  minPt[0] = this->Bounds[0];
  minPt[1] = this->Bounds[2];
  minPt[2] = this->Bounds[4];
  maxPt[0] = this->Bounds[1];
  maxPt[1] = this->Bounds[3];
  maxPt[2] = this->Bounds[5];

  viewport->SetWorldPoint(minPt[0], minPt[1], minPt[2], 1.0);
  viewport->WorldToDisplay();
  viewport->GetDisplayPoint(transMinPt);
  viewport->SetWorldPoint(maxPt[0], maxPt[1], maxPt[2], 1.0);
  viewport->WorldToDisplay();
  viewport->GetDisplayPoint(transMaxPt);

  bounds[0] = transMinPt[0];
  bounds[2] = transMinPt[1];
  bounds[4] = transMinPt[2];
  bounds[1] = transMaxPt[0];
  bounds[3] = transMaxPt[1];
  bounds[5] = transMaxPt[2];
457
458
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
459
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
460
void vtkPolarAxesActor::BuildAxes( vtkViewport *viewport )
461
462
463
{
  double bounds[6];

Philippe Pébay's avatar
Philippe Pébay committed
464
  if ( ( this->GetMTime() < this->BuildTime.GetMTime() ))
465
    {
Philippe Pébay's avatar
Philippe Pébay committed
466
    this->AutoScale( viewport );
467
468
469
    return;
    }

470
  // Determine the bounds for possible use ( input, prop, or user-defined )
Philippe Pébay's avatar
Philippe Pébay committed
471
  this->GetBounds( bounds );
Aashish Chaudhary's avatar
Aashish Chaudhary committed
472

473
  // If pole coordinates are invalid, use bounds
474
  double O[3];
475
476
  for ( int i = 0; i < 3; ++ i )
    {
477
    O[i] = this->Pole[i] == VTK_DOUBLE_MAX ? bounds[i * 2] : this->Pole[i];
478
    }
Aashish Chaudhary's avatar
Aashish Chaudhary committed
479

480
481
482
  // If axial scale it out of proportions with object length scale, reset to ls
  double ls = fabs( bounds[1] -  bounds[0] ) + fabs( bounds[3] -  bounds[2] );
  if ( this->AutoScaleRadius
Aashish Chaudhary's avatar
Aashish Chaudhary committed
483
       || this->MaximumRadius < 1.e-6 * ls
484
485
486
487
       || this->MaximumRadius > 1.e6 * ls )
    {
    this->MaximumRadius = .5 * ls;
    }
488

489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
  // Set polar axis endpoints
  vtkAxisActor* axis = this->PolarAxis;
  double ox = O[0] + this->MaximumRadius;
  axis->GetPoint1Coordinate()->SetValue( O[0], O[1], O[2] );
  axis->GetPoint2Coordinate()->SetValue( ox, O[1], O[2] );

  // Set common axis attributes
  this->SetCommonAxisAttributes( axis );

  // Set polar axis lines
  axis->SetAxisVisibility( this->PolarAxisVisibility );
  axis->SetAxisLinesProperty( this->PolarAxisProperty );

  // Set polar axis title
  axis->SetTitleVisibility( this->PolarTitleVisibility );
  axis->SetTitle( this->PolarAxisTitle );
  axis->SetTitleTextProperty( this->PolarAxisTitleTextProperty );

  // Set polar axis ticks (major only)
  axis->SetTickVisibility( this->PolarTickVisibility );
  axis->SetTickLocation( this->TickLocation );
  axis->SetMajorTickSize( .02 * this->MaximumRadius );
  
  // Set polar axis labels
  axis->SetLabelVisibility( this->PolarLabelVisibility );
  axis->SetLabelTextProperty( this->PolarAxisLabelTextProperty );

  // Create requested number of radial axes
  double dAlpha = 
    ( this->MaximumAngle  - this->MinimumAngle ) / ( this->NumberOfRadialAxes - 1. );
  double alpha = this->MinimumAngle;
  for ( int i = 0; i < this->NumberOfRadialAxes;  ++ i, alpha += dAlpha )
521
    {
522
523
524
525
526
527
528
    // Calculate endpoint coordinates
    double alphaRad = vtkMath::RadiansFromDegrees( alpha );
    double x = O[0] + this->MaximumRadius * cos( alphaRad );
    double y = O[1] + this->MaximumRadius * sin( alphaRad );

    // Set radial axis endpoints
    axis = this->RadialAxes[i];
529
530
    axis->GetPoint1Coordinate()->SetValue( O[0], O[1], O[2] );
    axis->GetPoint2Coordinate()->SetValue( x, y, O[2] );
Philippe Pébay's avatar
Philippe Pébay committed
531

532
533
    // Set common axis attributes
    this->SetCommonAxisAttributes( axis );
534

535
536
537
    // Set radial axis lines
    axis->SetAxisVisibility( this->RadialAxesVisibility );
    axis->SetAxisLinesProperty( this->RadialAxesProperty );
538

539
540
541
542
543
544
545
546
547
548
549
    // Set radial axis title with polar angle as title for non-polar axes
    axis->SetTitleVisibility( this->RadialTitleVisibility );
    axis->GetTitleTextProperty()->SetColor( this->RadialAxesProperty->GetColor() );
    vtksys_ios::ostringstream title;
    title << alpha
          << ( this->RadialUnits ? " deg" : "" );
    axis->SetTitle( title.str().c_str() );

    // No labels nor ticks for radial axes
    axis->SetLabelVisibility( 0 );
    axis->SetTickVisibility( 0 );
550
    }
Aashish Chaudhary's avatar
Aashish Chaudhary committed
551

552
553
  // Build polar axis ticks
  this->BuildPolarAxisTicks( O[0] );
554

555
556
  // Build polar axis labels
  this->BuildPolarAxisLabelsArcs( O );
557

558
  // Scale appropriately
559
560
561
562
563
564
  this->AutoScale( viewport );

  this->RenderSomething = 1;
  this->BuildTime.Modified();
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
565
//-----------------------------------------------------------------------------
566
void vtkPolarAxesActor::SetCommonAxisAttributes( vtkAxisActor* axis )
567
568
{
  vtkProperty *prop = this->GetProperty();
Philippe Pébay's avatar
Philippe Pébay committed
569
570
  prop->SetAmbient( 1.0 );
  prop->SetDiffuse( 0.0 );
571
572
573
574
575
576
577
578
  axis->SetProperty( prop );

  axis->SetCamera( this->Camera );
  axis->SetBounds( this->Bounds );
  axis->SetRange( 0., this->MaximumRadius );

  // No minor ticks for any kind of axes
  axis->SetMinorTicksVisible( 0 );
579
580
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
581
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
582
double vtkPolarAxesActor::MaxOf( double a, double b )
583
{
Philippe Pébay's avatar
Philippe Pébay committed
584
  return ( a > b ? a : b );
585
586
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
587
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
588
inline double vtkPolarAxesActor::FFix( double value )
589
{
Philippe Pébay's avatar
Philippe Pébay committed
590
  int ivalue = static_cast<int>( value );
591
592
593
  return ivalue;
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
594
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
595
inline double vtkPolarAxesActor::FSign( double value, double sign )
596
{
Philippe Pébay's avatar
Philippe Pébay committed
597
598
  value = fabs( value );
  if ( sign < 0.)
599
600
601
602
603
604
    {
    value *= -1.;
    }
  return value;
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
605
//-----------------------------------------------------------------------------
606
void vtkPolarAxesActor::BuildPolarAxisTicks( double x0 )
607
{
608
  cerr << "In BuildPolarAxisTicks\n";
609
  double delta;
610

611
612
613
  if ( this->AutoSubdividePolarAxis
       || this->NumberOfPolarAxisTicks < 0
       || this->NumberOfPolarAxisTicks > VTK_MAXIMUM_NUMBER_OF_POLAR_AXIS_TICKS )
614
    {
615
616
    // Programatically figure the number of divisions of the polar axis
    double pow10 = log10( this->MaximumRadius );
617

618
619
620
621
622
623
    // Build in numerical tolerance
    if ( pow10 != 0.)
      {
      double eps = 10.0e-10;
      pow10 = this->FSign( ( fabs( pow10 ) + eps ), pow10 );
      }
624

625
626
627
628
629
    // FFix will move in the wrong direction if pow10 is negative.
    if ( pow10 < 0.)
      {
      pow10 = pow10 - 1.;
      }
630

631
632
633
634
635
636
    // Find the number of integral points in the interval.
    delta = pow( 10., this->FFix( pow10 ) );
    double fnt = this->MaximumRadius / delta;
    fnt  = this->FFix( fnt );
    int numTicks = fnt <= 0.5 ? 
      static_cast<int>( this->FFix( fnt ) ) : static_cast<int>( this->FFix( fnt ) + 1 );
637

638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
    // If not enough tick points in this decade, scale down
    double div = 1.;
    if ( numTicks < 5 )
      {
      div = 2.;
      }
    if ( numTicks <= 2 )
      {
      div = 5.;
      }
    if ( div != 1.)
      {
      delta /= div;
      }

    // Finally calculate number of tick points
    this->NumberOfPolarAxisTicks = 0;
    while ( delta * this->NumberOfPolarAxisTicks <= this->MaximumRadius )
      {
      ++ this->NumberOfPolarAxisTicks;
      }
    }
  else // if ( this->AutoSubdividePolarAxis || this->NumberOfPolarAxisTicks ... )
661
    {
662
663
    // Use pre-set number of arcs when it is valid and no auto-subdivision was requested
    delta =  this->MaximumRadius / ( this->NumberOfPolarAxisTicks - 1 );
664
    }
665
  // Set major start and delta corresponding to range and coordinates
666
667
668
  this->PolarAxis->SetMajorRangeStart( 0. );
  this->PolarAxis->SetDeltaRangeMajor( delta );
  this->PolarAxis->SetMajorStart( VTK_AXIS_TYPE_X, x0 );
669

670
  // Build in numerical robustness to avoid truncation errors at endpoint
671
  delta *= VTK_POLAR_AXES_ACTOR_RTOL;
672
  this->PolarAxis->SetDeltaMajor( VTK_AXIS_TYPE_X, delta );
673
674
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
675
//-----------------------------------------------------------------------------
676
void vtkPolarAxesActor::BuildPolarAxisLabelsArcs( double* O )
677
{
678
  cerr << "In BuildPolarAxisLabelsArcs\n";
679
  // Prepare storage for polar axis labels
680
  vtkStringArray *labels = vtkStringArray::New();
681
  labels->SetNumberOfValues( this->NumberOfPolarAxisTicks );
682

683
  // Prepare trigonometric quantities
684
685
686
687
688
689
690
  double thetaMin = vtkMath::RadiansFromDegrees( this->MinimumAngle );
  double cosThetaMin = cos( thetaMin );
  double sinThetaMin = sin( thetaMin );
  double thetaMax = vtkMath::RadiansFromDegrees( this->MaximumAngle );
  double cosThetaMax = cos( thetaMax );
  double sinThetaMax = sin( thetaMax );
  double angularSector = this->MaximumAngle - this->MinimumAngle;
Aashish Chaudhary's avatar
Aashish Chaudhary committed
691
  vtkIdType arcResolution
692
    = static_cast<vtkIdType>( angularSector * VTK_POLAR_ARC_RESOLUTION_PER_DEG );
693

694
695
696
697
  // Arc points
  vtkPoints *polarArcsPoints = vtkPoints::New();
  this->PolarArcs->SetPoints( polarArcsPoints );
  polarArcsPoints->Delete();
698

699
700
701
702
703
  // Arc lines
  vtkCellArray *polarArcsLines = vtkCellArray::New();
  this->PolarArcs->SetLines( polarArcsLines );
  polarArcsLines->Delete();

704
  // Retreave label features
705
  vtkAxisActor* axis = this->PolarAxis;
706
707
708
709
  double delta = axis->GetDeltaMajor( VTK_AXIS_TYPE_X );
  double value = axis->GetMajorRangeStart();

  // Now create labels and polar arcs
710
  const char *format = this->PolarLabelFormat;
711
  char label[64];
712
  vtkIdType pointIdOffset = 0;
713
  for ( int  i = 0; i < this->NumberOfPolarAxisTicks; ++ i )
714
    {
715
    // Store label
716
    sprintf( label, format, value );
717
    labels->SetValue( i, label );
718

719
    if ( value  > 0. )
720
      {
721
      // Build corresponding polar arc for non-zero values
722
723
724
725
      double x1 = value * cosThetaMin;
      double y1 = value * sinThetaMin;
      double x2 = value * cosThetaMax;
      double y2 = value * sinThetaMax;
726
      vtkArcSource* arc = vtkArcSource::New();
727
      arc->SetCenter( O );
728
729
      arc->SetPoint1( O[0] + x1, O[1] + y1, O[2] );
      arc->SetPoint2( O[0] + x2, O[1] + y2, O[2] );
730
      arc->SetResolution( arcResolution );
731
      arc->SetNegative( angularSector > 180. );
732
      arc->Update();
Aashish Chaudhary's avatar
Aashish Chaudhary committed
733

734
735
736
737
738
739
740
741
742
743
      // Append new polar arc to existing ones
      vtkPoints* arcPoints = arc->GetOutput()->GetPoints();
      vtkIdType nPoints = arcResolution + 1;
      vtkIdType* arcPointIds = new vtkIdType[nPoints];
      for ( vtkIdType j = 0; j < nPoints; ++ j )
        {
        polarArcsPoints->InsertNextPoint( arcPoints->GetPoint( j ) );
        arcPointIds[j] = pointIdOffset + j;
        }
      polarArcsLines->InsertNextCell( nPoints, arcPointIds );
Aashish Chaudhary's avatar
Aashish Chaudhary committed
744

745
746
747
      // Clean up
      arc->Delete();
      delete [] arcPointIds;
Aashish Chaudhary's avatar
Aashish Chaudhary committed
748

749
750
      // Update polyline cell offset
      pointIdOffset += nPoints;
751
752
753
      }

    // Move to next value
754
    value += delta;
755
    }
756
757

  // Store labels
758
  this->PolarAxis->SetLabels( labels );
759
760

  // Clean up
761
  labels->Delete();
762
763
764

  // Update axis label followers
  vtkAxisFollower** labelActors = axis->GetLabelActors();
765
  for( int i = 0; i < this->NumberOfPolarAxisTicks; ++ i )
766
767
768
769
    {
    labelActors[i]->SetAxis( axis );
    labelActors[i]->SetScreenOffset( this->LabelScreenOffset );
    }
770
771
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
772
//-----------------------------------------------------------------------------
773
774
775
void vtkPolarAxesActor::AutoScale( vtkViewport *viewport )
{

776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
  // Scale polar axis title
  vtkAxisActor* axis = this->PolarAxis;
  double newTitleScale
    = vtkAxisFollower::AutoScale( viewport, 
                                  this->Camera,
                                  this->ScreenSize, 
                                  axis->GetTitleActor()->GetPosition() );
  axis->SetTitleScale( newTitleScale );

  // Scale polar axis labels
  vtkAxisFollower** labelActors = axis->GetLabelActors();
  for( int i = 0; i < axis->GetNumberOfLabelsBuilt(); ++ i )
    {
    double newLabelScale 
      = vtkAxisFollower::AutoScale( viewport,
                                    this->Camera, 
                                    this->ScreenSize, 
                                    labelActors[i]->GetPosition() );
    labelActors[i]->SetScale( newLabelScale );
    }
796
797

  // Loop over radial axes
798
799
  for ( int i = 0; i < this->NumberOfRadialAxes; ++ i )
    {
800
    axis = this->RadialAxes[i];
801
    // Scale title
802
803
804
805
806
807
    newTitleScale 
      = vtkAxisFollower::AutoScale( viewport, 
                                    this->Camera,
                                    this->ScreenSize,
                                    axis->GetTitleActor()->GetPosition() );
    axis->SetTitleScale( newTitleScale );
808
    }
809
810
}

811
812
813
814
815
816
817
818
819
820
821
822
823
//-----------------------------------------------------------------------------
void vtkPolarAxesActor::SetPolarAxisProperty( vtkProperty *prop )
{
  this->PolarAxisProperty->DeepCopy( prop );
  this->Modified();
}

//-----------------------------------------------------------------------------
vtkProperty* vtkPolarAxesActor::GetPolarAxisProperty()
{
  return this->PolarAxisProperty;
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
824
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
825
void vtkPolarAxesActor::SetRadialAxesProperty( vtkProperty *prop )
826
{
Philippe Pébay's avatar
Philippe Pébay committed
827
  this->RadialAxesProperty->DeepCopy( prop );
828
829
830
  this->Modified();
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
831
//-----------------------------------------------------------------------------
832
833
834
835
vtkProperty* vtkPolarAxesActor::GetRadialAxesProperty()
{
  return this->RadialAxesProperty;
}
836

Aashish Chaudhary's avatar
Aashish Chaudhary committed
837
//-----------------------------------------------------------------------------
838
839
840
841
842
843
void vtkPolarAxesActor::SetPolarArcsProperty( vtkProperty *prop )
{
  this->PolarArcsActor->SetProperty(prop);
  this->Modified();
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
844
//-----------------------------------------------------------------------------
845
846
847
848
vtkProperty* vtkPolarAxesActor::GetPolarArcsProperty()
{
  return this->PolarArcsActor->GetProperty();
}