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

Last change on this file since 2864 was 2864, checked in by ldelgass, 12 years ago

Include custom version of VTK 3d axes, with fix for showing gridlines only on
active axis planes. Also include a copy of 2D/3D axis classes, though these
are not currently customized. Based on VTK 5.8.0.

  • Property svn:eol-style set to native
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.