GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: tmp_project/PhoenixGraph/src/Tree/PNTreeLightNode_impl.h Lines: 134 139 96.4 %
Date: 2023-10-11 10:52:07 Branches: 59 81 72.8 %

Line Branch Exec Source
1
/***************************************
2
	Auteur : Pierre Aubert
3
	Mail : pierre.aubert@lapp.in2p3.fr
4
	Licence : CeCILL-C
5
****************************************/
6
7
#ifndef __PNTREE_LIGHT_NODE_H_IMPL__
8
#define __PNTREE_LIGHT_NODE_H_IMPL__
9
10
#include <string.h>
11
#include <math.h>
12
13
#include "pstatic_computation.h"
14
15
#include "PNTreeLightNode.h"
16
17
///Default constructor of PNTreeLightNode
18
template<typename T, typename U, unsigned char N>
19
1340
PNTreeLightNode<T, U, N>::PNTreeLightNode(){
20
1340
	initialisationPNTreeLightNode();
21
1340
}
22
23
///Copy constructor of PNTreeLightNode
24
/**	@param other : class to copy
25
*/
26
template<typename T, typename U, unsigned char N>
27
PNTreeLightNode<T, U, N>::PNTreeLightNode(const PNTreeLightNode<T, U, N> & other){
28
	copyPNTreeLightNode(other);
29
}
30
31
///Destructeur of PNTreeLightNode
32
template<typename T, typename U, unsigned char N>
33
1340
PNTreeLightNode<T, U, N>::~PNTreeLightNode(){
34
1340
	clear();
35
}
36
37
///Get the size of the child
38
/**	@param[out] childSize : child size
39
 * 	@param parentSize : parent size
40
*/
41
template<typename T, unsigned char N>
42
3656
void makeHalfSize(T childSize[N], const T parentSize[N]){
43
14192
	for(unsigned char i(0lu); i < N; ++i){
44
10536
		childSize[i] = parentSize[i]/2.f;
45
	}
46
3656
}
47
48
///Check the size of the childs of a N Tree
49
/**	@param halfSizeChild : table of half size of the current N Tree
50
 * 	@param sizeLimit : limit of the cell size
51
 * 	@return true if everything is OK, false if the childs are too small
52
*/
53
template<typename T, unsigned char N>
54
4984
bool checkSizeLimitLight(const T halfSizeChild[N], T sizeLimit){
55
19340
	for(unsigned char i(0); i < N; ++i){
56
14356
		if(halfSizeChild[i] < sizeLimit) return false;
57
	}
58
4984
	return true;
59
}
60
61
///Add an element in the PNTreeLightNode
62
/**	@param posData : position of the data
63
 * 	@param data : pointer to the data we want to sort
64
 * 	@param pos : position of the current node
65
 * 	@param size : size of the current node
66
 * 	@param sizeLimit : limit of the cell size
67
 * 	@return true on success, false otherwise
68
*/
69
template<typename T, typename U, unsigned char N>
70
4796
bool PNTreeLightNode<T, U, N>::addElement(T * posData, U * data, const T pos[N], const T size[N], T sizeLimit){
71
4796
	if(!checkSizeLimitLight<T, N>(size, sizeLimit)){
72
		return false;
73
	}
74
4796
	if(p_tableChildren == NULL){
75
1528
		if(p_data == NULL){			//The cell is empty
76
1340
			p_data = data;
77
1340
			p_posData = posData;
78
1340
			return true;
79
		}else{					//There is a data in the cell
80
188
			if(!split(pos, size, sizeLimit)) return false;
81
188
			return addElement(posData, data, pos, size, sizeLimit);
82
		}
83
	}else{						//There are children
84
		T childPos[N];
85
3268
		PNTreeLightNode<T, U, N> * child = getChildFromPos(childPos, posData, pos, size);
86
3268
		if(child == NULL){
87
			return false;
88
		}else{
89
			T childSize[N];
90
3268
			makeHalfSize<T,N>(childSize, size);
91
3268
			return child->addElement(posData, data, childPos, childSize, sizeLimit);
92
		}
93
	}
94
}
95
96
///Saves the PNTreeLightNode into a txt file for gnuplot
97
/**	@param fileName : name of the text file we want to write
98
 * 	@param pos : position of the current node
99
 * 	@param size : size of the current node
100
 * 	@return true on success, false otherwise
101
*/
102
template<typename T, typename U, unsigned char N>
103
4
bool PNTreeLightNode<T, U, N>::saveGnuplotData(const std::string & fileName, T pos[N], T size[N]){
104
4
	if(fileName == "") return false;
105
8
	std::ofstream fs;
106
4
	fs.open(fileName);
107
4
	if(!fs.is_open()){return false;}
108
4
	bool b = saveGnuplotData(fs, 0, pos, size);
109
4
	fs.close();
110
4
	return b;
111
}
112
113
///Saves the PNTreeLightNode into a txt file for gnuplot
114
/**	@param fs : text file we want to write
115
 * 	@param height : height of the quad to draw
116
 * 	@param pos : position of the current node
117
 * 	@param size : size of the current node
118
 * 	@return true on success, false otherwise
119
*/
120
template<typename T, typename U, unsigned char N>
121
1340
bool PNTreeLightNode<T, U, N>::saveGnuplotData(std::ofstream & fs, T height, T pos[N], T size[N]){
122
	if(N == 2){
123
170
		fs << pos[0] << "\t" << pos[1] << "\t" << height << std::endl;
124
170
		fs << (pos[0] + size[0]) << "\t" << pos[1] << "\t" << height << std::endl;
125
170
		fs << (pos[0] + size[0]) << "\t" << (pos[1] + size[1]) << "\t" << height << std::endl;
126
170
		fs << pos[0] << "\t" << (pos[1] + size[1]) << "\t" << height << std::endl;
127
170
		fs << pos[0] << "\t" << pos[1] << "\t" << height << std::endl;
128
	}else if(N == 3){
129
1170
		T px0(pos[0]), px1(pos[0] + size[0]);
130
1170
		T py0(pos[1]), py1(pos[1] + size[1]);
131
1170
		T pz0(pos[2]), pz1(pos[2] + size[2]);
132
133
		//lower quad
134
1170
		fs << px0 << "\t" << py0 << "\t" << pz0 << std::endl;
135
1170
		fs << px1 << "\t" << py0 << "\t" << pz0 << std::endl;
136
1170
		fs << px1 << "\t" << py1 << "\t" << pz0 << std::endl;
137
1170
		fs << px0 << "\t" << py1 << "\t" << pz0 << std::endl;
138
1170
		fs << px0 << "\t" << py0 << "\t" << pz0 << std::endl;
139
1170
		fs << std::endl;
140
		//upper quad
141
1170
		fs << px0 << "\t" << py0 << "\t" << pz1 << std::endl;
142
1170
		fs << px1 << "\t" << py0 << "\t" << pz1 << std::endl;
143
1170
		fs << px1 << "\t" << py1 << "\t" << pz1 << std::endl;
144
1170
		fs << px0 << "\t" << py1 << "\t" << pz1 << std::endl;
145
1170
		fs << px0 << "\t" << py0 << "\t" << pz1 << std::endl;
146
1170
		fs << std::endl;
147
		//Lines on Oz axis
148
1170
		fs << px0 << "\t" << py0 << "\t" << pz0 << std::endl;
149
1170
		fs << px0 << "\t" << py0 << "\t" << pz1 << std::endl;
150
1170
		fs << std::endl;
151
1170
		fs << px0 << "\t" << py1 << "\t" << pz0 << std::endl;
152
1170
		fs << px0 << "\t" << py1 << "\t" << pz1 << std::endl;
153
1170
		fs << std::endl;
154
1170
		fs << px1 << "\t" << py1 << "\t" << pz0 << std::endl;
155
1170
		fs << px1 << "\t" << py1 << "\t" << pz1 << std::endl;
156
1170
		fs << std::endl;
157
1170
		fs << px1 << "\t" << py0 << "\t" << pz0 << std::endl;
158
1170
		fs << px1 << "\t" << py0 << "\t" << pz1 << std::endl;
159
	}
160
1340
	fs << std::endl;
161
1340
	if(p_tableChildren != NULL){
162
		T childSize[N], posChild[N];
163
188
		makeHalfSize<T,N>(childSize, size);
164
1524
		for(unsigned char i(0); i < PPower<2, N>::Value; ++i){
165
5176
			for(unsigned char k(0); k < N; ++k){
166
3840
				posChild[k] = pos[k] + ((i >> k) & 1)*childSize[k];
167
			}
168
1336
			p_tableChildren[i].saveGnuplotData(fs, height + 1, posChild, childSize);
169
		}
170
	}
171
1340
	return true;
172
}
173
174
///Clear the PNTreeLightNode content
175
template<typename T, typename U, unsigned char N>
176
2680
void PNTreeLightNode<T, U, N>::clear(){
177
2680
	if(p_tableChildren != NULL){
178
1524
		for(unsigned char i(0); i < PPower<2, N>::Value; ++i){
179
1336
			PNTreeLightNode<T, U, N> * child = &(p_tableChildren[i]);
180
1336
			child->clear();
181
		}
182

1524
		delete [] p_tableChildren;
183
188
		p_tableChildren = NULL;
184
	}
185
2680
	p_data = NULL;
186
2680
}
187
188
///Get the data of the last node in the N tree
189
/**	@param posData : position of the data
190
 * 	@param pos : position of the current node
191
 * 	@param size : size of the current node
192
 * 	@return data of the last node in the N tree
193
*/
194
template<typename T, typename U, unsigned char N>
195
16
const U * PNTreeLightNode<T, U, N>::getLastData(const T * posData, const T pos[N], const T size[N]) const{
196
16
	if(p_tableChildren == NULL){
197
4
		if(p_data == NULL) return NULL;
198
4
		else return p_data;
199
	}else{
200
		T childPos[N];
201
12
		const PNTreeLightNode<T, U, N> * child = getChildFromPos(childPos, posData, pos, size);
202
12
		if(child == NULL) return NULL;
203
		else{
204
			T childSize[N];
205
12
			makeHalfSize<T,N>(childSize, size);
206
12
			return child->getLastData(posData, pos, childSize);
207
		}
208
	}
209
}
210
211
///Get the distance between two points
212
/**	@param posA : first position
213
 * 	@param posB : second position
214
 * 	@return distance between posA and posB
215
*/
216
template<typename T, unsigned char N>
217
T getDistanceFromData(const T posA[N], const T posB[N]){
218
	T res = 0.0, x;
219
	for(unsigned char i(0); i < N; ++i){
220
		x = posA[i] - posB[i];
221
		res += x*x;
222
	}
223
	return sqrt(res);
224
}
225
226
///Get the index of the check neighbours tab
227
/**	@param indexChild : index of the reference cell
228
 * 	@param currentChildIndex : index of the current node to be checked
229
 * 	@return index of the neighbours to be checked in the neighbours table
230
*/
231
template<unsigned char N>
232
unsigned int getNeighbourCellIndex(unsigned char indexChild[N], unsigned char currentChildIndex[N]){
233
	unsigned int index(0u), base(1u), tmp;
234
	for(unsigned char i(N); i < N; ++i){
235
		tmp = 0u;
236
		if(indexChild[i] > currentChildIndex[i]){
237
			tmp = 2u;
238
		}else if(indexChild[i] == currentChildIndex[i]){
239
			tmp = 1u;
240
		}
241
		index += base*tmp;
242
		base *= 3u;
243
	}
244
	return index;
245
}
246
247
///Get the closer data from the given position posData
248
/**	@param[out] closerData : pointer to the closer data found
249
 * 	@param[out] distFromCloserData : distance from the closer data to the search position posData
250
 * 	@param[out] tabIsNeighbourChecked : table of the checked neighbours (true), or unchecked neighbours (false)
251
 * 	@param nbNeighbour : size of the table of neighbours
252
 * 	@param posData : position used to search the closer data
253
 * 	@param pos : position of the current node
254
 * 	@param size : size of the current node
255
 * 	@return true if the closer data has been found, false if the parent needs to keep searching
256
*/
257
template<typename T, typename U, unsigned char N>
258
bool PNTreeLightNode<T, U, N>::getCloserData(U*& closerData, T & distFromCloserData, bool * tabIsNeighbourChecked, unsigned int nbNeighbour,
259
						const T * posData, const T pos[N], const T size[N]) const
