vtkPolarAxesActor.cxx 25.4 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
36

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

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

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

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

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

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

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

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

81
82
83
  os << indent << "Rebuild Axes: "
     << ( this->RebuildAxes ? "On\n" : "Off\n" );

84

Philippe Pébay's avatar
Philippe Pébay committed
85
86
87
  os << indent << "Polar Axis Title: " << this->PolarAxisTitle << "\n";
  os << indent << "PolarAxisLabelTextProperty: " << this->PolarAxisLabelTextProperty << endl;
  os << indent << "PolarAxisTitleTextProperty: " << this->PolarAxisTitleTextProperty << endl;
88
89

  os << indent << "Radial Axes Visibility: "
90
     << ( this->RadialAxesVisibility ? "On\n" : "Off\n" );
91

92
93
  os << indent << "Radial Title Visibility: "
     << ( this->RadialTitleVisibility ? "On" : "Off" ) << endl;
94

95
96
  os << indent << "Polar Label Visibility: "
     << ( this->PolarLabelVisibility ? "On" : "Off" ) << endl;
97

98
99
100
  os << indent << "Polar Tick Visibility: "
     << ( this->PolarTickVisibility ? "On" : "Off" ) << endl;

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

104
  os << indent << "Radial Axes Label Format: " << this->RadialLabelFormat << "\n";
105

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

