OmniSciDB  1dac507f6e
 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  const auto geospatial_base = GeoTypesFactory::createGeoType(wkt);
468 
469  int srid = 0;
470  ti.set_input_srid(srid);
471  ti.set_output_srid(srid);
472 
473  getGeoColumnsImpl(geospatial_base,
474  ti,
475  coords,
476  bounds,
477  ring_sizes,
478  poly_rings,
479  promote_poly_to_mpoly);
480 
481  } catch (const std::exception& e) {
482  LOG(ERROR) << "Geospatial Import Error: " << e.what();
483  return false;
484  }
485 
486  return true;
487 }
488 
489 bool GeoTypesFactory::getGeoColumns(OGRGeometry* geom,
490  SQLTypeInfo& ti,
491  std::vector<double>& coords,
492  std::vector<double>& bounds,
493  std::vector<int>& ring_sizes,
494  std::vector<int>& poly_rings,
495  const bool promote_poly_to_mpoly) {
496  try {
497  const auto geospatial_base = GeoTypesFactory::createGeoType(geom);
498 
499  int srid = 0;
500  ti.set_input_srid(srid);
501  ti.set_output_srid(srid);
502 
503  getGeoColumnsImpl(geospatial_base,
504  ti,
505  coords,
506  bounds,
507  ring_sizes,
508  poly_rings,
509  promote_poly_to_mpoly);
510 
511  } catch (const std::exception& e) {
512  LOG(ERROR) << "Geospatial Import Error: " << e.what();
513  return false;
514  }
515 
516  return true;
517 }
518 
519 bool GeoTypesFactory::getGeoColumns(const std::vector<std::string>* wkt_column,
520  SQLTypeInfo& ti,
521  std::vector<std::vector<double>>& coords_column,
522  std::vector<std::vector<double>>& bounds_column,
523  std::vector<std::vector<int>>& ring_sizes_column,
524  std::vector<std::vector<int>>& poly_rings_column,
525  const bool promote_poly_to_mpoly) {
526  try {
527  for (const auto wkt : *wkt_column) {
528  std::vector<double> coords;
529  std::vector<double> bounds;
530  std::vector<int> ring_sizes;
531  std::vector<int> poly_rings;
532 
533  SQLTypeInfo row_ti;
535  wkt, row_ti, coords, bounds, ring_sizes, poly_rings, promote_poly_to_mpoly);
536 
537  if (ti.get_type() != row_ti.get_type()) {
538  throw GeoTypesError("GeoFactory", "Columnar: Geometry type mismatch");
539  }
540  coords_column.push_back(coords);
541  bounds_column.push_back(bounds);
542  ring_sizes_column.push_back(ring_sizes);
543  poly_rings_column.push_back(poly_rings);
544  }
545 
546  } catch (const std::exception& e) {
547  LOG(ERROR) << "Geospatial column Import Error: " << e.what();
548  return false;
549  }
550 
551  return true;
552 }
553 
554 std::unique_ptr<GeoBase> GeoTypesFactory::createGeoTypeImpl(OGRGeometry* geom,
555  const bool owns_geom_obj) {
556  switch (wkbFlatten(geom->getGeometryType())) {
557  case wkbPoint:
558  return std::unique_ptr<GeoPoint>(new GeoPoint(geom, owns_geom_obj));
559  case wkbLineString:
560  return std::unique_ptr<GeoLineString>(new GeoLineString(geom, owns_geom_obj));
561  case wkbPolygon:
562  return std::unique_ptr<GeoPolygon>(new GeoPolygon(geom, owns_geom_obj));
563  case wkbMultiPolygon:
564  return std::unique_ptr<GeoMultiPolygon>(new GeoMultiPolygon(geom, owns_geom_obj));
565  default:
566  throw GeoTypesError(
567  "GeoTypesFactory",
568  "Unrecognized geometry type: " + std::string(geom->getGeometryName()));
569  }
570 }
571 
572 void GeoTypesFactory::getGeoColumnsImpl(const std::unique_ptr<GeoBase>& geospatial_base,
573  SQLTypeInfo& ti,
574  std::vector<double>& coords,
575  std::vector<double>& bounds,
576  std::vector<int>& ring_sizes,
577  std::vector<int>& poly_rings,
578  const bool promote_poly_to_mpoly) {
579  switch (geospatial_base->getType()) {
581  const auto geospatial_point = dynamic_cast<GeoPoint*>(geospatial_base.get());
582  CHECK(geospatial_point);
583  geospatial_point->getColumns(coords);
584  ti.set_type(kPOINT);
585  break;
586  }
588  const auto geospatial_linestring =
589  dynamic_cast<GeoLineString*>(geospatial_base.get());
590  CHECK(geospatial_linestring);
591  geospatial_linestring->getColumns(coords, bounds);
592  ti.set_type(kLINESTRING);
593  break;
594  }
596  const auto geospatial_poly = dynamic_cast<GeoPolygon*>(geospatial_base.get());
597  CHECK(geospatial_poly);
598  geospatial_poly->getColumns(coords, ring_sizes, bounds);
599  if (promote_poly_to_mpoly) {
600  if (ring_sizes.size()) {
601  CHECK_GT(coords.size(), 0u);
602  poly_rings.push_back(1 + geospatial_poly->getNumInteriorRings());
603  }
604  }
605  ti.set_type(kPOLYGON);
606  break;
607  }
609  const auto geospatial_mpoly = dynamic_cast<GeoMultiPolygon*>(geospatial_base.get());
610  CHECK(geospatial_mpoly);
611  geospatial_mpoly->getColumns(coords, ring_sizes, poly_rings, bounds);
613  break;
614  }
615  default:
616  throw std::runtime_error("Unrecognized geospatial type");
617  }
618 }
619 
620 } // namespace Geo_namespace
#define NULL_DOUBLE
Definition: sqltypes.h:179
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
#define LOG(tag)
Definition: Logger.h:185
std::string getWktString() const
Definition: geo_types.cpp:157
static int createFromWktString(const std::string &wkt, OGRGeometry **geom)
Definition: geo_types.cpp:147
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
void set_input_srid(int d)
Definition: sqltypes.h:420
HOST DEVICE void set_type(SQLTypes t)
Definition: sqltypes.h:416
Constants for Builtin SQL Types supported by MapD.
void getColumns(std::vector< double > &coords, std::vector< double > &bounds) const
Definition: geo_types.cpp:241
#define CHECK_GT(x, y)
Definition: Logger.h:202
std::string to_string(char const *&&v)
void set_output_srid(int s)
Definition: sqltypes.h:422
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:572
GeoLineString(const std::vector< double > &coords)
Definition: geo_types.cpp:219
void getColumns(std::vector< double > &coords, std::vector< int32_t > &ring_sizes, std::vector< double > &bounds) const
Definition: geo_types.cpp:305
CHECK(cgen_state)
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:326
GeoPoint(const std::vector< double > &coords)
Definition: geo_types.cpp:175
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
void getColumns(std::vector< double > &coords) const
Definition: geo_types.cpp:201
OGRGeometry * geom_
Definition: geo_types.h:59
int32_t getNumInteriorRings() const
Definition: geo_types.cpp:347
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:554
GeoPolygon(const std::vector< double > &coords, const std::vector< int32_t > &ring_sizes)
Definition: geo_types.cpp:273
int process_poly_ring(OGRLinearRing *ring, std::vector< double > &coords, BoundingBox *bbox)
Definition: geo_types.cpp:67
static std::string OGRErrorToStr(const int ogr_err)
Definition: geo_types.cpp:111