260
{
261
	if(p_tableChildren == NULL){			//If the node has no child
262
		if(p_data == NULL) return false;		//If the node has no data
263
		else{						//If the node has data
264
			if(closerData == NULL){
265
				closerData = p_data;
266
				distFromCloserData = getDistanceFromData<T,N>(p_posData, posData);
267
				return true;
268
			}else{
269
				T dist = getDistanceFromData<T,N>(p_posData, posData);
270
				if(dist < distFromCloserData){
271
					distFromCloserData = dist;
272
					closerData = p_data;
273
				}
274
				return false;
275
			}
276
		}
277
	}else{						//If the node has children
278
		T childPos[N];
279
		const PNTreeLightNode<T, U, N> * child = getChildFromPos(childPos, posData, pos, size);
280
		if(child == NULL) return false;
281
		else{
282
			T childSize[N];
283
			makeHalfSize<T,N>(childSize, size);
284
			bool b = child->getCloserData(closerData, distFromCloserData, tabIsNeighbourChecked, nbNeighbour, posData, childPos, childSize);
285
			if(b) return true;
286
			else{
287
				unsigned char indexChild[N], currentChildIndex[N];
288
				T currentChildPos[N];
289
				getIndexOfChildFromPos(indexChild, posData, pos, size);
290
				unsigned char fullIndexChild(getFullIndexChild(indexChild));
291
292
				for(unsigned char i(0); i < PPower<2, N>::Value; ++i){
293
					if(i == fullIndexChild) continue;
294
					for(unsigned char j(0); j < N; ++j){
295
						currentChildIndex[j] = (i >> j) & 1;
296
						currentChildPos[j] = pos[j] + ((T)currentChildIndex[j])*childSize[j];
297
					}
298
					unsigned int indexCurrentNeighbour(getNeighbourCellIndex<N>(indexChild, currentChildIndex));
299
					//If the neighbours is already checked, skip it
300
					if(tabIsNeighbourChecked[indexCurrentNeighbour]) continue;
301
					//If the neighbours is not check yet, check it and write it in the tabIsNeighbourChecked
302
					tabIsNeighbourChecked[indexCurrentNeighbour] = true;
303
					if(child->getCloserData(closerData, distFromCloserData, tabIsNeighbourChecked, nbNeighbour,
304
						posData, currentChildPos, childSize))
305
					{
306
						return true;
307
					}
308
				}
309
				if(isNeighbourSearchFinised(tabIsNeighbourChecked, nbNeighbour)) return true;
310
				return false;
311
			}
312
		}
313
	}
314
}
315
316
///Get the child of the PNTreeLightNode with a position
317
/**	@param[out] childPos : position of the child
318
 * 	@param posData : position of the data
319
 * 	@param pos : position of the current node
320
 * 	@param size : size of the current node
321
 * 	@return child of the current PNTreeLightNode which contains the position (pos)
322
*/
323
template<typename T, typename U, unsigned char N>
324
12
const PNTreeLightNode<T, U, N> * PNTreeLightNode<T, U, N>::getChildFromPos(T childPos[N], const T * posData, const T pos[N], const T size[N]) const{
325
12
	if(p_tableChildren == NULL) return NULL;
326
12
	unsigned char  posChild(0), base(1);
327
	bool cond;
328
42
	for(unsigned char j(0); j < N; ++j){
329
30
		cond = ((posData[j] - pos[j]) > size[j]*0.5);
330
30
		childPos[j] = pos[j] + cond*size[j]*0.5;
331
30
		posChild += cond*base;
332
30
		base *= 2;		//on poura faire du décalage de bit plus tard
333
	}
334
12
	if(posChild >= PPower<2, N>::Value) return NULL;
335
12
	else return &(p_tableChildren[posChild]);
336
}
337
338
///Get the child of the PNTreeLightNode with a position
339
/**	@param[out] childPos : position of the child
340
 * 	@param posData : position of the data
341
 * 	@param pos : position of the current node
342
 * 	@param size : size of the current node
343
 * 	@return child of the current PNTreeLightNode which contains the position (pos)
344
*/
345
template<typename T, typename U, unsigned char N>
346
3456
PNTreeLightNode<T, U, N> * PNTreeLightNode<T, U, N>::getChildFromPos(T childPos[N], const T * posData, const T pos[N], const T size[N]){
347
3456
	if(p_tableChildren == NULL) return NULL;
348
3456
	unsigned char  posChild(0), base(1);
349
	bool cond;
350
13440
	for(unsigned char j(0); j < N; ++j){
351
9984
		cond = ((posData[j] - pos[j]) > size[j]*0.5);
352
9984
		childPos[j] = pos[j] + cond*size[j]*0.5;
353
9984
		posChild += cond*base;
354
9984
		base *= 2;		//on poura faire du décalage de bit plus tard
355
	}
356
3456
	if(posChild >= PPower<2, N>::Value) return NULL;
357
	else{
358
// 		std::cerr << "PNTreeLightNode<T, U, N>::getChildFromPos : posChild = " << ((int)posChild) << std::endl;
359
3456
		return &(p_tableChildren[posChild]);
360
	}
361
}
362
363
///Get the index of the child position by respect to the position pos
364
/**	@param[out] index : vector of the position of the child
365
 * 	@param posData : position used to get the child
366
 * 	@param pos : position of the current node
367
 * 	@param size : size of the current node
368
*/
369
template<typename T, typename U, unsigned char N>
370
void PNTreeLightNode<T, U, N>::getIndexOfChildFromPos(unsigned char index[N], const T * posData, const T pos[N], const T size[N]) const{
371
	if(p_tableChildren == NULL) return;
372
	for(unsigned char j(0lu); j < N; ++j){
373
		index[j] = ((posData[j] - pos[j]) > size[j]*0.5);
374
	}
375
}
376
377
///Get the index of the child position by respect to the position pos
378
/**	@param[out] index : vector of the position of the child
379
 * 	@param posData : position used to get the child
380
 * 	@param pos : position of the current node
381
 * 	@param size : size of the current node
382
*/
383
template<typename T, typename U, unsigned char N>
384
void PNTreeLightNode<T, U, N>::getIndexOfChildFromPos(unsigned char index[N], T * posData, T pos[N], T size[N]){
385
	if(p_tableChildren == NULL) return;
386
	for(unsigned char j(0); j < N; ++j){
387
		index[j] = ((posData[j] - pos[j]) > size[j]*0.5);
388
	}
389
}
390
391
///Get the full index position of a child
392
/**	@param index : vector of index position of a child
393
 * 	@return full index position of a child
394
*/
395
template<typename T, typename U, unsigned char N>
396
unsigned char PNTreeLightNode<T, U, N>::getFullIndexChild(unsigned char index[N]) const{
397
	unsigned char  posChild(0), base(1);
398
	for(unsigned char j(0); j < N; ++j){
399
		posChild += (index[j])*base;
400
		base *= 2;		//on poura faire du décalage de bit plus tard
401
	}
402
	return posChild;
403
}
404
405
///Returns the data position
406
/**	@return data position
407
*/
408
template<typename T, typename U, unsigned char N>
409
const T * PNTreeLightNode<T, U, N>::getDataPos() const{return p_posData;}
410
411
///Returns the data position
412
/**	@return data position
413
*/
414
template<typename T, typename U, unsigned char N>
415
T * PNTreeLightNode<T, U, N>::getDataPos(){return p_posData;}
416
417
///Returns the table of children of the PNTreeLightNode
418
/**	@return table of children of the PNTreeLightNode
419
*/
420
template<typename T, typename U, unsigned char N>
421
const PNTreeLightNode<T, U, N> * PNTreeLightNode<T, U, N>::getTabChildren() const{return p_tableChildren;}
422
423
///Returns the table of children of the PNTreeLightNode
424
/**	@return table of children of the PNTreeLightNode
425
*/
426
template<typename T, typename U, unsigned char N>
427
PNTreeLightNode<T, U, N> * PNTreeLightNode<T, U, N>::getTabChildren(){return p_tableChildren;}
428
429
///Returns the child of the PNTreeLightNode
430
/**	@param childId : id of the child we want to have
431
 * 	@return pointer to the child or NULL if there is not
432
*/
433
template<typename T, typename U, unsigned char N>
434
const PNTreeLightNode<T, U, N> * PNTreeLightNode<T, U, N>::getChild(unsigned char childId) const{
435
	if(p_tableChildren == NULL || childId >= PPower<2, N>::Value) return NULL;
436
	return &(p_tableChildren[childId]);
437
}
438
439
///Returns the child of the PNTreeLightNode
440
/**	@param childId : id of the child we want to have
441
 * 	@return pointer to the child or NULL if there is not
442
*/
443
template<typename T, typename U, unsigned char N>
444
PNTreeLightNode<T, U, N> * PNTreeLightNode<T, U, N>::getChild(unsigned char childId){
445
	if(p_tableChildren == NULL || childId >= PPower<2, N>::Value) return NULL;
446
	return &(p_tableChildren[childId]);
447
}
448
449
///Copy function of PNTreeLightNode
450
/**	@param other : class to copy
451
*/
452
template<typename T, typename U, unsigned char N>
453
void PNTreeLightNode<T, U, N>::copyPNTreeLightNode(const PNTreeLightNode<T, U, N> & other){
454
455
}
456
457
///Split the PNTreeLightNode
458
/**	@param pos : position of the current node
459
 * 	@param size : size of the current node
460
 * 	@param sizeLimit : limit of the cell size
461
 * 	@return true on success, false otherwise
462
*/
463
template<typename T, typename U, unsigned char N>
464
188
bool PNTreeLightNode<T, U, N>::split(const T pos[N], const T size[N], T sizeLimit){
465

188
	if(p_tableChildren != NULL || p_data == NULL){
466
		std::cerr << "PNTreeLightNode<T, U, N>::split() : current node already split" << std::endl;
467
		return false;
468
	}
469
// 	std::cerr << "PNTreeLightNode<T, U, N>::split() : begin" << std::endl;
470
	T halfSizeChild[N];
471
188
	makeHalfSize<T, N>(halfSizeChild, size);
472
188
	if(!checkSizeLimitLight<T, N>(halfSizeChild, sizeLimit)){
473
// 		std::cerr << "PNTreeLightNode<T, U, N>::split : can't split more, child sizes less than " << sizeLimit << std::endl;
474
		return false;
475
	}
476
188
	unsigned char nbChildren(PPower<2, N>::Value);
477

1524
	p_tableChildren = new PNTreeLightNode<T, U, N>[nbChildren];
478
1524
	for(unsigned char i(0); i < nbChildren; ++i){
479
1336
		PNTreeLightNode<T, U, N> * child = &(p_tableChildren[i]);
480
1336
		child->p_tableChildren = NULL;
481
1336
		child->p_data = NULL;
482
1336
		child->p_posData = NULL;
483
	}
484
// 	std::cerr << "PNTreeLightNode<T, U, N>::split : replace child" << std::endl;
485
	T childPos[N];
486
188
	PNTreeLightNode<T, U, N> * child = getChildFromPos(childPos, p_posData, pos, size);
487
188
	bool b = true;;
488
188
	if(child == NULL) return false;
489
	else{
490
188
		b = child->addElement(p_posData, p_data, childPos, halfSizeChild, sizeLimit);
491
	}
492
188
	p_data = NULL;
493
188
	p_posData = NULL;
494
188
	return b;
495
}
496
497
///Initialisation function of the class PNTreeLightNode
498
template<typename T, typename U, unsigned char N>
499
1340
void PNTreeLightNode<T, U, N>::initialisationPNTreeLightNode(){
500
1340
	p_posData = NULL;
501
1340
	p_data = NULL;
502
1340
	p_tableChildren = NULL;
503
1340
}
504
505
506
507
508
509
#endif
510
511
512