vtkChartXYZ.cxx 48.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkChartXYZ.h

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkChartXYZ.h"

#include "vtkAnnotationLink.h"
#include "vtkAxis.h"
Zack Galbreath's avatar
Zack Galbreath committed
20
#include "vtkCommand.h"
21
#include "vtkContext2D.h"
22
#include "vtkContext3D.h"
Zack Galbreath's avatar
Zack Galbreath committed
23 24
#include "vtkContextKeyEvent.h"
#include "vtkContextMouseEvent.h"
25
#include "vtkContextScene.h"
Zack Galbreath's avatar
Zack Galbreath committed
26 27 28 29
#include "vtkLookupTable.h"
#include "vtkMath.h"
#include "vtkPen.h"
#include "vtkPlane.h"
30
#include "vtkPlaneCollection.h"
Zack Galbreath's avatar
Zack Galbreath committed
31
#include "vtkPlot3D.h"
32
#include "vtkTable.h"
Zack Galbreath's avatar
Zack Galbreath committed
33
#include "vtkTextProperty.h"
34 35 36
#include "vtkTransform.h"
#include "vtkVector.h"
#include "vtkVectorOperators.h"
37 38 39
#include "vtkSelection.h"
#include "vtkSelectionNode.h"
#include "vtkIdTypeArray.h"
40 41 42

#include "vtkObjectFactory.h"

Zack Galbreath's avatar
Zack Galbreath committed
43
#include <sstream>
44 45 46

vtkStandardNewMacro(vtkChartXYZ)

Zack Galbreath's avatar
Zack Galbreath committed
47 48
//-----------------------------------------------------------------------------
vtkChartXYZ::vtkChartXYZ() : Geometry(0, 0, 10, 10), IsX(false), Angle(0)
49
{
Zack Galbreath's avatar
Zack Galbreath committed
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
  this->Pen->SetWidth(5);
  this->Pen->SetColor(0, 0, 0, 255);
  this->AxisPen->SetWidth(1);
  this->AxisPen->SetColor(0, 0, 0, 255);
  this->Rotation->Identity();
  this->Rotation->PostMultiply();
  this->Translation->Identity();
  this->Translation->PostMultiply();
  this->Scale->Identity();
  this->Scale->PostMultiply();
  this->Interactive = true;
  this->SceneWidth = 0;
  this->SceneHeight = 0;
  this->InitializeAxesBoundaryPoints();
  this->AutoRotate = false;
  this->DrawAxesDecoration = true;
  this->FitToScene = true;
67 68
  this->Axes.resize(3);
  for(unsigned int i = 0; i < 3; ++i)
69
  {
70
    vtkNew<vtkAxis> axis;
71
    this->Axes[i] = axis;
72
  }
Zack Galbreath's avatar
Zack Galbreath committed
73 74 75
}

//-----------------------------------------------------------------------------
76
vtkChartXYZ::~vtkChartXYZ() = default;
Zack Galbreath's avatar
Zack Galbreath committed
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105

//-----------------------------------------------------------------------------
void vtkChartXYZ::SetAngle(double angle)
{
  this->Angle = angle;
}

//-----------------------------------------------------------------------------
void vtkChartXYZ::SetAroundX(bool IsX_)
{
  this->IsX = IsX_;
}

//-----------------------------------------------------------------------------
void vtkChartXYZ::SetAutoRotate(bool b)
{
  this->AutoRotate = b;
}

//-----------------------------------------------------------------------------
void vtkChartXYZ::SetDecorateAxes(bool b)
{
  this->DrawAxesDecoration = b;
}

//-----------------------------------------------------------------------------
void vtkChartXYZ::SetAnnotationLink(vtkAnnotationLink *link)
{
  if (this->Link != link)
106
  {
Zack Galbreath's avatar
Zack Galbreath committed
107 108
    this->Link = link;
    this->Modified();
109
  }
Zack Galbreath's avatar
Zack Galbreath committed
110 111 112 113 114 115
}

//-----------------------------------------------------------------------------
vtkAxis * vtkChartXYZ::GetAxis(int axis)
{
  assert(axis >= 0 && axis < 3);
116
  return this->Axes[axis];
117 118
}

Peter Franz's avatar
Peter Franz committed
119 120 121 122 123 124 125
//-----------------------------------------------------------------------------
void vtkChartXYZ::SetAxis(int axisIndex, vtkAxis* axis)
{
  assert(axisIndex >= 0 && axisIndex < 3);
  this->Axes[axisIndex] = axis;
}

126 127 128 129 130 131 132 133 134 135 136 137 138
//-----------------------------------------------------------------------------
void vtkChartXYZ::SetAxisColor(const vtkColor4ub& color)
{
  this->AxisPen->SetColor(color);
  this->Modified();
}

//-----------------------------------------------------------------------------
vtkColor4ub vtkChartXYZ::GetAxisColor()
{
  return this->AxisPen->GetColorObject();
}

Zack Galbreath's avatar
Zack Galbreath committed
139 140
//-----------------------------------------------------------------------------
void vtkChartXYZ::SetGeometry(const vtkRectf &bounds)
141
{
Zack Galbreath's avatar
Zack Galbreath committed
142 143
  this->Geometry = bounds;

144
  this->Axes[0]->SetPoint1(vtkVector2f(this->Geometry.GetX(),
Zack Galbreath's avatar
Zack Galbreath committed
145
                           this->Geometry.GetY()));
146
  this->Axes[0]->SetPoint2(vtkVector2f(this->Geometry.GetX() + this->Geometry.GetWidth(),
Zack Galbreath's avatar
Zack Galbreath committed
147 148
                           this->Geometry.GetY()));

149
  this->Axes[1]->SetPoint1(vtkVector2f(this->Geometry.GetX(),
Zack Galbreath's avatar
Zack Galbreath committed
150
                           this->Geometry.GetY()));
151
  this->Axes[1]->SetPoint2(vtkVector2f(this->Geometry.GetX(),
Zack Galbreath's avatar
Zack Galbreath committed
152 153 154
                           this->Geometry.GetY() + this->Geometry.GetHeight()));

  // Z is faked, largely to get valid ranges and rounded numbers...
155
  this->Axes[2]->SetPoint1(vtkVector2f(this->Geometry.GetX(),
Zack Galbreath's avatar
Zack Galbreath committed
156 157
                           0));
  if (this->IsX)
158
  {
159
    this->Axes[2]->SetPoint2(vtkVector2f(this->Geometry.GetX(),
Zack Galbreath's avatar
Zack Galbreath committed
160
                             this->Geometry.GetHeight()));
161
  }
Zack Galbreath's avatar
Zack Galbreath committed
162
  else
163
  {
164
    this->Axes[2]->SetPoint2(vtkVector2f(this->Geometry.GetX(),
Zack Galbreath's avatar
Zack Galbreath committed
165
                             this->Geometry.GetWidth()));
166
  }
Zack Galbreath's avatar
Zack Galbreath committed
167 168 169 170 171 172
}

