Skip to content
Snippets Groups Projects
Commit 4723716c authored by Jeff Baumes's avatar Jeff Baumes
Browse files

ENH: Adding a tree layout example to VTK.

parent acd4b717
No related branches found
No related tags found
No related merge requests found
PROJECT(Infovis)
FIND_PACKAGE(VTK REQUIRED)
IF(NOT VTK_USE_RENDERING)
MESSAGE(FATAL_ERROR "Example ${PROJECT_NAME} requires VTK_USE_RENDERING.")
ENDIF(NOT VTK_USE_RENDERING)
IF(NOT VTK_USE_INFOVIS)
MESSAGE(FATAL_ERROR "Example ${PROJECT_NAME} requires VTK_USE_INFOVIS.")
ENDIF(NOT VTK_USE_INFOVIS)
INCLUDE(${VTK_USE_FILE})
ADD_EXECUTABLE(TreeLayout TreeLayout.cxx)
TARGET_LINK_LIBRARIES(TreeLayout vtkInfovis vtkRendering vtkImaging vtkIO)
/*=========================================================================
Program: Visualization Toolkit
Module: TreeLayout.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.
=========================================================================*/
//
// This example shows how to create a simple tree view from an XML file.
// You may specify the label array and color array from the command line.
//
#include "vtkActor.h"
#include "vtkActor2D.h"
#include "vtkDynamic2DLabelMapper.h"
#include "vtkGlyph3D.h"
#include "vtkGlyphSource2D.h"
#include "vtkGraphLayout.h"
#include "vtkGraphToPolyData.h"
#include "vtkInteractorStyleImage.h"
#include "vtkPointData.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkStringToNumeric.h"
#include "vtkTextProperty.h"
#include "vtkTreeLayoutStrategy.h"
#include "vtkXMLTreeReader.h"
void usage()
{
cerr << endl;
cerr << "usage: TreeLayout filename [label_attribute] [color_attribute]" << endl;
cerr << " filename is an xml file" << endl;
cerr << " label_attribute is the attribute to use as labels." << endl;
cerr << " Default is .tagname which labels using the element tag." << endl;
cerr << " color_attribute is the attribute to color by (numeric)." << endl;
cerr << " Default is no color." << endl;
}
int main(int argc, char* argv[])
{
// Initialize parameters from the command line.
char* labelArray = ".tagname";
char* colorArray = NULL;
if (argc < 2)
{
usage();
return 0;
}
char* filename = argv[1];
if (argc >= 3)
{
labelArray = argv[2];
}
if (argc >= 4)
{
colorArray = argv[3];
}
// Read in the XML file into a tree.
// This creates a tree with string columns for every attribute
// present in the file, plus the special arrays named .tagname
// (containing the XML tag name) and .chardata (containg the
// character data within the tag).
vtkXMLTreeReader* reader = vtkXMLTreeReader::New();
reader->SetFileName(filename);
// Automatically convert string columns containing numeric
// values into integer and double arrays.
vtkStringToNumeric* stringToNumeric = vtkStringToNumeric::New();
stringToNumeric->SetInputConnection(reader->GetOutputPort());
// Retrieve the tree from the pipeline so we can check whether
// the specified label and color arrays exist.
stringToNumeric->Update();
vtkTree* tree = vtkTree::SafeDownCast(stringToNumeric->GetOutput());
if (tree->GetVertexData()->GetAbstractArray(labelArray) == NULL)
{
cerr << "ERROR: The label attribute " << labelArray << " is not defined in the file." << endl;
reader->Delete();
stringToNumeric->Delete();
usage();
return 0;
}
if (colorArray &&
tree->GetVertexData()->GetAbstractArray(colorArray) == NULL)
{
cerr << "ERROR: The color attribute " << colorArray << " is not defined in the file." << endl;
reader->Delete();
stringToNumeric->Delete();
usage();
return 0;
}
if (colorArray &&
vtkDataArray::SafeDownCast(tree->GetVertexData()->GetAbstractArray(colorArray)) == NULL)
{
cerr << "ERROR: The color attribute " << colorArray << " does not have numeric values." << endl;
reader->Delete();
stringToNumeric->Delete();
usage();
return 0;
}
// If coloring the vertices, get the range of the color array.
double colorRange[2] = {0, 1};
if (colorArray)
{
vtkDataArray* color = vtkDataArray::SafeDownCast(
tree->GetVertexData()->GetAbstractArray(colorArray));
color->GetRange(colorRange);
}
// Layout the tree using vtkGraphLayout.
vtkGraphLayout* layout = vtkGraphLayout::New();
layout->SetInputConnection(stringToNumeric->GetOutputPort());
// Specify that we want to use the tree layout strategy.
vtkTreeLayoutStrategy* strategy = vtkTreeLayoutStrategy::New();
strategy->RadialOn(); // Radial layout (as opposed to standard top-down layout)
strategy->SetAngle(360.0); // The tree fills a full circular arc.
layout->SetLayoutStrategy(strategy);
// vtkGraphToPolyData converts a graph or tree to polydata.
vtkGraphToPolyData* graphToPoly = vtkGraphToPolyData::New();
graphToPoly->SetInputConnection(layout->GetOutputPort());
// Create the standard VTK polydata mapper and actor
// for the connections (edges) in the tree.
vtkPolyDataMapper* edgeMapper = vtkPolyDataMapper::New();
edgeMapper->SetInputConnection(graphToPoly->GetOutputPort());
vtkActor* edgeActor = vtkActor::New();
edgeActor->SetMapper(edgeMapper);
edgeActor->GetProperty()->SetColor(0.0, 0.5, 1.0);
// Glyph the points of the tree polydata to create
// VTK_VERTEX cells at each vertex in the tree.
vtkGlyph3D* vertGlyph = vtkGlyph3D::New();
vertGlyph->SetInputConnection(0, graphToPoly->GetOutputPort());
vtkGlyphSource2D* glyphSource = vtkGlyphSource2D::New();
glyphSource->SetGlyphTypeToVertex();
vertGlyph->SetInputConnection(1, glyphSource->GetOutputPort());
// Create a mapper for the vertices, and tell the mapper
// to use the specified color array.
vtkPolyDataMapper* vertMapper = vtkPolyDataMapper::New();
vertMapper->SetInputConnection(vertGlyph->GetOutputPort());
if (colorArray)
{
vertMapper->SetScalarModeToUsePointFieldData();
vertMapper->SelectColorArray(colorArray);
vertMapper->SetScalarRange(colorRange);
}
// Create an actor for the vertices. Move the actor forward
// in the z direction so it is drawn on top of the edge actor.
vtkActor* vertActor = vtkActor::New();
vertActor->SetMapper(vertMapper);
vertActor->GetProperty()->SetPointSize(5);
vertActor->SetPosition(0, 0, 0.001);
// Use a dynamic label mapper to draw the labels. This mapper
// does not allow labels to overlap, as long as the camera is
// not rotated from pointing down the z axis.
vtkDynamic2DLabelMapper* labelMapper = vtkDynamic2DLabelMapper::New();
labelMapper->SetInputConnection(graphToPoly->GetOutputPort());
labelMapper->GetLabelTextProperty()->SetJustificationToLeft();
labelMapper->GetLabelTextProperty()->SetColor(0, 0, 0);
if (labelArray)
{
labelMapper->SetLabelModeToLabelFieldData();
labelMapper->SetFieldDataName(labelArray);
}
vtkActor2D* labelActor = vtkActor2D::New();
labelActor->SetMapper(labelMapper);
// Add the edges, vertices, and labels to the renderer.
vtkRenderer* ren = vtkRenderer::New();
ren->SetBackground(0.8, 0.8, 0.8);
ren->AddActor(edgeActor);
ren->AddActor(vertActor);
ren->AddActor(labelActor);
// Setup the render window and interactor.
vtkRenderWindow* win = vtkRenderWindow::New();
win->AddRenderer(ren);
vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(win);
// Constrain movement to zoom and pan using the image interactor style.
vtkInteractorStyleImage* style = vtkInteractorStyleImage::New();
iren->SetInteractorStyle(style);
// Start the main application loop.
iren->Initialize();
iren->Start();
// Clean up.
style->Delete();
iren->Delete();
win->Delete();
ren->Delete();
labelActor->Delete();
labelMapper->Delete();
vertActor->Delete();
vertMapper->Delete();
glyphSource->Delete();
vertGlyph->Delete();
edgeMapper->Delete();
edgeActor->Delete();
graphToPoly->Delete();
strategy->Delete();
layout->Delete();
stringToNumeric->Delete();
reader->Delete();
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment