Commit 7cee41db authored by Marcus D. Hanwell's avatar Marcus D. Hanwell

Shift the origin and/or apply scaling in charts

This accounts for both under and overflow. Added a test requiring the
origin shift in order to correctly render points. The odd artifact is
the labels on the X axis (all 1) due to the number of significant
figures displayed.

Change-Id: I6247a00ce84c7d2012cde692e24b717a174c2752
parent dd403de2
......@@ -24,6 +24,7 @@ vtk_add_test_cxx(
TestLegendHiddenPlots.cxx
TestLinePlot.cxx,-E25
TestLinePlotDouble.cxx
TestLinePlotDouble2.cxx
TestLinePlot3D.cxx
TestLinePlotAxisFonts.cxx
TestLinePlot2.cxx,-E25
......
......@@ -14,7 +14,6 @@
=========================================================================*/
#include "vtkRenderWindow.h"
#include "vtkSmartPointer.h"
#include "vtkChartXY.h"
#include "vtkPlot.h"
#include "vtkTable.h"
......@@ -23,8 +22,6 @@
#include "vtkContextScene.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkNew.h"
#include "vtkAxis.h"
#include "vtkMath.h"
//----------------------------------------------------------------------------
......@@ -77,17 +74,10 @@ int TestLinePlotDouble(int, char *[])
line->SetColor(0, 0, 255, 255);
line->SetWidth(4.0);
double bounds[4];
// Render the scene and compare the image to a reference image
view->GetRenderWindow()->SetMultiSamples(0);
view->GetInteractor()->Initialize();
view->GetInteractor()->Start();
line->GetUnscaledInputBounds(bounds);
cout << chart->GetAxis(vtkAxis::LEFT)->GetMinimum() << " -> "
<< chart->GetAxis(vtkAxis::LEFT)->GetMaximum() << endl;
return EXIT_SUCCESS;
}
/*=========================================================================
Program: Visualization Toolkit
Module: TestLinePlotDouble2.cxx
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 "vtkRenderWindow.h"
#include "vtkChartXY.h"
#include "vtkPlot.h"
#include "vtkTable.h"
#include "vtkDoubleArray.h"
#include "vtkContextView.h"
#include "vtkContextScene.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkNew.h"
//----------------------------------------------------------------------------
int TestLinePlotDouble2(int, char *[])
{
// Set up a 2D scene, add an XY chart to it
vtkNew<vtkContextView> view;
view->GetRenderWindow()->SetSize(400, 300);
vtkNew<vtkChartXY> chart;
view->GetScene()->AddItem(chart.GetPointer());
// Create a table with some points in it...
vtkNew<vtkTable> table;
vtkNew<vtkDoubleArray> arrX;
arrX->SetName("X");
table->AddColumn(arrX.GetPointer());
vtkNew<vtkDoubleArray> arrC;
arrC->SetName("Cosine");
table->AddColumn(arrC.GetPointer());
// Test charting some very small points.
int numPoints = 69;
float inc = 7.5 / (numPoints - 1);
table->SetNumberOfRows(numPoints);
for (int i = 0; i < numPoints; ++i)
{
double x(1 + 1e-11 * inc * i);
table->SetValue(i, 0, x);
table->SetValue(i, 1, cos((x - 1.0) * 1.0e11));
}
vtkPlot *line = chart->AddPlot(vtkChart::LINE);
line->SetInputData(table.GetPointer(), 0, 1);
// Render the scene and compare the image to a reference image
view->GetRenderWindow()->SetMultiSamples(0);
view->GetInteractor()->Initialize();
view->GetInteractor()->Start();
return EXIT_SUCCESS;
}
......@@ -82,6 +82,7 @@ vtkAxis::vtkAxis()
this->Pen = vtkPen::New();
this->TitleAppended = false;
this->ScalingFactor = 1.0;
this->Shift = 0.0;
this->Pen->SetColor(0, 0, 0);
this->Pen->SetWidth(1.0);
......@@ -1343,7 +1344,7 @@ double vtkAxis::NiceMinMax(double &min, double &max, float pixelRange,
max *= 1.05;
}
}
else if ((max - min) < 1.0e-20)
else if ((max - min) < 1.0e-60)
{
min *= 0.95;
max *= 1.05;
......
......@@ -337,6 +337,8 @@ public:
// scaling), and is used to coordinate scaling with the plots, charts, etc.
vtkSetMacro(ScalingFactor, double)
vtkGetMacro(ScalingFactor, double)
vtkSetMacro(Shift, double)
vtkGetMacro(Shift, double)
// Description:
// Update the geometry of the axis. Takes care of setting up the tick mark
......@@ -516,6 +518,7 @@ protected:
// small/large numbers accurately by converting the underlying range by the
// scaling factor.
double ScalingFactor;
double Shift;
// Description:
// Are we using custom tick labels, or should the axis generate them?
......
......@@ -219,12 +219,19 @@ bool vtkChart::CalculatePlotTransform(vtkAxis *x, vtkAxis *y,
return false;
}
vtkVector2d origin(x->GetMinimum(), y->GetMinimum());
vtkVector2d scale(x->GetMaximum() - x->GetMinimum(),
y->GetMaximum() - y->GetMinimum());
vtkVector2d shift(0.0, 0.0);
vtkVector2d factor(1.0, 1.0);
for (int i = 0; i < 2; ++i)
{
if (fabs(log10(origin[i] / scale[i])) > 2)
{
shift[i] = floor(log10(origin[i] / scale[i]) / 3.0) * 3.0;
shift[i] = -origin[i];
}
if (fabs(log10(scale[i])) > 10)
{
// We need to scale the transform to show all data, do this in blocks.
......@@ -233,12 +240,14 @@ bool vtkChart::CalculatePlotTransform(vtkAxis *x, vtkAxis *y,
}
}
x->SetScalingFactor(factor[0]);
x->SetShift(shift[0]);
y->SetScalingFactor(factor[1]);
y->SetShift(shift[1]);
// Get the scale for the plot area from the x and y axes
float *min = x->GetPoint1();
float *max = x->GetPoint2();
if (fabs(max[0] - min[0]) == 0.0f)
if (fabs(max[0] - min[0]) == 0.0)
{
return false;
}
......@@ -247,7 +256,7 @@ bool vtkChart::CalculatePlotTransform(vtkAxis *x, vtkAxis *y,
// Now the y axis
min = y->GetPoint1();
max = y->GetPoint2();
if (fabs(max[1] - min[1]) == 0.0f)
if (fabs(max[1] - min[1]) == 0.0)
{
return false;
}
......@@ -257,8 +266,8 @@ bool vtkChart::CalculatePlotTransform(vtkAxis *x, vtkAxis *y,
transform->Translate(this->Point1[0], this->Point1[1]);
// Get the scale for the plot area from the x and y axes
transform->Scale(1.0 / xScale, 1.0 / yScale);
transform->Translate(-x->GetMinimum() * factor[0],
-y->GetMinimum() * factor[1]);
transform->Translate(-(x->GetMinimum() + shift[0]) * factor[0],
-(y->GetMinimum() + shift[1]) * factor[1]);
return true;
}
......
......@@ -496,7 +496,8 @@ void vtkChartXY::RecalculatePlotTransforms()
xAxis, yAxis, this->ChartPrivate->PlotCorners[i]->GetTransform());
// Now we need to set the scale factor on the plots to ensure they rescale
// their input data when necessary.
vtkVector2d factor(xAxis->GetScalingFactor(), yAxis->GetScalingFactor());
vtkRectd shiftScale(xAxis->GetShift(), yAxis->GetShift(),
xAxis->GetScalingFactor(), yAxis->GetScalingFactor());
for (unsigned int j = 0;
j < this->ChartPrivate->PlotCorners[i]->GetNumberOfItems(); ++j)
{
......@@ -504,7 +505,7 @@ void vtkChartXY::RecalculatePlotTransforms()
vtkPlot::SafeDownCast(this->ChartPrivate->PlotCorners[i]->GetItem(j));
if (plot)
{
plot->SetScalingFactor(factor);
plot->SetShiftScale(shiftScale);
}
}
}
......
......@@ -32,7 +32,7 @@ vtkCxxSetObjectMacro(vtkPlot, XAxis, vtkAxis);
vtkCxxSetObjectMacro(vtkPlot, YAxis, vtkAxis);
//-----------------------------------------------------------------------------
vtkPlot::vtkPlot() : ScalingFactor(1.0, 1.0)
vtkPlot::vtkPlot() : ShiftScale(0.0, 0.0, 1.0, 1.0)
{
this->Pen = vtkSmartPointer<vtkPen>::New();
this->Pen->SetWidth(2.0);
......@@ -449,19 +449,19 @@ void vtkPlot::SetInputArray(int index, const vtkStdString &name)
}
//-----------------------------------------------------------------------------
void vtkPlot::SetScalingFactor(const vtkVector2d &scaling)
void vtkPlot::SetShiftScale(const vtkRectd &shiftScale)
{
if (scaling != this->ScalingFactor)
if (shiftScale != this->ShiftScale)
{
this->Modified();
this->ScalingFactor = scaling;
this->ShiftScale = shiftScale;
}
}
//-----------------------------------------------------------------------------
vtkVector2d vtkPlot::GetScalingFactor()
vtkRectd vtkPlot::GetShiftScale()
{
return this->ScalingFactor;
return this->ShiftScale;
}
//-----------------------------------------------------------------------------
......
......@@ -29,6 +29,7 @@
#include "vtkStdString.h" // Needed to hold TooltipLabelFormat ivar
#include "vtkSmartPointer.h" // Needed to hold SP ivars
#include "vtkContextPolygon.h" // For vtkContextPolygon
#include "vtkRect.h" // For vtkRectd ivar
class vtkVariant;
class vtkTable;
......@@ -37,8 +38,6 @@ class vtkContextMapper2D;
class vtkPen;
class vtkBrush;
class vtkAxis;
class vtkVector2f;
class vtkRectf;
class vtkStringArray;
class VTKCHARTSCORE_EXPORT vtkPlot : public vtkContextItem
......@@ -213,12 +212,12 @@ public:
virtual void SetYAxis(vtkAxis* axis);
// Description:
// Get/set the scaling factor used by the plot, this is normally 1.0 but can
// be used to render data outside of the single precision range. The chart
// that owns the plot should set this and ensure the appropriate matrix is
// used when rendering the plot.
void SetScalingFactor(const vtkVector2d &scaling);
vtkVector2d GetScalingFactor();
// Get/set the origin shift and scaling factor used by the plot, this is
// normally 0.0 offset and 1.0 scaling, but can be used to render data outside
// of the single precision range. The chart that owns the plot should set this
// and ensure the appropriate matrix is used when rendering the plot.
void SetShiftScale(const vtkRectd &scaling);
vtkRectd GetShiftScale();
// Description:
// Get the bounds for this plot as (Xmin, Xmax, Ymin, Ymax).
......@@ -330,9 +329,8 @@ protected:
int TooltipPrecision;
// Description:
// The current scaling factor applied to the input data, used to render
// beyond single precision in the charts.
vtkVector2d ScalingFactor;
// The current shift in origin and scaling factor applied to the plot.
vtkRectd ShiftScale;
private:
vtkPlot(const vtkPlot &); // Not implemented.
......
......@@ -47,7 +47,7 @@ namespace {
// Copy the two arrays into the points array
template<class A, class B>
void CopyToPoints(vtkPoints2D *points, vtkPoints2D *previousPoints, A *a, B *b,
int n, int logScale, const vtkVector2d &scale)
int n, int logScale, const vtkRectd &ss)
{
points->SetNumberOfPoints(n);
float* data = static_cast<float*>(points->GetVoidPointer(0));
......@@ -63,8 +63,8 @@ void CopyToPoints(vtkPoints2D *points, vtkPoints2D *previousPoints, A *a, B *b,
{
prev = prevData[2 * i + 1];
}
A tmpA(a[i] * scale[0]);
B tmpB(b[i] * scale[1]);
A tmpA((a[i] + ss[0]) * ss[2]);
B tmpB((b[i] + ss[1]) * ss[3]);
data[2 * i] = static_cast<float>((logScale & 1) ?
log10(static_cast<double>(tmpA))
: tmpA);
......@@ -77,7 +77,7 @@ void CopyToPoints(vtkPoints2D *points, vtkPoints2D *previousPoints, A *a, B *b,
// Copy one array into the points array, use the index of that array as x
template<class A>
void CopyToPoints(vtkPoints2D *points, vtkPoints2D *previousPoints, A *a, int n,
int logScale, const vtkVector2d &scale)
int logScale, const vtkRectd &ss)
{
points->SetNumberOfPoints(n);
float* data = static_cast<float*>(points->GetVoidPointer(0));
......@@ -93,7 +93,7 @@ void CopyToPoints(vtkPoints2D *points, vtkPoints2D *previousPoints, A *a, int n,
{
prev = prevData[2 * i + 1];
}
A tmpA(a[i] * scale[1]);
A tmpA((a[i] + ss[1]) * ss[3]);
data[2 * i] = static_cast<float>((logScale & 1) ?
log10(static_cast<double>(i + 1.0))
: i);
......@@ -107,14 +107,14 @@ void CopyToPoints(vtkPoints2D *points, vtkPoints2D *previousPoints, A *a, int n,
template<class A>
void CopyToPointsSwitch(vtkPoints2D *points, vtkPoints2D *previousPoints, A *a,
vtkDataArray *b, int n, int logScale,
const vtkVector2d &scale)
const vtkRectd &ss)
{
switch(b->GetDataType())
{
vtkTemplateMacro(
CopyToPoints(points,previousPoints, a,
static_cast<VTK_TT*>(b->GetVoidPointer(0)), n, logScale,
scale));
ss));
}
}
......@@ -203,7 +203,7 @@ class vtkPlotBarSegment : public vtkObject {
CopyToPointsSwitch(this->Points,this->Previous ? this->Previous->Points : 0,
static_cast<VTK_TT*>(xArray->GetVoidPointer(0)),
yArray, xArray->GetNumberOfTuples(), logScale,
this->Bar->GetScalingFactor()));
this->Bar->GetShiftScale()));
}
}
else
......@@ -214,7 +214,7 @@ class vtkPlotBarSegment : public vtkObject {
CopyToPoints(this->Points, this->Previous ? this->Previous->Points : 0,
static_cast<VTK_TT*>(yArray->GetVoidPointer(0)),
yArray->GetNumberOfTuples(), logScale,
this->Bar->GetScalingFactor()));
this->Bar->GetShiftScale()));
}
}
}
......
......@@ -594,41 +594,40 @@ void ComputeBounds(A *a, vtkDataArray *b, int n, vtkIdTypeArray *bad,
// Copy the two arrays into the points array
template<typename A, typename B>
void CopyToPoints(vtkPoints2D *points, A *a, B *b, int n,
const vtkVector2d &scale)
void CopyToPoints(vtkPoints2D *points, A *a, B *b, int n, const vtkRectd &ss)
{
points->SetNumberOfPoints(n);
float* data = static_cast<float*>(points->GetVoidPointer(0));
for (int i = 0; i < n; ++i)
{
data[2 * i] = static_cast<float>(a[i] * scale[0]);
data[2 * i + 1] = static_cast<float>(b[i] * scale[1]);
data[2 * i] = static_cast<float>((a[i] + ss[0]) * ss[2]);
data[2 * i + 1] = static_cast<float>((b[i] + ss[1]) * ss[3]);
}
}
// Copy one array into the points array, use the index of that array as x
template<typename A>
void CopyToPoints(vtkPoints2D *points, A *a, int n, const vtkVector2d &scale)
void CopyToPoints(vtkPoints2D *points, A *a, int n, const vtkRectd &ss)
{
points->SetNumberOfPoints(n);
float* data = static_cast<float*>(points->GetVoidPointer(0));
for (int i = 0; i < n; ++i)
{
data[2 * i] = static_cast<float>( i * scale[0]);
data[2 * i + 1] = static_cast<float>(a[i] * scale[1]);
data[2 * i] = static_cast<float>(( i + ss[0]) * ss[2]);
data[2 * i + 1] = static_cast<float>((a[i] + ss[1]) * ss[3]);
}
}
// Copy the two arrays into the points array
template<typename A>
void CopyToPointsSwitch(
vtkPoints2D *points, A *a, vtkDataArray *b, int n, const vtkVector2d &scale)
void CopyToPointsSwitch(vtkPoints2D *points, A *a, vtkDataArray *b, int n,
const vtkRectd &ss)
{
switch(b->GetDataType())
{
vtkTemplateMacro(
CopyToPoints(
points, a, static_cast<VTK_TT*>(b->GetVoidPointer(0)), n, scale));
points, a, static_cast<VTK_TT*>(b->GetVoidPointer(0)), n, ss));
}
}
......@@ -693,7 +692,7 @@ bool vtkPlotPoints::UpdateTableCache(vtkTable *table)
vtkTemplateMacro(
CopyToPoints(
this->Points, static_cast<VTK_TT*>(y->GetVoidPointer(0)),
y->GetNumberOfTuples(), this->ScalingFactor));
y->GetNumberOfTuples(), this->ShiftScale));
}
}
else
......@@ -703,7 +702,7 @@ bool vtkPlotPoints::UpdateTableCache(vtkTable *table)
vtkTemplateMacro(
CopyToPointsSwitch(
this->Points, static_cast<VTK_TT*>(x->GetVoidPointer(0)),
y, x->GetNumberOfTuples(), this->ScalingFactor));
y, x->GetNumberOfTuples(), this->ShiftScale));
}
}
this->CalculateLogSeries();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment