OmniSciDB  0fdbebe030
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
geo_types.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 MapD Technologies, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "geo_types.h"
18 #include "Logger.h"
19 #include "sqltypes.h"
20 
21 #include <gdal.h>
22 #include <ogr_geometry.h>
23 #include <ogrsf_frmts.h>
24 
25 #include <limits>
26 
36 namespace {
37 constexpr auto DOUBLE_MAX = std::numeric_limits<double>::max();
38 constexpr auto DOUBLE_MIN = std::numeric_limits<double>::lowest();
39 
40 struct Coords {
41  double x;
42  double y;
43  Coords(double x, double y) : x(x), y(y) {}
44 };
45 
46 struct BoundingBox {
49  BoundingBox() : min(DOUBLE_MAX, DOUBLE_MAX), max(DOUBLE_MIN, DOUBLE_MIN) {}
50 
51  void update(double x, double y) {
52  if (x < min.x) {
53  min.x = x;
54  }
55  if (y < min.y) {
56  min.y = y;
57  }
58  if (x > max.x) {
59  max.x = x;
60  }
61  if (y > max.y) {
62  max.y = y;
63  }
64  }
65 };
66 
67 int process_poly_ring(OGRLinearRing* ring,
68  std::vector<double>& coords,
69  BoundingBox* bbox) {
70  double last_x = DOUBLE_MAX, last_y = DOUBLE_MAX;
71  size_t first_index = coords.size();
72  int num_points_added = 0;
73  int num_points_in_ring = ring->getNumPoints();
74  if (num_points_in_ring < 3) {
76  "PolyRing",
77  "All poly rings must have more than 3 points. Found ring with " +
78  std::to_string(num_points_in_ring) + " points.");
79  }
80  for (auto i = 0; i < num_points_in_ring; i++) {
81  OGRPoint point;
82  ring->getPoint(i, &point);
83  last_x = point.getX();
84  last_y = point.getY();
85  coords.push_back(last_x);
86  coords.push_back(last_y);
87  if (bbox) {
88  bbox->update(last_x, last_y);
89  }
90  num_points_added++;
91  }
92  // Store all rings as open rings (implicitly assumes all rings are closed)
93  if ((coords[first_index] == last_x) && (coords[first_index + 1] == last_y)) {
94  coords.pop_back();
95  coords.pop_back();
96  num_points_added--;
97  if (num_points_added < 3) {
99  "PolyRing",
100  "All exterior rings must have more than 3 points. Found ring with " +
101  std::to_string(num_points_added) + " points.");
102  }
103  }
104  return num_points_added;
105 }
106 
107 } // namespace
108 
109 namespace Geo_namespace {
110 
111 std::string GeoTypesError::OGRErrorToStr(const int ogr_err) {
112  switch (ogr_err) {
113  case OGRERR_NOT_ENOUGH_DATA:
114  return std::string("not enough input data");
115  case OGRERR_NOT_ENOUGH_MEMORY:
116  return std::string("not enough memory");
117  case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
118  return std::string("unsupported geometry type");
119  case OGRERR_UNSUPPORTED_OPERATION:
120  return std::string("unsupported operation");
121  case OGRERR_CORRUPT_DATA:
122  return std::string("corrupt input data");
123  case OGRERR_FAILURE:
124  return std::string("ogr failure");
125  case OGRERR_UNSUPPORTED_SRS:
126  return std::string("unsupported spatial reference system");
127  case OGRERR_INVALID_HANDLE:
128  return std::string("invalid file handle");
129 #if (GDAL_VERSION_MAJOR > 1)
130  case OGRERR_NON_EXISTING_FEATURE:
131  return std::string("feature does not exist in input geometry");
132 #endif
133  default:
134  return std::string("Unknown OGOR error encountered: ") + std::to_string(ogr_err);
135  }
136 }
137 
139  // Note: Removing the geometry object that was pulled from an OGRFeature results in a
140  // segfault. If we are wrapping around a pre-existing OGRGeometry object, we let the
141  // caller manage the memory.
142  if (geom_ && owns_geom_obj_) {
143  OGRGeometryFactory::destroyGeometry(geom_);
144  }
145 }
146 
147 OGRErr GeoBase::createFromWktString(const std::string& wkt, OGRGeometry** geom) {
148 #if (GDAL_VERSION_MAJOR > 2) || (GDAL_VERSION_MAJOR == 2 && GDAL_VERSION_MINOR >= 3)
149  OGRErr ogr_status = OGRGeometryFactory::createFromWkt(wkt.c_str(), nullptr, geom);
150 #else
151  auto data = (char*)wkt.c_str();
152  OGRErr ogr_status = OGRGeometryFactory::createFromWkt(&data, NULL, geom);
153 #endif
154  return ogr_status;
155 }
156 
157 std::string GeoBase::getWktString() const {
158  char* wkt = nullptr;
159  geom_->exportToWkt(&wkt);
160  CHECK(wkt);
161  std::string wkt_str(wkt);
162  CPLFree(wkt);
163  return wkt_str;
164 }
165 
166 bool GeoBase::operator==(const GeoBase& other) const {
167  if (!this->geom_ || !other.geom_) {
168  return false;
169  }
170  return this->geom_->Equals(other.geom_);
171  // return const_cast<const OGRGeometry*>(this->geom_) == const_cast<const
172  // OGRGeometry*>(other.geom_);
173 }
174 
175 GeoPoint::GeoPoint(const std::vector<double>& coords) {
176  if (coords.size() != 2) {
177  throw GeoTypesError("Point",
178  "Incorrect coord size of " + std::to_string(coords.size()) +
179  " supplied. Expected 2.");
180  }
181  geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbPoint);
182  OGRPoint* point = dynamic_cast<OGRPoint*>(geom_);
183  CHECK(point);
184  point->setX(coords[0]);
185  point->setY(coords[1]);
186 }
187 
188 GeoPoint::GeoPoint(const std::string& wkt) {
189  const auto err = GeoBase::createFromWktString(wkt, &geom_);
190  if (err != OGRERR_NONE) {
191  throw GeoTypesError("Point", err);
192  }
193  CHECK(geom_);
194  if (wkbFlatten(geom_->getGeometryType()) != OGRwkbGeometryType::wkbPoint) {
195  throw GeoTypesError("Point",
196  "Unexpected geometry type from WKT string: " +
197  std::string(OGRGeometryTypeToName(geom_->getGeometryType())));
198  }
199 }
200 
201 void GeoPoint::getColumns(std::vector<double>& coords) const {
202  const auto point_geom = dynamic_cast<OGRPoint*>(geom_);
203  CHECK(point_geom);
204 
205  if (point_geom->IsEmpty()) {
206  // until the run-time can handle empties
207  throw GeoTypesError("Point", "'EMPTY' not supported");
208  // we cannot yet handle NULL fixed-length array
209  // so we have to store sentinel values instead
210  coords.push_back(NULL_DOUBLE);
211  coords.push_back(NULL_DOUBLE);
212  return;
213  }
214 
215  coords.push_back(point_geom->getX());
216  coords.push_back(point_geom->getY());
217 }
218 
219 GeoLineString::GeoLineString(const std::vector<double>& coords) {
220  geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbLineString);
221  OGRLineString* line = dynamic_cast<OGRLineString*>(geom_);
222  CHECK(line);
223  for (size_t i = 0; i < coords.size(); i += 2) {
224  line->addPoint(coords[i], coords[i + 1]);
225  }
226 }
227 
228 GeoLineString::GeoLineString(const std::string& wkt) {
229  const auto err = GeoBase::createFromWktString(wkt, &geom_);
230  if (err != OGRERR_NONE) {
231  throw GeoTypesError("LineString", err);
232  }
233  CHECK(geom_);
234  if (wkbFlatten(geom_->getGeometryType()) != OGRwkbGeometryType::wkbLineString) {
235  throw GeoTypesError("LineString",
236  "Unexpected geometry type from WKT string: " +
237  std::string(OGRGeometryTypeToName(geom_->getGeometryType())));
238  }
239 }
240 
241 void GeoLineString::getColumns(std::vector<double>& coords,
242  std::vector<double>& bounds) const {
243  auto linestring_geom = dynamic_cast<OGRLineString*>(geom_);
244  CHECK(linestring_geom);
245 
246  if (linestring_geom->IsEmpty()) {
247  // until the run-time can handle empties
248  throw GeoTypesError("LineString", "'EMPTY' not supported");
249  // return null bounds
250  bounds.push_back(NULL_DOUBLE);
251  bounds.push_back(NULL_DOUBLE);
252  bounds.push_back(NULL_DOUBLE);
253  bounds.push_back(NULL_DOUBLE);
254  return;
255  }
256 
257  BoundingBox bbox;
258  for (auto i = 0; i < linestring_geom->getNumPoints(); i++) {
259  OGRPoint point;
260  linestring_geom->getPoint(i, &point);
261  double x = point.getX();
262  double y = point.getY();
263  coords.push_back(x);
264  coords.push_back(y);
265  bbox.update(x, y);
266  }
267  bounds.push_back(bbox.min.x);
268  bounds.push_back(bbox.min.y);
269  bounds.push_back(bbox.max.x);
270  bounds.push_back(bbox.max.y);
271 }
272 
273 GeoPolygon::GeoPolygon(const std::vector<double>& coords,
274  const std::vector<int32_t>& ring_sizes) {
275  geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbPolygon);
276  OGRPolygon* poly = dynamic_cast<OGRPolygon*>(geom_);
277  CHECK(poly);
278 
279  size_t coords_ctr = 0;
280  for (size_t r = 0; r < ring_sizes.size(); r++) {
281  OGRLinearRing ring;
282  const auto ring_sz = ring_sizes[r];
283  for (auto i = 0; i < 2 * ring_sz; i += 2) {
284  ring.addPoint(coords[coords_ctr + i], coords[coords_ctr + i + 1]);
285  }
286  ring.addPoint(coords[coords_ctr], coords[coords_ctr + 1]);
287  coords_ctr += 2 * ring_sz;
288  poly->addRing(&ring);
289  }
290 }
291 
292 GeoPolygon::GeoPolygon(const std::string& wkt) {
293  const auto err = GeoBase::createFromWktString(wkt, &geom_);
294  if (err != OGRERR_NONE) {
295  throw GeoTypesError("Polygon", err);
296  }
297  CHECK(geom_);
298  if (wkbFlatten(geom_->getGeometryType()) != OGRwkbGeometryType::wkbPolygon) {
299  throw GeoTypesError("Polygon",
300  "Unexpected geometry type from WKT string: " +
301  std::string(OGRGeometryTypeToName(geom_->getGeometryType())));
302  }
303 }
304 
305 void GeoPolygon::getColumns(std::vector<double>& coords,
306  std::vector<int32_t>& ring_sizes,
307  std::vector<double>& bounds) const {
308  const auto poly_geom = dynamic_cast<OGRPolygon*>(geom_);
309  CHECK(poly_geom);
310 
311  if (poly_geom->IsEmpty()) {
312  // until the run-time can handle empties
313  throw GeoTypesError("Polygon", "'EMPTY' not supported");
314  // return null bounds
315  bounds.push_back(NULL_DOUBLE);
316  bounds.push_back(NULL_DOUBLE);
317  bounds.push_back(NULL_DOUBLE);
318  bounds.push_back(NULL_DOUBLE);
319  return;
320  }
321 
322  BoundingBox bbox;
323  const auto exterior_ring = poly_geom->getExteriorRing();
324  CHECK(exterior_ring);
325  // All exterior rings are imported CCW
326  if (exterior_ring->isClockwise()) {
327  exterior_ring->reverseWindingOrder();
328  }
329  const auto num_points_added = process_poly_ring(exterior_ring, coords, &bbox);
330  ring_sizes.push_back(num_points_added);
331  for (auto r = 0; r < poly_geom->getNumInteriorRings(); r++) {
332  auto interior_ring = poly_geom->getInteriorRing(r);
333  CHECK(interior_ring);
334  // All interior rings are imported CW
335  if (!interior_ring->isClockwise()) {
336  interior_ring->reverseWindingOrder();
337  }
338  const auto num_points_added = process_poly_ring(interior_ring, coords, nullptr);
339  ring_sizes.push_back(num_points_added);
340  }
341  bounds.push_back(bbox.min.x);
342  bounds.push_back(bbox.min.y);
343  bounds.push_back(bbox.max.x);
344  bounds.push_back(bbox.max.y);
345 }
346 
348  const auto poly_geom = dynamic_cast<OGRPolygon*>(geom_);
349  CHECK(poly_geom);
350  return poly_geom->getNumInteriorRings();
351 }
352 
353 GeoMultiPolygon::GeoMultiPolygon(const std::vector<double>& coords,
354  const std::vector<int32_t>& ring_sizes,
355  const std::vector<int32_t>& poly_rings) {
356  geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbMultiPolygon);
357  OGRMultiPolygon* multipoly = dynamic_cast<OGRMultiPolygon*>(geom_);
358  CHECK(multipoly);
359 
360  size_t ring_ctr = 0;
361  size_t coords_ctr = 0;
362  for (const auto& rings_in_poly : poly_rings) {
363  OGRPolygon poly;
364  for (auto r = 0; r < rings_in_poly; r++) {
365  OGRLinearRing ring;
366  const auto ring_sz = ring_sizes[ring_ctr];
367  for (auto i = 0; i < 2 * ring_sz; i += 2) {
368  ring.addPoint(coords[coords_ctr + i], coords[coords_ctr + i + 1]);
369  }
370  ring.addPoint(coords[coords_ctr], coords[coords_ctr + 1]);
371  coords_ctr += 2 * ring_sz;
372  poly.addRing(&ring);
373  ring_ctr++;
374  }
375  multipoly->addGeometry(&poly);
376  }
377 }
378 
379 GeoMultiPolygon::GeoMultiPolygon(const std::string& wkt) {
380  const auto err = GeoBase::createFromWktString(wkt, &geom_);
381  if (err != OGRERR_NONE) {
382  throw GeoTypesError("MultiPolygon", err);
383  }
384  CHECK(geom_);
385  if (wkbFlatten(geom_->getGeometryType()) != OGRwkbGeometryType::wkbMultiPolygon) {
386  throw GeoTypesError("MultiPolygon",
387  "Unexpected geometry type from WKT string: " +
388  std::string(OGRGeometryTypeToName(geom_->getGeometryType())));
389  }
390 }
391 
392 void GeoMultiPolygon::getColumns(std::vector<double>& coords,
393  std::vector<int32_t>& ring_sizes,
394  std::vector<int32_t>& poly_rings,
395  std::vector<double>& bounds) const {
396  const auto mpoly = dynamic_cast<OGRMultiPolygon*>(geom_);
397  CHECK(mpoly);
398 
399  if (mpoly->IsEmpty()) {
400  // until the run-time can handle empties
401  throw GeoTypesError("MultiPolygon", "'EMPTY' not supported");
402  // return null bounds
403  bounds.push_back(NULL_DOUBLE);
404  bounds.push_back(NULL_DOUBLE);
405  bounds.push_back(NULL_DOUBLE);
406  bounds.push_back(NULL_DOUBLE);
407  return;
408  }
409 
410  BoundingBox bbox;
411  for (auto p = 0; p < mpoly->getNumGeometries(); p++) {
412  const auto mpoly_geom = mpoly->getGeometryRef(p);
413  CHECK(mpoly_geom);
414  const auto poly_geom = dynamic_cast<OGRPolygon*>(mpoly_geom);
415  if (!poly_geom) {
416  throw GeoTypesError("MultiPolygon",
417  "Failed to read polygon geometry from multipolygon");
418  }
419  const auto exterior_ring = poly_geom->getExteriorRing();
420  CHECK(exterior_ring);
421  // All exterior rings are imported CCW
422  if (exterior_ring->isClockwise()) {
423  exterior_ring->reverseWindingOrder();
424  }
425  const auto num_points_added = process_poly_ring(exterior_ring, coords, &bbox);
426  ring_sizes.push_back(num_points_added);
427 
428  for (auto r = 0; r < poly_geom->getNumInteriorRings(); r++) {
429  auto interior_ring = poly_geom->getInteriorRing(r);
430  CHECK(interior_ring);
431  // All interior rings are imported CW
432  if (!interior_ring->isClockwise()) {
433  interior_ring->reverseWindingOrder();
434  }
435  const auto num_points_added = process_poly_ring(interior_ring, coords, nullptr);
436  ring_sizes.push_back(num_points_added);
437  }
438  poly_rings.push_back(poly_geom->getNumInteriorRings() + 1);
439  }
440  bounds.push_back(bbox.min.x);
441  bounds.push_back(bbox.min.y);
442  bounds.push_back(bbox.max.x);
443  bounds.push_back(bbox.max.y);
444 }
445 
446 std::unique_ptr<GeoBase> GeoTypesFactory::createGeoType(const std::string& wkt) {
447  OGRGeometry* geom = nullptr;
448  const auto err = GeoBase::createFromWktString(wkt, &geom);
449  if (err != OGRERR_NONE) {
450  throw GeoTypesError("GeoFactory", err);
451  }
453 }
454 
455 std::unique_ptr<GeoBase> GeoTypesFactory::createGeoType(OGRGeometry* geom) {
456  return GeoTypesFactory::createGeoTypeImpl(geom, false);
457 }
458 
459 bool GeoTypesFactory::getGeoColumns(const std::string& wkt,
460  SQLTypeInfo& ti,
461  std::vector<double>& coords,
462  std::vector<double>& bounds,
463  std::vector<int>& ring_sizes,
464  std::vector<int>& poly_rings,
465  const bool promote_poly_to_mpoly) {
466  try {
467  if (wkt.empty() || wkt == "NULL") {
469  ti, coords, bounds, ring_sizes, poly_rings, promote_poly_to_mpoly);
470  return true;
471  }
472 
473  const auto geospatial_base = GeoTypesFactory::createGeoType(wkt);
474 
475  int srid = 0;
476  ti.set_input_srid(srid);
477  ti.set_output_srid(srid);
478 
479  getGeoColumnsImpl(geospatial_base,
480  ti,
481  coords,
482  bounds,
483  ring_sizes,
484  poly_rings,
485  promote_poly_to_mpoly);
486 
487  } catch (const std::exception& e) {
488  LOG(ERROR) << "Geospatial Import Error: " << e.what();
489  return false;
490  }
491 
492  return true;
493 }
494 
495 bool GeoTypesFactory::getGeoColumns(OGRGeometry* geom,
496  SQLTypeInfo& ti,
497  std::vector<double>& coords,
498  std::vector<double>& bounds,
499  std::vector<int>& ring_sizes,
500  std::vector<int>& poly_rings,
501  const bool promote_poly_to_mpoly) {
502  try {
503  const auto geospatial_base = GeoTypesFactory::createGeoType(geom);
504 
505  int srid = 0;
506  ti.set_input_srid(srid);
507  ti.set_output_srid(srid);
508 
509  getGeoColumnsImpl(geospatial_base,
510  ti,
511  coords,
512  bounds,
513  ring_sizes,
514  poly_rings,
515  promote_poly_to_mpoly);
516 
517  } catch (const std::exception& e) {
518  LOG(ERROR) << "Geospatial Import Error: " << e.what();
519  return false;
520  }
521 
522  return true;
523 }
524 
525 bool GeoTypesFactory::getGeoColumns(const std::vector<std::string>* wkt_column,
526  SQLTypeInfo& ti,
527  std::vector<std::vector<double>>& coords_column,
528  std::vector<std::vector<double>>& bounds_column,
529  std::vector<std::vector<int>>& ring_sizes_column,
530  std::vector<std::vector<int>>& poly_rings_column,
531  const bool promote_poly_to_mpoly) {
532  try {
533  for (const auto wkt : *wkt_column) {
534  std::vector<double> coords;
535  std::vector<double> bounds;
536  std::vector<int> ring_sizes;
537  std::vector<int> poly_rings;
538 
539  SQLTypeInfo row_ti;
541  wkt, row_ti, coords, bounds, ring_sizes, poly_rings, promote_poly_to_mpoly);
542 
543  if (ti.get_type() != row_ti.get_type()) {
544  throw GeoTypesError("GeoFactory", "Columnar: Geometry type mismatch");
545  }
546  coords_column.push_back(coords);
547  bounds_column.push_back(bounds);
548  ring_sizes_column.push_back(ring_sizes);
549  poly_rings_column.push_back(poly_rings);
550  }
551 
552  } catch (const std::exception& e) {
553  LOG(ERROR) << "Geospatial column Import Error: " << e.what();
554  return false;
555  }
556 
557  return true;
558 }
559 
560 std::unique_ptr<GeoBase> GeoTypesFactory::createGeoTypeImpl(OGRGeometry* geom,
561  const bool owns_geom_obj) {
562  switch (wkbFlatten(geom->getGeometryType())) {
563  case wkbPoint:
564  return std::unique_ptr<GeoPoint>(new GeoPoint(geom, owns_geom_obj));
565  case wkbLineString:
566  return std::unique_ptr<GeoLineString>(new GeoLineString(geom, owns_geom_obj));
567  case wkbPolygon:
568  return std::unique_ptr<GeoPolygon>(new GeoPolygon(geom, owns_geom_obj));
569  case wkbMultiPolygon:
570  return std::unique_ptr<GeoMultiPolygon>(new GeoMultiPolygon(geom, owns_geom_obj));
571  default:
572  throw GeoTypesError(
573  "GeoTypesFactory",
574  "Unrecognized geometry type: " + std::string(geom->getGeometryName()));
575  }
576 }
577 
578 void GeoTypesFactory::getGeoColumnsImpl(const std::unique_ptr<GeoBase>& geospatial_base,
579  SQLTypeInfo& ti,
580  std::vector<double>& coords,
581  std::vector<double>& bounds,
582  std::vector<int>& ring_sizes,
583  std::vector<int>& poly_rings,
584  const bool promote_poly_to_mpoly) {
585  switch (geospatial_base->getType()) {
587  const auto geospatial_point = dynamic_cast<GeoPoint*>(geospatial_base.get());
588  CHECK(geospatial_point);
589  geospatial_point->getColumns(coords);
590  ti.set_type(kPOINT);
591  break;
592  }
594  const auto geospatial_linestring =
595  dynamic_cast<GeoLineString*>(geospatial_base.get());
596  CHECK(geospatial_linestring);
597  geospatial_linestring->getColumns(coords, bounds);
598  ti.set_type(kLINESTRING);
599  break;
600  }
602  const auto geospatial_poly = dynamic_cast<GeoPolygon*>(geospatial_base.get());
603  CHECK(geospatial_poly);
604  geospatial_poly->getColumns(coords, ring_sizes, bounds);
605  if (promote_poly_to_mpoly) {
606  if (ring_sizes.size()) {
607  CHECK_GT(coords.size(), 0u);
608  poly_rings.push_back(1 + geospatial_poly->getNumInteriorRings());
609  }
610  }
611  ti.set_type(kPOLYGON);
612  break;
613  }
615  const auto geospatial_mpoly = dynamic_cast<GeoMultiPolygon*>(geospatial_base.get());
616  CHECK(geospatial_mpoly);
617  geospatial_mpoly->getColumns(coords, ring_sizes, poly_rings, bounds);
619  break;
620  }
621  default:
622  throw std::runtime_error("Unrecognized geospatial type");
623  }
624 }
625 
627  std::vector<double>& coords,
628  std::vector<double>& bounds,
629  std::vector<int>& ring_sizes,
630  std::vector<int>& poly_rings,
631  const bool promote_poly_to_mpoly) {
632  auto t = ti.get_type();
633  switch (t) {
634  case kPOINT: {
635  // NULL fixlen coords array
636  coords.push_back(NULL_ARRAY_DOUBLE);
637  coords.push_back(NULL_DOUBLE);
638  } break;
639  case kLINESTRING:
640  case kPOLYGON:
641  case kMULTIPOLYGON: {
642  // Leaving coords array empty
643  // NULL fixlen bounds array
644  bounds.push_back(NULL_ARRAY_DOUBLE);
645  bounds.push_back(NULL_DOUBLE);
646  bounds.push_back(NULL_DOUBLE);
647  bounds.push_back(NULL_DOUBLE);
648  // Leaving ring_sizes and poly_rings arrays empty
649  } break;
650  default:
651  throw std::runtime_error("Unsupported NULL geo");
652  }
653 }
654 
655 } // namespace Geo_namespace
GeoMultiPolygon(const std::vector< double > &coords, const std::vector< int32_t > &ring_sizes, const std::vector< int32_t > &poly_rings)
Definition: geo_types.cpp:353
void getColumns(std::vector< double > &coords) const
Definition: geo_types.cpp:201
#define NULL_DOUBLE
Definition: sqltypes.h:175
void getColumns(std::vector< double > &coords, std::vector< double > &bounds) const
Definition: geo_types.cpp:241
int32_t getNumInteriorRings() const
Definition: geo_types.cpp:347
#define NULL_ARRAY_DOUBLE
Definition: sqltypes.h:183
#define LOG(tag)
Definition: Logger.h:188
std::string getWktString() const
Definition: geo_types.cpp:157
static int createFromWktString(const std::string &wkt, OGRGeometry **geom)
Definition: geo_types.cpp:147
Constants for Builtin SQL Types supported by OmniSci.
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:248
#define CHECK_GT(x, y)
Definition: Logger.h:209
std::string to_string(char const *&&v)
static void getGeoColumnsImpl(const std::unique_ptr< GeoBase > &geospatial_base, SQLTypeInfo &ti, std::vector< double > &coords, std::vector< double > &bounds, std::vector< int > &ring_sizes, std::vector< int > &poly_rings, const bool promote_poly_to_mpoly=false)
Definition: geo_types.cpp:578
void set_input_srid(int d)
Definition: sqltypes.h:342
CHECK(cgen_state)
void getColumns(std::vector< double > &coords, std::vector< int32_t > &ring_sizes, std::vector< double > &bounds) const
Definition: geo_types.cpp:305
void getColumns(std::vector< double > &coords, std::vector< int32_t > &ring_sizes, std::vector< int32_t > &poly_rings, std::vector< double > &bounds) const
Definition: geo_types.cpp:392
GeoPolygon(const std::vector< double > &coords, const std::vector< int32_t > &ring_sizes)
Definition: geo_types.cpp:273
GeoPoint(const std::vector< double > &coords)
Definition: geo_types.cpp:175
void set_output_srid(int s)
Definition: sqltypes.h:344
static void getNullGeoColumns(SQLTypeInfo &ti, std::vector< double > &coords, std::vector< double > &bounds, std::vector< int > &ring_sizes, std::vector< int > &poly_rings, const bool promote_poly_to_mpoly=false)
Definition: geo_types.cpp:626
static std::unique_ptr< GeoBase > createGeoType(const std::string &wkt)
Definition: geo_types.cpp:446
static bool getGeoColumns(const std::string &wkt, SQLTypeInfo &ti, std::vector< double > &coords, std::vector< double > &bounds, std::vector< int > &ring_sizes, std::vector< int > &poly_rings, const bool promote_poly_to_mpoly=false)
Definition: geo_types.cpp:459
OGRGeometry * geom_
Definition: geo_types.h:59
virtual bool operator==(const GeoBase &other) const
Definition: geo_types.cpp:166
static std::unique_ptr< Geo_namespace::GeoBase > createGeoTypeImpl(OGRGeometry *geom, const bool owns_geom_obj=true)
Definition: geo_types.cpp:560
int process_poly_ring(OGRLinearRing *ring, std::vector< double > &coords, BoundingBox *bbox)
Definition: geo_types.cpp:67
GeoLineString(const std::vector< double > &coords)
Definition: geo_types.cpp:219
static std::string OGRErrorToStr(const int ogr_err)
Definition: geo_types.cpp:111
HOST DEVICE void set_type(SQLTypes t)
Definition: sqltypes.h:338