//-----------------------------------------------------------------------------
void vtkChartXYZ::RecalculateBounds()
{
  if (this->Plots.empty())
173
  {
Zack Galbreath's avatar
Zack Galbreath committed
174
    return;
175
  }
Zack Galbreath's avatar
Zack Galbreath committed
176

177 178 179
  double bounds[] = { VTK_DOUBLE_MAX, VTK_DOUBLE_MIN,
                      VTK_DOUBLE_MAX, VTK_DOUBLE_MIN,
                      VTK_DOUBLE_MAX, VTK_DOUBLE_MIN};
Zack Galbreath's avatar
Zack Galbreath committed
180 181 182

  // Need to calculate the bounds in three dimensions and set up the axes.
  for (unsigned int i = 0; i < this->Plots.size(); ++i)
183
  {
184
    std::vector<vtkVector3f> const& points = this->Plots[i]->GetPoints();
Zack Galbreath's avatar
Zack Galbreath committed
185
    for (unsigned int j = 0; j < points.size(); ++j)
186
    {
Zack Galbreath's avatar
Zack Galbreath committed
187
      const vtkVector3f &v = points[j];
188
      for (int k = 0; k < 3; ++k)
189
      {
190
        if (v[k] < bounds[2 * k])
191
        {
192
          bounds[2 * k] = v[k];
193
        }
194
        if (v[k] > bounds[2 * k + 1])
195
        {
196
          bounds[2 * k + 1] = v[k];
197 198 199
        }
      }
    }
200
  }
Zack Galbreath's avatar
Zack Galbreath committed
201
  for (int i = 0; i < 3; ++i)
202
  {
203
    this->Axes[i]->SetUnscaledRange(&bounds[2*i]);
204
  }
Zack Galbreath's avatar
Zack Galbreath committed
205 206 207

  // Recalculate transform since axes' ranges were modified
  this->RecalculateTransform();
208 209
}

Zack Galbreath's avatar
Zack Galbreath committed
210 211 212 213 214 215
//-----------------------------------------------------------------------------
void vtkChartXYZ::PrintSelf(ostream &os, vtkIndent indent)
{
  Superclass::PrintSelf(os, indent);
}

216 217 218 219
//-----------------------------------------------------------------------------
void vtkChartXYZ::Update()
{
  if (this->Link)
220
  {
221 222 223
    vtkSelection *selection =
        vtkSelection::SafeDownCast(this->Link->GetOutputDataObject(2));
    if (selection->GetNumberOfNodes())
224
    {
225 226
      vtkSelectionNode *node = selection->GetNode(0);
      vtkIdTypeArray *idArray =
227
          vtkArrayDownCast<vtkIdTypeArray>(node->GetSelectionList());
228
      for (size_t i = 0; i < this->Plots.size(); ++i)
229
      {
230 231 232
        this->Plots[i]->SetSelection(idArray);
      }
    }
233
  }
234 235
}

Zack Galbreath's avatar
Zack Galbreath committed
236
//-----------------------------------------------------------------------------
237 238
bool vtkChartXYZ::Paint(vtkContext2D *painter)
{
Zack Galbreath's avatar
Zack Galbreath committed
239
  if (!this->Visible)
240 241
    return false;

242 243
  this->Update();

244 245 246 247 248 249
  // Get the 3D context.
  vtkContext3D *context = painter->GetContext3D();

  if (!context)
    return false;

Zack Galbreath's avatar
Zack Galbreath committed
250 251 252 253 254
  this->Update();

  // Check if the scene changed size
  bool resizeHappened = false;
  if (this->FitToScene)
255
  {
Zack Galbreath's avatar
Zack Galbreath committed
256
    resizeHappened = this->CheckForSceneResize();
257
  }
Zack Galbreath's avatar
Zack Galbreath committed
258 259 260 261

  // Calculate the transforms required for the current rotation.
  this->CalculateTransforms();

262 263
  // Set up clipping planes
  for (int i = 0; i < 6; i++)
264
  {
265 266 267
    double planeEquation[4];
    this->GetClippingPlaneEquation(i, planeEquation);
    context->EnableClippingPlane(i, planeEquation);
268
  }
269

Zack Galbreath's avatar
Zack Galbreath committed
270 271
  // Draw plots
  context->PushMatrix();
272
  context->AppendTransform(this->ContextTransform);
Zack Galbreath's avatar
Zack Galbreath committed
273 274
  this->PaintChildren(painter);

275 276
  // Remove clipping planes
  for (int i = 0; i < 6; i++)
277
  {
278
    context->DisableClippingPlane(i);
279
  }
280

Zack Galbreath's avatar
Zack Galbreath committed
281 282 283 284 285 286 287 288 289
  // Calculate the bounds of the data within the axes
  this->ComputeDataBounds();

  // Pop the ContextTransform now that we're done drawing data within the axes
  context->PopMatrix();

  // Draw the axes, tick marks, and labels
  this->DrawAxes(context);
  if(this->DrawAxesDecoration)
290
  {
Zack Galbreath's avatar
Zack Galbreath committed
291 292 293
    this->DetermineWhichAxesToLabel();
    this->DrawTickMarks(painter);
    this->DrawAxesLabels(painter);
294
  }
Zack Galbreath's avatar
Zack Galbreath committed
295 296 297

  // If necessary, rescale the axes so they fits our scene nicely
  if (resizeHappened)
298
  {
Zack Galbreath's avatar
Zack Galbreath committed
299
    this->RescaleAxes();
300
  }
Zack Galbreath's avatar
Zack Galbreath committed
301 302 303 304 305 306 307 308

  return true;
}

