source: vtkvis/trunk/vtkRpCubeAxesActor.cpp @ 6226

Last change on this file since 6226 was 5802, checked in by ldelgass, 9 years ago

Update custom cube axes: rebase on version in VTK 6.1.0 plus backported fixes
from 6.3.0rc1, but without TextActor3D option.

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