APRIterator.hpp 17 KB
Newer Older
1
//
cheesema's avatar
cheesema committed
2
// Created by cheesema on 16.01.18.
3
4
//

cheesema's avatar
cheesema committed
5
6
#ifndef PARTPLAY_APR_ITERATOR_NEW_HPP
#define PARTPLAY_APR_ITERATOR_NEW_HPP
7

8
#include "APRAccessStructures.hpp"
9

10
#include "GenIterator.hpp"
11

12
class APRIterator  : public GenIterator {
13

cheesema's avatar
cheesema committed
14
public:
15

16
    explicit APRIterator(APRAccess& apr_access_) {
17
        this->apr_access = &apr_access_;
cheesema's avatar
cheesema committed
18
    }
19

20
21
22
23
    /////////////////////////
    /// Random access
    ///
    /////////////////////////
24

25
26
27
    bool set_iterator_by_particle_cell(ParticleCell& random_particle_cell);
    bool set_iterator_by_global_coordinate(float x,float y,float z);
    bool find_neighbours_same_level(const uint8_t& direction);
28

29
    bool set_iterator_to_particle_next_particle();
30
31


32
    uint64_t set_new_lzx(const uint16_t level,const uint16_t z,const uint16_t x);
33

34
    uint64_t set_new_lzxy(const uint16_t level,const uint16_t z,const uint16_t x,const uint16_t y);
35

36
    bool find_neighbours_in_direction(const uint8_t& direction);
37

38
39
40
    inline bool set_neighbour_iterator(APRIterator &original_iterator, const uint8_t& direction, const uint8_t& index);
protected:
    bool find_next_child(const uint8_t& direction,const uint8_t& index);
41

42
    uint64_t start_index(const uint16_t level, const uint64_t offset);
43

44
    uint64_t max_row_level_offset(const uint16_t x,const uint16_t z,const uint16_t num_parts);
cheesema's avatar
cheesema committed
45

46
};
cheesema's avatar
cheesema committed
47
48


49
uint64_t APRIterator::start_index(const uint16_t level, const uint64_t offset){
50

51
52
53
    if(this->current_particle_cell.pc_offset == 0){
        if(level == this->level_min()){
            return  0;
54
        } else {
55
            return this->apr_access->global_index_by_level_and_zx_end[this->current_particle_cell.level-1].back();
56
        }
57
58
    } else {
        return this->apr_access->global_index_by_level_and_zx_end[this->current_particle_cell.level][this->current_particle_cell.pc_offset-1];
59
60
    }

61
}
62

63
64
65
uint64_t APRIterator::max_row_level_offset(const uint16_t x,const uint16_t z,const uint16_t num_parts){
    return ((x%2) + (z%2)*2)*((uint64_t)num_parts) ;//calculates the number of particles in the row
}
cheesema's avatar
cheesema committed
66

