-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPoissonDiskSampling.cpp
More file actions
96 lines (76 loc) · 2.98 KB
/
Copy pathPoissonDiskSampling.cpp
File metadata and controls
96 lines (76 loc) · 2.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include "DiskSampling/PoissonDiskSampling.h"
#include <cmath>
PoissonDiskSampling::PoissonDiskSampling(int p_width, int p_height, double p_min_dist, int p_point_count){
m_width = p_width;
m_height = p_height;
m_min_dist = p_min_dist;
m_point_count = p_point_count;
m_cell_size = m_min_dist / 1.414214;
m_grid_width = ceil(m_width / m_cell_size);
m_grid_height = ceil(m_height / m_cell_size);
m_grid = std::vector<std::vector<point *> >(m_grid_width, std::vector<point *>(m_grid_height, NULL));
}
std::vector<std::pair<double,double> > PoissonDiskSampling::Generate(){
point first_point(rand() % m_width, rand() % m_height);
m_process.push_back(first_point);
m_sample.push_back(std::make_pair(first_point.x, first_point.y));
int first_point_x = first_point.x/m_cell_size;
int first_point_y = first_point.y/m_cell_size;
m_grid[first_point_x][first_point_y] = new point(first_point);
while( !m_process.empty() ){
int new_point_index = rand() % m_process.size();
point new_point = m_process[new_point_index];
m_process.erase(m_process.begin() + new_point_index);
for(int i = 0; i < m_point_count; i++){
point new_point_around = generatePointAround(new_point);
if(inRectangle(new_point_around) && !inNeighbourhood(new_point_around)){
// cout << "Nuevo punto: (" << new_point_around.x << ", " << new_point_around.y << ")" << endl;
m_process.push_back(new_point_around);
m_sample.push_back(std::make_pair(new_point_around.x, new_point_around.y));
int new_point_x = new_point_around.x/m_cell_size;
int new_point_y = new_point_around.y/m_cell_size;
m_grid[new_point_x][new_point_y] = new point(new_point_around);
}
}
}
return m_sample;
}
PoissonDiskSampling::point PoissonDiskSampling::generatePointAround(point p_point){
double r1 = (double) rand() / RAND_MAX;
double r2 = (double) rand() / RAND_MAX;
double radius = m_min_dist * (r1 + 1);
double angle = 2 * 3.14159265 * r2;
double new_x = p_point.x + radius * cos(angle);
double new_y = p_point.y + radius * sin(angle);
return point(new_x, new_y);
}
bool PoissonDiskSampling::inRectangle(point p_point){
return (p_point.x >= 0 && p_point.y >= 0 && p_point.x < m_width && p_point.y < m_height);
}
bool PoissonDiskSampling::inNeighbourhood(point p_point){
std::vector<point *> cells = getCellsAround(p_point);
int size = cells.size();
for(int i = 0; i < size; i++){
if(cells[i]->distance(p_point) < m_min_dist){
return true;
}
}
return false;
}
std::vector<PoissonDiskSampling::point *> PoissonDiskSampling::getCellsAround(point p_point){
std::vector<point *> cells;
int x_index = p_point.x / m_cell_size;
int y_index = p_point.y / m_cell_size;
int min_x = std::max(0, x_index - 1);
int max_x = std::min(m_grid_width - 1, x_index + 1);
int min_y = std::max(0, y_index - 1);
int max_y = std::min(m_grid_height - 1, y_index + 1);
for(int i = min_x; i <= max_x; i++){
for(int j = min_y; j <= max_y; j++){
if(m_grid[i][j] != NULL){
cells.push_back(m_grid[i][j]);
}
}
}
return cells;
}