mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
338 lines
9.8 KiB
C++
338 lines
9.8 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkBoostBreadthFirstSearchTree.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.
|
|
|
|
=========================================================================*/
|
|
/*-------------------------------------------------------------------------
|
|
Copyright 2008 Sandia Corporation.
|
|
Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
|
the U.S. Government retains certain rights in this software.
|
|
-------------------------------------------------------------------------*/
|
|
#include "vtkBoostBreadthFirstSearchTree.h"
|
|
|
|
#include "vtkCellArray.h"
|
|
#include "vtkCellData.h"
|
|
#include "vtkMath.h"
|
|
#include "vtkIdTypeArray.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkPoints.h"
|
|
#include "vtkFloatArray.h"
|
|
#include "vtkDataArray.h"
|
|
#include "vtkSmartPointer.h"
|
|
#include "vtkStringArray.h"
|
|
|
|
#include "vtkBoostGraphAdapter.h"
|
|
#include "vtkMutableDirectedGraph.h"
|
|
#include "vtkUndirectedGraph.h"
|
|
#include "vtkTree.h"
|
|
|
|
#include <boost/graph/breadth_first_search.hpp>
|
|
#include <boost/graph/reverse_graph.hpp>
|
|
#include <boost/pending/queue.hpp>
|
|
|
|
using namespace boost;
|
|
|
|
vtkStandardNewMacro(vtkBoostBreadthFirstSearchTree);
|
|
|
|
|
|
#if BOOST_VERSION >= 104800 // Boost 1.48.x
|
|
namespace {
|
|
vtkIdType unwrap_edge_id(vtkEdgeType const &e)
|
|
{
|
|
return e.Id;
|
|
}
|
|
vtkIdType unwrap_edge_id(boost::detail::reverse_graph_edge_descriptor<vtkEdgeType> const &e)
|
|
{
|
|
# if BOOST_VERSION == 104800
|
|
return e.underlying_desc.Id;
|
|
# else
|
|
return e.underlying_descx.Id;
|
|
# endif
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Redefine the bfs visitor, the only visitor we
|
|
// are using is the tree_edge visitor.
|
|
template <typename IdMap>
|
|
class bfs_tree_builder : public default_bfs_visitor
|
|
{
|
|
public:
|
|
bfs_tree_builder()
|
|
{ }
|
|
|
|
bfs_tree_builder(IdMap& g2t, IdMap& t2g, vtkGraph* g, vtkMutableDirectedGraph* t, vtkIdType root)
|
|
: graph_to_tree(g2t), tree_to_graph(t2g), tree(t), graph(g)
|
|
{
|
|
double x[3];
|
|
graph->GetPoints()->GetPoint(root, x);
|
|
tree->GetPoints()->InsertNextPoint(x);
|
|
vtkIdType tree_root = t->AddVertex();
|
|
put(graph_to_tree, root, tree_root);
|
|
put(tree_to_graph, tree_root, root);
|
|
tree->GetVertexData()->CopyData(graph->GetVertexData(), root, tree_root);
|
|
}
|
|
|
|
template <typename Edge, typename Graph>
|
|
void tree_edge(Edge e, const Graph& g) const
|
|
{
|
|
typename graph_traits<Graph>::vertex_descriptor u, v;
|
|
u = source(e, g);
|
|
v = target(e, g);
|
|
|
|
// Get the source vertex id (it has already been visited).
|
|
vtkIdType tree_u = get(graph_to_tree, u);
|
|
|
|
// Add the point before the vertex so that
|
|
// points match the number of vertices, so that GetPoints()
|
|
// doesn't reallocate and zero-out points.
|
|
double x[3];
|
|
graph->GetPoints()->GetPoint(v, x);
|
|
tree->GetPoints()->InsertNextPoint(x);
|
|
|
|
// Create the target vertex in the tree.
|
|
vtkIdType tree_v = tree->AddVertex();
|
|
vtkEdgeType tree_e = tree->AddEdge(tree_u, tree_v);
|
|
|
|
// Store the mapping from graph to tree.
|
|
put(graph_to_tree, v, tree_v);
|
|
put(tree_to_graph, tree_v, v);
|
|
|
|
// Copy the vertex and edge data from the graph to the tree.
|
|
tree->GetVertexData()->CopyData(graph->GetVertexData(), v, tree_v);
|
|
#if BOOST_VERSION < 104800 // Boost 1.48.x
|
|
tree->GetEdgeData()->CopyData(graph->GetEdgeData(), e.Id, tree_e.Id);
|
|
#else
|
|
tree->GetEdgeData()->CopyData(graph->GetEdgeData(),
|
|
unwrap_edge_id(e), tree_e.Id);
|
|
#endif
|
|
}
|
|
|
|
private:
|
|
IdMap graph_to_tree;
|
|
IdMap tree_to_graph;
|
|
vtkMutableDirectedGraph *tree;
|
|
vtkGraph *graph;
|
|
};
|
|
|
|
// Constructor/Destructor
|
|
vtkBoostBreadthFirstSearchTree::vtkBoostBreadthFirstSearchTree()
|
|
{
|
|
// Default values for the origin vertex
|
|
this->OriginVertexIndex = 0;
|
|
this->ArrayName = 0;
|
|
this->SetArrayName("Not Set");
|
|
this->ArrayNameSet = false;
|
|
this->OriginValue = 0;
|
|
this->CreateGraphVertexIdArray = false;
|
|
this->ReverseEdges = false;
|
|
}
|
|
|
|
vtkBoostBreadthFirstSearchTree::~vtkBoostBreadthFirstSearchTree()
|
|
{
|
|
this->SetArrayName(NULL);
|
|
}
|
|
|
|
// Description:
|
|
// Set the index (into the vertex array) of the
|
|
// breadth first search 'origin' vertex.
|
|
void vtkBoostBreadthFirstSearchTree::SetOriginVertex(vtkIdType index)
|
|
{
|
|
this->OriginVertexIndex = index;
|
|
this->ArrayNameSet = false;
|
|
this->Modified();
|
|
}
|
|
|
|
// Description:
|
|
// Set the breadth first search 'origin' vertex.
|
|
// This method is basically the same as above
|
|
// but allows the application to simply specify
|
|
// an array name and value, instead of having to
|
|
// know the specific index of the vertex.
|
|
void vtkBoostBreadthFirstSearchTree::SetOriginVertex(
|
|
vtkStdString arrayName, vtkVariant value)
|
|
{
|
|
this->SetArrayName(arrayName);
|
|
this->ArrayNameSet = true;
|
|
this->OriginValue = value;
|
|
this->Modified();
|
|
}
|
|
|
|
vtkIdType vtkBoostBreadthFirstSearchTree::GetVertexIndex(
|
|
vtkAbstractArray *abstract,vtkVariant value)
|
|
{
|
|
|
|
// Okay now what type of array is it
|
|
if (abstract->IsNumeric())
|
|
{
|
|
vtkDataArray *dataArray = vtkDataArray::SafeDownCast(abstract);
|
|
int intValue = value.ToInt();
|
|
for(int i=0; i<dataArray->GetNumberOfTuples(); ++i)
|
|
{
|
|
if (intValue == static_cast<int>(dataArray->GetTuple1(i)))
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vtkStringArray *stringArray = vtkStringArray::SafeDownCast(abstract);
|
|
vtkStdString stringValue(value.ToString());
|
|
for(int i=0; i<stringArray->GetNumberOfTuples(); ++i)
|
|
{
|
|
if (stringValue == stringArray->GetValue(i))
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Failed
|
|
vtkErrorMacro("Did not find a valid vertex index...");
|
|
return 0;
|
|
}
|
|
|
|
int vtkBoostBreadthFirstSearchTree::FillInputPortInformation(
|
|
int vtkNotUsed(port), vtkInformation* info)
|
|
{
|
|
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGraph");
|
|
return 1;
|
|
}
|
|
|
|
int vtkBoostBreadthFirstSearchTree::RequestData(
|
|
vtkInformation *vtkNotUsed(request),
|
|
vtkInformationVector **inputVector,
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
// get the info objects
|
|
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
|
|
vtkInformation *outInfo = outputVector->GetInformationObject(0);
|
|
|
|
// get the input and output
|
|
vtkGraph *input = vtkGraph::SafeDownCast(
|
|
inInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
|
|
// Now figure out the origin vertex of the
|
|
// breadth first search
|
|
if (this->ArrayNameSet)
|
|
{
|
|
vtkAbstractArray* abstract = input->GetVertexData()->GetAbstractArray(this->ArrayName);
|
|
|
|
// Does the array exist at all?
|
|
if (abstract == NULL)
|
|
{
|
|
vtkErrorMacro("Could not find array named " << this->ArrayName);
|
|
return 0;
|
|
}
|
|
|
|
this->OriginVertexIndex = this->GetVertexIndex(abstract,this->OriginValue);
|
|
}
|
|
|
|
// Create tree to graph id map array
|
|
vtkIdTypeArray* treeToGraphIdMap = vtkIdTypeArray::New();
|
|
|
|
// Create graph to tree id map array
|
|
vtkIdTypeArray* graphToTreeIdMap = vtkIdTypeArray::New();
|
|
|
|
// Create a color map (used for marking visited nodes)
|
|
vector_property_map<default_color_type> color;
|
|
|
|
// Create a queue to hand off to the BFS
|
|
queue<int> q;
|
|
|
|
// Create the mutable graph to build the tree
|
|
vtkSmartPointer<vtkMutableDirectedGraph> temp =
|
|
vtkSmartPointer<vtkMutableDirectedGraph>::New();
|
|
// Initialize copying data into tree
|
|
temp->GetFieldData()->PassData(input->GetFieldData());
|
|
temp->GetVertexData()->CopyAllocate(input->GetVertexData());
|
|
temp->GetEdgeData()->CopyAllocate(input->GetEdgeData());
|
|
|
|
// Create the visitor which will build the tree
|
|
bfs_tree_builder<vtkIdTypeArray*> builder(
|
|
graphToTreeIdMap, treeToGraphIdMap, input, temp, this->OriginVertexIndex);
|
|
|
|
// Run the algorithm
|
|
if (vtkDirectedGraph::SafeDownCast(input))
|
|
{
|
|
vtkDirectedGraph *g = vtkDirectedGraph::SafeDownCast(input);
|
|
if (this->ReverseEdges)
|
|
{
|
|
#if BOOST_VERSION < 104100 // Boost 1.41.x
|
|
vtkErrorMacro("ReverseEdges requires Boost 1.41.x or higher");
|
|
return 0;
|
|
#else
|
|
boost::reverse_graph<vtkDirectedGraph*> r(g);
|
|
breadth_first_search(r, this->OriginVertexIndex, q, builder, color);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
breadth_first_search(g, this->OriginVertexIndex, q, builder, color);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vtkUndirectedGraph *g = vtkUndirectedGraph::SafeDownCast(input);
|
|
breadth_first_search(g, this->OriginVertexIndex, q, builder, color);
|
|
}
|
|
|
|
// If the user wants it, store the mapping back to graph vertices
|
|
if (this->CreateGraphVertexIdArray)
|
|
{
|
|
treeToGraphIdMap->SetName("GraphVertexId");
|
|
temp->GetVertexData()->AddArray(treeToGraphIdMap);
|
|
}
|
|
|
|
// Copy the builder graph structure into the output tree
|
|
vtkTree *output = vtkTree::SafeDownCast(
|
|
outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
if (!output->CheckedShallowCopy(temp))
|
|
{
|
|
vtkErrorMacro(<<"Invalid tree.");
|
|
return 0;
|
|
}
|
|
|
|
// Clean up
|
|
output->Squeeze();
|
|
graphToTreeIdMap->Delete();
|
|
treeToGraphIdMap->Delete();
|
|
|
|
return 1;
|
|
}
|
|
|
|
void vtkBoostBreadthFirstSearchTree::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os, indent);
|
|
|
|
os << indent << "OriginVertexIndex: " << this->OriginVertexIndex << endl;
|
|
|
|
os << indent << "ArrayName: "
|
|
<< (this->ArrayName ? this->ArrayName : "(none)") << endl;
|
|
|
|
os << indent << "OriginValue: " << this->OriginValue.ToString() << endl;
|
|
|
|
os << indent << "ArrayNameSet: "
|
|
<< (this->ArrayNameSet ? "true" : "false") << endl;
|
|
|
|
os << indent << "CreateGraphVertexIdArray: "
|
|
<< (this->CreateGraphVertexIdArray ? "on" : "off") << endl;
|
|
|
|
os << indent << "ReverseEdges: "
|
|
<< (this->ReverseEdges ? "on" : "off") << endl;
|
|
}
|
|
|