Subversion Repositories gelsvn

Rev

Rev 443 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
595 jab 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
 
443 jab 12
#ifndef __GEOMETRY_ANCESTORGRID_H
13
#define __GEOMETRY_ANCESTORGRID_H
61 jab 14
 
15
#include "CGLA/Vec3i.h"
16
 
17
namespace Geometry 
18
{
19
 
89 jab 20
	/** \brief Class template is used as abstract ancestor of 
21
			voxel grids. 
22
 
23
			Strictly speaking, this class is not 
61 jab 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.
89 jab 63
 
61 jab 64
				This function returns a Vec3i with the dimensions
65
				of the grid. */
66
 		const CGLA::Vec3i& get_dims() const {return dims;}
67
 
89 jab 68
		/// Get the corner having smallest coordinates.
61 jab 69
 		const CGLA::Vec3i get_lo_corner() const {return CGLA::Vec3i(0);}
70
 
89 jab 71
		/// Get the corner having greatest coordinates. 
61 jab 72
 		const CGLA::Vec3i& get_hi_corner() const {return dims;}
73
 
74
		/** Access (read only) a voxel in a grid. 
89 jab 75
 
61 jab 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. 
89 jab 90
 
61 jab 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