mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
374 lines
11 KiB
C++
374 lines
11 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkBoostBreadthFirstSearch.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.
|
|
-------------------------------------------------------------------------*/
|
|
/*
|
|
* Copyright (C) 2008 The Trustees of Indiana University.
|
|
* Use, modification and distribution is subject to the Boost Software
|
|
* License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt)
|
|
*/
|
|
#include "vtkBoostBreadthFirstSearch.h"
|
|
|
|
#include "vtkCellArray.h"
|
|
#include "vtkCellData.h"
|
|
#include "vtkConvertSelection.h"
|
|
#include "vtkMath.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkFloatArray.h"
|
|
#include "vtkDataArray.h"
|
|
#include "vtkSelection.h"
|
|
#include "vtkSelectionNode.h"
|
|
#include "vtkSmartPointer.h"
|
|
#include "vtkStringArray.h"
|
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
|
|
|
#include "vtkBoostGraphAdapter.h"
|
|
#include "vtkDirectedGraph.h"
|
|
#include "vtkUndirectedGraph.h"
|
|
|
|
#include <boost/graph/visitors.hpp>
|
|
#include <boost/graph/breadth_first_search.hpp>
|
|
#include <boost/pending/queue.hpp>
|
|
|
|
#include <utility> // for pair
|
|
|
|
using namespace boost;
|
|
|
|
vtkStandardNewMacro(vtkBoostBreadthFirstSearch);
|
|
|
|
// Redefine the bfs visitor, the only visitor we
|
|
// are using is the tree_edge visitor.
|
|
template <typename DistanceMap>
|
|
class my_distance_recorder : public default_bfs_visitor
|
|
{
|
|
public:
|
|
my_distance_recorder() { }
|
|
my_distance_recorder(DistanceMap dist, vtkIdType* far)
|
|
: d(dist), far_vertex(far), far_dist(-1) { *far_vertex = -1; }
|
|
|
|
template <typename Vertex, typename Graph>
|
|
void examine_vertex(Vertex v, const Graph& vtkNotUsed(g))
|
|
{
|
|
if (get(d, v) > far_dist)
|
|
{
|
|
*far_vertex = v;
|
|
far_dist = get(d, v);
|
|
}
|
|
}
|
|
|
|
template <typename Edge, typename Graph>
|
|
void tree_edge(Edge e, const Graph& g)
|
|
{
|
|
typename graph_traits<Graph>::vertex_descriptor
|
|
u = source(e, g), v = target(e, g);
|
|
put(d, v, get(d, u) + 1);
|
|
}
|
|
|
|
private:
|
|
DistanceMap d;
|
|
vtkIdType* far_vertex;
|
|
vtkIdType far_dist;
|
|
};
|
|
|
|
// Constructor/Destructor
|
|
vtkBoostBreadthFirstSearch::vtkBoostBreadthFirstSearch()
|
|
{
|
|
// Default values for the origin vertex
|
|
this->OriginVertexIndex = 0;
|
|
this->InputArrayName = 0;
|
|
this->OutputArrayName = 0;
|
|
this->OutputSelectionType = 0;
|
|
this->SetOutputSelectionType("MAX_DIST_FROM_ROOT");
|
|
this->OriginValue = -1;
|
|
this->OutputSelection = false;
|
|
this->OriginFromSelection = false;
|
|
this->SetNumberOfInputPorts(2);
|
|
this->SetNumberOfOutputPorts(2);
|
|
}
|
|
|
|
vtkBoostBreadthFirstSearch::~vtkBoostBreadthFirstSearch()
|
|
{
|
|
this->SetInputArrayName(0);
|
|
this->SetOutputArrayName(0);
|
|
this->SetOutputSelectionType(0);
|
|
}
|
|
|
|
void vtkBoostBreadthFirstSearch::SetOriginSelection(vtkSelection* s)
|
|
{
|
|
this->SetInputData(1, s);
|
|
}
|
|
|
|
// Description:
|
|
// Set the index (into the vertex array) of the
|
|
// breadth first search 'origin' vertex.
|
|
void vtkBoostBreadthFirstSearch::SetOriginVertex(vtkIdType index)
|
|
{
|
|
this->OriginVertexIndex = index;
|
|
this->InputArrayName = NULL; // Reset any origin set by another method
|
|
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 vtkBoostBreadthFirstSearch::SetOriginVertex(
|
|
vtkStdString arrayName, vtkVariant value)
|
|
{
|
|
this->SetInputArrayName(arrayName);
|
|
this->OriginValue = value;
|
|
this->Modified();
|
|
}
|
|
|
|
void vtkBoostBreadthFirstSearch::SetOriginVertexString(
|
|
char* arrayName, char* value)
|
|
{
|
|
this->SetOriginVertex(arrayName, value);
|
|
}
|
|
|
|
vtkIdType vtkBoostBreadthFirstSearch::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 vtkBoostBreadthFirstSearch::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()));
|
|
vtkGraph *output = vtkGraph::SafeDownCast(
|
|
outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
|
|
// Send the data to output.
|
|
output->ShallowCopy(input);
|
|
|
|
// Sanity check
|
|
// The Boost BFS likes to crash on empty datasets
|
|
if (input->GetNumberOfVertices() == 0)
|
|
{
|
|
//vtkWarningMacro("Empty input into " << this->GetClassName());
|
|
return 1;
|
|
}
|
|
|
|
if (this->OriginFromSelection)
|
|
{
|
|
vtkSelection* selection = vtkSelection::GetData(inputVector[1], 0);
|
|
if (selection == NULL)
|
|
{
|
|
vtkErrorMacro("OriginFromSelection set but selection input undefined.");
|
|
return 0;
|
|
}
|
|
vtkSmartPointer<vtkIdTypeArray> idArr =
|
|
vtkSmartPointer<vtkIdTypeArray>::New();
|
|
vtkConvertSelection::GetSelectedVertices(selection, input, idArr);
|
|
if (idArr->GetNumberOfTuples() == 0)
|
|
{
|
|
vtkErrorMacro("Origin selection is empty.");
|
|
return 0;
|
|
}
|
|
this->OriginVertexIndex = idArr->GetValue(0);
|
|
}
|
|
else
|
|
{
|
|
// Now figure out the origin vertex of the
|
|
// breadth first search
|
|
if (this->InputArrayName)
|
|
{
|
|
vtkAbstractArray* abstract = input->GetVertexData()->GetAbstractArray(this->InputArrayName);
|
|
|
|
// Does the array exist at all?
|
|
if (abstract == NULL)
|
|
{
|
|
vtkErrorMacro("Could not find array named " << this->InputArrayName);
|
|
return 0;
|
|
}
|
|
|
|
this->OriginVertexIndex = this->GetVertexIndex(abstract,this->OriginValue);
|
|
}
|
|
}
|
|
|
|
// Create the attribute array
|
|
vtkIntArray* BFSArray = vtkIntArray::New();
|
|
if (this->OutputArrayName)
|
|
{
|
|
BFSArray->SetName(this->OutputArrayName);
|
|
}
|
|
else
|
|
{
|
|
BFSArray->SetName("BFS");
|
|
}
|
|
BFSArray->SetNumberOfTuples(output->GetNumberOfVertices());
|
|
|
|
// Initialize the BFS array to all 0's
|
|
for(int i=0;i< BFSArray->GetNumberOfTuples(); ++i)
|
|
{
|
|
BFSArray->SetValue(i, VTK_INT_MAX);
|
|
}
|
|
|
|
vtkIdType maxFromRootVertex = this->OriginVertexIndex;
|
|
|
|
// Create a color map (used for marking visited nodes)
|
|
vector_property_map<default_color_type> color(output->GetNumberOfVertices());
|
|
|
|
// Set the distance to the source vertex to zero
|
|
BFSArray->SetValue(this->OriginVertexIndex, 0);
|
|
|
|
// Create a queue to hand off to the BFS
|
|
boost::queue<int> Q;
|
|
|
|
my_distance_recorder<vtkIntArray*> bfsVisitor(BFSArray, &maxFromRootVertex);
|
|
|
|
// Is the graph directed or undirected
|
|
if (vtkDirectedGraph::SafeDownCast(output))
|
|
{
|
|
vtkDirectedGraph *g = vtkDirectedGraph::SafeDownCast(output);
|
|
breadth_first_search(g, this->OriginVertexIndex, Q, bfsVisitor, color);
|
|
}
|
|
else
|
|
{
|
|
vtkUndirectedGraph *g = vtkUndirectedGraph::SafeDownCast(output);
|
|
breadth_first_search(g, this->OriginVertexIndex, Q, bfsVisitor, color);
|
|
}
|
|
|
|
// Add attribute array to the output
|
|
output->GetVertexData()->AddArray(BFSArray);
|
|
BFSArray->Delete();
|
|
|
|
if (this->OutputSelection)
|
|
{
|
|
vtkSelection* sel = vtkSelection::GetData(outputVector, 1);
|
|
vtkIdTypeArray* ids = vtkIdTypeArray::New();
|
|
|
|
// Set the output based on the output selection type
|
|
if (!strcmp(OutputSelectionType,"MAX_DIST_FROM_ROOT"))
|
|
{
|
|
ids->InsertNextValue(maxFromRootVertex);
|
|
}
|
|
|
|
vtkSmartPointer<vtkSelectionNode> node = vtkSmartPointer<vtkSelectionNode>::New();
|
|
sel->AddNode(node);
|
|
node->SetSelectionList(ids);
|
|
node->GetProperties()->Set(vtkSelectionNode::CONTENT_TYPE(), vtkSelectionNode::INDICES);
|
|
node->GetProperties()->Set(vtkSelectionNode::FIELD_TYPE(), vtkSelectionNode::VERTEX);
|
|
ids->Delete();
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void vtkBoostBreadthFirstSearch::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os, indent);
|
|
|
|
os << indent << "OriginVertexIndex: " << this->OriginVertexIndex << endl;
|
|
|
|
os << indent << "InputArrayName: "
|
|
<< (this->InputArrayName ? this->InputArrayName : "(none)") << endl;
|
|
|
|
os << indent << "OutputArrayName: "
|
|
<< (this->OutputArrayName ? this->OutputArrayName : "(none)") << endl;
|
|
|
|
os << indent << "OriginValue: " << this->OriginValue.ToString() << endl;
|
|
|
|
os << indent << "OutputSelection: "
|
|
<< (this->OutputSelection ? "on" : "off") << endl;
|
|
|
|
os << indent << "OriginFromSelection: "
|
|
<< (this->OriginFromSelection ? "on" : "off") << endl;
|
|
|
|
os << indent << "OutputSelectionType: "
|
|
<< (this->OutputSelectionType ? this->OutputSelectionType : "(none)") << endl;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkBoostBreadthFirstSearch::FillInputPortInformation(
|
|
int port, vtkInformation* info)
|
|
{
|
|
// now add our info
|
|
if (port == 0)
|
|
{
|
|
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGraph");
|
|
}
|
|
else if (port == 1)
|
|
{
|
|
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkSelection");
|
|
info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkBoostBreadthFirstSearch::FillOutputPortInformation(
|
|
int port, vtkInformation* info)
|
|
{
|
|
// now add our info
|
|
if (port == 0)
|
|
{
|
|
info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkGraph");
|
|
}
|
|
else if (port == 1)
|
|
{
|
|
info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkSelection");
|
|
}
|
|
return 1;
|
|
}
|
|
|