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

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