You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
714 lines
20 KiB
714 lines
20 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkSource.cxx,v $
|
|
|
|
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 "vtkSource.h"
|
|
|
|
#include "vtkCommand.h"
|
|
#include "vtkDataObject.h"
|
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
|
#include "vtkErrorCode.h"
|
|
#include "vtkFieldData.h"
|
|
#include "vtkGarbageCollector.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkObjectFactory.h"
|
|
|
|
#include "vtkImageData.h"
|
|
|
|
vtkCxxRevisionMacro(vtkSource, "$Revision: 1.16 $");
|
|
|
|
#ifndef NULL
|
|
#define NULL 0
|
|
#endif
|
|
|
|
class vtkSourceToDataSetFriendship
|
|
{
|
|
public:
|
|
static void GenerateGhostLevelArray(vtkDataSet* ds)
|
|
{
|
|
ds->GenerateGhostLevelArray();
|
|
}
|
|
};
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkSource::vtkSource()
|
|
{
|
|
this->NumberOfOutputs = 0;
|
|
this->Outputs = NULL;
|
|
this->Updating = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkSource::~vtkSource()
|
|
{
|
|
this->UnRegisterAllOutputs();
|
|
if(this->Outputs)
|
|
{
|
|
delete [] this->Outputs;
|
|
this->Outputs = NULL;
|
|
this->NumberOfOutputs = 0;
|
|
}
|
|
}
|
|
|
|
int vtkSource::GetOutputIndex(vtkDataObject *out)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < this->NumberOfOutputs; i++)
|
|
{
|
|
if (this->Outputs[i] == out)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkDataObject* vtkSource::GetOutput(int i)
|
|
{
|
|
if(i >= 0 && i < this->NumberOfOutputs)
|
|
{
|
|
return this->Outputs[i];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::UnRegisterAllOutputs()
|
|
{
|
|
for(int i=0; i < this->NumberOfOutputs; ++i)
|
|
{
|
|
this->SetNthOutput(i, 0);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkSource::GetReleaseDataFlag()
|
|
{
|
|
if (this->GetOutput(0))
|
|
{
|
|
return this->GetOutput(0)->GetReleaseDataFlag();
|
|
}
|
|
vtkWarningMacro(<<"Output doesn't exist!");
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::SetReleaseDataFlag(int i)
|
|
{
|
|
int idx;
|
|
|
|
for (idx = 0; idx < this->NumberOfOutputs; idx++)
|
|
{
|
|
if (this->Outputs[idx])
|
|
{
|
|
this->Outputs[idx]->SetReleaseDataFlag(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::UpdateWholeExtent()
|
|
{
|
|
this->UpdateInformation();
|
|
|
|
if (this->GetOutput(0))
|
|
{
|
|
this->GetOutput(0)->SetUpdateExtentToWholeExtent();
|
|
this->GetOutput(0)->Update();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::Update()
|
|
{
|
|
if(vtkDemandDrivenPipeline* ddp =
|
|
vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive()))
|
|
{
|
|
ddp->Update(0);
|
|
}
|
|
else
|
|
{
|
|
vtkErrorMacro("Executive is not a vtkDemandDrivenPipeline.");
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::UpdateInformation()
|
|
{
|
|
if(vtkDemandDrivenPipeline* ddp =
|
|
vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive()))
|
|
{
|
|
ddp->UpdateInformation();
|
|
}
|
|
else
|
|
{
|
|
vtkErrorMacro("Executive is not a vtkDemandDrivenPipeline.");
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::PropagateUpdateExtent(vtkDataObject* output)
|
|
{
|
|
if(vtkStreamingDemandDrivenPipeline* sddp =
|
|
vtkStreamingDemandDrivenPipeline::SafeDownCast(this->GetExecutive()))
|
|
{
|
|
if(output)
|
|
{
|
|
for(int i=0; i < this->NumberOfOutputs; ++i)
|
|
{
|
|
if(this->Outputs[i] == output)
|
|
{
|
|
sddp->PropagateUpdateExtent(i);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sddp->PropagateUpdateExtent(-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// By default we require all the input to produce the output. This is
|
|
// overridden in the subclasses since we can often produce the output with
|
|
// just a portion of the input data.
|
|
void vtkSource::ComputeInputUpdateExtents( vtkDataObject *vtkNotUsed(output) )
|
|
{
|
|
for (int idx = 0; idx < this->NumberOfInputs; ++idx)
|
|
{
|
|
if (this->Inputs[idx] != NULL)
|
|
{
|
|
this->Inputs[idx]->RequestExactExtentOn();
|
|
this->Inputs[idx]->SetUpdateExtentToWholeExtent();
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void vtkSource::TriggerAsynchronousUpdate()
|
|
{
|
|
// check flag to avoid executing forever if there is a loop
|
|
if (this->Updating)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Propagate the trigger to all the inputs
|
|
this->Updating = 1;
|
|
for (int idx = 0; idx < this->NumberOfInputs; ++idx)
|
|
{
|
|
if (this->Inputs[idx] != NULL)
|
|
{
|
|
this->Inputs[idx]->TriggerAsynchronousUpdate();
|
|
}
|
|
}
|
|
this->Updating = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::UpdateData(vtkDataObject* output)
|
|
{
|
|
if(vtkDemandDrivenPipeline* ddp =
|
|
vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive()))
|
|
{
|
|
if(output)
|
|
{
|
|
for(int i=0; i < this->NumberOfOutputs; ++i)
|
|
{
|
|
if(this->Outputs[i] == output)
|
|
{
|
|
ddp->UpdateData(i);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ddp->UpdateData(-1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vtkErrorMacro("Executive is not a vtkDemandDrivenPipeline.");
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Assume that any source that implements ExecuteData
|
|
// can handle an empty extent.
|
|
void vtkSource::ExecuteData(vtkDataObject *output)
|
|
{
|
|
// I want to find out if the requested extent is empty.
|
|
if (this->UpdateExtentIsEmpty(output) && output)
|
|
{
|
|
output->Initialize();
|
|
return;
|
|
}
|
|
|
|
this->Execute();
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::SetNumberOfOutputs(int newNumberOfOutputs)
|
|
{
|
|
if(newNumberOfOutputs < 0)
|
|
{
|
|
vtkErrorMacro("Cannot set number of outputs to " << newNumberOfOutputs);
|
|
newNumberOfOutputs = 0;
|
|
}
|
|
|
|
if(newNumberOfOutputs != this->NumberOfOutputs)
|
|
{
|
|
// Copy outputs that will still exist.
|
|
vtkDataObject** newOutputs = new vtkDataObject*[newNumberOfOutputs];
|
|
int i;
|
|
for(i=0; i < newNumberOfOutputs; ++i)
|
|
{
|
|
newOutputs[i] = (i < this->NumberOfOutputs)? this->Outputs[i] : 0;
|
|
}
|
|
|
|
// Delete outputs if number is decreasing.
|
|
for(;i < this->NumberOfOutputs; ++i)
|
|
{
|
|
this->SetNthOutput(i, 0);
|
|
}
|
|
|
|
// Free old outputs array.
|
|
if(this->Outputs)
|
|
{
|
|
delete [] this->Outputs;
|
|
this->Outputs = 0;
|
|
this->NumberOfOutputs = 0;
|
|
}
|
|
|
|
// Setup new outputs array.
|
|
this->Outputs = newOutputs;
|
|
this->NumberOfOutputs = newNumberOfOutputs;
|
|
this->SetNumberOfOutputPorts(this->NumberOfOutputs);
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::AddOutput(vtkDataObject* output)
|
|
{
|
|
if(output)
|
|
{
|
|
for(int i=0; i < this->GetNumberOfOutputPorts(); ++i)
|
|
{
|
|
if(!this->Outputs[i])
|
|
{
|
|
this->SetNthOutput(i, output);
|
|
return;
|
|
}
|
|
}
|
|
this->SetNthOutput(this->GetNumberOfOutputPorts(), output);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::RemoveOutput(vtkDataObject* output)
|
|
{
|
|
if(output)
|
|
{
|
|
for(int i=0; i < this->NumberOfOutputs; ++i)
|
|
{
|
|
if(this->Outputs[i] == output)
|
|
{
|
|
this->SetNthOutput(i, 0);
|
|
return;
|
|
}
|
|
}
|
|
vtkErrorMacro("Could not remove " << output->GetClassName()
|
|
<< "(" << output << ") because it is not an output.");
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::SetNthOutput(int index, vtkDataObject* newOutput)
|
|
{
|
|
if(index < 0)
|
|
{
|
|
vtkErrorMacro("SetNthOutput: " << index << ", cannot set output. ");
|
|
return;
|
|
}
|
|
|
|
if(index >= this->NumberOfOutputs)
|
|
{
|
|
this->SetNumberOfOutputs(index+1);
|
|
}
|
|
|
|
vtkDataObject* oldOutput = this->Outputs[index];
|
|
if(newOutput == oldOutput)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Ask the executive to setup the new output.
|
|
this->GetExecutive()->SetOutputData(index, newOutput);
|
|
|
|
this->InvokeEvent(vtkCommand::SetOutputEvent,NULL);
|
|
|
|
this->Modified();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::Execute()
|
|
{
|
|
vtkErrorMacro(<< "Definition of Execute() method should be in subclass and you should really use ExecuteData(vtkDataObject *) instead");
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkDataObject** vtkSource::GetOutputs()
|
|
{
|
|
return this->Outputs;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// Default implementation - copy information from first input to all outputs
|
|
void vtkSource::ExecuteInformation()
|
|
{
|
|
vtkDataObject *input, *output;
|
|
|
|
if (this->Inputs && this->Inputs[0])
|
|
{
|
|
input = this->Inputs[0];
|
|
|
|
for (int idx = 0; idx < this->NumberOfOutputs; ++idx)
|
|
{
|
|
output = this->GetOutput(idx);
|
|
if (output)
|
|
{
|
|
output->CopyInformation(input);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int idx = 0; idx < this->NumberOfOutputs; ++idx)
|
|
{
|
|
output = this->GetOutput(idx);
|
|
if (output)
|
|
{
|
|
// Since most unstructured filters in VTK generate all their data once,
|
|
// make it the default.
|
|
// protected: if ( output->GetExtentType() == VTK_PIECES_EXTENT )
|
|
if (output->IsA("vtkPolyData") || output->IsA("vtkUnstructuredGrid"))
|
|
{
|
|
output->SetMaximumNumberOfPieces(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
if ( this->NumberOfOutputs)
|
|
{
|
|
int idx;
|
|
for (idx = 0; idx < this->NumberOfOutputs; ++idx)
|
|
{
|
|
os << indent << "Output " << idx << ": (" << this->Outputs[idx] << ")\n";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
os << indent <<"No Outputs\n";
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkSource::FillOutputPortInformation(int port, vtkInformation* info)
|
|
{
|
|
return this->Superclass::FillOutputPortInformation(port, info);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::ReportReferences(vtkGarbageCollector* collector)
|
|
{
|
|
this->Superclass::ReportReferences(collector);
|
|
for(int i=0; i < this->NumberOfOutputs; ++i)
|
|
{
|
|
vtkGarbageCollectorReport(collector, this->Outputs[i], "Outputs");
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::SetExecutive(vtkExecutive* executive)
|
|
{
|
|
// Set the executive normally.
|
|
this->Superclass::SetExecutive(executive);
|
|
// Copy our set of outputs to the information objects in the
|
|
// executive.
|
|
for(int i=0; i < this->GetNumberOfOutputPorts(); ++i)
|
|
{
|
|
this->GetExecutive()->SetOutputData(i, this->Outputs[i]);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::SetNumberOfOutputPorts(int n)
|
|
{
|
|
if(n != this->GetNumberOfOutputPorts())
|
|
{
|
|
this->Superclass::SetNumberOfOutputPorts(n);
|
|
this->SetNumberOfOutputs(n);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkSource::ProcessRequest(vtkInformation* request,
|
|
vtkInformationVector** inputVector,
|
|
vtkInformationVector* outputVector)
|
|
{
|
|
if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT()))
|
|
{
|
|
// The compatibility layer always keeps output data objects around
|
|
// because they are needed for connections.
|
|
return 1;
|
|
}
|
|
else if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()))
|
|
{
|
|
// Make sure the outputs are synchronized between the old and new
|
|
// style pipelines.
|
|
int i;
|
|
for(i=0; i < this->NumberOfOutputs; ++i)
|
|
{
|
|
vtkInformation* info = this->GetExecutive()->GetOutputInformation(i);
|
|
this->SetNthOutput(i, info->Get(vtkDataObject::DATA_OBJECT()));
|
|
}
|
|
|
|
vtkDebugMacro("ProcessRequest(REQUEST_INFORMATION) "
|
|
"calling ExecuteInformation.");
|
|
|
|
// Old-style filters will get origin and spacing from the input
|
|
// data objects themselves. We handle this here by copying the
|
|
// pipeline information version of these values into the data
|
|
// object's version.
|
|
for(i=0; i < this->NumberOfInputs; ++i)
|
|
{
|
|
vtkInformation* info = inputVector[0]->GetInformationObject(i);
|
|
if(vtkImageData* id = vtkImageData::SafeDownCast(
|
|
info->Get(vtkDataObject::DATA_OBJECT())))
|
|
{
|
|
if(info->Has(vtkDataObject::ORIGIN()))
|
|
{
|
|
id->SetOrigin(info->Get(vtkDataObject::ORIGIN()));
|
|
}
|
|
if(info->Has(vtkDataObject::SPACING()))
|
|
{
|
|
id->SetSpacing(info->Get(vtkDataObject::SPACING()));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Ask the subclass to fill in the information for the outputs.
|
|
this->InvokeEvent(vtkCommand::ExecuteInformationEvent, NULL);
|
|
this->ExecuteInformation();
|
|
|
|
// The number of outputs may have been changed by execute information.
|
|
outputVector->SetNumberOfInformationObjects(this->NumberOfOutputs);
|
|
|
|
// Old-style filters will set the origin and spacing on the output
|
|
// data objects themselves. We handle this here by copying the
|
|
// information back to the pipeline information.
|
|
for(i=0; i < this->NumberOfOutputs; ++i)
|
|
{
|
|
vtkInformation* info = outputVector->GetInformationObject(i);
|
|
if(vtkImageData* id = vtkImageData::SafeDownCast(
|
|
info->Get(vtkDataObject::DATA_OBJECT())))
|
|
{
|
|
info->Set(vtkDataObject::ORIGIN(), id->GetOrigin(), 3);
|
|
info->Set(vtkDataObject::SPACING(), id->GetSpacing(), 3);
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
else if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT()))
|
|
{
|
|
int i;
|
|
for(i=0; i < this->NumberOfOutputs; ++i)
|
|
{
|
|
vtkInformation* info = this->GetExecutive()->GetOutputInformation(i);
|
|
this->SetNthOutput(i, info->Get(vtkDataObject::DATA_OBJECT()));
|
|
}
|
|
|
|
// If the user defines a ComputeInputUpdateExtent method, we want
|
|
// RequestExactUpdateExtent to be off by default (User does
|
|
// nothing else). Otherwise, the ComputeInputUpdateExtent in this
|
|
// superclass sets RequestExactExtent to on. The reason for this
|
|
// initialization here is if this sources shares an input with
|
|
// another, we do not want the input's RequestExactExtent "state"
|
|
// to interfere with each other.
|
|
for(i=0; i < this->NumberOfInputs; ++i)
|
|
{
|
|
if(this->Inputs[i])
|
|
{
|
|
this->Inputs[i]->RequestExactExtentOff();
|
|
}
|
|
}
|
|
|
|
// Check inputs.
|
|
if(this->NumberOfRequiredInputs > 0 &&
|
|
this->GetNumberOfInputPorts() < 1)
|
|
{
|
|
vtkErrorMacro("This filter requires " << this->NumberOfRequiredInputs
|
|
<< " input(s) but has no input ports. A call to "
|
|
<< "SetNumberOfInputPorts and an implementation of "
|
|
<< "FillInputPortInformation may need to be added to "
|
|
<< "this class.");
|
|
return 0;
|
|
}
|
|
|
|
int outputPort =
|
|
request->Get(vtkDemandDrivenPipeline::FROM_OUTPUT_PORT());
|
|
vtkDataObject* fromOutput = 0;
|
|
if(outputPort >= 0)
|
|
{
|
|
fromOutput = this->Outputs[outputPort];
|
|
}
|
|
|
|
// Give the subclass a chance to request a larger extent on the
|
|
// inputs. This is necessary when, for example, a filter requires
|
|
// more data at the "internal" boundaries to produce the boundary
|
|
// values - such as an image filter that derives a new pixel value
|
|
// by applying some operation to a neighborhood of surrounding
|
|
// original values.
|
|
vtkDebugMacro("ProcessRequest(REQUEST_UPDATE_EXTENT) "
|
|
"calling ComputeInputUpdateExtents using output port "
|
|
<< outputPort);
|
|
this->ComputeInputUpdateExtents(fromOutput);
|
|
|
|
return 1;
|
|
}
|
|
else if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_NOT_GENERATED()))
|
|
{
|
|
// Mark all outputs as not generated so that the executive does
|
|
// not try to handle initialization/finalization of the outputs.
|
|
// We will do it here.
|
|
int i;
|
|
for(i=0; i < outputVector->GetNumberOfInformationObjects(); ++i)
|
|
{
|
|
vtkInformation* outInfo = outputVector->GetInformationObject(i);
|
|
outInfo->Set(vtkDemandDrivenPipeline::DATA_NOT_GENERATED(), 1);
|
|
}
|
|
}
|
|
else if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
|
|
{
|
|
// Make sure the outputs are synchronized between the old and new
|
|
// style pipelines.
|
|
int i;
|
|
for(i=0; i < this->NumberOfOutputs; ++i)
|
|
{
|
|
vtkInformation* info = this->GetExecutive()->GetOutputInformation(i);
|
|
this->SetNthOutput(i, info->Get(vtkDataObject::DATA_OBJECT()));
|
|
}
|
|
int outputPort = request->Get(vtkDemandDrivenPipeline::FROM_OUTPUT_PORT());
|
|
|
|
// Check inputs.
|
|
if(this->NumberOfRequiredInputs > 0 &&
|
|
this->GetNumberOfInputPorts() < 1)
|
|
{
|
|
vtkErrorMacro("This filter requires " << this->NumberOfRequiredInputs
|
|
<< " input(s) but has no input ports. A call to "
|
|
<< "SetNumberOfInputPorts and an implementation of "
|
|
<< "FillInputPortInformation may need to be added to "
|
|
<< "this class.");
|
|
return 0;
|
|
}
|
|
|
|
vtkDebugMacro("ProcessRequest(REQUEST_DATA) "
|
|
"calling ExecuteData for output port " << outputPort);
|
|
|
|
// Prepare to execute the filter.
|
|
for(i=0; i < this->NumberOfOutputs; ++i)
|
|
{
|
|
if(this->Outputs[i])
|
|
{
|
|
this->Outputs[i]->PrepareForNewData();
|
|
}
|
|
}
|
|
|
|
// Pass the vtkDataObject's field data from the first input to all
|
|
// outputs.
|
|
if(this->NumberOfInputs > 0 && this->Inputs[0] &&
|
|
this->Inputs[0]->GetFieldData())
|
|
{
|
|
for(i=0; i < this->NumberOfOutputs; ++i)
|
|
{
|
|
if(this->Outputs[i] && this->Outputs[i]->GetFieldData())
|
|
{
|
|
this->Outputs[i]->GetFieldData()->PassData(
|
|
this->Inputs[0]->GetFieldData());
|
|
}
|
|
}
|
|
}
|
|
|
|
// Execute the filter.
|
|
vtkDataObject* output = (outputPort >= 0)? this->Outputs[outputPort] : 0;
|
|
this->ExecuteData(output);
|
|
|
|
// Mark the data as up-to-date.
|
|
this->MarkGeneratedOutputs(output);
|
|
|
|
// Cleanup the outputs.
|
|
for(i=0; i < this->NumberOfOutputs; ++i)
|
|
{
|
|
vtkInformation* info = outputVector->GetInformationObject(i);
|
|
|
|
// Old-style filters will set the origin and spacing on the output
|
|
// data objects themselves. We handle this here by copying the
|
|
// information back to the pipeline information.
|
|
if(vtkImageData* id = vtkImageData::SafeDownCast(
|
|
info->Get(vtkDataObject::DATA_OBJECT())))
|
|
{
|
|
info->Set(vtkDataObject::ORIGIN(), id->GetOrigin(), 3);
|
|
info->Set(vtkDataObject::SPACING(), id->GetSpacing(), 3);
|
|
}
|
|
|
|
// Compute the ghost level array for the output if necessary.
|
|
if(vtkDataSet* ds = vtkDataSet::SafeDownCast(this->Outputs[i]))
|
|
{
|
|
vtkSourceToDataSetFriendship::GenerateGhostLevelArray(ds);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
return this->Superclass::ProcessRequest(request, inputVector, outputVector);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSource::MarkGeneratedOutputs(vtkDataObject*)
|
|
{
|
|
// Mark the data as up-to-date. Mark all outputs by default.
|
|
for(int i=0; i < this->NumberOfOutputs; ++i)
|
|
{
|
|
if(this->Outputs[i])
|
|
{
|
|
this->Outputs[i]->DataHasBeenGenerated();
|
|
}
|
|
}
|
|
}
|
|
|