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 Cell.h
9
 * @brief Cell class for a voxel grid in a 2 level grid.
10
 */
11
 
12
#ifndef __GEOMETRY_CELL_H
13
#define __GEOMETRY_CELL_H
14
 
15
#include <vector>
16
#include "../CGLA/Vec3i.h"
17
#include "../CGLA/BitMask.h"
18
#include "RGrid.h"
19
 
20
namespace Geometry 
21
{
22
	/** \brief Class template for a cell in a hierarchical grid.
23
 
24
			The template arguments are the type and the cell dimension.
25
			A Cell is much like an RGrid - except that a Cell may 
26
			be coalesced into a single value and then split again
27
			when a new value is inserted. Also cells are constrained to
28
			be of size NxNxN where N=2^m for some m. This makes some things
29
			faster.
30
 
31
			The reason for making CELL_DIM a template argument rather 
32
			than a constructor argument is that we generally have many 
33
			cells	and do not wish that each cell contains its dimension. 
34
	*/
35
	template<class T, int CELL_DIM, class ChildT>
36
	class Cell
37
	{
38
	public:
39
		typedef T DataType;
40
 
41
	private:
42
		bool touched;
43
 
44
		/// Linear array containing data of this Cell.
45
		std::vector<T> data;
46
 
47
		/** Return a bit mask used to mask indices. 
48
				Some functions in this class are passed a Vec3i 
49
				whose lower bits index into the cell. The mask is
50
				used to select these lower bits before the 3D
51
				index is converted to	a linear index.
52
 
53
				If you are wondering about why the static variable 
54
				inside the function is not simply a static member of 
55
				the class, check out item 47 og "Effective C++" by 
56
				Scott Meyers.
57
		*/
58
		static const CGLA::BitMask& get_bit_mask()
59
		{
60
			static const CGLA::BitMask bit_mask(CELL_DIM);
61
			return bit_mask;
62
		}
63
 
64
	public:
65
 
66
		/** Get dimensions of Cell. Returns only one value since 
67
				x, y, and z dimensions are the same. */
68
		static int get_dim() 
69
		{
70
			return CELL_DIM;
71
		}
72
 
73
	private:
74
 
75
		/** Get index. Computes an index into the linear array representation
76
				of the voxels in the cell from a 3D grid index. The top bits (which
77
				have been used to find this Cell) are masked out. */
78
 		int get_idx(const CGLA::Vec3i& idx) const
79
		{
80
			CGLA::Vec3i bot_idx = get_bit_mask().mask(idx);
81
 			return (bot_idx[2]*get_dim()+bot_idx[1])*get_dim()+bot_idx[0];
82
		}
83
 
84
	protected:
85
 
86
		/** Store a value in the Cell. If the Cell is 
87
				coalesced, it is first resized to contain CELL_DIMS 
88
				cubed voxels, and then the voxel is inserted. */
89
 		void store_priv(const CGLA::Vec3i& p, const T& new_val) 
90
		{
91
			if(is_coalesced()) split();
92
			touched = true;
93
			data[get_idx(p)] = new_val;
94
		}
95
 
96
 
97
	public:
98
 
99
		/** Create empty grid cell. A Cell contains initially a single value.
100
				Reading (using operator[]) any voxel will yield this value. */
101
		Cell(const T& val): data(1,val), touched(false)
102
		{
103
			assert(CELL_DIM==get_dim());
104
		}
105
 
106
		/** Clear cell. Removes Cell contents replacing it with a single
107
				specified value. */
108
 		void coalesce(const T& val) 
109
		{
110
			data=std::vector<T>(1,val);
111
			touched = true;
112
		}
113
 
114
		/// Split cell - causes memory to be reserved for CELL_DIM^3 voxels.
115
		void split()
116
		{
117
			T val = data[0];
118
			data.resize(CGLA::qbe(CELL_DIM), val);
119
			touched = true;
120
		}
121
 
122
		/// Check if the cell is coalesced
123
		bool is_coalesced() const 
124
		{
125
			// We rely on size() being constant time below.
126
			// Probably this function should be changed.... it would be bad
127
			// if it was slow ... very bad....
128
			return data.size()==1;
129
		}
130
 
131
 
132
		/** Read access to voxel grid. This function is passed
133
				a Vec3i and returns the corresponding voxel. If the
134
				cell is coalesced, the single value stored is returned. */
135
		const T& operator[](const CGLA::Vec3i& p) const 
136
		{
137
			if(is_coalesced()) return data[0];
138
			return *(&data[get_idx(p)]);
139
		}
140
 
141
 		void store(const CGLA::Vec3i& p, const T& new_val) 
142
		{
143
			return static_cast<ChildT&>(*this).store(p,new_val);
144
		}
145
 
146
 
147
		/** Const get a pointer to the first element in the linear
148
				array representation of the grid. */
149
 		const T* get() const {return &data[0];}
150
 
151
		/** Non-const get a pointer to the first element in the linear
152
				array representation of the grid. */
153
		T* get() 
154
		{
155
			touched = true;
156
			return &data[0];
157
		}
158
 
159
		void untouch() {touched=false;}
160
		void touch() {touched=true;}
161
		bool is_touched() const {return touched;}
162
 
163
	};
164
 
165
 
166
	template<class T, int CELL_DIM>
167
	class DefaultCell: public Cell<T,CELL_DIM,DefaultCell<T, CELL_DIM> >
168
	{
169
	public:
170
		DefaultCell(const T& val): Cell<T,CELL_DIM,DefaultCell>(val){}
171
 		void store(const CGLA::Vec3i& p, const T& new_val) 
172
		{
173
			store_priv(p, new_val);
174
		}
175
 
176
	};
177
 
178
 
179
}
180
#endif