Subversion Repositories gelsvn

Rev

Details | Last modification | View Log | RSS feed

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