Subversion Repositories gelsvn

Rev

Rev 595 | 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
 
443 jab 7
#ifndef __GEOMETRY_GRIDALGORITHM_H
8
#define __GEOMETRY_GRIDALGORITHM_H
61 jab 9
 
595 jab 10
/**
11
 * @file GridAlgorithm.h
12
 * A number of algorithms for traversing a voxel grid. The algorithms are 
13
 * generally transformative and allow us to invoke a function on each.
14
 */
15
 
61 jab 16
/*
17
Functions:
18
 
19
  void for_each_voxel(Grid& g, F& f);
20
  void for_each_voxel(Grid& g,	const Vec3i& p0,	const Vec3i& p7, F& f);
21
  void for_each_voxel_ordered(Grid& g, const Vec3i& p0, const Vec3i& p7, F& f);
22
  void for_each_voxel_ordered(Grid& g,	F&);
23
  void for_each_voxel_const(const Grid& g, 
24
														const Vec3i& p0, const Vec3i& p7, F& f);
25
  void for_each_voxel_const(const Grid& g,	F& f);
26
  void for_each_voxel_ordered_const(Grid& g, 
27
																		const Vec3i& p0, const Vec3i& p7, 
28
																		F& f);
29
  void for_each_voxel_ordered_const(Grid& g, F& f);
30
 
31
Purpose:  
32
----------
33
 
34
Visit all voxels (or voxels in a region og interest) in grid. A function 
35
is invoked on each voxel. 
36
 
37
The "ordered" functions traverse the grid in a systematic way: A
38
slice at a time and for each slice one row at a time. The other
39
functions make no guarantees about how the volume (roi) is traversed. 
40
 
41
Types: 
42
----------
43
 
44
Grid - a grid type, either HGrid<T,CellT> or RGrid<T>
45
 
46
F - functor type a funtion or class with the function call operator 
47
overloaded. The functor should look either like this
48
 
49
void fun(const Vec3i&, T& x)
50
 
51
or this
52
 
53
void fun(const Vec3i&, const T& x)
54
 
55
in the case of the const functions.
56
 
57
Arguments:
58
----------
59
 
60
g  - The voxel grid, we wish to traverse.
61
p0 - (xmin, ymin, zmin) coordinates of the window we wish to
62
     traverse.
63
p7 - (xmax, ymax, zmax) coordinates of the window we wish to
64
     traverse.
65
f  - functor.
66
 
67
*/
68
 
69
#include <iostream>
70
#include "RGrid.h"
71
#include "HGrid.h"
72
 
