Commit 6518f801 authored by Marcus D. Hanwell's avatar Marcus D. Hanwell Committed by Code Review
Browse files

Merge topic 'plot-bar-lut' into master

b2e4fb38 Added colored bar charts, along with a test
parents 45e2449a b2e4fb38
......@@ -49,6 +49,7 @@ vtk_add_test_cxx(${vtk-module}CxxTests tests
TestCategoryLegend.cxx
TestColorTransferFunction.cxx
TestChartDouble.cxx
TestChartDoubleColors.cxx
TestChartMatrix.cxx
TestChartUnicode.cxx
TestChartsOn3D.cxx
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestChartDoubleColors.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 "vtkPlotPoints.h"
#include "vtkPlotBar.h"
#include "vtkPlotLine.h"
#include "vtkLookupTable.h"
#include "vtkTable.h"
#include "vtkDoubleArray.h"
#include "vtkContextView.h"
#include "vtkContextScene.h"
#include "vtkPen.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkNew.h"
#include "vtkAxis.h"
//----------------------------------------------------------------------------
int TestChartDoubleColors(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.Get());
vtkNew<vtkDoubleArray> arrC;
arrC->SetName("f1");
table->AddColumn(arrC.Get());
vtkNew<vtkDoubleArray> arrS;
arrS->SetName("f2");
table->AddColumn(arrS.Get());
vtkNew<vtkDoubleArray> arrS2;
arrS2->SetName("f3");
table->AddColumn(arrS2.Get());
vtkNew<vtkDoubleArray> arrColor;
arrColor->SetName("color");
table->AddColumn(arrColor.Get());
// Test charting with a few more points...
int numPoints = 69;
float inc = 7.5 / (numPoints - 1);
table->SetNumberOfRows(numPoints);
for (int i = 0; i < numPoints; ++i)
{
double x(i * inc + 0.2);
table->SetValue(i, 0, x);
table->SetValue(i, 1, 1.0e-80 * (cos(x - 1.0) + sin(x - 3.14 / 4.0)));
table->SetValue(i, 2, 1.0e-80 * sin(x) * 1e-12);
table->SetValue(i, 3, 1.0e-80 * sin(x - 1.0));
table->SetValue(i, 4, cos(i * inc));
}
vtkNew<vtkLookupTable> lut;
lut->SetValueRange(0.0, 1.0);
lut->SetSaturationRange(1.0, 1.0);
lut->SetHueRange(0.4, 0.9);
lut->SetAlphaRange(0.2, 0.8);
lut->SetRange(-1.0, 1.0);
lut->SetRampToLinear();
lut->Build();
// Add multiple line plots, setting the colors etc
vtkNew<vtkPlotPoints> points;
chart->AddPlot(points.Get());
points->SetInputData(table.Get(), 0, 1);
points->SetMarkerSize(10.0);
points->ScalarVisibilityOn();
points->SelectColorArray("color");
points->SetLookupTable(lut.Get());
vtkNew<vtkPlotLine> line;
chart->AddPlot(line.Get());
line->SetInputData(table.Get(), 0, 2);
line->SetColor(1.0, 0.0, 0.0);
// Put this plot in a different corner - it is orders of magnitude smaller.
chart->SetPlotCorner(line.Get(), 1);
vtkNew<vtkPlotBar> bar;
chart->AddPlot(bar.Get());
bar->SetInputData(table.Get(), 0, 3);
bar->ScalarVisibilityOn();
bar->SelectColorArray("color");
bar->SetLookupTable(lut.Get());
bar->GetPen()->SetLineType(vtkPen::NO_PEN);
chart->GetAxis(vtkAxis::LEFT)->SetTitle("A tiny range");
chart->GetAxis(vtkAxis::BOTTOM)->SetTitle("A normal range");
chart->GetAxis(vtkAxis::RIGHT)->SetTitle("An even tinier range");
chart->SetBarWidthFraction(1.0f);
// Render the scene and compare the image to a reference image
view->GetRenderWindow()->SetMultiSamples(0);
view->GetInteractor()->Initialize();
view->GetInteractor()->Start();
return EXIT_SUCCESS;
}
......@@ -33,6 +33,7 @@
#include "vtkColorSeries.h"
#include "vtkStringArray.h"
#include "vtkNew.h"
#include "vtkLookupTable.h"
#include "vtkObjectFactory.h"
......@@ -171,6 +172,7 @@ class vtkPlotBarSegment : public vtkObject {
this->Points = NULL;
this->Sorted = NULL;
this->Previous = NULL;
this->Colors = NULL;
}
~vtkPlotBarSegment()
......@@ -233,6 +235,10 @@ class vtkPlotBarSegment : public vtkObject {
for (int i = 0; i < n; ++i)
{
if (this->Colors)
{
painter->GetBrush()->SetColor(vtkColor4ub(this->Colors->GetPointer(i * 4)));
}
if (orientation == vtkPlotBar::VERTICAL)
{
if (p)
......@@ -452,6 +458,7 @@ class vtkPlotBarSegment : public vtkObject {
vtkPlotBar *Bar;
VectorPIMPL* Sorted;
vtkVector2d ScalingFactor;
vtkUnsignedCharArray *Colors;
};
vtkStandardNewMacro(vtkPlotBarSegment);
......@@ -552,6 +559,9 @@ vtkPlotBar::vtkPlotBar()
this->Offset = 1.0;
this->ColorSeries = NULL;
this->Orientation = vtkPlotBar::VERTICAL;
this->ScalarVisibility = false;
this->LogX = false;
this->LogY = false;
}
//-----------------------------------------------------------------------------
......@@ -566,41 +576,49 @@ vtkPlotBar::~vtkPlotBar()
}
//-----------------------------------------------------------------------------
bool vtkPlotBar::Paint(vtkContext2D *painter)
void vtkPlotBar::Update()
{
// This is where everything should be drawn, or dispatched to other methods.
vtkDebugMacro(<< "Paint event called in vtkPlotBar.");
if (!this->Visible)
{
return false;
return;
}
// First check if we have an input
vtkTable *table = this->Data->GetInput();
if (!table)
{
vtkDebugMacro(<< "Paint event called with no input table set.");
return false;
vtkDebugMacro(<< "Update event called with no input table set.");
return;
}
else if(this->Data->GetMTime() > this->BuildTime ||
this->GetXAxis()->GetMTime() > this->BuildTime ||
this->GetYAxis()->GetMTime() > this->BuildTime ||
table->GetMTime() > this->BuildTime ||
(this->LookupTable && this->LookupTable->GetMTime() > this->BuildTime) ||
this->MTime > this->BuildTime)
{
vtkDebugMacro(<< "Paint event called with outdated table cache. Updating.");
vtkDebugMacro(<< "Updating cached values.");
this->UpdateTableCache(table);
}
// Now add some decorations for our selected points...
if (this->Selection)
else if ((this->XAxis && this->XAxis->GetMTime() > this->BuildTime) ||
(this->YAxis && this->YAxis->GetMaximum() > this->BuildTime))
{
vtkDebugMacro(<<"Selection set " << this->Selection->GetNumberOfTuples());
if (this->LogX != this->XAxis->GetLogScale() ||
this->LogY != this->YAxis->GetLogScale())
{
this->LogX = this->XAxis->GetLogScale();
this->LogY = this->YAxis->GetLogScale();
this->UpdateTableCache(table);
}
}
else
}
//-----------------------------------------------------------------------------
bool vtkPlotBar::Paint(vtkContext2D *painter)
{
// This is where everything should be drawn, or dispatched to other methods.
vtkDebugMacro(<< "Paint event called in vtkPlotBar.");
if (!this->Visible)
{
vtkDebugMacro("No selection set.");
return false;
}
this->Private->PaintSegments(painter,this->ColorSeries, this->Pen,this->Brush,
......@@ -852,6 +870,31 @@ bool vtkPlotBar::UpdateTableCache(vtkTable *table)
vtkPlotBarSegment *prev = this->Private->AddSegment(x, y, this->GetXAxis(),
this->GetYAxis());
// Additions for color mapping
if (this->ScalarVisibility && !this->ColorArrayName.empty())
{
vtkDataArray* c =
vtkDataArray::SafeDownCast(table->GetColumnByName(this->ColorArrayName));
// TODO: Should add support for categorical coloring & try enum lookup
if (c)
{
if (!this->LookupTable)
{
this->CreateDefaultLookupTable();
}
this->Colors = this->LookupTable->MapScalars(c,
VTK_COLOR_MODE_MAP_SCALARS,
-1);
prev->Colors = this->Colors;
this->Colors->Delete();
}
else
{
this->Colors = NULL;
prev->Colors = NULL;
}
}
std::map< int, std::string >::iterator it;
for ( it = this->Private->AdditionalSeries.begin();
......@@ -916,6 +959,97 @@ vtkColorSeries *vtkPlotBar::GetColorSeries()
return this->ColorSeries;
}
//-----------------------------------------------------------------------------
void vtkPlotBar::SetLookupTable(vtkScalarsToColors *lut)
{
if (this->LookupTable != lut)
{
this->LookupTable = lut;
this->Modified();
}
}
//-----------------------------------------------------------------------------
vtkScalarsToColors *vtkPlotBar::GetLookupTable()
{
if (!this->LookupTable)
{
this->CreateDefaultLookupTable();
}
return this->LookupTable.Get();
}
//-----------------------------------------------------------------------------
void vtkPlotBar::CreateDefaultLookupTable()
{
this->LookupTable = vtkSmartPointer<vtkLookupTable>::New();
}
//-----------------------------------------------------------------------------
void vtkPlotBar::SelectColorArray(const vtkStdString& arrayName)
{
if (this->ColorArrayName == arrayName)
{
return;
}
vtkTable *table = this->Data->GetInput();
if (!table)
{
vtkWarningMacro(<< "SelectColorArray called with no input table set.");
return;
}
for (vtkIdType i = 0; i < table->GetNumberOfColumns(); ++i)
{
if (arrayName == table->GetColumnName(i))
{
this->ColorArrayName = arrayName;
this->Modified();
return;
}
}
vtkDebugMacro(<< "SelectColorArray called with invalid column name.");
this->ColorArrayName = "";
this->Modified();
return;
}
//-----------------------------------------------------------------------------
void vtkPlotBar::SelectColorArray(vtkIdType arrayNum)
{
vtkTable *table = this->Data->GetInput();
if (!table)
{
vtkWarningMacro(<< "SelectColorArray called with no input table set.");
return;
}
vtkDataArray *col = vtkDataArray::SafeDownCast(table->GetColumn(arrayNum));
// TODO: Should add support for categorical coloring & try enum lookup
if (!col)
{
vtkDebugMacro(<< "SelectColorArray called with invalid column index");
return;
}
else
{
const char *arrayName = table->GetColumnName(arrayNum);
if (this->ColorArrayName == arrayName || arrayName == 0)
{
return;
}
else
{
this->ColorArrayName = arrayName;
this->Modified();
}
}
}
//-----------------------------------------------------------------------------
vtkStdString vtkPlotBar::GetColorArrayName()
{
return this->ColorArrayName;
}
//-----------------------------------------------------------------------------
bool vtkPlotBar::SelectPoints(const vtkVector2f& min, const vtkVector2f& max)
{
......
......@@ -31,6 +31,8 @@ class vtkTable;
class vtkPoints2D;
class vtkStdString;
class vtkColorSeries;
class vtkUnsignedCharArray;
class vtkScalarsToColors;
class vtkPlotBarPrivate;
......@@ -51,6 +53,10 @@ public:
// Creates a 2D Chart object.
static vtkPlotBar *New();
// Description:
// Perform any updates to the item that may be necessary before rendering.
virtual void Update();
// Description:
// Paint event for the XY plot, called whenever the chart needs to be drawn
virtual bool Paint(vtkContext2D *painter);
......@@ -116,6 +122,33 @@ public:
// Get the color series used if when this is a stacked bar plot.
vtkColorSeries *GetColorSeries();
// Description:
// Specify a lookup table for the mapper to use.
virtual void SetLookupTable(vtkScalarsToColors *lut);
virtual vtkScalarsToColors *GetLookupTable();
// Description:
// Create default lookup table. Generally used to create one when none
// is available with the scalar data.
virtual void CreateDefaultLookupTable();
// Description:
// Turn on/off flag to control whether scalar data is used to color objects.
vtkSetMacro(ScalarVisibility, bool);
vtkGetMacro(ScalarVisibility, bool);
vtkBooleanMacro(ScalarVisibility, bool);
// Description:
// When ScalarMode is set to UsePointFieldData or UseCellFieldData,
// you can specify which array to use for coloring using these methods.
// The lookup table will decide how to convert vectors to colors.
void SelectColorArray(vtkIdType arrayNum);
void SelectColorArray(const vtkStdString& arrayName);
// Description:
// Get the array name to color by.
vtkStdString GetColorArrayName();
// Description
// Get the plot labels.
virtual vtkStringArray *GetLabels();
......@@ -184,6 +217,16 @@ protected:
// The color series to use if this becomes a stacked bar
vtkSmartPointer<vtkColorSeries> ColorSeries;
// Description:
// Lookup Table for coloring bars by scalar value
vtkSmartPointer<vtkScalarsToColors> LookupTable;
vtkSmartPointer<vtkUnsignedCharArray> Colors;
bool ScalarVisibility;
vtkStdString ColorArrayName;
bool LogX;
bool LogY;
private:
vtkPlotBar(const vtkPlotBar &); // Not implemented.
void operator=(const vtkPlotBar &); // Not implemented.
......
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