//-----------------------------------------------------------------------------
void vtkChartXYZ::DrawAxes(vtkContext3D *context)
{
  context->PushMatrix();
309 310
  context->AppendTransform(this->Box);
  context->ApplyPen(this->AxisPen);
Zack Galbreath's avatar
Zack Galbreath committed
311 312 313 314 315 316 317 318 319 320 321

  vtkVector3f box[4];
  box[0] = vtkVector3f(0, 0, 0);
  box[1] = vtkVector3f(0, 1, 0);
  box[2] = vtkVector3f(1, 1, 0);
  box[3] = vtkVector3f(1, 0, 0);
  context->DrawLine(box[0], box[1]);
  context->DrawLine(box[1], box[2]);
  context->DrawLine(box[2], box[3]);
  context->DrawLine(box[3], box[0]);
  for (int i = 0; i < 4; ++i)
322
  {
Zack Galbreath's avatar
Zack Galbreath committed
323
    box[i].SetZ(1);
324
  }
Zack Galbreath's avatar
Zack Galbreath committed
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
  context->DrawLine(box[0], box[1]);
  context->DrawLine(box[1], box[2]);
  context->DrawLine(box[2], box[3]);
  context->DrawLine(box[3], box[0]);
  context->DrawLine(vtkVector3f(0, 0, 0), vtkVector3f(0, 0, 1));
  context->DrawLine(vtkVector3f(1, 0, 0), vtkVector3f(1, 0, 1));
  context->DrawLine(vtkVector3f(0, 1, 0), vtkVector3f(0, 1, 1));
  context->DrawLine(vtkVector3f(1, 1, 0), vtkVector3f(1, 1, 1));
}

//-----------------------------------------------------------------------------
void vtkChartXYZ::ComputeDataBounds()
{
  double xMin = VTK_DOUBLE_MAX;
  double xMax = VTK_DOUBLE_MIN;
  double yMin = VTK_DOUBLE_MAX;
  double yMax = VTK_DOUBLE_MIN;
  float transformedPoint[3];

  for (unsigned int i = 0; i < this->Plots.size(); ++i)
345
  {
Zack Galbreath's avatar
Zack Galbreath committed
346 347 348 349
    vtkPlot3D *plot = this->Plots[i];

    // examine the eight corners of this plot's bounding cube
    for (unsigned int j = 0; j < 8; ++j)
350
    {
Zack Galbreath's avatar
Zack Galbreath committed
351
      this->ContextTransform->TransformPoint(
352
        plot->GetDataBounds()[j].GetData(), transformedPoint);
Zack Galbreath's avatar
Zack Galbreath committed
353 354

      if (transformedPoint[0] < xMin)
355
      {
Zack Galbreath's avatar
Zack Galbreath committed
356
        xMin = transformedPoint[0];
357
      }
Zack Galbreath's avatar
Zack Galbreath committed
358
      if (transformedPoint[0] > xMax)
359
      {
Zack Galbreath's avatar
Zack Galbreath committed
360
        xMax = transformedPoint[0];
361
      }
Zack Galbreath's avatar
Zack Galbreath committed
362
      if (transformedPoint[1] < yMin)
363
      {
Zack Galbreath's avatar
Zack Galbreath committed
364
        yMin = transformedPoint[1];
365
      }
Zack Galbreath's avatar
Zack Galbreath committed
366
      if (transformedPoint[1] > yMax)
367
      {
Zack Galbreath's avatar
Zack Galbreath committed
368 369 370
        yMax = transformedPoint[1];
      }
    }
371
  }
Zack Galbreath's avatar
Zack Galbreath committed
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390

  this->DataBounds[0] = xMin;
  this->DataBounds[1] = yMin;
  this->DataBounds[2] = xMax;
  this->DataBounds[3] = yMax;
}

//-----------------------------------------------------------------------------
void vtkChartXYZ::DrawAxesLabels(vtkContext2D *painter)
{
  vtkContext3D *context = painter->GetContext3D();

  // set up text property
  vtkNew<vtkTextProperty> textProperties;
  textProperties->SetJustificationToCentered();
  textProperties->SetVerticalJustificationToCentered();
  textProperties->SetColor(0.0, 0.0, 0.0);
  textProperties->SetFontFamilyToArial();
  textProperties->SetFontSize(14);
391
  painter->ApplyTextProp(textProperties);
Zack Galbreath's avatar
Zack Galbreath committed
392 393 394 395 396

  // if we're looking directly down any dimension, we shouldn't draw the
  // corresponding label
  bool shouldDrawAxis[3];
  for (int axis = 0; axis < 3; ++axis)
397
  {
Zack Galbreath's avatar
Zack Galbreath committed
398 399 400 401 402 403 404 405 406 407
    shouldDrawAxis[axis] = true;
    float start[3] = { 0, 0, 0 };
    float end[3] = { 0, 0, 0 };
    end[axis] = 1;
    this->Box->TransformPoint(start, start);
    this->Box->TransformPoint(end, end);
    float axisLength = sqrt(
      (end[0] - start[0]) * (end[0] - start[0]) +
      (end[1] - start[1]) * (end[1] - start[1]));
    if (axisLength == 0)
408
    {
Zack Galbreath's avatar
Zack Galbreath committed
409 410
      shouldDrawAxis[axis] = false;
    }
411
  }
Zack Galbreath's avatar
Zack Galbreath committed
412 413 414 415 416 417 418 419 420

  float bounds[4];
  float xLabelPos[3];
  float yLabelPos[3];
  float zLabelPos[3];
  float offset[2] = {0, 0};

  // calculate the pixel coordinates of the lines we wish to label
  if (shouldDrawAxis[0])
421
  {
Zack Galbreath's avatar
Zack Galbreath committed
422 423 424 425
    xLabelPos[0]  = 0.5;
    xLabelPos[1]  = this->XAxisToLabel[0];
    xLabelPos[2]  = this->XAxisToLabel[1];
    this->Box->TransformPoint(xLabelPos, xLabelPos);
426
  }
Zack Galbreath's avatar
Zack Galbreath committed
427
  if (shouldDrawAxis[1])
428
  {
Zack Galbreath's avatar
Zack Galbreath committed
429 430 431 432
    yLabelPos[0]  = this->YAxisToLabel[0];
    yLabelPos[1]  = 0.5;
    yLabelPos[2]  = this->YAxisToLabel[1];
    this->Box->TransformPoint(yLabelPos, yLabelPos);
433
  }
Zack Galbreath's avatar
Zack Galbreath committed
434
  if (shouldDrawAxis[2])
435
  {
Zack Galbreath's avatar
Zack Galbreath committed
436 437 438 439
    zLabelPos[0]  = this->ZAxisToLabel[0];
    zLabelPos[1]  = this->ZAxisToLabel[1];
    zLabelPos[2]  = 0.5;
    this->Box->TransformPoint(zLabelPos, zLabelPos);
440
  }
Zack Galbreath's avatar
Zack Galbreath committed
441 442 443 444

  context->PopMatrix();

  if (shouldDrawAxis[0])
445
  {
Zack Galbreath's avatar
Zack Galbreath committed
446 447 448 449 450
    painter->ComputeStringBounds(this->XAxisLabel, bounds);
    this->GetOffsetForAxisLabel(0, bounds, offset);
    xLabelPos[0] += (offset[0] + this->TickLabelOffset[0][0]);
    xLabelPos[1] += (offset[1] + this->TickLabelOffset[0][1]);
    painter->DrawString(xLabelPos[0], xLabelPos[1], this->XAxisLabel);
451
  }
Zack Galbreath's avatar
Zack Galbreath committed
452 453

  if (shouldDrawAxis[1])
454
  {
Zack Galbreath's avatar
Zack Galbreath committed
455 456 457 458 459 460 461
    painter->ComputeStringBounds(this->YAxisLabel, bounds);
    offset[0] = 0;
    offset[1] = 0;
    this->GetOffsetForAxisLabel(1, bounds, offset);
    yLabelPos[0] += (offset[0] + this->TickLabelOffset[1][0]);
    yLabelPos[1] += (offset[1] + this->TickLabelOffset[1][1]);
    painter->DrawString(yLabelPos[0], yLabelPos[1], this->YAxisLabel);
462
  }
Zack Galbreath's avatar
Zack Galbreath committed
463 464

  if (shouldDrawAxis[2])
465
  {
Zack Galbreath's avatar
Zack Galbreath committed
466 467 468 469 470 471 472
    painter->ComputeStringBounds(this->ZAxisLabel, bounds);
    offset[0] = 0;
    offset[1] = 0;
    this->GetOffsetForAxisLabel(2, bounds, offset);
    zLabelPos[0] += (offset[0] + this->TickLabelOffset[2][0]);
    zLabelPos[1] += (offset[1] + this->TickLabelOffset[2][1]);
    painter->DrawString(zLabelPos[0], zLabelPos[1], this->ZAxisLabel);
473
  }
Zack Galbreath's avatar
Zack Galbreath committed
474 475 476 477 478 479 480 481 482
}