73
namespace Geometry 
74
{
75
	template<class T, class F>
76
	void _for_each_voxel(T* data, 
77
											 int x_dim, int xy_dim,
78
											 const CGLA::Vec3i& p0, 
79
											 const CGLA::Vec3i& p7,
80
											 F& functor,
81
											 const CGLA::Vec3i& offset = CGLA::Vec3i(0))
82
	{
83
		const int Amin = p0[2]*xy_dim;
84
		const int Amax = p7[2]*xy_dim;
85
		int Bmin = Amin +p0[1]*x_dim;
86
		int Bmax = Amin +p7[1]*x_dim; 
87
		CGLA::Vec3i p0o = p0+offset;
88
		CGLA::Vec3i p(p0o);
89
		for(int A=Amin; A<Amax; A+=xy_dim, ++p[2])
90
			{
91
				p[1] = p0o[1];
92
				for(int B = Bmin; B<Bmax; B+=x_dim, ++p[1])
93
					{
94
						p[0] = p0o[0];
95
						int Cmin = B+p0[0];
96
						int Cmax = B+p7[0];
97
						for(int C=Cmin; C<Cmax; ++C, ++p[0])
98
							functor(p, data[C]);
99
					}
100
				Bmin += xy_dim;
101
				Bmax += xy_dim;
102
			}
103
	}
104
 
105
	template<class T, class F>
106
	void _for_each_voxel(T* data, 
107
											 const CGLA::Vec3i& dims,
108
											 F& functor,
109
											 const CGLA::Vec3i& offset = CGLA::Vec3i(0))
110
	{
111
		int l=0;
112
		CGLA::Vec3i p(offset);
113
		CGLA::Vec3i p7(offset);
114
		p7 += dims;
115
 
116
		for(;                   p[2]<p7[2]; ++p[2])
117
			for(p[1]=offset[1];   p[1]<p7[1]; ++p[1])
118
				for(p[0]=offset[0]; p[0]<p7[0]; ++p[0])
119
					functor(p, data[l++]);
120
	}
121
 
122
 
123
	/** Loop over all voxels in a sub-region (slice) of an
124
			RGrid and invoke a functor on each voxel. 
125
			The grid is the first argument, the slice is
126
			specified by the two subsequent args, and the functor 
127
			is the last argument. */
128
	template<class T, class F>
129
	void for_each_voxel(RGrid<T>& grid,
130
											const CGLA::Vec3i& p0, 
131
											const CGLA::Vec3i& p7,
132
											F& functor)
133
	{
134
		_for_each_voxel(grid.get(), grid.get_x_dim(), grid.get_xy_dim(),
135
										CGLA::v_max(p0, CGLA::Vec3i(0)),
136
										CGLA::v_min(p7, grid.get_dims()), 
137
										functor);
138
	}
139
 
140
	/** Loop over all voxels in an entire	RGrid. 
141
			Grid is the first argument, and a functor is 
142
			the second.	For each voxel, an operation 
143
			specified by the functor is performed. */
144
	template<class T, class F>
145
	void for_each_voxel(RGrid<T>& grid,	F& functor)
146
	{
147
		_for_each_voxel(grid.get(), grid.get_dims(), functor);
148
	}
149
 
150
 
151
	/** For each voxel (ordered). The idea of ordered traversal is 
152
			that we traverse the volume in a systematic fashion as opposed
153
			to traversing simply according to the memory layout of the volume
154
			data structure. This is important e.g. if we want to save the 
155
			volume in raw format. 
156
			For an RGrid, there is no difference though.
157
	*/ 
158
	template<class T, class F>
159
	void for_each_voxel_ordered(RGrid<T>& grid,
160
															const CGLA::Vec3i& p0, 
161
															const CGLA::Vec3i& p7,
162
															F& functor)
163
	{
164
		_for_each_voxel(grid.get(), grid.get_x_dim(), grid.get_xy_dim(),
165
										CGLA::v_max(p0, CGLA::Vec3i(0)),
166
										CGLA::v_min(p7, grid.get_dims()), 
167
										functor);
168
	}
169
 
170
	template<class T, class F>
171
	void for_each_voxel_ordered(RGrid<T>& grid,	F& functor)
172
	{
173
		_for_each_voxel(grid.get(), grid.get_dims(), functor);
174
	}
175
 
176
 
177
	template<class T, class CellT, class F>
178
	void for_each_cell(HGrid<T,CellT>& grid,
179
										 const CGLA::Vec3i& p0, 
180
										 const CGLA::Vec3i& p7,
181
										 F& functor)
182
	{
183
		CGLA::Vec3i p0t = p0/grid.get_bottom_dim();
184
		CGLA::Vec3i p7t = CGLA::v_min(p7/grid.get_bottom_dim()+
185
																	CGLA::Vec3i(1),
186
																	grid.get_top_dims());
187
		for(CGLA::Vec3i pt(p0t); pt[2]<p7t[2]; ++pt[2])
188
			for(pt[1]=p0t[1];      pt[1]<p7t[1]; ++pt[1])
189
				for(pt[0]=p0t[0];    pt[0]<p7t[0]; ++pt[0])
190
					functor(pt*CellT::get_dim(), grid.get_cell(pt));
191
	}
192
 
193
	template<class T, class CellT, class F>
194
	void for_each_cell(HGrid<T,CellT>& grid,
195
										 F& functor)
196
	{
197
		CGLA::Vec3i p0t;
198
		CGLA::Vec3i p7t =	grid.get_dims();
199
		const int inc = CellT::get_dim();
200
		int l=0;
201
		for(CGLA::Vec3i pt(p0t); pt[2]<p7t[2]; pt[2]+=inc)
202
			for(pt[1]=p0t[1];      pt[1]<p7t[1]; pt[1]+=inc)
203
				for(pt[0]=p0t[0];    pt[0]<p7t[0]; pt[0]+=inc)
204
					functor(pt, grid.get_cell(l++));
205
	}
206
 
207
 
208
	template<class CellT, class F>
209
	class _HGridCellFunctor
210
	{
211
		const CGLA::Vec3i p0;
212
		const CGLA::Vec3i p7;
213
		F& functor;
214
 
215
	public:
216
		_HGridCellFunctor(const CGLA::Vec3i _p0,
217
											const CGLA::Vec3i _p7,
218
											F& _functor): p0(_p0), p7(_p7), functor(_functor) {}
219
 
220
		void operator()(const CGLA::Vec3i& offset, 
221
										CellT& cell)
222
		{
223
			CGLA::Vec3i p0c = CGLA::v_max(p0-offset, CGLA::Vec3i(0));
224
			CGLA::Vec3i p7c = CGLA::v_min(p7-offset, CGLA::Vec3i(CellT::get_dim()));
225
 
226
			if(cell.is_coalesced())
227
				cell.split();
228
 
229
			_for_each_voxel(cell.get(), 
230
											CellT::get_dim(), 
231
											CGLA::sqr(CellT::get_dim()),
232
											p0c, p7c,	functor, offset);
233
		}
234
	};
235
 
236
 
237
	template<class T, class CellT, class F>
238
	void for_each_voxel(HGrid<T,CellT>& grid,
239
											const CGLA::Vec3i& _p0, 
240
											const CGLA::Vec3i& _p7,
241
											F& functor)
242
	{
243
		CGLA::Vec3i p0 = CGLA::v_max(_p0, CGLA::Vec3i(0));
244
		CGLA::Vec3i p7 = CGLA::v_min(_p7, grid.get_dims());
245
		_HGridCellFunctor<CellT,F> cell_functor(p0, p7, functor);
246
		for_each_cell(grid, p0, p7, cell_functor);
247
	}
248
 
249
	template<class T, class CellT, class F>
250
	void for_each_voxel(HGrid<T,CellT>& grid,	F& functor)
251
	{
252
		_HGridCellFunctor<CellT,F> cell_functor(CGLA::Vec3i(0), 
253
																						grid.get_dims(), functor);
254
		for_each_cell(grid, cell_functor);
255
	}
256
 
257
	template<class T, class CellT, class F>
258
	void for_each_voxel_ordered(HGrid<T,CellT>& grid,
259
															const CGLA::Vec3i& _p0, 
260
															const CGLA::Vec3i& _p7,
261
															F& functor)
262
	{
263
		CGLA::Vec3i p0 = CGLA::v_max(_p0, CGLA::Vec3i(0));
264
		CGLA::Vec3i p7 = CGLA::v_min(_p7, grid.get_dims());
265
		for(int k=p0[2];k<p7[2];++k)
266
			for(int j=p0[1];j<p7[1];++j)
267
				for(int i=p0[0];i<p7[0];++i)
268
					{
269
						CGLA::Vec3i p(i,j,k);
270
						float val = grid[p];
271
						float nval = val;
272
						functor(p, nval);
273
						if(nval != val)
274
							grid.store(p, nval);
275
					}
276
	}
277
 
278
	template<class T, class CellT, class F>
279
	void for_each_voxel_ordered(HGrid<T,CellT>& grid,	F& functor)
280
	{
281
		for_each_voxel_ordered(grid, CGLA::Vec3i(0), grid.get_dims(), functor);
282
	}
283
 
284
 
285
	template<typename T>
286
	class _AssignFun
287
	{
288
		T val;
289
	public:
290
		_AssignFun(const T& _val): val(_val) {}
291
		void operator()(const CGLA::Vec3i& pi, T& vox_val)
292
		{
293
			vox_val = val;
294
		}
295
	};
296
 
297
 	template<class G>
298
	void clear_region(G& grid, const typename G::DataType& value)
299
	{
300
		_AssignFun<typename G::DataType> afun(value);
301
		for_each_voxel(grid, afun);
302
	}
303
 
304
	template<class G>
305
	void clear_region(G& grid, 
306
										const CGLA::Vec3i& p0,
307
										const CGLA::Vec3i& p7,
308
										const typename G::DataType& value)
309
	{
310
		_AssignFun<typename G::DataType>afun(value) ;
311
		for_each_voxel(grid, p0, p7, afun);
312
	}
313
 
314
 
315
	//----------------------------------------------------------------------
316
	// const versions.
317
 
318
	/** Loop over all voxels in a sub-region (slice) of an
319
			RGrid and invoke a functor on each voxel. 
320
			The grid is the first argument, the slice is
321
			specified by the two subsequent args, and the functor 
322
			is the last argument. */
323
	template<class T, class F>
324
	void for_each_voxel_const(const RGrid<T>& grid,
325
														const CGLA::Vec3i& p0, 
326
														const CGLA::Vec3i& p7,
327
														F& functor)
328
	{
329
		_for_each_voxel(grid.get(), grid.get_x_dim(), grid.get_xy_dim(),
330
										CGLA::v_max(p0, CGLA::Vec3i(0)),
331
										CGLA::v_min(p7, grid.get_dims()), 
332
										functor);
333
	}
334
 
335
	/** Loop over all voxels in an entire	RGrid. 
336
			Grid is the first argument, and a functor is 
337
			the second.	For each voxel, an operation 
338
			specified by the functor is performed. */
339
	template<class T, class F>
340
	void for_each_voxel_const(const RGrid<T>& grid,	F& functor)
341
	{
342
		_for_each_voxel(grid.get(), grid.get_dims(), functor);
343
	}
344
 
345
 
346
	/** For each voxel (ordered). The idea of ordered traversal is 
347
			that we traverse the volume in a systematic fashion as opposed
348
			to traversing simply according to the memory layout of the volume
349
			data structure. This is important e.g. if we want to save the 
350
			volume in raw format. 
351
			For an RGrid, there is no difference though.
352
	*/ 
353
	template<class T, class F>
354
	void for_each_voxel_ordered_const(const RGrid<T>& grid,
355
																		const CGLA::Vec3i& p0, 
356
																		const CGLA::Vec3i& p7,
357
																		F& functor)
358
	{
359
		_for_each_voxel(grid.get(), grid.get_x_dim(), grid.get_xy_dim(),
360
										CGLA::v_max(p0, CGLA::Vec3i(0)),
361
										CGLA::v_min(p7, grid.get_dims()), 
362
										functor);
363
	}
364
 
365
	template<class T, class F>
366
	void for_each_voxel_ordered_const(const RGrid<T>& grid,	F& functor)
367
	{
368
		_for_each_voxel(grid.get(), grid.get_dims(), functor);
369
	}
370
 
371
 
372
	template<class T, class CellT, class F>
373
	void for_each_cell_const(const HGrid<T,CellT>& grid,
374
													 const CGLA::Vec3i& p0, 
375
													 const CGLA::Vec3i& p7,
376
													 F& functor)
377
	{
378
		CGLA::Vec3i p0t = p0/grid.get_bottom_dim();
379
		CGLA::Vec3i p7t = CGLA::v_min(p7/grid.get_bottom_dim()+
380
																	CGLA::Vec3i(1),
381
																	grid.get_top_dims());
382
		for(CGLA::Vec3i pt(p0t); pt[2]<p7t[2]; ++pt[2])
383
			for(pt[1]=p0t[1];      pt[1]<p7t[1]; ++pt[1])
384
				for(pt[0]=p0t[0];    pt[0]<p7t[0]; ++pt[0])
385
					functor(pt*CellT::get_dim(), grid.get_cell(pt));
386
	}
387
 
388
	template<class T, class CellT, class F>
389
	void for_each_cell_const(const HGrid<T,CellT>& grid,
390
													 F& functor)
391
	{
392
		CGLA::Vec3i p0t;
393
		CGLA::Vec3i p7t =	grid.get_dims();
394
		const int inc = CellT::get_dim();
395
		int l=0;
396
		for(CGLA::Vec3i pt(p0t); pt[2]<p7t[2]; pt[2]+=inc)
397
			for(pt[1]=p0t[1];      pt[1]<p7t[1]; pt[1]+=inc)
398
				for(pt[0]=p0t[0];    pt[0]<p7t[0]; pt[0]+=inc)
399
					functor(pt, grid.get_cell(l++));
400
	}
401
 
402
 
403
	template<class CellT, class F>
404
	class _HGridCellFunctorConst
405
	{
406
		const CGLA::Vec3i p0;
407
		const CGLA::Vec3i p7;
408
		F& functor;
409
 
410
	public:
411
		_HGridCellFunctorConst(const CGLA::Vec3i _p0,
412
													 const CGLA::Vec3i _p7,
413
													 F& _functor): p0(_p0), p7(_p7), functor(_functor) {}
414
 
415
		void operator()(const CGLA::Vec3i& offset, 
416
										const CellT& cell)
417
		{
418
			CGLA::Vec3i p0c = CGLA::v_max(p0-offset, CGLA::Vec3i(0));
419
			CGLA::Vec3i p7c = CGLA::v_min(p7-offset, CGLA::Vec3i(CellT::get_dim()));
420
 
421
			if(cell.is_coalesced())
422
				{
423
					typename CellT::DataType val = *cell.get();
424
					for(CGLA::Vec3i p(p0c); p[2]<p7c[2]; ++p[2])
425
						for(p[1]=p0c[1];      p[1]<p7c[1]; ++p[1])
426
							for(p[0]=p0c[0];    p[0]<p7c[0]; ++p[0])
427
								functor(p+offset, val);
428
				}
429
			_for_each_voxel(cell.get(), 
430
											CellT::get_dim(), 
431
											CGLA::sqr(CellT::get_dim()),
432
											p0c, p7c,	functor, offset);
433
		}
434
	};
435
 
436
 
437
	template<class T, class CellT, class F>
438
	void for_each_voxel_const(const HGrid<T,CellT>& grid,
439
														const CGLA::Vec3i& _p0, 
440
														const CGLA::Vec3i& _p7,
441
														F& functor)
442
	{
443
		CGLA::Vec3i p0 = CGLA::v_max(_p0, CGLA::Vec3i(0));
444
		CGLA::Vec3i p7 = CGLA::v_min(_p7, grid.get_dims());
445
		_HGridCellFunctorConst<CellT,F> cell_functor(p0, p7, functor);
446
		for_each_cell_const(grid, p0, p7, cell_functor);
447
	}
448
 
449
	template<class T, class CellT, class F>
450
	void for_each_voxel_const(const HGrid<T,CellT>& grid,	F& functor)
451
	{
452
		_HGridCellFunctorConst<CellT,F> cell_functor(CGLA::Vec3i(0), 
453
																								 grid.get_dims(), functor);
454
		for_each_cell_const(grid, cell_functor);
455
	}
456
 
457
	template<class T, class CellT, class F>
458
	void for_each_voxel_ordered_const(const HGrid<T,CellT>& grid,
459
																		const CGLA::Vec3i& _p0, 
460
																		const CGLA::Vec3i& _p7,
461
																		F& functor)
462
	{
463
		CGLA::Vec3i p0 = CGLA::v_max(_p0, CGLA::Vec3i(0));
464
		CGLA::Vec3i p7 = CGLA::v_min(_p7, grid.get_dims());
465
		for(int k=p0[2];k<p7[2];++k)
466
			for(int j=p0[1];j<p7[1];++j)
467
				for(int i=p0[0];i<p7[0];++i)
468
					{
469
						CGLA::Vec3i p(i,j,k);
470
						functor(p, grid[p]);
471
					}
472
	}
473
 
474
	template<class T, class CellT, class F>
475
	void for_each_voxel_ordered_const(const HGrid<T,CellT>& grid,	F& functor)
476
	{
477
		for_each_voxel_ordered_const(grid, 
478
																 CGLA::Vec3i(0), 
479
																 grid.get_dims(), 
480
																 functor);
481
	}
482
 
483
 
484
}
485
 
486
#endif