Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
1449 lines (1262 sloc) 44.1 KB
/*=========================================================================
Program: Visualization Toolkit
Module: vtkAlgorithm.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 "vtkAlgorithm.h"
#include "vtkAlgorithmOutput.h"
#include "vtkCellData.h"
#include "vtkCommand.h"
#include "vtkDataArray.h"
#include "vtkDataObject.h"
#include "vtkDataSet.h"
#include "vtkErrorCode.h"
#include "vtkFieldData.h"
#include "vtkGarbageCollector.h"
#include "vtkGraph.h"
#include "vtkInformation.h"
#include "vtkInformationExecutivePortKey.h"
#include "vtkInformationExecutivePortVectorKey.h"
#include "vtkInformationInformationVectorKey.h"
#include "vtkInformationIntegerKey.h"
#include "vtkInformationStringKey.h"
#include "vtkInformationStringVectorKey.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkSmartPointer.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkTable.h"
#include <vtkstd/set>
#include <vtkstd/vector>
vtkStandardNewMacro(vtkAlgorithm);
vtkCxxSetObjectMacro(vtkAlgorithm,Information,vtkInformation);
vtkInformationKeyMacro(vtkAlgorithm, INPUT_REQUIRED_DATA_TYPE, StringVector);
vtkInformationKeyMacro(vtkAlgorithm, INPUT_IS_OPTIONAL, Integer);
vtkInformationKeyMacro(vtkAlgorithm, INPUT_IS_REPEATABLE, Integer);
vtkInformationKeyMacro(vtkAlgorithm, INPUT_REQUIRED_FIELDS, InformationVector);
vtkInformationKeyMacro(vtkAlgorithm, PORT_REQUIREMENTS_FILLED, Integer);
vtkInformationKeyMacro(vtkAlgorithm, INPUT_PORT, Integer);
vtkInformationKeyMacro(vtkAlgorithm, INPUT_CONNECTION, Integer);
vtkInformationKeyMacro(vtkAlgorithm, INPUT_ARRAYS_TO_PROCESS, InformationVector);
vtkInformationKeyMacro(vtkAlgorithm, PRESERVES_DATASET, Integer);
vtkInformationKeyMacro(vtkAlgorithm, PRESERVES_GEOMETRY, Integer);
vtkInformationKeyMacro(vtkAlgorithm, PRESERVES_BOUNDS, Integer);
vtkInformationKeyMacro(vtkAlgorithm, PRESERVES_TOPOLOGY, Integer);
vtkInformationKeyMacro(vtkAlgorithm, PRESERVES_ATTRIBUTES, Integer);
vtkInformationKeyMacro(vtkAlgorithm, PRESERVES_RANGES, Integer);
vtkExecutive* vtkAlgorithm::DefaultExecutivePrototype = 0;
//----------------------------------------------------------------------------
class vtkAlgorithmInternals
{
public:
// Proxy object instances for use in establishing connections from
// the output ports to other algorithms.
vtkstd::vector< vtkSmartPointer<vtkAlgorithmOutput> > Outputs;
};
//----------------------------------------------------------------------------
class vtkAlgorithmToExecutiveFriendship
{
public:
static void SetAlgorithm(vtkExecutive* executive, vtkAlgorithm* algorithm)
{
executive->SetAlgorithm(algorithm);
}
};
//----------------------------------------------------------------------------
vtkAlgorithm::vtkAlgorithm()
{
this->AbortExecute = 0;
this->ErrorCode = 0;
this->Progress = 0.0;
this->ProgressText = NULL;
this->Executive = 0;
this->InputPortInformation = vtkInformationVector::New();
this->OutputPortInformation = vtkInformationVector::New();
this->AlgorithmInternal = new vtkAlgorithmInternals;
this->Information = vtkInformation::New();
this->Information->Register(this);
this->Information->Delete();
}
//----------------------------------------------------------------------------
vtkAlgorithm::~vtkAlgorithm()
{
this->SetInformation(0);
if(this->Executive)
{
this->Executive->UnRegister(this);
this->Executive = 0;
}
this->InputPortInformation->Delete();
this->OutputPortInformation->Delete();
delete this->AlgorithmInternal;
delete [] this->ProgressText;
this->ProgressText = NULL;
}
//----------------------------------------------------------------------------
// Update the progress of the process object. If a ProgressMethod exists,
// executes it. Then set the Progress ivar to amount. The parameter amount
// should range between (0,1).
void vtkAlgorithm::UpdateProgress(double amount)
{
this->Progress = amount;
this->InvokeEvent(vtkCommand::ProgressEvent,static_cast<void *>(&amount));
}
//----------------------------------------------------------------------------
vtkInformation *vtkAlgorithm
::GetInputArrayFieldInformation(int idx, vtkInformationVector **inputVector)
{
// first get out association
vtkInformation *info = this->GetInputArrayInformation(idx);
// then get the actual info object from the pinfo
int port = info->Get(INPUT_PORT());
int connection = info->Get(INPUT_CONNECTION());
int fieldAssoc = info->Get(vtkDataObject::FIELD_ASSOCIATION());
vtkInformation *inInfo = inputVector[port]->GetInformationObject(connection);
if (info->Has(vtkDataObject::FIELD_NAME()))
{
const char *name = info->Get(vtkDataObject::FIELD_NAME());
return vtkDataObject::GetNamedFieldInformation(inInfo, fieldAssoc, name);
}
int fType = info->Get(vtkDataObject::FIELD_ATTRIBUTE_TYPE());
return vtkDataObject::GetActiveFieldInformation(inInfo, fieldAssoc, fType);
}
//----------------------------------------------------------------------------
vtkInformation *vtkAlgorithm::GetInputArrayInformation(int idx)
{
// add this info into the algorithms info object
vtkInformationVector *inArrayVec =
this->Information->Get(INPUT_ARRAYS_TO_PROCESS());
if (!inArrayVec)
{
inArrayVec = vtkInformationVector::New();
this->Information->Set(INPUT_ARRAYS_TO_PROCESS(),inArrayVec);
inArrayVec->Delete();
}
vtkInformation *inArrayInfo = inArrayVec->GetInformationObject(idx);
if (!inArrayInfo)
{
inArrayInfo = vtkInformation::New();
inArrayVec->SetInformationObject(idx,inArrayInfo);
inArrayInfo->Delete();
}
return inArrayInfo;
}
//----------------------------------------------------------------------------
void vtkAlgorithm::SetInputArrayToProcess(int idx, vtkInformation *inInfo)
{
vtkInformation *info = this->GetInputArrayInformation(idx);
info->Copy(inInfo,1);
this->Modified();
}
//----------------------------------------------------------------------------
void vtkAlgorithm::SetInputArrayToProcess(int idx, int port, int connection,
int fieldAssociation,
int attributeType)
{
vtkInformation *info = this->GetInputArrayInformation(idx);
info->Set(INPUT_PORT(), port);
info->Set(INPUT_CONNECTION(), connection);
info->Set(vtkDataObject::FIELD_ASSOCIATION(),fieldAssociation);
info->Set(vtkDataObject::FIELD_ATTRIBUTE_TYPE(), attributeType);
// remove name if there is one
info->Remove(vtkDataObject::FIELD_NAME());
this->Modified();
}
//----------------------------------------------------------------------------
void vtkAlgorithm::SetInputArrayToProcess(
int idx, int port, int connection,
const char* fieldAssociation,
const char* fieldAttributeTypeOrName)
{
if (!fieldAssociation)
{
vtkErrorMacro("Association is requied");
return;
}
if (!fieldAttributeTypeOrName)
{
vtkErrorMacro("Attribute type or array name is required");
return ;
}
int i;
// Try to convert the string argument to an enum value
int association = -1;
for (i=0; i<vtkDataObject::NUMBER_OF_ASSOCIATIONS; i++)
{
if (strcmp(fieldAssociation,
vtkDataObject::GetAssociationTypeAsString(i)) == 0)
{
association = i;
break;
}
}
if (association == -1)
{
vtkErrorMacro("Unrecognized association type: " << fieldAssociation);
return;
}
int attributeType = -1;
for (i=0; i<vtkDataSetAttributes::NUM_ATTRIBUTES; i++)
{
if (strcmp(fieldAttributeTypeOrName,
vtkDataSetAttributes::GetLongAttributeTypeAsString(i)) == 0)
{
attributeType = i;
break;
}
}
if (attributeType == -1)
{
// Set by association and array name
this->SetInputArrayToProcess(
idx, port, connection, association, fieldAttributeTypeOrName);
return;
}
// Set by association and attribute type
this->SetInputArrayToProcess(
idx, port, connection, association, attributeType);
}
//----------------------------------------------------------------------------
void vtkAlgorithm::SetInputArrayToProcess(int idx, int port, int connection,
int fieldAssociation,
const char *name)
{
// ignore empty string
if (!name || name[0] == '\0')
{
return;
}
vtkInformation *info = this->GetInputArrayInformation(idx);
// remove fieldAttr if there is one
info->Remove(vtkDataObject::FIELD_ATTRIBUTE_TYPE());
// Check to see whether the current input array matches -
// if so we're done.
if(info->Has(vtkDataObject::FIELD_NAME()) &&
info->Get(INPUT_PORT()) == port &&
info->Get(INPUT_CONNECTION()) == connection &&
info->Get(vtkDataObject::FIELD_ASSOCIATION()) == fieldAssociation &&
info->Get(vtkDataObject::FIELD_NAME()) &&
strcmp(info->Get(vtkDataObject::FIELD_NAME()), name)==0)
{
return;
}
info->Set(INPUT_PORT(), port);
info->Set(INPUT_CONNECTION(), connection);
info->Set(vtkDataObject::FIELD_ASSOCIATION(),fieldAssociation);
info->Set(vtkDataObject::FIELD_NAME(),name);
this->Modified();
}
//----------------------------------------------------------------------------
int vtkAlgorithm::GetInputArrayAssociation
(int idx, vtkInformationVector **inputVector)
{
int association = vtkDataObject::FIELD_ASSOCIATION_NONE;
this->GetInputArrayToProcess(idx, inputVector, association);
return association;
}
//----------------------------------------------------------------------------
int vtkAlgorithm::GetInputArrayAssociation
(int idx, int connection, vtkInformationVector **inputVector)
{
int association = vtkDataObject::FIELD_ASSOCIATION_NONE;
this->GetInputArrayToProcess(idx, connection, inputVector, association);
return association;
}
//----------------------------------------------------------------------------
int vtkAlgorithm::GetInputArrayAssociation(int idx, vtkDataObject* input)
{
int association = vtkDataObject::FIELD_ASSOCIATION_NONE;
this->GetInputArrayToProcess(idx, input, association);
return association;
}
//----------------------------------------------------------------------------
vtkDataArray *vtkAlgorithm::GetInputArrayToProcess(
int idx, vtkInformationVector **inputVector)
{
int association = vtkDataObject::FIELD_ASSOCIATION_NONE;
return this->GetInputArrayToProcess(idx, inputVector, association);
}
//----------------------------------------------------------------------------
vtkDataArray* vtkAlgorithm::GetInputArrayToProcess
(int idx, vtkInformationVector **inputVector, int& association)
{
return vtkDataArray::SafeDownCast(
this->GetInputAbstractArrayToProcess(idx, inputVector, association));
}
//----------------------------------------------------------------------------
vtkDataArray *vtkAlgorithm::GetInputArrayToProcess(
int idx, int connection, vtkInformationVector **inputVector)
{
int association = vtkDataObject::FIELD_ASSOCIATION_NONE;
return this->GetInputArrayToProcess(idx, connection, inputVector, association);
}
//----------------------------------------------------------------------------
vtkDataArray* vtkAlgorithm::GetInputArrayToProcess
(int idx, int connection, vtkInformationVector **inputVector, int& association)
{
return vtkDataArray::SafeDownCast(this->GetInputAbstractArrayToProcess(
idx, connection, inputVector, association));
}
//----------------------------------------------------------------------------
vtkDataArray *vtkAlgorithm::GetInputArrayToProcess(
int idx, vtkDataObject* input)
{
int association = vtkDataObject::FIELD_ASSOCIATION_NONE;
return this->GetInputArrayToProcess(idx, input, association);
}
//----------------------------------------------------------------------------
vtkDataArray* vtkAlgorithm::GetInputArrayToProcess(int idx,
vtkDataObject* input,
int& association)
{
return vtkDataArray::SafeDownCast(this->GetInputAbstractArrayToProcess(idx,
input, association));
}
//----------------------------------------------------------------------------
vtkAbstractArray *vtkAlgorithm::GetInputAbstractArrayToProcess(
int idx, vtkInformationVector **inputVector)
{
int association = vtkDataObject::FIELD_ASSOCIATION_NONE;
return this->GetInputAbstractArrayToProcess(idx, inputVector, association);
}
//----------------------------------------------------------------------------
vtkAbstractArray* vtkAlgorithm::GetInputAbstractArrayToProcess
(int idx, vtkInformationVector **inputVector, int& association)
{
vtkInformationVector *inArrayVec =
this->Information->Get(INPUT_ARRAYS_TO_PROCESS());
if (!inArrayVec)
{
vtkErrorMacro
("Attempt to get an input array for an index that has not been specified");
return NULL;
}
vtkInformation *inArrayInfo = inArrayVec->GetInformationObject(idx);
if (!inArrayInfo)
{
vtkErrorMacro
("Attempt to get an input array for an index that has not been specified");
return NULL;
}
int connection = inArrayInfo->Get(INPUT_CONNECTION());
return this->GetInputAbstractArrayToProcess
(idx, connection, inputVector, association);
}
//----------------------------------------------------------------------------
vtkAbstractArray* vtkAlgorithm::GetInputAbstractArrayToProcess
(int idx, int connection, vtkInformationVector **inputVector)
{
int association = vtkDataObject::FIELD_ASSOCIATION_NONE;
return this->GetInputAbstractArrayToProcess
(idx, connection, inputVector, association);
}
//----------------------------------------------------------------------------
vtkAbstractArray* vtkAlgorithm::GetInputAbstractArrayToProcess(
int idx, int connection, vtkInformationVector **inputVector, int& association)
{
vtkInformationVector *inArrayVec =
this->Information->Get(INPUT_ARRAYS_TO_PROCESS());
if (!inArrayVec)
{
vtkErrorMacro
("Attempt to get an input array for an index that has not been specified");
return NULL;
}
vtkInformation *inArrayInfo = inArrayVec->GetInformationObject(idx);
if (!inArrayInfo)
{
vtkErrorMacro
("Attempt to get an input array for an index that has not been specified");
return NULL;
}
int port = inArrayInfo->Get(INPUT_PORT());
vtkInformation *inInfo = inputVector[port]->GetInformationObject(connection);
vtkDataObject *input = inInfo->Get(vtkDataObject::DATA_OBJECT());
return this->GetInputAbstractArrayToProcess(idx, input, association);
}
//----------------------------------------------------------------------------
vtkAbstractArray* vtkAlgorithm::GetInputAbstractArrayToProcess
(int idx, vtkDataObject* input)
{
int association = vtkDataObject::FIELD_ASSOCIATION_NONE;
return this->GetInputAbstractArrayToProcess(idx, input, association);
}
//----------------------------------------------------------------------------
vtkAbstractArray *vtkAlgorithm::GetInputAbstractArrayToProcess(
int idx, vtkDataObject* input, int& association)
{
if (!input)
{
return NULL;
}
vtkInformationVector *inArrayVec =
this->Information->Get(INPUT_ARRAYS_TO_PROCESS());
if (!inArrayVec)
{
vtkErrorMacro
("Attempt to get an input array for an index that has not been specified");
return NULL;
}
vtkInformation *inArrayInfo = inArrayVec->GetInformationObject(idx);
if (!inArrayInfo)
{
vtkErrorMacro
("Attempt to get an input array for an index that has not been specified");
return NULL;
}
int fieldAssoc = inArrayInfo->Get(vtkDataObject::FIELD_ASSOCIATION());
association = fieldAssoc;
if (inArrayInfo->Has(vtkDataObject::FIELD_NAME()))
{
const char *name = inArrayInfo->Get(vtkDataObject::FIELD_NAME());
if (fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_NONE)
{
vtkFieldData *fd = input->GetFieldData();
return fd->GetAbstractArray(name);
}
if (fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_ROWS)
{
vtkTable *inputT = vtkTable::SafeDownCast(input);
if (!inputT)
{
vtkErrorMacro("Attempt to get row data from a non-table");
return NULL;
}
vtkFieldData *fd = inputT->GetRowData();
return fd->GetAbstractArray(name);
}
if (fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_VERTICES ||
fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_EDGES)
{
vtkGraph *inputG = vtkGraph::SafeDownCast(input);
if (!inputG)
{
vtkErrorMacro("Attempt to get vertex or edge data from a non-graph");
return NULL;
}
vtkFieldData *fd = 0;
if (fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_VERTICES)
{
association = vtkDataObject::FIELD_ASSOCIATION_VERTICES;
fd = inputG->GetVertexData();
}
else
{
association = vtkDataObject::FIELD_ASSOCIATION_EDGES;
fd = inputG->GetEdgeData();
}
return fd->GetAbstractArray(name);
}
if (vtkGraph::SafeDownCast(input) &&
fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS)
{
return vtkGraph::SafeDownCast(input)->
GetVertexData()->GetAbstractArray(name);
}
vtkDataSet *inputDS = vtkDataSet::SafeDownCast(input);
if (!inputDS)
{
vtkErrorMacro("Attempt to get point or cell data from a data object");
return NULL;
}
if (fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS)
{
return inputDS->GetPointData()->GetAbstractArray(name);
}
if (fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS
&& inputDS->GetPointData()->GetAbstractArray(name))
{
association = vtkDataObject::FIELD_ASSOCIATION_POINTS;
return inputDS->GetPointData()->GetAbstractArray(name);
}
association = vtkDataObject::FIELD_ASSOCIATION_CELLS;
return inputDS->GetCellData()->GetAbstractArray(name);
}
else
{
vtkDataSet *inputDS = vtkDataSet::SafeDownCast(input);
if (!inputDS)
{
vtkErrorMacro("Attempt to get point or cell data from a data object");
return NULL;
}
int fType = inArrayInfo->Get(vtkDataObject::FIELD_ATTRIBUTE_TYPE());
if (fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS)
{
return inputDS->GetPointData()->GetAbstractAttribute(fType);
}
if (fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS
&& inputDS->GetPointData()->GetAbstractAttribute(fType))
{
association = vtkDataObject::FIELD_ASSOCIATION_POINTS;
return inputDS->GetPointData()->GetAbstractAttribute(fType);
}
association = vtkDataObject::FIELD_ASSOCIATION_CELLS;
return inputDS->GetCellData()->GetAbstractAttribute(fType);
}
}
//----------------------------------------------------------------------------
void vtkAlgorithm::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
if(this->HasExecutive())
{
os << indent << "Executive: " << this->Executive << "\n";
}
else
{
os << indent << "Executive: (none)\n";
}
os << indent << "ErrorCode: " <<
vtkErrorCode::GetStringFromErrorCode(this->ErrorCode) << endl;
if ( this->Information )
{
os << indent << "Information: " << this->Information << "\n";
}
else
{
os << indent << "Information: (none)\n";
}
os << indent << "AbortExecute: " << (this->AbortExecute ? "On\n" : "Off\n");
os << indent << "Progress: " << this->Progress << "\n";
if ( this->ProgressText )
{
os << indent << "Progress Text: " << this->ProgressText << "\n";
}
else
{
os << indent << "Progress Text: (None)\n";
}
}
//----------------------------------------------------------------------------
int vtkAlgorithm::HasExecutive()
{
return this->Executive ? 1 : 0;
}
//----------------------------------------------------------------------------
vtkExecutive* vtkAlgorithm::GetExecutive()
{
// Create the default executive if we do not have one already.
if(!this->HasExecutive())
{
vtkExecutive* e = this->CreateDefaultExecutive();
this->SetExecutive(e);
e->Delete();
}
return this->Executive;
}
//----------------------------------------------------------------------------
void vtkAlgorithm::SetExecutive(vtkExecutive* newExecutive)
{
vtkExecutive* oldExecutive = this->Executive;
if(newExecutive != oldExecutive)
{
if(newExecutive)
{
newExecutive->Register(this);
vtkAlgorithmToExecutiveFriendship::SetAlgorithm(newExecutive, this);
}
this->Executive = newExecutive;
if(oldExecutive)
{
vtkAlgorithmToExecutiveFriendship::SetAlgorithm(oldExecutive, 0);
oldExecutive->UnRegister(this);
}
}
}
//----------------------------------------------------------------------------
int vtkAlgorithm::ProcessRequest(vtkInformation* /* request */,
vtkInformationVector**,
vtkInformationVector*)
{
return 1;
}
//----------------------------------------------------------------------------
int vtkAlgorithm::ComputePipelineMTime(vtkInformation* /* request */,
vtkInformationVector**,
vtkInformationVector*,
int /* requestFromOutputPort */,
unsigned long* mtime)
{
// By default algorithms contribute only their own modified time.
*mtime = this->GetMTime();
return 1;
}
//----------------------------------------------------------------------------
int vtkAlgorithm::ModifyRequest(vtkInformation* /*request*/, int /*when*/)
{
return 1;
}
//----------------------------------------------------------------------------
int vtkAlgorithm::GetNumberOfInputPorts()
{
return this->InputPortInformation->GetNumberOfInformationObjects();
}
//----------------------------------------------------------------------------
void vtkAlgorithm::SetNumberOfInputPorts(int n)
{
// Sanity check.
if(n < 0)
{
vtkErrorMacro("Attempt to set number of input ports to " << n);
n = 0;
}
// We must remove all connections from ports that are removed.
for(int i=n; i < this->GetNumberOfInputPorts(); ++i)
{
this->SetNumberOfInputConnections(i, 0);
}
// Set the number of input port information objects.
this->InputPortInformation->SetNumberOfInformationObjects(n);
}
//----------------------------------------------------------------------------
int vtkAlgorithm::GetNumberOfOutputPorts()
{
return this->OutputPortInformation->GetNumberOfInformationObjects();
}
//----------------------------------------------------------------------------
void vtkAlgorithm::SetNumberOfOutputPorts(int n)
{
// Sanity check.
if(n < 0)
{
vtkErrorMacro("Attempt to set number of output ports to " << n);
n = 0;
}
// We must remove all connections from ports that are removed.
for(int i=n; i < this->GetNumberOfOutputPorts(); ++i)
{
// Get the producer and its output information for this port.
vtkExecutive* producer = this->GetExecutive();
vtkInformation* info = producer->GetOutputInformation(i);
// Remove all consumers' references to this producer on this port.
vtkExecutive** consumers = vtkExecutive::CONSUMERS()->GetExecutives(info);
int* consumerPorts = vtkExecutive::CONSUMERS()->GetPorts(info);
int consumerCount = vtkExecutive::CONSUMERS()->Length(info);
for(int j=0; j < consumerCount; ++j)
{
vtkInformationVector* inputs =
consumers[j]->GetInputInformation(consumerPorts[j]);
inputs->Remove(info);
}
// Remove this producer's references to all consumers on this port.
vtkExecutive::CONSUMERS()->Remove(info);
}
// Set the number of output port information objects.
this->OutputPortInformation->SetNumberOfInformationObjects(n);
// Set the number of connection proxy objects.
this->AlgorithmInternal->Outputs.resize(n);
}
//----------------------------------------------------------------------------
vtkInformation* vtkAlgorithm::GetInputPortInformation(int port)
{
if(!this->InputPortIndexInRange(port, "get information object for"))
{
return 0;
}
// Get the input port information object.
vtkInformation* info =
this->InputPortInformation->GetInformationObject(port);
// Fill it if it has not yet been filled.
if(!info->Has(PORT_REQUIREMENTS_FILLED()))
{
if(this->FillInputPortInformation(port, info))
{
info->Set(PORT_REQUIREMENTS_FILLED(), 1);
}
else
{
info->Clear();
}
}
// Return ths information object.
return info;
}
//----------------------------------------------------------------------------
vtkInformation* vtkAlgorithm::GetOutputPortInformation(int port)
{
if(!this->OutputPortIndexInRange(port, "get information object for"))
{
return 0;
}
// Get the output port information object.
vtkInformation* info =
this->OutputPortInformation->GetInformationObject(port);
// Fill it if it has not yet been filled.
if(!info->Has(PORT_REQUIREMENTS_FILLED()))
{
if(this->FillOutputPortInformation(port, info))
{
info->Set(PORT_REQUIREMENTS_FILLED(), 1);
}
else
{
info->Clear();
}
}
// Return ths information object.
return info;
}
//----------------------------------------------------------------------------
int vtkAlgorithm::FillInputPortInformation(int, vtkInformation*)
{
vtkErrorMacro("FillInputPortInformation is not implemented.");
return 0;
}
//----------------------------------------------------------------------------
int vtkAlgorithm::FillOutputPortInformation(int, vtkInformation*)
{
vtkErrorMacro("FillOutputPortInformation is not implemented.");
return 0;
}
//----------------------------------------------------------------------------
int vtkAlgorithm::InputPortIndexInRange(int index, const char* action)
{
// Make sure the index of the input port is in range.
if(index < 0 || index >= this->GetNumberOfInputPorts())
{
vtkErrorMacro("Attempt to " << (action?action:"access")
<< " input port index " << index
<< " for an algorithm with "
<< this->GetNumberOfInputPorts() << " input ports.");
return 0;
}
return 1;
}
//----------------------------------------------------------------------------
int vtkAlgorithm::OutputPortIndexInRange(int index, const char* action)
{
// Make sure the index of the output port is in range.
if(index < 0 || index >= this->GetNumberOfOutputPorts())
{
vtkErrorMacro("Attempt to " << (action?action:"access")
<< " output port index " << index
<< " for an algorithm with "
<< this->GetNumberOfOutputPorts() << " output ports.");
return 0;
}
return 1;
}
//----------------------------------------------------------------------------
void vtkAlgorithm::SetDefaultExecutivePrototype(vtkExecutive* proto)
{
if (vtkAlgorithm::DefaultExecutivePrototype == proto)
{
return;
}
if (vtkAlgorithm::DefaultExecutivePrototype)
{
vtkAlgorithm::DefaultExecutivePrototype->UnRegister(0);
vtkAlgorithm::DefaultExecutivePrototype = 0;
}
if (proto)
{
proto->Register(0);
}
vtkAlgorithm::DefaultExecutivePrototype = proto;
}
//----------------------------------------------------------------------------
vtkExecutive* vtkAlgorithm::CreateDefaultExecutive()
{
if (vtkAlgorithm::DefaultExecutivePrototype)
{
return vtkAlgorithm::DefaultExecutivePrototype->NewInstance();
}
return vtkStreamingDemandDrivenPipeline::New();
}
//----------------------------------------------------------------------------
void vtkAlgorithm::Register(vtkObjectBase* o)
{
this->RegisterInternal(o, 1);
}
//----------------------------------------------------------------------------
void vtkAlgorithm::UnRegister(vtkObjectBase* o)
{
this->UnRegisterInternal(o, 1);
}
//----------------------------------------------------------------------------
void vtkAlgorithm::ReportReferences(vtkGarbageCollector* collector)
{
this->Superclass::ReportReferences(collector);
vtkGarbageCollectorReport(collector, this->Executive, "Executive");
}
/// These are convenience methods to forward to the executive
//----------------------------------------------------------------------------
vtkDataObject* vtkAlgorithm::GetOutputDataObject(int port)
{
return this->GetExecutive()->GetOutputData(port);
}
//----------------------------------------------------------------------------
vtkDataObject *vtkAlgorithm::GetInputDataObject(int port,
int connection)
{
return this->GetExecutive()->GetInputData(port,connection);
}
//----------------------------------------------------------------------------
void vtkAlgorithm::RemoveAllInputs()
{
this->SetInputConnection(0, 0);
}
//----------------------------------------------------------------------------
void vtkAlgorithm::SetInputConnection(vtkAlgorithmOutput* input)
{
this->SetInputConnection(0,input);
}
//----------------------------------------------------------------------------
void vtkAlgorithm::SetInputConnection(int port, vtkAlgorithmOutput* input)
{
if(!this->InputPortIndexInRange(port, "connect"))
{
return;
}
// Get the producer/consumer pair for the connection.
vtkExecutive* producer =
(input && input->GetProducer())? input->GetProducer()->GetExecutive() : 0;
int producerPort = producer? input->GetIndex() : 0;
vtkExecutive* consumer = this->GetExecutive();
int consumerPort = port;
// Get the vector of connected input information objects.
vtkInformationVector* inputs = consumer->GetInputInformation(consumerPort);
// Get the information object from the producer of the new input.
vtkInformation* newInfo =
producer? producer->GetOutputInformation(producerPort) : 0;
// Check if the connection is already present.
if(!newInfo && inputs->GetNumberOfInformationObjects() == 0)
{
return;
}
else if(newInfo == inputs->GetInformationObject(0) &&
inputs->GetNumberOfInformationObjects() == 1)
{
return;
}
// The connection is not present.
vtkDebugMacro("Setting connection to input port index " << consumerPort
<< " from output port index " << producerPort
<< " on algorithm "
<< (producer? producer->GetAlgorithm()->GetClassName() : "")
<< "(" << (producer? producer->GetAlgorithm() : 0) << ").");
// Add this consumer to the new input's list of consumers.
if(newInfo)
{
vtkExecutive::CONSUMERS()->Append(newInfo, consumer, consumerPort);
}
// Remove this consumer from all old inputs' lists of consumers.
for(int i=0; i < inputs->GetNumberOfInformationObjects(); ++i)
{
if(vtkInformation* oldInfo = inputs->GetInformationObject(i))
{
vtkExecutive::CONSUMERS()->Remove(oldInfo, consumer, consumerPort);
}
}
// Make the new input the only connection.
if(newInfo)
{
inputs->SetInformationObject(0, newInfo);
inputs->SetNumberOfInformationObjects(1);
}
else
{
inputs->SetNumberOfInformationObjects(0);
}
// This algorithm has been modified.
this->Modified();
}
//----------------------------------------------------------------------------
void vtkAlgorithm::AddInputConnection(vtkAlgorithmOutput* input)
{
this->AddInputConnection(0, input);
}
void vtkAlgorithm::AddInputConnection(int port, vtkAlgorithmOutput* input)
{
if(!this->InputPortIndexInRange(port, "connect"))
{
return;
}
// If there is no input do nothing.
if(!input || !input->GetProducer())
{
return;
}
// Get the producer/consumer pair for the connection.
vtkExecutive* producer = input->GetProducer()->GetExecutive();
int producerPort = input->GetIndex();
vtkExecutive* consumer = this->GetExecutive();
int consumerPort = port;
// Get the vector of connected input information objects.
vtkInformationVector* inputs = consumer->GetInputInformation(consumerPort);
// Add the new connection.
vtkDebugMacro("Adding connection to input port index " << consumerPort
<< " from output port index " << producerPort
<< " on algorithm "
<< (producer? producer->GetAlgorithm()->GetClassName() : "")
<< "(" << (producer? producer->GetAlgorithm() : 0) << ").");
// Get the information object from the producer of the new input.
vtkInformation* newInfo = producer->GetOutputInformation(producerPort);
// Add this consumer to the input's list of consumers.
vtkExecutive::CONSUMERS()->Append(newInfo, consumer, consumerPort);
// Add the information object to the list of inputs.
inputs->Append(newInfo);
// This algorithm has been modified.
this->Modified();
}
//----------------------------------------------------------------------------
void vtkAlgorithm::RemoveInputConnection(int port, vtkAlgorithmOutput* input)
{
if(!this->InputPortIndexInRange(port, "disconnect"))
{
return;
}
// If there is no input do nothing.
if(!input || !input->GetProducer())
{
return;
}
// Get the producer/consumer pair for the connection.
vtkExecutive* producer = input->GetProducer()->GetExecutive();
int producerPort = input->GetIndex();
vtkExecutive* consumer = this->GetExecutive();
int consumerPort = port;
// Get the vector of connected input information objects.
vtkInformationVector* inputs = consumer->GetInputInformation(consumerPort);
// Remove the connection.
vtkDebugMacro("Removing connection to input port index " << consumerPort
<< " from output port index " << producerPort
<< " on algorithm "
<< (producer? producer->GetAlgorithm()->GetClassName() : "")
<< "(" << (producer? producer->GetAlgorithm() : 0) << ").");
// Get the information object from the producer of the old input.
vtkInformation* oldInfo = producer->GetOutputInformation(producerPort);
// Remove this consumer from the old input's list of consumers.
vtkExecutive::CONSUMERS()->Remove(oldInfo, consumer, consumerPort);
// Remove the information object from the list of inputs.
inputs->Remove(oldInfo);
// This algorithm has been modified.
this->Modified();
}
//----------------------------------------------------------------------------
void vtkAlgorithm::SetNthInputConnection(int port, int index,
vtkAlgorithmOutput* input)
{
if(!this->InputPortIndexInRange(port, "replace connection"))
{
return;
}
// Get the producer/consumer pair for the connection.
vtkExecutive* producer =
(input && input->GetProducer())? input->GetProducer()->GetExecutive() : 0;
int producerPort = producer? input->GetIndex() : 0;
vtkExecutive* consumer = this->GetExecutive();
int consumerPort = port;
// Get the vector of connected input information objects.
vtkInformationVector* inputs = consumer->GetInputInformation(consumerPort);
// Check for any existing connection with this index.
vtkInformation* oldInfo = inputs->GetInformationObject(index);
// Get the information object from the producer of the input.
vtkInformation* newInfo =
producer? producer->GetOutputInformation(producerPort) : 0;
// If the connection has not changed, do nothing.
if(newInfo == oldInfo)
{
return;
}
// Set the connection.
vtkDebugMacro("Setting connection index " << index
<< " to input port index " << consumerPort
<< " from output port index " << producerPort
<< " on algorithm "
<< (producer? producer->GetAlgorithm()->GetClassName() : "")
<< "(" << (producer? producer->GetAlgorithm() : 0) << ").");
// Add the consumer to the new input's list of consumers.
if(newInfo)
{
vtkExecutive::CONSUMERS()->Append(newInfo, consumer, consumerPort);
}
// Remove the consumer from the old input's list of consumers.
if(oldInfo)
{
vtkExecutive::CONSUMERS()->Remove(oldInfo, consumer, consumerPort);
}
// Store the information object in the vector of input connections.
inputs->SetInformationObject(index, newInfo);
// This algorithm has been modified.
this->Modified();
}
//----------------------------------------------------------------------------
void vtkAlgorithm::SetNumberOfInputConnections(int port, int n)
{
// Get the consumer executive and port number.
vtkExecutive* consumer = this->GetExecutive();
int consumerPort = port;
// Get the vector of connected input information objects.
vtkInformationVector* inputs = consumer->GetInputInformation(consumerPort);
// If the number of connections has not changed, do nothing.
if(n == inputs->GetNumberOfInformationObjects())
{
return;
}
// Remove connections beyond the new number.
for(int i=n; i < inputs->GetNumberOfInformationObjects(); ++i)
{
// Remove each input's reference to this consumer.
if(vtkInformation* oldInfo = inputs->GetInformationObject(i))
{
vtkExecutive::CONSUMERS()->Remove(oldInfo, consumer, consumerPort);
}
}
// Set the number of connected inputs. Non-existing inputs will be
// empty information objects.
inputs->SetNumberOfInformationObjects(n);
// This algorithm has been modified.
this->Modified();
}
//----------------------------------------------------------------------------
vtkAlgorithmOutput* vtkAlgorithm::GetOutputPort(int port)
{
if(!this->OutputPortIndexInRange(port, "get"))
{
return 0;
}
// Create the vtkAlgorithmOutput proxy object if there is not one.
if(!this->AlgorithmInternal->Outputs[port])
{
this->AlgorithmInternal->Outputs[port] =
vtkSmartPointer<vtkAlgorithmOutput>::New();
this->AlgorithmInternal->Outputs[port]->SetProducer(this);
this->AlgorithmInternal->Outputs[port]->SetIndex(port);
}
// Return the proxy object instance.
return this->AlgorithmInternal->Outputs[port];
}
//----------------------------------------------------------------------------
int vtkAlgorithm::GetNumberOfInputConnections(int port)
{
if(this->Executive)
{
return this->Executive->GetNumberOfInputConnections(port);
}
return 0;
}
//----------------------------------------------------------------------------
int vtkAlgorithm::GetTotalNumberOfInputConnections()
{
int i;
int total = 0;
for (i = 0; i < this->GetNumberOfInputPorts(); ++i)
{
total += this->GetNumberOfInputConnections(i);
}
return total;
}
//----------------------------------------------------------------------------
vtkAlgorithmOutput* vtkAlgorithm::GetInputConnection(int port, int index)
{
if(index < 0 || index >= this->GetNumberOfInputConnections(port))
{
vtkErrorMacro("Attempt to get connection index " << index
<< " for input port " << port << ", which has "
<< this->GetNumberOfInputConnections(port)
<< " connections.");
return 0;
}
if(vtkInformation* info =
this->GetExecutive()->GetInputInformation(port, index))
{
// Get the executive producing this input. If there is none, then
// it is a NULL input.
vtkExecutive* producer;
int producerPort;
vtkExecutive::PRODUCER()->Get(info,producer,producerPort);
if(producer)
{
return producer->GetAlgorithm()->GetOutputPort(producerPort);
}
}
return 0;
}
//----------------------------------------------------------------------------
void vtkAlgorithm::Update()
{
this->GetExecutive()->Update();
}
//----------------------------------------------------------------------------
void vtkAlgorithm::UpdateInformation()
{
vtkDemandDrivenPipeline* ddp =
vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive());
if (ddp)
{
ddp->UpdateInformation();
}
}
//----------------------------------------------------------------------------
void vtkAlgorithm::UpdateWholeExtent()
{
vtkStreamingDemandDrivenPipeline* sddp =
vtkStreamingDemandDrivenPipeline::SafeDownCast(this->GetExecutive());
if (sddp)
{
sddp->UpdateWholeExtent();
}
else
{
this->Update();
}
}
//----------------------------------------------------------------------------
void vtkAlgorithm::ConvertTotalInputToPortConnection(
int ind, int &port, int &conn)
{
port = 0;
conn = 0;
while (ind && port < this->GetNumberOfInputPorts())
{
int pNumCon;
pNumCon = this->GetNumberOfInputConnections(port);
if (ind >= pNumCon)
{
port++;
ind -= pNumCon;
}
else
{
return;
}
}
}
//----------------------------------------------------------------------------
void vtkAlgorithm::ReleaseDataFlagOn()
{
if(vtkDemandDrivenPipeline* ddp =
vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive()))
{
for(int i=0; i < this->GetNumberOfOutputPorts(); ++i)
{
ddp->SetReleaseDataFlag(i, 1);
}
}
}
//----------------------------------------------------------------------------
void vtkAlgorithm::ReleaseDataFlagOff()
{
if(vtkDemandDrivenPipeline* ddp =
vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive()))
{
for(int i=0; i < this->GetNumberOfOutputPorts(); ++i)
{
ddp->SetReleaseDataFlag(i, 0);
}
}
}
//----------------------------------------------------------------------------
void vtkAlgorithm::SetReleaseDataFlag(int val)
{
if(vtkDemandDrivenPipeline* ddp =
vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive()))
{
for(int i=0; i < this->GetNumberOfOutputPorts(); ++i)
{
ddp->SetReleaseDataFlag(i, val);
}
}
}
//----------------------------------------------------------------------------
int vtkAlgorithm::GetReleaseDataFlag()
{
if(vtkDemandDrivenPipeline* ddp =
vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive()))
{
return ddp->GetReleaseDataFlag(0);
}
return 0;
}
//----------------------------------------------------------------------------
int vtkAlgorithm::UpdateExtentIsEmpty(vtkDataObject *output)
{
if (output == NULL)
{
return 1;
}
// get the pinfo object then call the info signature
return this->UpdateExtentIsEmpty(
output->GetPipelineInformation(),
output->GetInformation()->Get(vtkDataObject::DATA_EXTENT_TYPE()));
}
//----------------------------------------------------------------------------
int vtkAlgorithm::UpdateExtentIsEmpty(vtkInformation *info, int extentType)
{
if (!info)
{
return 1;
}
int *ext;
switch (extentType)
{
case VTK_PIECES_EXTENT:
// Special way of asking for no input.
if (info->Get(
vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()) == 0 )
{
return 1;
}
break;
case VTK_3D_EXTENT:
ext = info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT());
// Special way of asking for no input. (zero volume)
if (!ext || ext[0] == (ext[1] + 1) ||
ext[2] == (ext[3] + 1) ||
ext[4] == (ext[5] + 1))
{
return 1;
}
break;
// We should never have this case occur
default:
vtkErrorMacro( << "Internal error - invalid extent type!" );
break;
}
return 0;
}
//----------------------------------------------------------------------------
void vtkAlgorithm::SetProgressText(const char* ptext)
{
if (!this->ProgressText && !ptext)
{
return;
}
if (this->ProgressText && ptext && (strcmp(this->ProgressText,ptext)) == 0)
{
return;
}
if (this->ProgressText)
{
delete[] this->ProgressText;
this->ProgressText = 0;
}
if (ptext)
{
size_t n = strlen(ptext) + 1;
char *cp1 = new char[n];
const char *cp2 = ptext;
this->ProgressText = cp1;
do { *cp1++ = *cp2++; } while ( --n );
}
}
//-------------------------------------------------------------
double vtkAlgorithm::ComputePriority()
{
vtkStreamingDemandDrivenPipeline *sddp =
vtkStreamingDemandDrivenPipeline::SafeDownCast
(this->GetExecutive());
if (!sddp)
{
return 1.0;
}
return sddp->ComputePriority(0);
}