source: trunk/packages/vizservers/vtkvis/vtkRpCubeAxesActor.cpp @ 3479

Last change on this file since 3479 was 3479, checked in by ldelgass, 10 years ago

Update custom axes to VTK 6 versions, use local customized classes instead of
patched VTK runtime versions.

  • Property svn:eol-style set to native
File size: 90.2 KB
Line 
1/*=========================================================================
2
3  Program:   Visualization Toolkit
4  Module:    vtkRpCubeAxesActor.cpp
5  Thanks:    Kathleen Bonnell, B Division, Lawrence Livermore National Lab
6
7  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
8  All rights reserved.
9  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
10
11     This software is distributed WITHOUT ANY WARRANTY; without even
12     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13     PURPOSE.  See the above copyright notice for more information.
14
15 =========================================================================*/
16#include "vtkRpCubeAxesActor.h"
17
18#include "vtkRpAxisActor.h"
19#include "vtkRpAxisFollower.h"
20#include "vtkBoundingBox.h"
21#include "vtkCamera.h"
22#include "vtkCoordinate.h"
23#include "vtkFollower.h"
24#include "vtkMath.h"
25#include "vtkObjectFactory.h"
26#include "vtkProperty.h"
27#include "vtkStringArray.h"
28#include "vtkTextProperty.h"
29#include "vtkViewport.h"
30
31
32vtkStandardNewMacro(vtkRpCubeAxesActor);
33vtkCxxSetObjectMacro(vtkRpCubeAxesActor, Camera,vtkCamera);
34// *************************************************************************
35// Instantiate this object.
36// *************************************************************************
37vtkRpCubeAxesActor::vtkRpCubeAxesActor() : vtkActor()
38{
39  this->Bounds[0] = -1.0; this->Bounds[1] = 1.0;
40  this->Bounds[2] = -1.0; this->Bounds[3] = 1.0;
41  this->Bounds[4] = -1.0; this->Bounds[5] = 1.0;
42  for(int i=0; i < 6; ++i)
43    {
44    this->RenderedBounds[i] = this->Bounds[i];
45    }
46
47  this->OrientedBounds[0] = -1.0; this->OrientedBounds[1] = 1.0;
48  this->OrientedBounds[2] = -1.0; this->OrientedBounds[3] = 1.0;
49  this->OrientedBounds[4] = -1.0; this->OrientedBounds[5] = 1.0;
50
51  // Disable oriented bounds and Axis origin
52  this->UseOrientedBounds = this->UseAxisOrigin = 0;
53
54  // Init default axis origin
55  this->AxisOrigin[0] = this->AxisOrigin[1] = this->AxisOrigin[2] = 0.0;
56
57  // Init default axis base
58  this->AxisBaseForX[0] = this->AxisBaseForX[1] = this->AxisBaseForX[2] = 0;
59  this->AxisBaseForY[0] = this->AxisBaseForY[1] = this->AxisBaseForY[2] = 0;
60  this->AxisBaseForZ[0] = this->AxisBaseForZ[1] = this->AxisBaseForZ[2] = 0;
61  this->AxisBaseForX[0] = this->AxisBaseForY[1] = this->AxisBaseForZ[2] = 1.0;
62
63  this->RebuildAxes = false;
64
65  this->Camera = NULL;
66
67  this->FlyMode = VTK_FLY_CLOSEST_TRIAD;
68  this->GridLineLocation = VTK_GRID_LINES_ALL;
69
70  // By default enable distance based LOD
71  this->EnableDistanceLOD = 1;
72  this->DistanceLODThreshold = .8;
73
74  // By default enable view angle based LOD
75  this->EnableViewAngleLOD = 1;
76  this->ViewAngleLODThreshold = .2;
77
78  // Title and label text properties
79  for (int i = 0; i < 3; i++)
80    {
81    this->TitleTextProperty[i] = vtkTextProperty::New();
82    this->TitleTextProperty[i]->SetColor(1.,1.,1.);
83    this->TitleTextProperty[i]->SetFontFamilyToArial();
84    this->TitleTextProperty[i]->SetFontSize(14);
85
86    this->LabelTextProperty[i] = vtkTextProperty::New();
87    this->LabelTextProperty[i]->SetColor(1.,1.,1.);
88    this->LabelTextProperty[i]->SetFontFamilyToArial();
89    this->LabelTextProperty[i]->SetFontSize(12);
90    }
91
92  // Axis lines
93  this->XAxesLinesProperty = vtkProperty::New();
94  this->YAxesLinesProperty = vtkProperty::New();
95  this->ZAxesLinesProperty = vtkProperty::New();
96
97  // Outer grid lines
98  this->XAxesGridlinesProperty = vtkProperty::New();
99  this->YAxesGridlinesProperty = vtkProperty::New();
100  this->ZAxesGridlinesProperty = vtkProperty::New();
101
102  // Inner grid lines
103  this->XAxesInnerGridlinesProperty = vtkProperty::New();
104  this->YAxesInnerGridlinesProperty = vtkProperty::New();
105  this->ZAxesInnerGridlinesProperty = vtkProperty::New();
106  this->XAxesInnerGridlinesProperty->SetColor(.3,.6,.1);
107  this->YAxesInnerGridlinesProperty->SetColor(.3,.6,.1);
108  this->ZAxesInnerGridlinesProperty->SetColor(.3,.6,.1);
109
110  this->XAxesGridpolysProperty = vtkProperty::New();
111  this->YAxesGridpolysProperty = vtkProperty::New();
112  this->ZAxesGridpolysProperty = vtkProperty::New();
113  this->XAxesGridpolysProperty->SetOpacity(.6);     // Default grid polys opacity
114  this->YAxesGridpolysProperty->SetOpacity(.6);     // Default grid polys opacity
115  this->ZAxesGridpolysProperty->SetOpacity(.6);     // Default grid polys opacity
116  //this->XAxesGridpolysProperty->LightingOff();       // To be able to see the polys from high camera angles
117  //this->YAxesGridpolysProperty->LightingOff();       // To be able to see the polys from high camera angles
118  //this->ZAxesGridpolysProperty->LightingOff();       // To be able to see the polys from high camera angles
119
120  for (int i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
121    {
122    this->XAxes[i] = vtkRpAxisActor::New();
123    this->XAxes[i]->SetTickVisibility(1);
124    this->XAxes[i]->SetMinorTicksVisible(1);
125    this->XAxes[i]->SetLabelVisibility(1);
126    this->XAxes[i]->SetTitleVisibility(1);
127    this->XAxes[i]->SetAxisTypeToX();
128    this->XAxes[i]->SetAxisPosition(i);
129    this->XAxes[i]->SetAxisLinesProperty(this->XAxesLinesProperty);
130    this->XAxes[i]->SetGridlinesProperty(this->XAxesGridlinesProperty);
131    this->XAxes[i]->SetInnerGridlinesProperty(this->XAxesInnerGridlinesProperty);
132    this->XAxes[i]->SetGridpolysProperty(this->XAxesGridpolysProperty);
133    this->XAxes[i]->SetCalculateTitleOffset(0);
134    this->XAxes[i]->SetCalculateLabelOffset(0);
135
136    this->YAxes[i] = vtkRpAxisActor::New();
137    this->YAxes[i]->SetTickVisibility(1);
138    this->YAxes[i]->SetMinorTicksVisible(1);
139    this->YAxes[i]->SetLabelVisibility(1);
140    this->YAxes[i]->SetTitleVisibility(1);
141    this->YAxes[i]->SetAxisTypeToY();
142    this->YAxes[i]->SetAxisPosition(i);
143    this->YAxes[i]->SetAxisLinesProperty(this->YAxesLinesProperty);
144    this->YAxes[i]->SetGridlinesProperty(this->YAxesGridlinesProperty);
145    this->YAxes[i]->SetInnerGridlinesProperty(this->YAxesInnerGridlinesProperty);
146    this->YAxes[i]->SetGridpolysProperty(this->YAxesGridpolysProperty);
147    this->YAxes[i]->SetCalculateTitleOffset(0);
148    this->YAxes[i]->SetCalculateLabelOffset(0);
149
150    this->ZAxes[i] = vtkRpAxisActor::New();
151    this->ZAxes[i]->SetTickVisibility(1);
152    this->ZAxes[i]->SetMinorTicksVisible(1);
153    this->ZAxes[i]->SetLabelVisibility(1);
154    this->ZAxes[i]->SetTitleVisibility(1);
155    this->ZAxes[i]->SetAxisTypeToZ();
156    this->ZAxes[i]->SetAxisPosition(i);
157    this->ZAxes[i]->SetAxisLinesProperty(this->ZAxesLinesProperty);
158    this->ZAxes[i]->SetGridlinesProperty(this->ZAxesGridlinesProperty);
159    this->ZAxes[i]->SetInnerGridlinesProperty(this->ZAxesInnerGridlinesProperty);
160    this->ZAxes[i]->SetGridpolysProperty(this->ZAxesGridpolysProperty);
161    this->ZAxes[i]->SetCalculateTitleOffset(0);
162    this->ZAxes[i]->SetCalculateLabelOffset(0);
163
164    this->ScreenSize = 10.0;
165
166    this->LabelScreenOffset = 20.0 + this->ScreenSize * 0.5;
167    this->TitleScreenOffset =
168      this->LabelScreenOffset * 2.0 + this->ScreenSize * 0.5;
169
170    // Pass information to axes followers.
171    vtkRpAxisFollower* follower = this->XAxes[i]->GetTitleActor();
172    follower->SetAxis(this->XAxes[i]);
173    follower->SetScreenOffset(this->TitleScreenOffset);
174    follower->SetEnableDistanceLOD( this->EnableDistanceLOD );
175    follower->SetDistanceLODThreshold( this->DistanceLODThreshold );
176    follower->SetEnableViewAngleLOD( this->EnableViewAngleLOD );
177    follower->SetViewAngleLODThreshold( this->ViewAngleLODThreshold );
178
179    follower = this->YAxes[i]->GetTitleActor();
180    follower->SetAxis(this->YAxes[i]);
181    follower->SetScreenOffset(this->TitleScreenOffset);
182    follower->SetEnableDistanceLOD( this->EnableDistanceLOD );
183    follower->SetDistanceLODThreshold( this->DistanceLODThreshold );
184    follower->SetEnableViewAngleLOD( this->EnableViewAngleLOD );
185    follower->SetViewAngleLODThreshold( this->ViewAngleLODThreshold );
186
187    follower = this->ZAxes[i]->GetTitleActor();
188    follower->SetAxis(this->ZAxes[i]);
189    follower->SetScreenOffset(this->TitleScreenOffset);
190    follower->SetEnableDistanceLOD( this->EnableDistanceLOD );
191    follower->SetDistanceLODThreshold( this->DistanceLODThreshold );
192    follower->SetEnableViewAngleLOD( this->EnableViewAngleLOD );
193    follower->SetViewAngleLODThreshold( this->ViewAngleLODThreshold );
194    }
195
196  this->XTitle = new char[7];
197  sprintf(this->XTitle, "%s", "X-Axis");
198  this->XUnits = NULL;
199  this->YTitle = new char[7];
200  sprintf(this->YTitle, "%s", "Y-Axis");
201  this->YUnits = NULL;
202  this->ZTitle = new char[7];
203  sprintf(this->ZTitle, "%s", "Z-Axis");
204  this->ZUnits = NULL;
205
206  this->ActualXLabel = 0;
207  this->ActualYLabel = 0;
208  this->ActualZLabel = 0;
209
210  this->TickLocation = VTK_TICKS_INSIDE;
211
212  this->XAxisVisibility = 1;
213  this->YAxisVisibility = 1;
214  this->ZAxisVisibility = 1;
215
216  this->XAxisTickVisibility = 1;
217  this->YAxisTickVisibility = 1;
218  this->ZAxisTickVisibility = 1;
219
220  this->XAxisMinorTickVisibility = 1;
221  this->YAxisMinorTickVisibility = 1;
222  this->ZAxisMinorTickVisibility = 1;
223
224  this->XAxisLabelVisibility = 1;
225  this->YAxisLabelVisibility = 1;
226  this->ZAxisLabelVisibility = 1;
227
228  this->DrawXGridlines = 0;
229  this->DrawYGridlines = 0;
230  this->DrawZGridlines = 0;
231
232  this->DrawXInnerGridlines = 0;
233  this->DrawYInnerGridlines = 0;
234  this->DrawZInnerGridlines = 0;
235
236  this->DrawXGridpolys = 0;
237  this->DrawYGridpolys = 0;
238  this->DrawZGridpolys = 0;
239
240  this->XLabelFormat = new char[8];
241  sprintf(this->XLabelFormat, "%s", "%-#6.3g");
242  this->YLabelFormat = new char[8];
243  sprintf(this->YLabelFormat, "%s", "%-#6.3g");
244  this->ZLabelFormat = new char[8];
245  sprintf(this->ZLabelFormat, "%s", "%-#6.3g");
246
247  this->XAutoLabelFormat = 1;
248  this->YAutoLabelFormat = 1;
249  this->ZAutoLabelFormat = 1;
250
251  this->CornerOffset = 0.0;
252
253  this->Inertia = 1;
254
255  this->RenderCount = 0;
256
257  this->InertiaLocs[0] = this->InertiaLocs[1] = this->InertiaLocs[2] = -1;
258
259  this->RenderSomething = 0;
260
261  this->LastUseOrientedBounds = 0;
262
263  this->LastXPow = 0;
264  this->LastYPow = 0;
265  this->LastZPow = 0;
266
267  this->UserXPow = 0;
268  this->UserYPow = 0;
269  this->UserZPow = 0;
270
271  this->AutoLabelScaling = true;
272
273  this->LastXAxisDigits = 3;
274  this->LastYAxisDigits = 3;
275  this->LastZAxisDigits = 3;
276
277  this->LastXRange[0] = VTK_FLOAT_MAX;
278  this->LastXRange[1] = VTK_FLOAT_MAX;
279  this->LastYRange[0] = VTK_FLOAT_MAX;
280  this->LastYRange[1] = VTK_FLOAT_MAX;
281  this->LastZRange[0] = VTK_FLOAT_MAX;
282  this->LastZRange[1] = VTK_FLOAT_MAX;
283
284  this->LastBounds[0] = VTK_DOUBLE_MAX;
285  this->LastBounds[1] = VTK_DOUBLE_MAX;
286  this->LastBounds[2] = VTK_DOUBLE_MAX;
287  this->LastBounds[3] = VTK_DOUBLE_MAX;
288  this->LastBounds[4] = VTK_DOUBLE_MAX;
289  this->LastBounds[5] = VTK_DOUBLE_MAX;
290
291  this->LastFlyMode = -1;
292
293  for (int i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
294    {
295    this->RenderAxesX[i] = i;
296    this->RenderAxesY[i] = i;
297    this->RenderAxesZ[i] = i;
298    }
299  this->NumberOfAxesX = this->NumberOfAxesY = this->NumberOfAxesZ = 1;
300
301  this->MustAdjustXValue = false;
302  this->MustAdjustYValue = false;
303  this->MustAdjustZValue = false;
304
305  this->ForceXLabelReset = false;
306  this->ForceYLabelReset = false;
307  this->ForceZLabelReset = false;
308
309  this->XAxisRange[0] = VTK_DOUBLE_MAX;
310  this->XAxisRange[1] = VTK_DOUBLE_MAX;
311  this->YAxisRange[0] = VTK_DOUBLE_MAX;
312  this->YAxisRange[1] = VTK_DOUBLE_MAX;
313  this->ZAxisRange[0] = VTK_DOUBLE_MAX;
314  this->ZAxisRange[1] = VTK_DOUBLE_MAX;
315
316  for (int i = 0; i < 3; ++i)
317    {
318    this->AxisLabels[i] = NULL;
319    }
320  this->LabelScale = -1.0;
321  this->TitleScale = -1.0;
322}
323
324void vtkRpCubeAxesActor::SetUse2DMode( int val )
325{
326  for( int i = 0 ; i < NUMBER_OF_ALIGNED_AXIS ; ++ i )
327    {
328    this->XAxes[i]->SetUse2DMode( val );
329    this->YAxes[i]->SetUse2DMode( val );
330    this->ZAxes[i]->SetUse2DMode( val );
331    }
332  if( ! val )
333    {
334    this->SetZAxisVisibility( 1 );
335    }
336  else
337    {
338    this->SetZAxisVisibility( 0 );
339    }
340}
341
342int vtkRpCubeAxesActor::GetUse2DMode()
343{
344  // It is assumed that all axes have the same value
345  return this->XAxes[0]->GetUse2DMode();
346}
347
348void vtkRpCubeAxesActor::SetSaveTitlePosition( int val )
349{
350  // For 2D mode only :
351  //   val = 0: no need to save position (3D axis)
352  //   val = 1: positions have to be saved during the next render pass
353  //   val = 2: positions are saved -> use them
354  for( int i = 0 ; i < NUMBER_OF_ALIGNED_AXIS ; ++ i )
355    {
356    this->XAxes[i]->SetSaveTitlePosition( val );
357    this->YAxes[i]->SetSaveTitlePosition( val );
358    }
359}
360
361// ****************************************************************************
362vtkRpCubeAxesActor::~vtkRpCubeAxesActor()
363{
364  this->SetCamera(NULL);
365
366  for (int i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
367    {
368    if (this->XAxes[i])
369      {
370      this->XAxes[i]->Delete();
371      this->XAxes[i] = NULL;
372      }
373    if (this->YAxes[i])
374      {
375      this->YAxes[i]->Delete();
376      this->YAxes[i] = NULL;
377      }
378    if (this->ZAxes[i])
379      {
380      this->ZAxes[i]->Delete();
381      this->ZAxes[i] = NULL;
382      }
383    }
384
385  if (this->XAxesLinesProperty)
386    {
387    this->XAxesLinesProperty->Delete();
388    }
389  if (this->XAxesGridlinesProperty)
390    {
391    this->XAxesGridlinesProperty->Delete();
392    }
393  if (this->XAxesInnerGridlinesProperty)
394    {
395    this->XAxesInnerGridlinesProperty->Delete();
396    }
397  if (this->XAxesGridpolysProperty)
398    {
399    this->XAxesGridpolysProperty->Delete();
400    }
401  if (this->YAxesLinesProperty)
402    {
403    this->YAxesLinesProperty->Delete();
404    }
405  if (this->YAxesGridlinesProperty)
406    {
407    this->YAxesGridlinesProperty->Delete();
408    }
409  if (this->YAxesInnerGridlinesProperty)
410    {
411    this->YAxesInnerGridlinesProperty->Delete();
412    }
413  if (this->YAxesGridpolysProperty)
414    {
415    this->YAxesGridpolysProperty->Delete();
416    }
417  if (this->ZAxesLinesProperty)
418    {
419    this->ZAxesLinesProperty->Delete();
420    }
421  if (this->ZAxesGridlinesProperty)
422    {
423    this->ZAxesGridlinesProperty->Delete();
424    }
425  if (this->ZAxesInnerGridlinesProperty)
426    {
427    this->ZAxesInnerGridlinesProperty->Delete();
428    }
429  if (this->ZAxesGridpolysProperty)
430    {
431    this->ZAxesGridpolysProperty->Delete();
432    }
433
434  for (int i = 0; i < 3; i++)
435    {
436    if(this->TitleTextProperty[i] != NULL)
437      {
438      this->TitleTextProperty[i]->Delete();
439      }
440    this->TitleTextProperty[i] = NULL;
441
442    if(this->LabelTextProperty[i] != NULL)
443      {
444      this->LabelTextProperty[i]->Delete();
445      }
446    this->LabelTextProperty[i] = NULL;
447    }
448
449  if (this->XLabelFormat)
450    {
451    delete [] this->XLabelFormat;
452    this->XLabelFormat = NULL;
453    }
454
455  if (this->YLabelFormat)
456    {
457    delete [] this->YLabelFormat;
458    this->YLabelFormat = NULL;
459    }
460
461  if (this->ZLabelFormat)
462    {
463    delete [] this->ZLabelFormat;
464    this->ZLabelFormat = NULL;
465    }
466
467  if (this->XTitle)
468    {
469    delete [] this->XTitle;
470    this->XTitle = NULL;
471    }
472  if (this->YTitle)
473    {
474    delete [] this->YTitle;
475    this->YTitle = NULL;
476    }
477  if (this->ZTitle)
478    {
479    delete [] this->ZTitle;
480    this->ZTitle = NULL;
481    }
482
483  if (this->XUnits)
484    {
485    delete [] this->XUnits;
486    this->XUnits = NULL;
487    }
488  if (this->YUnits)
489    {
490    delete [] this->YUnits;
491    this->YUnits = NULL;
492    }
493  if (this->ZUnits)
494    {
495    delete [] this->ZUnits;
496    this->ZUnits = NULL;
497    }
498
499  if (this->ActualXLabel)
500    {
501    delete [] this->ActualXLabel;
502    this->ActualXLabel = NULL;
503    }
504  if (this->ActualYLabel)
505    {
506    delete [] this->ActualYLabel;
507    this->ActualYLabel = NULL;
508    }
509  if (this->ActualZLabel)
510    {
511    delete [] this->ActualZLabel;
512    this->ActualZLabel = NULL;
513    }
514}
515
516// *************************************************************************
517// Project the bounding box and compute edges on the border of the bounding
518// cube. Determine which parts of the edges are visible via intersection
519// with the boundary of the viewport (minus borders).
520// *************************************************************************
521int vtkRpCubeAxesActor::RenderOpaqueGeometry(vtkViewport *viewport)
522{
523  static bool initialRender = true;
524  return this->RenderGeometry(
525        initialRender, viewport, true,
526        &vtkRpAxisActor::RenderOpaqueGeometry);
527}
528
529// *************************************************************************
530// Project the bounding box and compute edges on the border of the bounding
531// cube. Determine which parts of the edges are visible via intersection
532// with the boundary of the viewport (minus borders).
533// *************************************************************************
534int vtkRpCubeAxesActor::RenderTranslucentGeometry(vtkViewport *viewport)
535{
536  static bool initialRender = true;
537  return this->RenderGeometry(
538        initialRender, viewport, true,
539        &vtkRpAxisActor::RenderTranslucentGeometry);
540}
541
542// *************************************************************************
543// Project the bounding box and compute edges on the border of the bounding
544// cube. Determine which parts of the edges are visible via intersection
545// with the boundary of the viewport (minus borders).
546// *************************************************************************
547int vtkRpCubeAxesActor::RenderTranslucentPolygonalGeometry(vtkViewport *viewport)
548{
549  static bool initialRender = true;
550  return this->RenderGeometry(
551        initialRender, viewport, true,
552        &vtkRpAxisActor::RenderTranslucentPolygonalGeometry);
553}
554
555// *************************************************************************
556// RenderOverlay : render 2D annotations.
557// *************************************************************************
558int vtkRpCubeAxesActor::RenderOverlay(vtkViewport *viewport)
559{
560  static bool initialRender = true;
561  return this->RenderGeometry(
562        initialRender, viewport, false,
563        &vtkRpAxisActor::RenderOverlay);
564}
565
566// --------------------------------------------------------------------------
567int vtkRpCubeAxesActor::HasTranslucentPolygonalGeometry()
568{
569  if ((this->NumberOfAxesX > 0 &&
570       this->XAxes[0]->HasTranslucentPolygonalGeometry()) ||
571      (this->NumberOfAxesY > 0 &&
572       this->YAxes[0]->HasTranslucentPolygonalGeometry()) ||
573      (this->NumberOfAxesZ > 0 &&
574       this->ZAxes[0]->HasTranslucentPolygonalGeometry()))
575    {
576    return 1;
577    }
578
579  return 0;
580}
581
582// --------------------------------------------------------------------------
583// Do final adjustment of axes to control offset, etc.
584void vtkRpCubeAxesActor::AdjustAxes(double bounds[6],
585                                  double xCoords[NUMBER_OF_ALIGNED_AXIS][6],
586                                  double yCoords[NUMBER_OF_ALIGNED_AXIS][6],
587                                  double zCoords[NUMBER_OF_ALIGNED_AXIS][6],
588                                  double xRange[2], double yRange[2],
589                                  double zRange[2])
590{
591  xRange[0] = (this->XAxisRange[0] == VTK_DOUBLE_MAX ?
592                                  bounds[0] : this->XAxisRange[0]);
593  xRange[1] = (this->XAxisRange[1] == VTK_DOUBLE_MAX ?
594                                  bounds[1] : this->XAxisRange[1]);
595  yRange[0] = (this->YAxisRange[0] == VTK_DOUBLE_MAX ?
596                                  bounds[2] : this->YAxisRange[0]);
597  yRange[1] = (this->YAxisRange[1] == VTK_DOUBLE_MAX ?
598                                  bounds[3] : this->YAxisRange[1]);
599  zRange[0] = (this->ZAxisRange[0] == VTK_DOUBLE_MAX ?
600                                  bounds[4] : this->ZAxisRange[0]);
601  zRange[1] = (this->ZAxisRange[1] == VTK_DOUBLE_MAX ?
602                                  bounds[5] : this->ZAxisRange[1]);
603
604  const double xScale = (xRange[1] - xRange[0])/(bounds[1] - bounds[0]);
605  const double yScale = (yRange[1] - yRange[0])/(bounds[3] - bounds[2]);
606  const double zScale = (zRange[1] - zRange[0])/(bounds[5] - bounds[4]);
607
608  // Pull back the corners if specified
609  if (this->CornerOffset > 0.0)
610    {
611    for (int i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
612      {
613      double ave;
614
615      // x-axis
616      ave = (xCoords[i][0] + xCoords[i][2]) / 2.0;
617      xCoords[i][0] =
618        xCoords[i][0] - this->CornerOffset * (xCoords[i][0] - ave);
619      xCoords[i][2] =
620        xCoords[i][2] - this->CornerOffset * (xCoords[i][2] - ave);
621
622      ave = (xCoords[i][1] + xCoords[i][3]) / 2.0;
623      xCoords[i][1] =
624        xCoords[i][1] - this->CornerOffset * (xCoords[i][1] - ave);
625      xCoords[i][3] =
626        xCoords[i][3] - this->CornerOffset * (xCoords[i][3] - ave);
627
628      ave = (xRange[1] + xRange[0]) / 2.0;
629      xRange[0] = xRange[0] - this->CornerOffset * xScale * (xRange[0] - ave);
630      xRange[1] = xRange[1] - this->CornerOffset * xScale * (xRange[1] - ave);
631
632      // y-axis
633      ave = (yCoords[i][0] + yCoords[i][2]) / 2.0;
634      yCoords[i][0] =
635        yCoords[i][0] - this->CornerOffset * (yCoords[i][0] - ave);
636      yCoords[i][2] =
637        yCoords[i][2] - this->CornerOffset * (yCoords[i][2] - ave);
638
639      ave = (yCoords[i][1] + yCoords[i][3]) / 2.0;
640      yCoords[i][1] =
641        yCoords[i][1] - this->CornerOffset * (yCoords[i][1] - ave);
642      yCoords[i][3] =
643        yCoords[i][3] - this->CornerOffset * (yCoords[i][3] - ave);
644
645      ave = (yRange[1] + yRange[0]) / 2.0;
646      yRange[0] = yRange[0] - this->CornerOffset * yScale * (yRange[0] - ave);
647      yRange[1] = yRange[1] - this->CornerOffset * yScale * (yRange[1] - ave);
648
649      // z-axis
650      ave = (zCoords[i][0] + zCoords[i][2]) / 2.0;
651      zCoords[i][0] =
652        zCoords[i][0] - this->CornerOffset * (zCoords[i][0] - ave);
653      zCoords[i][2] =
654        zCoords[i][2] - this->CornerOffset * (zCoords[i][2] - ave);
655
656      ave = (zCoords[i][1] + zCoords[i][3]) / 2.0;
657      zCoords[i][1] =
658        zCoords[i][1] - this->CornerOffset * (zCoords[i][1] - ave);
659      zCoords[i][3] =
660        zCoords[i][3] - this->CornerOffset * (zCoords[i][3] - ave);
661
662      ave = (zRange[1] + zRange[0]) / 2.0;
663      zRange[0] = zRange[0] - this->CornerOffset * zScale * (zRange[0] - ave);
664      zRange[1] = zRange[1] - this->CornerOffset * zScale * (zRange[1] - ave);
665      }
666    }
667}
668
669// *************************************************************************
670// Screen size affects the screen offset as well.
671// *************************************************************************
672void vtkRpCubeAxesActor::SetScreenSize(double screenSize)
673{
674  this->ScreenSize = screenSize;
675// Considering pivot point at center of the geometry hence (this->ScreenSize * 0.5).
676  this->LabelScreenOffset = 20.0 + this->ScreenSize * 0.5;
677  this->TitleScreenOffset = this->LabelScreenOffset * 2.0 +
678    this->ScreenSize * 0.5;
679
680  for (int i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
681    {
682    this->XAxes[i]->GetTitleActor()->SetScreenOffset(this->TitleScreenOffset);
683    this->YAxes[i]->GetTitleActor()->SetScreenOffset(this->TitleScreenOffset);
684    this->ZAxes[i]->GetTitleActor()->SetScreenOffset(this->TitleScreenOffset);
685
686    int numberOfLabelsBuild = this->XAxes[i]->GetNumberOfLabelsBuilt();
687    vtkRpAxisFollower **labelActors = this->XAxes[i]->GetLabelActors();
688    for(int k=0; k < numberOfLabelsBuild; ++k)
689      {
690      labelActors[k]->SetScreenOffset(this->LabelScreenOffset);
691      }
692
693    numberOfLabelsBuild = this->YAxes[i]->GetNumberOfLabelsBuilt();
694    labelActors = this->YAxes[i]->GetLabelActors();
695    for(int k=0; k < numberOfLabelsBuild; ++k)
696      {
697      labelActors[k]->SetScreenOffset(this->LabelScreenOffset);
698      }
699
700    numberOfLabelsBuild = this->ZAxes[i]->GetNumberOfLabelsBuilt();
701    labelActors = this->ZAxes[i]->GetLabelActors();
702    for(int k=0; k < numberOfLabelsBuild; ++k)
703      {
704      labelActors[k]->SetScreenOffset(this->LabelScreenOffset);
705      }
706    }
707
708  this->Modified();
709}
710
711// *************************************************************************
712// Release any graphics resources that are being consumed by this actor.
713// The parameter window could be used to determine which graphic
714// resources to release.
715// *************************************************************************
716void vtkRpCubeAxesActor::ReleaseGraphicsResources(vtkWindow *win)
717{
718  for (int i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
719    {
720    this->XAxes[i]->ReleaseGraphicsResources(win);
721    this->YAxes[i]->ReleaseGraphicsResources(win);
722    this->ZAxes[i]->ReleaseGraphicsResources(win);
723    }
724}
725
726// ******************************************************************
727void vtkRpCubeAxesActor::PrintSelf(ostream& os, vtkIndent indent)
728{
729  this->Superclass::PrintSelf(os,indent);
730
731  os << indent << "Bounds: \n";
732  os << indent << "  Xmin,Xmax: (" << this->Bounds[0] << ", "
733     << this->Bounds[1] << ")" << endl;
734  os << indent << "  Ymin,Ymax: (" << this->Bounds[2] << ", "
735     << this->Bounds[3] << ")" << endl;
736  os << indent << "  Zmin,Zmax: (" << this->Bounds[4] << ", "
737     << this->Bounds[5] << ")" << endl;
738
739
740  os << indent << "XAxisRange: [" << this->XAxisRange[0] << ", "
741    << this->XAxisRange[1] << "] " << endl;
742  os << indent << "YAxisRange: [" << this->YAxisRange[0] << ", "
743    << this->YAxisRange[1] << "] " << endl;
744  os << indent << "ZAxisRange: [" << this->ZAxisRange[0] << ", "
745    << this->ZAxisRange[1] << "] " << endl;
746
747  os << indent << "ScreenSize: (" << this->ScreenSize << ")" << endl;
748
749  if (this->Camera)
750    {
751    os << indent << "Camera:\n";
752    this->Camera->PrintSelf(os,indent.GetNextIndent());
753    }
754  else
755    {
756    os << indent << "Camera: (none)\n";
757    }
758
759  os << indent << "RebuildAxes: " << this->RebuildAxes << endl;
760
761  if (this->FlyMode == VTK_FLY_CLOSEST_TRIAD)
762    {
763    os << indent << "Fly Mode: CLOSEST_TRIAD"<< endl;
764    }
765  else if (this->FlyMode == VTK_FLY_FURTHEST_TRIAD)
766    {
767    os << indent << "Fly Mode: FURTHEST_TRIAD"<< endl;
768    }
769  else if (this->FlyMode == VTK_FLY_STATIC_TRIAD)
770    {
771    os << indent << "Fly Mode: STATIC_TRIAD"<< endl;
772    }
773  else if (this->FlyMode == VTK_FLY_STATIC_EDGES)
774    {
775    os << indent << "Fly Mode: STATIC_EDGES"<< endl;
776    }
777  else
778    {
779    os << indent << "Fly Mode: OUTER_EDGES"<< endl;
780    }
781
782  os << indent << "EnableDistanceLOD: "
783     << ( this->EnableDistanceLOD ? "On" : "Off" ) << endl;
784  os << indent << "DistanceLODThreshold: "   << this->DistanceLODThreshold << endl;
785
786  os << indent << "EnableViewAngleLOD: "
787     << ( this->EnableViewAngleLOD ? "On" : "Off" ) << endl;
788  os << indent << "ViewAngleLODThreshold: "   << this->ViewAngleLODThreshold << endl;
789
790  os << indent << "X Axis Title: " << this->XTitle << endl;
791  os << indent << "Y Axis Title: " << this->YTitle << endl;
792  os << indent << "Z Axis Title: " << this->ZTitle << endl;
793
794  os << indent << "X Axis Visibility: "
795     << (this->XAxisVisibility ? "On\n" : "Off\n");
796  os << indent << "Y Axis Visibility: "
797     << (this->YAxisVisibility ? "On\n" : "Off\n");
798  os << indent << "Z Axis Visibility: "
799     << (this->ZAxisVisibility ? "On\n" : "Off\n");
800
801  os << indent << "X Axis Label Format: " << this->XLabelFormat << endl;
802  os << indent << "Y Axis Label Format: " << this->YLabelFormat << endl;
803  os << indent << "Z Axis Label Format: " << this->ZLabelFormat << endl;
804
805  os << indent << "XAutoLabelFormat: "
806     << (this->XAutoLabelFormat ? "On" : "Off") << endl;
807  os << indent << "YAutoLabelFormat: "
808     << (this->YAutoLabelFormat ? "On" : "Off") << endl;
809  os << indent << "ZAutoLabelFormat: "
810     << (this->ZAutoLabelFormat ? "On" : "Off") << endl;
811
812  os << indent << "Inertia: " << this->Inertia << endl;
813  os << indent << "Corner Offset: " << this->CornerOffset << endl;
814
815  os << indent << "XAxisTickVisibility: "
816     << (this->XAxisTickVisibility ? "On" : "Off") << endl;
817  os << indent << "YAxisTickVisibility: "
818     << (this->YAxisTickVisibility ? "On" : "Off") << endl;
819  os << indent << "ZAxisTickVisibility: "
820     << (this->ZAxisTickVisibility ? "On" : "Off") << endl;
821
822  os << indent << "XAxisMinorTickVisibility: "
823     << (this->XAxisMinorTickVisibility ? "On" : "Off") << endl;
824  os << indent << "YAxisMinorTickVisibility: "
825     << (this->YAxisMinorTickVisibility ? "On" : "Off") << endl;
826  os << indent << "ZAxisMinorTickVisibility: "
827     << (this->ZAxisMinorTickVisibility ? "On" : "Off") << endl;
828
829  os << indent << "XAxisLabelVisibility: "
830     << (this->XAxisLabelVisibility ? "On" : "Off") << endl;
831  os << indent << "YAxisLabelVisibility: "
832     << (this->YAxisLabelVisibility ? "On" : "Off") << endl;
833  os << indent << "ZAxisLabelVisibility: "
834     << (this->ZAxisLabelVisibility ? "On" : "Off") << endl;
835
836  os << indent << "XUnits: "
837     << (this->XUnits ? this->XUnits : "(none)") << endl;
838  os << indent << "YUnits: "
839     << (this->YUnits ? this->YUnits : "(none)") << endl;
840  os << indent << "ZUnits: "
841     << (this->ZUnits ? this->ZUnits : "(none)") << endl;
842
843  os << indent << "TickLocation: " << this->TickLocation << endl;
844
845  os << indent << "DrawXGridlines: " << this->DrawXGridlines << endl;
846  os << indent << "DrawYGridlines: " << this->DrawYGridlines << endl;
847  os << indent << "DrawZGridlines: " << this->DrawZGridlines << endl;
848
849  switch(this->GridLineLocation)
850    {
851  case VTK_GRID_LINES_ALL:
852    os << indent << "GridLineLocation: VTK_GRID_LINES_ALL (0)" << endl;
853    break;
854  case VTK_GRID_LINES_CLOSEST:
855    os << indent << "GridLineLocation: VTK_GRID_LINES_CLOSEST (1)" << endl;
856    break;
857  case VTK_GRID_LINES_FURTHEST:
858    os << indent << "GridLineLocation: VTK_GRID_LINES_FURTHEST (2)" << endl;
859    break;
860    }
861
862  os << indent << "DrawXInnerGridlines: " << this->DrawXInnerGridlines << endl;
863  os << indent << "DrawYInnerGridlines: " << this->DrawYInnerGridlines << endl;
864  os << indent << "DrawZInnerGridlines: " << this->DrawZInnerGridlines << endl;
865
866  os << indent << "DrawXGridpolys: " << this->DrawXGridpolys << endl;
867  os << indent << "DrawYGridpolys: " << this->DrawYGridpolys << endl;
868  os << indent << "DrawZGridpolys: " << this->DrawZGridpolys << endl;
869
870
871  os << indent << "UseOrientedBounds: " << this->UseOrientedBounds << endl;
872  if(this->UseOrientedBounds)
873    {
874    os << indent << "OrientedBounds: \n";
875    os << indent << "  Xmin,Xmax: (" << this->OrientedBounds[0] << ", "
876       << this->OrientedBounds[1] << ")" << endl;
877    os << indent << "  Ymin,Ymax: (" << this->OrientedBounds[2] << ", "
878       << this->OrientedBounds[3] << ")" << endl;
879    os << indent << "  Zmin,Zmax: (" << this->OrientedBounds[4] << ", "
880       << this->OrientedBounds[5] << ")" << endl;
881    }
882
883  os << indent << "Base: \n";
884  os << indent << "  For X: (" << this->AxisBaseForX[0] << ", "
885     << this->AxisBaseForX[1] << ", " << this->AxisBaseForX[2] << ")" << endl;
886  os << indent << "  For Y: (" << this->AxisBaseForY[0] << ", "
887     << this->AxisBaseForY[1] << ", " << this->AxisBaseForY[2] << ")" << endl;
888  os << indent << "  For Z: (" << this->AxisBaseForZ[0] << ", "
889     << this->AxisBaseForZ[1] << ", " << this->AxisBaseForZ[2] << ")" << endl;
890
891  os << indent << "UseAxisOrigin: " << this->UseAxisOrigin << endl;
892  if(this->UseAxisOrigin)
893    {
894    os << indent << "AxisOrigin: (" << this->AxisOrigin[0] << ", "
895       << this->AxisOrigin[1] << ", " << this->AxisOrigin[2] << ")" << endl;
896    }
897}
898
899// --------------------------------------------------------------------------
900void vtkRpCubeAxesActor::TransformBounds(vtkViewport *viewport,
901                                       const double bounds[6],
902                                       double pts[8][3])
903{
904  double x[3];
905
906  //loop over verts of bounding box
907  for ( int k = 0; k < 2; ++ k )
908    {
909    x[2] = bounds[4 + k];
910    for ( int j = 0; j < 2; ++ j )
911      {
912      x[1] = bounds[2 + j];
913      for ( int i = 0; i < 2; ++ i )
914        {
915        int idx = i + 2 * j + 4 * k;
916        x[0] = bounds[i];
917        viewport->SetWorldPoint( x[0], x[1], x[2], 1. );
918        viewport->WorldToDisplay();
919        viewport->GetDisplayPoint( pts[idx] );
920        }
921      }
922    }
923}
924
925// ***********************************************************************
926//  Calculate the size (length) of major and minor ticks,
927//  based on an average of the coordinate direction ranges.
928//  Set the necessary Axes methods with the calculated information.
929//
930//  Returns:  false if tick size not recomputed, true otherwise.
931// ***********************************************************************
932bool vtkRpCubeAxesActor::ComputeTickSize(double bounds[6])
933{
934  bool xPropsChanged = this->LabelTextProperty[0]->GetMTime() > this->BuildTime.GetMTime();
935  bool yPropsChanged = this->LabelTextProperty[1]->GetMTime() > this->BuildTime.GetMTime();
936  bool zPropsChanged = this->LabelTextProperty[2]->GetMTime() > this->BuildTime.GetMTime();
937
938  bool xRangeChanged = this->LastXRange[0] != this->XAxisRange[0] ||
939                       this->LastXRange[1] != this->XAxisRange[1];
940
941  bool yRangeChanged = this->LastYRange[0] != this->YAxisRange[0] ||
942                       this->LastYRange[1] != this->YAxisRange[1];
943
944  bool zRangeChanged = this->LastZRange[0] != this->ZAxisRange[0] ||
945                       this->LastZRange[1] != this->ZAxisRange[1];
946
947  bool boundsChanged = this->LastBounds[0] != bounds[0] ||
948                       this->LastBounds[1] != bounds[1] ||
949                       this->LastBounds[2] != bounds[2] ||
950                       this->LastBounds[3] != bounds[3] ||
951                       this->LastBounds[4] != bounds[4] ||
952                       this->LastBounds[5] != bounds[5];
953
954  if (!(xRangeChanged || yRangeChanged || zRangeChanged) &&
955      !(xPropsChanged || yPropsChanged || zPropsChanged || boundsChanged))
956    {
957    // no need to re-compute ticksize.
958    return false;
959    }
960
961  double xExt = bounds[1] - bounds[0];
962  double yExt = bounds[3] - bounds[2];
963  double zExt = bounds[5] - bounds[4];
964
965  if (xRangeChanged || boundsChanged)
966    {
967    this->AdjustTicksComputeRange(this->XAxes, bounds[0], bounds[1]);
968    this->BuildLabels(this->XAxes);
969    this->UpdateLabels(this->XAxes, 0);
970    }
971  if (yRangeChanged || boundsChanged)
972    {
973    this->AdjustTicksComputeRange(this->YAxes, bounds[2], bounds[3]);
974    this->BuildLabels(this->YAxes);
975    this->UpdateLabels(this->YAxes, 1);
976    }
977  if (zRangeChanged || boundsChanged)
978    {
979    this->AdjustTicksComputeRange(this->ZAxes, bounds[4], bounds[5]);
980    this->BuildLabels(this->ZAxes);
981    this->UpdateLabels(this->ZAxes, 2);
982    }
983
984  // We give information on deltas for the inner grid lines generation
985  for(int i = 0 ; i < NUMBER_OF_ALIGNED_AXIS ; i++)
986    {
987    for(int j = 0 ; j < 3 ; j++)
988      {
989      this->XAxes[i]->SetMajorStart(j,this->MajorStart[j]);
990      this->XAxes[i]->SetDeltaMajor(j,this->DeltaMajor[j]);
991      this->YAxes[i]->SetMajorStart(j,this->MajorStart[j]);
992      this->YAxes[i]->SetDeltaMajor(j,this->DeltaMajor[j]);
993      this->ZAxes[i]->SetMajorStart(j,this->MajorStart[j]);
994      this->ZAxes[i]->SetDeltaMajor(j,this->DeltaMajor[j]);
995      }
996    }
997
998  this->LastXRange[0] = (this->XAxisRange[0] == VTK_DOUBLE_MAX ?
999                                  bounds[0] : this->XAxisRange[0]);
1000  this->LastXRange[1] = (this->XAxisRange[1] == VTK_DOUBLE_MAX ?
1001                                  bounds[1] : this->XAxisRange[1]);
1002  this->LastYRange[0] = (this->YAxisRange[0] == VTK_DOUBLE_MAX ?
1003                                  bounds[2] : this->YAxisRange[0]);
1004  this->LastYRange[1] = (this->YAxisRange[1] == VTK_DOUBLE_MAX ?
1005                                  bounds[3] : this->YAxisRange[1]);
1006  this->LastZRange[0] = (this->ZAxisRange[0] == VTK_DOUBLE_MAX ?
1007                                  bounds[4] : this->ZAxisRange[0]);
1008  this->LastZRange[1] = (this->ZAxisRange[1] == VTK_DOUBLE_MAX ?
1009                                  bounds[5] : this->ZAxisRange[1]);
1010  for(int i=0; i < 6; i++)
1011    {
1012    this->LastBounds[i] = bounds[i];
1013    }
1014
1015  double major = 0.02 * (xExt + yExt + zExt) / 3.;
1016  double minor = 0.5 * major;
1017  for (int i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
1018    {
1019    this->XAxes[i]->SetMajorTickSize(major);
1020    this->XAxes[i]->SetMinorTickSize(minor);
1021
1022    this->YAxes[i]->SetMajorTickSize(major);
1023    this->YAxes[i]->SetMinorTickSize(minor);
1024
1025    this->ZAxes[i]->SetMajorTickSize(major);
1026    this->ZAxes[i]->SetMinorTickSize(minor);
1027
1028    this->XAxes[i]->SetGridlineXLength(xExt);
1029    this->XAxes[i]->SetGridlineYLength(yExt);
1030    this->XAxes[i]->SetGridlineZLength(zExt);
1031
1032    this->YAxes[i]->SetGridlineXLength(xExt);
1033    this->YAxes[i]->SetGridlineYLength(yExt);
1034    this->YAxes[i]->SetGridlineZLength(zExt);
1035
1036    this->ZAxes[i]->SetGridlineXLength(xExt);
1037    this->ZAxes[i]->SetGridlineYLength(yExt);
1038    this->ZAxes[i]->SetGridlineZLength(zExt);
1039    }
1040  return true;
1041}
1042
1043// ****************************************************************************
1044//  Method: vtkRpCubeAxesActor::AdjustValues
1045//
1046//  Purpose:
1047//      If the range of values is too big or too small, put them in scientific
1048//      notation and changes the labels.
1049//
1050//  Arguments:
1051//      bnds     The min/max values in each coordinate direction:
1052//                 (min_x, max_x, min_y, max_y, min_z, max_x).
1053//
1054//  Note:       This code is partially stolen from old MeshTV code,
1055//              /meshtvx/toolkit/plotgrid.c, axlab[x|y].
1056//
1057// ****************************************************************************
1058void vtkRpCubeAxesActor::AdjustValues(const double xRange[2],
1059                                    const double yRange[2],
1060                                    const double zRange[2])
1061{
1062  char xTitle[64];
1063
1064  int xPow, yPow, zPow;
1065
1066  if (AutoLabelScaling)
1067    {
1068    if (this->AxisLabels[0] == NULL)
1069      {
1070      xPow = this->LabelExponent(xRange[0], xRange[1]);
1071      }
1072    else
1073      {
1074      xPow = 0;
1075      }
1076    if (this->AxisLabels[1] == NULL)
1077      {
1078      yPow = this->LabelExponent(yRange[0], yRange[1]);
1079      }
1080    else
1081      {
1082      yPow = 0;
1083      }
1084    if (this->AxisLabels[2] == NULL)
1085      {
1086      zPow = this->LabelExponent(zRange[0], zRange[1]);
1087      }
1088    else
1089      {
1090      zPow = 0;
1091      }
1092    }
1093  else
1094    {
1095    xPow = UserXPow;
1096    yPow = UserYPow;
1097    zPow = UserZPow;
1098    }
1099
1100  if (xPow != 0)
1101    {
1102    if (!this->MustAdjustXValue || this->LastXPow != xPow)
1103      {
1104      this->ForceXLabelReset = true;
1105      }
1106    else
1107      {
1108      this->ForceXLabelReset = false;
1109      }
1110    this->MustAdjustXValue = true;
1111
1112    if (XUnits == NULL || XUnits[0] == '\0')
1113      {
1114      sprintf(xTitle, "%s (x10^%d)", this->XTitle, xPow);
1115      }
1116    else
1117      {
1118      sprintf(xTitle, "%s (x10^%d %s)", this->XTitle, xPow, XUnits);
1119      }
1120    }
1121  else
1122    {
1123    if (this->MustAdjustXValue)
1124      {
1125      this->Modified();
1126      this->ForceXLabelReset = true;
1127      }
1128    else
1129      {
1130      this->ForceXLabelReset = false;
1131      }
1132    this->MustAdjustXValue = false;
1133
1134    if (XUnits == NULL || XUnits[0] == '\0')
1135      {
1136      sprintf(xTitle,"%s",this->XTitle);
1137      }
1138    else
1139      {
1140      sprintf(xTitle, "%s (%s)", this->XTitle, XUnits);
1141      }
1142    }
1143
1144  char yTitle[64];
1145  if (yPow != 0)
1146    {
1147    if (!this->MustAdjustYValue || this->LastYPow != yPow)
1148      {
1149      this->ForceYLabelReset = true;
1150      }
1151    else
1152      {
1153      this->ForceYLabelReset = false;
1154      }
1155    this->MustAdjustYValue = true;
1156    if (YUnits == NULL || YUnits[0] == '\0')
1157      {
1158      sprintf(yTitle, "%s (x10^%d)", this->YTitle, yPow);
1159      }
1160    else
1161      {
1162      sprintf(yTitle, "%s (x10^%d %s)", this->YTitle, yPow, YUnits);
1163      }
1164    }
1165  else
1166    {
1167    if (this->MustAdjustYValue)
1168      {
1169      this->Modified();
1170      this->ForceYLabelReset = true;
1171      }
1172    else
1173      {
1174      this->ForceYLabelReset = false;
1175      }
1176    this->MustAdjustYValue = false;
1177    if (YUnits == NULL || YUnits[0] == '\0')
1178      {
1179      sprintf(yTitle,"%s",this->YTitle);
1180      }
1181    else
1182      {
1183      sprintf(yTitle, "%s (%s)", this->YTitle, YUnits);
1184      }
1185    }
1186
1187  char zTitle[64];
1188  if (zPow != 0)
1189    {
1190    if (!this->MustAdjustZValue || this->LastZPow != zPow)
1191      {
1192      this->ForceZLabelReset = true;
1193      }
1194    else
1195      {
1196      this->ForceZLabelReset = false;
1197      }
1198    this->MustAdjustZValue = true;
1199
1200    if (ZUnits == NULL || ZUnits[0] == '\0')
1201      {
1202      sprintf(zTitle, "%s (x10^%d)", this->ZTitle, zPow);
1203      }
1204    else
1205      {
1206      sprintf(zTitle, "%s (x10^%d %s)", this->ZTitle, zPow, ZUnits);
1207      }
1208    }
1209  else
1210    {
1211    if (this->MustAdjustZValue)
1212      {
1213      this->Modified();
1214      this->ForceZLabelReset = true;
1215      }
1216    else
1217      {
1218      this->ForceZLabelReset = false;
1219      }
1220    this->MustAdjustZValue = false;
1221
1222    if (ZUnits == NULL || ZUnits[0] == '\0')
1223      {
1224      sprintf(zTitle,"%s",this->ZTitle);
1225      }
1226    else
1227      {
1228      sprintf(zTitle, "%s (%s)", this->ZTitle, ZUnits);
1229      }
1230    }
1231
1232  this->LastXPow = xPow;
1233  this->LastYPow = yPow;
1234  this->LastZPow = zPow;
1235
1236  this->SetActualXLabel(xTitle);
1237  this->SetActualYLabel(yTitle);
1238  this->SetActualZLabel(zTitle);
1239}
1240
1241// ****************************************************************************
1242//  Method: vtkRpCubeAxesActor::AdjustRange
1243//
1244//  Purpose:
1245//    If the range is small, adjust the precision of the values displayed.
1246//
1247//  Arguments:
1248//    bnds    The minimum and maximum values in each coordinate direction
1249//            (min_x, max_x, min_y, max_y, min_z, max_z).
1250// ****************************************************************************
1251void vtkRpCubeAxesActor::AdjustRange(const double bnds[6])
1252{
1253  if (this->XAutoLabelFormat)
1254    {
1255    double xrange[2];
1256
1257    xrange[0] = (this->XAxisRange[0] == VTK_DOUBLE_MAX ?
1258                                    bnds[0] : this->XAxisRange[0]);
1259    xrange[1] = (this->XAxisRange[1] == VTK_DOUBLE_MAX ?
1260                                    bnds[1] : this->XAxisRange[1]);
1261    if (this->LastXPow != 0)
1262      {
1263      xrange[0] /= pow(10., this->LastXPow);
1264      xrange[1] /= pow(10., this->LastXPow);
1265      }
1266
1267    int xAxisDigits = this->Digits(xrange[0], xrange[1]);
1268    if (xAxisDigits != this->LastXAxisDigits)
1269      {
1270      char  format[16];
1271      sprintf(format, "%%.%df", xAxisDigits);
1272      this->SetXLabelFormat(format);
1273      this->LastXAxisDigits = xAxisDigits;
1274      }
1275    }
1276  if (this->YAutoLabelFormat)
1277    {
1278    double yrange[2];
1279
1280    yrange[0] = (this->YAxisRange[0] == VTK_DOUBLE_MAX ?
1281                                    bnds[2] : this->YAxisRange[0]);
1282    yrange[1] = (this->YAxisRange[1] == VTK_DOUBLE_MAX ?
1283                                    bnds[3] : this->YAxisRange[1]);
1284
1285    if (this->LastYPow != 0)
1286      {
1287      yrange[0] /= pow(10., this->LastYPow);
1288      yrange[1] /= pow(10., this->LastYPow);
1289      }
1290
1291    int yAxisDigits = this->Digits(yrange[0], yrange[1]);
1292    if (yAxisDigits != this->LastYAxisDigits)
1293      {
1294      char  format[16];
1295      sprintf(format, "%%.%df", yAxisDigits);
1296      this->SetYLabelFormat(format);
1297      this->LastYAxisDigits = yAxisDigits;
1298      }
1299    }
1300  if (this->ZAutoLabelFormat)
1301    {
1302    double zrange[2];
1303
1304    zrange[0] = (this->ZAxisRange[0] == VTK_DOUBLE_MAX ?
1305                                    bnds[4] : this->ZAxisRange[0]);
1306    zrange[1] = (this->ZAxisRange[1] == VTK_DOUBLE_MAX ?
1307                                    bnds[5] : this->ZAxisRange[1]);
1308
1309    if (this->LastZPow != 0)
1310      {
1311      zrange[0] /= pow(10., this->LastZPow);
1312      zrange[1] /= pow(10., this->LastZPow);
1313      }
1314 
1315    int zAxisDigits = this->Digits(zrange[0], zrange[1]);
1316    if (zAxisDigits != this->LastZAxisDigits)
1317      {
1318      char  format[16];
1319      sprintf(format, "%%.%df", zAxisDigits);
1320      this->SetZLabelFormat(format);
1321      this->LastZAxisDigits = zAxisDigits;
1322      }
1323    }
1324}
1325
1326// ****************************************************************************
1327//  Method: Digits
1328//
1329//  Purpose:
1330//      Determines the appropriate number of digits for a given range.
1331//
1332//  Arguments:
1333//      min    The minimum value in the range.
1334//      max    The maximum value in the range.
1335//
1336//  Returns:   The appropriate number of digits.
1337// ****************************************************************************
1338int vtkRpCubeAxesActor::Digits(double min, double max )
1339{
1340  double  range = max - min;
1341  double  pow10   = log10(range);
1342  int    ipow10  = static_cast<int>(floor(pow10));
1343  int    digitsPastDecimal = -ipow10;
1344
1345  if (digitsPastDecimal < 0)
1346    {
1347    //
1348    // The range is more than 10, but not so big we need scientific
1349    // notation, we don't need to worry about decimals.
1350    //
1351    digitsPastDecimal = 0;
1352    }
1353  else
1354    {
1355    //
1356    // We want one more than the range since there is more than one
1357    // tick per decade.
1358    //
1359    digitsPastDecimal++;
1360
1361    //
1362    // Anything more than 5 is just noise.  (and probably 5 is noise with
1363    // doubleing point if the part before the decimal is big).
1364    //
1365    if (digitsPastDecimal > 5)
1366      {
1367      digitsPastDecimal = 5;
1368      }
1369    }
1370
1371  return digitsPastDecimal;
1372}
1373
1374// ****************************************************************************
1375//  Method: LabelExponent
1376//
1377//  Purpose:
1378//      Determines the proper exponent for the min and max values.
1379//
1380//  Arguments:
1381//      min     The minimum value along a certain axis.
1382//      max     The maximum value along a certain axis.
1383//
1384//  Note:       This code is mostly stolen from old MeshTV code,
1385//              /meshtvx/toolkit/plotgrid.c, axlab_format.
1386// ****************************************************************************
1387
1388int vtkRpCubeAxesActor::LabelExponent(double min, double max)
1389{
1390  if (min == max)
1391    {
1392    return 0;
1393    }
1394
1395  //
1396  // Determine power of 10 to scale axis labels to.
1397  //
1398  double range = (fabs(min) > fabs(max) ? fabs(min) : fabs(max));
1399  double pow10 = log10(range);
1400
1401  //
1402  // Cutoffs for using scientific notation.  The following 4 variables
1403  // should all be static for maximum performance but were made non-static
1404  // to get around a compiler bug with the MIPSpro 7.2.1.3 compiler.
1405  //
1406  double eformat_cut_min = -1.5;
1407  double eformat_cut_max =  3.0;
1408  double cut_min = pow(10., eformat_cut_min);
1409  double cut_max = pow(10., eformat_cut_max);
1410  double ipow10;
1411  if (range < cut_min || range > cut_max)
1412    {
1413    //
1414    // We are going to use scientific notation and round the exponents to
1415    // the nearest multiple of three.
1416    //
1417    ipow10 = (floor(floor(pow10)/3.))*3;
1418    }
1419  else
1420    {
1421    ipow10 = 0;
1422    }
1423
1424  return static_cast<int>(ipow10);
1425}
1426
1427// *************************************************************************
1428//  Build the axes. Determine coordinates, position, etc.
1429// *************************************************************************
1430void vtkRpCubeAxesActor::BuildAxes(vtkViewport *viewport)
1431{
1432  if ((this->GetMTime() < this->BuildTime.GetMTime()))
1433    {
1434    this->AutoScale(viewport);
1435    return;
1436    }
1437
1438  this->SetNonDependentAttributes();
1439
1440  // Reset range in case of bounds type changed
1441  if(this->LastUseOrientedBounds != this->UseOrientedBounds)
1442    {
1443    this->XAxisRange[0] = this->XAxisRange[1] = VTK_DOUBLE_MAX;
1444    this->YAxisRange[0] = this->YAxisRange[1] = VTK_DOUBLE_MAX;
1445    this->ZAxisRange[0] = this->ZAxisRange[1] = VTK_DOUBLE_MAX;
1446    this->LastUseOrientedBounds = this->UseOrientedBounds;
1447    }
1448
1449  // determine the bounds to use (input, prop, or user-defined)
1450  double bounds[6];
1451  if(this->UseOrientedBounds != 0)
1452    {
1453    this->GetOrientedBounds(bounds);
1454    }
1455  else
1456    {
1457    this->GetBounds(bounds);
1458    }
1459
1460  // Setup the axes for plotting
1461  double xCoords[NUMBER_OF_ALIGNED_AXIS][6];
1462  double yCoords[NUMBER_OF_ALIGNED_AXIS][6];
1463  double zCoords[NUMBER_OF_ALIGNED_AXIS][6];
1464
1465  // these arrays are accessed by 'location':  mm, mX, XX, or Xm.
1466  int mm1[4] = { 0, 0, 1, 1 };
1467  int mm2[4] = { 0, 1, 1, 0 };
1468
1469  // Compute axes end-points
1470  int i;
1471  for (i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
1472    {
1473    if(this->UseAxisOrigin == 0)
1474      {
1475      xCoords[i][0] = bounds[0]*this->AxisBaseForX[0] + bounds[2+mm1[i]]*this->AxisBaseForY[0] + bounds[4+mm2[i]]*this->AxisBaseForZ[0];
1476      xCoords[i][1] = bounds[0]*this->AxisBaseForX[1] + bounds[2+mm1[i]]*this->AxisBaseForY[1] + bounds[4+mm2[i]]*this->AxisBaseForZ[1];
1477      xCoords[i][2] = bounds[0]*this->AxisBaseForX[2] + bounds[2+mm1[i]]*this->AxisBaseForY[2] + bounds[4+mm2[i]]*this->AxisBaseForZ[2];
1478      xCoords[i][3] = bounds[1]*this->AxisBaseForX[0] + bounds[2+mm1[i]]*this->AxisBaseForY[0] + bounds[4+mm2[i]]*this->AxisBaseForZ[0];
1479      xCoords[i][4] = bounds[1]*this->AxisBaseForX[1] + bounds[2+mm1[i]]*this->AxisBaseForY[1] + bounds[4+mm2[i]]*this->AxisBaseForZ[1];
1480      xCoords[i][5] = bounds[1]*this->AxisBaseForX[2] + bounds[2+mm1[i]]*this->AxisBaseForY[2] + bounds[4+mm2[i]]*this->AxisBaseForZ[2];
1481      }
1482    else
1483      {
1484      xCoords[i][0] = bounds[0]*this->AxisBaseForX[0] + this->AxisOrigin[1]*this->AxisBaseForY[0] + this->AxisOrigin[2]*this->AxisBaseForZ[0];
1485      xCoords[i][1] = bounds[0]*this->AxisBaseForX[1] + this->AxisOrigin[1]*this->AxisBaseForY[1] + this->AxisOrigin[2]*this->AxisBaseForZ[1];
1486      xCoords[i][2] = bounds[0]*this->AxisBaseForX[2] + this->AxisOrigin[1]*this->AxisBaseForY[2] + this->AxisOrigin[2]*this->AxisBaseForZ[2];
1487      xCoords[i][3] = bounds[1]*this->AxisBaseForX[0] + this->AxisOrigin[1]*this->AxisBaseForY[0] + this->AxisOrigin[2]*this->AxisBaseForZ[0];
1488      xCoords[i][4] = bounds[1]*this->AxisBaseForX[1] + this->AxisOrigin[1]*this->AxisBaseForY[1] + this->AxisOrigin[2]*this->AxisBaseForZ[1];
1489      xCoords[i][5] = bounds[1]*this->AxisBaseForX[2] + this->AxisOrigin[1]*this->AxisBaseForY[2] + this->AxisOrigin[2]*this->AxisBaseForZ[2];
1490      }
1491
1492    if(this->UseAxisOrigin == 0)
1493      {
1494      yCoords[i][0] = bounds[2]*this->AxisBaseForY[0] + bounds[0+mm1[i]]*this->AxisBaseForX[0] + bounds[4+mm2[i]]*this->AxisBaseForZ[0];
1495      yCoords[i][1] = bounds[2]*this->AxisBaseForY[1] + bounds[0+mm1[i]]*this->AxisBaseForX[1] + bounds[4+mm2[i]]*this->AxisBaseForZ[1];
1496      yCoords[i][2] = bounds[2]*this->AxisBaseForY[2] + bounds[0+mm1[i]]*this->AxisBaseForX[2] + bounds[4+mm2[i]]*this->AxisBaseForZ[2];
1497      yCoords[i][3] = bounds[3]*this->AxisBaseForY[0] + bounds[0+mm1[i]]*this->AxisBaseForX[0] + bounds[4+mm2[i]]*this->AxisBaseForZ[0];
1498      yCoords[i][4] = bounds[3]*this->AxisBaseForY[1] + bounds[0+mm1[i]]*this->AxisBaseForX[1] + bounds[4+mm2[i]]*this->AxisBaseForZ[1];
1499      yCoords[i][5] = bounds[3]*this->AxisBaseForY[2] + bounds[0+mm1[i]]*this->AxisBaseForX[2] + bounds[4+mm2[i]]*this->AxisBaseForZ[2];
1500      }
1501    else
1502      {
1503      yCoords[i][0] = bounds[2]*this->AxisBaseForY[0] + this->AxisOrigin[0]*this->AxisBaseForX[0] + this->AxisOrigin[2]*this->AxisBaseForZ[0];
1504      yCoords[i][1] = bounds[2]*this->AxisBaseForY[1] + this->AxisOrigin[0]*this->AxisBaseForX[1] + this->AxisOrigin[2]*this->AxisBaseForZ[1];
1505      yCoords[i][2] = bounds[2]*this->AxisBaseForY[2] + this->AxisOrigin[0]*this->AxisBaseForX[2] + this->AxisOrigin[2]*this->AxisBaseForZ[2];
1506      yCoords[i][3] = bounds[3]*this->AxisBaseForY[0] + this->AxisOrigin[0]*this->AxisBaseForX[0] + this->AxisOrigin[2]*this->AxisBaseForZ[0];
1507      yCoords[i][4] = bounds[3]*this->AxisBaseForY[1] + this->AxisOrigin[0]*this->AxisBaseForX[1] + this->AxisOrigin[2]*this->AxisBaseForZ[1];
1508      yCoords[i][5] = bounds[3]*this->AxisBaseForY[2] + this->AxisOrigin[0]*this->AxisBaseForX[2] + this->AxisOrigin[2]*this->AxisBaseForZ[2];
1509      }
1510
1511    if(this->UseAxisOrigin == 0)
1512      {
1513      zCoords[i][0] = bounds[4]*this->AxisBaseForZ[0] + bounds[0+mm1[i]]*this->AxisBaseForX[0] + bounds[2+mm2[i]]*this->AxisBaseForY[0];
1514      zCoords[i][1] = bounds[4]*this->AxisBaseForZ[1] + bounds[0+mm1[i]]*this->AxisBaseForX[1] + bounds[2+mm2[i]]*this->AxisBaseForY[1];
1515      zCoords[i][2] = bounds[4]*this->AxisBaseForZ[2] + bounds[0+mm1[i]]*this->AxisBaseForX[2] + bounds[2+mm2[i]]*this->AxisBaseForY[2];
1516      zCoords[i][3] = bounds[5]*this->AxisBaseForZ[0] + bounds[0+mm1[i]]*this->AxisBaseForX[0] + bounds[2+mm2[i]]*this->AxisBaseForY[0];
1517      zCoords[i][4] = bounds[5]*this->AxisBaseForZ[1] + bounds[0+mm1[i]]*this->AxisBaseForX[1] + bounds[2+mm2[i]]*this->AxisBaseForY[1];
1518      zCoords[i][5] = bounds[5]*this->AxisBaseForZ[2] + bounds[0+mm1[i]]*this->AxisBaseForX[2] + bounds[2+mm2[i]]*this->AxisBaseForY[2];
1519      }
1520    else
1521      {
1522      zCoords[i][0] = bounds[4]*this->AxisBaseForZ[0] + this->AxisOrigin[0]*this->AxisBaseForX[0] + this->AxisOrigin[1]*this->AxisBaseForY[0];
1523      zCoords[i][1] = bounds[4]*this->AxisBaseForZ[1] + this->AxisOrigin[0]*this->AxisBaseForX[1] + this->AxisOrigin[1]*this->AxisBaseForY[1];
1524      zCoords[i][2] = bounds[4]*this->AxisBaseForZ[2] + this->AxisOrigin[0]*this->AxisBaseForX[2] + this->AxisOrigin[1]*this->AxisBaseForY[2];
1525      zCoords[i][3] = bounds[5]*this->AxisBaseForZ[0] + this->AxisOrigin[0]*this->AxisBaseForX[0] + this->AxisOrigin[1]*this->AxisBaseForY[0];
1526      zCoords[i][4] = bounds[5]*this->AxisBaseForZ[1] + this->AxisOrigin[0]*this->AxisBaseForX[1] + this->AxisOrigin[1]*this->AxisBaseForY[1];
1527      zCoords[i][5] = bounds[5]*this->AxisBaseForZ[2] + this->AxisOrigin[0]*this->AxisBaseForX[2] + this->AxisOrigin[1]*this->AxisBaseForY[2];
1528      }
1529    }
1530
1531  double xRange[2], yRange[2], zRange[2];
1532
1533  // this method sets the Coords, and offsets if necessary.
1534  this->AdjustAxes(bounds, xCoords, yCoords, zCoords, xRange, yRange, zRange);
1535
1536  // adjust for sci. notation if necessary
1537  // May set a flag for each axis specifying that label values should
1538  // be scaled, may change title of each axis, may change label format.
1539  this->AdjustValues(xRange, yRange, zRange);
1540  this->AdjustRange(bounds);
1541
1542  // Prepare axes for rendering with user-definable options
1543  for (i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
1544    {
1545    this->XAxes[i]->SetAxisOnOrigin(this->UseAxisOrigin);
1546    this->XAxes[i]->GetPoint1Coordinate()->SetValue(xCoords[i][0],
1547                                                    xCoords[i][1],
1548                                                    xCoords[i][2]);
1549    this->XAxes[i]->GetPoint2Coordinate()->SetValue(xCoords[i][3],
1550                                                    xCoords[i][4],
1551                                                    xCoords[i][5]);
1552    this->YAxes[i]->SetAxisOnOrigin(this->UseAxisOrigin);
1553    this->YAxes[i]->GetPoint1Coordinate()->SetValue(yCoords[i][0],
1554                                                    yCoords[i][1],
1555                                                    yCoords[i][2]);
1556    this->YAxes[i]->GetPoint2Coordinate()->SetValue(yCoords[i][3],
1557                                                    yCoords[i][4],
1558                                                    yCoords[i][5]);
1559    this->ZAxes[i]->SetAxisOnOrigin(this->UseAxisOrigin);
1560    this->ZAxes[i]->GetPoint1Coordinate()->SetValue(zCoords[i][0],
1561                                                    zCoords[i][1],
1562                                                    zCoords[i][2]);
1563    this->ZAxes[i]->GetPoint2Coordinate()->SetValue(zCoords[i][3],
1564                                                    zCoords[i][4],
1565                                                    zCoords[i][5]);
1566
1567    this->XAxes[i]->SetRange(xRange[0], xRange[1]);
1568    this->YAxes[i]->SetRange(yRange[0], yRange[1]);
1569    this->ZAxes[i]->SetRange(zRange[0], zRange[1]);
1570
1571    this->XAxes[i]->SetTitle(this->ActualXLabel);
1572    this->YAxes[i]->SetTitle(this->ActualYLabel);
1573    this->ZAxes[i]->SetTitle(this->ActualZLabel);
1574    }
1575
1576  bool ticksRecomputed = this->ComputeTickSize(bounds);
1577
1578  //
1579  // Labels are built during ComputeTickSize. if
1580  // ticks were not recomputed, but we need a label
1581  // reset, then build the labels here.
1582  //
1583  if (!ticksRecomputed)
1584    {
1585    if (this->ForceXLabelReset)
1586      {
1587      this->BuildLabels(this->XAxes);
1588      this->UpdateLabels(this->XAxes, 0);
1589      }
1590    if (this->ForceYLabelReset)
1591      {
1592      this->BuildLabels(this->YAxes);
1593      this->UpdateLabels(this->YAxes, 1);
1594      }
1595    if (this->ForceZLabelReset)
1596      {
1597      this->BuildLabels(this->ZAxes);
1598      this->UpdateLabels(this->ZAxes, 2);
1599      }
1600    }
1601
1602  if (ticksRecomputed || this->ForceXLabelReset || this->ForceYLabelReset ||
1603      this->ForceZLabelReset)
1604    {
1605    // labels were re-built, need to recompute the scale.
1606    double center[3];
1607
1608    center[0] = (this->Bounds[1] - this->Bounds[0]) * 0.5;
1609    center[1] = (this->Bounds[3] - this->Bounds[2]) * 0.5;
1610    center[2] = (this->Bounds[5] - this->Bounds[4]) * 0.5;
1611
1612    double lenX = this->XAxes[0]->ComputeMaxLabelLength(center);
1613    double lenY = this->YAxes[0]->ComputeMaxLabelLength(center);
1614    double lenZ = this->ZAxes[0]->ComputeMaxLabelLength(center);
1615    double lenTitleX = this->XAxes[0]->ComputeTitleLength(center);
1616    double lenTitleY = this->YAxes[0]->ComputeTitleLength(center);
1617    double lenTitleZ = this->ZAxes[0]->ComputeTitleLength(center);
1618    double maxLabelLength = this->MaxOf(lenX, lenY, lenZ, 0.);
1619    double maxTitleLength = this->MaxOf(lenTitleX, lenTitleY, lenTitleZ, 0.);
1620    double bWidth  = this->Bounds[1] - this->Bounds[0];
1621    double bHeight = this->Bounds[3] - this->Bounds[2];
1622
1623    double bLength = sqrt(bWidth*bWidth + bHeight*bHeight);
1624
1625    double target = bLength *0.04;
1626    this->LabelScale = 1.;
1627    if (maxLabelLength != 0.)
1628      {
1629      this->LabelScale = target / maxLabelLength;
1630      }
1631    target = bLength *0.10;
1632    this->TitleScale = 1.;
1633    if (maxTitleLength != 0.)
1634      {
1635      this->TitleScale = target / maxTitleLength;
1636      }
1637
1638    //
1639    // Allow a bit bigger title if we have units, otherwise
1640    // the title may be too small to read.
1641    //
1642    if (XUnits != NULL && XUnits[0] != '\0')
1643      {
1644      this->TitleScale *= 2;
1645      }
1646
1647    for (i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
1648      {
1649      this->XAxes[i]->SetLabelScale(this->LabelScale);
1650      this->YAxes[i]->SetLabelScale(this->LabelScale);
1651      this->ZAxes[i]->SetLabelScale(this->LabelScale);
1652      this->XAxes[i]->SetTitleScale(this->TitleScale);
1653      this->YAxes[i]->SetTitleScale(this->TitleScale);
1654      this->ZAxes[i]->SetTitleScale(this->TitleScale);
1655      }
1656    }
1657
1658  // Scale appropriately.
1659  this->AutoScale(viewport);
1660
1661  this->RenderSomething = 1;
1662  this->BuildTime.Modified();
1663  this->LastFlyMode = this->FlyMode;
1664}
1665
1666// *************************************************************************
1667//  Sends attributes to each vtkRpAxisActor.  Only sets those that are
1668//  not dependent upon viewport changes, and thus do not need to be set
1669//  very often.
1670// *************************************************************************
1671void vtkRpCubeAxesActor::SetNonDependentAttributes()
1672{
1673  vtkProperty *prop = this->GetProperty();
1674  prop->SetAmbient(1.0);
1675  prop->SetDiffuse(0.0);
1676
1677  // Make sure our Axis Base is normalized
1678  vtkMath::Normalize(this->AxisBaseForX);
1679  vtkMath::Normalize(this->AxisBaseForY);
1680  vtkMath::Normalize(this->AxisBaseForZ);
1681
1682  // Manage custome grid visibility location if FLY and STATIC axis
1683  int gridLocationBasedOnAxis = (this->GridLineLocation == VTK_GRID_LINES_ALL)
1684      ? VTK_GRID_LINES_ALL : VTK_GRID_LINES_CLOSEST;
1685
1686  for (int i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
1687    {
1688    this->XAxes[i]->SetAxisPosition(i);
1689    this->XAxes[i]->SetAxisBaseForX(this->AxisBaseForX);
1690    this->XAxes[i]->SetAxisBaseForY(this->AxisBaseForY);
1691    this->XAxes[i]->SetAxisBaseForZ(this->AxisBaseForZ);
1692    this->XAxes[i]->SetCamera(this->Camera);
1693    this->XAxes[i]->SetProperty(prop);
1694    this->XAxes[i]->SetTitleTextProperty(this->TitleTextProperty[0]);
1695    this->XAxes[i]->SetLabelTextProperty(this->LabelTextProperty[0]);
1696    this->XAxes[i]->SetAxisLinesProperty(this->XAxesLinesProperty);
1697    this->XAxes[i]->SetGridlinesProperty(this->XAxesGridlinesProperty);
1698    this->XAxes[i]->SetGridpolysProperty(this->XAxesGridpolysProperty);
1699    this->XAxes[i]->SetTickLocation(this->TickLocation);
1700    this->XAxes[i]->SetDrawGridlines(this->DrawXGridlines);
1701    this->XAxes[i]->SetDrawGridlinesLocation(gridLocationBasedOnAxis);
1702    this->XAxes[i]->SetDrawInnerGridlines(this->DrawXInnerGridlines);
1703    this->XAxes[i]->SetDrawGridpolys(this->DrawXGridpolys);
1704    this->XAxes[i]->SetBounds(this->Bounds);
1705    this->XAxes[i]->SetAxisVisibility(this->XAxisVisibility);
1706    this->XAxes[i]->SetLabelVisibility(this->XAxisLabelVisibility);
1707    this->XAxes[i]->SetTitleVisibility(this->XAxisLabelVisibility);
1708    this->XAxes[i]->SetTickVisibility(this->XAxisTickVisibility);
1709    this->XAxes[i]->SetMinorTicksVisible(this->XAxisMinorTickVisibility);
1710
1711    this->YAxes[i]->SetAxisPosition(i);
1712    this->YAxes[i]->SetAxisBaseForX(this->AxisBaseForX);
1713    this->YAxes[i]->SetAxisBaseForY(this->AxisBaseForY);
1714    this->YAxes[i]->SetAxisBaseForZ(this->AxisBaseForZ);
1715    this->YAxes[i]->SetCamera(this->Camera);
1716    this->YAxes[i]->SetProperty(prop);
1717    this->YAxes[i]->SetTitleTextProperty(this->TitleTextProperty[1]);
1718    this->YAxes[i]->SetLabelTextProperty(this->LabelTextProperty[1]);
1719    this->YAxes[i]->SetAxisLinesProperty(this->YAxesLinesProperty);
1720    this->YAxes[i]->SetGridlinesProperty(this->YAxesGridlinesProperty);
1721    this->YAxes[i]->SetGridpolysProperty(this->YAxesGridpolysProperty);
1722    this->YAxes[i]->SetTickLocation(this->TickLocation);
1723    this->YAxes[i]->SetDrawGridlines(this->DrawYGridlines);
1724    this->YAxes[i]->SetDrawGridlinesLocation(gridLocationBasedOnAxis);
1725    this->YAxes[i]->SetDrawInnerGridlines(this->DrawYInnerGridlines);
1726    this->YAxes[i]->SetDrawGridpolys(this->DrawYGridpolys);
1727    this->YAxes[i]->SetBounds(this->Bounds);
1728    this->YAxes[i]->SetAxisVisibility(this->YAxisVisibility);
1729    this->YAxes[i]->SetLabelVisibility(this->YAxisLabelVisibility);
1730    this->YAxes[i]->SetTitleVisibility(this->YAxisLabelVisibility);
1731    this->YAxes[i]->SetTickVisibility(this->YAxisTickVisibility);
1732    this->YAxes[i]->SetMinorTicksVisible(this->YAxisMinorTickVisibility);
1733
1734    this->ZAxes[i]->SetAxisPosition(i);
1735    this->ZAxes[i]->SetAxisBaseForX(this->AxisBaseForX);
1736    this->ZAxes[i]->SetAxisBaseForY(this->AxisBaseForY);
1737    this->ZAxes[i]->SetAxisBaseForZ(this->AxisBaseForZ);
1738    this->ZAxes[i]->SetCamera(this->Camera);
1739    this->ZAxes[i]->SetProperty(prop);
1740    this->ZAxes[i]->SetTitleTextProperty(this->TitleTextProperty[2]);
1741    this->ZAxes[i]->SetLabelTextProperty(this->LabelTextProperty[2]);
1742    this->ZAxes[i]->SetAxisLinesProperty(this->ZAxesLinesProperty);
1743    this->ZAxes[i]->SetGridlinesProperty(this->ZAxesGridlinesProperty);
1744    this->ZAxes[i]->SetGridpolysProperty(this->ZAxesGridpolysProperty);
1745    this->ZAxes[i]->SetTickLocation(this->TickLocation);
1746    this->ZAxes[i]->SetDrawGridlines(this->DrawZGridlines);
1747    this->ZAxes[i]->SetDrawGridlinesLocation(gridLocationBasedOnAxis);
1748    this->ZAxes[i]->SetDrawInnerGridlines(this->DrawZInnerGridlines);
1749    this->ZAxes[i]->SetDrawGridpolys(this->DrawZGridpolys);
1750    this->ZAxes[i]->SetBounds(this->Bounds);
1751    this->ZAxes[i]->SetAxisVisibility(this->ZAxisVisibility);
1752    this->ZAxes[i]->SetLabelVisibility(this->ZAxisLabelVisibility);
1753    this->ZAxes[i]->SetTitleVisibility(this->ZAxisLabelVisibility);
1754    this->ZAxes[i]->SetTickVisibility(this->ZAxisTickVisibility);
1755    this->ZAxes[i]->SetMinorTicksVisible(this->ZAxisMinorTickVisibility);
1756    }
1757}
1758
1759// Static variable describes locations in cube, relative to the type
1760// of axis:  mm for an X-axis means the x-edge at min-y and min-z.
1761// mX for a Y-axis means the y-edge at min-x and max-z, and so on.
1762
1763enum {mm = 0, mX, XX, Xm };
1764//
1765// For CLOSEST_TRIAD, and FURTHEST_TRIAD, this variable determines
1766// which locations in the cube each 'Major' axis should take.
1767//
1768static int vtkRpCubeAxesActorTriads[8][3] = {
1769  {mm,mm,mm}, {mm,Xm,Xm}, {Xm,mm,mX}, {Xm,Xm,XX},
1770  {mX,mX,mm}, {mX,XX,Xm}, {XX,mX,mX}, {XX,XX,XX}};
1771static int vtkRpCubeAxesActorConn[8][3] = {{1,2,4}, {0,3,5}, {3,0,6}, {2,1,7},
1772                                         {5,6,0}, {4,7,1}, {7,4,2}, {6,5,3}};
1773
1774// *************************************************************************
1775// Determine which of the axes in each coordinate direction actually should
1776// be rendered.  For STATIC FlyMode, all axes are rendered.  For other
1777// FlyModes, either 1 or 2 per coordinate direction are rendered.
1778// *************************************************************************
1779void vtkRpCubeAxesActor::DetermineRenderAxes(vtkViewport *viewport)
1780{
1781  double bounds[6];
1782  double pts[8][3];
1783  int i = 0, closestIdx = -1, furtherstIdx = -1;
1784  int xloc = 0, yloc = 0, zloc = 0;
1785
1786  // Make sure we start with only one axis by default, then we might extend it
1787  this->NumberOfAxesX = this->NumberOfAxesY = this->NumberOfAxesZ = 1;
1788
1789  // Compute relevant axis points only if a axis/grid visibility change based
1790  // on the viewpoint
1791  if( !( this->GridLineLocation == VTK_GRID_LINES_ALL
1792         && ( this->FlyMode == VTK_FLY_STATIC_EDGES
1793              || this->FlyMode == VTK_FLY_STATIC_TRIAD)))
1794    {
1795    // determine the bounds to use (input, prop, or user-defined)
1796    this->GetBounds(bounds);
1797    this->TransformBounds(viewport, bounds, pts);
1798    }
1799
1800  // Check closest point if needed
1801  if( this->GridLineLocation == VTK_GRID_LINES_CLOSEST
1802      || this->FlyMode == VTK_FLY_CLOSEST_TRIAD )
1803    {
1804    closestIdx = this->FindClosestAxisIndex(pts);
1805    }
1806
1807  // Check furtherst point if needed
1808  if( this->GridLineLocation == VTK_GRID_LINES_FURTHEST
1809      || this->FlyMode == VTK_FLY_FURTHEST_TRIAD )
1810    {
1811    furtherstIdx = this->FindFurtherstAxisIndex(pts);
1812    }
1813
1814  // Manage fast static axis visibility
1815  if (this->FlyMode == VTK_FLY_STATIC_EDGES || this->FlyMode == VTK_FLY_STATIC_TRIAD)
1816    {
1817    if(this->FlyMode == VTK_FLY_STATIC_EDGES)
1818      {
1819      this->NumberOfAxesX = this->NumberOfAxesY = this->NumberOfAxesZ
1820          = NUMBER_OF_ALIGNED_AXIS;
1821      }
1822
1823    for (i = 0; i < this->NumberOfAxesX; i++)
1824      {
1825      this->RenderAxesX[i] = this->RenderAxesY[i] = this->RenderAxesZ[i] = i;
1826      }
1827
1828    this->UpdateGridLineVisibility(
1829          (this->GridLineLocation == VTK_GRID_LINES_CLOSEST)
1830          ? closestIdx : furtherstIdx);
1831    return;
1832    }
1833
1834
1835  // Take into account the inertia. Process only so often.
1836  if (this->RenderCount++ == 0 || !(this->RenderCount % this->Inertia))
1837    {
1838    if (this->FlyMode == VTK_FLY_CLOSEST_TRIAD)
1839      {
1840      xloc = vtkRpCubeAxesActorTriads[closestIdx][0];
1841      yloc = vtkRpCubeAxesActorTriads[closestIdx][1];
1842      zloc = vtkRpCubeAxesActorTriads[closestIdx][2];
1843      }
1844    else if (this->FlyMode == VTK_FLY_FURTHEST_TRIAD)
1845      {
1846      xloc = vtkRpCubeAxesActorTriads[furtherstIdx][0];
1847      yloc = vtkRpCubeAxesActorTriads[furtherstIdx][1];
1848      zloc = vtkRpCubeAxesActorTriads[furtherstIdx][2];
1849      }
1850    else // else boundary edges fly mode
1851      {
1852      this->FindBoundaryEdge(xloc, yloc, zloc, pts);
1853      }
1854
1855    this->InertiaLocs[0] = xloc;
1856    this->InertiaLocs[1] = yloc;
1857    this->InertiaLocs[2] = zloc;
1858    } // inertia
1859  else
1860    {
1861    // Do not change anything, use locations from last render
1862    xloc = this->InertiaLocs[0];
1863    yloc = this->InertiaLocs[1];
1864    zloc = this->InertiaLocs[2];
1865    }
1866
1867  // Set axes to be rendered
1868  this->RenderAxesX[0] = xloc % NUMBER_OF_ALIGNED_AXIS;
1869  this->RenderAxesY[0] = yloc % NUMBER_OF_ALIGNED_AXIS;
1870  this->RenderAxesZ[0] = zloc % NUMBER_OF_ALIGNED_AXIS;
1871
1872  // Manage grid visibility (can increase the number of axis to render)
1873  this->UpdateGridLineVisibility(
1874        (this->GridLineLocation == VTK_GRID_LINES_CLOSEST)
1875        ? closestIdx : furtherstIdx);
1876}
1877
1878// --------------------------------------------------------------------------
1879double vtkRpCubeAxesActor::MaxOf(double a, double b)
1880{
1881  return (a > b ? a : b);
1882}
1883
1884// --------------------------------------------------------------------------
1885double vtkRpCubeAxesActor::MaxOf(double a, double b, double c, double d)
1886{
1887  return this->MaxOf(this->MaxOf(a, b), this->MaxOf(c, d));
1888}
1889
1890// --------------------------------------------------------------------------
1891inline double vtkRpCubeAxesActor::FFix(double value)
1892{
1893  int ivalue = static_cast<int>(value);
1894  return ivalue;
1895}
1896
1897inline int vtkRpCubeAxesActor::FRound(double value)
1898{
1899  return value <= 0.5 ? static_cast<int>(this->FFix(value)) : static_cast<int>(this->FFix(value) + 1);
1900}
1901
1902inline int vtkRpCubeAxesActor::GetNumTicks(double range, double fxt)
1903{
1904  // Find the number of integral points in the interval.
1905  double fnt  = range/fxt;
1906  fnt  = this->FFix(fnt);
1907  return this->FRound(fnt);
1908}
1909
1910// --------------------------------------------------------------------------
1911inline double vtkRpCubeAxesActor::FSign(double value, double sign)
1912{
1913  value = fabs(value);
1914  if (sign < 0.)
1915    {
1916    value *= -1.;
1917    }
1918  return value;
1919}
1920
1921// *******************************************************************
1922// Method: vtkRpCubeAxesActor::AdjustTicksComputeRange
1923//
1924// Purpose: Sets private members controlling the number and position
1925//          of ticks.
1926//
1927// Arguments:
1928//   inRange   The range for this axis.
1929// *******************************************************************
1930
1931void vtkRpCubeAxesActor::AdjustTicksComputeRange(vtkRpAxisActor *axes[NUMBER_OF_ALIGNED_AXIS],
1932    double boundsMin, double boundsMax)
1933{
1934  double sortedRange[2], range;
1935  double fxt;
1936  double div, major, minor;
1937  double majorStart, minorStart;
1938  int numTicks;
1939  double *inRange = axes[0]->GetRange();
1940  vtkStringArray* customizedLabels = NULL;
1941
1942  sortedRange[0] = inRange[0] < inRange[1] ? inRange[0] : inRange[1];
1943  sortedRange[1] = inRange[0] > inRange[1] ? inRange[0] : inRange[1];
1944
1945  range = sortedRange[1] - sortedRange[0];
1946
1947  // Find the integral points.
1948  double pow10 = log10(range);
1949
1950  // Build in numerical tolerance
1951  if (pow10 != 0.)
1952    {
1953    double eps = 10.0e-10;
1954    pow10 = this->FSign((fabs(pow10) + eps), pow10);
1955    }
1956
1957  // FFix move you in the wrong direction if pow10 is negative.
1958  if (pow10 < 0.)
1959    {
1960    pow10 = pow10 - 1.;
1961    }
1962
1963  fxt = pow(10., this->FFix(pow10));
1964
1965  numTicks = this->GetNumTicks(range, fxt);
1966
1967  div = 1.;
1968  if (numTicks < 5)
1969    {
1970    div = 2.;
1971    }
1972  if (numTicks <= 2)
1973    {
1974    div = 5.;
1975    }
1976
1977  // If there aren't enough major tick points in this decade, use the next
1978  // decade.
1979  major = fxt;
1980  if (div != 1.)
1981    {
1982    major /= div;
1983    }
1984
1985  int axis = 0;
1986  switch(axes[0]->GetAxisType())
1987  {
1988  case VTK_AXIS_TYPE_X:
1989    axis = 0;
1990    break;
1991  case VTK_AXIS_TYPE_Y:
1992    axis = 1;
1993    break;
1994  case VTK_AXIS_TYPE_Z:
1995    axis = 2;
1996    break;
1997  }
1998  customizedLabels = this->AxisLabels[axis];
1999
2000  if (customizedLabels == NULL)
2001    {
2002    // Figure out the first major tick locations, relative to the
2003    // start of the axis.
2004    if (sortedRange[0] <= 0.)
2005      {
2006      majorStart = major*(this->FFix(sortedRange[0]*(1./major)) + 0.);
2007      }
2008    else
2009      {
2010      majorStart = major*(this->FFix(sortedRange[0]*(1./major)) + 1.);
2011      }
2012    }
2013  else
2014    {
2015      // If we have custom labels, they are supposed to be uniformly distributed
2016      // inside the values range.
2017      majorStart = sortedRange[0];
2018      numTicks = this->GetNumTicks(range, major);
2019      int labelsCount = customizedLabels->GetNumberOfValues();
2020      if (numTicks > labelsCount)
2021        {
2022        major = range / (labelsCount - 1.);
2023        }
2024    }
2025
2026  minor = major / 10.;
2027  // Figure out the first minor tick locations, relative to the
2028  // start of the axis.
2029  if (sortedRange[0] <= 0.)
2030    {
2031    minorStart = minor*(this->FFix(sortedRange[0]*(1./minor)) + 0.);
2032    }
2033  else
2034    {
2035    minorStart = minor*(this->FFix(sortedRange[0]*(1./minor)) + 1.);
2036    }
2037
2038  for (int i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
2039    {
2040    axes[i]->SetMinorRangeStart(minorStart);
2041    axes[i]->SetMajorRangeStart(majorStart);
2042    axes[i]->SetDeltaRangeMinor(minor);
2043    axes[i]->SetDeltaRangeMajor(major);
2044    }
2045
2046  double t;
2047  t = (minorStart - sortedRange[0])/range;
2048  minorStart = t * boundsMax + (1-t) * boundsMin;
2049  t = (majorStart - sortedRange[0])/range;
2050  majorStart = t * boundsMax + (1-t) * boundsMin;
2051  const double scale = (boundsMax - boundsMin) / range;
2052  minor *= scale;
2053  major *= scale;
2054
2055  // Set major start and delta for the corresponding cube axis
2056  switch(axes[0]->GetAxisType())
2057    {
2058    case VTK_AXIS_TYPE_X:
2059      this->MajorStart[0] = majorStart;
2060      this->DeltaMajor[0] = major;
2061      break;
2062    case VTK_AXIS_TYPE_Y:
2063      this->MajorStart[1] = majorStart;
2064      this->DeltaMajor[1] = major;
2065      break;
2066    case VTK_AXIS_TYPE_Z:
2067      this->MajorStart[2] = majorStart;
2068      this->DeltaMajor[2] = major;
2069      break;
2070    }
2071
2072  // Set major and minor starts and deltas for all underlying axes
2073  for (int i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
2074    {
2075    axes[i]->SetMinorStart(minorStart);
2076    axes[i]->SetMajorStart(axes[0]->GetAxisType(), majorStart);
2077
2078    axes[i]->SetDeltaMinor(minor);
2079    axes[i]->SetDeltaMajor(axes[0]->GetAxisType(), major);
2080    }
2081}
2082
2083// ****************************************************************
2084void vtkRpCubeAxesActor::AutoScale(vtkViewport *viewport)
2085{
2086  // Current implementation only for perspective projections.
2087  this->AutoScale(viewport, this->XAxes);
2088  this->AutoScale(viewport, this->YAxes);
2089  this->AutoScale(viewport, this->ZAxes);
2090}
2091
2092// ****************************************************************
2093void vtkRpCubeAxesActor::AutoScale(vtkViewport *viewport, vtkRpAxisActor *axis[NUMBER_OF_ALIGNED_AXIS])
2094{
2095  for (int i = 0; i < NUMBER_OF_ALIGNED_AXIS; ++i)
2096    {
2097    double newTitleScale
2098      = this->AutoScale(viewport,
2099                        this->ScreenSize,
2100                        axis[i]->GetTitleActor()->GetPosition());
2101
2102    axis[i]->SetTitleScale(newTitleScale);
2103
2104    // Now labels.
2105    vtkRpAxisFollower** labelActors = axis[i]->GetLabelActors();
2106
2107    for(int j = 0; j < axis[i]->GetNumberOfLabelsBuilt(); ++j)
2108      {
2109      double newLabelScale
2110        = this->AutoScale(viewport,
2111                          this->ScreenSize,
2112                          labelActors[j]->GetPosition());
2113
2114      labelActors[j]->SetScale(newLabelScale);
2115      }
2116    }
2117}
2118
2119// ****************************************************************
2120double vtkRpCubeAxesActor::AutoScale(vtkViewport *viewport, double screenSize,
2121                                   double position[3])
2122{
2123  double factor = 1;
2124  if (viewport->GetSize()[1] > 0)
2125    {
2126    factor = 2.0 * screenSize
2127      * tan(vtkMath::RadiansFromDegrees(this->Camera->GetViewAngle()/2.0))
2128      / viewport->GetSize()[1];
2129    }
2130
2131    double dist = sqrt(
2132          vtkMath::Distance2BetweenPoints(position,
2133                                          this->Camera->GetPosition()));
2134    double newScale = factor * dist;
2135
2136    return newScale;
2137}
2138
2139// ****************************************************************
2140//  Determine what the labels should be and set them in each axis.
2141// ****************************************************************
2142void vtkRpCubeAxesActor::BuildLabels(vtkRpAxisActor *axes[NUMBER_OF_ALIGNED_AXIS])
2143{
2144  char label[64];
2145  int labelCount = 0;
2146  double deltaMajor = axes[0]->GetDeltaMajor(axes[0]->GetAxisType());
2147  double val = axes[0]->GetMajorRangeStart();
2148  double p2[3], p1[3];
2149  axes[0]->GetPoint1Coordinate()->GetValue(p1);
2150  axes[0]->GetPoint2Coordinate()->GetValue(p2);
2151  double *range = axes[0]->GetRange();
2152  double axis[3] = { p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2] };
2153  double axisLength = vtkMath::Norm(axis);
2154  double extents = range[1] - range[0];
2155  double rangeScale = axisLength / extents;
2156  double labelCountAsDouble = (axisLength - (val-range[0])*rangeScale) / deltaMajor;
2157  bool mustAdjustValue = 0;
2158  int lastPow = 0;
2159  int axisIndex = 0;
2160  vtkStringArray* customizedLabels = NULL;
2161
2162  vtkStringArray *labels = vtkStringArray::New();
2163  const char *format = "%s";
2164  switch (axes[0]->GetAxisType())
2165    {
2166    case VTK_AXIS_TYPE_X:
2167      axisIndex = 0;
2168      format = this->XLabelFormat;
2169      mustAdjustValue = this->MustAdjustXValue;
2170      lastPow = this->LastXPow;
2171      break;
2172    case VTK_AXIS_TYPE_Y:
2173      axisIndex = 1;
2174      format = this->YLabelFormat;
2175      mustAdjustValue = this->MustAdjustYValue;
2176      lastPow = this->LastYPow;
2177      break;
2178    case VTK_AXIS_TYPE_Z:
2179      axisIndex = 2;
2180      format = this->ZLabelFormat;
2181      mustAdjustValue = this->MustAdjustZValue;
2182      lastPow = this->LastZPow;
2183      break;
2184    }
2185  customizedLabels = this->AxisLabels[axisIndex];
2186  // figure out how many labels we need:
2187  if(extents == 0 || vtkMath::IsNan(labelCountAsDouble))
2188    {
2189    labelCount = 0;
2190    }
2191  else
2192    {
2193    labelCount = vtkMath::Floor(labelCountAsDouble+2*FLT_EPSILON) + 1;
2194    }
2195
2196  labels->SetNumberOfValues(labelCount);
2197
2198  if (customizedLabels == NULL)
2199    {
2200    // Convert deltaMajor from world coord to range scale
2201    deltaMajor = extents * deltaMajor/axisLength;
2202
2203    double scaleFactor = 1.;
2204    if (lastPow != 0)
2205      {
2206      scaleFactor = 1.0/pow(10., lastPow);
2207      }
2208
2209    for (int i = 0; i < labelCount; i++)
2210      {
2211      if (fabs(val) < 0.01 && extents > 1)
2212        {
2213        // We just happened to fall at something near zero and the range is
2214        // large, so set it to zero to avoid ugliness.
2215        val = 0.;
2216        }
2217      if (mustAdjustValue)
2218        {
2219        sprintf(label, format, val*scaleFactor);
2220        }
2221      else
2222        {
2223        sprintf(label, format, val);
2224        }
2225      if (fabs(val) < 0.01)
2226        {
2227        //
2228        // Ensure that -0.0 is never a label
2229        // The maximum number of digits that we allow past the decimal is 5.
2230        //
2231        if (strcmp(label, "-0") == 0)
2232          {
2233          sprintf(label, "0");
2234          }
2235        else if (strcmp(label, "-0.0") == 0)
2236          {
2237          sprintf(label, "0.0");
2238          }
2239        else if (strcmp(label, "-0.00") == 0)
2240          {
2241          sprintf(label, "0.00");
2242          }
2243        else if (strcmp(label, "-0.000") == 0)
2244          {
2245          sprintf(label, "0.000");
2246          }
2247        else if (strcmp(label, "-0.0000") == 0)
2248          {
2249          sprintf(label, "0.0000");
2250          }
2251        else if (strcmp(label, "-0.00000") == 0)
2252          {
2253          sprintf(label, "0.00000");
2254          }
2255        }
2256      labels->SetValue(i, label);
2257      val += deltaMajor;
2258      }
2259    }
2260  else
2261    {
2262    if (labelCount > 0)
2263      {
2264      double delta = customizedLabels->GetNumberOfValues() / labelCount;
2265      for (int i = 0; i < labelCount; ++i)
2266        {
2267        labels->SetValue(i, customizedLabels->GetValue(i * delta));
2268        }
2269      }
2270    }
2271  for (int i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
2272    {
2273    axes[i]->SetLabels(labels);
2274    }
2275  labels->Delete();
2276}
2277
2278vtkStringArray* vtkRpCubeAxesActor::GetAxisLabels(int axis)
2279{
2280  return (axis >= 0 && axis < 3) ? this->AxisLabels[axis] : NULL;
2281}
2282
2283void vtkRpCubeAxesActor::SetAxisLabels(int axis, vtkStringArray* value)
2284{
2285  if (axis >= 0 && axis < 3 && value != this->AxisLabels[axis])
2286    {
2287    vtkStringArray* previous = this->AxisLabels[axis];
2288    if (value != NULL)
2289      {
2290      value->Register(this);
2291      }
2292    this->AxisLabels[axis] = value;
2293    if (previous != NULL)
2294      {
2295      previous->UnRegister(this);
2296      }
2297    this->Modified();
2298    }
2299}
2300
2301// ****************************************************************************
2302//  Set automatic label scaling mode, set exponents for each axis type.
2303// ****************************************************************************
2304void vtkRpCubeAxesActor::SetLabelScaling(bool autoscale, int upowX, int upowY,
2305                                       int upowZ)
2306{
2307  if (autoscale != this->AutoLabelScaling || upowX != this->UserXPow ||
2308      upowY != this->UserYPow || upowZ != this->UserZPow)
2309    {
2310    this->AutoLabelScaling = autoscale;
2311    this->UserXPow = upowX;
2312    this->UserYPow = upowY;
2313    this->UserZPow = upowZ;
2314    this->Modified();
2315    }
2316}
2317
2318// ****************************************************************************
2319// Set the i-th title text property.
2320// ****************************************************************************
2321
2322vtkTextProperty* vtkRpCubeAxesActor::GetTitleTextProperty(int axis)
2323{
2324  return (axis >= 0 && axis < 3) ? this->TitleTextProperty[axis] : NULL;
2325}
2326
2327// ****************************************************************************
2328// Get the i-th label text property.
2329// ****************************************************************************
2330
2331vtkTextProperty* vtkRpCubeAxesActor::GetLabelTextProperty(int axis)
2332{
2333  return (axis >= 0 && axis < 3) ? this->LabelTextProperty[axis] : NULL;
2334}
2335
2336// ****************************************************************************
2337//  Set axes and screen size of the labels.
2338// ****************************************************************************
2339void vtkRpCubeAxesActor::UpdateLabels(vtkRpAxisActor **axis, int index)
2340  {
2341  for (int i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
2342    {
2343    int numberOfLabelsBuild = axis[i]->GetNumberOfLabelsBuilt();
2344    vtkRpAxisFollower **labelActors = axis[i]->GetLabelActors();
2345    for(int k=0; k < numberOfLabelsBuild; ++k)
2346      {
2347      if(index == 0)
2348        {
2349        labelActors[k]->SetAxis(this->XAxes[i]);
2350        }
2351      else if(index == 1)
2352        {
2353        labelActors[k]->SetAxis(this->YAxes[i]);
2354        }
2355      else if(index == 2)
2356        {
2357        labelActors[k]->SetAxis(this->ZAxes[i]);
2358        }
2359      else
2360        {
2361        // Do nothing.
2362        }
2363
2364      labelActors[k]->SetScreenOffset(this->LabelScreenOffset);
2365      labelActors[k]->SetEnableDistanceLOD( this->EnableDistanceLOD );
2366      labelActors[k]->SetDistanceLODThreshold( this->DistanceLODThreshold );
2367      labelActors[k]->SetEnableViewAngleLOD( this->EnableViewAngleLOD );
2368      labelActors[k]->SetViewAngleLODThreshold( this->ViewAngleLODThreshold );
2369      }
2370    }
2371  }
2372// ****************************************************************************
2373void vtkRpCubeAxesActor::SetXAxesLinesProperty(vtkProperty *prop)
2374{
2375  this->XAxesLinesProperty->DeepCopy(prop);
2376  this->Modified();
2377}
2378void vtkRpCubeAxesActor::SetYAxesLinesProperty(vtkProperty *prop)
2379{
2380  this->YAxesLinesProperty->DeepCopy(prop);
2381  this->Modified();
2382}
2383void vtkRpCubeAxesActor::SetZAxesLinesProperty(vtkProperty *prop)
2384{
2385  this->ZAxesLinesProperty->DeepCopy(prop);
2386  this->Modified();
2387}
2388
2389// ****************************************************************************
2390vtkProperty* vtkRpCubeAxesActor::GetXAxesLinesProperty()
2391{
2392  return this->XAxesLinesProperty;
2393}
2394vtkProperty* vtkRpCubeAxesActor::GetYAxesLinesProperty()
2395{
2396  return this->YAxesLinesProperty;
2397}
2398vtkProperty* vtkRpCubeAxesActor::GetZAxesLinesProperty()
2399{
2400  return this->ZAxesLinesProperty;
2401}
2402
2403// ****************************************************************************
2404void vtkRpCubeAxesActor::SetXAxesGridlinesProperty(vtkProperty *prop)
2405{
2406  this->XAxesGridlinesProperty->DeepCopy(prop);
2407  this->Modified();
2408}
2409void vtkRpCubeAxesActor::SetYAxesGridlinesProperty(vtkProperty *prop)
2410{
2411  this->YAxesGridlinesProperty->DeepCopy(prop);
2412  this->Modified();
2413}
2414void vtkRpCubeAxesActor::SetZAxesGridlinesProperty(vtkProperty *prop)
2415{
2416  this->ZAxesGridlinesProperty->DeepCopy(prop);
2417  this->Modified();
2418}
2419
2420// ****************************************************************************
2421vtkProperty* vtkRpCubeAxesActor::GetXAxesGridlinesProperty()
2422{
2423  return this->XAxesGridlinesProperty;
2424}
2425vtkProperty* vtkRpCubeAxesActor::GetYAxesGridlinesProperty()
2426{
2427  return this->YAxesGridlinesProperty;
2428}
2429vtkProperty* vtkRpCubeAxesActor::GetZAxesGridlinesProperty()
2430{
2431  return this->ZAxesGridlinesProperty;
2432}
2433
2434// ****************************************************************************
2435void vtkRpCubeAxesActor::SetXAxesInnerGridlinesProperty(vtkProperty *prop)
2436{
2437  this->XAxesInnerGridlinesProperty->DeepCopy(prop);
2438  this->Modified();
2439}
2440void vtkRpCubeAxesActor::SetYAxesInnerGridlinesProperty(vtkProperty *prop)
2441{
2442  this->YAxesInnerGridlinesProperty->DeepCopy(prop);
2443  this->Modified();
2444}
2445void vtkRpCubeAxesActor::SetZAxesInnerGridlinesProperty(vtkProperty *prop)
2446{
2447  this->ZAxesInnerGridlinesProperty->DeepCopy(prop);
2448  this->Modified();
2449}
2450
2451// ****************************************************************************
2452vtkProperty* vtkRpCubeAxesActor::GetXAxesInnerGridlinesProperty()
2453{
2454  return this->XAxesInnerGridlinesProperty;
2455}
2456vtkProperty* vtkRpCubeAxesActor::GetYAxesInnerGridlinesProperty()
2457{
2458  return this->YAxesInnerGridlinesProperty;
2459}
2460vtkProperty* vtkRpCubeAxesActor::GetZAxesInnerGridlinesProperty()
2461{
2462  return this->ZAxesInnerGridlinesProperty;
2463}
2464
2465// ****************************************************************************
2466void vtkRpCubeAxesActor::SetXAxesGridpolysProperty(vtkProperty *prop)
2467{
2468  this->XAxesGridpolysProperty->DeepCopy(prop);
2469  this->Modified();
2470}
2471void vtkRpCubeAxesActor::SetYAxesGridpolysProperty(vtkProperty *prop)
2472{
2473  this->YAxesGridpolysProperty->DeepCopy(prop);
2474  this->Modified();
2475}
2476void vtkRpCubeAxesActor::SetZAxesGridpolysProperty(vtkProperty *prop)
2477{
2478  this->ZAxesGridpolysProperty->DeepCopy(prop);
2479  this->Modified();
2480}
2481
2482// ****************************************************************************
2483vtkProperty* vtkRpCubeAxesActor::GetXAxesGridpolysProperty()
2484{
2485  return this->XAxesGridpolysProperty;
2486}
2487vtkProperty* vtkRpCubeAxesActor::GetYAxesGridpolysProperty()
2488{
2489  return this->YAxesGridpolysProperty;
2490}
2491vtkProperty* vtkRpCubeAxesActor::GetZAxesGridpolysProperty()
2492{
2493  return this->ZAxesGridpolysProperty;
2494}
2495// --------------------------------------------------------------------------
2496void vtkRpCubeAxesActor::UpdateGridLineVisibility(int idx)
2497{
2498  if( this->GridLineLocation != VTK_GRID_LINES_ALL &&
2499      (this->DrawXGridlines || this->DrawYGridlines || this->DrawZGridlines) )
2500    {
2501    for(int i=0; i < NUMBER_OF_ALIGNED_AXIS; ++i)
2502      {
2503      this->XAxes[i]->SetDrawGridlines(0);
2504      this->YAxes[i]->SetDrawGridlines(0);
2505      this->ZAxes[i]->SetDrawGridlines(0);
2506      this->XAxes[i]->SetDrawGridlinesOnly(0);
2507      this->YAxes[i]->SetDrawGridlinesOnly(0);
2508      this->ZAxes[i]->SetDrawGridlinesOnly(0);
2509      }
2510
2511    this->XAxes[vtkRpCubeAxesActorTriads[idx][0]]->SetDrawGridlines(this->DrawXGridlines);
2512    this->YAxes[vtkRpCubeAxesActorTriads[idx][1]]->SetDrawGridlines(this->DrawYGridlines);
2513    this->ZAxes[vtkRpCubeAxesActorTriads[idx][2]]->SetDrawGridlines(this->DrawZGridlines);
2514
2515    // Update axis render list
2516    int id = 0;
2517    if(this->NumberOfAxesX == 1)
2518      {
2519      id = this->RenderAxesX[this->NumberOfAxesX] = vtkRpCubeAxesActorTriads[idx][0];
2520      this->XAxes[id]->SetDrawGridlinesOnly((this->RenderAxesX[0] != id) ? 1 : 0);
2521      this->NumberOfAxesX += (this->RenderAxesX[0] != id) ? 1 : 0;
2522      }
2523    if(this->NumberOfAxesY == 1)
2524      {
2525      id = this->RenderAxesY[this->NumberOfAxesY] = vtkRpCubeAxesActorTriads[idx][1];
2526      this->YAxes[id]->SetDrawGridlinesOnly((this->RenderAxesY[0] != id) ? 1 : 0);
2527      this->NumberOfAxesY += (this->RenderAxesY[0] != id) ? 1 : 0;
2528      }
2529    if(this->NumberOfAxesZ == 1)
2530      {
2531      id = this->RenderAxesZ[this->NumberOfAxesZ] = vtkRpCubeAxesActorTriads[idx][2];
2532      this->ZAxes[id]->SetDrawGridlinesOnly((this->RenderAxesZ[0] != id) ? 1 : 0);
2533      this->NumberOfAxesZ += (this->RenderAxesZ[0] != id) ? 1 : 0;
2534      }
2535    }
2536}
2537// --------------------------------------------------------------------------
2538int vtkRpCubeAxesActor::FindClosestAxisIndex(double pts[8][3])
2539{
2540  // Loop over points and find the closest point to the camera
2541  double min = VTK_LARGE_FLOAT;
2542  int idx = 0;
2543  for (int i=0; i < 8; i++)
2544    {
2545    if (pts[i][2] < min)
2546      {
2547      idx = i;
2548      min = pts[i][2];
2549      }
2550    }
2551  return idx;
2552}
2553
2554// --------------------------------------------------------------------------
2555int vtkRpCubeAxesActor::FindFurtherstAxisIndex(double pts[8][3])
2556{
2557  // Loop over points and find the furthest point from the camera
2558  double max = -VTK_LARGE_FLOAT;
2559  int idx = 0;
2560  for (int i=0; i < 8; i++)
2561    {
2562    if (pts[i][2] > max)
2563      {
2564      idx = i;
2565      max = pts[i][2];
2566      }
2567    }
2568  return idx;
2569}
2570// --------------------------------------------------------------------------
2571 void vtkRpCubeAxesActor::FindBoundaryEdge( int &xloc, int &yloc,
2572                                          int &zloc, double pts[8][3])
2573 {
2574   // boundary edges fly mode
2575   xloc = yloc = zloc = 1;
2576   int i, xIdx = 0, yIdx = 0, zIdx = 0, zIdx2 = 0;
2577   int xAxes = 0, yAxes = 0, zAxes = 0;
2578   double slope = 0.0, minSlope, num, den, d2;
2579   double e1[3], e2[3], e3[3];
2580   int idx = 0;
2581
2582   // Find distance to origin
2583   double d2Min = VTK_LARGE_FLOAT;
2584   for (i=0; i < 8; i++)
2585     {
2586     d2 = pts[i][0]*pts[i][0] + pts[i][1]*pts[i][1];
2587     if (d2 < d2Min)
2588       {
2589       d2Min = d2;
2590       idx = i;
2591       }
2592     }
2593
2594   // find minimum slope point connected to closest point and on
2595   // right side (in projected coordinates). This is the first edge.
2596   minSlope = VTK_LARGE_FLOAT;
2597   for (xIdx=0, i=0; i<3; i++)
2598     {
2599     num = (pts[vtkRpCubeAxesActorConn[idx][i]][1] - pts[idx][1]);
2600     den = (pts[vtkRpCubeAxesActorConn[idx][i]][0] - pts[idx][0]);
2601     if (den != 0.0)
2602       {
2603       slope = num / den;
2604       }
2605     if (slope < minSlope && den > 0)
2606       {
2607       xIdx = vtkRpCubeAxesActorConn[idx][i];
2608       yIdx = vtkRpCubeAxesActorConn[idx][(i+1)%3];
2609       zIdx = vtkRpCubeAxesActorConn[idx][(i+2)%3];
2610       xAxes = i;
2611       minSlope = slope;
2612       }
2613     }
2614
2615   // find edge (connected to closest point) on opposite side
2616   for ( i=0; i<3; i++)
2617     {
2618     e1[i] = (pts[xIdx][i] - pts[idx][i]);
2619     e2[i] = (pts[yIdx][i] - pts[idx][i]);
2620     e3[i] = (pts[zIdx][i] - pts[idx][i]);
2621     }
2622   vtkMath::Normalize(e1);
2623   vtkMath::Normalize(e2);
2624   vtkMath::Normalize(e3);
2625
2626   if (vtkMath::Dot(e1,e2) < vtkMath::Dot(e1,e3))
2627     {
2628     yAxes = (xAxes + 1) % 3;
2629     }
2630   else
2631     {
2632     yIdx = zIdx;
2633     yAxes = (xAxes + 2) % 3;
2634     }
2635
2636   // Find the final point by determining which global x-y-z axes have not
2637   // been represented, and then determine the point closest to the viewer.
2638   zAxes = (xAxes != 0 && yAxes != 0 ? 0 :
2639           (xAxes != 1 && yAxes != 1 ? 1 : 2));
2640   if (pts[vtkRpCubeAxesActorConn[xIdx][zAxes]][2] <
2641       pts[vtkRpCubeAxesActorConn[yIdx][zAxes]][2])
2642     {
2643     zIdx = xIdx;
2644     zIdx2 = vtkRpCubeAxesActorConn[xIdx][zAxes];
2645     }
2646   else
2647     {
2648     zIdx = yIdx;
2649     zIdx2 = vtkRpCubeAxesActorConn[yIdx][zAxes];
2650     }
2651
2652   int mini = (idx < xIdx ? idx : xIdx);
2653   switch (xAxes)
2654     {
2655     case 0:
2656       xloc = vtkRpCubeAxesActorTriads[mini][0];
2657       break;
2658     case 1:
2659       yloc = vtkRpCubeAxesActorTriads[mini][1];
2660       break;
2661     case 2:
2662       zloc = vtkRpCubeAxesActorTriads[mini][2];
2663       break;
2664     }
2665   mini = (idx < yIdx ? idx : yIdx);
2666   switch (yAxes)
2667     {
2668     case 0:
2669       xloc = vtkRpCubeAxesActorTriads[mini][0];
2670       break;
2671     case 1:
2672       yloc =vtkRpCubeAxesActorTriads[mini][1];
2673       break;
2674     case 2:
2675       zloc = vtkRpCubeAxesActorTriads[mini][2];
2676       break;
2677     }
2678   mini = (zIdx < zIdx2 ? zIdx : zIdx2);
2679   switch (zAxes)
2680     {
2681     case 0:
2682       xloc = vtkRpCubeAxesActorTriads[mini][0];
2683       break;
2684     case 1:
2685       yloc = vtkRpCubeAxesActorTriads[mini][1];
2686       break;
2687     case 2:
2688       zloc = vtkRpCubeAxesActorTriads[mini][2];
2689       break;
2690     }
2691 }
2692
2693// --------------------------------------------------------------------------
2694int vtkRpCubeAxesActor::RenderGeometry(
2695    bool &initialRender, vtkViewport *viewport, bool checkAxisVisibility,
2696    int (vtkRpAxisActor::*renderMethod)(vtkViewport*))
2697{
2698  int i, renderedSomething = 0;
2699
2700  // Make sure axes are initialized and visibility is properly set
2701  if(checkAxisVisibility)
2702    {
2703    // Initialization
2704    if (!this->Camera)
2705      {
2706      vtkErrorMacro(<<"No camera!");
2707      this->RenderSomething = 0;
2708      return 0;
2709      }
2710
2711    this->BuildAxes(viewport);
2712
2713    if (initialRender)
2714      {
2715      for (i = 0; i < NUMBER_OF_ALIGNED_AXIS; i++)
2716        {
2717        this->XAxes[i]->BuildAxis(viewport, true);
2718        this->YAxes[i]->BuildAxis(viewport, true);
2719        this->ZAxes[i]->BuildAxis(viewport, true);
2720        }
2721      }
2722    initialRender = false;
2723
2724    this->DetermineRenderAxes(viewport);
2725    }
2726
2727  // Render the axes
2728  for (i = 0; i < this->NumberOfAxesX; i++)
2729    {
2730    renderedSomething +=
2731        (this->XAxes[this->RenderAxesX[i]]->*renderMethod)(viewport);
2732    }
2733
2734  for (i = 0; i < this->NumberOfAxesY; i++)
2735    {
2736    renderedSomething +=
2737        (this->YAxes[this->RenderAxesY[i]]->*renderMethod)(viewport);
2738    }
2739
2740  for (i = 0; i < this->NumberOfAxesZ; i++)
2741    {
2742    renderedSomething +=
2743        (this->ZAxes[this->RenderAxesZ[i]]->*renderMethod)(viewport);
2744    }
2745  return renderedSomething;
2746}
2747
2748// --------------------------------------------------------------------------
2749void vtkRpCubeAxesActor::GetRenderedBounds(double *b)
2750{
2751  vtkBoundingBox bbox(this->GetBounds()); // Data bounds
2752
2753  // Make a heuristic on the final bounds that embed test labels
2754  // Just inflate the box based on its max length
2755  bbox.Inflate(bbox.GetMaxLength());
2756
2757  bbox.GetBounds(b);
2758}
2759
2760// --------------------------------------------------------------------------
2761double* vtkRpCubeAxesActor::GetRenderedBounds()
2762{
2763  this->GetRenderedBounds(this->RenderedBounds);
2764  // Return our data holder
2765  return this->RenderedBounds;
2766}
Note: See TracBrowser for help on using the repository browser.