Files
ThirdParty-6/ParaView-5.0.1/Plugins/StreamingParticles/vtkPVRandomPointsStreamingSource.cxx

178 lines
5.6 KiB
C++

#include "vtkPVRandomPointsStreamingSource.h"
#include "vtkCellArray.h"
#include "vtkCompositeDataPipeline.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMinimalStandardRandomSequence.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkNew.h"
#include "vtkObjectFactory.h"
#include "vtkPoints.h"
#include "vtkSmartPointer.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkPolyData.h"
#include <algorithm>
#include <cassert>
class vtkPVRandomPointsStreamingSource::vtkInternals
{
public:
std::vector<int> GeneratedSeeds;
vtkMinimalStandardRandomSequence* RNG;
};
vtkStandardNewMacro(vtkPVRandomPointsStreamingSource)
vtkPVRandomPointsStreamingSource::vtkPVRandomPointsStreamingSource()
{
this->SetNumberOfInputPorts(0);
this->SetNumberOfOutputPorts(1);
this->Internal = new vtkInternals;
this->Internal->RNG = vtkMinimalStandardRandomSequence::New();
this->NumLevels = 5;
this->PointsPerBlock = 100;
this->Seed = 1;
}
vtkPVRandomPointsStreamingSource::~vtkPVRandomPointsStreamingSource()
{
this->Internal->RNG->Delete();
delete this->Internal;
}
void vtkPVRandomPointsStreamingSource::PrintSelf(ostream &os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
}
int vtkPVRandomPointsStreamingSource::RequestInformation(
vtkInformation*, vtkInformationVector**, vtkInformationVector *outputVector)
{
// tell the pipeline that this dataset is distributed
outputVector->GetInformationObject(0)->Set(
CAN_HANDLE_PIECE_REQUEST(),
1
);
// Initialize the datastructures for the metadata
vtkSmartPointer< vtkMultiBlockDataSet > outline =
vtkSmartPointer< vtkMultiBlockDataSet >::New();
outline->SetNumberOfBlocks(this->NumLevels);
// Initialize the random seed used to generate the block seeds
this->Internal->RNG->SetSeed(this->Seed);
this->Internal->GeneratedSeeds.clear();
// Initialize the block bounds and seeds
for (int i = 0; i < this->NumLevels; ++i)
{
int blocksInLevel = 1 << (3 * i); // 8 ^ i
vtkNew< vtkMultiBlockDataSet > ds;
vtkNew< vtkMultiBlockDataSet > dsTmp;
ds->SetNumberOfBlocks(blocksInLevel);
outline->SetBlock(i,ds.GetPointer());
for (int j = 0; j < blocksInLevel; ++j)
{
this->Internal->RNG->Next();
this->Internal->GeneratedSeeds.push_back(
this->Internal->RNG->GetSeed() * 49);
int blocksPerSide = 1 << i;
int xJump = blocksPerSide * blocksPerSide;
int yJump = blocksPerSide;
int x = j / xJump;
int y = (j % xJump) / yJump;
int z = j % yJump;
double sideLen = 128.0 / blocksPerSide;
double bounds[6];
bounds[0] = sideLen * x;
bounds[1] = bounds[0] + sideLen;
bounds[2] = sideLen * y;
bounds[3] = bounds[2] + sideLen;
bounds[4] = sideLen * z;
bounds[5] = bounds[4] + sideLen;
vtkInformation* info = ds->GetMetaData(j);
info->Set(vtkStreamingDemandDrivenPipeline::BOUNDS(),
bounds,6);
}
}
outputVector->GetInformationObject(0)->Set(
vtkCompositeDataPipeline::COMPOSITE_DATA_META_DATA(),outline);
return 1;
}
int vtkPVRandomPointsStreamingSource::RequestData(
vtkInformation*, vtkInformationVector**, vtkInformationVector *outputVector)
{
// Get the input and output objects
vtkMultiBlockDataSet* output = vtkMultiBlockDataSet::GetData(outputVector,0);
vtkInformation* outInfo = outputVector->GetInformationObject(0);
// make sure the output has the right structure
output->SetNumberOfBlocks(this->NumLevels);
for (int i = 0; i < this->NumLevels; ++i)
{
int blocksInLevel = 1 << (3 * i); // 8 ^ i
vtkNew< vtkMultiBlockDataSet > ds;
ds->SetNumberOfBlocks(blocksInLevel);
output->SetBlock(i,ds.GetPointer());
}
// Find out which blocks have been requested
int defaultIds[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
int size = 9;
int* ids = defaultIds;
if (outInfo->Has(vtkCompositeDataPipeline::LOAD_REQUESTED_BLOCKS()))
{
size = outInfo->Length(
vtkCompositeDataPipeline::UPDATE_COMPOSITE_INDICES());
ids = outInfo->Get(
vtkCompositeDataPipeline::UPDATE_COMPOSITE_INDICES());
}
// sort the requested ids
std::sort(ids,ids+size);
int offset = 0;
int level = 0;
// for each requested id, generate that block
for (int i = 0; i < size; ++i)
{
// find out which level the block is on
while (ids[i] >= offset + (1 << (3*level)))
{
offset += 1 << (3*level);
++level;
assert(level <= this->NumLevels);
}
int blocksPerSide = 1 << level;
int xJump = blocksPerSide * blocksPerSide;
int yJump = blocksPerSide;
int xBlock = (ids[i] -offset) / xJump;
int yBlock = ((ids[i] -offset) % xJump) / yJump;
int zBlock = (ids[i] -offset) % yJump;
double sideLen = 128.0 / blocksPerSide;
vtkNew< vtkPolyData > grid;
grid->Initialize();
vtkMultiBlockDataSet::SafeDownCast(output->GetBlock(level))->SetBlock(
ids[i]-offset,grid.GetPointer());
vtkNew< vtkPoints > points;
grid->SetPoints(points.GetPointer());
vtkNew< vtkCellArray > cells;
// Generate the points
this->Internal->RNG->SetSeed(this->Internal->GeneratedSeeds[ids[i]]);
for (vtkIdType j = 0; j < this->PointsPerBlock; ++j)
{
double x = sideLen * (xBlock + this->Internal->RNG->GetValue());
this->Internal->RNG->Next();
double y = sideLen * (yBlock + this->Internal->RNG->GetValue());
this->Internal->RNG->Next();
double z = sideLen * (zBlock + this->Internal->RNG->GetValue());
this->Internal->RNG->Next();
points->InsertNextPoint(x,y,z);
cells->InsertNextCell(1,&j);
}
grid->SetVerts(cells.GetPointer());
}
return 1;
}