67
inline uint64_t APRIterator::set_new_lzx(const uint16_t level,const uint16_t z,const uint16_t x){
cheesema's avatar
cheesema committed
68

69
        this->current_particle_cell.level = level;
70
        //otherwise now we have to figure out where to look for the next particle cell;
cheesema's avatar
cheesema committed
71

72
        //back out your xz from the offset
73
74
        this->current_particle_cell.z = z;
        this->current_particle_cell.x = x;
cheesema's avatar
cheesema committed
75

76
77
        if(level == this->level_max()){
            this->current_particle_cell.pc_offset =this->apr_access->x_num[level-1]*(z/2) + (x/2);
cheesema's avatar
cheesema committed
78

79
            if(this->apr_access->gap_map.data[this->current_particle_cell.level][this->current_particle_cell.pc_offset].size() > 0) {
cheesema's avatar
cheesema committed
80

81
82
                this->current_gap.iterator =this->apr_access->gap_map.data[this->current_particle_cell.level][this->current_particle_cell.pc_offset][0].map.begin();
                this->current_particle_cell.y = this->current_gap.iterator->first;
cheesema's avatar
cheesema committed
83

cheesema's avatar
cheesema committed
84
                uint64_t begin = start_index(level,this->current_particle_cell.pc_offset);
cheesema's avatar
cheesema committed
85

86
                this->current_particle_cell.global_index = begin;
cheesema's avatar
cheesema committed
87

88
                this->set_neighbour_flag();
cheesema's avatar
cheesema committed
89

90
                //requries now an offset depending on the child position odd/even
91
                auto it =(this->apr_access->gap_map.data[level][this->current_particle_cell.pc_offset][0].map.rbegin());
92
                uint16_t num_parts = ((it->second.global_index_begin_offset + (it->second.y_end-it->first))+1);
cheesema's avatar
cheesema committed
93

94
                this->end_index =  begin + num_parts;
cheesema's avatar
cheesema committed
95

cheesema's avatar
cheesema committed
96
                //calculates the offset for the xz position
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
                uint64_t index_offset=0;

                if(check_neigh_flag){

                    uint64_t x_factor =2;

                    if((x==(spatial_index_x_max(level)-1)) && ((x%2)==0)){
                        x_factor = 1;
                    }

                    index_offset = ((x%2) + (z%2)*x_factor)*((uint64_t)num_parts);
                } else {

                    //calculates the offset for the xz position
                    index_offset = max_row_level_offset(x, z, num_parts);
                }
cheesema's avatar
cheesema committed
113

114
115
                this->end_index += index_offset;
                this->current_particle_cell.global_index += index_offset;
cheesema's avatar
cheesema committed
116

117
                return this->current_particle_cell.global_index;
118
            } else {
119
120
                this->end_index = 0;
                current_particle_cell.y = UINT16_MAX;
121
                return UINT64_MAX;
cheesema's avatar
cheesema committed
122
123
124
            }

        } else {
125
            this->current_particle_cell.pc_offset =this->apr_access->x_num[level]*z + x;
cheesema's avatar
cheesema committed
126

127
            if(this->apr_access->gap_map.data[this->current_particle_cell.level][this->current_particle_cell.pc_offset].size() > 0) {
cheesema's avatar
cheesema committed
128

129
130
                this->current_gap.iterator =this->apr_access->gap_map.data[this->current_particle_cell.level][this->current_particle_cell.pc_offset][0].map.begin();
                this->current_particle_cell.y = this->current_gap.iterator->first;
131

cheesema's avatar
cheesema committed
132
                uint64_t begin = start_index(level,this->current_particle_cell.pc_offset);
133

134
                this->current_particle_cell.global_index = this->current_gap.iterator->second.global_index_begin_offset + begin;
135

136
                this->set_neighbour_flag();
137

138
                // IN HERE PUT THE STARTING INDEX!
139
                //auto it =(this->apr_access->gap_map.data[level][this->current_particle_cell.pc_offset][0].map.rbegin());
140
                this->end_index = this->apr_access->global_index_by_level_and_zx_end[this->current_particle_cell.level][this->current_particle_cell.pc_offset];
141

142
                return this->current_particle_cell.global_index;
143
            } else {
144
145
                this->end_index = 0;
                current_particle_cell.y = UINT16_MAX;
146
                return UINT64_MAX;
147
148
149
            }

        }
150
}
151
152
153



