Commit a1ae3ed4 authored by Dave Partyka's avatar Dave Partyka
Browse files

BUG: merge in major refactoring from Marcus.

parent 1cbd293a
......@@ -19,6 +19,7 @@
#include "vtkPen.h"
#include "vtkTextProperty.h"
#include "vtkFloatArray.h"
#include "vtkDoubleArray.h"
#include "vtkStringArray.h"
#include "vtkStdString.h"
#include "vtksys/ios/sstream"
......@@ -28,7 +29,7 @@
#include "math.h"
//-----------------------------------------------------------------------------
vtkCxxRevisionMacro(vtkAxis, "1.20.4.2");
vtkCxxRevisionMacro(vtkAxis, "1.20.4.3");
//-----------------------------------------------------------------------------
vtkStandardNewMacro(vtkAxis);
......@@ -69,8 +70,11 @@ vtkAxis::vtkAxis()
this->GridPen = vtkPen::New();
this->GridPen->SetColor(242, 242, 242);
this->GridPen->SetWidth(1.0);
this->TickPositions = vtkFloatArray::New();
this->TickLabels = vtkStringArray::New();
this->TickPositions = vtkSmartPointer<vtkDoubleArray>::New();
this->TickScenePositions = vtkSmartPointer<vtkFloatArray>::New();
this->TickLabels = vtkSmartPointer<vtkStringArray>::New();
this->UsingNiceMinMax = false;
this->TickMarksDirty = true;
}
//-----------------------------------------------------------------------------
......@@ -79,10 +83,6 @@ vtkAxis::~vtkAxis()
this->SetTitle(NULL);
this->TitleProperties->Delete();
this->LabelProperties->Delete();
this->TickPositions->Delete();
this->TickPositions = NULL;
this->TickLabels->Delete();
this->TickLabels = NULL;
this->Pen->Delete();
this->GridPen->Delete();
}
......@@ -95,34 +95,27 @@ void vtkAxis::Update()
return;
}
this->TickPositions->SetNumberOfTuples(0);
this->TickLabels->SetNumberOfTuples(0);
// Figure out what type of behavior we should follow
if (this->Behavior < 2)
if (this->Behavior == 1)
{
this->RecalculateTickSpacing();
}
// Calculate where the first tick mark should be drawn
double tick = ceil(this->Minimum / this->TickInterval) * this->TickInterval;
int n = (this->Maximum - this->Minimum) / this->TickInterval;
// If there will be more than 500 tick marks it is likely a rounding issue
// with a small range.
if (n > 500)
{
vtkWarningMacro("A large number of tick marks was calculated (" << n
<< "). This is likely an error.")
return;
}
// If this check is not used, and the first tick is at 0.0 then it has the
// negative sign bit set. This check gets rid of the negative bit but is quite
// possibly not the best way of doing it...
if (tick == 0.0f)
if (this->Behavior < 2 && this->TickMarksDirty)
{
tick = 0.0f;
// Regenerate the tick marks/positions if necessary
// Calculate where the first tick mark should be drawn
double first = ceil(this->Minimum / this->TickInterval) * this->TickInterval;
double last = first;
for (int i = 0; i < 500; ++i)
{
last += this->TickInterval;
if (last > this->Maximum)
{
this->GenerateTickLabels(first, last-this->TickInterval);
break;
}
}
}
double scaling = 0.0;
......@@ -140,40 +133,25 @@ void vtkAxis::Update()
origin = this->Point1[0];
}
while (tick <= this->Maximum)
if (this->TickPositions->GetNumberOfTuples() !=
this->TickLabels->GetNumberOfTuples())
{
// Calculate the next tick mark position
int iTick = static_cast<int>(origin + (tick - this->Minimum) * scaling);
this->TickPositions->InsertNextValue(iTick);
// Make a tick mark label for the tick
double value = tick;
if (this->LogScale)
{
value = pow(double(10.0), double(tick));
}
vtksys_ios::ostringstream ostr;
ostr.imbue(vtkstd::locale::classic());
if (this->Notation > 0)
{
ostr.precision(this->Precision);
}
if (this->Notation == 1)
{
// Scientific notation
ostr.setf(vtksys_ios::ios::scientific, vtksys_ios::ios::floatfield);
}
else if (this->Notation == 2)
{
ostr.setf(ios::fixed, ios::floatfield);
}
ostr << value;
this->TickLabels->InsertNextValue(ostr.str());
vtkWarningMacro("The number of tick positions is not the same as the number "
<< "of tick labels - error.");
this->TickScenePositions->SetNumberOfTuples(0);
return;
}
tick += this->TickInterval;
vtkIdType n = this->TickPositions->GetNumberOfTuples();
this->TickScenePositions->SetNumberOfTuples(n);
for (vtkIdType i = 0; i < n; ++i)
{
int iPos = static_cast<int>(origin +
(this->TickPositions->GetValue(i) -
this->Minimum) * scaling);
this->TickScenePositions->InsertValue(i, iPos);
}
this->BuildTime.Modified();
}
......@@ -196,7 +174,7 @@ bool vtkAxis::Paint(vtkContext2D *painter)
vtkTextProperty *prop = painter->GetTextProp();
// Draw the axis title if there is one
if (this->Title)
if (this->Title && this->Title[0])
{
int x = 0;
int y = 0;
......@@ -247,9 +225,9 @@ bool vtkAxis::Paint(vtkContext2D *painter)
// Now draw the tick marks
painter->ApplyTextProp(this->LabelProperties);
float *tickPos = this->TickPositions->GetPointer(0);
float *tickPos = this->TickScenePositions->GetPointer(0);
vtkStdString *tickLabel = this->TickLabels->GetPointer(0);
vtkIdType numMarks = this->TickPositions->GetNumberOfTuples();
vtkIdType numMarks = this->TickScenePositions->GetNumberOfTuples();
// There are four possible tick label positions, which should be set by the
// class laying out the axes.
......@@ -321,11 +299,46 @@ bool vtkAxis::Paint(vtkContext2D *painter)
return true;
}
//-----------------------------------------------------------------------------
void vtkAxis::SetMinimum(double minimum)
{
if (this->Minimum == minimum)
{
return;
}
this->Minimum = minimum;
this->UsingNiceMinMax = false;
this->TickMarksDirty = true;
this->Modified();
}
//-----------------------------------------------------------------------------
void vtkAxis::SetMaximum(double maximum)
{
if (this->Maximum == maximum)
{
return;
}
this->Maximum = maximum;
this->UsingNiceMinMax = false;
this->TickMarksDirty = true;
this->Modified();
}
//-----------------------------------------------------------------------------
void vtkAxis::SetRange(double minimum, double maximum)
{
this->SetMinimum(minimum);
this->SetMaximum(maximum);
}
//-----------------------------------------------------------------------------
void vtkAxis::AutoScale()
{
// Calculate the min and max, set the number of ticks and the tick spacing
this->TickInterval = this->CalculateNiceMinMax(this->Minimum, this->Maximum);
this->UsingNiceMinMax = true;
this->GenerateTickLabels(this->Minimum, this->Maximum);
}
//-----------------------------------------------------------------------------
......@@ -333,12 +346,115 @@ void vtkAxis::RecalculateTickSpacing()
{
// Calculate the min and max, set the number of ticks and the tick spacing,
// discard the min and max in this case. TODO: Refactor the function called.
double min, max;
this->TickInterval = this->CalculateNiceMinMax(min, max);
if (this->Behavior < 2)
{
double min, max;
this->TickInterval = this->CalculateNiceMinMax(min, max);
if (this->UsingNiceMinMax)
{
this->GenerateTickLabels(this->Minimum, this->Maximum);
}
else
{
while (min < this->Minimum)
{
min += this->TickInterval;
}
while (max > this->Maximum)
{
max -= this->TickInterval;
}
this->GenerateTickLabels(min, max);
}
}
}
//-----------------------------------------------------------------------------
vtkDoubleArray* vtkAxis::GetTickPositions()
{
return this->TickPositions;
}
//-----------------------------------------------------------------------------
void vtkAxis::SetTickPositions(vtkDoubleArray* array)
{
if (this->TickPositions == array)
{
return;
}
this->TickPositions = array;
this->Behavior = 2;
this->TickMarksDirty = false;
this->Modified();
}
//-----------------------------------------------------------------------------
vtkFloatArray* vtkAxis::GetTickScenePositions()
{
return this->TickScenePositions;
}
//-----------------------------------------------------------------------------
vtkStringArray* vtkAxis::GetTickLabels()
{
return this->TickLabels;
}
//-----------------------------------------------------------------------------
void vtkAxis::SetTickLabels(vtkStringArray* array)
{
if (this->TickLabels == array)
{
return;
}
this->TickLabels = array;
this->Behavior = 2;
this->TickMarksDirty = false;
this->Modified();
}
//-----------------------------------------------------------------------------
void vtkAxis::GenerateTickLabels(double min, double max)
{
// Now calculate the tick labels, and positions within the axis range
this->TickPositions->SetNumberOfTuples(0);
this->TickLabels->SetNumberOfTuples(0);
int n = static_cast<int>((max - min) / this->TickInterval);
for (int i = 0; i <= n && i < 200; ++i)
{
double value = min + double(i) * this->TickInterval;
this->TickPositions->InsertNextValue(value);
// Make a tick mark label for the tick
if (this->LogScale)
{
value = pow(double(10.0), double(value));
}
// Now create a label for the tick position
vtksys_ios::ostringstream ostr;
ostr.imbue(vtkstd::locale::classic());
if (this->Notation > 0)
{
ostr.precision(this->Precision);
}
if (this->Notation == 1)
{
// Scientific notation
ostr.setf(vtksys_ios::ios::scientific, vtksys_ios::ios::floatfield);
}
else if (this->Notation == 2)
{
ostr.setf(ios::fixed, ios::floatfield);
}
ostr << value;
this->TickLabels->InsertNextValue(ostr.str());
}
this->TickMarksDirty = false;
}
//-----------------------------------------------------------------------------
float vtkAxis::CalculateNiceMinMax(double &min, double &max)
double vtkAxis::CalculateNiceMinMax(double &min, double &max)
{
// First get the order of the range of the numbers
if (this->Maximum == this->Minimum)
......@@ -390,7 +506,7 @@ float vtkAxis::CalculateNiceMinMax(double &min, double &max)
}
//-----------------------------------------------------------------------------
float vtkAxis::NiceNumber(double n, bool roundUp)
double vtkAxis::NiceNumber(double n, bool roundUp)
{
if (roundUp)
{
......
......@@ -24,10 +24,12 @@
#define __vtkAxis_h
#include "vtkContextItem.h"
#include "vtkSmartPointer.h" // For vtkSmartPointer
class vtkContext2D;
class vtkPen;
class vtkFloatArray;
class vtkDoubleArray;
class vtkStringArray;
class vtkTextProperty;
......@@ -90,7 +92,7 @@ public:
// Description:
// Set the logical minimum value of the axis, in plot coordinates.
vtkSetMacro(Minimum, double);
virtual void SetMinimum(double minimum);
// Description:
// Get the logical minimum value of the axis, in plot coordinates.
......@@ -98,12 +100,16 @@ public:
// Description:
// Set the logical maximum value of the axis, in plot coordinates.
vtkSetMacro(Maximum, double);
virtual void SetMaximum(double maximum);
// Description:
// Get the logical maximum value of the axis, in plot coordinates.
vtkGetMacro(Maximum, double);
// Description:
// Get the logical range of the axis, in plot coordinates.
virtual void SetRange(double minimum, double maximum);
// Description:
// Get/set the title text of the axis.
vtkSetStringMacro(Title);
......@@ -173,26 +179,46 @@ public:
virtual void RecalculateTickSpacing();
// Description:
// A float array with the positions of the tick marks along the axis line.
// The positions are specified in the coordinate system the axis is drawn in
// (normally screen coordinates).
vtkFloatArray* GetTickPositions() { return this->TickPositions; }
// An array with the positions of the tick marks along the axis line.
// The positions are specified in the plot coordinates of the axis.
virtual vtkDoubleArray* GetTickPositions();
// Description:
// Set the tick positions (in plot coordinates).
virtual void SetTickPositions(vtkDoubleArray*);
// Description:
// An array with the positions of the tick marks along the axis line.
// The positions are specified in scene coordinates.
virtual vtkFloatArray* GetTickScenePositions();
// Description:
// A string array containing the tick labels for the axis.
virtual vtkStringArray* GetTickLabels();
// Description:
// Set the tick labels for the axis.
virtual void SetTickLabels(vtkStringArray*);
//BTX
protected:
vtkAxis();
~vtkAxis();
// Description:
// Calculate and assign nice labels/logical label positions.
void GenerateTickLabels(double min, double max);
// Description:
// Calculate the next "nicest" numbers above and below the current minimum.
// \return the "nice" spacing of the numbers.
float CalculateNiceMinMax(double &min, double &max);
double CalculateNiceMinMax(double &min, double &max);
// Description:
// Return a "nice number", often defined as 1, 2 or 5. If roundUp is true then
// the nice number will be rounded up, false it is rounded down. The supplied
// number should be between 0.0 and 9.9.
float NiceNumber(double number, bool roundUp);
double NiceNumber(double number, bool roundUp);
int Position; // The position of the axis (LEFT, BOTTOM, RIGHT, TOP)
float Point1[2]; // The position of point 1 (usually the origin)
......@@ -200,7 +226,6 @@ protected:
double TickInterval; // Interval between tick marks in plot space
int NumberOfTicks; // The number of tick marks to draw
vtkTextProperty* LabelProperties; // Text properties for the labels.
int TickLabelSize; // The point size of the tick labels
double Minimum; // Minimum value of the axis
double Maximum; // Maximum values of the axis
char* Title; // The text label drawn on the axis
......@@ -220,8 +245,26 @@ protected:
// This object stores the vtkPen that controls how the grid lines are drawn.
vtkPen* GridPen;
vtkFloatArray* TickPositions; // Position of tick marks in screen coordinates
vtkStringArray* TickLabels; // The labels for the tick marks
// Description:
// Position of tick marks in screen coordinates
vtkSmartPointer<vtkDoubleArray> TickPositions;
// Description:
// Position of tick marks in screen coordinates
vtkSmartPointer<vtkFloatArray> TickScenePositions;
// Description:
// The labels for the tick marks
vtkSmartPointer<vtkStringArray> TickLabels;
// Description:
// Hint as to whether a nice min/max was set, otherwise labels may not be
// present at the top/bottom of the axis.
bool UsingNiceMinMax;
// Description:
// Mark the tick labels as dirty when the min/max value is changed
bool TickMarksDirty;
// Description:
// The point cache is marked dirty until it has been initialized.
......
......@@ -24,7 +24,7 @@
#include "vtkObjectFactory.h"
//-----------------------------------------------------------------------------
vtkCxxRevisionMacro(vtkPlotGrid, "1.5");
vtkCxxRevisionMacro(vtkPlotGrid, "1.5.4.1");
vtkCxxSetObjectMacro(vtkPlotGrid, XAxis, vtkAxis);
vtkCxxSetObjectMacro(vtkPlotGrid, YAxis, vtkAxis);
//-----------------------------------------------------------------------------
......@@ -65,7 +65,7 @@ bool vtkPlotGrid::Paint(vtkContext2D *painter)
// in x
if (this->XAxis->GetGridVisible())
{
vtkFloatArray *xLines = this->XAxis->GetTickPositions();
vtkFloatArray *xLines = this->XAxis->GetTickScenePositions();
painter->ApplyPen(this->XAxis->GetGridPen());
float *xPositions = xLines->GetPointer(0);
for (int i = 0; i < xLines->GetNumberOfTuples(); ++i)
......@@ -78,7 +78,7 @@ bool vtkPlotGrid::Paint(vtkContext2D *painter)
// in y
if (this->YAxis->GetGridVisible())
{
vtkFloatArray *yLines = this->YAxis->GetTickPositions();
vtkFloatArray *yLines = this->YAxis->GetTickScenePositions();
painter->ApplyPen(this->YAxis->GetGridPen());
float *yPositions = yLines->GetPointer(0);
for (int i = 0; i < yLines->GetNumberOfTuples(); ++i)
......
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