Commit 6f8f8037 authored by David Thompson's avatar David Thompson

Provide information on plot input data range.

This commit provides an interface for querying the
range of values taken on by a vtkPlot's X- and Y-axis
inputs.

This can be used to determine whether log-scaling
is appropriate for each axis of the plot. It is part
of a fix to ParaView bug 13899.

Change-Id: Ia0449ca496dd935fb4ca25dc5dd2b691d2f89d93
parent cdde4af4
......@@ -27,6 +27,7 @@
//----------------------------------------------------------------------------
int TestLinePlot( int, char * [] )
{
int status = EXIT_SUCCESS;
// Set up a 2D scene, add an XY chart to it
vtkNew<vtkContextView> view;
view->GetRenderWindow()->SetSize(400, 300);
......@@ -47,6 +48,9 @@ int TestLinePlot( int, char * [] )
vtkNew<vtkFloatArray> arrS2;
arrS2->SetName("Sine2");
table->AddColumn(arrS2.GetPointer());
vtkNew<vtkFloatArray> arr1;
arr1->SetName("One");
table->AddColumn(arr1.GetPointer());
// Test charting with a few more points...
int numPoints = 69;
float inc = 7.5 / (numPoints-1);
......@@ -57,6 +61,7 @@ int TestLinePlot( int, char * [] )
table->SetValue(i, 1, cos(i * inc) + 0.0);
table->SetValue(i, 2, sin(i * inc) + 0.0);
table->SetValue(i, 3, sin(i * inc) + 0.5);
table->SetValue(i, 4, 1.0);
}
// Add multiple line plots, setting the colors etc
......@@ -73,9 +78,33 @@ int TestLinePlot( int, char * [] )
line->SetColor(0, 0, 255, 255);
line->SetWidth(4.0);
//Finally render the scene and compare the image to a reference image
// Render the scene and compare the image to a reference image
view->GetRenderWindow()->SetMultiSamples(0);
view->GetInteractor()->Initialize();
view->GetInteractor()->Start();
return EXIT_SUCCESS;
// Verify that log-scaling is improper for both x & y axes
double bds[4];
line->GetUnscaledInputBounds(bds);
if (bds[0] * bds[1] > 0. || bds[2] * bds[3] > 0.)
{
cerr
<< "ERROR: Data on both X and Y axes expected to cross origin.\n";
status = EXIT_FAILURE;
}
// Verify that log-scaling is proper for arr1 y axis (which
// is not plotted so as to avoid changing baseline images).
line = chart->AddPlot(vtkChart::LINE);
line->SetInputData(table.GetPointer(), 0, 4);
line->Update();
line->GetUnscaledInputBounds(bds);
if (bds[0] * bds[1] > 0. || bds[2] * bds[3] <= 0.)
{
cerr
<< "ERROR: Data on X axis expected to cross origin.\n";
status = EXIT_FAILURE;
}
return status;
}
......@@ -214,9 +214,41 @@ public:
// Description:
// Get the bounds for this plot as (Xmin, Xmax, Ymin, Ymax).
//
// See \a GetUnscaledInputBounds for more information.
virtual void GetBounds(double bounds[4])
{ bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0; }
// Description:
// Provide un-log-scaled bounds for the plot inputs.
//
// This function is analogous to GetBounds() with 2 exceptions:
// 1. It will never return log-scaled bounds even when the
// x- and/or y-axes are log-scaled.
// 2. It will always return the bounds along the *input* axes
// rather than the output chart coordinates. Thus GetXAxis()
// returns the axis associated with the first 2 bounds entries
// and GetYAxis() returns the axis associated with the next 2
// bounds entries.
//
// For example, vtkPlotBar's GetBounds() method
// will swap axis bounds when its orientation is vertical while
// its GetUnscaledInputBounds() will not swap axis bounds.
//
// This method is provided so user interfaces can determine
// whether or not to allow log-scaling of a particular vtkAxis.
//
// Subclasses of vtkPlot are responsible for implementing this
// function to transform input plot data.
//
// The returned \a bounds are stored as (Xmin, Xmax, Ymin, Ymax).
virtual void GetUnscaledInputBounds(double bounds[4])
{
// Implemented here by calling GetBounds() to support plot
// subclasses that do no log-scaling or plot orientation.
return this->GetBounds(bounds);
}
//BTX
// Description:
// A General setter/getter that should be overridden. It can silently drop
......
......@@ -581,10 +581,11 @@ bool vtkPlotBar::PaintLegend(vtkContext2D *painter, const vtkRectf& rect,
}
//-----------------------------------------------------------------------------
void vtkPlotBar::GetBounds(double bounds[4])
void vtkPlotBar::GetBounds(double bounds[4], bool unscaled)
{
int seriesLow, seriesHigh, valuesLow, valuesHigh;
if (this->Orientation == vtkPlotBar::VERTICAL)
// Don't re-orient the axes for vertical plots or unscaled bounds:
if (this->Orientation == vtkPlotBar::VERTICAL || unscaled)
{
seriesLow = 0; // Xmin
seriesHigh = 1; // Xmax
......@@ -647,10 +648,39 @@ void vtkPlotBar::GetBounds(double bounds[4])
{
bounds[valuesHigh] = 0.0;
}
if (unscaled)
{
vtkAxis* axes[2];
axes[seriesLow / 2] = this->GetXAxis();
axes[valuesLow / 2] = this->GetYAxis();
if (axes[0]->GetLogScaleActive())
{
bounds[0] = log10(fabs(bounds[0]));
bounds[1] = log10(fabs(bounds[1]));
}
if (axes[1]->GetLogScaleActive())
{
bounds[2] = log10(fabs(bounds[2]));
bounds[3] = log10(fabs(bounds[3]));
}
}
vtkDebugMacro(<< "Bounds: " << bounds[0] << "\t" << bounds[1] << "\t"
<< bounds[2] << "\t" << bounds[3]);
}
//-----------------------------------------------------------------------------
void vtkPlotBar::GetBounds(double bounds[4])
{
this->GetBounds(bounds, false);
}
//-----------------------------------------------------------------------------
void vtkPlotBar::GetUnscaledInputBounds(double bounds[4])
{
this->GetBounds(bounds, true);
}
//-----------------------------------------------------------------------------
void vtkPlotBar::SetOrientation(int orientation)
{
......
......@@ -92,10 +92,18 @@ public:
virtual void SetOrientation(int orientation);
vtkGetMacro(Orientation, int);
// Description:
// A helper used by both GetUnscaledBounds and GetBounds(double[4]).
virtual void GetBounds(double bounds[4], bool unscaled);
// Description:
// Get the bounds for this mapper as (Xmin,Xmax,Ymin,Ymax).
virtual void GetBounds(double bounds[4]);
// Description:
// Get un-log-scaled bounds for this mapper as (Xmin,Xmax,Ymin,Ymax).
virtual void GetUnscaledInputBounds(double bounds[4]);
// Description:
// When used to set additional arrays, stacked bars are created.
virtual void SetInputArray(int index, const vtkStdString &name);
......
......@@ -75,6 +75,9 @@ vtkPlotPoints::vtkPlotPoints()
this->LookupTable = 0;
this->Colors = 0;
this->ScalarVisibility = 0;
this->UnscaledInputBounds[0] = this->UnscaledInputBounds[2] = vtkMath::Inf();
this->UnscaledInputBounds[1] = this->UnscaledInputBounds[3] = -vtkMath::Inf();
}
//-----------------------------------------------------------------------------
......@@ -254,6 +257,18 @@ void vtkPlotPoints::GetBounds(double bounds[4])
<< bounds[2] << "\t" << bounds[3]);
}
//-----------------------------------------------------------------------------
void vtkPlotPoints::GetUnscaledInputBounds(double bounds[4])
{
for (int i = 0; i < 4; ++i)
{
bounds[i] = this->UnscaledInputBounds[i];
}
vtkDebugMacro(
<< "Bounds: " << bounds[0] << "\t" << bounds[1] << "\t"
<< bounds[2] << "\t" << bounds[3]);
}
namespace
{
......@@ -436,38 +451,53 @@ namespace {
// Copy the two arrays into the points array
template<class A, class B>
void CopyToPoints(vtkPoints2D *points, A *a, B *b, int n)
void CopyToPoints(vtkPoints2D *points, A *a, B *b, int n, double bds[4])
{
bds[0] = bds[2] = vtkMath::Inf();
bds[1] = bds[3] = -vtkMath::Inf();
points->SetNumberOfPoints(n);
float* data = static_cast<float*>(points->GetVoidPointer(0));
for (int i = 0; i < n; ++i)
{
data[2*i] = a[i];
data[2*i+1] = b[i];
bds[0] = bds[0] < a[i] ? bds[0] : a[i];
bds[1] = bds[1] > a[i] ? bds[1] : a[i];
bds[2] = bds[2] < b[i] ? bds[2] : b[i];
bds[3] = bds[3] > b[i] ? bds[3] : b[i];
}
}
// Copy one array into the points array, use the index of that array as x
template<class A>
void CopyToPoints(vtkPoints2D *points, A *a, int n)
void CopyToPoints(vtkPoints2D *points, A *a, int n, double bds[4])
{
bds[0] = 0.;
bds[1] = n - 1.;
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);
data[2*i+1] = a[i];
bds[2] = bds[2] < a[i] ? bds[2] : a[i];
bds[3] = bds[3] > a[i] ? bds[3] : a[i];
}
}
// Copy the two arrays into the points array
template<class A>
void CopyToPointsSwitch(vtkPoints2D *points, A *a, vtkDataArray *b, int n)
void CopyToPointsSwitch(
vtkPoints2D *points, A *a, vtkDataArray *b, int n, double bds[4])
{
switch(b->GetDataType())
{
vtkTemplateMacro(
CopyToPoints(points, a, static_cast<VTK_TT*>(b->GetVoidPointer(0)), n));
CopyToPoints(
points, a, static_cast<VTK_TT*>(b->GetVoidPointer(0)), n, bds));
}
}
......@@ -512,10 +542,10 @@ bool vtkPlotPoints::UpdateTableCache(vtkTable *table)
{
switch(y->GetDataType())
{
vtkTemplateMacro(
CopyToPoints(this->Points,
static_cast<VTK_TT*>(y->GetVoidPointer(0)),
y->GetNumberOfTuples()));
vtkTemplateMacro(
CopyToPoints(
this->Points, static_cast<VTK_TT*>(y->GetVoidPointer(0)),
y->GetNumberOfTuples(), this->UnscaledInputBounds));
}
}
else
......@@ -523,9 +553,9 @@ bool vtkPlotPoints::UpdateTableCache(vtkTable *table)
switch(x->GetDataType())
{
vtkTemplateMacro(
CopyToPointsSwitch(this->Points,
static_cast<VTK_TT*>(x->GetVoidPointer(0)),
y, x->GetNumberOfTuples()));
CopyToPointsSwitch(
this->Points, static_cast<VTK_TT*>(x->GetVoidPointer(0)),
y, x->GetNumberOfTuples(), this->UnscaledInputBounds));
}
}
this->CalculateLogSeries();
......
......@@ -75,6 +75,10 @@ public:
// Get the bounds for this plot as (Xmin, Xmax, Ymin, Ymax).
virtual void GetBounds(double bounds[4]);
// Description:
// Get the non-log-scaled bounds on chart inputs for this plot as (Xmin, Xmax, Ymin, Ymax).
virtual void GetUnscaledInputBounds(double bounds[4]);
// Description:
// Specify a lookup table for the mapper to use.
void SetLookupTable(vtkScalarsToColors *lut);
......@@ -204,6 +208,10 @@ protected:
int ScalarVisibility;
vtkStdString ColorArrayName;
// Description:
// Cached bounds on the plot input axes
double UnscaledInputBounds[4];
private:
vtkPlotPoints(const vtkPlotPoints &); // Not implemented.
void operator=(const vtkPlotPoints &); // Not implemented.
......
......@@ -57,7 +57,7 @@ bool compVector2fX(const vtkVector2f& v1, const vtkVector2f& v2)
// Copy the two arrays into the points array
template<class A, class B>
void CopyToPoints(vtkPoints2D *points, vtkPoints2D *previous_points, A *a, B *b,
int n)
int n, double bds[4])
{
points->SetNumberOfPoints(n);
for (int i = 0; i < n; ++i)
......@@ -65,34 +65,48 @@ void CopyToPoints(vtkPoints2D *points, vtkPoints2D *previous_points, A *a, B *b,
double prev[] = {0.0,0.0};
if (previous_points)
previous_points->GetPoint(i,prev);
points->SetPoint(i, a[i], b[i] + prev[1]);
double yi = b[i] + prev[1];
points->SetPoint(i, a[i], yi);
bds[0] = bds[0] < a[i] ? bds[0] : a[i];
bds[1] = bds[1] > a[i] ? bds[1] : a[i];
bds[2] = bds[2] < yi ? bds[2] : yi;
bds[3] = bds[3] > yi ? bds[3] : yi;
}
}
// Copy one array into the points array, use the index of that array as x
template<class A>
void CopyToPoints(vtkPoints2D *points, vtkPoints2D *previous_points, A *a, int n)
void CopyToPoints(
vtkPoints2D *points, vtkPoints2D *previous_points, A *a, int n, double bds[4])
{
bds[0] = 0.;
bds[1] = n - 1.;
points->SetNumberOfPoints(n);
for (int i = 0; i < n; ++i)
{
double prev[] = {0.0,0.0};
if (previous_points)
previous_points->GetPoint(i,prev);
points->SetPoint(i, i, a[i] + prev[1]);
double yi = a[i] + prev[1];
points->SetPoint(i, i, yi);
bds[2] = bds[2] < yi ? bds[2] : yi;
bds[3] = bds[3] > yi ? bds[3] : yi;
}
}
// Copy the two arrays into the points array
template<class A>
void CopyToPointsSwitch(vtkPoints2D *points, vtkPoints2D *previous_points, A *a,
vtkDataArray *b, int n)
vtkDataArray *b, int n, double bds[4])
{
switch(b->GetDataType())
{
vtkTemplateMacro(
CopyToPoints(points,previous_points, a,
static_cast<VTK_TT*>(b->GetVoidPointer(0)), n));
static_cast<VTK_TT*>(b->GetVoidPointer(0)), n, bds));
}
}
......@@ -112,7 +126,10 @@ class vtkPlotStackedSegment : public vtkObject {
this->Sorted = false;
}
void Configure(vtkPlotStacked *stacked,vtkDataArray *x_array, vtkDataArray *y_array,vtkPlotStackedSegment *prev)
void Configure(
vtkPlotStacked *stacked, vtkDataArray *x_array,
vtkDataArray *y_array,vtkPlotStackedSegment *prev,
double bds[4])
{
this->Stacked = stacked;
this->Sorted = false;
......@@ -130,7 +147,7 @@ class vtkPlotStackedSegment : public vtkObject {
vtkTemplateMacro(
CopyToPointsSwitch(this->Points,this->Previous ? this->Previous->Points : 0,
static_cast<VTK_TT*>(x_array->GetVoidPointer(0)),
y_array,x_array->GetNumberOfTuples()));
y_array,x_array->GetNumberOfTuples(), bds));
}
}
else
......@@ -140,7 +157,7 @@ class vtkPlotStackedSegment : public vtkObject {
vtkTemplateMacro(
CopyToPoints(this->Points, this->Previous ? this->Previous->Points : 0,
static_cast<VTK_TT*>(y_array->GetVoidPointer(0)),
y_array->GetNumberOfTuples()));
y_array->GetNumberOfTuples(), bds));
}
}
......@@ -449,12 +466,14 @@ class vtkPlotStackedPrivate {
void Update()
{
this->Segments.clear();
this->UnscaledInputBounds[0] = this->UnscaledInputBounds[2] = vtkMath::Inf();
this->UnscaledInputBounds[1] = this->UnscaledInputBounds[3] = -vtkMath::Inf();
}
vtkPlotStackedSegment *AddSegment(vtkDataArray *x_array, vtkDataArray *y_array, vtkPlotStackedSegment *prev=0)
{
vtkSmartPointer<vtkPlotStackedSegment> segment = vtkSmartPointer<vtkPlotStackedSegment>::New();
segment->Configure(this->Stacked,x_array,y_array,prev);
segment->Configure(this->Stacked,x_array,y_array,prev,this->UnscaledInputBounds);
this->Segments.push_back(segment);
return segment;
}
......@@ -536,6 +555,7 @@ class vtkPlotStackedPrivate {
std::vector<vtkSmartPointer<vtkPlotStackedSegment> > Segments;
vtkPlotStacked *Stacked;
std::map<int,std::string> AdditionalSeries;
double UnscaledInputBounds[4];
};
//-----------------------------------------------------------------------------
......@@ -682,6 +702,15 @@ void vtkPlotStacked::GetBounds(double bounds[4])
this->Private->GetBounds(bounds);
}
//-----------------------------------------------------------------------------
void vtkPlotStacked::GetUnscaledInputBounds(double bounds[4])
{
for (int i = 0; i < 4; ++i)
{
bounds[i] = this->Private->UnscaledInputBounds[i];
}
}
//-----------------------------------------------------------------------------
vtkIdType vtkPlotStacked::GetNearestPoint(const vtkVector2f& point,
const vtkVector2f& tol,
......
......@@ -71,9 +71,14 @@ public:
int legendIndex);
// Description:
// Get the bounds for this mapper as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax).
// Get the bounds for this mapper as (Xmin,Xmax,Ymin,Ymax).
virtual void GetBounds(double bounds[4]);
// Description:
// Get the unscaled input bounds for this mapper as (Xmin,Xmax,Ymin,Ymax).
// See vtkPlot for more information.
virtual void GetUnscaledInputBounds(double bounds[4]);
// Description:
// When used to set additional arrays, stacked bars are created.
virtual void SetInputArray(int index, const vtkStdString &name);
......
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