cgv
Loading...
Searching...
No Matches
grid.h
1#pragma once
2
3#include <vector>
4namespace cgv {
5 namespace data {
6
7template <typename Pnt, typename Idx = int>
8class grid : public std::vector<std::vector<Idx> >
9{
10public:
11 typename decltype(min_pnt[0]) Crd;
12 typename decltype(max_pnt-min_pnt) Vec;
13 std::size_t dim[3];
14 Crd rmax;
15 Crd rmax_sqr;
16 Crd rmax_estimate_factor;
17protected:
18 Vec scale;
19 Vec extent;
20 Vec cell_extent;
21 Pnt min_pnt, max_pnt;
22
23 void init() {
24 clear();
25 resize(get_size());
26 }
27 void compute_scales() {
28 extent = max_pnt-min_pnt;
29 for (int c=0; c<3; ++c) {
30 scale[c] = dim[c]/extent[c];
31 cell_extent[c] = extent[c]/dim[c];
32 }
33 }
34public:
35 grid(Idx dim = 20) { set_dim(dim); init(); }
36 grid(Idx dimx, Idx dimy, Idx dimz) { set_dim(dimx,dimy,dimz); init(); }
37 void clear() {
38 std::vector<std::vector<Idx> >::clear();
39 min_pnt = Pnt(-1,-1,-1);
40 max_pnt = Pnt(1,1,1);
41 }
42 bool is_empty() const { return std::vector<std::vector<Idx> >::empty(); }
43 void set_dim(Cnt dim) { set_dim(dim,dim,dim); }
44 void set_dim(Cnt dimx, Cnt dimy, Cnt dimz) {
45 dim[0] = dimx;
46 dim[1] = dimy;
47 dim[2] = dimz;
48 init();
49 compute_scales();
50 }
51 void set_box(const Pnt& _min_pnt, const Pnt& _max_pnt) {
52 min_pnt = _min_pnt;
53 max_pnt = _max_pnt;
54 compute_scales();
55 }
56 template <typename Func>
57 void compute_box(Idx nr_points, const Func& pnts) {
58 min_pnt = max_pnt = pnts(0);
59 for (Idx i=1; i<nr_points; ++i) {
60 for (int c=0; c<3; ++c) {
61 if (pnts(i)[c] < min_pnt[c])
62 min_pnt[c] = pnts(i)[c];
63 if (pnts(i)[c] > max_pnt[c])
64 max_pnt[c] = pnts(i)[c];
65 }
66 }
67 compute_scales();
68 }
70 template <typename Func>
71 void build(Idx nr_points, const Func& pnts) {
72 init();
73 rmax = (Crd) (rmax_estimate_factor*sqrt(2*(extent[0]*(extent[1]+extent[2])+extent[1]*extent[2])/nr_points));
74 rmax_sqr = rmax*rmax;
75 cout << "rmax = " << rmax << endl;
76 set_dim((Idx)(extent[0]/rmax), (Idx)(extent[1]/rmax), (Idx)(extent[2]/rmax));
77 for (Idx i=0; i<nr_points; ++i)
78 insert(pnts(i), i);
79 }
80 Idx get_size() const {
81 return dim[0]*dim[1]*dim[2];
82 }
83 template <typename Jdx>
84 Idx get_index(Jdx *ci) const {
85 return (ci[2]*dim[1]+ci[1])*dim[0]+ci[0];
86 }
87 Idx get_index(const Pnt& p) const {
88 Idx ci[3];
89 for (int c = 0; c < 3; ++c) {
90 ci[c] = (Idx) (scale[c]*(p[c]-min_pnt[c]));
91 if (ci[c] >= (Idx)dim[c])
92 ci[c] = dim[c]-1;
93 }
94 return get_index(ci);
95 }
96 template <typename Jdx>
97 void split_index(Idx idx, Jdx* ci) const {
98 Idx n = dim[0]*dim[1];
99 ci[2] = (Jdx)(idx / n);
100 idx -= n*ci[2];
101 ci[1] = (Jdx)(idx/dim[0]);
102 ci[0] = (Jdx)(idx-dim[0]*ci[1]);
103 }
104 void put_grid_cell(Idx idx, const Pnt& _min_pnt, const Pnt& _max_pnt) const {
105 Idx ci[3];
106 split_index(idx, ci);
107 for (int c=0; c<3; ++c)
108 _min_pnt[c] = ci[c]/scale[c] + min_pnt[c];
109 _max_pnt = _min_pnt+cell_extent;
110 }
111 void insert(const Pnt& p, Idx i) {
112 Idx ci = get_index(p);
113 if (ci >= size()) {
114 std::cerr << "hit not available cell " << ci << endl;
115 return;
116 }
117 at(ci).push_back(i);
118 }
119 void add_neighbors(Idx pi, const Pnt& p, Idx ci, const Func& pnts, vector<Idx>& N) const {
120 for (Idx i=0; i<at(ci).size(); ++i) {
121 Idx ni = at(ci)[i];
122 if (ni != pi) {
123 if (sqr_length(pnts(ni)-p) < rmax_sqr)
124 N.push_back(ni);
125 }
126 }
127 }
128 template <typename Func>
129 void extract_neighbors(Idx i, const Func& pnts, vector<Idx>& N) const
130 {
131 static const int d[3*26] = {
132 1,0,0,
133 0,1,0,
134 0,0,1,
135 -1,0,0,
136 0,-1,0,
137 0,0,-1,
138
139 1,1,0,
140 0,1,1,
141 1,0,1,
142 -1,1,0,
143 0,-1,1,
144 -1,0,1,
145 1,-1,0,
146 0,1,-1,
147 1,0,-1,
148 -1,-1,0,
149 0,-1,-1,
150 -1,0,-1,
151
152 1,1,1,
153 -1,1,1,
154 1,-1,1,
155 -1,-1,1,
156 1,1,-1,
157 -1,1,-1,
158 1,-1,-1,
159 -1,-1,-1
160 };
161 const Pnt& p = pnts(i);
162 Idx ci = get_index(p);
163 add_neighbors(i, p, ci, N);
164 for (int j=0; j<26; ++j) {
165 Idx cj = ci+d[3*j]+dim[0]*(d[3*j+1]+dim[1]*d[3*j+2]);
166 if (cj >= 0 && cj < (Idx)size())
167 add_neighbors(i, p, cj, N);
168 }
169 }
170};
171
172 }
173}
void build(Idx nr_points, const Func &pnts)
before calling the build function, ensure that the bounding box has been set with set_box or computed...
Definition grid.h:71
the cgv namespace
Definition print.h:11