154
uint64_t APRIterator::set_new_lzxy(const uint16_t level,const uint16_t z,const uint16_t x,const uint16_t y){
155

156
157
158
    //otherwise now we have to figure out where to look for the next particle cell;
    //set to the correct row
    uint64_t begin_index = set_new_lzx(level,z,x);
159

160
    this->current_particle_cell.y = y;
161

162
163
    if(begin_index!=UINT64_MAX){
        ParticleCellGapMap& current_pc_map =this->apr_access->gap_map.data[this->current_particle_cell.level][this->current_particle_cell.pc_offset][0];
164

165
166
        //otherwise search for it (points to first key that is greater than the y value)
        this->current_gap.iterator = current_pc_map.map.upper_bound(this->current_particle_cell.y);
167

168
        bool end = false;
169

170
171
        if(this->current_gap.iterator == current_pc_map.map.begin()){
            //less then the first value
172

173
174
            this->current_particle_cell.y = this->current_gap.iterator->first;
            this->current_particle_cell.global_index = this->current_gap.iterator->second.global_index_begin_offset + begin_index;
175

176
            this->set_neighbour_flag();
177

178
179
            return this->current_particle_cell.global_index;
        } else{
180

181
182
            if(this->current_gap.iterator == current_pc_map.map.end()){
                end = true;
cheesema's avatar
cheesema committed
183
            }
184
            this->current_gap.iterator--;
185
186
        }

187
188
189
190
191
192
        if ((this->current_particle_cell.y >= this->current_gap.iterator->first) & (this->current_particle_cell.y <= this->current_gap.iterator->second.y_end)) {
            // exists
            this->current_particle_cell.global_index = this->current_gap.iterator->second.global_index_begin_offset +
                                                       (this->current_particle_cell.y - this->current_gap.iterator->first) + begin_index;
            this->set_neighbour_flag();
            return this->current_particle_cell.global_index;
cheesema's avatar
cheesema committed
193
        }
194

195
196
197
198
        if(end){
            //no more particles
            this->current_particle_cell.global_index = UINT64_MAX;
            return this->current_particle_cell.global_index;
cheesema's avatar
cheesema committed
199
        } else {
200
201
202
203
204
            //still within range
            this->current_particle_cell.global_index = this->current_gap.iterator->second.global_index_begin_offset + begin_index;
            this->current_particle_cell.y = this->current_gap.iterator->first;
            this->set_neighbour_flag();
            return this->current_particle_cell.global_index;
205
206
        }

207
208
    } else {
        return UINT64_MAX;
209
    }
210
}
211
212


213

214
215
216
217
inline bool APRIterator::set_iterator_to_particle_next_particle(){
    //
    //  Moves the iterator to point to the particle number (global index of the particle)
    //
cheesema's avatar
cheesema committed
218

219
    if( (this->current_particle_cell.y+1) <= this->current_gap.iterator->second.y_end){
220
        //  Still in same y gap
221

222
223
        this->current_particle_cell.global_index++;
        this->current_particle_cell.y++;
224
        return true;
225

226
    } else {
227

228
        //not in the same gap
229
        this->current_gap.iterator++;//move the iterator forward.
230

231

232
        //I am in the next gap
233
234
        this->current_particle_cell.global_index++;
        this->current_particle_cell.y = this->current_gap.iterator->first; // the key is the first y value for the gap
235
        return true;
236
    }
237
}
238

239

240
241
242
243
//
//inline ParticleCell APRIterator::get_neigh_particle_cell(){
//    return this->neighbour_particle_cell;
//}
244