//-----------------------------------------------------------------------------
void vtkChartXYZ::GetOffsetForAxisLabel(int axis, float *bounds,
                                                   float *offset)
{
  offset[0] = 0;
  offset[1] = 0;
  switch (this->DirectionToData[axis])
483
  {
Zack Galbreath's avatar
Zack Galbreath committed
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
    // data is to the north
    // offset is -y
    case 0:
      offset[1] = -bounds[3];
      break;

    // data is northeast
    // offset is -x, -y
    case 1:
      offset[0] = -bounds[2];
      offset[1] = -bounds[3];
      break;

    // data is east
    // offset is -x
    case 2:
      offset[0] = -bounds[2];
      break;

    // data is southeast
    // offset is -x, +y
    case 3:
      offset[0] = -bounds[2];
      offset[1] = bounds[3];
      break;

    // data is south
    // offset is +y
    case 4:
      offset[1] = bounds[3];
      break;

    // data is southwest
    // offset is +x, +y
    case 5:
      offset[0] = bounds[2];
      offset[1] = bounds[3];
      break;

    // data is west
    // offset is +y
    case 6:
      offset[0] = bounds[2];
      break;

    // data is northwest
    // offset is +x, -y
    case 7:
    default:
      offset[0] = bounds[2];
      offset[1] = -bounds[3];
      break;
536
  }
Zack Galbreath's avatar
Zack Galbreath committed
537 538 539 540 541 542 543 544 545
}

//-----------------------------------------------------------------------------
void vtkChartXYZ::DrawTickMarks(vtkContext2D *painter)
{
  vtkContext3D *context = painter->GetContext3D();
  float bounds[4];

  // draw points instead of lines
546
  context->ApplyPen(this->Pen);
Zack Galbreath's avatar
Zack Galbreath committed
547 548 549

  // treat each axis separately
  for (int axis = 0; axis < 3; ++axis)
550
  {
Zack Galbreath's avatar
Zack Galbreath committed
551 552 553 554 555 556 557 558 559
    // pop matrix since we'll be drawing text in 2D before we draw the
    // actual tick marks
    context->PopMatrix();
    float labelOffset[2] = { 0, 0 };

    // initialize start and end of the axis to label in box coordinates
    double startBox[3] = { 0, 0, 0 };
    double endBox[3] = { 0, 0, 0 };
    switch (axis)
560
    {
Zack Galbreath's avatar
Zack Galbreath committed
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
      case 0:
        startBox[0] = 0;
        endBox[0]   = 1;
        startBox[1] = endBox[1] = this->XAxisToLabel[0];
        startBox[2] = endBox[2] = this->XAxisToLabel[1];
        break;
      case 1:
        startBox[0] = this->YAxisToLabel[0];
        startBox[1] = 0;
        endBox[1]   = 1;
        startBox[2] = endBox[2] = this->YAxisToLabel[1];
        break;
      case 2:
      default:
        startBox[0] = endBox[0] = this->ZAxisToLabel[0];
        startBox[1] = endBox[1] = this->ZAxisToLabel[1];
        startBox[2] = 0;
        endBox[2]   = 1;
        break;
580
    }
Zack Galbreath's avatar
Zack Galbreath committed
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596

    // convert these values to pixel coordinates
    double start[3];
    double end[3];
    this->Box->TransformPoint(startBox, start);
    this->Box->TransformPoint(endBox, end);

    // ...and then into data coordinates
    this->ContextTransform->GetInverse()->TransformPoint(start, start);
    this->ContextTransform->GetInverse()->TransformPoint(end, end);

    // get "nice" values for min, max, and spacing (again, in data coordinates)
    double tickSpacing =
      this->CalculateNiceMinMax(start[axis], end[axis], axis);

    if (tickSpacing == -1)
597
    {
Zack Galbreath's avatar
Zack Galbreath committed
598
      continue;
599
    }
Zack Galbreath's avatar
Zack Galbreath committed
600 601 602 603 604

    std::vector < vtkVector3f > tickPoints;
    int currentTick = 0;
    float tickPositionAlongAxis = start[axis];
    while (tickPositionAlongAxis < end[axis])
605
    {
Zack Galbreath's avatar
Zack Galbreath committed
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
      vtkVector3f tick;
      // convert tick position back into box coordinates
      // during this process, we save the tick position in pixels for labeling
      float tickPosition[3];
      tickPosition[0] = start[0];
      tickPosition[1] = start[1];
      tickPosition[2] = start[2];
      tickPosition[axis] = tickPositionAlongAxis;
      float tickPositionInPixels[3];
      this->ContextTransform->TransformPoint(tickPosition,
                                             tickPositionInPixels);
      this->Box->GetInverse()->TransformPoint(tickPositionInPixels,
                                              tickPosition);

      // determine the location of this tick mark and push it onto the vector
      // if it falls within the bounds of the axis
      tick[0] = startBox[0];
      tick[1] = startBox[1];
      tick[2] = startBox[2];
      tick[axis] = tickPosition[axis];

      if (tick[axis] >= startBox[axis] && tick[axis] <= endBox[axis])
628
      {
Zack Galbreath's avatar
Zack Galbreath committed
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
        tickPoints.push_back(tick);

        // get the tick mark label
        std::stringstream sstream;
        sstream << std::fixed << setprecision(1) << tickPositionAlongAxis;
        std::string tickLabel = sstream.str();

        // offset the label from the axis
        float offset[2] = {0, 0};
        painter->ComputeStringBounds(tickLabel, bounds);
        this->GetOffsetForAxisLabel(axis, bounds, offset);
        tickPositionInPixels[0] += offset[0];
        tickPositionInPixels[1] += offset[1];

        // we store this offset so we know where to draw the axis label later
644
        if (fabs(offset[0]) > fabs(labelOffset[0]))
645
        {
Zack Galbreath's avatar
Zack Galbreath committed
646
          labelOffset[0] = offset[0];
647
        }
648
        if (fabs(offset[1]) > fabs(labelOffset[1]))
649
        {
Zack Galbreath's avatar
Zack Galbreath committed
650
          labelOffset[1] = offset[1];
651
        }
Zack Galbreath's avatar
Zack Galbreath committed
652 653 654 655

        // draw the label for this tick mark
        painter->DrawString(tickPositionInPixels[0], tickPositionInPixels[1],
                            tickLabel);
656
      }
Zack Galbreath's avatar
Zack Galbreath committed
657 658
      ++currentTick;
      tickPositionAlongAxis = start[axis] + (tickSpacing * currentTick);
659
    }
Zack Galbreath's avatar
Zack Galbreath committed
660 661

    // re-apply the Box matrix and draw the tick marks as points
662
    if (!tickPoints.empty())
663
    {
Zack Galbreath's avatar
Zack Galbreath committed
664
      context->PushMatrix();
665
      context->AppendTransform(this->Box);
Zack Galbreath's avatar
Zack Galbreath committed
666 667 668 669 670
      context->DrawPoints(tickPoints[0].GetData(),
                          static_cast<int>(tickPoints.size()));
      this->TickLabelOffset[axis][0] = labelOffset[0];
      this->TickLabelOffset[axis][1] = labelOffset[1];
    }
671
  }
Zack Galbreath's avatar
Zack Galbreath committed
672 673

  //revert from drawing points.
674
  context->ApplyPen(this->AxisPen);
Zack Galbreath's avatar
Zack Galbreath committed
675 676 677 678 679 680 681
}

