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

Last change on this file since 3586 was 3586, checked in by ldelgass, 11 years ago

Fix label disappearing at first tick: if axis min value is divisible by
tick delta, set tick labels starting at minimum.

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