245
inline bool APRIterator::find_neighbours_in_direction(const uint8_t& direction){
cheesema's avatar
cheesema committed
246

247
    //the three cases
248
    if(this->current_particle_cell.level ==this->apr_access->level_max()){
249
        //for (int l = 0; l < 2; ++l) {
250

251
        this->apr_access->get_neighbour_coordinate(this->current_particle_cell,this->neighbour_particle_cell,direction,_LEVEL_SAME,0);
cheesema's avatar
cheesema committed
252

253
254
        if(this->check_neighbours_particle_cell_in_bounds()){
            if(this->apr_access->find_particle_cell(this->neighbour_particle_cell,this->local_iterators.same_level[direction])){
255
                //found the neighbour! :D
256
                this->level_delta = _LEVEL_SAME;
257
258
259
                return true;
            }
        };
260

261
        this->apr_access->get_neighbour_coordinate(this->current_particle_cell,this->neighbour_particle_cell,direction,_LEVEL_DECREASE,0);
262

263
264
265
        if(this->check_neighbours_particle_cell_in_bounds()){
            if(this->apr_access->find_particle_cell(this->neighbour_particle_cell,this->local_iterators.parent_level[direction])){
                this->level_delta = _LEVEL_DECREASE;
266

267
                return true;
268

cheesema's avatar
cheesema committed
269
            }
270
        };
cheesema's avatar
cheesema committed
271

272
        //}
273

274
    } else if(this->current_particle_cell.level ==this->apr_access->level_min()){
275
        //for (int l = 0; l < 2; ++l) {
276

277
        this->apr_access->get_neighbour_coordinate(this->current_particle_cell,this->neighbour_particle_cell,direction,_LEVEL_SAME,0);
278

279
280
        if(this->check_neighbours_particle_cell_in_bounds()){
            if(this->apr_access->find_particle_cell(this->neighbour_particle_cell,this->local_iterators.same_level[direction])){
281
                //found the neighbour! :D
282
                this->level_delta = _LEVEL_SAME;
283
284
285
                return true;
            }
        };
286

287
        this->apr_access->get_neighbour_coordinate(this->current_particle_cell,this->neighbour_particle_cell,direction,_LEVEL_INCREASE,0);
288

289
290
291
        if(this->check_neighbours_particle_cell_in_bounds()){
            if(this->apr_access->find_particle_cell(this->neighbour_particle_cell,this->local_iterators.child_level[direction][0])){
                this->level_delta = _LEVEL_INCREASE;
292
293
294
                return true;
            }
        };
295

296
297
298
        //}
    } else {
        //for (int l = 0; l < 3; ++l) {
299
        this->apr_access->get_neighbour_coordinate(this->current_particle_cell,this->neighbour_particle_cell,direction,_LEVEL_SAME,0);
300

301
302
        if(this->check_neighbours_particle_cell_in_bounds()){
            if(this->apr_access->find_particle_cell(this->neighbour_particle_cell,this->local_iterators.same_level[direction])){
303
                //found the neighbour! :D
304
                this->level_delta = _LEVEL_SAME;
305
                return true;
cheesema's avatar
cheesema committed
306
            }
307
        };
308

309
        this->apr_access->get_neighbour_coordinate(this->current_particle_cell,this->neighbour_particle_cell,direction,_LEVEL_DECREASE,0);
310

311
312
313
        if(this->check_neighbours_particle_cell_in_bounds()){
            if(this->apr_access->find_particle_cell(this->neighbour_particle_cell,this->local_iterators.parent_level[direction])){
                this->level_delta = _LEVEL_DECREASE;
314
                return true;
cheesema's avatar
cheesema committed
315
            }
316
        };
317
        this->apr_access->get_neighbour_coordinate(this->current_particle_cell,this->neighbour_particle_cell,direction,_LEVEL_INCREASE,0);
318

319
320
321
        if(this->check_neighbours_particle_cell_in_bounds()){
            if(this->apr_access->find_particle_cell(this->neighbour_particle_cell,this->local_iterators.child_level[direction][0])){
                this->level_delta = _LEVEL_INCREASE;
322
323
324
                return true;
            }
        };
325
326
    }

327
    this->level_delta=_NO_NEIGHBOUR;
328

329
    return false;
330

331
332
    }

333
334
335
336
inline bool APRIterator::set_neighbour_iterator(APRIterator &original_iterator, const uint8_t& direction, const uint8_t& index){
    //
    //  This is sets the this iterator, to the neighbour of the particle cell that original_iterator is pointing to
    //
337

338
    if(original_iterator.level_delta!=_LEVEL_INCREASE){
339
        //copy the information from the original iterator
340
        std::swap(this->current_particle_cell,original_iterator.neighbour_particle_cell);
341

342
343
    } else {
        if(index==0){
344
            std::swap(this->current_particle_cell,original_iterator.neighbour_particle_cell);
345
346

        } else {
347
            bool success = original_iterator.find_next_child(direction,index);
348
            std::swap(this->current_particle_cell,original_iterator.neighbour_particle_cell);
349

350
            return success;
351
        }
352
    }
353

354
355
356
    //this needs the if clause that finds the neighbour
    return true;
}
357