//-----------------------------------------------------------------------------
void vtkChartXYZ::DetermineWhichAxesToLabel()
{
  // for each dimension (XYZ)
  for (int axis = 0; axis < 3; ++axis)
682
  {
Zack Galbreath's avatar
Zack Galbreath committed
683 684 685
    double maxDistance = -1;
    // for each of the four "axis" lines corresponding to this dimension
    for (float i = 0; i < 2; ++i)
686
    {
Zack Galbreath's avatar
Zack Galbreath committed
687
      for (float j = 0; j < 2; ++j)
688
      {
Zack Galbreath's avatar
Zack Galbreath committed
689
        for (float k = 0; k < 2; ++k)
690
        {
Zack Galbreath's avatar
Zack Galbreath committed
691 692 693 694 695 696 697 698 699 700 701 702
          // convert this line's midpoint to screen (pixel) coordinates
          float midpoint[3] = { i, j, k };
          midpoint[axis] = 0.5;
          this->Box->TransformPoint(midpoint, midpoint);

          // ignore any lines whose midpoint falls within the data range.
          // we increment the iterators so we don't evaluate the same line
          // twice.
          if (midpoint[0] > this->DataBounds[0] &&
              midpoint[1] > this->DataBounds[1] &&
              midpoint[0] < this->DataBounds[2] &&
              midpoint[1] < this->DataBounds[3])
703
          {
Zack Galbreath's avatar
Zack Galbreath committed
704
            switch (axis)
705
            {
Zack Galbreath's avatar
Zack Galbreath committed
706 707 708 709 710 711 712 713
              case 0:
                ++i;
                break;
              case 1:
                ++j;
                break;
              case 2:
                ++k;
714
                break;
Zack Galbreath's avatar
Zack Galbreath committed
715 716 717
              default:
                break;
            }
718 719
            continue;
          }
Zack Galbreath's avatar
Zack Galbreath committed
720 721 722 723 724 725 726 727

          // calculate the distance from this line's midpoint to the data range
          double d = 0;
          int directionToData = 0;

          // case 1: midpoint falls within x range (but not y)
          if (midpoint[0] > this->DataBounds[0] &&
              midpoint[0] < this->DataBounds[2])
728
          {
729 730
            double d1 = fabs(midpoint[1] - this->DataBounds[1]);
            double d2 = fabs(midpoint[1] - this->DataBounds[3]);
Zack Galbreath's avatar
Zack Galbreath committed
731
            if (d1 < d2)
732
            {
Zack Galbreath's avatar
Zack Galbreath committed
733 734
              directionToData = 0;  // data is "up" from the axis
              d = d1;
735
            }
Zack Galbreath's avatar
Zack Galbreath committed
736
            else
737
            {
Zack Galbreath's avatar
Zack Galbreath committed
738 739 740
              directionToData = 4;  // data is "down" from the axis
              d = d2;
            }
741
          }
Zack Galbreath's avatar
Zack Galbreath committed
742 743 744 745

          // case 2: midpoint falls within y range (but not x)
          else if (midpoint[1] > this->DataBounds[1] &&
                   midpoint[1] < this->DataBounds[3])
746
          {
747 748
            double d1 = fabs(midpoint[0] - this->DataBounds[0]);
            double d2 = fabs(midpoint[0] - this->DataBounds[2]);
Zack Galbreath's avatar
Zack Galbreath committed
749
            if (d1 < d2)
750
            {
Zack Galbreath's avatar
Zack Galbreath committed
751 752
              directionToData = 2;  // data is "right" from the axis
              d = d1;
753
            }
Zack Galbreath's avatar
Zack Galbreath committed
754
            else
755
            {
Zack Galbreath's avatar
Zack Galbreath committed
756 757 758
              directionToData = 6;  // data is "left" from the axis
              d = d2;
            }
759
          }
Zack Galbreath's avatar
Zack Galbreath committed
760 761 762

          // case 3: compute distance to nearest corner
          else
763
          {
Zack Galbreath's avatar
Zack Galbreath committed
764 765 766 767 768 769 770 771 772 773 774 775 776 777
            //x min, y min
            d = sqrt( (this->DataBounds[0] - midpoint[0]) *
                      (this->DataBounds[0] - midpoint[0]) +
                      (this->DataBounds[1] - midpoint[1]) *
                      (this->DataBounds[1] - midpoint[1]) );
            directionToData = 1;  // data is to the northeast

            //x min, y max
            double d0 =
              sqrt( (this->DataBounds[0] - midpoint[0]) *
                    (this->DataBounds[0] - midpoint[0]) +
                    (this->DataBounds[3] - midpoint[1]) *
                    (this->DataBounds[3] - midpoint[1]) );
            if (d0 < d)
778
            {
Zack Galbreath's avatar
Zack Galbreath committed
779 780
              d = d0;
              directionToData = 3;  // data is to the southeast
781
            }
Zack Galbreath's avatar
Zack Galbreath committed
782 783 784 785 786 787
            //x max, y min
            d0 = sqrt( (this->DataBounds[2] - midpoint[0]) *
                       (this->DataBounds[2] - midpoint[0]) +
                       (this->DataBounds[1] - midpoint[1]) *
                       (this->DataBounds[1] - midpoint[1]) );
            if (d0 < d)
788
            {
Zack Galbreath's avatar
Zack Galbreath committed
789 790
              d = d0;
              directionToData = 7;  // data is to the northwest
791
            }
Zack Galbreath's avatar
Zack Galbreath committed
792 793 794 795 796 797
            //x max, y max
            d0 = sqrt( (this->DataBounds[2] - midpoint[0]) *
                       (this->DataBounds[2] - midpoint[0]) +
                       (this->DataBounds[3] - midpoint[1]) *
                       (this->DataBounds[3] - midpoint[1]) );
            if (d0 < d)
798
            {
Zack Galbreath's avatar
Zack Galbreath committed
799 800
              d = d0;
              directionToData = 5;  // data is to the southwest
801
            }
Zack Galbreath's avatar
Zack Galbreath committed
802 803 804 805 806 807 808 809 810 811 812 813 814 815

            // Test if the data falls within the bounds of our axis line,
            // despite the fact that it is diagonal from the line's midpoint.
            // This is performed to determine how the label should be offset
            // from the line.  To do this, we transform the line's start and
            // end point to pixel coordinates.
            float start[3] = { i, j, k };
            start[axis] = 0;
            this->Box->TransformPoint(start, start);
            float end[3] = { i, j, k };
            end[axis] = 1;
            this->Box->TransformPoint(end, end);

            if (start[0] < this->DataBounds[0] && end[0] > this->DataBounds[2])
816
            {
Zack Galbreath's avatar
Zack Galbreath committed
817 818 819
                // data falls within horizontal range of this axis line
                // set directionToData as purely up or purely down
                if (directionToData == 1 || directionToData == 7)
820
                {
Zack Galbreath's avatar
Zack Galbreath committed
821
                  directionToData = 0;
822
                }
Zack Galbreath's avatar
Zack Galbreath committed
823
                else
824
                {
Zack Galbreath's avatar
Zack Galbreath committed
825
                  directionToData = 4;
826 827
                }
            }
Zack Galbreath's avatar
Zack Galbreath committed
828 829
            else if (start[1] < this->DataBounds[1] &&
                     end[1] > this->DataBounds[3])
830
            {
Zack Galbreath's avatar
Zack Galbreath committed
831 832 833
              // data falls within vertical range of this axis line
              // set directionToData as purely left or purely right
                if (directionToData == 1 || directionToData == 3)
834
                {
Zack Galbreath's avatar
Zack Galbreath committed
835
                  directionToData = 2;
836
                }
Zack Galbreath's avatar
Zack Galbreath committed
837
                else
838
                {
Zack Galbreath's avatar
Zack Galbreath committed
839
                  directionToData = 6;
840
                }
Zack Galbreath's avatar
Zack Galbreath committed
841
            }
842
          }
Zack Galbreath's avatar
Zack Galbreath committed
843 844 845

          // record this axis line if it has the greatest distance to the data
          if (d > maxDistance)
846
          {
Zack Galbreath's avatar
Zack Galbreath committed
847 848 849
            this->DirectionToData[axis] = directionToData;
            maxDistance = d;
            switch (axis)
850
            {
Zack Galbreath's avatar
Zack Galbreath committed
851
              case 0:
852 853
                this->XAxisToLabel[0] = static_cast<int>(j);
                this->XAxisToLabel[1] = static_cast<int>(k);
Zack Galbreath's avatar
Zack Galbreath committed
854 855
                break;
              case 1:
856 857
                this->YAxisToLabel[0] = static_cast<int>(i);
                this->YAxisToLabel[1] = static_cast<int>(k);
Zack Galbreath's avatar
Zack Galbreath committed
858 859 860
                break;
              case 2:
              default:
861 862
                this->ZAxisToLabel[0] = static_cast<int>(i);
                this->ZAxisToLabel[1] = static_cast<int>(j);
Zack Galbreath's avatar
Zack Galbreath committed
863 864
                break;
            }
865
          }
Zack Galbreath's avatar
Zack Galbreath committed
866 867 868

          // these three cases keep us from evaluating the same line twice.
          if (axis == 2)
869
          {
Zack Galbreath's avatar
Zack Galbreath committed
870 871
            ++k;
          }
872
        }
Zack Galbreath's avatar
Zack Galbreath committed
873
        if (axis == 1)
874
        {
Zack Galbreath's avatar
Zack Galbreath committed
875 876
          ++j;
        }
877
      }
Zack Galbreath's avatar
Zack Galbreath committed
878
      if (axis == 0)
879
      {
Zack Galbreath's avatar
Zack Galbreath committed
880 881 882
        ++i;
      }
    }
883
  }
Zack Galbreath's avatar
Zack Galbreath committed
884 885 886 887 888 889
}

