source: branches/blt4/packages/vizservers/vtkvis/vtkRpCubeAxesActor.cpp @ 2936

Last change on this file since 2936 was 2936, checked in by gah, 12 years ago

sync back with trunk

File size: 62.5 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 "vtkCamera.h"
19#include "vtkCoordinate.h"
20#include "vtkRpAxisActor.h"
21#include "vtkMath.h"
22#include "vtkObjectFactory.h"
23#include "vtkProperty.h"
24#include "vtkStringArray.h"
25#include "vtkViewport.h"
26
27// *************************************************************************
28// Modifications:
29//   Kathleen Bonnell, Wed Mar  6 13:48:48 PST 2002
30//   Replace 'New' method with Macro to match VTK 4.0 API.
31//
32// *************************************************************************
33
34vtkStandardNewMacro(vtkRpCubeAxesActor);
35vtkCxxSetObjectMacro(vtkRpCubeAxesActor, Camera,vtkCamera);
36
37// *************************************************************************
38// Instantiate this object.
39//
40// Modifications:
41//   Kathleen Bonnell, Wed Oct 31 07:57:49 PST 2001
42//   Intialize new members lastPow, last*AxisDigits.
43//
44//   Kathleen Bonnell, Wed Nov  7 16:19:16 PST 2001
45//   Intialize new members:  Last*Extent, LastFlyMode,
46//   renderAxes*, numAxes*.
47//
48//   Hank Childs, Fri Sep 27 17:15:07 PDT 2002
49//   Initialize new members for units.
50//
51//   Kathleen Bonnell, Fri Jul 25 14:37:32 PDT 2003
52//   Remove 'Input' and 'Prop' members, initialize new members
53//   valueScaleFactor, mustAdjustValue, ForceLabelReset.
54//
55//   Kathleen Bonnell, Wed Aug  6 13:59:15 PDT 2003
56//   Remove valueScaleFactor, replace mustAdjustValue and ForceLabelReset
57//   with one for each axis type.
58//
59//   Kathleen Bonnell, Tue Dec 16 11:27:30 PST 2003
60//   Replace Last*Extent with Last*Range.  (* = X, Y, Z)
61//   Add AutoLabelScaling, UserXPow, UserYPow, UserZPow.
62//
63//   Brad Whitlock, Fri Jul 23 18:18:41 PST 2004
64//   Added ActualXLabel et al so we can keep title separate from what's
65//   actually displayed so information is not lost.
66//
67// *************************************************************************
68
69vtkRpCubeAxesActor::vtkRpCubeAxesActor()
70{
71  this->Bounds[0] = -1.0; this->Bounds[1] = 1.0;
72  this->Bounds[2] = -1.0; this->Bounds[3] = 1.0;
73  this->Bounds[4] = -1.0; this->Bounds[5] = 1.0;
74
75  this->TickLocation = VTK_TICKS_INSIDE;
76  this->Camera = NULL;
77  this->FlyMode = VTK_FLY_CLOSEST_TRIAD;
78  int i;
79  for (i = 0; i < 4; i++)
80    {
81    this->XAxes[i] = vtkRpAxisActor::New();
82    this->XAxes[i]->SetTickVisibility(1);
83    this->XAxes[i]->SetMinorTicksVisible(1);
84    this->XAxes[i]->SetLabelVisibility(1);
85    this->XAxes[i]->SetTitleVisibility(1);
86    this->XAxes[i]->SetAxisTypeToX();
87    this->XAxes[i]->SetAxisPosition(i);
88
89    this->YAxes[i] = vtkRpAxisActor::New();
90    this->YAxes[i]->SetTickVisibility(1);
91    this->YAxes[i]->SetMinorTicksVisible(1);
92    this->YAxes[i]->SetLabelVisibility(1);
93    this->YAxes[i]->SetTitleVisibility(1);
94    this->YAxes[i]->SetAxisTypeToY();
95    this->YAxes[i]->SetAxisPosition(i);
96
97    this->ZAxes[i] = vtkRpAxisActor::New();
98    this->ZAxes[i]->SetTickVisibility(1);
99    this->ZAxes[i]->SetMinorTicksVisible(1);
100    this->ZAxes[i]->SetLabelVisibility(1);
101    this->ZAxes[i]->SetTitleVisibility(1);
102    this->ZAxes[i]->SetAxisTypeToZ();
103    this->ZAxes[i]->SetAxisPosition(i);
104    }
105
106  this->XLabelFormat = new char[8];
107  sprintf(this->XLabelFormat, "%s", "%-#6.3g");
108  this->YLabelFormat = new char[8];
109  sprintf(this->YLabelFormat, "%s", "%-#6.3g");
110  this->ZLabelFormat = new char[8];
111  sprintf(this->ZLabelFormat, "%s", "%-#6.3g");
112  this->CornerOffset = 0.0;
113  this->Inertia = 1;
114  this->RenderCount = 0;
115
116  this->XAxisVisibility = 1;
117  this->YAxisVisibility = 1;
118  this->ZAxisVisibility = 1;
119
120  this->XAxisTickVisibility = 1;
121  this->YAxisTickVisibility = 1;
122  this->ZAxisTickVisibility = 1;
123
124  this->XAxisMinorTickVisibility = 1;
125  this->YAxisMinorTickVisibility = 1;
126  this->ZAxisMinorTickVisibility = 1;
127
128  this->XAxisLabelVisibility = 1;
129  this->YAxisLabelVisibility = 1;
130  this->ZAxisLabelVisibility = 1;
131
132  this->DrawXGridlines = 0;
133  this->DrawYGridlines = 0;
134  this->DrawZGridlines = 0;
135
136  this->XTitle = new char[7];
137  sprintf(this->XTitle, "%s", "X-Axis");
138  this->XUnits = NULL;
139  this->YTitle = new char[7];
140  sprintf(this->YTitle, "%s", "Y-Axis");
141  this->YUnits = NULL;
142  this->ZTitle = new char[7];
143  sprintf(this->ZTitle, "%s", "Z-Axis");
144  this->ZUnits = NULL;
145
146  this->ActualXLabel = 0;
147  this->ActualYLabel = 0;
148  this->ActualZLabel = 0;
149
150  this->LastXPow = 0;
151  this->LastYPow = 0;
152  this->LastZPow = 0;
153  this->LastXAxisDigits = 3;
154  this->LastYAxisDigits = 3;
155  this->LastZAxisDigits = 3;
156
157  this->LastXRange[0] = VTK_FLOAT_MAX;
158  this->LastXRange[1] = VTK_FLOAT_MAX;
159  this->LastYRange[0] = VTK_FLOAT_MAX;
160  this->LastYRange[1] = VTK_FLOAT_MAX;
161  this->LastZRange[0] = VTK_FLOAT_MAX;
162  this->LastZRange[1] = VTK_FLOAT_MAX;
163
164  this->LastFlyMode = -1;
165  for (i = 0; i < 4; i++)
166    {
167    this->RenderAxesX[i] = i;
168    this->RenderAxesY[i] = i;
169    this->RenderAxesZ[i] = i;
170    }
171  this->NumberOfAxesX = this->NumberOfAxesY = this->NumberOfAxesZ = 1;
172
173  this->MustAdjustXValue = false;
174  this->MustAdjustYValue = false;
175  this->MustAdjustZValue = false;
176
177  this->ForceXLabelReset = false;
178  this->ForceYLabelReset = false;
179  this->ForceZLabelReset = false;
180
181  this->AutoLabelScaling = true;
182  this->UserXPow = 0;
183  this->UserYPow = 0;
184  this->UserZPow = 0;
185
186  this->XAxisRange[0] = VTK_DOUBLE_MAX;
187  this->XAxisRange[1] = VTK_DOUBLE_MAX;
188  this->YAxisRange[0] = VTK_DOUBLE_MAX;
189  this->YAxisRange[1] = VTK_DOUBLE_MAX;
190  this->ZAxisRange[0] = VTK_DOUBLE_MAX;
191  this->ZAxisRange[1] = VTK_DOUBLE_MAX;
192}
193
194// ****************************************************************************
195// Shallow copy of an actor.
196//
197// Modifications:
198//   Kathleen Bonnell, Wed Mar  6 13:48:48 PST 2002
199//   Call superclass method the new VTK 4.0 way.
200//
201//   Kathleen Bonnell, Fri Jul 25 14:37:32 PDT 2003
202//   Remove 'Input' and 'Prop' members, added new members
203//   valueScaleFactor, mustAdjustValue, ForceLabelReset.
204//
205//   Kathleen Bonnell, Wed Aug  6 13:59:15 PDT 2003
206//   Remove valueScaleFactor, replace mustAdjustValue and ForceLabelReset
207//   with one for each axis type.
208//
209// ****************************************************************************
210
211void vtkRpCubeAxesActor::ShallowCopy(vtkRpCubeAxesActor *actor)
212{
213  this->Superclass::ShallowCopy(actor);
214  this->SetXLabelFormat(actor->GetXLabelFormat());
215  this->SetYLabelFormat(actor->GetYLabelFormat());
216  this->SetZLabelFormat(actor->GetZLabelFormat());
217  this->SetCornerOffset(actor->GetCornerOffset());
218  this->SetInertia(actor->GetInertia());
219  this->SetXTitle(actor->GetXTitle());
220  this->SetYTitle(actor->GetYTitle());
221  this->SetZTitle(actor->GetZTitle());
222  this->SetFlyMode(actor->GetFlyMode());
223  this->SetCamera(actor->GetCamera());
224  this->SetBounds(actor->GetBounds());
225  this->MustAdjustXValue = actor->MustAdjustXValue;
226  this->MustAdjustYValue = actor->MustAdjustYValue;
227  this->MustAdjustZValue = actor->MustAdjustZValue;
228  this->ForceXLabelReset = actor->ForceXLabelReset;
229  this->ForceYLabelReset = actor->ForceYLabelReset;
230  this->ForceZLabelReset = actor->ForceZLabelReset;
231}
232
233// ****************************************************************************
234//  Modifications:
235//
236//    Hank Childs, Fri Sep 27 17:15:07 PDT 2002
237//    Destruct new data members for units.
238//
239//    Brad Whitlock, Fri Jul 23 18:21:16 PST 2004
240//    Added more items and fixed a small memory leak.
241//
242// ****************************************************************************
243
244vtkRpCubeAxesActor::~vtkRpCubeAxesActor()
245{
246  this->SetCamera(NULL);
247
248  for (int i = 0; i < 4; i++)
249    {
250    if (this->XAxes[i])
251      {
252      this->XAxes[i]->Delete();
253      this->XAxes[i] = NULL;
254      }
255    if (this->YAxes[i])
256      {
257      this->YAxes[i]->Delete();
258      this->YAxes[i] = NULL;
259      }
260    if (this->ZAxes[i])
261      {
262      this->ZAxes[i]->Delete();
263      this->ZAxes[i] = NULL;
264      }
265    }
266
267  if (this->XLabelFormat)
268    {
269    delete [] this->XLabelFormat;
270    this->XLabelFormat = NULL;
271    }
272
273  if (this->YLabelFormat)
274    {
275    delete [] this->YLabelFormat;
276    this->YLabelFormat = NULL;
277    }
278
279  if (this->ZLabelFormat)
280    {
281    delete [] this->ZLabelFormat;
282    this->ZLabelFormat = NULL;
283    }
284
285  if (this->XTitle)
286    {
287    delete [] this->XTitle;
288    this->XTitle = NULL;
289    }
290  if (this->YTitle)
291    {
292    delete [] this->YTitle;
293    this->YTitle = NULL;
294    }
295  if (this->ZTitle)
296    {
297    delete [] this->ZTitle;
298    this->ZTitle = NULL;
299    }
300
301  if (this->XUnits)
302    {
303    delete [] this->XUnits;
304    this->XUnits = NULL;
305    }
306  if (this->YUnits)
307    {
308    delete [] this->YUnits;
309    this->YUnits = NULL;
310    }
311  if (this->ZUnits)
312    {
313    delete [] this->ZUnits;
314    this->ZUnits = NULL;
315    }
316
317  if (this->ActualXLabel)
318    {
319    delete [] this->ActualXLabel;
320    this->ActualXLabel = NULL;
321    }
322  if (this->ActualYLabel)
323    {
324    delete [] this->ActualYLabel;
325    this->ActualYLabel = NULL;
326    }
327  if (this->ActualZLabel)
328    {
329    delete [] this->ActualZLabel;
330    this->ActualZLabel = NULL;
331    }
332}
333
334// *************************************************************************
335// Project the bounding box and compute edges on the border of the bounding
336// cube. Determine which parts of the edges are visible via intersection
337// with the boundary of the viewport (minus borders).
338//
339//  Modifications:
340//    Kathleen Bonnell, Wed Oct 31 07:57:49 PST 2001
341//    Added calls to AdjustValues, AdjustRange.
342//
343//   Kathleen Bonnell, Wed Nov  7 16:19:16 PST 2001
344//   Only render those axes needed for current FlyMode.
345//   Moved bulk of 'build' code to BuildAxes method, added calls to
346//   BuildAxes and DetermineRenderAxes methods.
347//
348//   Kathleen Bonnell, Fri Jul 25 14:37:32 PDT 2003
349//   Added initial build of each axis.
350// *************************************************************************
351
352int vtkRpCubeAxesActor::RenderOpaqueGeometry(vtkViewport *viewport)
353{
354  int i, renderedSomething=0;
355  static bool initialRender = true;
356  // Initialization
357  if (!this->Camera)
358    {
359    vtkErrorMacro(<<"No camera!");
360    this->RenderSomething = 0;
361    return 0;
362    }
363
364  this->BuildAxes(viewport);
365
366  if (initialRender)
367    {
368    for (i = 0; i < 4; i++)
369      {
370      this->XAxes[i]->BuildAxis(viewport, true);
371      this->YAxes[i]->BuildAxis(viewport, true);
372      this->ZAxes[i]->BuildAxis(viewport, true);
373      }
374    }
375  initialRender = false;
376
377  this->DetermineRenderAxes(viewport);
378
379  //Render the axes
380  if (this->XAxisVisibility)
381    {
382    for (i = 0; i < this->NumberOfAxesX; i++)
383      {
384      renderedSomething +=
385        this->XAxes[this->RenderAxesX[i]]->RenderOpaqueGeometry(viewport);
386      }
387    }
388
389  if (this->YAxisVisibility)
390    {
391    for (i = 0; i < this->NumberOfAxesY; i++)
392      {
393      renderedSomething +=
394        this->YAxes[this->RenderAxesY[i]]->RenderOpaqueGeometry(viewport);
395      }
396    }
397
398  if (this->ZAxisVisibility)
399    {
400    for (i = 0; i < this->NumberOfAxesZ; i++)
401      {
402      renderedSomething +=
403        this->ZAxes[this->RenderAxesZ[i]]->RenderOpaqueGeometry(viewport);
404      }
405    }
406  return renderedSomething;
407}
408
409// Do final adjustment of axes to control offset, etc.
410void vtkRpCubeAxesActor::AdjustAxes(double bounds[6], double xCoords[4][6],
411                                  double yCoords[4][6], double zCoords[4][6],
412                                  double xRange[2], double yRange[2],
413                                  double zRange[2])
414{
415  xRange[0] = (this->XAxisRange[0] == VTK_DOUBLE_MAX ?
416                                  bounds[0] : this->XAxisRange[0]);
417  xRange[1] = (this->XAxisRange[1] == VTK_DOUBLE_MAX ?
418                                  bounds[1] : this->XAxisRange[1]);
419  yRange[0] = (this->YAxisRange[0] == VTK_DOUBLE_MAX ?
420                                  bounds[2] : this->YAxisRange[0]);
421  yRange[1] = (this->YAxisRange[1] == VTK_DOUBLE_MAX ?
422                                  bounds[3] : this->YAxisRange[1]);
423  zRange[0] = (this->ZAxisRange[0] == VTK_DOUBLE_MAX ?
424                                  bounds[4] : this->ZAxisRange[0]);
425  zRange[1] = (this->ZAxisRange[1] == VTK_DOUBLE_MAX ?
426                                  bounds[5] : this->ZAxisRange[1]);
427
428  const double xScale = (xRange[1] - xRange[0])/(bounds[1] - bounds[0]);
429  const double yScale = (yRange[1] - yRange[0])/(bounds[3] - bounds[2]);
430  const double zScale = (zRange[1] - zRange[0])/(bounds[5] - bounds[4]);
431
432  // Pull back the corners if specified
433  if (this->CornerOffset > 0.0)
434    {
435    for (int i = 0; i < 4; i++)
436      {
437      double ave;
438
439      // x-axis
440      ave = (xCoords[i][0] + xCoords[i][2]) / 2.0;
441      xCoords[i][0] =
442        xCoords[i][0] - this->CornerOffset * (xCoords[i][0] - ave);
443      xCoords[i][2] =
444        xCoords[i][2] - this->CornerOffset * (xCoords[i][2] - ave);
445
446      ave = (xCoords[i][1] + xCoords[i][3]) / 2.0;
447      xCoords[i][1] =
448        xCoords[i][1] - this->CornerOffset * (xCoords[i][1] - ave);
449      xCoords[i][3] =
450        xCoords[i][3] - this->CornerOffset * (xCoords[i][3] - ave);
451
452      ave = (xRange[1] + xRange[0]) / 2.0;
453      xRange[0] = xRange[0] - this->CornerOffset * xScale * (xRange[0] - ave);
454      xRange[1] = xRange[1] - this->CornerOffset * xScale * (xRange[1] - ave);
455
456      // y-axis
457      ave = (yCoords[i][0] + yCoords[i][2]) / 2.0;
458      yCoords[i][0] =
459        yCoords[i][0] - this->CornerOffset * (yCoords[i][0] - ave);
460      yCoords[i][2] =
461        yCoords[i][2] - this->CornerOffset * (yCoords[i][2] - ave);
462
463      ave = (yCoords[i][1] + yCoords[i][3]) / 2.0;
464      yCoords[i][1] =
465        yCoords[i][1] - this->CornerOffset * (yCoords[i][1] - ave);
466      yCoords[i][3] =
467        yCoords[i][3] - this->CornerOffset * (yCoords[i][3] - ave);
468
469      ave = (yRange[1] + yRange[0]) / 2.0;
470      yRange[0] = yRange[0] - this->CornerOffset * yScale * (yRange[0] - ave);
471      yRange[1] = yRange[1] - this->CornerOffset * yScale * (yRange[1] - ave);
472
473      // z-axis
474      ave = (zCoords[i][0] + zCoords[i][2]) / 2.0;
475      zCoords[i][0] =
476        zCoords[i][0] - this->CornerOffset * (zCoords[i][0] - ave);
477      zCoords[i][2] =
478        zCoords[i][2] - this->CornerOffset * (zCoords[i][2] - ave);
479
480      ave = (zCoords[i][1] + zCoords[i][3]) / 2.0;
481      zCoords[i][1] =
482        zCoords[i][1] - this->CornerOffset * (zCoords[i][1] - ave);
483      zCoords[i][3] =
484        zCoords[i][3] - this->CornerOffset * (zCoords[i][3] - ave);
485
486      ave = (zRange[1] + zRange[0]) / 2.0;
487      zRange[0] = zRange[0] - this->CornerOffset * zScale * (zRange[0] - ave);
488      zRange[1] = zRange[1] - this->CornerOffset * zScale * (zRange[1] - ave);
489      }
490    }
491}
492
493// Release any graphics resources that are being consumed by this actor.
494// The parameter window could be used to determine which graphic
495// resources to release.
496void vtkRpCubeAxesActor::ReleaseGraphicsResources(vtkWindow *win)
497{
498  for (int i = 0; i < 4; i++)
499    {
500    this->XAxes[i]->ReleaseGraphicsResources(win);
501    this->YAxes[i]->ReleaseGraphicsResources(win);
502    this->ZAxes[i]->ReleaseGraphicsResources(win);
503    }
504}
505
506// *************************************************************************
507// Compute the bounds
508//
509// Modifications:
510//   Kathleen Bonnell, Fri Jul 25 14:37:32 PDT 2003
511//   Removed support for Prop and Input.
512// *************************************************************************
513void vtkRpCubeAxesActor::GetBounds(double bounds[6])
514{
515  for (int i=0; i< 6; i++)
516    {
517    bounds[i] = this->Bounds[i];
518    }
519}
520
521// Compute the bounds
522void vtkRpCubeAxesActor::GetBounds(double& xmin, double& xmax,
523                                 double& ymin, double& ymax,
524                                 double& zmin, double& zmax)
525{
526  xmin = this->Bounds[0];
527  xmax = this->Bounds[1];
528  ymin = this->Bounds[2];
529  ymax = this->Bounds[3];
530  zmin = this->Bounds[4];
531  zmax = this->Bounds[5];
532}
533
534// Compute the bounds
535double *vtkRpCubeAxesActor::GetBounds()
536{
537  return this->Bounds;
538}
539
540// ******************************************************************
541// Modifications:
542//   Kathleen Bonnell, Wed Mar  6 13:48:48 PST 2002
543//   Call superclass method the new VTK 4.0 way.
544//
545//   Kathleen Bonnell, Fri Jul 25 14:37:32 PDT 2003
546//   Removed Input and Prop.
547//
548// ******************************************************************
549
550void vtkRpCubeAxesActor::PrintSelf(ostream& os, vtkIndent indent)
551{
552  this->Superclass::PrintSelf(os,indent);
553
554  os << indent << "Bounds: \n";
555  os << indent << "  Xmin,Xmax: (" << this->Bounds[0] << ", "
556     << this->Bounds[1] << ")\n";
557  os << indent << "  Ymin,Ymax: (" << this->Bounds[2] << ", "
558     << this->Bounds[3] << ")\n";
559  os << indent << "  Zmin,Zmax: (" << this->Bounds[4] << ", "
560     << this->Bounds[5] << ")\n";
561
562
563  os << indent << "XAxisRange: [" << this->XAxisRange[0] << ", "
564    << this->XAxisRange[1] << "] " << endl;
565  os << indent << "YAxisRange: [" << this->YAxisRange[0] << ", "
566    << this->YAxisRange[1] << "] " << endl;
567  os << indent << "ZAxisRange: [" << this->ZAxisRange[0] << ", "
568    << this->ZAxisRange[1] << "] " << endl;
569
570  if (this->Camera)
571    {
572    os << indent << "Camera:\n";
573    this->Camera->PrintSelf(os,indent.GetNextIndent());
574    }
575  else
576    {
577    os << indent << "Camera: (none)\n";
578    }
579
580  if (this->FlyMode == VTK_FLY_CLOSEST_TRIAD)
581    {
582    os << indent << "Fly Mode: CLOSEST_TRIAD\n";
583    }
584  else if (this->FlyMode == VTK_FLY_FURTHEST_TRIAD)
585    {
586    os << indent << "Fly Mode: FURTHEST_TRIAD\n";
587    }
588  else if (this->FlyMode == VTK_FLY_STATIC_TRIAD)
589    {
590    os << indent << "Fly Mode: STATIC_TRIAD\n";
591    }
592  else if (this->FlyMode == VTK_FLY_STATIC_EDGES)
593    {
594    os << indent << "Fly Mode: STATIC_EDGES\n";
595    }
596  else
597    {
598    os << indent << "Fly Mode: OUTER_EDGES\n";
599    }
600
601  os << indent << "X Axis Title: " << this->XTitle << "\n";
602  os << indent << "Y Axis Title: " << this->YTitle << "\n";
603  os << indent << "Z Axis Title: " << this->ZTitle << "\n";
604
605  os << indent << "X Axis Visibility: "
606     << (this->XAxisVisibility ? "On\n" : "Off\n");
607  os << indent << "Y Axis Visibility: "
608     << (this->YAxisVisibility ? "On\n" : "Off\n");
609  os << indent << "Z Axis Visibility: "
610     << (this->ZAxisVisibility ? "On\n" : "Off\n");
611
612  os << indent << "X Axis Label Format: " << this->XLabelFormat << "\n";
613  os << indent << "Y Axis Label Format: " << this->YLabelFormat << "\n";
614  os << indent << "Z Axis Label Format: " << this->ZLabelFormat << "\n";
615  os << indent << "Inertia: " << this->Inertia << "\n";
616  os << indent << "Corner Offset: " << this->CornerOffset << "\n";
617
618  os << indent << "XAxisTickVisibility: "
619     << (this->XAxisTickVisibility ? "On" : "Off") << endl;
620  os << indent << "YAxisTickVisibility: "
621     << (this->YAxisTickVisibility ? "On" : "Off") << endl;
622  os << indent << "ZAxisTickVisibility: "
623     << (this->ZAxisTickVisibility ? "On" : "Off") << endl;
624
625  os << indent << "XAxisMinorTickVisibility: "
626     << (this->XAxisMinorTickVisibility ? "On" : "Off") << endl;
627  os << indent << "YAxisMinorTickVisibility: "
628     << (this->YAxisMinorTickVisibility ? "On" : "Off") << endl;
629  os << indent << "ZAxisMinorTickVisibility: "
630     << (this->ZAxisMinorTickVisibility ? "On" : "Off") << endl;
631
632  os << indent << "XAxisLabelVisibility: "
633     << (this->XAxisLabelVisibility ? "On" : "Off") << endl;
634  os << indent << "YAxisLabelVisibility: "
635     << (this->YAxisLabelVisibility ? "On" : "Off") << endl;
636  os << indent << "ZAxisLabelVisibility: "
637     << (this->ZAxisLabelVisibility ? "On" : "Off") << endl;
638
639  os << indent << "XUnits: "
640     << (this->XUnits ? this->XUnits : "(none)") << endl;
641  os << indent << "YUnits: "
642     << (this->YUnits ? this->YUnits : "(none)") << endl;
643  os << indent << "ZUnits: "
644     << (this->ZUnits ? this->ZUnits : "(none)") << endl;
645
646  os << indent << "TickLocation: " << this->TickLocation << endl;
647
648  os << indent << "DrawXGridlines: " << this->DrawXGridlines << endl;
649  os << indent << "DrawYGridlines: " << this->DrawYGridlines << endl;
650  os << indent << "DrawZGridlines: " << this->DrawZGridlines << endl;
651}
652
653void vtkRpCubeAxesActor::TransformBounds(vtkViewport *viewport,
654                                       const double bounds[6],
655                                       double pts[8][3])
656{
657  int i, j, k, idx;
658  double x[3];
659
660  //loop over verts of bounding box
661  for (k=0; k<2; k++)
662    {
663    x[2] = bounds[4+k];
664    for (j=0; j<2; j++)
665      {
666      x[1] = bounds[2+j];
667      for (i=0; i<2; i++)
668        {
669        idx = i + 2*j + 4*k;
670        x[0] = bounds[i];
671        viewport->SetWorldPoint(x[0],x[1],x[2],1.0);
672        viewport->WorldToDisplay();
673        viewport->GetDisplayPoint(pts[idx]);
674        }
675      }
676    }
677}
678
679// ***********************************************************************
680//
681//  Calculate the size (length) of major and minor ticks,
682//  based on an average of the coordinate direction ranges.
683//  Set the necessary Axes methods with the calculated information.
684//
685//  Returns:  false if tick size not recomputed, true otherwise.
686//
687//  Modifications:
688//    Kathleen Bonnell, Wed Nov  7 16:19:16 PST 2001
689//    Added logic for early-termination.
690//
691//    Kathleen Bonnell, Fri Jul 18 09:09:31 PDT 2003
692//    Added return value, added calls to AdjustTicksComputeRange and
693//    BuildLabels.
694//
695//    Kathleen Bonnell, Mon Dec 15 14:59:26 PST 2003
696//    Use the actual range values instead of range-extents to determine
697//    if tick size needs to be recomputed.
698//
699// ***********************************************************************
700
701bool vtkRpCubeAxesActor::ComputeTickSize(double bounds[6])
702{
703  bool xRangeChanged = this->LastXRange[0] != bounds[0] ||
704                       this->LastXRange[1] != bounds[1];
705
706  bool yRangeChanged = this->LastYRange[0] != bounds[2] ||
707                       this->LastYRange[1] != bounds[3];
708
709  bool zRangeChanged = this->LastZRange[0] != bounds[4] ||
710                       this->LastZRange[1] != bounds[5];
711
712  if (!(xRangeChanged || yRangeChanged || zRangeChanged))
713    {
714    // no need to re-compute ticksize.
715    return false;
716    }
717
718  int i;
719  double xExt = bounds[1] - bounds[0];
720  double yExt = bounds[3] - bounds[2];
721  double zExt = bounds[5] - bounds[4];
722
723  if (xRangeChanged)
724    {
725    this->AdjustTicksComputeRange(this->XAxes, bounds[0], bounds[1]);
726    this->BuildLabels(this->XAxes);
727    }
728  if (yRangeChanged)
729    {
730    this->AdjustTicksComputeRange(this->YAxes, bounds[2], bounds[3]);
731    this->BuildLabels(this->YAxes);
732    }
733  if (zRangeChanged)
734    {
735    this->AdjustTicksComputeRange(this->ZAxes, bounds[4], bounds[5]);
736    this->BuildLabels(this->ZAxes);
737    }
738
739  this->LastXRange[0] = (this->XAxisRange[0] == VTK_DOUBLE_MAX ?
740                                  bounds[0] : this->XAxisRange[0]);
741  this->LastXRange[1] = (this->XAxisRange[1] == VTK_DOUBLE_MAX ?
742                                  bounds[1] : this->XAxisRange[1]);
743  this->LastYRange[0] = (this->YAxisRange[0] == VTK_DOUBLE_MAX ?
744                                  bounds[2] : this->YAxisRange[0]);
745  this->LastYRange[1] = (this->YAxisRange[1] == VTK_DOUBLE_MAX ?
746                                  bounds[3] : this->YAxisRange[1]);
747  this->LastZRange[0] = (this->ZAxisRange[0] == VTK_DOUBLE_MAX ?
748                                  bounds[4] : this->ZAxisRange[0]);
749  this->LastZRange[1] = (this->ZAxisRange[1] == VTK_DOUBLE_MAX ?
750                                  bounds[5] : this->ZAxisRange[1]);
751
752  double major = 0.02 * (xExt + yExt + zExt) / 3.;
753  double minor = 0.5 * major;
754  for (i = 0; i < 4; i++)
755    {
756    this->XAxes[i]->SetMajorTickSize(major);
757    this->XAxes[i]->SetMinorTickSize(minor);
758
759    this->YAxes[i]->SetMajorTickSize(major);
760    this->YAxes[i]->SetMinorTickSize(minor);
761
762    this->ZAxes[i]->SetMajorTickSize(major);
763    this->ZAxes[i]->SetMinorTickSize(minor);
764
765    this->XAxes[i]->SetGridlineXLength(xExt);
766    this->XAxes[i]->SetGridlineYLength(yExt);
767    this->XAxes[i]->SetGridlineZLength(zExt);
768
769    this->YAxes[i]->SetGridlineXLength(xExt);
770    this->YAxes[i]->SetGridlineYLength(yExt);
771    this->YAxes[i]->SetGridlineZLength(zExt);
772
773    this->ZAxes[i]->SetGridlineXLength(xExt);
774    this->ZAxes[i]->SetGridlineYLength(yExt);
775    this->ZAxes[i]->SetGridlineZLength(zExt);
776    }
777  return true;
778}
779
780// ****************************************************************************
781//  Method: vtkRpCubeAxesActor::AdjustValues
782//
783//  Purpose:
784//      If the range of values is too big or too small, put them in scientific
785//      notation and changes the labels.
786//
787//  Arguments:
788//      bnds     The min/max values in each coordinate direction:
789//                 (min_x, max_x, min_y, max_y, min_z, max_x).
790//
791//  Note:       This code is partially stolen from old MeshTV code,
792//              /meshtvx/toolkit/plotgrid.c, axlab[x|y].
793//
794//  Programmer: Hank Childs
795//  Creation:   July 11, 2000
796//
797//  Modifications:
798//    Kathleen Bonnell, Wed Oct 31 07:57:49 PST 2001
799//    Regardless of individual ranges, if any coord direction has too
800//    small/large a range, all will have a scale factor set for scaling their
801//    label values, and their titles adjusted accordingly.
802//
803//    Kathleen Bonnell, Thu Sep  5 17:32:16 PDT 2002
804//    Only use dimensions with range > 0 for determining scale factor.
805//
806//    Hank Childs, Fri Sep 27 17:15:07 PDT 2002
807//    Account for units.
808//
809//    Kathleen Bonnell, Wed Aug  6 13:59:15 PDT 2003
810//    Each axis type now has its own 'mustAdjustValue' and 'lastPow'.
811//
812//    Kathleen Bonnell, Tue Dec 16 11:23:31 PST 2003
813//    Allow the LabelExponent to be user-settable (autLabelScaling is off).
814//    For title use '10e' instead of just 'e' to designate that exponent
815//    has been used.
816//
817//    Kathleen Bonnell, Tue Jul 20 11:41:45 PDT 2004
818//    For title use 'x10^' instead of '10e' to designate that exponent.
819//
820//    Brad Whitlock, Fri Jul 23 18:27:30 PST 2004
821//    Added support for using user-defined titles for axes.
822//
823// ****************************************************************************
824
825void vtkRpCubeAxesActor::AdjustValues(const double xRange[2],
826                                    const double yRange[2],
827                                    const double zRange[2])
828{
829  char xTitle[64];
830
831  int xPow, yPow, zPow;
832
833  if (AutoLabelScaling)
834    {
835    xPow = this->LabelExponent(xRange[0], xRange[1]);
836    yPow = this->LabelExponent(yRange[0], yRange[1]);
837    zPow = this->LabelExponent(zRange[0], zRange[1]);
838    }
839  else
840    {
841    xPow = UserXPow;
842    yPow = UserYPow;
843    zPow = UserZPow;
844    }
845
846  if (xPow != 0)
847    {
848    if (!this->MustAdjustXValue || this->LastXPow != xPow)
849      {
850      this->ForceXLabelReset = true;
851      }
852    else
853      {
854      this->ForceXLabelReset = false;
855      }
856    this->MustAdjustXValue = true;
857
858    if (XUnits == NULL || XUnits[0] == '\0')
859      {
860      sprintf(xTitle, "%s (x10^%d)", this->XTitle, xPow);
861      }
862    else
863      {
864      sprintf(xTitle, "%s (x10^%d %s)", this->XTitle, xPow, XUnits);
865      }
866    }
867  else
868    {
869    if (this->MustAdjustXValue)
870      {
871      this->Modified();
872      this->ForceXLabelReset = true;
873      }
874    else
875      {
876      this->ForceXLabelReset = false;
877      }
878    this->MustAdjustXValue = false;
879
880    if (XUnits == NULL || XUnits[0] == '\0')
881      {
882      sprintf(xTitle,"%s",this->XTitle);
883      }
884    else
885      {
886      sprintf(xTitle, "%s (%s)", this->XTitle, XUnits);
887      }
888    }
889
890  char yTitle[64];
891  if (yPow != 0)
892    {
893    if (!this->MustAdjustYValue || this->LastYPow != yPow)
894      {
895      this->ForceYLabelReset = true;
896      }
897    else
898      {
899      this->ForceYLabelReset = false;
900      }
901    this->MustAdjustYValue = true;
902    if (YUnits == NULL || YUnits[0] == '\0')
903      {
904      sprintf(yTitle, "%s (x10^%d)", this->YTitle, yPow);
905      }
906    else
907      {
908      sprintf(yTitle, "%s (x10^%d %s)", this->YTitle, yPow, YUnits);
909      }
910    }
911  else
912    {
913    if (this->MustAdjustYValue)
914      {
915      this->Modified();
916      this->ForceYLabelReset = true;
917      }
918    else
919      {
920      this->ForceYLabelReset = false;
921      }
922    this->MustAdjustYValue = false;
923    if (YUnits == NULL || YUnits[0] == '\0')
924      {
925      sprintf(yTitle,"%s",this->YTitle);
926      }
927    else
928      {
929      sprintf(yTitle, "%s (%s)", this->YTitle, YUnits);
930      }
931    }
932
933  char zTitle[64];
934  if (zPow != 0)
935    {
936    if (!this->MustAdjustZValue || this->LastZPow != zPow)
937      {
938      this->ForceZLabelReset = true;
939      }
940    else
941      {
942      this->ForceZLabelReset = false;
943      }
944    this->MustAdjustZValue = true;
945
946    if (ZUnits == NULL || ZUnits[0] == '\0')
947      {
948      sprintf(zTitle, "%s (x10^%d)", this->ZTitle, zPow);
949      }
950    else
951      {
952      sprintf(zTitle, "%s (x10^%d %s)", this->ZTitle, zPow, ZUnits);
953      }
954    }
955  else
956    {
957    if (this->MustAdjustZValue)
958      {
959      this->Modified();
960      this->ForceZLabelReset = true;
961      }
962    else
963      {
964      this->ForceZLabelReset = false;
965      }
966    this->MustAdjustZValue = false;
967
968    if (ZUnits == NULL || ZUnits[0] == '\0')
969      {
970      sprintf(zTitle,"%s",this->ZTitle);
971      }
972    else
973      {
974      sprintf(zTitle, "%s (%s)", this->ZTitle, ZUnits);
975      }
976    }
977
978  this->LastXPow = xPow;
979  this->LastYPow = yPow;
980  this->LastZPow = zPow;
981
982  this->SetActualXLabel(xTitle);
983  this->SetActualYLabel(yTitle);
984  this->SetActualZLabel(zTitle);
985}
986
987// ****************************************************************************
988//  Method: vtkRpCubeAxesActor::AdjustRange
989//
990//  Purpose:
991//    If the range is small, adjust the precision of the values displayed.
992//
993//  Arguments:
994//    bnds    The minimum and maximum values in each coordinate direction
995//            (min_x, max_x, min_y, max_y, min_z, max_z).
996//
997//  Programmer: Hank Childs
998//  Creation:   July 11, 2000
999//
1000//  Modifications:
1001//    Kathleen Bonnell, Wed Oct 31 07:57:49 PST 2001
1002//    Moved from VisWinAxes3D.
1003//
1004//    Kathleen Bonnell, Thu Aug  1 14:05:05 PDT 2002
1005//    Send lastPos as argument to Digits.
1006//
1007//    Kathleen Bonnell, Wed Aug  6 13:59:15 PDT 2003
1008//    Adjust the range values using LastXPow, LastYPow, LastZPow.
1009//
1010// ****************************************************************************
1011
1012void vtkRpCubeAxesActor::AdjustRange(const double bnds[6])
1013{
1014  double xrange[2], yrange[2], zrange[2];
1015
1016  xrange[0] = (this->XAxisRange[0] == VTK_DOUBLE_MAX ?
1017                                  bnds[0] : this->XAxisRange[0]);
1018  xrange[1] = (this->XAxisRange[1] == VTK_DOUBLE_MAX ?
1019                                  bnds[1] : this->XAxisRange[1]);
1020  yrange[0] = (this->YAxisRange[0] == VTK_DOUBLE_MAX ?
1021                                  bnds[2] : this->YAxisRange[0]);
1022  yrange[1] = (this->YAxisRange[1] == VTK_DOUBLE_MAX ?
1023                                  bnds[3] : this->YAxisRange[1]);
1024  zrange[0] = (this->ZAxisRange[0] == VTK_DOUBLE_MAX ?
1025                                  bnds[4] : this->ZAxisRange[0]);
1026  zrange[1] = (this->ZAxisRange[1] == VTK_DOUBLE_MAX ?
1027                                  bnds[5] : this->ZAxisRange[1]);
1028
1029  if (this->LastXPow != 0)
1030    {
1031    xrange[0] /= pow(10., this->LastXPow);
1032    xrange[1] /= pow(10., this->LastXPow);
1033    }
1034  if (this->LastYPow != 0)
1035    {
1036    yrange[0] /= pow(10., this->LastYPow);
1037    yrange[1] /= pow(10., this->LastYPow);
1038    }
1039  if (this->LastZPow != 0)
1040    {
1041    zrange[0] /= pow(10., this->LastZPow);
1042    zrange[1] /= pow(10., this->LastZPow);
1043    }
1044
1045  int xAxisDigits = this->Digits(xrange[0], xrange[1]);
1046  if (xAxisDigits != this->LastXAxisDigits)
1047    {
1048    char  format[16];
1049    sprintf(format, "%%.%df", xAxisDigits);
1050    this->SetXLabelFormat(format);
1051    this->LastXAxisDigits = xAxisDigits;
1052    }
1053
1054  int yAxisDigits = this->Digits(yrange[0], yrange[1]);
1055  if (yAxisDigits != this->LastYAxisDigits)
1056    {
1057    char  format[16];
1058    sprintf(format, "%%.%df", yAxisDigits);
1059    this->SetYLabelFormat(format);
1060    this->LastYAxisDigits = yAxisDigits;
1061    }
1062
1063  int zAxisDigits = this->Digits(zrange[0], zrange[1]);
1064  if (zAxisDigits != this->LastZAxisDigits)
1065    {
1066    char  format[16];
1067    sprintf(format, "%%.%df", zAxisDigits);
1068    this->SetZLabelFormat(format);
1069    this->LastZAxisDigits = zAxisDigits;
1070    }
1071}
1072
1073// ****************************************************************************
1074//  Method: Digits
1075//
1076//  Purpose:
1077//      Determines the appropriate number of digits for a given range.
1078//
1079//  Arguments:
1080//      min    The minimum value in the range.
1081//      max    The maximum value in the range.
1082//
1083//  Returns:   The appropriate number of digits.
1084//
1085//  Programmer: Hank Childs
1086//  Creation:   July 11, 2000
1087//
1088//  Modifications:
1089//
1090//    Hank Childs, Tue Sep 18 11:58:33 PDT 2001
1091//    Cast ipow10 to get rid of compiler warning.
1092//
1093//    Kathleen Bonnell, Wed Oct 31 07:57:49 PST 2001
1094//    Moved from VisWinAxes3D.
1095//
1096//    Kathleen Bonnell, Thu Aug  1 13:44:02 PDT 2002
1097//    Added lastPow argument, it specifies whether or not scientific notation
1098//    is being used on the labels.
1099//
1100//    Kathleen Bonnell, Wed Aug  6 13:59:15 PDT 2003
1101//    Removed lastPow argment, as the adjustment necessary is now taking
1102//    place in AdjustRange.
1103//
1104// ****************************************************************************
1105
1106int vtkRpCubeAxesActor::Digits(double min, double max )
1107{
1108  double  range = max - min;
1109  double  pow10   = log10(range);
1110  int    ipow10  = static_cast<int>(floor(pow10));
1111  int    digitsPastDecimal = -ipow10;
1112
1113  if (digitsPastDecimal < 0)
1114    {
1115    //
1116    // The range is more than 10, but not so big we need scientific
1117    // notation, we don't need to worry about decimals.
1118    //
1119    digitsPastDecimal = 0;
1120    }
1121  else
1122    {
1123    //
1124    // We want one more than the range since there is more than one
1125    // tick per decade.
1126    //
1127    digitsPastDecimal++;
1128
1129    //
1130    // Anything more than 5 is just noise.  (and probably 5 is noise with
1131    // doubleing point if the part before the decimal is big).
1132    //
1133    if (digitsPastDecimal > 5)
1134      {
1135      digitsPastDecimal = 5;
1136      }
1137    }
1138
1139  return digitsPastDecimal;
1140}
1141
1142// ****************************************************************************
1143//  Method: LabelExponent
1144//
1145//  Purpose:
1146//      Determines the proper exponent for the min and max values.
1147//
1148//  Arguments:
1149//      min     The minimum value along a certain axis.
1150//      max     The maximum value along a certain axis.
1151//
1152//  Note:       This code is mostly stolen from old MeshTV code,
1153//              /meshtvx/toolkit/plotgrid.c, axlab_format.
1154//
1155//  Programmer: Hank Childs
1156//  Creation:   July 11, 2000
1157//
1158//  Modifications:
1159//    Eric Brugger, Tue Sep 18 09:18:17 PDT 2001
1160//    Change a few static local variables to be non-static to get around a
1161//    compiler bug with the MIPSpro 7.2.1.3 compiler.
1162//
1163//    Hank Childs, Tue Sep 18 11:58:33 PDT 2001
1164//    Cast return value to get rid of compiler warning.
1165//
1166//    Kathleen Bonnell, Wed Oct 31 07:57:49 PST 2001
1167//    Moved from VisWinAxes3D.
1168//
1169//    Kathleen Bonnell, Wed Aug  6 13:59:15 PDT 2003
1170//    Added test for min==max.
1171//
1172// ****************************************************************************
1173
1174int vtkRpCubeAxesActor::LabelExponent(double min, double max)
1175{
1176  if (min == max)
1177    {
1178    return 0;
1179    }
1180
1181  //
1182  // Determine power of 10 to scale axis labels to.
1183  //
1184  double range = (fabs(min) > fabs(max) ? fabs(min) : fabs(max));
1185  double pow10 = log10(range);
1186
1187  //
1188  // Cutoffs for using scientific notation.  The following 4 variables
1189  // should all be static for maximum performance but were made non-static
1190  // to get around a compiler bug with the MIPSpro 7.2.1.3 compiler.
1191  //
1192  double eformat_cut_min = -1.5;
1193  double eformat_cut_max =  3.0;
1194  double cut_min = pow(10., eformat_cut_min);
1195  double cut_max = pow(10., eformat_cut_max);
1196  double ipow10;
1197  if (range < cut_min || range > cut_max)
1198    {
1199    //
1200    // We are going to use scientific notation and round the exponents to
1201    // the nearest multiple of three.
1202    //
1203    ipow10 = (floor(floor(pow10)/3.))*3;
1204    }
1205  else
1206    {
1207    ipow10 = 0;
1208    }
1209
1210  return static_cast<int>(ipow10);
1211}
1212
1213// *************************************************************************
1214//  Build the axes. Determine coordinates, position, etc.
1215//
1216//  Note:  Bulk of code moved here from RenderOpaqueGeomtry.
1217//         Early-termination test added.
1218//
1219//  Programmer:  Kathleen Bonnell
1220//  Creation:    November 7, 2001
1221//
1222//  Modifications:
1223//    Kathleen Bonnell, Mon Dec  3 16:49:01 PST 2001
1224//    Compare vtkTimeStamps correctly.
1225//
1226//    Kathleen Bonnell, Fri Jul 25 14:37:32 PDT 2003
1227//    Added logic to compute and set for each axis the labels and title
1228//    scale size.
1229//
1230//    Kathleen Bonnell, Wed Aug  6 13:59:15 PDT 2003
1231//    Indivdual axes now have their own ForceLabelReset.
1232//
1233// *************************************************************************
1234
1235void vtkRpCubeAxesActor::BuildAxes(vtkViewport *viewport)
1236{
1237  double bounds[6];
1238  double pts[8][3];
1239  int i;
1240
1241  if ((this->GetMTime() < this->BuildTime.GetMTime()))
1242    {
1243    return;
1244    }
1245
1246  this->SetNonDependentAttributes();
1247  // determine the bounds to use (input, prop, or user-defined)
1248  this->GetBounds(bounds);
1249
1250  // Build the axes (almost always needed so we don't check mtime)
1251  // Transform all points into display coordinates (to determine which closest
1252  // to camera).
1253  this->TransformBounds(viewport, bounds, pts);
1254
1255  // Setup the axes for plotting
1256  double xCoords[4][6], yCoords[4][6], zCoords[4][6];
1257
1258  // these arrays are accessed by 'location':  mm, mX, XX, or Xm.
1259  int mm1[4] = { 0, 0, 1, 1 };
1260  int mm2[4] = { 0, 1, 1, 0 };
1261
1262  for (i = 0; i < 4; i++)
1263    {
1264    this->XAxes[i]->SetAxisPosition(i);
1265    xCoords[i][0] = bounds[0];
1266    xCoords[i][3] = bounds[1];
1267    xCoords[i][1] = xCoords[i][4] = bounds[2+mm1[i]];
1268    xCoords[i][2] = xCoords[i][5] = bounds[4+mm2[i]];
1269
1270    this->YAxes[i]->SetAxisPosition(i);
1271    yCoords[i][0] = yCoords[i][3] = bounds[0+mm1[i]];
1272    yCoords[i][1] = bounds[2];
1273    yCoords[i][4] = bounds[3];
1274    yCoords[i][2] = yCoords[i][5] = bounds[4+mm2[i]];
1275
1276    this->ZAxes[i]->SetAxisPosition(i);
1277    zCoords[i][0] = zCoords[i][3] = bounds[0+mm1[i]];
1278    zCoords[i][1] = zCoords[i][4] = bounds[2+mm2[i]];
1279    zCoords[i][2] = bounds[4];
1280    zCoords[i][5] = bounds[5];
1281    }
1282
1283  double xRange[2], yRange[2], zRange[2];
1284
1285  // this method sets the Coords, and offsets if necessary.
1286  this->AdjustAxes(bounds, xCoords, yCoords, zCoords, xRange, yRange, zRange);
1287
1288  // adjust for sci. notation if necessary
1289  // May set a flag for each axis specifying that label values should
1290  // be scaled, may change title of each axis, may change label format.
1291  this->AdjustValues(xRange, yRange, zRange);
1292  this->AdjustRange(this->Bounds);
1293
1294  // Prepare axes for rendering with user-definable options
1295  for (i = 0; i < 4; i++)
1296    {
1297    this->XAxes[i]->GetPoint1Coordinate()->SetValue(xCoords[i][0],
1298                                                    xCoords[i][1],
1299                                                    xCoords[i][2]);
1300    this->XAxes[i]->GetPoint2Coordinate()->SetValue(xCoords[i][3],
1301                                                    xCoords[i][4],
1302                                                    xCoords[i][5]);
1303    this->YAxes[i]->GetPoint1Coordinate()->SetValue(yCoords[i][0],
1304                                                    yCoords[i][1],
1305                                                    yCoords[i][2]);
1306    this->YAxes[i]->GetPoint2Coordinate()->SetValue(yCoords[i][3],
1307                                                    yCoords[i][4],
1308                                                    yCoords[i][5]);
1309    this->ZAxes[i]->GetPoint1Coordinate()->SetValue(zCoords[i][0],
1310                                                    zCoords[i][1],
1311                                                    zCoords[i][2]);
1312    this->ZAxes[i]->GetPoint2Coordinate()->SetValue(zCoords[i][3],
1313                                                    zCoords[i][4],
1314                                                    zCoords[i][5]);
1315
1316    this->XAxes[i]->SetRange(xRange[0], xRange[1]);
1317    this->YAxes[i]->SetRange(yRange[0], yRange[1]);
1318    this->ZAxes[i]->SetRange(zRange[0], zRange[1]);
1319
1320    this->XAxes[i]->SetTitle(this->ActualXLabel);
1321    this->YAxes[i]->SetTitle(this->ActualYLabel);
1322    this->ZAxes[i]->SetTitle(this->ActualZLabel);
1323    }
1324
1325  bool ticksRecomputed = this->ComputeTickSize(bounds);
1326
1327  //
1328  // Labels are built during ComputeTickSize. if
1329  // ticks were not recomputed, but we need a label
1330  // reset, then build the labels here.
1331  //
1332  if (!ticksRecomputed)
1333    {
1334    if (this->ForceXLabelReset)
1335      {
1336      this->BuildLabels(this->XAxes);
1337      }
1338    if (this->ForceYLabelReset)
1339      {
1340      this->BuildLabels(this->YAxes);
1341      }
1342    if (this->ForceZLabelReset)
1343      {
1344      this->BuildLabels(this->ZAxes);
1345      }
1346    }
1347
1348  if (ticksRecomputed || this->ForceXLabelReset || this->ForceYLabelReset ||
1349      this->ForceZLabelReset)
1350    {
1351    // labels were re-built, need to recompute the scale.
1352    double center[3];
1353
1354    center[0] = (this->Bounds[1] - this->Bounds[0]) * 0.5;
1355    center[1] = (this->Bounds[3] - this->Bounds[2]) * 0.5;
1356    center[2] = (this->Bounds[5] - this->Bounds[4]) * 0.5;
1357
1358    double lenX = this->XAxes[0]->ComputeMaxLabelLength(center);
1359    double lenY = this->YAxes[0]->ComputeMaxLabelLength(center);
1360    double lenZ = this->ZAxes[0]->ComputeMaxLabelLength(center);
1361    double lenTitleX = this->XAxes[0]->ComputeTitleLength(center);
1362    double lenTitleY = this->YAxes[0]->ComputeTitleLength(center);
1363    double lenTitleZ = this->ZAxes[0]->ComputeTitleLength(center);
1364    double maxLabelLength = this->MaxOf(lenX, lenY, lenZ, 0.);
1365    double maxTitleLength = this->MaxOf(lenTitleX, lenTitleY, lenTitleZ, 0.);
1366    double bWidth  = this->Bounds[1] - this->Bounds[0];
1367    double bHeight = this->Bounds[3] - this->Bounds[2];
1368
1369    double bLength = sqrt(bWidth*bWidth + bHeight*bHeight);
1370
1371    double target = bLength *0.04;
1372    double labelscale = 1.;
1373    if (maxLabelLength != 0.)
1374      {
1375      labelscale = target / maxLabelLength;
1376      }
1377    target = bLength *0.10;
1378    double titlescale = 1.;
1379    if (maxTitleLength != 0.)
1380      {
1381      titlescale = target / maxTitleLength;
1382      }
1383
1384    //
1385    // Allow a bit bigger title if we have units, otherwise
1386    // the title may be too small to read.
1387    //
1388    if (XUnits != NULL && XUnits[0] != '\0')
1389      {
1390      titlescale *= 2;
1391      }
1392
1393    for (i = 0; i < 4; i++)
1394      {
1395      this->XAxes[i]->SetLabelScale(labelscale);
1396      this->YAxes[i]->SetLabelScale(labelscale);
1397      this->ZAxes[i]->SetLabelScale(labelscale);
1398      this->XAxes[i]->SetTitleScale(titlescale);
1399      this->YAxes[i]->SetTitleScale(titlescale);
1400      this->ZAxes[i]->SetTitleScale(titlescale);
1401      }
1402    }
1403  this->RenderSomething = 1;
1404  this->BuildTime.Modified();
1405  this->LastFlyMode = this->FlyMode;
1406}
1407
1408// *************************************************************************
1409//  Sends attributes to each vtkRpAxisActor.  Only sets those that are
1410//  not dependent upon viewport changes, and thus do not need to be set
1411//  very often.
1412//
1413//  Programmer:  Kathleen Bonnell
1414//  Creation:    November 7, 2001
1415//
1416//  Modifications:
1417//    Kathleen Bonnell, Thu Oct  3 14:33:15 PDT 2002
1418//    Disable lighting for the axes by setting the ambient coefficient to 1
1419//    and the diffuse coeeficient to 0.
1420// *************************************************************************
1421
1422void vtkRpCubeAxesActor::SetNonDependentAttributes()
1423{
1424  vtkProperty *prop = this->GetProperty();
1425  prop->SetAmbient(1.0);
1426  prop->SetDiffuse(0.0);
1427  for (int i = 0; i < 4; i++)
1428    {
1429    this->XAxes[i]->SetCamera(this->Camera);
1430    this->XAxes[i]->SetProperty(prop);
1431    this->XAxes[i]->SetTickLocation(this->TickLocation);
1432    this->XAxes[i]->SetDrawGridlines(this->DrawXGridlines);
1433    this->XAxes[i]->SetBounds(this->Bounds);
1434    this->XAxes[i]->AxisVisibilityOn();
1435    this->XAxes[i]->SetLabelVisibility(this->XAxisLabelVisibility);
1436    this->XAxes[i]->SetTitleVisibility(this->XAxisLabelVisibility);
1437    this->XAxes[i]->SetTickVisibility(this->XAxisTickVisibility);
1438    this->XAxes[i]->SetMinorTicksVisible(this->XAxisMinorTickVisibility);
1439
1440    this->YAxes[i]->SetCamera(this->Camera);
1441    this->YAxes[i]->SetProperty(prop);
1442    this->YAxes[i]->SetTickLocation(this->TickLocation);
1443    this->YAxes[i]->SetDrawGridlines(this->DrawYGridlines);
1444    this->YAxes[i]->SetBounds(this->Bounds);
1445    this->YAxes[i]->AxisVisibilityOn();
1446    this->YAxes[i]->SetLabelVisibility(this->YAxisLabelVisibility);
1447    this->YAxes[i]->SetTitleVisibility(this->YAxisLabelVisibility);
1448    this->YAxes[i]->SetTickVisibility(this->YAxisTickVisibility);
1449    this->YAxes[i]->SetMinorTicksVisible(this->YAxisMinorTickVisibility);
1450
1451    this->ZAxes[i]->SetCamera(this->Camera);
1452    this->ZAxes[i]->SetProperty(prop);
1453    this->ZAxes[i]->SetTickLocation(this->TickLocation);
1454    this->ZAxes[i]->SetDrawGridlines(this->DrawZGridlines);
1455    this->ZAxes[i]->SetBounds(this->Bounds);
1456    this->ZAxes[i]->AxisVisibilityOn();
1457    this->ZAxes[i]->SetLabelVisibility(this->ZAxisLabelVisibility);
1458    this->ZAxes[i]->SetTitleVisibility(this->ZAxisLabelVisibility);
1459    this->ZAxes[i]->SetTickVisibility(this->ZAxisTickVisibility);
1460    this->ZAxes[i]->SetMinorTicksVisible(this->ZAxisMinorTickVisibility);
1461    }
1462}
1463
1464// Static variable describes locations in cube, relative to the type
1465// of axis:  mm for an X-axis means the x-edge at min-y and min-z.
1466// mX for a Y-axis means the y-edge at min-x and max-z, and so on.
1467
1468enum {mm = 0, mX, XX, Xm };
1469//
1470// For CLOSEST_TRIAD, and FURTHEST_TRIAD, this variable determines
1471// which locations in the cube each 'Major' axis should take.
1472//
1473static int vtkRpCubeAxesActorTriads[8][3] = {
1474  {mm,mm,mm}, {mm,Xm,Xm}, {Xm,mm,mX}, {Xm,Xm,XX},
1475  {mX,mX,mm}, {mX,XX,Xm}, {XX,mX,mX}, {XX,XX,XX}};
1476static int vtkRpCubeAxesActorConn[8][3] = {{1,2,4}, {0,3,5}, {3,0,6}, {2,1,7},
1477                                         {5,6,0}, {4,7,1}, {7,4,2}, {6,5,3}};
1478
1479// *************************************************************************
1480// Determine which of the axes in each coordinate direction actually should
1481// be rendered.  For STATIC FlyMode, all axes are rendered.  For other
1482// FlyModes, either 1 or 2 per coordinate direction are rendered.
1483//
1484// Programmer:  Kathleen Bonnell
1485// Creation:    November 7, 2001
1486//
1487// Modifications:
1488//   Kathleen Bonnell, Thu Jul 18 10:33:07 PDT 2002
1489//   Ensure that primary axes visibility flags are set properly, and
1490//   that secondary axes visibility flags are turned off.
1491// *************************************************************************
1492void vtkRpCubeAxesActor::DetermineRenderAxes(vtkViewport *viewport)
1493{
1494  double bounds[6], slope = 0.0, minSlope, num, den;
1495  double pts[8][3], d2, d2Min, min, max;
1496  int i = 0, idx = 0;
1497  int xIdx = 0, yIdx = 0, zIdx = 0, zIdx2 = 0;
1498  int xAxes = 0, yAxes = 0, zAxes = 0, xloc = 0, yloc = 0, zloc = 0;
1499
1500  if (this->FlyMode == VTK_FLY_STATIC_EDGES)
1501    {
1502    for (i = 0; i < 4; i++)
1503      {
1504      this->RenderAxesX[i] = i;
1505      this->RenderAxesY[i] = i;
1506      this->RenderAxesZ[i] = i;
1507      }
1508    this->NumberOfAxesX = this->NumberOfAxesY = this->NumberOfAxesZ = 4;
1509    return;
1510    }
1511  if (this->FlyMode == VTK_FLY_STATIC_TRIAD)
1512    {
1513    this->RenderAxesX[0] = 0;
1514    this->RenderAxesY[0] = 0;
1515    this->RenderAxesZ[0] = 0;
1516    if (this->DrawXGridlines && 0)
1517      {
1518      this->RenderAxesX[1] = 2;
1519      this->NumberOfAxesX = 2;
1520      this->XAxes[RenderAxesX[1]]->SetTickVisibility(0);
1521      this->XAxes[RenderAxesX[1]]->SetLabelVisibility(0);
1522      this->XAxes[RenderAxesX[1]]->SetTitleVisibility(0);
1523      this->XAxes[RenderAxesX[1]]->SetMinorTicksVisible(0);
1524      }
1525    else
1526      {
1527      this->NumberOfAxesX = 1;
1528      }
1529    if (this->DrawYGridlines && 0)
1530      {
1531      this->RenderAxesY[1] = 2;
1532      this->NumberOfAxesY = 2;
1533      this->YAxes[RenderAxesY[1]]->SetTickVisibility(0);
1534      this->YAxes[RenderAxesY[1]]->SetLabelVisibility(0);
1535      this->YAxes[RenderAxesY[1]]->SetTitleVisibility(0);
1536      this->YAxes[RenderAxesY[1]]->SetMinorTicksVisible(0);
1537      }
1538    else
1539      {
1540      this->NumberOfAxesY = 1;
1541      }
1542    if (this->DrawZGridlines && 0)
1543      {
1544      this->RenderAxesZ[1] = 2;
1545      this->NumberOfAxesZ = 2;
1546      this->ZAxes[RenderAxesZ[1]]->SetTickVisibility(0);
1547      this->ZAxes[RenderAxesZ[1]]->SetLabelVisibility(0);
1548      this->ZAxes[RenderAxesZ[1]]->SetTitleVisibility(0);
1549      this->ZAxes[RenderAxesZ[1]]->SetMinorTicksVisible(0);
1550      }
1551    else
1552      {
1553      this->NumberOfAxesZ = 1;
1554      }
1555    return;
1556    }
1557
1558  // determine the bounds to use (input, prop, or user-defined)
1559  this->GetBounds(bounds);
1560  this->TransformBounds(viewport, bounds, pts);
1561
1562  // Take into account the inertia. Process only so often.
1563  if (this->RenderCount++ == 0 || !(this->RenderCount % this->Inertia))
1564    {
1565    if (this->FlyMode == VTK_FLY_CLOSEST_TRIAD)
1566      {
1567      // Loop over points and find the closest point to the camera
1568      min = VTK_LARGE_FLOAT;
1569      for (i=0; i < 8; i++)
1570        {
1571        if (pts[i][2] < min)
1572          {
1573          idx = i;
1574          min = pts[i][2];
1575          }
1576        }
1577      xloc = vtkRpCubeAxesActorTriads[idx][0];
1578      yloc = vtkRpCubeAxesActorTriads[idx][1];
1579      zloc = vtkRpCubeAxesActorTriads[idx][2];
1580
1581      } // closest-triad
1582    else if (this->FlyMode == VTK_FLY_FURTHEST_TRIAD)
1583      {
1584      // Loop over points and find the furthest point from the camera
1585      max = -VTK_LARGE_FLOAT;
1586      for (i=0; i < 8; i++)
1587        {
1588        if (pts[i][2] > max)
1589          {
1590          idx = i;
1591          max = pts[i][2];
1592          }
1593        }
1594      xloc = vtkRpCubeAxesActorTriads[idx][0];
1595      yloc = vtkRpCubeAxesActorTriads[idx][1];
1596      zloc = vtkRpCubeAxesActorTriads[idx][2];
1597
1598      } // furthest-triad
1599    else
1600      {
1601      double e1[3], e2[3], e3[3];
1602
1603      // Find distance to origin
1604      d2Min = VTK_LARGE_FLOAT;
1605      for (i=0; i < 8; i++)
1606        {
1607        d2 = pts[i][0]*pts[i][0] + pts[i][1]*pts[i][1];
1608        if (d2 < d2Min)
1609          {
1610          d2Min = d2;
1611          idx = i;
1612          }
1613        }
1614
1615      // find minimum slope point connected to closest point and on
1616      // right side (in projected coordinates). This is the first edge.
1617      minSlope = VTK_LARGE_FLOAT;
1618      for (xIdx=0, i=0; i<3; i++)
1619        {
1620        num = (pts[vtkRpCubeAxesActorConn[idx][i]][1] - pts[idx][1]);
1621        den = (pts[vtkRpCubeAxesActorConn[idx][i]][0] - pts[idx][0]);
1622        if (den != 0.0)
1623          {
1624          slope = num / den;
1625          }
1626        if (slope < minSlope && den > 0)
1627          {
1628          xIdx = vtkRpCubeAxesActorConn[idx][i];
1629          yIdx = vtkRpCubeAxesActorConn[idx][(i+1)%3];
1630          zIdx = vtkRpCubeAxesActorConn[idx][(i+2)%3];
1631          xAxes = i;
1632          minSlope = slope;
1633          }
1634        }
1635
1636      // find edge (connected to closest point) on opposite side
1637      for ( i=0; i<3; i++)
1638        {
1639        e1[i] = (pts[xIdx][i] - pts[idx][i]);
1640        e2[i] = (pts[yIdx][i] - pts[idx][i]);
1641        e3[i] = (pts[zIdx][i] - pts[idx][i]);
1642        }
1643      vtkMath::Normalize(e1);
1644      vtkMath::Normalize(e2);
1645      vtkMath::Normalize(e3);
1646
1647      if (vtkMath::Dot(e1,e2) < vtkMath::Dot(e1,e3))
1648        {
1649        yAxes = (xAxes + 1) % 3;
1650        }
1651      else
1652        {
1653        yIdx = zIdx;
1654        yAxes = (xAxes + 2) % 3;
1655        }
1656
1657      // Find the final point by determining which global x-y-z axes have not
1658      // been represented, and then determine the point closest to the viewer.
1659      zAxes = (xAxes != 0 && yAxes != 0 ? 0 :
1660              (xAxes != 1 && yAxes != 1 ? 1 : 2));
1661      if (pts[vtkRpCubeAxesActorConn[xIdx][zAxes]][2] <
1662          pts[vtkRpCubeAxesActorConn[yIdx][zAxes]][2])
1663        {
1664        zIdx = xIdx;
1665        zIdx2 = vtkRpCubeAxesActorConn[xIdx][zAxes];
1666        }
1667      else
1668        {
1669        zIdx = yIdx;
1670        zIdx2 = vtkRpCubeAxesActorConn[yIdx][zAxes];
1671        }
1672
1673      int mini = (idx < xIdx ? idx : xIdx);
1674      switch (xAxes)
1675        {
1676        case 0:
1677          xloc = vtkRpCubeAxesActorTriads[mini][0];
1678          break;
1679        case 1:
1680          yloc = vtkRpCubeAxesActorTriads[mini][1];
1681          break;
1682        case 2:
1683          zloc = vtkRpCubeAxesActorTriads[mini][2];
1684          break;
1685        }
1686      mini = (idx < yIdx ? idx : yIdx);
1687      switch (yAxes)
1688        {
1689        case 0:
1690          xloc = vtkRpCubeAxesActorTriads[mini][0];
1691          break;
1692        case 1:
1693          yloc =vtkRpCubeAxesActorTriads[mini][1];
1694          break;
1695        case 2:
1696          zloc = vtkRpCubeAxesActorTriads[mini][2];
1697          break;
1698        }
1699      mini = (zIdx < zIdx2 ? zIdx : zIdx2);
1700      switch (zAxes)
1701        {
1702        case 0:
1703          xloc = vtkRpCubeAxesActorTriads[mini][0];
1704          break;
1705        case 1:
1706          yloc = vtkRpCubeAxesActorTriads[mini][1];
1707          break;
1708        case 2:
1709          zloc = vtkRpCubeAxesActorTriads[mini][2];
1710          break;
1711        }
1712
1713      }//else boundary edges fly mode
1714
1715    this->InertiaLocs[0] = xloc;
1716    this->InertiaLocs[1] = yloc;
1717    this->InertiaLocs[2] = zloc;
1718    } //inertia
1719  else
1720    {
1721    // don't change anything, use locations from last render
1722    xloc = this->InertiaLocs[0];
1723    yloc = this->InertiaLocs[1];
1724    zloc = this->InertiaLocs[2];
1725    }
1726
1727  this->RenderAxesX[0] = xloc % 4;
1728  if (this->DrawXGridlines && 0)
1729    {
1730    this->RenderAxesX[1] = (xloc + 2) % 4;
1731    this->NumberOfAxesX = 2;
1732    this->XAxes[RenderAxesX[1]]->SetTickVisibility(0);
1733    this->XAxes[RenderAxesX[1]]->SetLabelVisibility(0);
1734    this->XAxes[RenderAxesX[1]]->SetTitleVisibility(0);
1735    this->XAxes[RenderAxesX[1]]->SetMinorTicksVisible(0);
1736    }
1737  else
1738    {
1739    this->NumberOfAxesX = 1;
1740    }
1741
1742  this->RenderAxesY[0] = yloc % 4;
1743  if (this->DrawYGridlines && 0)
1744    {
1745    this->RenderAxesY[1] = (yloc + 2) % 4;
1746    this->NumberOfAxesY = 2;
1747    this->YAxes[RenderAxesY[1]]->SetTickVisibility(0);
1748    this->YAxes[RenderAxesY[1]]->SetLabelVisibility(0);
1749    this->YAxes[RenderAxesY[1]]->SetTitleVisibility(0);
1750    this->YAxes[RenderAxesY[1]]->SetMinorTicksVisible(0);
1751    }
1752  else
1753    {
1754    this->NumberOfAxesY = 1;
1755    }
1756
1757  this->RenderAxesZ[0] = zloc % 4;
1758  if (this->DrawZGridlines && 0)
1759    {
1760    this->RenderAxesZ[1] = (zloc + 2) % 4;
1761    this->NumberOfAxesZ = 2;
1762    this->ZAxes[RenderAxesZ[1]]->SetTickVisibility(0);
1763    this->ZAxes[RenderAxesZ[1]]->SetLabelVisibility(0);
1764    this->ZAxes[RenderAxesZ[1]]->SetTitleVisibility(0);
1765    this->ZAxes[RenderAxesZ[1]]->SetMinorTicksVisible(0);
1766    }
1767  else
1768    {
1769    this->NumberOfAxesZ = 1;
1770    }
1771  //
1772  //  Make sure that the primary axis visibility flags are set correctly.
1773  //
1774  this->XAxes[RenderAxesX[0]]->SetLabelVisibility(this->XAxisLabelVisibility);
1775  this->XAxes[RenderAxesX[0]]->SetTitleVisibility(this->XAxisLabelVisibility);
1776  this->XAxes[RenderAxesX[0]]->SetTickVisibility(this->XAxisTickVisibility);
1777  this->XAxes[RenderAxesX[0]]->SetMinorTicksVisible(
1778    this->XAxisMinorTickVisibility);
1779  this->XAxes[RenderAxesX[0]]->SetDrawGridlines(this->DrawXGridlines);
1780
1781  this->YAxes[RenderAxesY[0]]->SetLabelVisibility(this->YAxisLabelVisibility);
1782  this->YAxes[RenderAxesY[0]]->SetTitleVisibility(this->YAxisLabelVisibility);
1783  this->YAxes[RenderAxesY[0]]->SetTickVisibility(this->YAxisTickVisibility);
1784  this->YAxes[RenderAxesY[0]]->SetMinorTicksVisible(
1785    this->YAxisMinorTickVisibility);
1786  this->YAxes[RenderAxesY[0]]->SetDrawGridlines(this->DrawYGridlines);
1787
1788  this->ZAxes[RenderAxesZ[0]]->SetLabelVisibility(this->ZAxisLabelVisibility);
1789  this->ZAxes[RenderAxesZ[0]]->SetTitleVisibility(this->ZAxisLabelVisibility);
1790  this->ZAxes[RenderAxesZ[0]]->SetTickVisibility(this->ZAxisTickVisibility);
1791  this->ZAxes[RenderAxesZ[0]]->SetMinorTicksVisible(
1792    this->ZAxisMinorTickVisibility);
1793  this->ZAxes[RenderAxesZ[0]]->SetDrawGridlines(this->DrawZGridlines);
1794}
1795
1796double vtkRpCubeAxesActor::MaxOf(double a, double b)
1797{
1798  return (a > b ? a : b);
1799}
1800
1801double vtkRpCubeAxesActor::MaxOf(double a, double b, double c, double d)
1802{
1803  return this->MaxOf(this->MaxOf(a, b), this->MaxOf(c, d));
1804}
1805
1806inline double vtkRpCubeAxesActor::FFix(double value)
1807{
1808  int ivalue = static_cast<int>(value);
1809  return ivalue;
1810}
1811
1812inline double vtkRpCubeAxesActor::FSign(double value, double sign)
1813{
1814  value = fabs(value);
1815  if (sign < 0.)
1816    {
1817    value *= -1.;
1818    }
1819  return value;
1820}
1821
1822// *******************************************************************
1823// Method: vtkRpCubeAxesActor::AdjustTicksComputeRange
1824//
1825// Purpose: Sets private members controlling the number and position
1826//          of ticks.
1827//
1828// Arguments:
1829//   inRange   The range for this axis.
1830//
1831// Note:    The bulk of this method was taken from vtkHankAxisActor.C
1832//          The original method was reduced to serve the purposes
1833//          of this class.
1834//
1835// Programmer: Kathleen Bonnell
1836// Creation:   29 August, 2001
1837//
1838// Modifications:
1839//   Kathleen Bonnell, Fri Jul 25 14:37:32 PDT 2003
1840//   Moved from vtkRpAxisActor. Added calls to set inividual axis'
1841//   MajorStart, MinorStart, deltaMajor, deltaMinor.
1842//
1843// *******************************************************************
1844
1845void vtkRpCubeAxesActor::AdjustTicksComputeRange(vtkRpAxisActor *axes[4],
1846    double boundsMin, double boundsMax)
1847{
1848  double sortedRange[2], range;
1849  double fxt, fnt, frac;
1850  double div, major, minor;
1851  double majorStart, minorStart;
1852  int numTicks;
1853  double *inRange = axes[0]->GetRange();
1854
1855  sortedRange[0] = inRange[0] < inRange[1] ? inRange[0] : inRange[1];
1856  sortedRange[1] = inRange[0] > inRange[1] ? inRange[0] : inRange[1];
1857
1858  range = sortedRange[1] - sortedRange[0];
1859
1860  // Find the integral points.
1861  double pow10 = log10(range);
1862
1863  // Build in numerical tolerance
1864  if (pow10 != 0.)
1865    {
1866    double eps = 10.0e-10;
1867    pow10 = this->FSign((fabs(pow10) + eps), pow10);
1868    }
1869
1870  // FFix move you in the wrong direction if pow10 is negative.
1871  if (pow10 < 0.)
1872    {
1873    pow10 = pow10 - 1.;
1874    }
1875
1876  fxt = pow(10., this->FFix(pow10));
1877
1878  // Find the number of integral points in the interval.
1879  fnt  = range/fxt;
1880  fnt  = this->FFix(fnt);
1881  frac = fnt;
1882  numTicks = frac <= 0.5 ? static_cast<int>(this->FFix(fnt)) : static_cast<int>(this->FFix(fnt) + 1);
1883
1884  div = 1.;
1885  if (numTicks < 5)
1886    {
1887    div = 2.;
1888    }
1889  if (numTicks <= 2)
1890    {
1891    div = 5.;
1892    }
1893
1894  // If there aren't enough major tick points in this decade, use the next
1895  // decade.
1896  major = fxt;
1897  if (div != 1.)
1898    {
1899    major /= div;
1900    }
1901  minor = (fxt/div) / 10.;
1902
1903  // Figure out the first major and minor tick locations, relative to the
1904  // start of the axis.
1905  if (sortedRange[0] <= 0.)
1906    {
1907    majorStart = major*(this->FFix(sortedRange[0]*(1./major)) + 0.);
1908    minorStart = minor*(this->FFix(sortedRange[0]*(1./minor)) + 0.);
1909    }
1910  else
1911    {
1912    majorStart = major*(this->FFix(sortedRange[0]*(1./major)) + 1.);
1913    minorStart = minor*(this->FFix(sortedRange[0]*(1./minor)) + 1.);
1914    }
1915
1916  for (int i = 0; i < 4; i++)
1917    {
1918    axes[i]->SetMinorRangeStart(minorStart);
1919    axes[i]->SetMajorRangeStart(majorStart);
1920    axes[i]->SetDeltaRangeMinor(minor);
1921    axes[i]->SetDeltaRangeMajor(major);
1922    }
1923
1924  double t;
1925  t = (minorStart - sortedRange[0])/range;
1926  minorStart = t * boundsMax + (1-t) * boundsMin;
1927  t = (majorStart - sortedRange[0])/range;
1928  majorStart = t * boundsMax + (1-t) * boundsMin;
1929  const double scale = (boundsMax - boundsMin) / range;
1930  minor *= scale;
1931  major *= scale;
1932
1933  for (int i = 0; i < 4; i++)
1934    {
1935    axes[i]->SetMinorStart(minorStart);
1936    axes[i]->SetMajorStart(majorStart);
1937
1938    axes[i]->SetDeltaMinor(minor);
1939    axes[i]->SetDeltaMajor(major);
1940    }
1941}
1942
1943// ****************************************************************
1944//  Determine what the labels should be and set them in each axis.
1945//
1946//  Modification:
1947//    Kathleen Bonnell, Wed Aug  6 13:59:15 PDT 2003
1948//    Each axis type now has it's own 'mustAdjustValue' and 'pow'.
1949//
1950//    Kathleen Bonnell, Tue Jul 20 14:29:10 PDT 2004
1951//    Ensure that '-0.0' is never used as a label.
1952//
1953//    Eric Brugger, Mon Jul 26 16:09:26 PDT 2004
1954//    Correct a bug with a misplaced closing parenthesis.
1955//
1956// ****************************************************************
1957
1958void vtkRpCubeAxesActor::BuildLabels(vtkRpAxisActor *axes[4])
1959{
1960  char label[64];
1961  int i, labelCount = 0;
1962  double deltaMajor = axes[0]->GetDeltaMajor();
1963  const double *p2  = axes[0]->GetPoint2Coordinate()->GetValue();
1964  double *range     = axes[0]->GetRange();
1965  double lastVal = 0, val = axes[0]->GetMajorStart();
1966  double extents = range[1] - range[0];
1967  bool mustAdjustValue = 0;
1968  int lastPow = 0;
1969
1970  vtkStringArray *labels = vtkStringArray::New();
1971  const char *format = "%s";
1972  switch (axes[0]->GetAxisType())
1973    {
1974    case VTK_AXIS_TYPE_X:
1975      lastVal = p2[0];
1976      format = this->XLabelFormat;
1977      mustAdjustValue = this->MustAdjustXValue;
1978      lastPow = this->LastXPow;
1979      break;
1980    case VTK_AXIS_TYPE_Y:
1981      lastVal = p2[1];
1982      format = this->YLabelFormat;
1983      mustAdjustValue = this->MustAdjustYValue;
1984      lastPow = this->LastYPow;
1985      break;
1986    case VTK_AXIS_TYPE_Z:
1987      lastVal = p2[2];
1988      format = this->ZLabelFormat;
1989      mustAdjustValue = this->MustAdjustZValue;
1990      lastPow = this->LastZPow;
1991      break;
1992    }
1993
1994  // figure out how many labels we need:
1995  while (val <= lastVal && labelCount < VTK_MAX_LABELS)
1996    {
1997    labelCount++;
1998    val += deltaMajor;
1999    }
2000
2001  labels->SetNumberOfValues(labelCount);
2002
2003  val = axes[0]->GetMajorRangeStart();
2004  deltaMajor = axes[0]->GetDeltaRangeMajor();
2005
2006  double scaleFactor = 1.;
2007  if (lastPow != 0)
2008    {
2009    scaleFactor = 1.0/pow(10., lastPow);
2010    }
2011
2012  for (i = 0; i < labelCount; i++)
2013    {
2014    if (fabs(val) < 0.01 && extents > 1)
2015      {
2016      // We just happened to fall at something near zero and the range is
2017      // large, so set it to zero to avoid ugliness.
2018      val = 0.;
2019      }
2020    if (mustAdjustValue)
2021      {
2022      sprintf(label, format, val*scaleFactor);
2023      }
2024    else
2025      {
2026      sprintf(label, format, val);
2027      }
2028    if (fabs(val) < 0.01)
2029      {
2030      //
2031      // Ensure that -0.0 is never a label
2032      // The maximum number of digits that we allow past the decimal is 5.
2033      //
2034      if (strcmp(label, "-0") == 0)
2035        {
2036        sprintf(label, "0");
2037        }
2038      else if (strcmp(label, "-0.0") == 0)
2039        {
2040        sprintf(label, "0.0");
2041        }
2042      else if (strcmp(label, "-0.00") == 0)
2043        {
2044        sprintf(label, "0.00");
2045        }
2046      else if (strcmp(label, "-0.000") == 0)
2047        {
2048        sprintf(label, "0.000");
2049        }
2050      else if (strcmp(label, "-0.0000") == 0)
2051        {
2052        sprintf(label, "0.0000");
2053        }
2054      else if (strcmp(label, "-0.00000") == 0)
2055        {
2056        sprintf(label, "0.00000");
2057        }
2058      }
2059    labels->SetValue(i, label);
2060    val += deltaMajor;
2061    }
2062  for (i = 0; i < 4; i++)
2063    {
2064    axes[i]->SetLabels(labels);
2065    }
2066  labels->Delete();
2067}
2068
2069// ****************************************************************************
2070//  Set automatic label scaling mode, set exponents for each axis type.
2071//
2072// ****************************************************************************
2073void vtkRpCubeAxesActor::SetLabelScaling(bool autoscale, int upowX, int upowY,
2074                                       int upowZ)
2075{
2076  if (autoscale != this->AutoLabelScaling || upowX != this->UserXPow ||
2077      upowY != this->UserYPow || upowZ != this->UserZPow)
2078    {
2079    this->AutoLabelScaling = autoscale;
2080    this->UserXPow = upowX;
2081    this->UserYPow = upowY;
2082    this->UserZPow = upowZ;
2083    this->Modified();
2084    }
2085}
Note: See TracBrowser for help on using the repository browser.