Subversion Repositories gelsvn

Rev

Rev 89 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
61 jab 1
#ifndef __ANCESTORGRID_H
2
#define __ANCESTORGRID_H
3
 
4
#include "CGLA/Vec3i.h"
5
 
6
namespace Geometry 
7
{
8
 
9
	/** This class template is used as abstract ancestor of 
10
			voxel grids. Strictly speaking, this class is not 
11
			abstract, since it does not have any virtual functions.
12
			However, operator[]() and store() simply call 
13
			functions in derived classes. To do so, you must pass
14
			the derived class as a template argument to this class
15
			when you define the derived class. This is called the
16
			Barton and Nackman trick. See Todd Veldhuizen, 
17
			"Techniques for Scientific C++" 1.3.3.
18
	*/
19
 
20
 	template<typename T, class ChildT>
21
	class AncestorGrid
22
	{
23
	public:
24
		typedef T DataType;
25
 
26
	private:
27
		/// xyz dimensions of grid.
28
		CGLA::Vec3i dims;
29
 
30
	public:
31
 
32
		/// Construct a grid of specified xyz dimensions.
33
		AncestorGrid(int _x_dim, int _y_dim, int _z_dim): 
34
			dims(_x_dim,_y_dim,_z_dim) {}
35
 
36
		/// Construct a grid of specified xyz dimensions.
37
		AncestorGrid(const CGLA::Vec3i& _dims): dims(_dims) {}
38
 
39
		/** Check if voxel is within grid bounds.
40
				This function is passed a Vec3i, p, and returns true
41
				if p is within the voxel grid. */
42
 		bool in_domain(const CGLA::Vec3i& p) const
43
		{
44
			for(int i=0; i<3; i++)
45
				if (p[i]<0 || p[i] >= dims[i])
46
					return false;
47
			return true;
48
		}
49
 
50
		/** Get dimensions of grid.
51
				This function returns a Vec3i with the dimensions
52
				of the grid. */
53
 		const CGLA::Vec3i& get_dims() const {return dims;}
54
 
55
		/** Get the corner having smallest coordinates */
56
 		const CGLA::Vec3i get_lo_corner() const {return CGLA::Vec3i(0);}
57
 
58
		/** Get the corner having greatest coordinates. */
59
 		const CGLA::Vec3i& get_hi_corner() const {return dims;}
60
 
61
		/** Access (read only) a voxel in a grid. 
62
				This is the operator[] which is passed a Vec3i 
63
				and returns a const reference to a voxel.
64
				This function is "statically virtual", i.e.
65
				it simply calls the store function of a derived 
66
				class.
67
				See below why there is no non-const operator[] 
68
		*/
69
		const T& operator[](const CGLA::Vec3i& p) const 
70
		{
71
			return static_cast<const ChildT&>(*this)[p];
72
		}
73
 
74
 
75
		/** Store a voxel in grid. 
76
				This function returns nothing but is passed a 
77
				Vec3i p and T value t and stores t at p in the 
78
				grid. This function is "statically virtual", i.e.
79
				it simply calls the store function of a derived 
80
				class. 
81
 
82
				Yes, it would be simpler to provide a non-const
83
				operator[], however, a non-const operator[] will
84
				often be called even when no writing takes place.
85
				(Scott Meyers, "More Effective C++, p. 218)
86
				If a grid implementation allocates memory when 
87
				a voxel is accessed for writing, then it is a problem
88
				that we cannot be sure a non-const operator[] is 
89
				called only if we are writing. We might then allocate
90
				memory even if we just want to read. 
91
		*/
92
 		void store(const CGLA::Vec3i& p, const T& t)
93
		{
94
			return static_cast<ChildT&>(*this).store(p,t);
95
		}
96
 
97
 		void clear()
98
		{
99
			return static_cast<ChildT&>(*this).clear();
100
		}
101
	};
102
}
103
 
104
#endif