//-----------------------------------------------------------------------------
bool vtkChartXYZ::Hit(const vtkContextMouseEvent& vtkNotUsed(mouse))
{
  if (!this->Interactive || !this->Visible || this->AutoRotate)
890
  {
Zack Galbreath's avatar
Zack Galbreath committed
891
    return false;
892
  }
Zack Galbreath's avatar
Zack Galbreath committed
893 894 895 896 897 898 899 900 901

  return true;
}

//-----------------------------------------------------------------------------
bool vtkChartXYZ::MouseButtonPressEvent(const vtkContextMouseEvent
                                                   &mouse)
{
  if (mouse.GetButton() == vtkContextMouseEvent::LEFT_BUTTON)
902
  {
Zack Galbreath's avatar
Zack Galbreath committed
903
    return true;
904
  }
Zack Galbreath's avatar
Zack Galbreath committed
905 906 907 908 909 910 911
  return false;
}

//-----------------------------------------------------------------------------
bool vtkChartXYZ::MouseMoveEvent(const vtkContextMouseEvent &mouse)
{
  if (mouse.GetButton() == vtkContextMouseEvent::LEFT_BUTTON)
912
  {
Zack Galbreath's avatar
Zack Galbreath committed
913
    if (mouse.GetModifiers() == vtkContextMouseEvent::SHIFT_MODIFIER)
914
    {
Zack Galbreath's avatar
Zack Galbreath committed
915
      return this->Spin(mouse);
916
    }
Zack Galbreath's avatar
Zack Galbreath committed
917
    else
918
    {
Zack Galbreath's avatar
Zack Galbreath committed
919 920
      return this->Rotate(mouse);
    }
921
  }
Zack Galbreath's avatar
Zack Galbreath committed
922
  if (mouse.GetButton() == vtkContextMouseEvent::RIGHT_BUTTON)
923
  {
Zack Galbreath's avatar
Zack Galbreath committed
924
    if (mouse.GetModifiers() == vtkContextMouseEvent::SHIFT_MODIFIER)
925
    {
Zack Galbreath's avatar
Zack Galbreath committed
926
      return this->Pan(mouse);
927
    }
Zack Galbreath's avatar
Zack Galbreath committed
928
    else
929
    {
Zack Galbreath's avatar
Zack Galbreath committed
930 931
      return this->Zoom(mouse);
    }
932
  }
Zack Galbreath's avatar
Zack Galbreath committed
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966
  return false;
}

