Subversion Repositories gelsvn

Rev

Rev 601 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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