Cloned library of VTK-5.0.0 with extra build files for internal package management.
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.
 
 
 
 
 
 

421 lines
12 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkPStreamTracer.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 "vtkPStreamTracer.h"
#include "vtkAppendPolyData.h"
#include "vtkCellData.h"
#include "vtkIdList.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkIntArray.h"
#include "vtkInterpolatedVelocityField.h"
#include "vtkMultiProcessController.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkStreamingDemandDrivenPipeline.h"
vtkCxxRevisionMacro(vtkPStreamTracer, "$Revision: 1.17 $");
vtkCxxSetObjectMacro(vtkPStreamTracer, Controller, vtkMultiProcessController);
vtkCxxSetObjectMacro(vtkPStreamTracer,
Interpolator,
vtkInterpolatedVelocityField);
vtkPStreamTracer::vtkPStreamTracer()
{
this->Controller = vtkMultiProcessController::GetGlobalController();
if (this->Controller)
{
this->Controller->Register(this);
}
this->Interpolator = 0;
this->Seeds = 0;
this->SeedIds = 0;
this->IntegrationDirections = 0;
this->GenerateNormalsInIntegrate = 0;
}
vtkPStreamTracer::~vtkPStreamTracer()
{
if (this->Controller)
{
this->Controller->UnRegister(this);
this->Controller = 0;
}
this->SetInterpolator(0);
if (this->Seeds)
{
this->Seeds->Delete();
}
if (this->SeedIds)
{
this->SeedIds->Delete();
}
if (this->IntegrationDirections)
{
this->IntegrationDirections->Delete();
}
}
// After the integration is over, we need to add one point
// at the end of streamline pieces which were not the end
// piece. This has to be done in order to close the gap between
// pieces which appear due to jump from one process to another.
// This method waits until a process sends its first points.
void vtkPStreamTracer::ReceiveLastPoints(vtkPolyData *output)
{
int streamId = 0;
while(1)
{
this->Controller->Receive(&streamId,
1,
vtkMultiProcessController::ANY_SOURCE,
733);
if (streamId < 0)
{
break;
}
this->ReceiveCellPoint(this->GetOutput(), streamId, -1);
}
// We were told that it is our turn to send first points.
if (streamId == -2)
{
this->SendFirstPoints(output);
}
}
// Once we are done sending, let's tell the next guy (unless
// this is the last process) to send it's first points
void vtkPStreamTracer::MoveToNextSend(vtkPolyData *output)
{
int numProcs = this->Controller->GetNumberOfProcesses();
int myid = this->Controller->GetLocalProcessId();
int tag;
if (myid == numProcs - 1)
{
tag = -1;
for(int i=0; i<numProcs; i++)
{
if (i != myid)
{
this->Controller->Send(&tag, 1, i, 733);
}
}
}
else
{
tag = -2;
this->Controller->Send(&tag, 1, myid+1, 733);
this->ReceiveLastPoints(output);
}
}
// After the integration is over, we need to add one point
// at the end of streamline pieces which were not the end
// piece. This has to be done in order to close the gap between
// pieces which appear due to jump from one process to another.
// This method sends the first point of each streamline which
// originated in another process to that process. This information
// is stored in the "Streamline Origin" array.
void vtkPStreamTracer::SendFirstPoints(vtkPolyData *output)
{
vtkIntArray* strOrigin = vtkIntArray::SafeDownCast(
output->GetCellData()->GetArray("Streamline Origin"));
if (!strOrigin)
{
this->MoveToNextSend(output);
return;
}
int numLines = strOrigin->GetNumberOfTuples();
int streamId, sendToId;
int i;
for(i=0; i<numLines; i++)
{
sendToId = strOrigin->GetValue(2*i);
streamId = strOrigin->GetValue(2*i+1);
if (streamId != -1)
{
this->Controller->Send(&streamId, 1, sendToId, 733);
this->SendCellPoint(output, i, 0, sendToId);
}
}
this->MoveToNextSend(output);
}
// Receive one point and add it to the given cell.
void vtkPStreamTracer::ReceiveCellPoint(vtkPolyData* tomod,
int streamId,
vtkIdType idx)
{
vtkPolyData* input = vtkPolyData::New();
// Receive a polydata which contains one point.
this->Controller->Receive(input, vtkMultiProcessController::ANY_SOURCE, 765);
int numCells = tomod->GetNumberOfCells();
// Use the "Streamline Ids" array to locate the right cell.
vtkIntArray* streamIds = vtkIntArray::SafeDownCast(
tomod->GetCellData()->GetArray("Streamline Ids"));
if (!streamIds)
{
input->Delete();
return;
}
vtkIdType cellId=-1;
for(vtkIdType cellIdx=0; cellIdx < numCells; cellIdx++)
{
if (streamIds->GetValue(cellIdx) == streamId)
{
cellId = cellIdx;
break;
}
}
if ( cellId == -1 )
{
return;
}
// Find the point to be modified. We don't actually add a point,
// we just replace replace the attributes of one (usually the last)
// with the new attributes we received.
vtkIdType ptId;
vtkIdType npts;
vtkIdType* pts;
tomod->GetCellPoints(cellId, npts, pts);
if (idx == -1)
{
idx = npts-1;
}
ptId = pts[idx];
// Replace attributes
vtkPointData* pd = input->GetPointData();
int numArrays = pd->GetNumberOfArrays();
int i;
vtkPointData* outputPD = tomod->GetPointData();
for(i=0; i<numArrays; i++)
{
vtkDataArray* da = pd->GetArray(i);
const char* name = da->GetName();
if (name)
{
vtkDataArray* outputDA = outputPD->GetArray(name);
outputDA->SetTuple(ptId, da->GetTuple(0));
}
}
input->Delete();
}
// Send one point and all of it's attributes to another process
void vtkPStreamTracer::SendCellPoint(vtkPolyData* togo,
vtkIdType cellId,
vtkIdType idx,
int sendToId)
{
// We create a dummy dataset which will contain the point
// we want to send and it's attributes.
vtkPolyData* copy = vtkPolyData::New();
vtkIdType ptId;
vtkIdType npts;
vtkIdType* pts;
togo->GetCellPoints(cellId, npts, pts);
ptId = pts[idx];
vtkPoints* points = vtkPoints::New();
points->SetNumberOfPoints(1);
points->SetPoint(0, togo->GetPoint(ptId));
copy->SetPoints(points);
points->Delete();
vtkPointData* togoPD = togo->GetPointData();
vtkPointData* copyPD = copy->GetPointData();
copyPD->CopyAllocate(togoPD, 1);
copyPD->CopyData(togoPD, ptId, 0);
this->Controller->Send(copy, sendToId, 765);
copy->Delete();
}
int vtkPStreamTracer::RequestUpdateExtent(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
vtkInformation *outInfo = outputVector->GetInformationObject(0);
int piece =
outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
int numPieces =
outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
int ghostLevel =
outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
int numInputs = this->GetNumberOfInputConnections(0);
for (int idx = 0; idx < numInputs; ++idx)
{
vtkInformation *info = inputVector[0]->GetInformationObject(idx);
if (info)
{
info->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),
piece);
info->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
numPieces);
info->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
ghostLevel);
}
}
vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0);
if (sourceInfo)
{
sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),
0);
sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
1);
sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
ghostLevel);
}
return 1;
}
int vtkPStreamTracer::RequestInformation(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **vtkNotUsed(inputVector),
vtkInformationVector *outputVector)
{
vtkInformation *outInfo = outputVector->GetInformationObject(0);
outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), -1);
return 1;
}
int vtkPStreamTracer::RequestData(
vtkInformation *request,
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
if (!this->Controller)
{
vtkErrorMacro("No controller assigned. Can not execute.");
return 0;
}
if (this->Controller->GetNumberOfProcesses() == 1)
{
this->GenerateNormalsInIntegrate = 1;
int retVal = this->Superclass::RequestData(request, inputVector,
outputVector);
this->GenerateNormalsInIntegrate = 0;
return retVal;
}
vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0);
vtkDataSet *source = 0;
if (sourceInfo)
{
source = vtkDataSet::SafeDownCast(
sourceInfo->Get(vtkDataObject::DATA_OBJECT()));
}
vtkInformation *outInfo = outputVector->GetInformationObject(0);
vtkPolyData* output = vtkPolyData::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkInterpolatedVelocityField* func;
int maxCellSize = 0;
if (this->CheckInputs(func, &maxCellSize, inputVector) != VTK_OK)
{
vtkDebugMacro("No appropriate inputs have been found. Can not execute.");
func->Delete();
// >>>>>>>>>> TODO: All should pass this test.
return 1;
}
func->SetCaching(0);
this->SetInterpolator(func);
func->Delete();
this->InitializeSeeds(this->Seeds,
this->SeedIds,
this->IntegrationDirections,
source);
this->TmpOutputs.erase(this->TmpOutputs.begin(), this->TmpOutputs.end());
this->ParallelIntegrate(inputVector);
// The parallel integration adds all streamlines to TmpOutputs
// container. We append them all together here.
vtkAppendPolyData* append = vtkAppendPolyData::New();
for (TmpOutputsType::iterator it = this->TmpOutputs.begin();
it != this->TmpOutputs.end(); it++)
{
vtkPolyData* inp = it->GetPointer();
if ( inp->GetNumberOfCells() > 0 )
{
append->AddInput(inp);
}
}
if (append->GetNumberOfInputConnections(0) > 0)
{
append->Update();
vtkPolyData* appoutput = append->GetOutput();
output->CopyStructure(appoutput);
output->GetPointData()->PassData(appoutput->GetPointData());
output->GetCellData()->PassData(appoutput->GetCellData());
}
append->Delete();
this->TmpOutputs.erase(this->TmpOutputs.begin(), this->TmpOutputs.end());
// Fill the gaps between streamlines.
output->BuildCells();
int myid = this->Controller->GetLocalProcessId();
if (myid == 0)
{
this->SendFirstPoints(output);
}
else
{
this->ReceiveLastPoints(output);
}
if (this->Seeds)
{
this->Seeds->Delete();
this->Seeds = 0;
}
this->IntegrationDirections->Delete();
this->IntegrationDirections = 0;
this->SeedIds->Delete();
this->SeedIds = 0;
output->Squeeze();
return 1;
}
void vtkPStreamTracer::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "Controller: " << this->Controller << endl;
}