Commit f3804171 authored by Marcus D. Hanwell's avatar Marcus D. Hanwell
Browse files

ENH: Added some new 2D histogram chart and items.

This new chart type takes a vtkImageData as input, and produces a plot
using another vtkImageData. The axes and transform are all handled by
the chart. I still need to add an additional item to display the color
mapping and scale. There are a few layout issues to solve too, but all
fo the basics are now working.

Change-Id: Icf8170e89d720fd6381c8ed9c420ae0c2a023c6d
parent b684b9dc
......@@ -15,6 +15,7 @@ SET(KIT_LIBS vtkIO vtkftgl
)
SET(Kit_SRCS
vtk2DHistogramItem.cxx
vtkAbstractContextBufferId.cxx
vtkAbstractContextItem.cxx
vtkAxis.cxx
......@@ -22,6 +23,7 @@ SET(Kit_SRCS
vtkBrush.cxx
vtkChart.cxx
vtkChartLegend.cxx
vtkChart2DHistogram.cxx
vtkChartParallelCoordinates.cxx
vtkChartXY.cxx
vtkChartPie.cxx
......
......@@ -13,6 +13,7 @@ IF (VTK_USE_RENDERING AND VTK_USE_VIEWS)
# add tests that require data
SET(MyTests ${MyTests}
#TestContextUnicode.cxx # Disabled until Freetype unicode works
Test2DHistogram.cxx
TestBarGraph.cxx
TestContext.cxx
TestContextImage.cxx
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestLinePlot.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 "vtkSmartPointer.h"
#include "vtkChart2DHistogram.h"
#include "vtk2DHistogramItem.h"
#include "vtkImageData.h"
#include "vtkColorTransferFunction.h"
#include "vtkContextView.h"
#include "vtkContextScene.h"
#include "vtkMath.h"
#include "vtkRenderWindowInteractor.h"
//----------------------------------------------------------------------------
int Test2DHistogram( int, char * [] )
{
// Set up a 2D scene, add an XY chart to it
int size = 401;
vtkSmartPointer<vtkContextView> view =
vtkSmartPointer<vtkContextView>::New();
view->GetRenderWindow()->SetSize(size, size);
vtkSmartPointer<vtkChart2DHistogram> chart =
vtkSmartPointer<vtkChart2DHistogram>::New();
view->GetScene()->AddItem(chart);
vtkSmartPointer<vtkImageData> data = vtkSmartPointer<vtkImageData>::New();
data->SetExtent(0, size-1, 0, size-1, 0, 0);
data->SetNumberOfScalarComponents(1);
data->SetScalarTypeToDouble();
data->AllocateScalars();
data->SetOrigin(100.0, 0.0, 0.0);
data->SetSpacing(2.0, 1.0, 1.0);
double *dPtr = static_cast<double *>(data->GetScalarPointer(0, 0, 0));
for (int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j)
{
dPtr[i * size + j] = sin(vtkMath::RadiansFromDegrees(double(2*i))) *
cos(vtkMath::RadiansFromDegrees(double(j)));
}
}
chart->SetInput(data);
vtkSmartPointer<vtkColorTransferFunction> transferFunction =
vtkSmartPointer<vtkColorTransferFunction>::New();
transferFunction->AddHSVSegment(0.0, 0.0, 1.0, 1.0,
0.3333, 0.3333, 1.0, 1.0);
transferFunction->AddHSVSegment(0.3333, 0.3333, 1.0, 1.0,
0.6666, 0.6666, 1.0, 1.0);
transferFunction->AddHSVSegment(0.6666, 0.6666, 1.0, 1.0,
1.0, 0.0, 1.0, 1.0);
transferFunction->Build();
chart->SetTransferFunction(transferFunction);
//Finally render the scene and compare the image to a reference image
view->GetRenderWindow()->SetMultiSamples(0);
view->GetInteractor()->Initialize();
view->GetInteractor()->Start();
return EXIT_SUCCESS;
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtk2DHistogramItem.h
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 "vtk2DHistogramItem.h"
#include "vtkImageData.h"
#include "vtkColorTransferFunction.h"
#include "vtkContext2D.h"
#include "vtkObjectFactory.h"
//-----------------------------------------------------------------------------
vtkStandardNewMacro(vtk2DHistogramItem);
//-----------------------------------------------------------------------------
vtk2DHistogramItem::vtk2DHistogramItem()
{
}
//-----------------------------------------------------------------------------
vtk2DHistogramItem::~vtk2DHistogramItem()
{
}
//-----------------------------------------------------------------------------
bool vtk2DHistogramItem::Paint(vtkContext2D *painter)
{
this->GenerateHistogram();
if (this->Output)
{
if (this->Input)
{
double bounds[4];
int *extent = this->Input->GetExtent();
bounds[0] = this->Input->GetOrigin()[0];
bounds[1] = bounds[0] +
(extent[1] - extent[0]) * this->Input->GetSpacing()[0];
bounds[2] = this->Input->GetOrigin()[1];
bounds[3] = bounds[2] +
(extent[3] - extent[2]) * this->Input->GetSpacing()[1];
this->Position = vtkRectf(bounds[0], bounds[2],
bounds[1] - bounds[0], bounds[3] - bounds[2]);
}
painter->DrawImage(this->Position, this->Output);
}
return true;
}
//-----------------------------------------------------------------------------
void vtk2DHistogramItem::SetInput(vtkImageData *data, vtkIdType z)
{
this->Input = data;
}
//-----------------------------------------------------------------------------
vtkImageData * vtk2DHistogramItem::GetInput()
{
return this->Input;
}
//-----------------------------------------------------------------------------
void vtk2DHistogramItem::SetTransferFunction(vtkColorTransferFunction *function)
{
this->TransferFunction = function;
}
//-----------------------------------------------------------------------------
vtkColorTransferFunction * vtk2DHistogramItem::GetTransferFunction()
{
return this->TransferFunction;
}
void vtk2DHistogramItem::GetBounds(double bounds[4])
{
if (this->Input)
{
int *extent = this->Input->GetExtent();
bounds[0] = this->Input->GetOrigin()[0];
bounds[1] = bounds[0] +
(extent[1] - extent[0]) * this->Input->GetSpacing()[0];
bounds[2] = this->Input->GetOrigin()[1];
bounds[3] = bounds[2] +
(extent[3] - extent[2]) * this->Input->GetSpacing()[1];
}
else
{
bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0;
}
}
//-----------------------------------------------------------------------------
void vtk2DHistogramItem::SetPosition(const vtkRectf& pos)
{
this->Position = pos;
}
//-----------------------------------------------------------------------------
vtkRectf vtk2DHistogramItem::GetPosition()
{
return this->Position;
}
//-----------------------------------------------------------------------------
void vtk2DHistogramItem::GenerateHistogram()
{
if (!this->Output)
{
this->Output = vtkSmartPointer<vtkImageData>::New();
}
this->Output->SetExtent(this->Input->GetExtent());
this->Output->SetNumberOfScalarComponents(4);
this->Output->SetScalarTypeToUnsignedChar();
this->Output->AllocateScalars();
int dimension = this->Input->GetDimensions()[0] * this->Input->GetDimensions()[1];
double *input = reinterpret_cast<double *>(this->Input->GetScalarPointer());
unsigned char *output =
reinterpret_cast<unsigned char*>(this->Output->GetScalarPointer(0,0,0));
if (this->TransferFunction)
{
this->TransferFunction->MapScalarsThroughTable2(input, output, VTK_DOUBLE,
dimension, 1, 4);
}
}
//-----------------------------------------------------------------------------
void vtk2DHistogramItem::PrintSelf(ostream &os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtk2DHistogramItem.h
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.
=========================================================================*/
// .NAME vtk2DHistogramItem - 2D histogram item.
//
// .SECTION Description
//
#ifndef __vtk2DHistogramItem_h
#define __vtk2DHistogramItem_h
#include "vtkContextItem.h"
#include "vtkSmartPointer.h" // Needed for SP ivars
#include "vtkVector.h" // Needed for vtkRectf
class vtkImageData;
class vtkColorTransferFunction;
class VTK_CHARTS_EXPORT vtk2DHistogramItem : public vtkContextItem
{
public:
vtkTypeMacro(vtk2DHistogramItem, vtkContextItem);
virtual void PrintSelf(ostream &os, vtkIndent indent);
// Description:
// Creates a new object.
static vtk2DHistogramItem *New();
// Description:
// Paint event for the item, called whenever it needs to be drawn.
virtual bool Paint(vtkContext2D *painter);
// Description:
// Set the input, we are expecting a vtkImageData with just one component,
// this would normally be a float or a double. It will be passed to the other
// functions as a double to generate a color.
void SetInput(vtkImageData *data, vtkIdType z = 0);
// Description:
// Get the input table used by the plot.
vtkImageData * GetInput();
// Description:
// Set the color transfer funtion that will be used to generate the 2D
// histogram.
void SetTransferFunction(vtkColorTransferFunction *transfer);
// Description:
// Get the color transfer function that is used to generate the histogram.
vtkColorTransferFunction * GetTransferFunction();
virtual void GetBounds(double bounds[4]);
virtual void SetPosition(const vtkRectf& pos);
virtual vtkRectf GetPosition();
//BTX
protected:
vtk2DHistogramItem();
~vtk2DHistogramItem();
// Description:
// Where all the magic happens...
void GenerateHistogram();
vtkSmartPointer<vtkImageData> Input;
vtkSmartPointer<vtkImageData> Output;
vtkSmartPointer<vtkColorTransferFunction> TransferFunction;
vtkRectf Position;
private:
vtk2DHistogramItem(const vtk2DHistogramItem &); // Not implemented.
void operator=(const vtk2DHistogramItem &); // Not implemented.
//ETX
};
#endif //__vtk2DHistogramItem_h
/*=========================================================================
Program: Visualization Toolkit
Module: vtkChart2DHistogram.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 "vtkChart2DHistogram.h"
#include "vtkContext2D.h"
#include "vtkBrush.h"
#include "vtkPen.h"
#include "vtkContextScene.h"
#include "vtkContextMouseEvent.h"
#include "vtkTextProperty.h"
#include "vtkAxis.h"
#include "vtk2DHistogramItem.h"
#include "vtkContextTransform.h"
#include "vtkSmartPointer.h"
#include "vtkTransform2D.h"
#include "vtkObjectFactory.h"
#include "vtkCommand.h"
#include <vector>
// Minimal storage class for STL containers etc.
class vtkChart2DHistogram::Private
{
public:
Private()
{
this->Transform = vtkSmartPointer<vtkContextTransform>::New();
}
~Private()
{
for(std::vector<vtkAxis *>::iterator it = this->Axes.begin();
it != this->Axes.end(); ++it)
{
(*it)->Delete();
}
}
vtkSmartPointer<vtkContextTransform> Transform;
std::vector<vtkAxis *> Axes;
};
//-----------------------------------------------------------------------------
vtkStandardNewMacro(vtkChart2DHistogram);
//-----------------------------------------------------------------------------
vtkChart2DHistogram::vtkChart2DHistogram()
{
this->Storage = new vtkChart2DHistogram::Private;
// Now for the 2D histogram
this->AddItem(this->Storage->Transform);
this->Histogram = vtkSmartPointer<vtk2DHistogramItem>::New();
this->Storage->Transform->AddItem(this->Histogram);
// Setup the axes
for (int i = 0; i < 2; ++i)
{
this->Storage->Axes.push_back(vtkAxis::New());
this->AddItem(this->Storage->Axes.back());
this->Storage->Axes[i]->SetPosition(i);
}
}
//-----------------------------------------------------------------------------
vtkChart2DHistogram::~vtkChart2DHistogram()
{
delete this->Storage;
}
//-----------------------------------------------------------------------------
void vtkChart2DHistogram::Update()
{
for(std::vector<vtkAxis *>::iterator it = this->Storage->Axes.begin();
it != this->Storage->Axes.end(); ++it)
{
(*it)->Update();
}
}
//-----------------------------------------------------------------------------
bool vtkChart2DHistogram::Paint(vtkContext2D *painter)
{
int geometry[] = { this->GetScene()->GetSceneWidth(),
this->GetScene()->GetSceneHeight() };
if (geometry[0] == 0 || geometry[1] == 0 || !this->Visible)
{
// The geometry of the chart must be valid before anything can be drawn
return false;
}
this->Update();
if (geometry[0] != this->Geometry[0] || geometry[1] != this->Geometry[1] ||
this->MTime > this->Storage->Axes[0]->GetMTime())
{
// Take up the entire window right now, this could be made configurable
this->SetGeometry(geometry);
}
this->UpdateGeometry();
this->PaintChildren(painter);
return true;
}
void vtkChart2DHistogram::SetInput(vtkImageData *data, vtkIdType z)
{
this->Histogram->SetInput(data, z);
}
void vtkChart2DHistogram::SetTransferFunction(vtkColorTransferFunction *function)
{
this->Histogram->SetTransferFunction(function);
}
//-----------------------------------------------------------------------------
vtkPlot* vtkChart2DHistogram::GetPlot(vtkIdType)
{
return NULL;
}
//-----------------------------------------------------------------------------
vtkIdType vtkChart2DHistogram::GetNumberOfPlots()
{
return 1;
}
//-----------------------------------------------------------------------------
vtkAxis* vtkChart2DHistogram::GetAxis(int index)
{
if (index < this->GetNumberOfAxes())
{
return this->Storage->Axes[index];
}
else
{
return NULL;
}
}
//-----------------------------------------------------------------------------
vtkIdType vtkChart2DHistogram::GetNumberOfAxes()
{
return this->Storage->Axes.size();
}
//-----------------------------------------------------------------------------
void vtkChart2DHistogram::UpdateGeometry()
{
this->SetBorders(20, 20, 20, 20);
double bounds[4];
this->Histogram->GetBounds(bounds);
vtkAxis *axis = this->Storage->Axes[vtkAxis::LEFT];
axis->SetRange(bounds[2], bounds[3]);
axis->SetPoint1(this->Point1[0], this->Point1[1]);
axis->SetPoint2(this->Point1[0], this->Point2[1]);
axis->AutoScale();
axis->Update();
axis = this->Storage->Axes[vtkAxis::BOTTOM];
axis->SetRange(bounds[0], bounds[1]);
axis->SetPoint1(this->Point1[0], this->Point1[1]);
axis->SetPoint2(this->Point2[0], this->Point1[1]);
axis->AutoScale();
axis->Update();
this->CalculatePlotTransform(this->Storage->Axes[vtkAxis::BOTTOM],
this->Storage->Axes[vtkAxis::LEFT],
this->Storage->Transform->GetTransform());
}
//-----------------------------------------------------------------------------
void vtkChart2DHistogram::RecalculateBounds()
{
return;
}
//-----------------------------------------------------------------------------
bool vtkChart2DHistogram::Hit(const vtkContextMouseEvent &mouse)
{
if (mouse.ScreenPos[0] > this->Point1[0]-10 &&
mouse.ScreenPos[0] < this->Point2[0]+10 &&
mouse.ScreenPos[1] > this->Point1[1] &&
mouse.ScreenPos[1] < this->Point2[1])
{
return true;
}
else
{
return false;
}
}
//-----------------------------------------------------------------------------
bool vtkChart2DHistogram::MouseEnterEvent(const vtkContextMouseEvent &)
{
return true;
}
//-----------------------------------------------------------------------------
bool vtkChart2DHistogram::MouseMoveEvent(const vtkContextMouseEvent &mouse)
{
return true;
}
//-----------------------------------------------------------------------------
bool vtkChart2DHistogram::MouseLeaveEvent(const vtkContextMouseEvent &)
{
return true;
}
//-----------------------------------------------------------------------------
bool vtkChart2DHistogram::MouseButtonPressEvent(
const vtkContextMouseEvent& mouse)
{
return false;
}
//-----------------------------------------------------------------------------
bool vtkChart2DHistogram::MouseButtonReleaseEvent(
const vtkContextMouseEvent& mouse)
{
return false;
}
//-----------------------------------------------------------------------------
bool vtkChart2DHistogram::MouseWheelEvent(const vtkContextMouseEvent &,
int)
{
return true;
}
//-----------------------------------------------------------------------------
void vtkChart2DHistogram::PrintSelf(ostream &os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkChart2DHistogram.h
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.
=========================================================================*/
// .NAME vtkChart2DHistogram - Chart for 2D histograms.
//
// .SECTION Description
// This defines the interface for a 2D histogram chart.
#ifndef __vtkChart2DHistogram_h
#define __vtkChart2DHistogram_h
#include "vtkChart.h"
#include "vtkSmartPointer.h" // For SP ivars