Subversion Repositories gelsvn

Rev

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