Aashish Chaudhary's avatar
Aashish Chaudhary committed
109
//-----------------------------------------------------------------------------
110
111
vtkPolarAxesActor::vtkPolarAxesActor() : vtkActor()
{
112
113
114
115
116
  // 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;

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

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

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

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

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

135
136
137
138
139
  // Default maximum polar angle
  this->MaximumAngle = VTK_DEFAULT_MAXIMUM_POLAR_ANGLE;

  // By default show angle units (degrees)
  this->RadialUnits = 1;
140
141
142
143
144
145
146

  this->RebuildAxes = false;

  this->Camera = NULL;

  this->ScreenSize = 10.0;

147
148
  // Considering pivot point at center of the geometry,
  // hence ( this->ScreenSize * 0.5 ).
Philippe Pébay's avatar
Philippe Pébay committed
149
  this->LabelScreenOffset = 15.0 + this->ScreenSize * 0.5;
150

151
  // Properties of the radial axes, with default color black
Philippe Pébay's avatar
Philippe Pébay committed
152
  this->RadialAxesProperty = vtkProperty::New();
153
  this->RadialAxesProperty->SetColor( 0., 0., 0. );
Philippe Pébay's avatar
Philippe Pébay committed
154

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

163
  // Create and set radial axes
164
165
  this->RadialAxes = new vtkAxisActor*[VTK_MAXIMUM_NUMBER_OF_RADIAL_AXES];
  for ( int i = 0; i < VTK_MAXIMUM_NUMBER_OF_RADIAL_AXES; ++ i )
166
    {
167
    // Create axis of type X
168
    this->RadialAxes[i] = vtkAxisActor::New();
169
170
    vtkAxisActor* axis = this->RadialAxes[i];
    axis->SetAxisTypeToX();
171
172
    axis->SetAxisPositionToMinMax();
    axis->SetCalculateTitleOffset( 0 );
173
    axis->SetCalculateLabelOffset( 0 );
174
175

    // Pass information to axes followers
176
177
    vtkAxisFollower* follower = axis->GetTitleActor();
    follower->SetAxis( axis );
178
179
180

    double offset = this->LabelScreenOffset + this->ScreenSize * 0.5;

Philippe Pébay's avatar
Philippe Pébay committed
181
182
    // Using 2/3 of base offset if not a polar axis.
    follower->SetScreenOffset( .67 * offset );
183

184
    if ( !i )
185
      {
Philippe Pébay's avatar
Philippe Pébay committed
186
187
      // Using twice the base offset and a little for the title of the polar axis.
      follower->SetScreenOffset( 2.0 * offset + 5 );
188
189
190
191
192
193
194

      vtkAxisFollower **labelActors = axis->GetLabelActors();
      int numberOfLabels = axis->GetNumberOfLabelsBuilt();
      for( int k=0; k < numberOfLabels; ++k )
        {
        labelActors[k]->SetScreenOffset( offset );
        }
195
      }
196
197
198
    }

  // Default tick location, defined in vtkAxisActor
199
  this->TickLocation = VTK_TICKS_BOTH;
200

201
  // Create and set polar arcs and ancillary objects, with default color white
202
203
204
205
206
  this->PolarArcs = vtkPolyData::New();
  this->PolarArcsMapper = vtkPolyDataMapper::New();
  this->PolarArcsMapper->SetInput( this->PolarArcs );
  this->PolarArcsActor = vtkActor::New();
  this->PolarArcsActor->SetMapper( this->PolarArcsMapper );
207
  this->PolarArcsActor->GetProperty()->SetColor( 1., 1., 1. );
208

209
210
  // By default all features are visible
  this->RadialAxesVisibility = 1;
211
  this->RadialTitleVisibility = 1;
212
213
  this->PolarLabelVisibility = 1;
  this->PolarTickVisibility = 1;
214
  this->PolarArcsVisibility = 1;
215

216
217
218
219
  // Default title for polar axis (can also be called "Radius")
  this->PolarAxisTitle = new char[16];
  sprintf(this->PolarAxisTitle, "%s", "Radial Distance");

220
  this->RadialLabelFormat = new char[8];
221
  sprintf( this->RadialLabelFormat, "%s", "%-#6.3g" );
222
223
224
225
226
227
228
229
230
231

  this->RenderCount = 0;

  this->RenderSomething = 0;

  this->UserRadialPow = 0;

  this->AutoLabelScaling = true;

  this->LabelScale = -1.0;
232
  this->TitleScale = -1.0;
233
234
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
235
//-----------------------------------------------------------------------------
236
237
238
239
vtkPolarAxesActor::~vtkPolarAxesActor()
{
  this->SetCamera( NULL );

Philippe Pébay's avatar
Philippe Pébay committed
240
  if ( this->RadialAxesProperty )
241
242
243
244
    {
    this->RadialAxesProperty->Delete();
    }

Philippe Pébay's avatar
Philippe Pébay committed
245
  if ( this->RadialLabelFormat )
246
247
248
249
    {
    delete [] this->RadialLabelFormat;
    this->RadialLabelFormat = NULL;
    }
Philippe Pébay's avatar
Philippe Pébay committed
250

Philippe Pébay's avatar
Philippe Pébay committed
251
  if ( this->PolarAxisTitle )
252
253
254
255
256
    {
    delete [] this->PolarAxisTitle;
    this->PolarAxisTitle = NULL;
    }

Philippe Pébay's avatar
Philippe Pébay committed
257
258
259
260
261
262
263
264
265
266
267
268
  if ( this->PolarAxisTitleTextProperty )
    {
    this->PolarAxisTitleTextProperty->Delete();
    this->PolarAxisTitleTextProperty = NULL;
    }

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

Philippe Pébay's avatar
Philippe Pébay committed
269
270
  if ( this->RadialAxes )
    {
271
    for ( int i = 0; i < VTK_MAXIMUM_NUMBER_OF_RADIAL_AXES; ++ i )
Philippe Pébay's avatar
Philippe Pébay committed
272
273
274
275
276
277
278
279
280
281
      {
      if ( this->RadialAxes[i] )
        {
        this->RadialAxes[i]->Delete();
        this->RadialAxes[i] = NULL;
        }
      }
    delete [] this->RadialAxes;
    this->RadialAxes = NULL;
    }
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

  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;
    }

299
300
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
301
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
302
int vtkPolarAxesActor::RenderOpaqueGeometry( vtkViewport *viewport )
303
304
305
{
  // Initialization
  static bool initialRender = true;
306
  if ( !this->Camera )
307
308
309
310
311
312
313
314
315
316
317
318
    {
    vtkErrorMacro( <<"No camera!" );
    this->RenderSomething = 0;
    return 0;
    }

  this->BuildAxes( viewport );

  if ( initialRender || this->RebuildAxes )
    {
    for ( int i = 0; i < this->NumberOfRadialAxes; ++ i )
      {
Philippe Pébay's avatar
Philippe Pébay committed
319
      this->RadialAxes[i]->BuildAxis( viewport, true );
320
321
322
323
324
      }
    }
  initialRender = false;
  this->RebuildAxes = false;

325
  // Render the radial axes
326
327
328
329
330
  int renderedSomething = 0;
  if ( this->RadialAxesVisibility )
    {
    for ( int i = 0; i < this->NumberOfRadialAxes; ++ i )
      {
331
      renderedSomething += this->RadialAxes[i]->RenderOpaqueGeometry( viewport );
332
333
334
      }
    }

335
336
337
338
339
340
  // Render the polar arcs
  if ( this->PolarArcsVisibility )
    {
    renderedSomething += this->PolarArcsActor->RenderOpaqueGeometry(viewport);
    }

341
342
343
  return renderedSomething;
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
344
//-----------------------------------------------------------------------------
345
// Screen size affects the screen offset as well.
Aashish Chaudhary's avatar
Aashish Chaudhary committed
346

Philippe Pébay's avatar
Philippe Pébay committed
347
void vtkPolarAxesActor::SetScreenSize( double screenSize )
348
349
{
  this->ScreenSize = screenSize;
350
351
  // Considering pivot point at center of the geometry,
  // hence ( this->ScreenSize * 0.5 ).
Philippe Pébay's avatar
Philippe Pébay committed
352
  this->LabelScreenOffset = 15.0 + this->ScreenSize * 0.5;
353
354
355

  for ( int i = 0; i < this->NumberOfRadialAxes; ++ i )
    {
356
    vtkAxisActor* axis = this->RadialAxes[i];
Aashish Chaudhary's avatar
Aashish Chaudhary committed
357

358
359
360
    int numberOfLabelsBuilt = axis->GetNumberOfLabelsBuilt();
    vtkAxisFollower** labelActors = axis->GetLabelActors();
    for( int k=0; k < numberOfLabelsBuilt; ++k )
361
      {
Philippe Pébay's avatar
Philippe Pébay committed
362
      labelActors[k]->SetScreenOffset( this->LabelScreenOffset );
363
364
365
366
367
368
      }
    }

  this->Modified();
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
369
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
370
void vtkPolarAxesActor::ReleaseGraphicsResources( vtkWindow *win )
371
372
373
{
  for ( int i = 0; i < this->NumberOfRadialAxes;  ++i )
    {
Philippe Pébay's avatar
Philippe Pébay committed
374
    this->RadialAxes[i]->ReleaseGraphicsResources( win );
375
    }
376
377
  this->PolarArcsActor->ReleaseGraphicsResources(win);

378
379
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
380
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
381
void vtkPolarAxesActor::GetBounds( double bounds[6])
382
{
Philippe Pébay's avatar
Philippe Pébay committed
383
  for ( int i=0; i< 6; i++)
384
385
386
387
388
    {
    bounds[i] = this->Bounds[i];
    }
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
389
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
390
void vtkPolarAxesActor::GetBounds( double& xmin, double& xmax,
391
                                 double& ymin, double& ymax,
Philippe Pébay's avatar
Philippe Pébay committed
392
                                 double& zmin, double& zmax )
393
394
395
396
397
398
399
400
401
{
  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
402
//-----------------------------------------------------------------------------
403
404
405
406
407
double *vtkPolarAxesActor::GetBounds()
{
  return this->Bounds;
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
408
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
409
void vtkPolarAxesActor::TransformBounds( vtkViewport *viewport,
Philippe Pébay's avatar
Philippe Pébay committed
410
                                         double bounds[6] )
411
{
Philippe Pébay's avatar
Philippe Pébay committed
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
  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];
433
434
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
435
//-----------------------------------------------------------------------------
436
437
438
439
440
441
442
443
444
445
446
//  Method: LabelExponent
//
//  Purpose:
//      Determines the proper exponent for the min and max values.
//
//  Arguments:
//      min     The minimum value along a certain axis.
//      max     The maximum value along a certain axis.
//
//  Note:       This code is mostly stolen from old MeshTV code,
//              /meshtvx/toolkit/plotgrid.c, axlab_format.
Aashish Chaudhary's avatar
Aashish Chaudhary committed
447

Philippe Pébay's avatar
Philippe Pébay committed
448
int vtkPolarAxesActor::LabelExponent( double min, double max )
449
{
Philippe Pébay's avatar
Philippe Pébay committed
450
  if ( min == max )
451
452
453
454
455
456
457
    {
    return 0;
    }

  //
  // Determine power of 10 to scale axis labels to.
  //
Philippe Pébay's avatar
Philippe Pébay committed
458
459
  double range = ( fabs( min ) > fabs( max ) ? fabs( min ) : fabs( max ) );
  double pow10 = log10( range );
460
461
462
463
464
465
466
467

  //
  // Cutoffs for using scientific notation.  The following 4 variables
  // should all be static for maximum performance but were made non-static
  // to get around a compiler bug with the MIPSpro 7.2.1.3 compiler.
  //
  double eformat_cut_min = -1.5;
  double eformat_cut_max =  3.0;
Philippe Pébay's avatar
Philippe Pébay committed
468
469
  double cut_min = pow( 10., eformat_cut_min );
  double cut_max = pow( 10., eformat_cut_max );
470
  double ipow10;
Philippe Pébay's avatar
Philippe Pébay committed
471
  if ( range < cut_min || range > cut_max )
472
473
474
475
476
    {
    //
    // We are going to use scientific notation and round the exponents to
    // the nearest multiple of three.
    //
Philippe Pébay's avatar
Philippe Pébay committed
477
    ipow10 = ( floor( floor( pow10 )/3.) )*3;
478
479
480
481
482
483
    }
  else
    {
    ipow10 = 0;
    }

Philippe Pébay's avatar
Philippe Pébay committed
484
  return static_cast<int>( ipow10 );
485
486
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
487
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
488
void vtkPolarAxesActor::BuildAxes( vtkViewport *viewport )
489
490
491
{
  double bounds[6];

Philippe Pébay's avatar
Philippe Pébay committed
492
  if ( ( this->GetMTime() < this->BuildTime.GetMTime() ))
493
    {
Philippe Pébay's avatar
Philippe Pébay committed
494
    this->AutoScale( viewport );
495
496
497
498
    return;
    }

  this->SetNonDependentAttributes();
Philippe Pébay's avatar
Philippe Pébay committed
499

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

503
  // If pole coordinates are invalid, use bounds
504
  double O[3];
505
506
  for ( int i = 0; i < 3; ++ i )
    {
507
    O[i] = this->Pole[i] == VTK_DOUBLE_MAX ? bounds[i * 2] : this->Pole[i];
508
    }
Aashish Chaudhary's avatar
Aashish Chaudhary committed
509

510
511
512
  // 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
513
       || this->MaximumRadius < 1.e-6 * ls
514
515
516
517
       || this->MaximumRadius > 1.e6 * ls )
    {
    this->MaximumRadius = .5 * ls;
    }
518

519
  // Prepare axes for rendering with user-definable options
520
  double dAlpha =  this->MaximumAngle / ( this->NumberOfRadialAxes - 1. );
521

522
  // Set radial axes
Philippe Pébay's avatar
Philippe Pébay committed
523
  for ( int i = 0; i < this->NumberOfRadialAxes;  ++ i )
524
    {
525
    double theta = i * dAlpha;
Philippe Pébay's avatar
Philippe Pébay committed
526
527
    double thetaRad = vtkMath::RadiansFromDegrees( theta );
    vtkAxisActor* axis = this->RadialAxes[i];
528
529
530
531
    double x = O[0] + this->MaximumRadius * cos( thetaRad );
    double y = O[1] + this->MaximumRadius * sin( thetaRad );
    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
532

533
    // Set axis ticks
534
535
    axis->SetRange( 0., this->MaximumRadius );
    axis->SetMajorTickSize( .02 * this->MaximumRadius );
536

537
    // Set axis title
Philippe Pébay's avatar
Philippe Pébay committed
538
    if ( i )
539
      {
540
      // Use polar angle as title for non-polar axes
Philippe Pébay's avatar
Philippe Pébay committed
541
542
543
544
545
546
      vtksys_ios::ostringstream thetaStream;
      thetaStream << theta;
      if ( this->RadialUnits )
        {
        thetaStream << " deg.";
        }
547

Philippe Pébay's avatar
Philippe Pébay committed
548
      axis->SetTitle( thetaStream.str().c_str() );
549
      }
Aashish Chaudhary's avatar
Aashish Chaudhary committed
550
    else // if ( i )
551
      {
Philippe Pébay's avatar
Philippe Pébay committed
552
      // Special case of polar axis
553
554
      axis->SetTitle( this->PolarAxisTitle );
      }
555
    }
Aashish Chaudhary's avatar
Aashish Chaudhary committed
556

557
558
  // Build polar axis ticks
  this->BuildPolarAxisTicks( O[0] );
559

560
561
  // Build polar axis labels
  this->BuildPolarAxisLabelsArcs( O );
562

563
  // Scale appropriately
564
565
566
567
568
569
  this->AutoScale( viewport );

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

Aashish Chaudhary's avatar
Aashish Chaudhary committed
570
//-----------------------------------------------------------------------------
571
572
573
void vtkPolarAxesActor::SetNonDependentAttributes()
{
  vtkProperty *prop = this->GetProperty();
Philippe Pébay's avatar
Philippe Pébay committed
574
575
  prop->SetAmbient( 1.0 );
  prop->SetDiffuse( 0.0 );
576
577
  for ( int i = 0; i < this->NumberOfRadialAxes; ++ i )
    {
578
579
580
581
582
583
584
585
586
587
588
589
590
591
    vtkAxisActor* axis = this->RadialAxes[i];
    axis->SetCamera( this->Camera );
    axis->SetProperty( prop );
    axis->SetAxisLinesProperty( this->RadialAxesProperty );
    axis->SetTickLocation( this->TickLocation );
    axis->SetBounds( this->Bounds );
    axis->SetAxisVisibility( this->RadialAxesVisibility );
    axis->SetTitleVisibility( this->RadialTitleVisibility );
    axis->SetMinorTicksVisible( 0 );
    // Features available only on polar axis
    if ( ! i )
      {
      axis->SetLabelVisibility( this->PolarLabelVisibility );
      axis->SetTickVisibility( this->PolarTickVisibility );
Philippe Pébay's avatar
Philippe Pébay committed
592
593
      axis->SetTitleTextProperty( this->GetPolarAxisTitleTextProperty() );
      axis->SetLabelTextProperty( this->GetPolarAxisLabelTextProperty() );
594
595
596
597
598
      }
    else
      {
      axis->SetLabelVisibility( 0 );
      axis->SetTickVisibility( 0 );
599
      axis->GetTitleTextProperty()->SetColor( this->GetRadialAxesProperty()->GetColor() );
600
      }
601
602
603
    }
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
604
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
605
double vtkPolarAxesActor::MaxOf( double a, double b )
606
{
Philippe Pébay's avatar
Philippe Pébay committed
607
  return ( a > b ? a : b );
608
609
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
610
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
611
inline double vtkPolarAxesActor::FFix( double value )
612
{
Philippe Pébay's avatar
Philippe Pébay committed
613
  int ivalue = static_cast<int>( value );
614
615
616
  return ivalue;
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
617
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
618
inline double vtkPolarAxesActor::FSign( double value, double sign )
619
{
Philippe Pébay's avatar
Philippe Pébay committed
620
621
  value = fabs( value );
  if ( sign < 0.)
622
623
624
625
626
627
    {
    value *= -1.;
    }
  return value;
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
628
//-----------------------------------------------------------------------------
629
void vtkPolarAxesActor::BuildPolarAxisTicks( double x0 )
630
{
631
  double delta;
632

633
634
635
  if ( this->AutoSubdividePolarAxis
       || this->NumberOfPolarAxisTicks < 0
       || this->NumberOfPolarAxisTicks > VTK_MAXIMUM_NUMBER_OF_POLAR_AXIS_TICKS )
636
    {
637
638
    // Programatically figure the number of divisions of the polar axis
    double pow10 = log10( this->MaximumRadius );
639

640
641
642
643
644
645
    // Build in numerical tolerance
    if ( pow10 != 0.)
      {
      double eps = 10.0e-10;
      pow10 = this->FSign( ( fabs( pow10 ) + eps ), pow10 );
      }
646

647
648
649
650
651
    // FFix will move in the wrong direction if pow10 is negative.
    if ( pow10 < 0.)
      {
      pow10 = pow10 - 1.;
      }
652

653
654
655
656
657
658
    // 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 );
659

660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
    // 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 ... )
683
    {
684
685
    // Use pre-set number of arcs when it is valid and no auto-subdivision was requested
    delta =  this->MaximumRadius / ( this->NumberOfPolarAxisTicks - 1 );
686
687
    }

688
  // Set major start and delta corresponding to range and coordinates
689
  vtkAxisActor* axis = this->RadialAxes[0];
690
691
692
693
  axis->SetMajorRangeStart( 0. );
  axis->SetDeltaRangeMajor( delta );
  axis->SetMajorStart( VTK_AXIS_TYPE_X, x0 );
  axis->SetDeltaMajor( VTK_AXIS_TYPE_X, delta );
694
695
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
696
//-----------------------------------------------------------------------------
697
void vtkPolarAxesActor::BuildPolarAxisLabelsArcs( double* O )
698
{
699
700
701
702
  // Calculate number of labels needed and create array for them
  vtkAxisActor* axis = this->RadialAxes[0];
  double deltaMajor = axis->GetDeltaMajor( VTK_AXIS_TYPE_X );
  double val = axis->GetMajorStart( VTK_AXIS_TYPE_X );
703
704
  
  // Prepare storage for polar axis labels
705
  vtkStringArray *labels = vtkStringArray::New();
706
  labels->SetNumberOfValues( this->NumberOfPolarAxisTicks );
707

708
  // Prepare trigonometric quantities
709
710
711
  double thetaRad = vtkMath::RadiansFromDegrees( this->MaximumAngle );
  double cosTheta = cos( thetaRad );
  double sinTheta = sin( thetaRad );
Aashish Chaudhary's avatar
Aashish Chaudhary committed
712
  vtkIdType arcResolution
713
714
    = static_cast<vtkIdType>( this->MaximumAngle * VTK_POLAR_ARC_RESOLUTION_PER_DEG );

715
716
717
718
  // Arc points
  vtkPoints *polarArcsPoints = vtkPoints::New();
  this->PolarArcs->SetPoints( polarArcsPoints );
  polarArcsPoints->Delete();
719

720
721
722
723
724
725
  // Arc lines
  vtkCellArray *polarArcsLines = vtkCellArray::New();
  this->PolarArcs->SetLines( polarArcsLines );
  polarArcsLines->Delete();

  // Now create labels and polar arcs
726
727
728
  val = axis->GetMajorRangeStart();
  const char *format = this->RadialLabelFormat;
  char label[64];
729
  vtkIdType pointIdOffset = 0;
730
  for ( int  i = 0; i < this->NumberOfPolarAxisTicks; ++ i )
731
    {
732
    // Store label
733
    sprintf( label, format, val );
734
    labels->SetValue( i, label );
735

736
    if ( val  > 0. )
737
      {
738
739
740
741
      // Build corresponding polar arc for non-zero values
      double x = val * cosTheta;
      double y = val * sinTheta;
      vtkArcSource* arc = vtkArcSource::New();
742
743
744
      arc->SetCenter( O );
      arc->SetPoint1( O[0] + val, O[1], O[2] );
      arc->SetPoint2( O[0] + x, O[1] + y, O[2] );
745
      arc->SetResolution( arcResolution );
746
      arc->SetNegative( this->MaximumAngle > 180. );
747
      arc->Update();
Aashish Chaudhary's avatar
Aashish Chaudhary committed
748

749
750
751
752
753
754
755
756
757
758
      // 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
759

760
761
762
      // Clean up
      arc->Delete();
      delete [] arcPointIds;
Aashish Chaudhary's avatar
Aashish Chaudhary committed
763

764
765
      // Update polyline cell offset
      pointIdOffset += nPoints;
766
767
768
      }

    // Move to next value
769
770
    val += deltaMajor;
    }
771
772
773
774
775

  // Store labels
  axis->SetLabels( labels );

  // Clean up
776
  labels->Delete();
777
778
779

  // Update axis label followers
  vtkAxisFollower** labelActors = axis->GetLabelActors();
780
  for( int i = 0; i < this->NumberOfPolarAxisTicks; ++i )
781
782
783
784
    {
    labelActors[i]->SetAxis( axis );
    labelActors[i]->SetScreenOffset( this->LabelScreenOffset );
    }
785
786
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
787
//-----------------------------------------------------------------------------
788
789
790
791
792
793
794
795
796
797
void vtkPolarAxesActor::SetLabelScaling( bool autoscale, int upow )
{
  if ( autoscale != this->AutoLabelScaling || upow != this->UserRadialPow )
    {
    this->AutoLabelScaling = autoscale;
    this->UserRadialPow = upow;
    this->Modified();
    }
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
798
//-----------------------------------------------------------------------------
799
800
801
802
803
804
void vtkPolarAxesActor::AutoScale( vtkViewport *viewport )
{
  // Current implementation only for perspective projections.
  this->AutoScale( viewport, this->RadialAxes );
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
805
806
//-----------------------------------------------------------------------------
void vtkPolarAxesActor::AutoScale( vtkViewport *viewport,
807
808
809
810
811
                                   vtkAxisActor** axis )
{
  double newTitleScale = this->TitleScale;

  // Loop over radial axes
812
813
  for ( int i = 0; i < this->NumberOfRadialAxes; ++ i )
    {
814
    // Scale title
815
816
    newTitleScale = vtkAxisFollower::AutoScale( viewport, this->Camera,
      this->ScreenSize, axis[i]->GetTitleActor()->GetPosition() );
817
818
819
820

    axis[i]->SetTitleScale( newTitleScale );

    // Scale labels
821
    vtkAxisFollower** labelActors = axis[i]->GetLabelActors();
822
823

    for( int j = 0; j < axis[i]->GetNumberOfLabelsBuilt(); ++ j )
824
      {
825
826
      double newLabelScale = vtkAxisFollower::AutoScale( viewport,
        this->Camera, this->ScreenSize, labelActors[j]->GetPosition() );
827
828

      labelActors[j]->SetScale( newLabelScale );
829
830
      }
    }
831
832
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
833
//-----------------------------------------------------------------------------
Philippe Pébay's avatar
Philippe Pébay committed
834
void vtkPolarAxesActor::SetRadialAxesProperty( vtkProperty *prop )
835
{
Philippe Pébay's avatar
Philippe Pébay committed
836
  this->RadialAxesProperty->DeepCopy( prop );
837
838
839
  this->Modified();
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
840
//-----------------------------------------------------------------------------
841
842
843
844
vtkProperty* vtkPolarAxesActor::GetRadialAxesProperty()
{
  return this->RadialAxesProperty;
}
845

Aashish Chaudhary's avatar
Aashish Chaudhary committed
846
//-----------------------------------------------------------------------------
847
848
849
850
851
852
void vtkPolarAxesActor::SetPolarArcsProperty( vtkProperty *prop )
{
  this->PolarArcsActor->SetProperty(prop);
  this->Modified();
}

Aashish Chaudhary's avatar
Aashish Chaudhary committed
853
//-----------------------------------------------------------------------------
854
855
856
857
vtkProperty* vtkPolarAxesActor::GetPolarArcsProperty()
{
  return this->PolarArcsActor->GetProperty();
}