Skip to content

Commit 5a72824

Browse files
committed
much happier with the walk grid method now
1 parent 3a2530c commit 5a72824

File tree

3 files changed

+66
-136
lines changed

3 files changed

+66
-136
lines changed

raylib/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ set(SOURCES
108108
)
109109

110110
get_target_property(SIMPLE_FFT_INCLUDE_DIRS simple_fft INTERFACE_INCLUDE_DIRECTORIES)
111-
add_compile_options("-fPIC" -O0)
111+
add_compile_options("-fPIC")
112112

113113
if(WITH_QHULL)
114114
set(QHULL_LIBS

raylib/raydecimation.cpp

Lines changed: 9 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,6 @@ bool decimateSpatioTemporal(const std::string &file_stub, double vox_width, int
164164
return true;
165165
}
166166

167-
int sign(double x)
168-
{
169-
return (x > 0.0) - (x < 0.0);
170-
}
171167

172168
bool decimateRaysSpatial(const std::string &file_stub, double vox_width)
173169
{
@@ -177,148 +173,26 @@ bool decimateRaysSpatial(const std::string &file_stub, double vox_width)
177173

178174
// By maintaining these buffers below, we avoid almost all memory fragmentation
179175
ray::Cloud chunk;
180-
std::vector<int64_t> subsample;
181-
std::set<Eigen::Vector3i, ray::Vector3iLess> voxel_set;
182176

177+
Subsampler subsampler;
183178
auto decimate = [&](std::vector<Eigen::Vector3d> &starts, std::vector<Eigen::Vector3d> &ends,
184179
std::vector<double> &times, std::vector<ray::RGBA> &colours)
185180
{
186181
double width = 0.01 * vox_width;
187-
subsample.clear();
182+
subsampler.subsample.clear();
188183
for (int i = 0; i < (int)ends.size(); i++)
189184
{
190-
// #define END_FIRST // by traversing from end to start we match the existence of the ray more to the free space near the end point. In building1 test start first found more ray locations
185+
#define END_FIRST // Testing on building.ply it finds more rays, so deemed to be more successful at filling space
191186
#if defined END_FIRST
192-
Eigen::Vector3d dir = starts[i] - ends[i];
193-
const Eigen::Vector3d source = ends[i] / width;
194-
const Eigen::Vector3d target = starts[i] / width;
187+
walkGrid(ends[i] / width, starts[i] / width, subsampler, i);
195188
#else
196-
Eigen::Vector3d dir = ends[i] - starts[i];
197-
const Eigen::Vector3d source = starts[i] / width;
198-
const Eigen::Vector3d target = ends[i] / width;
199-
#endif
200-
201-
#define OLD_METHOD
202-
#if defined OLD_METHOD
203-
const double length = dir.norm();
204-
dir /= length;
205-
for (int a = 0; a<3; a++)
206-
{
207-
if (dir[a] == 0.0)
208-
{
209-
dir[a] = 1e-10; // prevent division by 0
210-
}
211-
}
212-
const double eps = 1e-9; // to stay away from edge cases
213-
const double maxDist = (target - source).norm();
214-
215-
// cached values to speed up the loop below
216-
Eigen::Vector3i adds;
217-
Eigen::Vector3d offsets;
218-
for (int k = 0; k < 3; ++k)
219-
{
220-
if (dir[k] > 0.0)
221-
{
222-
adds[k] = 1;
223-
offsets[k] = 0.5;
224-
}
225-
else
226-
{
227-
adds[k] = -1;
228-
offsets[k] = -0.5;
229-
}
230-
}
231-
232-
Eigen::Vector3d p = source; // our moving variable as we walk over the grid
233-
Eigen::Vector3i inds((int)std::floor(p[0]), (int)std::floor(p[1]), (int)std::floor(p[2]));
234-
if (voxel_set.insert(inds).second)
235-
{
236-
subsample.push_back(i);
237-
continue;
238-
}
239-
double depth = 0;
240-
// for every ray, walk over its length and if there is a free space then add it
241-
do
242-
{
243-
double ls[3] = { (std::round(p[0] + offsets[0]) - p[0]) / dir[0], (std::round(p[1] + offsets[1]) - p[1]) / dir[1],
244-
(std::round(p[2] + offsets[2]) - p[2]) / dir[2] };
245-
int axis = (ls[0] < ls[1] && ls[0] < ls[2]) ? 0 : (ls[1] < ls[2] ? 1 : 2);
246-
inds[axis] += adds[axis];
247-
depth += ls[axis] + eps;
248-
p = source + dir * depth;
249-
250-
if (voxel_set.insert(inds).second)
251-
{
252-
subsample.push_back(i);
253-
break; // only adding to one cell
254-
}
255-
} while (depth <= maxDist);
256-
#else
257-
Eigen::Vector3i p = Eigen::Vector3d(std::floor(source[0]), std::floor(source[1]), std::floor(source[2])).cast<int>();
258-
Eigen::Vector3i end = Eigen::Vector3d(std::floor(target[0]), std::floor(target[1]), std::floor(target[2])).cast<int>();
259-
260-
if (voxel_set.insert(p).second)
261-
{
262-
std::cout << "missed p: " << p.transpose() << " between " << source.transpose() << " and " << target.transpose() << std::endl;
263-
subsample.push_back(i);
264-
continue; // only adding to one cell
265-
}
266-
267-
Eigen::Vector3i step(sign(target[0] - source[0]), sign(target[1] - source[1]), sign(target[2] - source[2]));
268-
Eigen::Vector3d tmax, tdelta;
269-
for (int j = 0; j<3; j++)
270-
{
271-
step[j] = sign(target[j] - source[j]);
272-
double to = std::abs(source[j] - p[j] - (double)std::max(0, step[j]));
273-
double dir = std::max(std::numeric_limits<double>::min(), std::abs(source[j] - target[j]));
274-
tmax[j] = to / dir;
275-
tdelta[j] = 1.0 / dir;
276-
}
277-
278-
while (p != end)
279-
{
280-
int ax = tmax[0] < tmax[1] && tmax[0] < tmax[2] ? 0 : (tmax[1] < tmax[2] ? 1 : 2);
281-
p[ax] += step[ax];
282-
tmax[ax] += tdelta[ax];
283-
/* if (tmax[0] < tmax[1])
284-
{
285-
if (tmax[0] < tmax[2])
286-
{
287-
p[0] += step[0];
288-
tmax[0] += tdelta[0];
289-
}
290-
else
291-
{
292-
p[2] += step[2];
293-
tmax[2] += tdelta[2];
294-
}
295-
}
296-
else
297-
{
298-
if (tmax[1] < tmax[2])
299-
{
300-
p[1] += step[1];
301-
tmax[1] += tdelta[1];
302-
}
303-
else
304-
{
305-
p[2] += step[2];
306-
tmax[2] += tdelta[2];
307-
}
308-
}*/
309-
if (voxel_set.insert(p).second)
310-
{
311-
std::cout << "missed p: " << p.transpose() << " between " << source.transpose() << " and " << target.transpose() << std::endl;
312-
subsample.push_back(i);
313-
break; // only adding to one cell
314-
}
315-
}
316-
#endif
189+
walkGrid(starts[i] / width, ends[i] / width, subsampler, i);
190+
#endif
317191
}
318-
chunk.resize(subsample.size());
319-
for (int64_t i = 0; i < (int64_t)subsample.size(); i++)
192+
chunk.resize(subsampler.subsample.size());
193+
for (int64_t i = 0; i < (int64_t)subsampler.subsample.size(); i++)
320194
{
321-
int64_t id = subsample[i];
195+
int64_t id = subsampler.subsample[i];
322196
chunk.starts[i] = starts[id];
323197
chunk.ends[i] = ends[id];
324198
chunk.colours[i] = colours[id];

raylib/raydecimation.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,62 @@ bool RAYLIB_EXPORT decimateRaysSpatial(const std::string &file_stub, double vox_
3636
/// @brief decimate to no more than 1 point per voxel of width @c radius_per_length x ray length.
3737
/// This is used when error is proportional to ray length, prioritising closer measurements and leaving distant areas sparse
3838
bool RAYLIB_EXPORT decimateAngular(const std::string &file_stub, double radius_per_length);
39+
40+
41+
struct Subsampler
42+
{
43+
inline bool operator()(const Eigen::Vector3i &p, int i)
44+
{
45+
if (voxel_set.insert(p).second)
46+
{
47+
subsample.push_back(i);
48+
return true;
49+
}
50+
return false;
51+
}
52+
std::vector<int64_t> subsample;
53+
std::set<Eigen::Vector3i, ray::Vector3iLess> voxel_set;
54+
};
55+
56+
inline int sign(double x)
57+
{
58+
return (x > 0.0) - (x < 0.0);
59+
}
60+
61+
// for similar appraoch see: https://github.com/StrandedKitty/tiles-intersect/blob/master/src/index.js
62+
template<class T>
63+
void walkGrid(const Eigen::Vector3d &start, const Eigen::Vector3d &end, T &object, int i)
64+
{
65+
Eigen::Vector3i p = Eigen::Vector3d(std::floor(start[0]), std::floor(start[1]), std::floor(start[2])).cast<int>();
66+
67+
if (object(p, i))
68+
{
69+
return; // only adding to one cell
70+
}
71+
72+
Eigen::Vector3i step(sign(end[0] - start[0]), sign(end[1] - start[1]), sign(end[2] - start[2]));
73+
Eigen::Vector3d tmax, tdelta;
74+
for (int j = 0; j<3; j++)
75+
{
76+
step[j] = sign(end[j] - start[j]);
77+
double to = std::abs(start[j] - p[j] - (double)std::max(0, step[j]));
78+
double dir = std::max(std::numeric_limits<double>::min(), std::abs(start[j] - end[j]));
79+
tmax[j] = to / dir;
80+
tdelta[j] = 1.0 / dir;
81+
}
82+
83+
Eigen::Vector3i target = Eigen::Vector3d(std::floor(end[0]), std::floor(end[1]), std::floor(end[2])).cast<int>();
84+
while (p != target)
85+
{
86+
int ax = tmax[0] < tmax[1] && tmax[0] < tmax[2] ? 0 : (tmax[1] < tmax[2] ? 1 : 2);
87+
p[ax] += step[ax];
88+
tmax[ax] += tdelta[ax];
89+
if (object(p, i))
90+
{
91+
break; // only adding to one cell
92+
}
93+
}
94+
}
3995
} // namespace ray
4096

4197
#endif // RAYLIB_RAYDECIMATION_H

0 commit comments

Comments
 (0)