Commit 8707ad9e authored by Yuanxin Liu's avatar Yuanxin Liu
Browse files

Clean up amr data structure API

- Set spacing and AMRBox separately.
- Expose APIs on vtkAMRInformation on vtkOverlappingAMR
- Add printing and auditing routines for better debugging support
- Fix bug in AMRSliceFilter and add test
- Simplify vtkOverlappingAMR initialization
- change vtkOverlappingAMR:SetGridSpacing to vtkOverlappingAMR:SetSpacing

Change-Id: I4ea8497192bc8c0dcda3a5a3726051342a3d48f5
parent 9e477c2b
......@@ -19,6 +19,7 @@
#include "vtkType.h"
#include "vtkStructuredData.h"
#include "vtkImageData.h"
#include "vtkMath.h"
#include <algorithm>
#include <cstring>
......@@ -33,11 +34,21 @@ vtkAMRBox::vtkAMRBox()
}
//-----------------------------------------------------------------------------
vtkAMRBox::vtkAMRBox(
int ilo,int jlo,
int ihi,int jhi)
vtkAMRBox::vtkAMRBox(const double* origin, const int* dimensions, const double* spacing, const double* globalOrigin,int gridDescription)
{
this->BuildAMRBox( ilo,jlo,0,ihi,jhi,-1);
int ndim[3];
for( int d=0; d<3; ++d )
{
ndim[d] = dimensions[d]-1;
}
int lo[3], hi[3];
for( int d=0; d<3; ++d )
{
lo[d] = vtkMath::Round( (origin[d] - globalOrigin[d])/spacing[d] );
hi[d] = vtkMath::Round( static_cast<double>(lo[d] + ( ndim[d]-1 )) );
}
this->SetDimensions( lo, hi, gridDescription);
}
//-----------------------------------------------------------------------------
......@@ -178,7 +189,7 @@ void vtkAMRBox::GetValidHiCorner(int *hi) const
}
//-----------------------------------------------------------------------------
void vtkAMRBox::GetBoxOrigin(const vtkAMRBox& extent, double X0[3], double spacing[3],double x0[3])
void vtkAMRBox::GetBoxOrigin(const vtkAMRBox& extent, const double X0[3], const double spacing[3],double x0[3])
{
assert( "pre: input array is NULL" && (x0 != NULL) );
x0[0] = x0[1] = x0[2] = 0.0;
......@@ -191,7 +202,7 @@ void vtkAMRBox::GetBoxOrigin(const vtkAMRBox& extent, double X0[3], double spaci
//-----------------------------------------------------------------------------
void vtkAMRBox::GetBounds(const vtkAMRBox& extent, double origin[3], double spacing[3],double bounds[6])
void vtkAMRBox::GetBounds(const vtkAMRBox& extent, const double origin[3], const double spacing[3], double bounds[6])
{
int i, j;
for( i=0, j=0; i < 3; ++i )
......@@ -202,7 +213,7 @@ void vtkAMRBox::GetBounds(const vtkAMRBox& extent, double origin[3], double spac
}
//-----------------------------------------------------------------------------
bool vtkAMRBox::HasPoint(const vtkAMRBox& box, double origin[3], double spacing[3], const double x, const double y, const double z )
bool vtkAMRBox::HasPoint(const vtkAMRBox& box, const double origin[3], const double spacing[3], double x, double y, double z )
{
assert( "pre: AMR Box instance is invalid" && !box.IsInvalid() );
......@@ -469,8 +480,8 @@ bool vtkAMRBox::DoesIntersect(const vtkAMRBox &other) const
return true;
}
int vtkAMRBox::ComputeStructuredCoordinates(const vtkAMRBox& box, double dataOrigin[3],
double h[3], double x[3], int ijk[3], double pcoords[3])
int vtkAMRBox::ComputeStructuredCoordinates(const vtkAMRBox& box, const double dataOrigin[3],
const double h[3], const double x[3], int ijk[3], double pcoords[3])
{
double origin[3];
vtkAMRBox::GetBoxOrigin(box,dataOrigin,h,origin);
......
......@@ -30,6 +30,14 @@
class VTKCOMMONDATAMODEL_EXPORT vtkAMRBox
{
public:
// Description:
// Construct the empty box.
vtkAMRBox();
// Description:
// Copy construct this box from another.
vtkAMRBox(const vtkAMRBox &other);
// Description:
// Construct a specific 3D box.
vtkAMRBox(
......@@ -42,23 +50,19 @@ class VTKCOMMONDATAMODEL_EXPORT vtkAMRBox
int ilo,int jlo,
int ihi,int jhi);
// Description
// Construct an AMR box from the description a vtkUniformGrid
// Note that the dimensions specify the node dimensions, rather than the cell dimensions
vtkAMRBox(const double* origin, const int* dimensions, const double* spacing,
const double* globalOrigin, int gridDescription=VTK_XYZ_GRID);
// Description:
// Construct a specific box. (ilo,jlo,klo,)(ihi,jhi,khi)
vtkAMRBox(const int lo[3], const int hi[3]);
// Description:
// Construct a specific box. (ilo,ihi, jlo,jhi, klo,khi)
vtkAMRBox(const int dims[6]);
// Description:
// Construct the empty box.
vtkAMRBox();
// Description:
// Copy construct this box from another.
vtkAMRBox(const vtkAMRBox &other);
// Description:
// Copy the other box to this box.
vtkAMRBox &operator=(const vtkAMRBox &other);
......@@ -77,11 +81,6 @@ class VTKCOMMONDATAMODEL_EXPORT vtkAMRBox
// Whether dimension i is empty, e.g. if the data set is type VTK_XY_PLANE
bool EmptyDimension(int i) const{ return HiCorner[i]<=LoCorner[i]-1;}
// Description:
// Returns the number of ghost layes that have been extruded along
// each dimension.
void GetNumberOfGhosts( int *ng );
// Description:
// Set the dimensions of the box. ilo,jlo,klo,ihi,jhi,khi
void SetDimensions(
......@@ -240,22 +239,22 @@ class VTKCOMMONDATAMODEL_EXPORT vtkAMRBox
// Description:
// Get the bounds of this box.
static void GetBounds(const vtkAMRBox& box, double origin[3],double spacing[3],double bounds[6]) ;
static void GetBounds(const vtkAMRBox& box, const double origin[3], const double spacing[3],double bounds[6]) ;
// Description:
// Get the world space origin of this box. The origin is the
// location of the lower corner cell's lower corner node,
static void GetBoxOrigin(const vtkAMRBox& box, double X0[3], double spacing[3],double x0[3]);
static void GetBoxOrigin(const vtkAMRBox& box, const double X0[3], const double spacing[3],double x0[3]);
// Description:
// Checks if the point is inside this AMRBox instance.
// x,y,z the world point
static bool HasPoint(const vtkAMRBox& box, double origin[3], double spacing[3], const double x, const double y, const double z );
static int ComputeStructuredCoordinates(const vtkAMRBox& box, double dataOrigin[3],
double h[3], double x[3], int ijk[3], double pcoords[3]);
static bool HasPoint(const vtkAMRBox& box, const double origin[3], const double spacing[3], double x, double y, double z );
// Description
//Compute structured coordinates
static int ComputeStructuredCoordinates(const vtkAMRBox& box, const double dataOrigin[3],
const double h[3], const double x[3], int ijk[3], double pcoords[3]);
protected:
// Description:
......
......@@ -147,20 +147,28 @@ vtkAMRInformation::~vtkAMRInformation()
void vtkAMRInformation::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "Grid description: " << this->GetGridDescription()<< "\n";
os << indent << "Global origin: ("
<< this->GetOrigin()[0] <<", "
<< this->GetOrigin()[1] <<", "
<< this->GetOrigin()[2] <<")\n ";
os<<"Number of blocks per level: ";
for(unsigned int i=1; i<this->NumBlocks.size();i++)
{
os<<this->NumBlocks[i]-this->NumBlocks[i-1]<<" ";
os<<indent<<this->NumBlocks[i]-this->NumBlocks[i-1]<<" ";
}
os<<"\n";
os<<"Refinemnt Ratio: ";
os<<indent<<"Refinemnt Ratio: ";
for(unsigned int i=0; i<this->GetNumberOfLevels();i++)
{
os<<this->GetRefinementRatio(i)<<" ";
}
if(this->HasChildrenInformation())
{
os<<indent<<"Parent Child information: \n";
for (unsigned int levelIdx=0; levelIdx<this->GetNumberOfLevels(); levelIdx++)
{
unsigned int numDataSets = this->GetNumberOfDataSets( levelIdx );
......@@ -173,23 +181,73 @@ void vtkAMRInformation::PrintSelf(ostream& os, vtkIndent indent)
os<<"\n";
}
bool vtkAMRInformation::IsValid()
bool vtkAMRInformation::Audit()
{
if(static_cast<unsigned int>(this->Refinement->GetNumberOfTuples())!=this->GetNumberOfLevels())
int emptyDimension(-1);
switch (this->GridDescription)
{
return false;
case VTK_YZ_PLANE: emptyDimension = 0; break;
case VTK_XZ_PLANE: emptyDimension = 1; break;
case VTK_XY_PLANE: emptyDimension = 2; break;
}
//Check origin
for(int d = 0; d<3; d++)
{
if(d!=emptyDimension)
{
if(this->Origin[d]!=this->Bounds[2*d])
{
vtkErrorMacro("Bound min does not match origin at dimension "<<d<<": "<<this->Origin[d]<<" != "<< this->Bounds[2*d]);
}
}
}
//check refinement levels
if(this->Refinement && static_cast<unsigned int>(this->Refinement->GetNumberOfTuples())!=this->GetNumberOfLevels())
{
vtkErrorMacro("Refinement levels wrong "<< this->Refinement->GetNumberOfTuples());
}
//check spacing
for(unsigned int i=0; i<this->GetNumberOfLevels(); i++)
{
double h[3];
this->GetSpacing(i,h);
for(int d=0; d<3; d++)
{
if(h[d]<0)
{
vtkErrorMacro("Invalid spacing at level "<<i<<endl);
}
}
}
//check amr boxes
for(unsigned int i=0; i<this->Boxes.size();i++)
{
if(this->Boxes[i].IsInvalid())
const vtkAMRBox& box = this->Boxes[i];
if(box.IsInvalid())
{
return false;
vtkErrorMacro("Invalid AMR Box");
}
bool valid(true);
switch (this->GridDescription)
{
case VTK_YZ_PLANE: valid = box.EmptyDimension(0); break;
case VTK_XZ_PLANE: valid = box.EmptyDimension(1); break;
case VTK_XY_PLANE: valid = box.EmptyDimension(2); break;
}
if(!valid)
{
vtkErrorMacro("Invalid AMRBox. Wrong dimension");
}
}
return true;
}
void vtkAMRInformation::Initialize(int numLevels, int* blocksPerLevel)
void vtkAMRInformation::Initialize(int numLevels, const int* blocksPerLevel)
{
if(numLevels<0)
{
......@@ -215,13 +273,6 @@ void vtkAMRInformation::Initialize(int numLevels, int* blocksPerLevel)
}
}
void vtkAMRInformation::Initialize(int numLevels, int* blocksPerLevel, double origin[3], int description)
{
this->Initialize(numLevels, blocksPerLevel);
this->SetOrigin(origin);
this->SetGridDescription(description);
}
unsigned int vtkAMRInformation::GetNumberOfDataSets(unsigned int level) const
{
if( level>= this->GetNumberOfLevels())
......@@ -248,55 +299,23 @@ void vtkAMRInformation::AllocateBoxes(unsigned int n)
}
void vtkAMRInformation::SetAMRBox(unsigned int level, unsigned int id, const vtkAMRBox& box, double* spacing)
void vtkAMRInformation::SetAMRBox(unsigned int level, unsigned int id, const vtkAMRBox& box)
{
unsigned int index = this->GetIndex(level,id);
this->Boxes[index] = box;
if(spacing)
if(this->HasSpacing(level)) //has valid spacing
{
this->UpdateSpacing(level, spacing);
this->UpdateBounds(level,id);
}
}
void vtkAMRInformation::SetAMRBox(unsigned int level, unsigned int id, double* min, double* max, int* dimensions)
{
double h[3];
for( int j=0; j < 3; ++j )
{
h[j] = (dimensions[j] > 1)? (max[j]-min[j])/(dimensions[j]-1.0):1.0;
}
this->SetAMRBox(level,id,min, dimensions,h);
}
void vtkAMRInformation::SetAMRBox(unsigned int level, unsigned int id, double* gridOrigin, int* dimensions, double* h)
{
assert(dimensions[0]>=1 && dimensions[1]>=1 && dimensions[2]>=1);
this->UpdateSpacing(level,h);
unsigned int index = this->GetIndex(level,id);
vtkAMRBox& box(this->Boxes[index]);
int ndim[3] = {dimensions[0]-1,dimensions[1]-1,dimensions[2]-1};
int lo[3];
int hi[3];
for(int i=0; i < 3; ++i )
{
lo[i] = vtkMath::Round( (gridOrigin[i] - this->Origin[i])/h[i] );
hi[i] = vtkMath::Round( static_cast<double>(lo[i] + ( ndim[i]-1 )) );
}
box.SetDimensions( lo, hi);
this->UpdateBounds(level,id);
}
int vtkAMRInformation::GetAMRBlockSourceIndex(int index)
{
return this->SourceIndex->GetValue(index);
}
void vtkAMRInformation::SetAMRBlockSourceIndex(int index, int sourceId)
{
{
if(!this->SourceIndex)
{
this->SourceIndex = vtkSmartPointer<vtkIntArray>::New();
......@@ -333,7 +352,7 @@ double* vtkAMRInformation::GetOrigin()
return this->Origin;
}
void vtkAMRInformation::SetOrigin( double* origin)
void vtkAMRInformation::SetOrigin( const double* origin)
{
for(int d=0; d<3; d++)
{
......@@ -498,6 +517,10 @@ PrintParentChildInfo(unsigned int level, unsigned int index)
void vtkAMRInformation::GenerateParentChildInformation()
{
if(!this->HasRefinementRatio())
{
this->GenerateRefinementRatio();
}
AllChildren.resize(this->GetNumberOfLevels());
AllParents.resize(this->GetNumberOfLevels());
......@@ -513,6 +536,11 @@ bool vtkAMRInformation::HasValidOrigin()
return this->Origin[0]!=DBL_MAX && this->Origin[1]!=DBL_MAX && this->Origin[2]!=DBL_MAX;
}
bool vtkAMRInformation::HasValidBounds()
{
return this->Bounds[0]!=DBL_MAX && this->Bounds[1]!=DBL_MAX && this->Bounds[2]!=DBL_MAX;
}
void vtkAMRInformation::SetGridDescription(int description)
{
if(this->GridDescription>=0 && description!=this->GridDescription)
......@@ -522,7 +550,7 @@ void vtkAMRInformation::SetGridDescription(int description)
this->GridDescription = description;
}
void vtkAMRInformation::UpdateSpacing(unsigned int level, const double* h)
void vtkAMRInformation::SetSpacing(unsigned int level, const double* h)
{
double* spacing = this->Spacing->GetTuple(level);
for(unsigned int i=0; i<3; i++)
......@@ -645,10 +673,10 @@ void vtkAMRInformation::CalculateParentChildRelationShip(
loExtent[1] = extents[2];
loExtent[2] = extents[4];
DataSetBinner binner(nbins, loExtent, binsize);
for(int i=0; i<3; i++)
{
cout<<nbins[i]<<" "<<loExtent[i]<<" "<<binsize[i]<<endl;
}
// for(int i=0; i<3; i++)
// {
// cout<<nbins[i]<<" "<<loExtent[i]<<" "<<binsize[i]<<endl;
// }
// Bin the blocks
for (unsigned int i=0; i<numParentDataSets; i++)
......@@ -857,3 +885,25 @@ void vtkAMRInformation::DeepCopy(vtkAMRInformation *other)
memcpy(this->Bounds, other->Bounds, sizeof(double)*6);
}
bool vtkAMRInformation::HasSpacing(unsigned int level)
{
return this->Spacing->GetTuple(level)[0] >=0
|| this->Spacing->GetTuple(level)[1] >=0
|| this->Spacing->GetTuple(level)[2] >=0;
}
const double* vtkAMRInformation::GetBounds()
{
if(!HasValidBounds())
{
for(unsigned int i=0; i<this->GetNumberOfLevels();i++)
{
for(unsigned int j=0; j<this->GetNumberOfDataSets(i);j++)
{
this->UpdateBounds(i,j);
}
}
}
return this->Bounds;
}
......@@ -56,14 +56,7 @@ public:
//Initialize the meta information
// numLevels is the number of levels
// blocksPerLevel[i] is the number of blocks at level i
// origin is the global origin
// gridDescription is the type of vtkUniformGrid, e.g. VTK_XYZ_GRID
void Initialize(int numLevels, int* numPerBlocks, double origin[3], int gridDescription);
// Description
// If this is used, then SetOrigin and SetGridDescription should be called
// laster
void Initialize(int numLevels, int* blocksPerLevel);
void Initialize(int numLevels, const int* blocksPerLevel);
// Description:
// returns the value of vtkUniformGrid::GridDescription() of any block
......@@ -75,7 +68,7 @@ public:
// The origin is essentially the minimum of all the grids.
void GetOrigin( double origin[3] );
double* GetOrigin();
void SetOrigin( double* origin);
void SetOrigin(const double* origin);
// Description:
// Return the number of levels
......@@ -93,7 +86,7 @@ public:
// Description:
// Returns the single index from a pair of indices
unsigned int GetIndex(unsigned int level, unsigned int id) const
int GetIndex(unsigned int level, unsigned int id) const
{ return this->NumBlocks[level] + id;}
// Description:
......@@ -102,7 +95,7 @@ public:
// Description
// Returns the bounds of the entire domain
const double* GetBounds() const {return this->Bounds;}
const double* GetBounds();
// Description
// Returns the bounding box of a given box
......@@ -116,11 +109,11 @@ public:
//Return the spacing at the given fiven
void GetSpacing(unsigned int level, double spacing[3]);
bool HasSpacing(unsigned int level);
// Description:
// Methods to set and get the AMR box at a given position
void SetAMRBox(unsigned int level, unsigned int id, const vtkAMRBox& box, double* spacing);
void SetAMRBox(unsigned int level, unsigned int id, double* min, double* max, int* dimensions);
void SetAMRBox(unsigned int level, unsigned int id, double* min, int* dimensions, double* h);
void SetAMRBox(unsigned int level, unsigned int id, const vtkAMRBox& box);
const vtkAMRBox& GetAMRBox(unsigned int level, unsigned int id) const;
// Description
......@@ -158,6 +151,10 @@ public:
// Returns the refinement of a given level.
int GetRefinementRatio(unsigned int level) const;
// Description:
// Set the spacing at a given level
void SetSpacing(unsigned int level,const double* h);
//Description:
//Return whether parent child information has been generated
bool HasChildrenInformation();
......@@ -183,10 +180,9 @@ public:
// before GetParents or GetChildren can be used!
void GenerateParentChildInformation();
// Description:
// Checks whether the meta data is internally consistent. Useful for testing
bool IsValid();
// Checks whether the meta data is internally consistent.
bool Audit();
// Description:
//Given a point q, find whether q is bounded by the data set at
......@@ -211,8 +207,8 @@ public:
void operator=(const vtkAMRInformation&); // Not implemented.
bool HasValidOrigin();
bool HasValidBounds();
void UpdateBounds(const int level, const int id);
void UpdateSpacing(unsigned int level,const double* h);
void AllocateBoxes(unsigned int n);
void GenerateBlockLevel();
void CalculateParentChildRelationShip( unsigned int level,
......
......@@ -919,9 +919,9 @@ void vtkImageData::SetDimensions(const int dim[3])
// The voxel is specified by the array ijk[3], and the parametric coordinates
// in the cell are specified with pcoords[3]. The function returns a 0 if the
// point x is outside of the volume, and a 1 if inside the volume.
int vtkImageData::ComputeStructuredCoordinates( double x[3], int ijk[3], double pcoords[3],
int* extent,
double* spacing,
int vtkImageData::ComputeStructuredCoordinates( const double x[3], int ijk[3], double pcoords[3],
const int* extent,
const double* spacing,
const double* origin,
const double* bounds)
{
......@@ -994,7 +994,7 @@ int vtkImageData::ComputeStructuredCoordinates( double x[3], int ijk[3], double
}
//----------------------------------------------------------------------------
int vtkImageData::ComputeStructuredCoordinates(double x[3], int ijk[3],
int vtkImageData::ComputeStructuredCoordinates(const double x[3], int ijk[3],
double pcoords[3])
{
return ComputeStructuredCoordinates(x,ijk,pcoords,this->Extent, this->Spacing, this->Origin, this->GetBounds());
......
......@@ -110,11 +110,11 @@ public:
// in the cell are specified with pcoords[3]. The function returns a 0 if the
// point x is outside of the volume, and a 1 if inside the volume.
virtual int ComputeStructuredCoordinates(
double x[3], int ijk[3], double pcoords[3]);
const double x[3], int ijk[3], double pcoords[3]);
static int ComputeStructuredCoordinates( double x[3], int ijk[3], double pcoords[3],
int* extent,
double* spacing,
static int ComputeStructuredCoordinates( const double x[3], int ijk[3], double pcoords[3],
const int* extent,
const double* spacing,
const double* origin,
const double* bounds);
// Description:
......
......@@ -19,6 +19,7 @@
#include "vtkUnsignedCharArray.h"
#include "vtkUniformGrid.h"
#include "vtkInformationIdTypeKey.h"
#include "vtkCellData.h"
#include <vector>
vtkStandardNewMacro(vtkOverlappingAMR);
......@@ -28,7 +29,6 @@ vtkInformationKeyMacro(vtkOverlappingAMR,NUMBER_OF_BLANKED_POINTS,IdType);
//----------------------------------------------------------------------------
vtkOverlappingAMR::vtkOverlappingAMR()
{
this->PadCellVisibility = false;
}
//----------------------------------------------------------------------------
......@@ -36,27 +36,14 @@ vtkOverlappingAMR::~vtkOverlappingAMR()
{
}
//----------------------------------------------------------------------------
void vtkOverlappingAMR::Initialize(int numLevels, int * blocksPerLevel, double origin[3], int gridDescription)
{
Superclass::Initialize();
this->AMRInfo->Initialize(numLevels,blocksPerLevel,origin,gridDescription);
}
//----------------------------------------------------------------------------
void vtkOverlappingAMR::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << "PadCellVisibility: ";
if( this->PadCellVisibility )
{
os << "ON(";
}
else
if(this->AMRInfo)
{
os << "OFF(";
this->AMRInfo->PrintSelf(os,indent);
}
os << this->PadCellVisibility << ")\n";
}
//----------------------------------------------------------------------------
......@@ -100,6 +87,7 @@ void vtkOverlappingAMR::GenerateParentChildInformation()
{
this->AMRInfo->GenerateParentChildInformation();
}
//----------------------------------------------------------------------------
bool vtkOverlappingAMR::
HasChildrenInformation()
......@@ -128,6 +116,12 @@ PrintParentChildInfo(unsigned int level, unsigned int index)
this->AMRInfo->PrintParentChildInfo(level,index);