Commit e304d95a authored by Purves, Murray's avatar Purves, Murray
Browse files

#20 WIP Adding vtkPlotErrorBars class & initial error data additions

parent 0760f8fa
......@@ -60,11 +60,11 @@ ELSE()
IF(TPL_ENABLE_VTK)
SET(HEADERS ${HEADERS}
vtkchartwidget.hh
vtkPlotPointsErrorBars.hh
)
SET(SOURCES
${SOURCES}
vtkchartwidget.cc
vtkPlotErrorBars.cc
vtkPlotPointsErrorBars.cc
)
ENDIF()
......@@ -74,6 +74,12 @@ ELSE()
SET(HEADERS ${HEADERS}
navigationitem.hh
)
IF(TPL_ENABLE_VTK)
SET(HEADERS ${HEADERS}
vtkPlotErrorBars.hh
vtkPlotPointsErrorBars.hh
)
ENDIF()
#
# Process qt resource files
#QT5_ADD_RESOURCES(RESOURCE_RESULT
......
......@@ -25,7 +25,7 @@ ELSE()
QT5_WRAP_CPP(QMOC_FILES4
radixvtkchartwidget.hh
)
QT5_WRAP_CPP(QMOC_FILES5
QT5_WRAP_CPP(QMOC_FILES5
radixvtkerrorbars.hh
)
ENDIF()
......@@ -47,10 +47,12 @@ ELSE()
TRIBITS_ADD_EXECUTABLE(radixvtkchartwidget
NOEXEPREFIX
SOURCES radixvtkchartwidget.cc ${QMOC_FILES4}
radixvtkchartwidget.hh
)
TRIBITS_ADD_EXECUTABLE(radixvtkerrorbars
NOEXEPREFIX
SOURCES radixvtkerrorbars.cc ${QMOC_FILES5}
radixvtkerrorbars.hh
)
ENDIF()
ENDIF()
......
......@@ -10,9 +10,9 @@ VTK_MODULE_INIT(vtkRenderingFreeType)
#include <QWidget>
#include "vtkFloatArray.h"
#include "vtkPlot.h"
#include "vtkTable.h"
#include "radixwidgets/vtkPlotErrorBars.hh"
#include "radixwidgets/vtkPlotPointsErrorBars.hh"
#include "radixwidgets/vtkchartwidget.hh"
......@@ -46,17 +46,27 @@ vtkChartMainWindow::vtkChartMainWindow(QWidget* parent)
vtkNew<vtkFloatArray> arrSum;
arrSum->SetName("Sum");
table->AddColumn(arrSum);
vtkNew<vtkFloatArray> arrXErr;
arrXErr->SetName("x error");
table->AddColumn(arrXErr);
vtkNew<vtkFloatArray> arrSumErr;
arrSumErr->SetName("Sum error");
table->AddColumn(arrSumErr);
int numPoints = 29;
float inc = 7.0 / (numPoints - 1);
table->SetNumberOfRows(numPoints);
for (int i = 0; i < numPoints; ++i)
{
table->SetValue(i, 0, i * inc);
table->SetValue(i, 1, std::cos(double(i * inc)));
table->SetValue(i, 2, std::sin(double(i * inc)));
table->SetValue(i, 3,
std::fabs(std::sin(double(i * inc))) +
std::fabs(std::cos(double(i * inc))));
double x = double(i * inc), sin = std::sin(x), cos = std::cos(x),
sum = std::fabs(sin) + std::fabs(cos), sumErr = sum / 5.0,
xErr = x / 5.0;
table->SetValue(i, 0, x);
table->SetValue(i, 1, cos);
table->SetValue(i, 2, sin);
table->SetValue(i, 3, sum);
table->SetValue(i, 4, xErr);
table->SetValue(i, 5, sumErr);
}
vtkPlot* line = vtkChartWidget->chartXY()->AddPlot(vtkChart::LINE);
......@@ -70,7 +80,7 @@ vtkChartMainWindow::vtkChartMainWindow(QWidget* parent)
vtkPlotPointsErrorBars* points = vtkPlotPointsErrorBars::New();
vtkChartWidget->chartXY()->AddPlot(points);
points->SetInputData(table, 0, 3); // x-axis and sum
points->SetInputData(table, 0, 3, 4, 5); // x-axis and sum with errors
points->SetColor(255, 0, 255, 255);
points->SetWidth(2.0);
}
......
/*=========================================================================
Program: Visualization Toolkit
Module: vtkPlot.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 "radixwidgets/vtkPlotErrorBars.hh"
#include <sstream>
#include "vtkAxis.h"
#include "vtkBrush.h"
#include "vtkContextMapper2D.h"
#include "vtkDataObject.h"
#include "vtkIdTypeArray.h"
#include "vtkNew.h"
#include "vtkObjectFactory.h"
#include "vtkPen.h"
#include "vtkStringArray.h"
#include "vtkTable.h"
vtkCxxSetObjectMacro(vtkPlotErrorBars, XAxis, vtkAxis);
vtkCxxSetObjectMacro(vtkPlotErrorBars, YAxis, vtkAxis);
//-----------------------------------------------------------------------------
vtkPlotErrorBars::vtkPlotErrorBars()
: ShiftScale(0.0, 0.0, 1.0, 1.0)
{
this->Pen = vtkSmartPointer<vtkPen>::New();
this->Pen->SetWidth(2.0);
this->Brush = vtkSmartPointer<vtkBrush>::New();
this->SelectionPen = vtkSmartPointer<vtkPen>::New();
this->SelectionPen->SetColor(255, 50, 0, 150);
this->SelectionPen->SetWidth(4.0);
this->SelectionBrush = vtkSmartPointer<vtkBrush>::New();
this->SelectionBrush->SetColor(255, 50, 0, 150);
this->Labels = nullptr;
this->UseIndexForXSeries = false;
this->Data = vtkSmartPointer<vtkContextMapper2D>::New();
this->Selectable = true;
this->Selection = nullptr;
this->XAxis = nullptr;
this->YAxis = nullptr;
this->TooltipDefaultLabelFormat = "%l: %x, %y";
this->TooltipNotation = vtkAxis::STANDARD_NOTATION;
this->TooltipPrecision = 6;
this->LegendVisibility = true;
}
//-----------------------------------------------------------------------------
vtkPlotErrorBars::~vtkPlotErrorBars()
{
if (this->Selection)
{
this->Selection->Delete();
this->Selection = nullptr;
}
this->SetLabels(nullptr);
this->SetXAxis(nullptr);
this->SetYAxis(nullptr);
}
//-----------------------------------------------------------------------------
bool vtkPlotErrorBars::PaintLegend(vtkContext2D *, const vtkRectf &, int)
{
return false;
}
//-----------------------------------------------------------------------------
vtkIdType vtkPlotErrorBars::GetNearestPoint(const vtkVector2f &,
const vtkVector2f &, vtkVector2f *)
{
return -1;
}
//-----------------------------------------------------------------------------
vtkStdString vtkPlotErrorBars::GetTooltipLabel(const vtkVector2d &plotPos,
vtkIdType seriesIndex, vtkIdType)
{
vtkStdString tooltipLabel;
vtkStdString &format = this->TooltipLabelFormat.empty()
? this->TooltipDefaultLabelFormat
: this->TooltipLabelFormat;
// Parse TooltipLabelFormat and build tooltipLabel
bool escapeNext = false;
for (size_t i = 0; i < format.length(); ++i)
{
if (escapeNext)
{
switch (format[i])
{
case 'x':
tooltipLabel += this->GetNumber(plotPos.GetX(), this->XAxis);
break;
case 'y':
tooltipLabel += this->GetNumber(plotPos.GetY(), this->YAxis);
break;
case 'i':
if (this->IndexedLabels && seriesIndex >= 0 &&
seriesIndex < this->IndexedLabels->GetNumberOfTuples())
{
tooltipLabel += this->IndexedLabels->GetValue(seriesIndex);
}
break;
case 'l':
// GetLabel() is GetLabel(0) in this implementation
tooltipLabel += this->GetLabel();
break;
default: // If no match, insert the entire format tag
tooltipLabel += "%";
tooltipLabel += format[i];
break;
}
escapeNext = false;
}
else
{
if (format[i] == '%')
{
escapeNext = true;
}
else
{
tooltipLabel += format[i];
}
}
}
return tooltipLabel;
}
//-----------------------------------------------------------------------------
vtkStdString vtkPlotErrorBars::GetNumber(double position, vtkAxis *axis)
{
// Determine and format the X and Y position in the chart
std::ostringstream ostr;
ostr.imbue(std::locale::classic());
ostr.precision(this->GetTooltipPrecision());
if (this->GetTooltipNotation() == vtkAxis::SCIENTIFIC_NOTATION)
{
ostr.setf(ios::scientific, ios::floatfield);
}
else if (this->GetTooltipNotation() == vtkAxis::FIXED_NOTATION)
{
ostr.setf(ios::fixed, ios::floatfield);
}
if (axis && axis->GetLogScaleActive())
{
// If axes are set to logarithmic scale we need to convert the
// axis value using 10^(axis value)
ostr << pow(double(10.0), double(position));
}
else
{
ostr << position;
}
return ostr.str();
}
//-----------------------------------------------------------------------------
bool vtkPlotErrorBars::SelectPoints(const vtkVector2f &, const vtkVector2f &)
{
if (this->Selection)
{
this->Selection->SetNumberOfTuples(0);
}
return false;
}
//-----------------------------------------------------------------------------
bool vtkPlotErrorBars::SelectPointsInPolygon(const vtkContextPolygon &)
{
if (this->Selection)
{
this->Selection->SetNumberOfTuples(0);
}
return false;
}
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetColor(unsigned char r, unsigned char g,
unsigned char b, unsigned char a)
{
this->Pen->SetColor(r, g, b, a);
}
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetColor(double r, double g, double b)
{
this->Pen->SetColorF(r, g, b);
}
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::GetColor(double rgb[3]) { this->Pen->GetColorF(rgb); }
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::GetColor(unsigned char rgb[3])
{
double rgbF[3];
this->GetColor(rgbF);
rgb[0] = static_cast<unsigned char>(255. * rgbF[0] + 0.5);
rgb[1] = static_cast<unsigned char>(255. * rgbF[1] + 0.5);
rgb[2] = static_cast<unsigned char>(255. * rgbF[2] + 0.5);
}
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetWidth(float width) { this->Pen->SetWidth(width); }
//-----------------------------------------------------------------------------
float vtkPlotErrorBars::GetWidth() { return this->Pen->GetWidth(); }
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetPen(vtkPen *pen)
{
if (this->Pen != pen)
{
this->Pen = pen;
this->Modified();
}
}
//-----------------------------------------------------------------------------
vtkPen *vtkPlotErrorBars::GetPen() { return this->Pen; }
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetBrush(vtkBrush *brush)
{
if (this->Brush != brush)
{
this->Brush = brush;
this->Modified();
}
}
//-----------------------------------------------------------------------------
vtkBrush *vtkPlotErrorBars::GetBrush() { return this->Brush; }
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetSelectionPen(vtkPen *pen)
{
if (this->SelectionPen != pen)
{
this->SelectionPen = pen;
this->Modified();
}
}
//-----------------------------------------------------------------------------
vtkPen *vtkPlotErrorBars::GetSelectionPen() { return this->SelectionPen; }
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetSelectionBrush(vtkBrush *brush)
{
if (this->SelectionBrush != brush)
{
this->SelectionBrush = brush;
this->Modified();
}
}
//-----------------------------------------------------------------------------
vtkBrush *vtkPlotErrorBars::GetSelectionBrush() { return this->SelectionBrush; }
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetLabel(const vtkStdString &label)
{
vtkNew<vtkStringArray> labels;
labels->InsertNextValue(label);
this->SetLabels(labels);
}
//-----------------------------------------------------------------------------
vtkStdString vtkPlotErrorBars::GetLabel() { return this->GetLabel(0); }
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetLabels(vtkStringArray *labels)
{
if (this->Labels == labels)
{
return;
}
this->Labels = labels;
this->Modified();
}
//-----------------------------------------------------------------------------
vtkStringArray *vtkPlotErrorBars::GetLabels()
{
// If the label string is empty, return the y column name
if (this->Labels)
{
return this->Labels;
}
else if (this->AutoLabels)
{
return this->AutoLabels;
}
else if (this->Data->GetInput() &&
this->Data->GetInputArrayToProcess(1, this->Data->GetInput()))
{
this->AutoLabels = vtkSmartPointer<vtkStringArray>::New();
this->AutoLabels->InsertNextValue(
this->Data->GetInputArrayToProcess(1, this->Data->GetInput())
->GetName());
return this->AutoLabels;
}
else
{
return nullptr;
}
}
//-----------------------------------------------------------------------------
int vtkPlotErrorBars::GetNumberOfLabels()
{
vtkStringArray *labels = this->GetLabels();
if (labels)
{
return labels->GetNumberOfValues();
}
else
{
return 0;
}
}
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetIndexedLabels(vtkStringArray *labels)
{
if (this->IndexedLabels == labels)
{
return;
}
if (labels)
{
this->TooltipDefaultLabelFormat = "%i: %x, %y";
}
else
{
this->TooltipDefaultLabelFormat = "%l: %x, %y";
}
this->IndexedLabels = labels;
this->Modified();
}
//-----------------------------------------------------------------------------
vtkStringArray *vtkPlotErrorBars::GetIndexedLabels()
{
return this->IndexedLabels;
}
//-----------------------------------------------------------------------------
vtkContextMapper2D *vtkPlotErrorBars::GetData() { return this->Data; }
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetTooltipLabelFormat(const vtkStdString &labelFormat)
{
if (this->TooltipLabelFormat == labelFormat)
{
return;
}
this->TooltipLabelFormat = labelFormat;
this->Modified();
}
//-----------------------------------------------------------------------------
vtkStdString vtkPlotErrorBars::GetTooltipLabelFormat()
{
return this->TooltipLabelFormat;
}
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetTooltipNotation(int notation)
{
this->TooltipNotation = notation;
this->Modified();
}
//-----------------------------------------------------------------------------
int vtkPlotErrorBars::GetTooltipNotation() { return this->TooltipNotation; }
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetTooltipPrecision(int precision)
{
this->TooltipPrecision = precision;
this->Modified();
}
//-----------------------------------------------------------------------------
int vtkPlotErrorBars::GetTooltipPrecision() { return this->TooltipPrecision; }
//-----------------------------------------------------------------------------
vtkStdString vtkPlotErrorBars::GetLabel(vtkIdType index)
{
vtkStringArray *labels = this->GetLabels();
if (labels && index >= 0 && index < labels->GetNumberOfValues())
{
return labels->GetValue(index);
}
else
{
return vtkStdString();
}
}
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetInputData(vtkTable *table)
{
this->Data->SetInputData(table);
this->AutoLabels = nullptr; // No longer valid
}
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetInputData(vtkTable *table,
const vtkStdString &xColumn,
const vtkStdString &yColumn)
{
vtkDebugMacro(<< "Setting input, X column = \"" << xColumn.c_str() << "\", "
<< "Y column = \"" << yColumn.c_str() << "\"");
this->Data->SetInputData(table);
this->Data->SetInputArrayToProcess(
0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_ROWS, xColumn.c_str());
this->Data->SetInputArrayToProcess(
1, 0, 0, vtkDataObject::FIELD_ASSOCIATION_ROWS, yColumn.c_str());
this->AutoLabels = nullptr; // No longer valid
}
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetInputData(vtkTable *table, vtkIdType xColumn,
vtkIdType yColumn)
{
this->SetInputData(table, table->GetColumnName(xColumn),
table->GetColumnName(yColumn));
}
//--Set input data inc. errors-------------------------------------------------
void vtkPlotErrorBars::SetInputData(vtkTable *table,
const vtkStdString &xColumn,
const vtkStdString &yColumn,
const vtkStdString &xErrorColumn,
const vtkStdString &yErrorColumn)
{
vtkDebugMacro(<< "Setting input, X column = \"" << xColumn.c_str() << "\", "
<< "Y column = \"" << yColumn.c_str() << "\"");
this->Data->SetInputData(table);
this->Data->SetInputArrayToProcess(
0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_ROWS, xColumn.c_str());
this->Data->SetInputArrayToProcess(
1, 0, 0, vtkDataObject::FIELD_ASSOCIATION_ROWS, yColumn.c_str());
this->Data->SetInputArrayToProcess(
2, 0, 0, vtkDataObject::FIELD_ASSOCIATION_ROWS, xErrorColumn.c_str());
this->Data->SetInputArrayToProcess(
3, 0, 0, vtkDataObject::FIELD_ASSOCIATION_ROWS, yErrorColumn.c_str());
this->AutoLabels = nullptr; // No longer valid
}
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetInputData(vtkTable *table, vtkIdType xColumn,
vtkIdType yColumn, vtkIdType xErrorColumn,
vtkIdType yErrorColumn)
{
this->SetInputData(
table, table->GetColumnName(xColumn), table->GetColumnName(yColumn),
table->GetColumnName(xErrorColumn), table->GetColumnName(yErrorColumn));
}
//-----------------------------------------------------------------------------
vtkTable *vtkPlotErrorBars::GetInput() { return this->Data->GetInput(); }
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetInputArray(int index, const vtkStdString &name)
{
this->Data->SetInputArrayToProcess(
index, 0, 0, vtkDataObject::FIELD_ASSOCIATION_ROWS, name.c_str());
this->AutoLabels = nullptr; // No longer valid
}
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetSelection(vtkIdTypeArray *id)
{
if (!this->GetSelectable())
{
return;
}
vtkSetObjectBodyMacro(Selection, vtkIdTypeArray, id);
}
//-----------------------------------------------------------------------------
void vtkPlotErrorBars::SetShiftScale(const vtkRectd &shiftScale)
{
if (shiftScale != this->ShiftScale)
{
this->Modified();
this->ShiftScale = shiftScale;
}