99#include " raycuboid.h"
1010#include " raypose.h"
1111#include " rayutils.h"
12- #define FLAT_TOP_COMPENSATION // use a 2-medium model for the top of the cloud, so only the cloud's density is estimated, not the air above it
12+ #define FLAT_TOP_COMPENSATION // use a 2-medium model for the top of the cloud, so only the cloud's density is
13+ // estimated, not the air above it
1314
1415namespace ray
1516{
@@ -45,8 +46,8 @@ bool RAYLIB_EXPORT renderCloud(const std::string &cloud_file, const Cuboid &boun
4546#if RAYLIB_WITH_TIFF
4647// save to geotif format using floating-point per-channel colour data. This function passes a projection file in order
4748// to geolocate the image
48- bool RAYLIB_EXPORT writeGeoTiffFloat (const std::string &filename, int x, int y, const float *data, double pixel_width, bool scalar,
49- const std::string &projection_file, double origin_x, double origin_y);
49+ bool RAYLIB_EXPORT writeGeoTiffFloat (const std::string &filename, int x, int y, const float *data, double pixel_width,
50+ bool scalar, const std::string &projection_file, double origin_x, double origin_y);
5051#endif
5152
5253// / This is used for estimating the per-voxel density of a ray cloud
@@ -65,6 +66,23 @@ struct RAYLIB_EXPORT DensityGrid
6566 , voxel_width_(vox_width)
6667 , voxel_dims_(dims)
6768 {
69+ // 3D dimensions are stored in a vector of 32-bit signed ints. It's fairly
70+ // easy to overflow when calculating voxel counts or 1D indices. Make sure
71+ // this won't happen.
72+ const std::size_t voxel_count =
73+ static_cast <std::size_t >(dims[0 ]) * static_cast <std::size_t >(dims[1 ]) * static_cast <std::size_t >(dims[2 ]);
74+ if (voxel_count > static_cast <std::size_t >(std::numeric_limits<int >::max ()))
75+ {
76+ std::cerr << " dims[0]: " << dims[0 ] << ' \n ' ;
77+ std::cerr << " dims[1]: " << dims[1 ] << ' \n ' ;
78+ std::cerr << " dims[2]: " << dims[2 ] << ' \n ' ;
79+ std::cerr << " dims[0] * dims[1] * dims[2]: " << voxel_count << ' \n ' ;
80+ std::cerr << " std::numeric_limits<int>::max(): " << std::numeric_limits<int >::max () << ' \n ' ;
81+ throw std::runtime_error (" Dimensions given to ray::DensityGrid are too large. "
82+ " Their product must be less than std::numeric_limits<int>::max()." );
83+ }
84+
85+ // Allocate.
6886 voxels_.resize (dims[0 ] * dims[1 ] * dims[2 ]);
6987 peaks_.resize (dims[0 ] * dims[1 ], std::numeric_limits<double >::lowest ());
7088 }
@@ -111,13 +129,14 @@ struct RAYLIB_EXPORT DensityGrid
111129 inline int getIndexFromPos (const Eigen::Vector3d &pos) const ;
112130 // / Return the vector of density voxels
113131 inline const std::vector<Voxel> &voxels () const { return voxels_; }
114- inline Eigen::Vector3i dimensions (){ return voxel_dims_; }
115- inline Cuboid bounds (){ return bounds_; }
132+ inline Eigen::Vector3i dimensions () { return voxel_dims_; }
133+ inline Cuboid bounds () { return bounds_; }
116134 inline double voxelWidth () const { return voxel_width_; }
117135 // used in walking grid only
118- inline bool operator ()(const Eigen::Vector3i &p, const Eigen::Vector3i &target, double in_length, double out_length, double max_length);
136+ inline bool operator ()(const Eigen::Vector3i &p, const Eigen::Vector3i &target, double in_length, double out_length,
137+ double max_length);
119138
120- std::vector<double > peaks_; // highest points
139+ std::vector<double > peaks_; // highest points
121140private:
122141 Cuboid bounds_;
123142 std::vector<Voxel> voxels_;
@@ -137,7 +156,7 @@ double DensityGrid::Voxel::numerator() const
137156}
138157double DensityGrid::Voxel::denominator () const
139158{
140- const double eps = 1e-10 ; // avoid division by 0
159+ const double eps = 1e-10 ; // avoid division by 0
141160 return eps + num_rays_ * path_length_;
142161}
143162double DensityGrid::Voxel::density () const
@@ -146,7 +165,7 @@ double DensityGrid::Voxel::density() const
146165 {
147166 return 0.0 ;
148167 }
149- const double eps = 1e-10 ; // avoid division by 0
168+ const double eps = 1e-10 ; // avoid division by 0
150169 // below -1.0 should be -2.0 when min length is estimated (e.g. when initially air)
151170 return spherical_distribution_scale * (num_rays_ - 1.0 ) * num_hits_ / (eps + num_rays_ * path_length_);
152171}
@@ -184,20 +203,24 @@ int DensityGrid::getIndexFromPos(const Eigen::Vector3d &pos) const
184203 Eigen::Vector3d gridspace = (pos - bounds_.min_bound_ ) / voxel_width_;
185204 return getIndex (gridspace.cast <int >());
186205}
187- inline bool DensityGrid::operator ()(const Eigen::Vector3i &p, const Eigen::Vector3i &target, double in_length, double out_length, double max_length)
206+ inline bool DensityGrid::operator ()(const Eigen::Vector3i &p, const Eigen::Vector3i &target, double in_length,
207+ double out_length, double max_length)
188208{
189209 int index = getIndex (p);
190210 double end_length = std::min (out_length, max_length);
191211
192212#if defined FLAT_TOP_COMPENSATION
193213 int peak_id = p[0 ] + p[1 ] * voxel_dims_[0 ];
194214 double peak = peaks_[peak_id];
195- double in_height = source_[2 ] + dir_[2 ]* in_length;
196- double end_height = source_[2 ] + dir_[2 ]* end_length;
197- if (dir_[2 ] < 0.0 && in_height > peak && end_height <= peak) // currently only supported on downwards rays
215+ double in_height = source_[2 ] + dir_[2 ] * in_length;
216+ double end_height = source_[2 ] + dir_[2 ] * end_length;
217+ if (dir_[2 ] < 0.0 && in_height > peak && end_height <= peak) // currently only supported on downwards rays
198218 {
199- double t = (in_height - peak)/(in_height - end_height);
200- in_length += (end_length - in_length) * std::max (0.0 , std::min (t, 0.99 )); // 0.99 because 1 can cause very tiny distances, which can give density outliers
219+ double t = (in_height - peak) / (in_height - end_height);
220+ in_length +=
221+ (end_length - in_length) *
222+ std::max (0.0 ,
223+ std::min (t, 0.99 )); // 0.99 because 1 can cause very tiny distances, which can give density outliers
201224 }
202225#endif
203226
0 commit comments