source: vtkvis/trunk/vtkRpCubeAxesActor.cpp @ 4643

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

Remove enclosing Rappture namespace from vtkvis. Remove outline and outline
color subcommands from dataset in vtkvis protocol -- they are replaced by the
outline object. Translate heightmap to dataset z plane (client is doing this
right now).

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