mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
502 lines
16 KiB
C++
502 lines
16 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkFieldDataSerializer.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 "vtkDataArray.h"
|
|
#include "vtkFieldData.h"
|
|
#include "vtkFieldDataSerializer.h"
|
|
#include "vtkIdList.h"
|
|
#include "vtkIntArray.h"
|
|
#include "vtkMultiProcessStream.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkStringArray.h"
|
|
#include "vtkStructuredData.h"
|
|
#include "vtkStructuredExtent.h"
|
|
|
|
#include <cassert> // For assert()
|
|
#include <cstring> // For memcpy
|
|
|
|
vtkStandardNewMacro(vtkFieldDataSerializer);
|
|
|
|
//------------------------------------------------------------------------------
|
|
vtkFieldDataSerializer::vtkFieldDataSerializer()
|
|
{
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
vtkFieldDataSerializer::~vtkFieldDataSerializer()
|
|
{
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkFieldDataSerializer::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkFieldDataSerializer::SerializeMetaData(
|
|
vtkFieldData *fieldData, vtkMultiProcessStream& bytestream)
|
|
{
|
|
if( fieldData == NULL )
|
|
{
|
|
vtkGenericWarningMacro("Field data is NULL!");
|
|
return;
|
|
}
|
|
|
|
// STEP 0: Write the number of arrays
|
|
bytestream << fieldData->GetNumberOfArrays();
|
|
|
|
// STEP 1: Loop through each array and write the metadata
|
|
for( int array=0; array < fieldData->GetNumberOfArrays(); ++array )
|
|
{
|
|
vtkDataArray *dataArray = fieldData->GetArray( array );
|
|
assert("pre: data array should not be NULL!" && (dataArray != NULL));
|
|
|
|
int dataType = dataArray->GetDataType();
|
|
int numComp = dataArray->GetNumberOfComponents();
|
|
int numTuples = dataArray->GetNumberOfTuples();
|
|
|
|
// serialize array information
|
|
bytestream << dataType << numTuples << numComp;
|
|
bytestream << std::string( dataArray->GetName() );
|
|
} // END for all arrays
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkFieldDataSerializer::DeserializeMetaData(
|
|
vtkMultiProcessStream& bytestream,
|
|
vtkStringArray *names,
|
|
vtkIntArray *datatypes,
|
|
vtkIntArray *dimensions)
|
|
{
|
|
if( bytestream.Empty() )
|
|
{
|
|
vtkGenericWarningMacro("ByteStream is empty");
|
|
return;
|
|
}
|
|
|
|
if( (names == NULL) || (datatypes == NULL) || (dimensions == NULL) )
|
|
{
|
|
vtkGenericWarningMacro(
|
|
"ERROR: caller must pre-allocation names/datatypes/dimensions!");
|
|
return;
|
|
}
|
|
|
|
// STEP 0: Extract the number of arrays
|
|
int NumberOfArrays;
|
|
bytestream >> NumberOfArrays;
|
|
if( NumberOfArrays == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// STEP 1: Allocate output data-structures
|
|
names->SetNumberOfValues(NumberOfArrays);
|
|
datatypes->SetNumberOfValues(NumberOfArrays);
|
|
dimensions->SetNumberOfComponents(2);
|
|
dimensions->SetNumberOfTuples(NumberOfArrays);
|
|
|
|
std::string *namesPtr = static_cast<std::string*>(names->GetVoidPointer(0));
|
|
int *datatypesPtr = static_cast<int*>(datatypes->GetVoidPointer(0));
|
|
int *dimensionsPtr = static_cast<int*>(dimensions->GetVoidPointer(0));
|
|
|
|
// STEP 2: Extract metadata for each array in corresponding output arrays
|
|
for( int arrayIdx=0; arrayIdx < NumberOfArrays; ++arrayIdx )
|
|
{
|
|
bytestream >> datatypesPtr[ arrayIdx ] >> dimensionsPtr[arrayIdx*2] >>
|
|
dimensionsPtr[arrayIdx*2+1] >> namesPtr[ arrayIdx ];
|
|
} // END for all arrays
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkFieldDataSerializer::Serialize(
|
|
vtkFieldData *fieldData, vtkMultiProcessStream& bytestream)
|
|
{
|
|
if( fieldData == NULL )
|
|
{
|
|
vtkGenericWarningMacro("Field data is NULL!");
|
|
return;
|
|
}
|
|
|
|
// STEP 0: Write the number of arrays
|
|
bytestream << fieldData->GetNumberOfArrays();
|
|
|
|
if( fieldData->GetNumberOfArrays() == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// STEP 1: Loop through each array and serialize its metadata
|
|
for( int array=0; array < fieldData->GetNumberOfArrays(); ++array )
|
|
{
|
|
vtkDataArray *dataArray = fieldData->GetArray( array );
|
|
vtkFieldDataSerializer::SerializeDataArray( dataArray, bytestream );
|
|
} // END for all arrays
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkFieldDataSerializer::SerializeTuples(
|
|
vtkIdList *tupleIds, vtkFieldData *fieldData,
|
|
vtkMultiProcessStream& bytestream )
|
|
{
|
|
if( fieldData == NULL )
|
|
{
|
|
vtkGenericWarningMacro("Field data is NULL!");
|
|
return;
|
|
}
|
|
|
|
// STEP 0: Write the number of arrays
|
|
bytestream << fieldData->GetNumberOfArrays();
|
|
|
|
if( fieldData->GetNumberOfArrays() == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// STEP 1: Loop through each array, extract the data on the selected tuples
|
|
// and serialize it
|
|
for( int array=0; array < fieldData->GetNumberOfArrays(); ++array )
|
|
{
|
|
vtkDataArray *dataArray = fieldData->GetArray( array );
|
|
|
|
// STEP 2: For each array extract only the selected tuples, i.e., a subset
|
|
vtkDataArray *subSet = NULL;
|
|
subSet = vtkFieldDataSerializer::ExtractSelectedTuples(tupleIds,dataArray);
|
|
assert("pre: subset array is NULL!" && (subSet != NULL) );
|
|
|
|
// STEP 3: Serialize only a subset of the data
|
|
vtkFieldDataSerializer::SerializeDataArray( subSet, bytestream );
|
|
subSet->Delete();
|
|
} // END for all arrays
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkFieldDataSerializer::SerializeSubExtent(
|
|
int subext[6], int gridExtent[6], vtkFieldData *fieldData,
|
|
vtkMultiProcessStream& bytestream)
|
|
{
|
|
if( fieldData == NULL )
|
|
{
|
|
vtkGenericWarningMacro("Field data is NULL!");
|
|
return;
|
|
}
|
|
|
|
// STEP 0: Write the number of arrays
|
|
bytestream << fieldData->GetNumberOfArrays();
|
|
|
|
if( fieldData->GetNumberOfArrays() == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// STEP 1: Loop through each array, extract the data within the subext
|
|
// and serialize it
|
|
for( int array=0; array < fieldData->GetNumberOfArrays(); ++array )
|
|
{
|
|
vtkDataArray *dataArray = fieldData->GetArray( array );
|
|
|
|
// STEP 2: Extract the data within the requested sub-extent
|
|
vtkDataArray *subSet = NULL;
|
|
subSet = vtkFieldDataSerializer::ExtractSubExtentData(
|
|
subext,gridExtent,dataArray);
|
|
assert("pre: subset array is NULL!" && (subSet != NULL) );
|
|
|
|
// STEP 3: Serialize only a subset of the data
|
|
vtkFieldDataSerializer::SerializeDataArray( subSet, bytestream );
|
|
subSet->Delete();
|
|
} // END for all arrays
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkFieldDataSerializer::DeSerializeToSubExtent(
|
|
int subext[6], int gridExtent[6], vtkFieldData* fieldData,
|
|
vtkMultiProcessStream& bytestream)
|
|
{
|
|
assert("pre: sub-extent outside grid-extent" &&
|
|
vtkStructuredExtent::Smaller(subext,gridExtent));
|
|
|
|
if( fieldData == NULL )
|
|
{
|
|
vtkGenericWarningMacro("Field data is NULL!");
|
|
return;
|
|
}
|
|
|
|
int numArrays = 0;
|
|
bytestream >> numArrays;
|
|
assert("post: numArrays mismatch!" &&
|
|
(numArrays==fieldData->GetNumberOfArrays()) );
|
|
|
|
int ijk[3];
|
|
for( int array=0; array < numArrays; ++array )
|
|
{
|
|
vtkDataArray* dataArray = NULL;
|
|
vtkFieldDataSerializer::DeserializeDataArray(bytestream,dataArray);
|
|
assert("post: dataArray is NULL!" && (dataArray != NULL) );
|
|
assert("post: fieldData does not have array!" &&
|
|
fieldData->HasArray(dataArray->GetName()));
|
|
|
|
vtkDataArray* targetArray = fieldData->GetArray( dataArray->GetName() );
|
|
assert("post: ncomp mismatch!" &&
|
|
(dataArray->GetNumberOfComponents()==targetArray->GetNumberOfComponents()));
|
|
|
|
for(ijk[0]=subext[0]; ijk[0] <= subext[1]; ++ijk[0])
|
|
{
|
|
for(ijk[1]=subext[2]; ijk[1] <= subext[3]; ++ijk[1])
|
|
{
|
|
for(ijk[2]=subext[4]; ijk[2] <= subext[5]; ++ijk[2])
|
|
{
|
|
vtkIdType sourceIdx =
|
|
vtkStructuredData::ComputePointIdForExtent(subext,ijk);
|
|
assert("post: sourceIdx out-of-bounds!" && (sourceIdx >= 0) &&
|
|
(sourceIdx < dataArray->GetNumberOfTuples()) );
|
|
|
|
vtkIdType targetIdx =
|
|
vtkStructuredData::ComputePointIdForExtent(gridExtent,ijk);
|
|
assert("post: targetIdx out-of-bounds!" && (targetIdx >= 0) &&
|
|
(targetIdx < targetArray->GetNumberOfTuples()) );
|
|
|
|
targetArray->SetTuple(targetIdx,sourceIdx,dataArray);
|
|
} // END for all k
|
|
} // END for all j
|
|
} // END for all i
|
|
|
|
dataArray->Delete();
|
|
} // END for all arrays
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
vtkDataArray* vtkFieldDataSerializer::ExtractSubExtentData(
|
|
int subext[6], int gridExtent[6], vtkDataArray *inputDataArray )
|
|
{
|
|
if( inputDataArray == NULL )
|
|
{
|
|
vtkGenericWarningMacro("input data array is NULL!");
|
|
return NULL;
|
|
}
|
|
|
|
// STEP 0: Acquire structured data description, i.e, XY_PLANE, XYZ_GRID etc.
|
|
int description = vtkStructuredData::GetDataDescriptionFromExtent(gridExtent);
|
|
|
|
// STEP 1: Allocate subset array
|
|
vtkDataArray *subSetArray =
|
|
vtkDataArray::CreateDataArray( inputDataArray->GetDataType() );
|
|
subSetArray->SetName( inputDataArray->GetName() );
|
|
subSetArray->SetNumberOfComponents( inputDataArray->GetNumberOfComponents());
|
|
subSetArray->SetNumberOfTuples(
|
|
vtkStructuredData::GetNumberOfPoints(subext,description));
|
|
|
|
int ijk[3];
|
|
for( ijk[0]=subext[0]; ijk[0] <= subext[1]; ++ijk[0] )
|
|
{
|
|
for( ijk[1]=subext[2]; ijk[1] <= subext[3]; ++ijk[1] )
|
|
{
|
|
for( ijk[2]=subext[4]; ijk[2] <= subext[5]; ++ijk[2] )
|
|
{
|
|
// Compute the source index from the grid extent. Note, this could be
|
|
// a cell index if the incoming gridExtent and subext are cell extents.
|
|
vtkIdType sourceIdx =
|
|
vtkStructuredData::ComputePointIdForExtent(
|
|
gridExtent,ijk,description);
|
|
assert("pre: source index is out-of-bounds" &&
|
|
(sourceIdx >= 0) &&
|
|
(sourceIdx < inputDataArray->GetNumberOfTuples()));
|
|
|
|
// Compute the target index in the subset array. Likewise, this could be
|
|
// either a cell index or a node index depending on what gridExtent or
|
|
// subext represent.
|
|
vtkIdType targetIdx =
|
|
vtkStructuredData::ComputePointIdForExtent(
|
|
subext,ijk,description);
|
|
assert("pre: target index is out-of-bounds" &&
|
|
(targetIdx >= 0) &&
|
|
(targetIdx < subSetArray->GetNumberOfTuples()));
|
|
|
|
subSetArray->SetTuple( targetIdx, sourceIdx, inputDataArray );
|
|
} // END for all k
|
|
} // END for all j
|
|
} // END for all i
|
|
|
|
return(subSetArray);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
vtkDataArray* vtkFieldDataSerializer::ExtractSelectedTuples(
|
|
vtkIdList *tupleIds, vtkDataArray *inputDataArray )
|
|
{
|
|
vtkDataArray *subSetArray =
|
|
vtkDataArray::CreateDataArray( inputDataArray->GetDataType() );
|
|
subSetArray->SetName( inputDataArray->GetName() );
|
|
subSetArray->SetNumberOfComponents( inputDataArray->GetNumberOfComponents());
|
|
subSetArray->SetNumberOfTuples(tupleIds->GetNumberOfIds());
|
|
|
|
vtkIdType idx = 0;
|
|
for( ; idx < tupleIds->GetNumberOfIds(); ++idx )
|
|
{
|
|
vtkIdType tupleIdx = tupleIds->GetId(idx);
|
|
assert("pre: tuple ID is out-of bounds" &&
|
|
(tupleIdx >= 0) && (tupleIdx < inputDataArray->GetNumberOfTuples()));
|
|
|
|
subSetArray->SetTuple( idx, tupleIdx, inputDataArray );
|
|
} // END for all tuples to extract
|
|
return( subSetArray );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkFieldDataSerializer::SerializeDataArray(
|
|
vtkDataArray *dataArray, vtkMultiProcessStream& bytestream)
|
|
{
|
|
if( dataArray == NULL )
|
|
{
|
|
vtkGenericWarningMacro("data array is NULL!");
|
|
return;
|
|
}
|
|
|
|
// STEP 0: Serialize array information
|
|
int dataType = dataArray->GetDataType();
|
|
int numComp = dataArray->GetNumberOfComponents();
|
|
int numTuples = dataArray->GetNumberOfTuples();
|
|
|
|
// serialize array information
|
|
bytestream << dataType << numTuples << numComp;
|
|
bytestream << std::string( dataArray->GetName() );
|
|
|
|
// STEP 1: Push the raw data into the bytestream
|
|
// TODO: Add more cases for more datatypes here (?)
|
|
unsigned int size = numComp*numTuples;
|
|
switch( dataArray->GetDataType() )
|
|
{
|
|
case VTK_FLOAT:
|
|
bytestream.Push(static_cast<float*>(dataArray->GetVoidPointer(0)),size);
|
|
break;
|
|
case VTK_DOUBLE:
|
|
bytestream.Push(static_cast<double*>(dataArray->GetVoidPointer(0)),size);
|
|
break;
|
|
case VTK_INT:
|
|
bytestream.Push(static_cast<int*>(dataArray->GetVoidPointer(0)),size);
|
|
break;
|
|
case VTK_ID_TYPE:
|
|
bytestream.Push(
|
|
static_cast<vtkIdType*>(dataArray->GetVoidPointer(0)),size);
|
|
break;
|
|
default:
|
|
assert("ERROR: cannot serialize data of given type" && false);
|
|
cerr << "Canot serialize data of type="
|
|
<< dataArray->GetDataType() << endl;
|
|
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkFieldDataSerializer::Deserialize(
|
|
vtkMultiProcessStream& bytestream, vtkFieldData *fieldData)
|
|
{
|
|
if( fieldData == NULL )
|
|
{
|
|
vtkGenericWarningMacro("FieldData is NULL!");
|
|
return;
|
|
}
|
|
|
|
if( bytestream.Empty() )
|
|
{
|
|
vtkGenericWarningMacro("Bytestream is empty!");
|
|
return;
|
|
}
|
|
|
|
// STEP 0: Get the number of arrays
|
|
int numberOfArrays = 0;
|
|
bytestream >> numberOfArrays;
|
|
|
|
if( numberOfArrays == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// STEP 1: Loop and deserialize each array
|
|
for( int array=0; array < numberOfArrays; ++array )
|
|
{
|
|
vtkDataArray *dataArray = NULL;
|
|
vtkFieldDataSerializer::DeserializeDataArray( bytestream,dataArray );
|
|
assert("post: deserialized data array should not be NULL!" &&
|
|
(dataArray != NULL));
|
|
fieldData->AddArray( dataArray );
|
|
dataArray->Delete();
|
|
} // END for all arrays
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkFieldDataSerializer::DeserializeDataArray(
|
|
vtkMultiProcessStream& bytestream,
|
|
vtkDataArray *&dataArray)
|
|
{
|
|
if( bytestream.Empty() )
|
|
{
|
|
vtkGenericWarningMacro("Bytestream is empty!");
|
|
return;
|
|
}
|
|
|
|
// STEP 0: Deserialize array information
|
|
int dataType, numTuples, numComp;
|
|
std::string name;
|
|
|
|
bytestream >> dataType >> numTuples >> numComp >> name;
|
|
assert("pre: numComp >= 1" && (numComp >= 1) );
|
|
|
|
// STEP 1: Construct vtkDataArray object
|
|
dataArray = vtkDataArray::CreateDataArray( dataType );
|
|
dataArray->SetNumberOfComponents( numComp );
|
|
dataArray->SetNumberOfTuples( numTuples );
|
|
dataArray->SetName( name.c_str() );
|
|
|
|
// STEP 2: Extract raw data to vtkDataArray
|
|
// TODO: Add more cases for more datatypes here (?)
|
|
unsigned int size = numTuples*numComp;
|
|
void* rawPtr = dataArray->GetVoidPointer(0);
|
|
assert("pre: raw pointer is NULL!" && (rawPtr != NULL) );
|
|
switch( dataType )
|
|
{
|
|
case VTK_FLOAT:
|
|
{
|
|
float* data = static_cast<float*>(rawPtr);
|
|
bytestream.Pop(data,size);
|
|
}
|
|
break;
|
|
case VTK_DOUBLE:
|
|
{
|
|
double *data = static_cast<double*>(rawPtr);
|
|
bytestream.Pop(data,size);
|
|
}
|
|
break;
|
|
case VTK_INT:
|
|
{
|
|
int *data = static_cast<int*>(rawPtr);
|
|
bytestream.Pop(data,size);
|
|
}
|
|
break;
|
|
case VTK_ID_TYPE:
|
|
{
|
|
vtkIdType* data = static_cast<vtkIdType*>(rawPtr);
|
|
bytestream.Pop(data,size);
|
|
}
|
|
break;
|
|
default:
|
|
assert("ERROR: cannot serialize data of given type" && false);
|
|
cerr << "Canot serialize data of type="
|
|
<< dataArray->GetDataType() << endl;
|
|
}
|
|
}
|