I have template class for spatial indexing which by default should work for any 2d object which implements function void boundingBox( Rect2d * box )
using std::vector<OBJECT*>
as container of objects inserted in particular grid tile.
template <class OBJECT, class TILE = std::vector<OBJECT*> >
class GridMap2D {
public:
double step, invStep;
int nx, ny, nxy;
TILE * tiles;
// ==== functions
inline int getIx( double x ){ return (int)( invStep * x ); };
inline int getIy( double y ){ return (int)( invStep * y ); };
inline double getX( int ix ){ return step * ix ; };
inline double getY( int iy ){ return step * iy ; };
inline int getIndex ( int ix, int iy ){ return nx*iy + ix; };
inline int getIndex ( double x, double y ){ return getIndex( getIx(x), getIy(y) ); };
inline TILE* getTile( double x, double y ){ return tiles + getIndex( x, y ); };
inline void insert( OBJECT* p, int i ){
tiles[ i ].push_back( p );
}
inline void insert( OBJECT* p, int ix, int iy ){ insert( p, getIndex( ix,iy ) ); };
// this is very general method to insert any object with bounding box
// but for many object it is not very efficient
// some objects suchb as Point2d does not even implement boundingBox()
inline void insert( OBJECT* p ){
Rect2d bbox;
p.boundingBox( &bbox );
int ix0 = getIx( bbox.x0 ); // TODO: bound check ?
int iy0 = getIy( bbox.y0 );
int ix1 = getIx( bbox.x1 );
int iy1 = getIy( bbox.y1 );
for( int iy=iy0; iy<=iy1; iy++ ){
for( int ix=ix0; ix<=ix1; ix++ ){
insert( p, ix, iy );
}
}
}
void init( int nx_, int ny_, double step_, int tile_n0 ){
step = step_;
invStep = 1/step;
nx = nx_; ny=ny_;
nxy = nx*ny;
tiles = new TILE[ nxy ];
for (int i=0; i<nxy; i++){
if ( tile_n0 != 0 ){
tiles[i].reserve( tile_n0 );
}
}
}
};
And its specialization for Segment2d
which does not implement boundingBox()
but has own insert
algorithm based on line rasterization:
template<> class GridMap2D< Segment2d, std::vector<Segment2d*> >{
public:
inline void insert( Segment2d* l ){
Vec2d* a = l->a;
Vec2d* b = l->b;
double ax = a->x;
double ay = a->y;
double bx = b->x;
double by = b->y;
double dx = fabs( bx - ax );
double dy = fabs( by - ay );
int dix = ( ax < bx ) ? 1 : -1;
int diy = ( ay < by ) ? 1 : -1;
int ix = getIx( ax );
int iy = getIy( ay );
int ixb = getIx( bx );
int iyb = getIy( by );
double x=0, y=0;
int i=0;
insert( l, ix, iy );
insert( l, ixb, iyb );
while ( ( ix != ixb ) && ( iy != iyb ) ) {
if ( x < y ) {
x += dy;
ix += dix;
} else {
y += dx;
iy += diy;
}
insert( l, ix, iy );
}
}
};
which will insert line into grid tiles trough which it goes ... like this:
but I have several problems with how templates work:
In the specialization for
Segment2d
I goterror: ‘getIx’ was not declared in this scope
. Does it mean that the specialized template does not know functions defined in base template ? Or I probably do the specialization wrongly. I really do not want to rewrite the code several times, then the template approach would be pointless.I'm not sure what happen when I instantiate or specialize the template by some parameter which does not implement some methods which the base template use. e.g.
- consider I use different container type argument as
TILE
which does not implement.push_back()
- my
Segment2d
does not implementboundingBox()
can does the specialization solve this problem ?
- consider I use different container type argument as
background:
I have two goals:
I want to create very fast spatial indexing for acceleration of ray-casting and collisions for any 2d shape.
- Because it should be as fast as possible I want o use templates (resolved in compile-time ) rather than some class inherience hierarchy with
virtual
methods.
- Because it should be as fast as possible I want o use templates (resolved in compile-time ) rather than some class inherience hierarchy with
I want to learn how to use templates effectively
This question is related to this " Generic Quadtree ", where is recommendation to use templates for similar task. Tried to implement that ... but I perhaps my understanding of templates is not good enough.
NOTE: my GridMap2d is not a QuadTree, but I still added QuadTree as an keyword, because the question is relavant to it. QuadTree is very common spatial indexing data-structure, and implementing it using templates would have the same issue.