24 #include <tbb/parallel_for.h>
25 #include <tbb/task_arena.h>
39 const bool is_fill_agg);
41 template <RasterAggType AggType>
46 template <
typename Z,
typename Z2>
47 void operator()(
const Z2& input_z, Z& output_z,
const Z2 input_sentinel)
const {
48 if (input_z != input_sentinel) {
49 output_z = output_z == std::numeric_limits<Z>::lowest() ? 1 : output_z + 1;
56 template <
typename Z,
typename Z2>
57 void operator()(
const Z2& input_z, Z& output_z,
const Z2 input_sentinel)
const {
58 if (input_z != input_sentinel && input_z > output_z) {
66 template <
typename Z,
typename Z2>
67 void operator()(
const Z2& input_z, Z& output_z,
const Z2 input_sentinel)
const {
68 if (input_z != input_sentinel && input_z < output_z) {
76 template <
typename Z,
typename Z2>
77 void operator()(
const Z2& input_z, Z& output_z,
const Z2 input_sentinel)
const {
78 if (input_z != input_sentinel) {
80 output_z == std::numeric_limits<Z>::lowest() ? input_z : output_z + input_z;
89 template <
typename T,
typename Z>
116 template <
typename T2,
typename Z2>
121 const double bin_dim_meters,
122 const bool geographic_coords,
123 const bool align_bins_to_zero_based_grid);
125 template <
typename T2,
typename Z2>
129 const std::vector<RasterAggType>& raster_agg_types,
130 const double bin_dim_meters,
131 const bool geographic_coords,
132 const bool align_bins_to_zero_based_grid);
134 template <
typename T2,
typename Z2>
139 const double bin_dim_meters,
140 const bool geographic_coords,
141 const bool align_bins_to_zero_based_grid,
163 const int64_t y_bin)
const {
168 return std::make_pair(bin_idx,
z_[bin_idx]);
172 if (x < x_min_ || x >
x_max_ || y < y_min_ || y >
y_max_) {
182 return std::make_pair(x, y);
186 const int64_t source_y_bin,
187 const Z source_z_offset)
const;
190 const int64_t source_y_bin,
191 const Z source_z_offset,
192 const int64_t z_col_idx)
const;
199 template <
typename T2,
typename Z2>
203 std::vector<Z>& output_z,
208 const int64_t neighborhood_fill_radius,
209 const bool fill_only_nulls,
213 const bool fill_only_nulls,
219 const int64_t num_bins_radius,
220 std::vector<Z>& neighboring_bins)
const;
222 const std::vector<Z>& neighboring_cells,
223 const bool compute_slope_in_degrees)
const;
226 const bool compute_slope_in_degrees)
const;
232 const int64_t band_idx = 0)
const;
236 const int64_t band_idx)
const;
247 const int64_t neighborhood_null_fill_radius)
const;
252 template <RasterAggType AggType,
typename T2,
typename Z2>
256 std::vector<Z>& output_z);
258 template <RasterAggType AggType>
260 std::vector<Z>& output_z,
261 const Z agg_sentinel);
263 template <RasterAggType AggType,
typename T2,
typename Z2>
267 std::vector<Z>& output_z,
271 const int64_t y_centroid_bin,
272 const int64_t bins_radius,
273 std::vector<Z>& z)
const;
275 template <RasterAggType AggType>
277 const int64_t y_centroid_bin,
278 const int64_t bins_radius,
280 std::vector<Z>& z)
const;
282 template <RasterAggType AggType>
284 const bool fill_only_nulls,
287 const bool fill_only_nulls,
294 template <
typename T,
typename Z>
295 template <
typename T2,
typename Z2>
300 const double bin_dim_meters,
301 const bool geographic_coords,
302 const bool align_bins_to_zero_based_grid)
303 : bin_dim_meters_(bin_dim_meters)
304 , geographic_coords_(geographic_coords)
306 , is_multi_z_(
false) {
308 const int64_t input_size{input_z.
size()};
309 if (input_size <= 0) {
318 x_max_ = min_max_x.second;
320 y_max_ = min_max_y.second;
336 template <
typename T,
typename Z>
337 template <
typename T2,
typename Z2>
341 const std::vector<RasterAggType>& raster_agg_types,
342 const double bin_dim_meters,
343 const bool geographic_coords,
344 const bool align_bins_to_zero_based_grid)
345 : bin_dim_meters_(bin_dim_meters)
346 , geographic_coords_(geographic_coords)
348 , is_multi_z_(
true) {
350 const int64_t input_size{input_x.
size()};
351 const int64_t num_z_cols = input_z_cols.
numCols();
352 if (num_z_cols != static_cast<int64_t>(raster_agg_types.size())) {
353 throw std::runtime_error(
"Number of z cols and raster_agg_types do not match.");
355 if (input_size <= 0) {
365 x_max_ = min_max_x.second;
367 y_max_ = min_max_y.second;
380 for (int64_t z_col_idx = 0; z_col_idx < num_z_cols; ++z_col_idx) {
383 input_z_cols[z_col_idx],
385 raster_agg_types[z_col_idx],
393 template <
typename T,
typename Z>
394 template <
typename T2,
typename Z2>
399 const double bin_dim_meters,
400 const bool geographic_coords,
401 const bool align_bins_to_zero_based_grid,
406 : bin_dim_meters_(bin_dim_meters)
407 , geographic_coords_(geographic_coords)
428 template <
typename T,
typename Z>
430 const int64_t source_y_bin,
431 const Z source_z_offset)
const {
432 if (is_bin_out_of_bounds(source_x_bin, source_y_bin)) {
433 return null_sentinel_;
436 if (terrain_z == null_sentinel_) {
439 return terrain_z + source_z_offset;
442 template <
typename T,
typename Z>
444 const int64_t source_y_bin,
445 const Z source_z_offset,
446 const int64_t z_col_idx)
const {
447 if (is_bin_out_of_bounds(source_x_bin, source_y_bin)) {
448 return null_sentinel_;
452 if (terrain_z == null_sentinel_) {
455 return terrain_z + source_z_offset;
458 template <
typename T,
typename Z>
460 x_min_ = std::floor(x_min_ / bin_dim_meters_) * bin_dim_meters_;
461 x_max_ = std::floor(x_max_ / bin_dim_meters_) * bin_dim_meters_ +
463 y_min_ = std::floor(y_min_ / bin_dim_meters_) * bin_dim_meters_;
464 y_max_ = std::floor(y_max_ / bin_dim_meters_) * bin_dim_meters_ +
468 template <
typename T,
typename Z>
470 x_min_ = std::floor(x_min_ / bin_dim_meters_) * bin_dim_meters_;
471 x_max_ = std::ceil(x_max_ / bin_dim_meters_) * bin_dim_meters_;
472 y_min_ = std::floor(y_min_ / bin_dim_meters_) * bin_dim_meters_;
473 y_max_ = std::ceil(y_max_ / bin_dim_meters_) * bin_dim_meters_;
476 template <
typename T,
typename Z>
478 CHECK_GT(bin_dim_meters_, static_cast<T>(0));
479 x_range_ = x_max_ - x_min_;
480 y_range_ = y_max_ - y_min_;
481 if (geographic_coords_) {
482 const T x_centroid = (x_min_ + x_max_) * 0.5;
483 const T y_centroid = (y_min_ + y_max_) * 0.5;
484 x_meters_per_degree_ =
487 y_meters_per_degree_ =
490 num_x_bins_ = x_range_ * x_meters_per_degree_ / bin_dim_meters_;
491 num_y_bins_ = y_range_ * y_meters_per_degree_ / bin_dim_meters_;
493 if (num_x_bins_ < 1 || num_y_bins_ < 1) {
494 throw std::runtime_error(
"Invalid GeoRaster (" +
std::to_string(num_x_bins_) +
"x" +
498 x_scale_input_to_bin_ = x_meters_per_degree_ / bin_dim_meters_;
499 y_scale_input_to_bin_ = y_meters_per_degree_ / bin_dim_meters_;
500 x_scale_bin_to_input_ = bin_dim_meters_ / x_meters_per_degree_;
501 y_scale_bin_to_input_ = bin_dim_meters_ / y_meters_per_degree_;
504 num_x_bins_ = x_range_ / bin_dim_meters_;
505 num_y_bins_ = y_range_ / bin_dim_meters_;
507 if (num_x_bins_ < 1 || num_y_bins_ < 1) {
508 throw std::runtime_error(
"Invalid GeoRaster (" +
std::to_string(num_x_bins_) +
"x" +
512 x_scale_input_to_bin_ = 1.0 / bin_dim_meters_;
513 y_scale_input_to_bin_ = 1.0 / bin_dim_meters_;
514 x_scale_bin_to_input_ = bin_dim_meters_;
515 y_scale_bin_to_input_ = bin_dim_meters_;
517 num_bins_ = num_x_bins_ * num_y_bins_;
520 template <
typename T,
typename Z>
521 template <RasterAggType AggType,
typename T2,
typename Z2>
525 std::vector<Z>& output_z) {
527 const int64_t input_size{input_z.
size()};
529 : std::numeric_limits<Z>::lowest();
530 output_z.resize(num_bins_, agg_sentinel);
532 for (int64_t sparse_idx = 0; sparse_idx != input_size; ++sparse_idx) {
533 auto const z = input_z[sparse_idx];
534 if constexpr (std::is_same_v<Z2, float> || std::is_same_v<Z2, double>) {
535 if (std::isnan(z) || std::isinf(z)) {
539 const int64_t x_bin = get_x_bin(input_x[sparse_idx]);
540 const int64_t y_bin = get_y_bin(input_y[sparse_idx]);
541 if (x_bin < 0 || x_bin >= num_x_bins_ || y_bin < 0 || y_bin >= num_y_bins_) {
545 compute_agg(z, output_z[bin_idx], inline_null_value<Z2>());
547 for (int64_t bin_idx = 0; bin_idx != num_bins_; ++bin_idx) {
548 if (output_z[bin_idx] == agg_sentinel) {
549 output_z[bin_idx] = null_sentinel_;
554 template <
typename T,
typename Z>
555 template <RasterAggType AggType>
557 const std::vector<std::vector<Z>>& z_inputs,
558 std::vector<Z>& output_z,
559 const Z agg_sentinel) {
560 const size_t num_inputs = z_inputs.size();
561 output_z.resize(num_bins_, agg_sentinel);
565 tbb::blocked_range<size_t>(0, num_bins_), [&](
const tbb::blocked_range<size_t>& r) {
566 const size_t start_idx = r.begin();
567 const size_t end_idx = r.end();
568 for (
size_t bin_idx = start_idx; bin_idx != end_idx; ++bin_idx) {
569 for (
size_t input_idx = 0; input_idx < num_inputs; ++input_idx) {
570 reduction_agg(z_inputs[input_idx][bin_idx], output_z[bin_idx], agg_sentinel);
576 [&](
const tbb::blocked_range<size_t>& r) {
577 const size_t start_idx = r.begin();
578 const size_t end_idx = r.end();
579 for (
size_t bin_idx = start_idx; bin_idx != end_idx; ++bin_idx) {
580 if (output_z[bin_idx] == agg_sentinel) {
581 output_z[bin_idx] = null_sentinel_;
587 template <
typename T,
typename Z>
588 template <RasterAggType AggType,
typename T2,
typename Z2>
592 std::vector<Z>& output_z,
594 const size_t input_size = input_z.
size();
595 const size_t max_thread_count = std::thread::hardware_concurrency();
596 const size_t num_threads_by_input_elements =
597 std::min(max_thread_count,
598 ((input_size + max_inputs_per_thread - 1) / max_inputs_per_thread));
599 const size_t num_threads_by_output_size =
601 const size_t num_threads =
602 std::min(num_threads_by_input_elements, num_threads_by_output_size);
603 if (num_threads <= 1) {
604 computeSerialImpl<AggType, T2, Z2>(input_x, input_y, input_z, output_z);
609 std::vector<std::vector<Z>> per_thread_z_outputs(num_threads);
612 : std::numeric_limits<Z>::lowest();
615 [&](
const tbb::blocked_range<size_t>& r) {
616 for (
size_t t = r.begin(); t != r.end(); ++t) {
617 per_thread_z_outputs[t].resize(num_bins_, agg_sentinel);
622 tbb::task_arena limited_arena(num_threads);
623 limited_arena.execute([&] {
625 tbb::blocked_range<int64_t>(0, input_size),
626 [&](
const tbb::blocked_range<int64_t>& r) {
627 const int64_t start_idx = r.begin();
628 const int64_t end_idx = r.end();
629 size_t thread_idx = tbb::this_task_arena::current_thread_index();
630 std::vector<Z>& this_thread_z_output = per_thread_z_outputs[thread_idx];
632 for (int64_t sparse_idx = start_idx; sparse_idx != end_idx; ++sparse_idx) {
633 auto const z = input_z[sparse_idx];
634 if constexpr (std::is_same_v<Z2, float> || std::is_same_v<Z2, double>) {
635 if (std::isnan(z) || std::isinf(z)) {
639 const int64_t x_bin = get_x_bin(input_x[sparse_idx]);
640 const int64_t y_bin = get_y_bin(input_y[sparse_idx]);
641 if (x_bin < 0 || x_bin >= num_x_bins_ || y_bin < 0 || y_bin >= num_y_bins_) {
645 compute_agg(z, this_thread_z_output[bin_idx], inline_null_value<Z2>());
653 computeParallelReductionAggImpl<RasterAggType::SUM>(
654 per_thread_z_outputs, output_z, agg_sentinel);
656 computeParallelReductionAggImpl<AggType>(
657 per_thread_z_outputs, output_z, agg_sentinel);
661 template <
typename T,
typename Z>
662 template <
typename T2,
typename Z2>
666 std::vector<Z>& output_z,
669 switch (raster_agg_type) {
671 computeParallelImpl<RasterAggType::COUNT, T2, Z2>(
676 computeParallelImpl<RasterAggType::MIN, T2, Z2>(
681 computeParallelImpl<RasterAggType::MAX, T2, Z2>(
686 computeParallelImpl<RasterAggType::SUM, T2, Z2>(
691 computeParallelImpl<RasterAggType::SUM, T2, Z2>(
693 computeParallelImpl<RasterAggType::COUNT, T2, Z2>(
696 [&](
const tbb::blocked_range<size_t>& r) {
697 const size_t start_idx = r.begin();
698 const size_t end_idx = r.end();
699 for (
size_t bin_idx = start_idx; bin_idx != end_idx;
703 if (counts_[bin_idx] > 1) {
704 output_z[bin_idx] /= counts_[bin_idx];
716 template <
typename T,
typename Z>
718 const int64_t y_centroid_bin,
719 const int64_t bins_radius,
720 std::vector<Z>& z)
const {
723 for (int64_t y_bin = y_centroid_bin - bins_radius;
724 y_bin <= y_centroid_bin + bins_radius;
726 for (int64_t x_bin = x_centroid_bin - bins_radius;
727 x_bin <= x_centroid_bin + bins_radius;
729 if (x_bin >= 0 && x_bin < num_x_bins_ && y_bin >= 0 && y_bin < num_y_bins_) {
731 const Z bin_val = z[bin_idx];
732 if (bin_val != null_sentinel_) {
739 return (count == 0) ? null_sentinel_ : val / count;
744 template <
typename T,
typename Z>
746 const int64_t neighborhood_fill_radius,
747 const bool fill_only_nulls,
749 const double sigma = neighborhood_fill_radius * 2.0 / 6.0;
750 const auto gaussian_kernel =
752 std::vector<Z> only_nulls_source_z;
753 if (fill_only_nulls) {
755 only_nulls_source_z.resize(z.size());
757 [&](
const tbb::blocked_range<int64_t>& r) {
758 const int64_t end_bin_idx = r.end();
759 for (int64_t bin_idx = r.begin(); bin_idx < end_bin_idx;
761 only_nulls_source_z[bin_idx] = z[bin_idx];
765 auto& source_z = fill_only_nulls ? only_nulls_source_z : z;
767 std::vector<Z> new_z(num_bins_);
769 tbb::blocked_range<int64_t>(0, num_y_bins_),
770 [&](
const tbb::blocked_range<int64_t>& r) {
771 const int64_t end_y_bin = r.end();
772 for (int64_t y_start_bin = r.begin(); y_start_bin != end_y_bin; ++y_start_bin) {
773 for (int64_t x_bin = 0; x_bin < num_x_bins_; ++x_bin) {
776 for (int64_t y_offset = -neighborhood_fill_radius;
777 y_offset <= neighborhood_fill_radius;
779 const auto y_bin = y_start_bin + y_offset;
780 if (y_bin >= 0 && y_bin < num_y_bins_) {
782 const Z bin_val = source_z[bin_idx];
783 if (bin_val != null_sentinel_) {
784 const auto gaussian_weight =
785 gaussian_kernel[y_offset + neighborhood_fill_radius];
786 val += bin_val * gaussian_weight;
787 sum_weights += gaussian_weight;
792 new_z[bin_idx] = sum_weights > 0.0 ? (val / sum_weights) : null_sentinel_;
796 source_z.swap(new_z);
798 tbb::blocked_range<int64_t>(0, num_x_bins_),
799 [&](
const tbb::blocked_range<int64_t>& r) {
800 const int64_t end_x_bin = r.end();
801 for (int64_t x_start_bin = r.begin(); x_start_bin != end_x_bin; ++x_start_bin) {
802 for (int64_t y_bin = 0; y_bin < num_y_bins_; ++y_bin) {
805 for (int64_t x_offset = -neighborhood_fill_radius;
806 x_offset <= neighborhood_fill_radius;
808 const auto x_bin = x_start_bin + x_offset;
809 if (x_bin >= 0 && x_bin < num_x_bins_) {
811 const Z bin_val = source_z[bin_idx];
812 if (bin_val != null_sentinel_) {
813 const auto gaussian_weight =
814 gaussian_kernel[x_offset + neighborhood_fill_radius];
815 val += bin_val * gaussian_weight;
816 sum_weights += gaussian_weight;
821 new_z[bin_idx] = sum_weights > 0.0 ? (val / sum_weights) : null_sentinel_;
825 if (fill_only_nulls) {
829 [&](
const tbb::blocked_range<int64_t>& r) {
830 const int64_t end_bin_idx = r.end();
831 for (int64_t bin_idx = r.begin(); bin_idx < end_bin_idx;
833 if (z[bin_idx] == null_sentinel_) {
834 z[bin_idx] = new_z[bin_idx];
836 only_nulls_source_z[bin_idx] = z[bin_idx];
840 source_z.swap(new_z);
844 template <
typename T,
typename Z>
845 template <RasterAggType AggType>
847 const int64_t x_centroid_bin,
848 const int64_t y_centroid_bin,
849 const int64_t bins_radius,
851 std::vector<Z>& z)
const {
853 : std::numeric_limits<Z>::lowest();
855 for (int64_t y_bin = y_centroid_bin - bins_radius;
856 y_bin <= y_centroid_bin + bins_radius;
858 for (int64_t x_bin = x_centroid_bin - bins_radius;
859 x_bin <= x_centroid_bin + bins_radius;
861 if (x_bin >= 0 && x_bin < num_x_bins_ && y_bin >= 0 && y_bin < num_y_bins_) {
863 compute_agg(z[bin_idx], val, null_sentinel_);
867 return val == agg_sentinel ? null_sentinel_ : val;
870 template <
typename T,
typename Z>
871 template <RasterAggType AggType>
873 const int64_t neighborhood_fill_radius,
874 const bool fill_only_nulls,
879 std::vector<Z> new_z(num_bins_);
882 [&](
const tbb::blocked_range<int64_t>& r) {
883 const int64_t end_y_bin = r.end();
884 for (int64_t y_bin = r.begin(); y_bin != end_y_bin; ++y_bin) {
885 for (int64_t x_bin = 0; x_bin < num_x_bins_; ++x_bin) {
886 const int64_t bin_idx =
888 const Z z_val = z[bin_idx];
889 if (!fill_only_nulls || z_val == null_sentinel_) {
891 new_z[bin_idx] = fill_bin_from_avg_box_neighborhood(
892 x_bin, y_bin, neighborhood_fill_radius, z);
894 new_z[bin_idx] = fill_bin_from_box_neighborhood(
895 x_bin, y_bin, neighborhood_fill_radius, compute_agg, z);
898 new_z[bin_idx] = z_val;
906 template <
typename T,
typename Z>
908 const bool fill_only_nulls,
910 fill_bins_from_neighbors(
911 neighborhood_fill_radius, fill_only_nulls, raster_fill_agg_type, z_);
914 template <
typename T,
typename Z>
916 const bool fill_only_nulls,
926 switch (raster_fill_agg_type) {
928 fill_bins_from_box_neighborhood<RasterAggType::COUNT>(
929 neighborhood_fill_radius, fill_only_nulls, z);
933 fill_bins_from_box_neighborhood<RasterAggType::MIN>(
934 neighborhood_fill_radius, fill_only_nulls, z);
938 fill_bins_from_box_neighborhood<RasterAggType::MAX>(
939 neighborhood_fill_radius, fill_only_nulls, z);
943 fill_bins_from_box_neighborhood<RasterAggType::SUM>(
944 neighborhood_fill_radius, fill_only_nulls, z);
948 fill_bins_from_box_neighborhood<RasterAggType::BOX_AVG>(
949 neighborhood_fill_radius, fill_only_nulls, z);
954 fill_bins_from_gaussian_neighborhood(neighborhood_fill_radius, fill_only_nulls, z);
963 template <
typename T,
typename Z>
967 const int64_t num_bins_radius,
968 std::vector<Z>& neighboring_bins)
const {
969 const size_t num_bins_per_dim = num_bins_radius * 2 + 1;
970 CHECK_EQ(neighboring_bins.size(), num_bins_per_dim * num_bins_per_dim);
971 const int64_t end_y_bin_idx = y_bin + num_bins_radius;
972 const int64_t end_x_bin_idx = x_bin + num_bins_radius;
973 size_t output_bin = 0;
974 for (int64_t y_bin_idx = y_bin - num_bins_radius; y_bin_idx <= end_y_bin_idx;
976 for (int64_t x_bin_idx = x_bin - num_bins_radius; x_bin_idx <= end_x_bin_idx;
978 if (x_bin_idx < 0 || x_bin_idx >= num_x_bins_ || y_bin_idx < 0 ||
979 y_bin_idx >= num_y_bins_) {
983 neighboring_bins[output_bin++] = z_[bin_idx];
984 if (z_[bin_idx] == null_sentinel_) {
992 template <
typename T,
typename Z>
994 const std::vector<Z>& neighboring_cells,
995 const bool compute_slope_in_degrees)
const {
997 ((neighboring_cells[8] + 2 * neighboring_cells[5] + neighboring_cells[2]) -
998 (neighboring_cells[6] + 2 * neighboring_cells[3] + neighboring_cells[0])) /
999 (8 * bin_dim_meters_);
1001 ((neighboring_cells[6] + 2 * neighboring_cells[7] + neighboring_cells[8]) -
1002 (neighboring_cells[0] + 2 * neighboring_cells[1] + neighboring_cells[2])) /
1003 (8 * bin_dim_meters_);
1004 const Z slope = sqrt(dz_dx * dz_dx + dz_dy * dz_dy);
1005 std::pair<Z, Z> slope_and_aspect;
1006 slope_and_aspect.first =
1008 if (slope < 0.0001) {
1009 slope_and_aspect.second = null_sentinel_;
1011 const Z aspect_degrees =
1013 slope_and_aspect.second = aspect_degrees + 180.0;
1016 return slope_and_aspect;
1019 template <
typename T,
typename Z>
1023 const bool compute_slope_in_degrees)
const {
1027 tbb::blocked_range<int64_t>(0, num_y_bins_),
1028 [&](
const tbb::blocked_range<int64_t>& r) {
1029 std::vector<Z> neighboring_z_vals(9);
1030 for (int64_t y_bin = r.begin(); y_bin != r.end(); ++y_bin) {
1031 for (int64_t x_bin = 0; x_bin < num_x_bins_; ++x_bin) {
1032 const bool not_null =
1033 get_nxn_neighbors_if_not_null(x_bin, y_bin, 1, neighboring_z_vals);
1039 const auto slope_and_aspect = calculate_slope_and_aspect_of_cell(
1040 neighboring_z_vals, compute_slope_in_degrees);
1041 slope[bin_idx] = slope_and_aspect.first;
1042 if (slope_and_aspect.second == null_sentinel_) {
1045 aspect[bin_idx] = slope_and_aspect.second;
1053 template <
typename T,
typename Z>
1059 const int64_t neighborhood_null_fill_radius)
const {
1063 tbb::blocked_range<int64_t>(0, num_y_bins_),
1064 [&](
const tbb::blocked_range<int64_t>& r) {
1065 for (int64_t y_bin = r.begin(); y_bin != r.end(); ++y_bin) {
1066 for (int64_t x_bin = 0; x_bin < num_x_bins_; ++x_bin) {
1068 output_x[bin_idx] = x_min_ + (x_bin + 0.5) * x_scale_bin_to_input_;
1069 output_y[bin_idx] = y_min_ + (y_bin + 0.5) * y_scale_bin_to_input_;
1070 const Z z_val = z_[bin_idx];
1071 if (z_val == null_sentinel_) {
1073 if (neighborhood_null_fill_radius) {
1074 const Z avg_neighbor_value = fill_bin_from_avg_box_neighborhood(
1075 x_bin, y_bin, neighborhood_null_fill_radius);
1076 if (avg_neighbor_value != null_sentinel_) {
1077 output_z[bin_idx] = avg_neighbor_value;
1081 output_z[bin_idx] = z_[bin_idx];
1089 template <
typename T,
typename Z>
1094 const int64_t band_idx)
const {
1095 const std::vector<Z>& z = z_cols_.empty() ? z_ : z_cols_[band_idx];
1100 tbb::blocked_range<int64_t>(0, num_y_bins_),
1101 [&](
const tbb::blocked_range<int64_t>& r) {
1102 for (int64_t y_bin = r.begin(); y_bin != r.end(); ++y_bin) {
1103 for (int64_t x_bin = 0; x_bin < num_x_bins_; ++x_bin) {
1105 output_x[bin_idx] = x_min_ + (x_bin + 0.5) * x_scale_bin_to_input_;
1106 output_y[bin_idx] = y_min_ + (y_bin + 0.5) * y_scale_bin_to_input_;
1107 const Z z_val = z[bin_idx];
1108 if (z_val == null_sentinel_) {
1111 output_z[bin_idx] = z_val;
1119 template <
typename T,
typename Z>
1122 const int64_t band_idx)
const {
1123 const std::vector<Z>& z = z_cols_.empty() ? z_ : z_cols_[band_idx];
1127 [&](
const tbb::blocked_range<int64_t>& r) {
1128 for (int64_t y_bin = r.begin(); y_bin != r.end(); ++y_bin) {
1129 for (int64_t x_bin = 0; x_bin < num_x_bins_; ++x_bin) {
1130 const int64_t bin_idx =
1132 const Z z_val = z[bin_idx];
1133 if (z_val == null_sentinel_) {
1136 output_z[bin_idx] = z_val;
1170 template <
typename T,
typename Z>
1176 const int64_t num_z_cols =
static_cast<int64_t
>(z_cols_.size());
1179 num_bins_ * num_z_cols);
1181 for (int64_t y_bin = 0; y_bin != num_y_bins_; ++y_bin) {
1182 for (int64_t x_bin = 0; x_bin < num_x_bins_; ++x_bin) {
1184 output_x[bin_idx] = x_min_ + (x_bin + 0.5) * x_scale_bin_to_input_;
1185 output_y[bin_idx] = y_min_ + (y_bin + 0.5) * y_scale_bin_to_input_;
1186 Array<Z> z_array = output_z.getItem(bin_idx, num_z_cols);
1187 for (int64_t z_col_idx = 0; z_col_idx < num_z_cols; ++z_col_idx) {
1188 const Z z_val = z_cols_[z_col_idx][bin_idx];
1189 z_array[z_col_idx] = z_val;
1196 template <
typename T,
typename Z>
1198 mgr.
set_metadata(
"geo_raster_num_x_bins", num_x_bins_);
1199 mgr.
set_metadata(
"geo_raster_num_y_bins", num_y_bins_);
1200 mgr.
set_metadata(
"geo_raster_x_min", static_cast<double>(x_min_));
1201 mgr.
set_metadata(
"geo_raster_y_min", static_cast<double>(y_min_));
1203 static_cast<double>(x_scale_input_to_bin_));
1205 static_cast<double>(y_scale_input_to_bin_));
1208 template <
typename T,
typename Z>
1215 const T bin_dim_meters,
1216 const bool geographic_coords,
1217 const int64_t neighborhood_fill_radius,
1218 const bool fill_only_nulls,
1232 if (neighborhood_fill_radius > 0) {
1234 neighborhood_fill_radius, fill_only_nulls, raster_fill_agg_type);
1253 template <
typename T,
typename Z>
1260 const T bin_dim_meters,
1261 const bool geographic_coords,
1262 const int64_t neighborhood_fill_radius,
1263 const bool fill_only_nulls,
1269 const std::string error_msg =
1270 "Invalid Raster Aggregate Type: " + agg_type_str.
getString();
1271 return mgr.ERROR_MESSAGE(error_msg);
1281 neighborhood_fill_radius,
1302 template <
typename T,
typename Z>
1310 const T bin_dim_meters,
1311 const bool geographic_coords,
1312 const int64_t neighborhood_fill_radius,
1313 const bool fill_only_nulls,
1319 const std::string error_msg =
1320 "Invalid Raster Aggregate Type: " + agg_type_str.
getString();
1321 return mgr.ERROR_MESSAGE(error_msg);
1325 const std::string error_msg =
1326 "Invalid Raster Fill Aggregate Type: " + fill_agg_type_str.
getString();
1327 return mgr.ERROR_MESSAGE(error_msg);
1334 raster_fill_agg_type,
1337 neighborhood_fill_radius,
1359 template <
typename T,
typename Z>
1367 const T bin_dim_meters,
1368 const bool geographic_coords,
1369 const int64_t neighborhood_fill_radius,
1370 const bool fill_only_nulls,
1380 const std::string error_msg =
1381 "Invalid Raster Aggregate Type: " + agg_type_str.
getString();
1382 return mgr.ERROR_MESSAGE(error_msg);
1386 const std::string error_msg =
1387 "Invalid Raster Fill Aggregate Type: " + fill_agg_type_str.
getString();
1388 return mgr.ERROR_MESSAGE(error_msg);
1405 if (neighborhood_fill_radius > 0) {
1407 neighborhood_fill_radius, fill_only_nulls, raster_fill_agg_type);
1427 template <
typename T,
typename Z>
1435 const T bin_dim_meters,
1436 const bool geographic_coords,
1437 const int64_t neighborhood_fill_radius,
1438 const bool fill_only_nulls,
1442 const int64_t num_z_cols = input_z_cols.
numCols();
1443 const auto agg_types_strs =
split(agg_types_str.
getString(),
"|");
1444 const auto fill_agg_types_strs =
split(fill_agg_types_str.
getString(),
"|");
1445 if (num_z_cols != static_cast<int64_t>(agg_types_strs.size()) ||
1446 num_z_cols != static_cast<int64_t>(fill_agg_types_strs.size())) {
1447 const std::string error_msg =
1448 "Mismatch between number of cols and number of agg or fill agg types.";
1449 return mgr.ERROR_MESSAGE(error_msg);
1452 auto get_agg_types = [](
const std::vector<std::string>& agg_types_strs,
1453 const bool is_fill_agg) {
1454 std::vector<RasterAggType> agg_types;
1455 for (
const auto& agg_type_str : agg_types_strs) {
1458 throw std::runtime_error(
"Invalid agg type");
1464 std::vector<RasterAggType> raster_agg_types;
1465 std::vector<RasterAggType> raster_fill_agg_types;
1467 raster_agg_types = get_agg_types(agg_types_strs,
false);
1468 raster_fill_agg_types = get_agg_types(fill_agg_types_strs,
true);
1469 }
catch (std::exception& e) {
1470 return mgr.ERROR_MESSAGE(e.what());
1482 if (neighborhood_fill_radius > 0) {
1483 for (int64_t z_col_idx = 0; z_col_idx < num_z_cols; ++z_col_idx) {
1486 raster_fill_agg_types[z_col_idx],
1487 geo_raster.
z_cols_[z_col_idx]);
1507 template <
typename T,
typename Z>
1514 const T bin_dim_meters,
1515 const bool geographic_coords,
1516 const int64_t neighborhood_fill_radius,
1517 const bool fill_only_nulls,
1518 const bool compute_slope_in_degrees,
1526 const std::string error_msg =
1527 "Invalid Raster Aggregate Type: " + agg_type_str.
getString();
1528 return mgr.ERROR_MESSAGE(error_msg);
1540 if (neighborhood_fill_radius > 0) {
1545 const size_t output_rows =
1548 output_slope, output_aspect, compute_slope_in_degrees);
1552 #endif // __CUDACC__
TEMPLATE_NOINLINE int32_t tf_geo_rasterize__cpu_template(TableFunctionManager &mgr, const Column< T > &input_x, const Column< T > &input_y, const Column< Z > &input_z, const TextEncodingNone &agg_type_str, const T bin_dim_meters, const bool geographic_coords, const int64_t neighborhood_fill_radius, const bool fill_only_nulls, Column< T > &output_x, Column< T > &output_y, Column< Z > &output_z)
void set_output_row_size(int64_t num_rows)
TEMPLATE_NOINLINE int32_t tf_geo_multi_rasterize__cpu_template(TableFunctionManager &mgr, const Column< T > &input_x, const Column< T > &input_y, const ColumnList< Z > &input_z_cols, const TextEncodingNone &agg_types_str, const TextEncodingNone &fill_agg_types_str, const T bin_dim_meters, const bool geographic_coords, const int64_t neighborhood_fill_radius, const bool fill_only_nulls, Column< T > &output_x, Column< T > &output_y, Column< Array< Z >> &output_z)
constexpr double radians_to_degrees
Z offset_source_z_from_raster_z(const int64_t source_x_bin, const int64_t source_y_bin, const Z source_z_offset) const
bool get_nxn_neighbors_if_not_null(const int64_t x_bin, const int64_t y_bin, const int64_t num_bins_radius, std::vector< Z > &neighboring_bins) const
std::vector< std::vector< Z > > z_cols_
void set_output_array_values_total_number(int32_t index, int64_t output_array_values_total_number)
TEMPLATE_NOINLINE int32_t geo_rasterize_impl(TableFunctionManager &mgr, const Column< T > &input_x, const Column< T > &input_y, const Column< Z > &input_z, const RasterAggType raster_agg_type, const RasterAggType raster_fill_agg_type, const T bin_dim_meters, const bool geographic_coords, const int64_t neighborhood_fill_radius, const bool fill_only_nulls, Column< T > &output_x, Column< T > &output_y, Column< Z > &output_z)
void operator()(const Z2 &input_z, Z &output_z, const Z2 input_sentinel) const
const size_t max_temp_output_entries
int64_t get_bin_idx_for_xy_coords(const T x, const T y) const
void setMetadata(TableFunctionManager &mgr) const
std::pair< Z, Z > calculate_slope_and_aspect_of_cell(const std::vector< Z > &neighboring_cells, const bool compute_slope_in_degrees) const
std::pair< T, T > get_xy_coords_for_bin_idx(const int64_t bin_idx) const
std::string getString() const
NEVER_INLINE HOST std::pair< T, T > get_column_min_max(const Column< T > &col)
GeoRaster(const Column< T2 > &input_x, const Column< T2 > &input_y, const Column< Z2 > &input_z, const RasterAggType raster_agg_type, const double bin_dim_meters, const bool geographic_coords, const bool align_bins_to_zero_based_grid)
DEVICE int64_t size() const
DEVICE int64_t numCols() const
void operator()(const Z2 &input_z, Z &output_z, const Z2 input_sentinel) const
void fill_bins_from_neighbors(const int64_t neighborhood_fill_radius, const bool fill_only_nulls, const RasterAggType raster_agg_type=RasterAggType::GAUSS_AVG)
void computeParallelReductionAggImpl(const std::vector< std::vector< Z >> &z_inputs, std::vector< Z > &output_z, const Z agg_sentinel)
void fill_bins_from_box_neighborhood(const int64_t neighborhood_fill_radius, const bool fill_only_nulls, std::vector< Z > &z)
T get_y_bin(const T input) const
Z fill_bin_from_avg_box_neighborhood(const int64_t x_centroid_bin, const int64_t y_centroid_bin, const int64_t bins_radius, std::vector< Z > &z) const
RasterAggType get_raster_agg_type(const std::string &agg_type_str, const bool is_fill_agg)
T get_x_bin(const T input) const
bool is_bin_out_of_bounds(const int64_t x_bin, const int64_t y_bin) const
TEMPLATE_NOINLINE int32_t tf_geo_rasterize_slope__cpu_template(TableFunctionManager &mgr, const Column< T > &input_x, const Column< T > &input_y, const Column< Z > &input_z, const TextEncodingNone &agg_type_str, const T bin_dim_meters, const bool geographic_coords, const int64_t neighborhood_fill_radius, const bool fill_only_nulls, const bool compute_slope_in_degrees, Column< T > &output_x, Column< T > &output_y, Column< Z > &output_z, Column< Z > &output_slope, Column< Z > &output_aspect)
const size_t max_inputs_per_thread
DEVICE TextEncodingDict inline_null_value()
static constexpr int64_t BIN_OUT_OF_BOUNDS
void align_bins_max_exclusive()
std::vector< double > generate_1d_gaussian_kernel(const int64_t fill_radius, double sigma)
int64_t x_y_bin_to_bin_index(const int64_t x_bin, const int64_t y_bin, const int64_t num_x_bins)
const bool geographic_coords_
void operator()(const Z2 &input_z, Z &output_z, const Z2 input_sentinel) const
void calculate_slope_and_aspect(Column< Z > &slope, Column< Z > &aspect, const bool compute_slope_in_degrees) const
bool g_enable_smem_group_by true
void computeParallelImpl(const Column< T2 > &input_x, const Column< T2 > &input_y, const Column< Z2 > &input_z, std::vector< Z > &output_z, const size_t max_inputs_per_thread)
std::pair< int64_t, Z > get_bin_idx_and_z_val_for_xy_bin(const int64_t x_bin, const int64_t y_bin) const
int64_t outputDenseColumnsAndFill(TableFunctionManager &mgr, Column< T > &output_x, Column< T > &output_y, Column< Z > &output_z, const int64_t neighborhood_null_fill_radius) const
DEVICE void setNull(int64_t index)
bool is_null(const Z value) const
Z fill_bin_from_box_neighborhood(const int64_t x_centroid_bin, const int64_t y_centroid_bin, const int64_t bins_radius, const ComputeAgg< AggType > &compute_agg, std::vector< Z > &z) const
std::pair< int64_t, int64_t > bin_to_x_y_bin_indexes(const int64_t bin, const int64_t num_x_bins)
void parallel_for(const blocked_range< Int > &range, const Body &body, const Partitioner &p=Partitioner())
EXTENSION_NOINLINE double distance_in_meters(const double fromlon, const double fromlat, const double tolon, const double tolat)
Computes the distance, in meters, between two WGS-84 positions.
bool g_enable_watchdog false
void set_metadata(const std::string &key, const T &value)
#define DEBUG_TIMER(name)
void fill_bins_from_gaussian_neighborhood(const int64_t neighborhood_fill_radius, const bool fill_only_nulls, std::vector< Z > &z)
void align_bins_max_inclusive()
void operator()(const Z2 &input_z, Z &output_z, const Z2 input_sentinel) const
void compute(const Column< T2 > &input_x, const Column< T2 > &input_y, const Column< Z2 > &input_z, std::vector< Z > &output_z, const RasterAggType raster_agg_type, const size_t max_inputs_per_thread)
void calculate_bins_and_scales()
void computeSerialImpl(const Column< T2 > &input_x, const Column< T2 > &input_y, const Column< Z2 > &input_z, std::vector< Z > &output_z)
#define TEMPLATE_NOINLINE
int64_t outputDenseColumns(TableFunctionManager &mgr, Column< T > &output_x, Column< T > &output_y, Column< Z > &output_z, const int64_t band_idx=0) const
int64_t outputDenseColumn(TableFunctionManager &mgr, Column< Z > &output_z, const int64_t band_idx) const