358
359
360
361
inline bool APRIterator::set_iterator_by_particle_cell(ParticleCell& random_particle_cell){
    //
    //  Have to have set the particle cells x,y,z,level, and it will move the iterator to this location if it exists
    //
362
363
364
365
366
367
368
369
370
    if(random_particle_cell.level==this->level_max()) {
        random_particle_cell.pc_offset =
                this->apr_access->gap_map.x_num[random_particle_cell.level-1] * (random_particle_cell.z/2) +
                        (random_particle_cell.x/2);
    } else {
        random_particle_cell.pc_offset =
                this->apr_access->gap_map.x_num[random_particle_cell.level] * random_particle_cell.z +
                random_particle_cell.x;
    }
371

372
373
    if(this->apr_access->find_particle_cell(random_particle_cell,this->current_gap)){
        this->current_particle_cell = random_particle_cell;
374
        this->set_neighbour_flag();
375
        //exists
376
        return true;
377
378
379
    } else {
        //particle cell doesn't exist
        return false;
cheesema's avatar
cheesema committed
380
    }
381
}
cheesema's avatar
cheesema committed
382

383
384
385
386
inline bool APRIterator::set_iterator_by_global_coordinate(float x,float y,float z){
    //
    //  Finds the Particle Cell for which the point (x,y,z) belongs to its spatial domain and set the iterator to it
    //
387

388
    //check in bounds
389
    if(((uint16_t)(x)>(this->apr_access->org_dims[1]-1)) | ((uint16_t)(z)>(this->apr_access->org_dims[2]-1)) | ((uint16_t)(y)>(this->apr_access->org_dims[0]-1))){
390
391
        //out of bounds
        return false;
392
393
    }

394
395
    //Then check from the highest level to lowest.
    ParticleCell particle_cell;
396
397
398
    particle_cell.y = floor(y);
    particle_cell.x = floor(x);
    particle_cell.z = floor(z);
399
    particle_cell.level = this->level_max();
400

401
    particle_cell.pc_offset = this->apr_access->gap_map.x_num[particle_cell.level] * (particle_cell.z/2) + (particle_cell.x/2);
cheesema's avatar
cheesema committed
402

403
    while( (particle_cell.level > this->level_min()) & !(this->apr_access->find_particle_cell(particle_cell,this->current_gap)) ){
404
405
406
407
        particle_cell.y = particle_cell.y/2;
        particle_cell.x = particle_cell.x/2;
        particle_cell.z = particle_cell.z/2;
        particle_cell.level--;
cheesema's avatar
cheesema committed
408

409
        particle_cell.pc_offset = this->apr_access->gap_map.x_num[particle_cell.level] * particle_cell.z + particle_cell.x;
410
411
    }

412
    this->current_particle_cell = particle_cell; //if its in bounds it will always have a particle cell responsible
413

414
    this->set_neighbour_flag();
415
416
    return true;
}
cheesema's avatar
cheesema committed
417

418
inline bool APRIterator::find_neighbours_same_level(const uint8_t& direction){
cheesema's avatar
cheesema committed
419

420
    bool found = false;
cheesema's avatar
cheesema committed
421

422
    this->apr_access->get_neighbour_coordinate(this->current_particle_cell,this->neighbour_particle_cell,direction,_LEVEL_SAME,0);
cheesema's avatar
cheesema committed
423

424
    if(this->check_neighbours_particle_cell_in_bounds()){
425
        if(this->apr_access->find_particle_cell(this->neighbour_particle_cell,this->local_iterators.same_level[direction])){
426
            //found the neighbour! :D
427

428
            this->level_delta = _LEVEL_SAME;
429
430
            return true;
        }
431
    };
432

433
434
    if(!found){
        this->level_delta=_NO_NEIGHBOUR;
435
436
    }

437
    return found;
438

439
}
440

441
inline bool APRIterator::find_next_child(const uint8_t& direction,const uint8_t& index){
442

443
444
    this->level_delta = _LEVEL_INCREASE;
    this->apr_access->get_neighbour_coordinate(this->current_particle_cell,this->neighbour_particle_cell,direction,this->level_delta,index);
445

446
447
    if(this->check_neighbours_particle_cell_in_bounds()){
        if(this->apr_access->find_particle_cell(this->neighbour_particle_cell,this->apr_access->get_local_iterator(this->local_iterators, this->level_delta, direction,index))){
448
            //found the neighbour! :D
449
450
            return true;
        }
451
452
453
    };
    return false;
}
454

455
456


cheesema's avatar
cheesema committed
457
#endif //PARTPLAY_APR_ITERATOR_NEW_HPP