//-----------------------------------------------------------------------------
bool vtkChartXYZ::MouseWheelEvent(const vtkContextMouseEvent&,
                                             int delta)
{
  // Ten "wheels" to double/halve zoom level
  float scaling = pow(2.0f, delta/10.0f);
  this->Scale->Scale(scaling, scaling, scaling);

  // Mark the scene as dirty
  this->Scene->SetDirty(true);

  this->InvokeEvent(vtkCommand::InteractionEvent);
  return true;
}

//-----------------------------------------------------------------------------
void vtkChartXYZ::ZoomAxes(int delta)
{
  float scaling = pow(2.0f, delta/10.0f);
  this->BoxScale->Scale(scaling, scaling, scaling);

  // Mark the scene as dirty
  this->Scene->SetDirty(true);
}

//-----------------------------------------------------------------------------
bool vtkChartXYZ::Rotate(const vtkContextMouseEvent &mouse)
{
  // avoid NaNs in our transformation matrix if the scene has not yet been
  // rendered.
  if (this->Scene->GetSceneHeight() == 0 || this->Scene->GetSceneWidth() == 0)
967
  {
Zack Galbreath's avatar
Zack Galbreath committed
968
    return false;
969
  }
Zack Galbreath's avatar
Zack Galbreath committed
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021

  // Figure out how much the mouse has moved in plot coordinates
  vtkVector2d screenPos(mouse.GetScreenPos().Cast<double>().GetData());
  vtkVector2d lastScreenPos(mouse.GetLastScreenPos().Cast<double>().GetData());

  double dx = screenPos[0] - lastScreenPos[0];
  double dy = screenPos[1] - lastScreenPos[1];

  double delta_elevation = -20.0 / this->Scene->GetSceneHeight();
  double delta_azimuth = -20.0 / this->Scene->GetSceneWidth();

  double rxf = -dx * delta_azimuth * 10.0;
  double ryf = -dy * delta_elevation * 10.0;

  this->Rotation->RotateY(rxf);
  this->Rotation->RotateX(-ryf);

  // Mark the scene as dirty
  this->Scene->SetDirty(true);

  this->InvokeEvent(vtkCommand::InteractionEvent);
  return true;
}

//-----------------------------------------------------------------------------
bool vtkChartXYZ::Pan(const vtkContextMouseEvent &mouse)
{
  // Figure out how much the mouse has moved in plot coordinates
  vtkVector2d screenPos(mouse.GetScreenPos().Cast<double>().GetData());
  vtkVector2d lastScreenPos(mouse.GetLastScreenPos().Cast<double>().GetData());

  double dx = (screenPos[0] - lastScreenPos[0]);
  double dy = (screenPos[1] - lastScreenPos[1]);

  this->Translation->Translate(dx, dy, 0.0);

  // Mark the scene as dirty
  this->Scene->SetDirty(true);

  this->InvokeEvent(vtkCommand::InteractionEvent);
  return true;
}

//-----------------------------------------------------------------------------
bool vtkChartXYZ::Zoom(const vtkContextMouseEvent &mouse)
{
  // Figure out how much the mouse has moved and scale accordingly
  vtkVector2d screenPos(mouse.GetScreenPos().Cast<double>().GetData());
  vtkVector2d lastScreenPos(mouse.GetLastScreenPos().Cast<double>().GetData());

  float delta = 0.0f;
  if (this->Scene->GetSceneHeight() > 0)
1022
  {
Zack Galbreath's avatar
Zack Galbreath committed
1023 1024 1025
    delta = static_cast<float>(
      mouse.GetLastScreenPos()[1] - mouse.GetScreenPos()[1]) /
      this->Scene->GetSceneHeight();
1026
  }
Zack Galbreath's avatar
Zack Galbreath committed
1027 1028 1029 1030

  // Dragging full screen height zooms 4x.
  float scaling = pow(4.0f, delta);
  this->Scale->Scale(scaling, scaling, scaling);
1031

Zack Galbreath's avatar
Zack Galbreath committed
1032 1033
  // Mark the scene as dirty
  this->Scene->SetDirty(true);
1034

Zack Galbreath's avatar
Zack Galbreath committed
1035 1036 1037
  this->InvokeEvent(vtkCommand::InteractionEvent);
  return true;
}
1038

Zack Galbreath's avatar
Zack Galbreath committed
1039 1040 1041 1042 1043 1044
//-----------------------------------------------------------------------------
bool vtkChartXYZ::Spin(const vtkContextMouseEvent &mouse)
{
  // Figure out how much the mouse has moved in plot coordinates
  vtkVector2d screenPos(mouse.GetScreenPos().Cast<double>().GetData());
  vtkVector2d lastScreenPos(mouse.GetLastScreenPos().Cast<double>().GetData());
1045

Zack Galbreath's avatar
Zack Galbreath committed
1046 1047 1048 1049
  double newAngle =
    vtkMath::DegreesFromRadians(atan2(screenPos[1], screenPos[0]));
  double oldAngle =
    vtkMath::DegreesFromRadians(atan2(lastScreenPos[1], lastScreenPos[0]));
1050

Zack Galbreath's avatar
Zack Galbreath committed
1051
  this->Rotation->RotateZ(-(newAngle - oldAngle));
1052

Zack Galbreath's avatar
Zack Galbreath committed
1053 1054
  // Mark the scene as dirty
  this->Scene->SetDirty(true);
1055

Zack Galbreath's avatar
Zack Galbreath committed
1056 1057 1058 1059 1060 1061 1062 1063
  this->InvokeEvent(vtkCommand::InteractionEvent);
  return true;
}

