OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CrossSectionTableFunctions Namespace Reference

Functions

template<typename TLL , typename TV >
int32_t tf_cross_section_1d_impl (TableFunctionManager &mgr, const Column< TLL > &lon, const Column< TLL > &lat, const Column< TV > &values, const TLL line_x1, const TLL line_y1, const TLL line_x2, const TLL line_y2, const int32_t num_points, Column< GeoLineString > &line)
 
template<typename TLL , typename TY , typename TV >
int32_t tf_cross_section_2d_impl (TableFunctionManager &mgr, const Column< TLL > &lon, const Column< TLL > &lat, const Column< TY > &y_axis, const Column< TV > &values, const TLL line_x1, const TLL line_y1, const TLL line_x2, const TLL line_y2, const int32_t num_points_x, const int32_t num_points_y, const TLL dwithin_distance, Column< TLL > &x, Column< TLL > &y, Column< TV > &color)
 

Function Documentation

template<typename TLL , typename TV >
int32_t CrossSectionTableFunctions::tf_cross_section_1d_impl ( TableFunctionManager mgr,
const Column< TLL > &  lon,
const Column< TLL > &  lat,
const Column< TV > &  values,
const TLL  line_x1,
const TLL  line_y1,
const TLL  line_x2,
const TLL  line_y2,
const int32_t  num_points,
Column< GeoLineString > &  line 
)

Definition at line 33 of file CrossSectionTableFunctions.hpp.

References CHECK_EQ, CHECK_GT, Column< T >::getPtr(), logger::INFO, LOG, LOG_IF, TableFunctionManager::set_output_array_values_total_number(), TableFunctionManager::set_output_row_size(), Column< T >::size(), timer_start(), timer_stop(), VLOG, and logger::WARNING.

42  {
43  // supported types
44  static_assert(std::is_same_v<double, TLL>);
45  static_assert(std::is_same_v<float, TV> || std::is_same_v<double, TV>);
46 
47  // validate sizes
48  CHECK_EQ(lon.size(), lat.size()) << "input column size mismatch";
49  CHECK_EQ(lon.size(), values.size()) << "input column size mismatch";
50 
51  // enforce parser validation
52  CHECK_GT(num_points, 1) << "num_points must be > 1";
53 
54  // any raster data?
55  if (values.size() == 0) {
56  // return LINESTRING EMPTY
58  mgr.set_output_row_size(1);
59  return 1;
60  }
61 
62  // report values (verbose only)
63  VLOG(2) << "tf_cross_section_1d: Input raster data has " << values.size()
64  << " values, min "
65  << *std::min_element(values.getPtr(), values.getPtr() + values.size())
66  << ", max "
67  << *std::max_element(values.getPtr(), values.getPtr() + values.size());
68 
69  // buckets
70  std::vector<TV> bucket_values(num_points, static_cast<TV>(0));
71  std::vector<int32_t> bucket_counts(num_points, 0);
72 
73  // start timer
74  auto scatter_timer = timer_start();
75 
76  // scatter points into buckets
77  // help from http://www.sunshine2k.de/coding/java/PointOnLine/PointOnLine.html
78  const TLL e1x = line_x2 - line_x1;
79  const TLL e1y = line_y2 - line_y1;
80  const TLL len2_e1 = (e1x * e1x) + (e1y * e1y);
81  int32_t bucket_misses = 0;
82  for (int i = 0; i < lon.size(); i++) {
83  // project point to line
84  const TLL e2x = lon[i] - line_x1;
85  const TLL e2y = lat[i] - line_y1;
86  const TLL dp_e1e2 = (e1x * e2x) + (e1y * e2y);
87  const TLL normalized_distance = dp_e1e2 / len2_e1;
88  // find bucket
89  auto const bucket_index = static_cast<int32_t>(normalized_distance * num_points);
90  // add to bucket?
91  if (bucket_index >= 0 && bucket_index < num_points) {
92  bucket_values[bucket_index] += values[i];
93  bucket_counts[bucket_index]++;
94  } else {
95  bucket_misses++;
96  }
97  }
98 
99  // stop timer
100  LOG(INFO) << "tf_cross_section_1d: scatter took " << timer_stop(scatter_timer) << "ms";
101 
102  // warn if any misses
103  LOG_IF(WARNING, bucket_misses > 0)
104  << "tf_cross_section_1d: had " << bucket_misses << " bucket misses";
105 
106  // size outputs
107  mgr.set_output_array_values_total_number(0, num_points * 2);
108  mgr.set_output_row_size(1);
109 
110  // generate LINESTRING
111  std::vector<double> coords;
112  coords.reserve(num_points * 2);
113  for (int i = 0; i < num_points; i++) {
114  auto const x = static_cast<TV>(i) / static_cast<TV>(num_points - 1);
115  auto const y = bucket_counts[i]
116  ? (bucket_values[i] / static_cast<TV>(bucket_counts[i]))
117  : static_cast<TV>(0);
118  coords.push_back(x);
119  coords.push_back(y);
120  }
121 
122  // set output linestring
123  line[0].fromCoords(coords);
124 
125  // done
126  return 1;
127 }
void set_output_row_size(int64_t num_rows)
Definition: heavydbTypes.h:373
#define CHECK_EQ(x, y)
Definition: Logger.h:301
void set_output_array_values_total_number(int32_t index, int64_t output_array_values_total_number)
Definition: heavydbTypes.h:361
#define LOG(tag)
Definition: Logger.h:285
DEVICE int64_t size() const
TypeR::rep timer_stop(Type clock_begin)
Definition: measure.h:48
DEVICE T * getPtr() const
#define CHECK_GT(x, y)
Definition: Logger.h:305
#define LOG_IF(severity, condition)
Definition: Logger.h:384
#define VLOG(n)
Definition: Logger.h:388
Type timer_start()
Definition: measure.h:42

