jedi-academy/code/Ratl/grid_vs.h
2013-04-23 15:21:39 +10:00

526 lines
13 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////
// RAVEN STANDARD TEMPLATE LIBRARY
// (c) 2002 Activision
//
//
// Grid
// ----
// There are two versions of the Grid class. Simply, they apply a discreet function
// mapping from a n dimensional space to a linear aray.
//
//
//
//
//
//
// NOTES:
//
//
//
////////////////////////////////////////////////////////////////////////////////////////
#if !defined(RATL_GRID_VS_INC)
#define RATL_GRID_VS_INC
////////////////////////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////////////////////////
#if !defined(RATL_COMMON_INC)
#include "ratl_common.h"
#endif
#if !defined(RATL_ARRAY_VS)
#include "array_vs.h"
#endif
namespace ratl
{
////////////////////////////////////////////////////////////////////////////////////////
// The 2D Grid Class
////////////////////////////////////////////////////////////////////////////////////////
template <class T, int XSIZE_MAX, int YSIZE_MAX>
class grid2_vs : public ratl_base
{
public:
////////////////////////////////////////////////////////////////////////////////////
// Constructor
////////////////////////////////////////////////////////////////////////////////////
grid2_vs()
{
clear();
}
enum
{
RANGE_NULL = 12345,
};
////////////////////////////////////////////////////////////////////////////////////
// Assignment Operator
////////////////////////////////////////////////////////////////////////////////////
grid2_vs& operator=(const grid2_vs& other)
{
mData = other.mData;
for (int i=0; i<2; i++)
{
mSize[i] = other.mSize[i];
mMins[i] = other.mMins[i];
mMaxs[i] = other.mMaxs[i];
mScale[i] = other.mScale[i];
}
return (*this);
}
void set_size(int xSize, int ySize)
{
if (xSize<XSIZE_MAX)
{
mSize[0] = xSize;
}
if (ySize<YSIZE_MAX)
{
mSize[1] = ySize;
}
}
void snap_scale()
{
mScale[0] = (float)((int)(mScale[0]));
mScale[1] = (float)((int)(mScale[1]));
}
void get_size(int& xSize, int& ySize)
{
xSize = mSize[0];
ySize = mSize[1];
}
////////////////////////////////////////////////////////////////////////////////////
// Clear
////////////////////////////////////////////////////////////////////////////////////
void clear()
{
mSize[0] = XSIZE_MAX;
mSize[1] = YSIZE_MAX;
mData.clear();
for (int i=0; i<2; i++)
{
mMins[i] = RANGE_NULL;
mMaxs[i] = RANGE_NULL;
mScale[i] = 0.0f;
}
}
////////////////////////////////////////////////////////////////////////////////////
// Initialize The Entire Grid To A Value
////////////////////////////////////////////////////////////////////////////////////
void init(const T& val)
{
for (int i=0; i<(XSIZE_MAX*YSIZE_MAX); i++)
{
mData[i] = val;
}
}
////////////////////////////////////////////////////////////////////////////////////
// Copy The Bounds Of Another Grid
////////////////////////////////////////////////////////////////////////////////////
void copy_bounds(const grid2_vs& other)
{
for (int i=0; i<2; i++)
{
mSize[i] = other.mSize[i];
mMins[i] = other.mMins[i];
mMaxs[i] = other.mMaxs[i];
mScale[i] = other.mScale[i];
}
}
////////////////////////////////////////////////////////////////////////////////////
// Accessor
////////////////////////////////////////////////////////////////////////////////////
T& get(const int x, const int y)
{
assert(x>=0 && y>=0 && x<mSize[0] && y<mSize[1]);
return mData[(x + y*XSIZE_MAX)];
}
////////////////////////////////////////////////////////////////////////////////////
// Accessor
////////////////////////////////////////////////////////////////////////////////////
T& get(float x, float y)
{
assert(mScale[0]!=0.0f && mScale[1]!=0.0f);
truncate_position_to_bounds(x, y);
int xint = (int)( (x-mMins[0]) / mScale[0] );
int yint = (int)( (y-mMins[1]) / mScale[1] );
assert(xint>=0 && yint>=0 && xint<mSize[0] && yint<mSize[1]);
return mData[(xint + yint*XSIZE_MAX)];
}
////////////////////////////////////////////////////////////////////////////////////
// Convert The Scaled Coordinates To A Grid Coordinate
////////////////////////////////////////////////////////////////////////////////////
void get_cell_coords(float x, float y, int& xint, int& yint)
{
assert(mScale[0]!=0.0f && mScale[1]!=0.0f);
truncate_position_to_bounds(x, y);
xint = (int)( (x-mMins[0]) / mScale[0] );
yint = (int)( (y-mMins[1]) / mScale[1] );
assert(xint>=0 && yint>=0 && xint<mSize[0] && yint<mSize[1]);
}
////////////////////////////////////////////////////////////////////////////////////
// Expand
//
// NOTE: This MUST be at least a 2 dimensional point
////////////////////////////////////////////////////////////////////////////////////
void expand_bounds(float xReal, float yReal)
{
float point[2] = {xReal, yReal};
for (int i=0; i<2; i++)
{
if (point[i]<mMins[i] || mMins[i]==RANGE_NULL)
{
mMins[i] = point[i];
}
if (point[i]>mMaxs[i] || mMaxs[i]==RANGE_NULL)
{
mMaxs[i] = point[i];
}
}
assert(mSize[0]>0 && mSize[1]>0);
mScale[0] = ((mMaxs[0] - mMins[0])/mSize[0]);
mScale[1] = ((mMaxs[1] - mMins[1])/mSize[1]);
}
////////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////////
void truncate_position_to_bounds(float& xReal, float& yReal)
{
if (xReal<mMins[0])
{
xReal = mMins[0];
}
if (xReal>(mMaxs[0]-1.0f))
{
xReal = mMaxs[0]-1.0f;
}
if (yReal<mMins[1])
{
yReal = mMins[1];
}
if (yReal>(mMaxs[1]-1.0f))
{
yReal = mMaxs[1]-1.0f;
}
}
////////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////////
void get_cell_position(int x, int y, float& xReal, float& yReal)
{
// assert(mScale[0]!=0.0f && mScale[1]!=0.0f);
xReal = (x * mScale[0]) + mMins[0] + (mScale[0] * 0.5f);
yReal = (y * mScale[1]) + mMins[1] + (mScale[1] * 0.5f);
}
void get_cell_upperleft(int x, int y, float& xReal, float& yReal)
{
// assert(mScale[0]!=0.0f && mScale[1]!=0.0f);
xReal = (x * mScale[0]) + mMins[0];
yReal = (y * mScale[1]) + mMins[1];
}
void get_cell_lowerright(int x, int y, float& xReal, float& yReal)
{
// assert(mScale[0]!=0.0f && mScale[1]!=0.0f);
xReal = (x * mScale[0]) + mMins[0] + (mScale[0]);
yReal = (y * mScale[1]) + mMins[1] + (mScale[1]);
}
void scale_by_largest_axis(float& dist)
{
assert(mScale[0]!=0.0f && mScale[1]!=0.0f);
if (mScale[0]>mScale[1])
{
dist /= mScale[0];
}
else
{
dist /= mScale[1];
}
}
////////////////////////////////////////////////////////////////////////////////////
// Data
////////////////////////////////////////////////////////////////////////////////////
private:
array_vs<T, XSIZE_MAX*YSIZE_MAX> mData;
int mSize[2];
float mMins[2];
float mMaxs[2];
float mScale[2];
public:
////////////////////////////////////////////////////////////////////////////////////
// Raw Get - For The Iterator Dereference Function
////////////////////////////////////////////////////////////////////////////////////
T& rawGet(int Loc)
{
assert(Loc>=0 && Loc<XSIZE_MAX*YSIZE_MAX);
return mData[Loc];
}
////////////////////////////////////////////////////////////////////////////////////
// Iterator
////////////////////////////////////////////////////////////////////////////////////
class iterator
{
public:
// Constructors
//--------------
iterator() {}
iterator(grid2_vs* p, int t) : mOwner(p), mLoc(t) {}
// Assignment Operator
//---------------------
void operator= (const iterator &t) {mOwner=t.mOwner; mLoc=t.mLoc;}
// Equality & Inequality Operators
//---------------------------------
bool operator!=(const iterator &t) {return (mLoc!=t.mLoc);}
bool operator==(const iterator &t) {return (mLoc==t.mLoc);}
// Dereference Operator
//----------------------
T& operator* () {return (mOwner->rawGet(mLoc));}
// Inc Operator
//--------------
void operator++(int) {mLoc++;}
// Row & Col Offsets
//-------------------
void offsetRows(int num) {mLoc += (YSIZE_MAX*num);}
void offsetCols(int num) {mLoc += (num);}
// Return True If On Frist Column Of A Row
//-----------------------------------------
bool onColZero()
{
return (mLoc%XSIZE_MAX)==0;
}
// Evaluate The XY Position Of This Iterator
//-------------------------------------------
void position(int& X, int& Y)
{
Y = mLoc / XSIZE_MAX;
X = mLoc - (Y*XSIZE_MAX);
}
private:
int mLoc;
grid2_vs* mOwner;
};
////////////////////////////////////////////////////////////////////////////////////
// Iterator Begin
////////////////////////////////////////////////////////////////////////////////////
iterator begin(int x=0, int y=0)
{
assert(x>=0 && y>=0 && x<mSize[0] && y<mSize[1]);
return iterator(this, (x + y*XSIZE_MAX));
}
////////////////////////////////////////////////////////////////////////////////////
// Iterator Begin (scaled position, use mins and maxs to calc real position)
////////////////////////////////////////////////////////////////////////////////////
iterator begin(float xReal, float yReal)
{
assert(mScale[0]!=0.0f && mScale[1]!=0.0f);
truncate_position_to_bounds(xReal, yReal);
int x = (int)( (xReal-mMins[0]) / mScale[0] );
int y = (int)( (yReal-mMins[1]) / mScale[1] );
return begin(x,y);
}
////////////////////////////////////////////////////////////////////////////////////
// Iterator End
////////////////////////////////////////////////////////////////////////////////////
iterator end()
{
return iterator(this, (XSIZE_MAX*YSIZE_MAX));
}
////////////////////////////////////////////////////////////////////////////////////
// Ranged Iterator
////////////////////////////////////////////////////////////////////////////////////
class riterator
{
public:
// Constructors
//--------------
riterator()
{}
riterator(grid2_vs* p, int Range, int SX, int SY) :
mOwner(p)
{
int Start[2] = {SX, SY};
int Bounds[2] = {XSIZE_MAX-1, YSIZE_MAX-1};
for (int i=0; i<2; i++)
{
mMins[i] = Start[i] - Range;
mMaxs[i] = Start[i] + Range;
if (mMins[i]<0)
{
mMins[i] = 0;
}
if (mMaxs[i] > Bounds[i])
{
mMaxs[i] = Bounds[i];
}
mLoc[i] = mMins[i];
}
}
// Assignment Operator
//---------------------
void operator= (const riterator &t)
{
mOwner = t.mOwner;
for (int i=0; i<2; i++)
{
mMins[i] = t.mMins[i];
mMaxs[i] = t.mMaxs[i];
mLoc[i] = t.mLoc[i];
}
}
// Equality & Inequality Operators
//---------------------------------
bool operator!=(const riterator &t)
{
return (mLoc[0]!=t.mLoc[0] || mLoc[1]!=t.mLoc[1]);
}
bool operator==(const riterator &t)
{
return (mLoc[0]==t.mLoc[0] && mLoc[1]==t.mLoc[1]);
}
// Dereference Operator
//----------------------
T& operator* ()
{
return (mOwner->get(mLoc[0], mLoc[1]));
}
// Inc Operator
//--------------
void operator++(int)
{
if (mLoc[1] <= mMaxs[1])
{
mLoc[0]++;
if (mLoc[0]>(mMaxs[0]))
{
mLoc[0] = mMins[0];
mLoc[1]++;
}
}
}
bool at_end()
{
return (mLoc[1]>mMaxs[1]);
}
// Return True If On Frist Column Of A Row
//-----------------------------------------
bool onColZero()
{
return (mLoc[0]==mMins[0]);
}
// Evaluate The XY Position Of This Iterator
//-------------------------------------------
void position(int& X, int& Y)
{
Y = mLoc[1];
X = mLoc[0];
}
private:
int mMins[2];
int mMaxs[2];
int mLoc[2];
grid2_vs* mOwner;
};
////////////////////////////////////////////////////////////////////////////////////
// Ranged Iterator Begin (x and y are the center of the range)
////////////////////////////////////////////////////////////////////////////////////
riterator rangeBegin(int range, int x, int y)
{
assert(x>=0 && y>=0 && x<XSIZE_MAX && y<YSIZE_MAX);
return riterator(this, range, x, y);
}
////////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////////
riterator rangeBegin(int range, float xReal, float yReal)
{
float position[2] = {xReal, yReal};
assert(mScale[0]!=0.0f && mScale[1]!=0.0f);
truncate_position_to_bounds(xReal, yReal);
int x = ( (position[0]-mMins[0]) / mScale[0] );
int y = ( (position[1]-mMins[1]) / mScale[1] );
assert(x>=0 && y>=0 && x<XSIZE_MAX && y<YSIZE_MAX);
return riterator(this, range, x, y);
}
};
}
#endif