//-----------------------------------------------------------------------------
bool vtkChartXYZ::KeyPressEvent(const vtkContextKeyEvent &key)
{
  switch (key.GetKeyCode())
1064
  {
Zack Galbreath's avatar
Zack Galbreath committed
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
    // Change view to 2D, YZ chart
    case 'x':
      this->LookDownX();
      break;
    case 'X':
      this->LookUpX();
      break;
    // Change view to 2D, XZ chart
    case 'y':
      this->LookDownY();
      break;
    case 'Y':
      this->LookUpY();
      break;
    // Change view to 2D, XY chart
    case 'z':
      this->LookDownZ();
      break;
    case 'Z':
      this->LookUpZ();
      break;
1086
  }
1087

1088 1089 1090
  return true;
}

Zack Galbreath's avatar
Zack Galbreath committed
1091 1092
//-----------------------------------------------------------------------------
void vtkChartXYZ::LookDownX()
1093
{
Zack Galbreath's avatar
Zack Galbreath committed
1094 1095 1096 1097
  this->InvokeEvent(vtkCommand::InteractionEvent);
  this->Rotation->Identity();
  this->Rotation->RotateY(-90.0);
  this->Scene->SetDirty(true);
1098 1099
}

Zack Galbreath's avatar
Zack Galbreath committed
1100 1101
//-----------------------------------------------------------------------------
void vtkChartXYZ::LookDownY()
1102
{
Zack Galbreath's avatar
Zack Galbreath committed
1103 1104 1105 1106
  this->Rotation->Identity();
  this->Rotation->RotateX(90.0);
  this->InvokeEvent(vtkCommand::InteractionEvent);
  this->Scene->SetDirty(true);
1107 1108
}

Zack Galbreath's avatar
Zack Galbreath committed
1109 1110
//-----------------------------------------------------------------------------
void vtkChartXYZ::LookDownZ()
1111
{
Zack Galbreath's avatar
Zack Galbreath committed
1112 1113 1114
  this->Rotation->Identity();
  this->InvokeEvent(vtkCommand::InteractionEvent);
  this->Scene->SetDirty(true);
1115 1116
}

Zack Galbreath's avatar
Zack Galbreath committed
1117 1118
//-----------------------------------------------------------------------------
void vtkChartXYZ::LookUpX()
1119
{
Zack Galbreath's avatar
Zack Galbreath committed
1120 1121 1122 1123
  this->InvokeEvent(vtkCommand::InteractionEvent);
  this->Rotation->Identity();
  this->Rotation->RotateY(90.0);
  this->Scene->SetDirty(true);
1124 1125
}

Zack Galbreath's avatar
Zack Galbreath committed
1126 1127 1128 1129 1130 1131 1132
//-----------------------------------------------------------------------------
void vtkChartXYZ::LookUpY()
{
  this->Rotation->Identity();
  this->Rotation->RotateX(-90.0);
  this->InvokeEvent(vtkCommand::InteractionEvent);
  this->Scene->SetDirty(true);
1133 1134
}

Zack Galbreath's avatar
Zack Galbreath committed
1135 1136
//-----------------------------------------------------------------------------
void vtkChartXYZ::LookUpZ()
1137
{
Zack Galbreath's avatar
Zack Galbreath committed
1138 1139 1140 1141 1142
  this->Rotation->Identity();
  this->Rotation->RotateY(180.0);
  this->InvokeEvent(vtkCommand::InteractionEvent);
  this->Scene->SetDirty(true);
}
1143

Zack Galbreath's avatar
Zack Galbreath committed
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156
//-----------------------------------------------------------------------------
void vtkChartXYZ::CalculateTransforms()
{
  // Calculate the correct translation vector so that rotation and scale
  // are applied about the middle of the axes box.
  vtkVector3f translation(
    (this->Axes[0]->GetPosition2()[0] - this->Axes[0]->GetPosition1()[0]) / 2.0
      + this->Axes[0]->GetPosition1()[0],
    (this->Axes[1]->GetPosition2()[1] - this->Axes[1]->GetPosition1()[1]) / 2.0
      + this->Axes[1]->GetPosition1()[1],
    (this->Axes[2]->GetPosition2()[1] - this->Axes[2]->GetPosition1()[1]) / 2.0
      + this->Axes[2]->GetPosition1()[1]);
  vtkVector3f mtranslation = -1.0 * translation;
1157

Zack Galbreath's avatar
Zack Galbreath committed
1158
  this->ContextTransform->Identity();
1159
  this->ContextTransform->Concatenate(this->Translation);
Zack Galbreath's avatar
Zack Galbreath committed
1160
  this->ContextTransform->Translate(translation.GetData());
1161 1162
  this->ContextTransform->Concatenate(this->Rotation);
  this->ContextTransform->Concatenate(this->BoxScale);
Zack Galbreath's avatar
Zack Galbreath committed
1163
  if (this->AutoRotate)
1164
  {
Zack Galbreath's avatar
Zack Galbreath committed
1165
    if (this->IsX)
1166
    {
Zack Galbreath's avatar
Zack Galbreath committed
1167
      this->ContextTransform->RotateX(this->Angle);
1168
    }
Zack Galbreath's avatar
Zack Galbreath committed
1169
    else
1170
    {
Zack Galbreath's avatar
Zack Galbreath committed
1171 1172
      this->ContextTransform->RotateY(this->Angle);
    }
1173
  }
1174
  this->ContextTransform->Concatenate(this->Scale);
Zack Galbreath's avatar
Zack Galbreath committed
1175 1176 1177 1178 1179
  this->ContextTransform->Translate(mtranslation.GetData());
  this->ContextTransform->Translate(
    this->Axes[0]->GetPosition1()[0] - this->Geometry.GetX(),
    this->Axes[1]->GetPosition1()[1] - this->Geometry.GetY(),
    this->Axes[2]->GetPosition1()[1]);
1180
  this->ContextTransform->Concatenate(this->PlotTransform);
1181

Zack Galbreath's avatar
Zack Galbreath committed
1182 1183 1184
  // Next construct the transform for the box axes.
  double scale[3] = { 300, 300, 300 };
  for (int i = 0; i < 3; ++i)
Kitware Robot's avatar