+ Here is the call graph for this function:

template<typename TLL , typename TY , typename TV >
int32_t CrossSectionTableFunctions::tf_cross_section_2d_impl ( TableFunctionManager mgr,
const Column< TLL > &  lon,
const Column< TLL > &  lat,
const Column< TY > &  y_axis,
const Column< TV > &  values,
const TLL  line_x1,
const TLL  line_y1,
const TLL  line_x2,
const TLL  line_y2,
const int32_t  num_points_x,
const int32_t  num_points_y,
const TLL  dwithin_distance,
Column< TLL > &  x,
Column< TLL > &  y,
Column< TV > &  color 
)

Definition at line 134 of file CrossSectionTableFunctions.hpp.

References CHECK_EQ, CHECK_GT, Column< T >::getPtr(), logger::INFO, LOG, anonymous_namespace{Utm.h}::n, NULL_DOUBLE, NULL_FLOAT, threading_serial::parallel_for(), run_benchmark_import::result, TableFunctionManager::set_output_item_values_total_number(), TableFunctionManager::set_output_row_size(), Column< T >::size(), timer_start(), timer_stop(), and VLOG.

148  {
149  // supported types
150  static_assert(std::is_same_v<double, TLL>);
151  static_assert(std::is_same_v<float, TY> || std::is_same_v<double, TY>);
152  static_assert(std::is_same_v<float, TV> || std::is_same_v<double, TV>);
153 
154  // validate sizes
155  CHECK_EQ(lon.size(), lat.size()) << "input column size mismatch";
156  CHECK_EQ(lon.size(), y_axis.size()) << "input column size mismatch";
157  CHECK_EQ(lon.size(), values.size()) << "input column size mismatch";
158 
159  // enforce parser validation
160  CHECK_GT(num_points_x, 1) << "num_points_x must be > 1";
161  CHECK_GT(num_points_y, 1) << "num_points_y must be > 1";
162 
163  static constexpr int kNumNearest = 3;
164 
165  // enough raster data?
166  if (values.size() < kNumNearest) {
170  mgr.set_output_row_size(0);
171  return 0;
172  }
173 
174  // report values (verbose only)
175  VLOG(2) << "tf_cross_section_2d: Input raster data has " << values.size()
176  << " values, min "
177  << *std::min_element(values.getPtr(), values.getPtr() + values.size())
178  << ", max "
179  << *std::max_element(values.getPtr(), values.getPtr() + values.size());
180 
181  //
182  // build points for tree and capture y-axis range
183  //
184 
185  auto build_nodes_timer = timer_start();
186 
187  auto y_min = std::numeric_limits<double>::max();
188  auto y_max = -std::numeric_limits<double>::max();
189 
190  Kdtree::KdNodeVector nodes(lon.size());
191 
192  for (int i = 0; i < lon.size(); i++) {
193  auto& n = nodes[i];
194  auto const dlon = static_cast<double>(lon[i]);
195  auto const dlat = static_cast<double>(lat[i]);
196  auto const dy = static_cast<double>(y_axis[i]);
197  n.point = {dlon, dlat, dy};
198  n.data = nullptr;
199  n.index = i;
200  y_min = std::min(dy, y_min);
201  y_max = std::max(dy, y_max);
202  }
203 
204  LOG(INFO) << "tf_cross_section_2d: build nodes took " << timer_stop(build_nodes_timer)
205  << "ms";
206 
207  //
208  // build tree
209  //
210 
211  auto build_tree_timer = timer_start();
212 
213  Kdtree::KdTree tree(&nodes);
214 
215  LOG(INFO) << "tf_cross_section_2d: build tree took " << timer_stop(build_tree_timer)
216  << "ms";
217 
218  //
219  // size outputs
220  //
221 
222  auto const num_output_rows = num_points_x * num_points_y;
223 
224  mgr.set_output_item_values_total_number(0, num_output_rows);
225  mgr.set_output_item_values_total_number(1, num_output_rows);
226  mgr.set_output_item_values_total_number(2, num_output_rows);
227  mgr.set_output_row_size(num_output_rows);
228 
229  //
230  // compute mesh
231  //
232 
233  auto compute_mesh_timer = timer_start();
234 
235  auto const max_dist2 = dwithin_distance * dwithin_distance;
236 
237  static constexpr double kMinDistance2 = 0.0001;
238 
240  tbb::blocked_range<int32_t>(0, num_output_rows),
241  [&](const tbb::blocked_range<int32_t>& r) {
242  auto const start_idx = r.begin();
243  auto const end_idx = r.end();
244  for (int32_t output_index = start_idx; output_index < end_idx; output_index++) {
245  // discrete mesh-space point
246  auto const xi = output_index % num_points_x;
247  auto const yi = output_index / num_points_x;
248 
249  // normalized mesh-space point
250  auto const tx = static_cast<double>(xi) / static_cast<double>(num_points_x - 1);
251  auto const ty = static_cast<double>(yi) / static_cast<double>(num_points_y - 1);
252 
253  // world-space point
254  std::vector<double> p{(tx * (line_x2 - line_x1)) + line_x1,
255  (tx * (line_y2 - line_y1)) + line_y1,
256  (ty * (y_max - y_min)) + y_min};
257 
258  // get nearest N points from tree
259  Kdtree::KdNodeVector result;
260  tree.k_nearest_neighbors(p, kNumNearest, &result);
261  CHECK_EQ(result.size(), kNumNearest);
262 
263  // are the points close enough in lon/lat space?
264  int valid_indices[kNumNearest];
265  double valid_weights[kNumNearest];
266  double total_weight = 0.0;
267  size_t num_valid = 0u;
268  for (size_t i = 0; i < kNumNearest; i++) {
269  auto const dx = result[i].point[0] - p[0];
270  auto const dy = result[i].point[1] - p[1];
271  auto const dist2 = (dx * dx) + (dy * dy);
272  // discard points that are more than one mesh grid cell away
273  if (dist2 < max_dist2) {
274  // weights are inverse squared distance
275  auto const dz = result[i].point[2] - p[2];
276  auto const len2 = dist2 + (dz * dz);
277  auto const weight = 1.0 / std::max(len2, kMinDistance2);
278  // use this point
279  valid_indices[num_valid] = i;
280  valid_weights[num_valid] = weight;
281  total_weight += weight;
282  num_valid++;
283  }
284  }
285 
286  // compute final weighted value
287  TV col;
288  if constexpr (std::is_same_v<double, TV>) {
289  col = static_cast<TV>(NULL_DOUBLE);
290  } else {
291  col = static_cast<TV>(NULL_FLOAT);
292  }
293  if (num_valid > 0u && total_weight > 0.0) {
294  col = static_cast<TV>(0.0);
295  const double weight_multiplier = 1.0 / total_weight;
296  for (size_t i = 0; i < num_valid; i++) {
297  auto const index = valid_indices[i];
298  auto const weight = valid_weights[i];
299  auto const value = values[result[index].index];
300  col += static_cast<TV>(value * weight * weight_multiplier);
301  }
302  }
303 
304  // output the screen-space point and color
305  x[output_index] = tx;
306  y[output_index] = p[2];
307  color[output_index] = col;
308  }
309  });
310 
311  LOG(INFO) << "tf_cross_section_2d: compute mesh took " << timer_stop(compute_mesh_timer)
312  << "ms";
313 
314  // done
315  return num_output_rows;
316 }
void set_output_row_size(int64_t num_rows)
Definition: heavydbTypes.h:373
#define CHECK_EQ(x, y)
Definition: Logger.h:301
#define NULL_DOUBLE
#define NULL_FLOAT
#define LOG(tag)
Definition: Logger.h:285
DEVICE int64_t size() const
TypeR::rep timer_stop(Type clock_begin)
Definition: measure.h:48
DEVICE T * getPtr() const
#define CHECK_GT(x, y)
Definition: Logger.h:305
void set_output_item_values_total_number(int32_t index, int64_t output_item_values_total_number)
Definition: heavydbTypes.h:367
void parallel_for(const blocked_range< Int > &range, const Body &body, const Partitioner &p=Partitioner())
constexpr double n
Definition: Utm.h:38
#define VLOG(n)
Definition: Logger.h:388
Type timer_start()
Definition: measure.h:42

+ Here is the call graph for this function: