23 #include <ogr_geometry.h>
24 #include <ogrsf_frmts.h>
40 constexpr
auto DOUBLE_MAX = std::numeric_limits<double>::max();
41 constexpr
auto DOUBLE_MIN = std::numeric_limits<double>::lowest();
46 Coords(
double x,
double y) : x(x), y(y) {}
52 BoundingBox() : min(DOUBLE_MAX, DOUBLE_MAX), max(DOUBLE_MIN, DOUBLE_MIN) {}
71 std::vector<double>& coords,
74 size_t first_index = coords.size();
75 int num_points_added = 0;
76 int num_points_in_ring = ring->getNumPoints();
77 if (num_points_in_ring < 3) {
80 "All poly rings must have more than 3 points. Found ring with " +
83 for (
auto i = 0; i < num_points_in_ring; i++) {
85 ring->getPoint(i, &point);
86 last_x = point.getX();
87 last_y = point.getY();
88 coords.push_back(last_x);
89 coords.push_back(last_y);
91 bbox->
update(last_x, last_y);
96 if ((coords[first_index] == last_x) && (coords[first_index + 1] == last_y)) {
100 if (num_points_added < 3) {
103 "All exterior rings must have more than 3 points. Found ring with " +
107 return num_points_added;
112 namespace Geospatial {
115 std::map<std::tuple<int32_t, int32_t>, std::shared_ptr<OGRCoordinateTransformation>>
120 case OGRERR_NOT_ENOUGH_DATA:
121 return std::string(
"not enough input data");
122 case OGRERR_NOT_ENOUGH_MEMORY:
123 return std::string(
"not enough memory");
124 case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
125 return std::string(
"unsupported geometry type");
126 case OGRERR_UNSUPPORTED_OPERATION:
127 return std::string(
"unsupported operation");
128 case OGRERR_CORRUPT_DATA:
129 return std::string(
"corrupt input data");
131 return std::string(
"ogr failure");
132 case OGRERR_UNSUPPORTED_SRS:
133 return std::string(
"unsupported spatial reference system");
134 case OGRERR_INVALID_HANDLE:
135 return std::string(
"invalid file handle");
136 #if (GDAL_VERSION_MAJOR > 1)
137 case OGRERR_NON_EXISTING_FEATURE:
138 return std::string(
"feature does not exist in input geometry");
141 return std::string(
"Unknown OGOR error encountered: ") +
std::to_string(ogr_err);
150 OGRGeometryFactory::destroyGeometry(
geom_);
155 #if (GDAL_VERSION_MAJOR > 2) || (GDAL_VERSION_MAJOR == 2 && GDAL_VERSION_MINOR >= 3)
156 OGRErr ogr_status = OGRGeometryFactory::createFromWkt(wkt.c_str(),
nullptr, geom);
158 auto data = (
char*)wkt.c_str();
159 OGRErr ogr_status = OGRGeometryFactory::createFromWkt(&data, NULL, geom);
166 geom_->exportToWkt(&wkt);
168 std::string wkt_str(wkt);
174 #if (GDAL_VERSION_MAJOR > 2) || (GDAL_VERSION_MAJOR == 2 && GDAL_VERSION_MINOR >= 3)
176 OGRGeometryFactory::createFromWkb(wkb.data(),
nullptr, geom, wkb.size());
187 auto size =
geom_->WkbSize();
190 geom_->exportToWkb(wkbNDR, wkb.data());
208 #define SRID_WORLD_MERCATOR 999000
210 #define SRID_NORTH_UTM_START 999001
212 #define SRID_NORTH_UTM_END 999060
214 #define SRID_NORTH_LAMBERT 999061
216 #define SRID_SOUTH_UTM_START 999101
218 #define SRID_SOUTH_UTM_END 999160
220 #define SRID_SOUTH_LAMBERT 999161
222 #define SRID_LAEA_START 999163
224 #define SRID_LAEA_END 999283
230 double cx, cy, xwidth, ywidth;
231 OGREnvelope envelope;
232 geom_->getEnvelope(&envelope);
236 cx = (envelope.MaxX + envelope.MinX) / 2.0;
237 cy = (envelope.MaxY + envelope.MinY) / 2.0;
238 xwidth = envelope.MaxX - envelope.MinX;
239 ywidth = envelope.MaxY - envelope.MinY;
242 if (cy > 70.0 && ywidth < 45.0) {
246 if (cy < -70.0 && ywidth < 45.0) {
252 int zone = floor((cx + 180.0) / 6.0);
270 int zone = floor((cx + 180.0) / 6.0);
286 int yzone = 3 + floor(cy / 30.0);
287 if ((yzone == 2 || yzone == 3) && xwidth < 30.0) {
289 xzone = 6 + floor(cx / 30.0);
290 }
else if ((yzone == 1 || yzone == 4) && xwidth < 45.0) {
292 xzone = 4 + floor(cx / 45.0);
293 }
else if ((yzone == 0 || yzone == 5) && xwidth < 90.0) {
295 xzone = 2 + floor(cx / 90.0);
310 std::tuple<int32_t, int32_t> key{srid0, srid1};
315 auto setSpatialReference = [&](OGRSpatialReference* sr, int32_t srid) ->
bool {
316 OGRErr status = OGRERR_NONE;
318 status = sr->importFromEPSG(4326);
322 status = sr->importFromEPSG(3574);
326 status = sr->importFromEPSG(3409);
330 status = sr->importFromEPSG(32701 + zone);
334 status = sr->importFromEPSG(32601 + zone);
340 status = sr->importFromEPSG(3395);
344 status = sr->importFromEPSG(3395);
345 }
else if (srid > 0) {
347 status = sr->importFromEPSG(srid);
351 #if GDAL_VERSION_MAJOR >= 3
355 if (status == OGRERR_NONE) {
356 sr->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
359 return (status == OGRERR_NONE);
365 OGRSpatialReference sr0;
366 if (!setSpatialReference(&sr0, srid0)) {
369 OGRSpatialReference sr1;
370 if (!setSpatialReference(&sr1, srid1)) {
377 std::shared_ptr<OGRCoordinateTransformation> new_transformation;
378 new_transformation.reset(OGRCreateCoordinateTransformation(&sr0, &sr1));
380 return new_transformation;
385 if (!coordinate_transformation) {
388 auto ogr_status =
geom_->transform(coordinate_transformation.get());
389 return (ogr_status == OGRERR_NONE);
396 if (srid0 > 0 && srid0 != 4326) {
407 OGRGeometry*
result =
nullptr;
425 if (!result || result->IsEmpty() ||
426 !(result->getGeometryType() == wkbPolygon ||
427 result->getGeometryType() == wkbMultiPolygon)) {
433 "MULTIPOLYGON(((0 0,0.0000001 0,0 0.0000001)))");
441 OGRGeometry*
result =
nullptr;
444 auto gc1 =
geom_->toGeometryCollection();
445 auto gc2 = other.
geom_->toGeometryCollection();
446 if (!gc1 || !gc2 || gc1->IsEmpty() || gc2->IsEmpty()) {
449 for (
int i1 = 0; i1 < gc1->getNumGeometries(); i1++) {
450 auto g1 = gc1->getGeometryRef(i1);
452 if (!g1 || g1->IsEmpty() ) {
456 g1->getEnvelope(&ge1);
457 for (
int i2 = 0; i2 < gc2->getNumGeometries(); i2++) {
458 auto g2 = gc2->getGeometryRef(i2);
460 if (!g2 || g2->IsEmpty() ) {
465 g2->getEnvelope(&ge2);
466 if (!ge1.Intersects(ge2)) {
470 auto intermediate_result = g1->Intersection(g2);
471 if (!intermediate_result || intermediate_result->IsEmpty()) {
475 result = intermediate_result;
477 result = result->Union(intermediate_result);
483 if (!result || result->IsEmpty() ||
484 !(result->getGeometryType() == wkbPolygon ||
485 result->getGeometryType() == wkbMultiPolygon)) {
491 "MULTIPOLYGON(((0 0,0.0000001 0,0 0.0000001)))");
498 OGRGeometry*
result =
nullptr;
501 result =
geom_->Buffer(param);
507 if (!result || result->IsEmpty() ||
508 !(result->getGeometryType() == wkbPolygon ||
509 result->getGeometryType() == wkbMultiPolygon)) {
515 "MULTIPOLYGON(((0 0,0.0000001 0,0 0.0000001)))");
538 return std::unique_ptr<GeoBase>(
new GeoPoint(
geom_->clone(),
true));
542 if (coords.size() != 2) {
545 " supplied. Expected 2.");
547 geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbPoint);
548 OGRPoint* point =
dynamic_cast<OGRPoint*
>(
geom_);
550 point->setX(coords[0]);
551 point->setY(coords[1]);
556 if (err != OGRERR_NONE) {
560 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbPoint) {
562 "Unexpected geometry type from WKT string: " +
563 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
568 const auto point_geom =
dynamic_cast<OGRPoint*
>(
geom_);
571 if (point_geom->IsEmpty()) {
581 coords.push_back(point_geom->getX());
582 coords.push_back(point_geom->getY());
591 geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbLineString);
592 OGRLineString*
line =
dynamic_cast<OGRLineString*
>(
geom_);
594 for (
size_t i = 0; i < coords.size(); i += 2) {
595 line->addPoint(coords[i], coords[i + 1]);
601 if (err != OGRERR_NONE) {
605 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbLineString) {
607 "Unexpected geometry type from WKT string: " +
608 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
613 std::vector<double>& bounds)
const {
614 auto linestring_geom =
dynamic_cast<OGRLineString*
>(
geom_);
615 CHECK(linestring_geom);
617 if (linestring_geom->IsEmpty()) {
629 for (
auto i = 0; i < linestring_geom->getNumPoints(); i++) {
631 linestring_geom->getPoint(i, &point);
632 double x = point.getX();
633 double y = point.getY();
638 bounds.push_back(bbox.min.x);
639 bounds.push_back(bbox.min.y);
640 bounds.push_back(bbox.max.x);
641 bounds.push_back(bbox.max.y);
650 const std::vector<int32_t>& ring_sizes) {
651 geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbPolygon);
652 OGRPolygon* poly =
dynamic_cast<OGRPolygon*
>(
geom_);
655 size_t coords_ctr = 0;
656 for (
size_t r = 0; r < ring_sizes.size(); r++) {
658 const auto ring_sz = ring_sizes[r];
659 for (
auto i = 0; i < 2 * ring_sz; i += 2) {
660 ring.addPoint(coords[coords_ctr + i], coords[coords_ctr + i + 1]);
662 ring.addPoint(coords[coords_ctr], coords[coords_ctr + 1]);
663 coords_ctr += 2 * ring_sz;
664 poly->addRing(&ring);
670 if (err != OGRERR_NONE) {
674 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbPolygon) {
676 "Unexpected geometry type from WKT string: " +
677 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
682 std::vector<int32_t>& ring_sizes,
683 std::vector<double>& bounds)
const {
684 const auto poly_geom =
dynamic_cast<OGRPolygon*
>(
geom_);
687 if (poly_geom->IsEmpty()) {
699 const auto exterior_ring = poly_geom->getExteriorRing();
700 CHECK(exterior_ring);
702 if (exterior_ring->isClockwise()) {
703 exterior_ring->reverseWindingOrder();
706 ring_sizes.push_back(num_points_added);
707 for (
auto r = 0; r < poly_geom->getNumInteriorRings(); r++) {
708 auto interior_ring = poly_geom->getInteriorRing(r);
709 CHECK(interior_ring);
711 if (!interior_ring->isClockwise()) {
712 interior_ring->reverseWindingOrder();
715 ring_sizes.push_back(num_points_added);
717 bounds.push_back(bbox.min.x);
718 bounds.push_back(bbox.min.y);
719 bounds.push_back(bbox.max.x);
720 bounds.push_back(bbox.max.y);
724 const auto poly_geom =
dynamic_cast<OGRPolygon*
>(
geom_);
726 return poly_geom->getNumInteriorRings();
735 const std::vector<int32_t>& ring_sizes,
736 const std::vector<int32_t>& poly_rings) {
737 geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbMultiPolygon);
738 OGRMultiPolygon* multipoly =
dynamic_cast<OGRMultiPolygon*
>(
geom_);
742 size_t coords_ctr = 0;
743 for (
const auto& rings_in_poly : poly_rings) {
745 for (
auto r = 0; r < rings_in_poly; r++) {
747 const auto ring_sz = ring_sizes[ring_ctr];
748 for (
auto i = 0; i < 2 * ring_sz; i += 2) {
749 ring.addPoint(coords[coords_ctr + i], coords[coords_ctr + i + 1]);
751 ring.addPoint(coords[coords_ctr], coords[coords_ctr + 1]);
752 coords_ctr += 2 * ring_sz;
756 multipoly->addGeometry(&poly);
762 if (err != OGRERR_NONE) {
766 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbMultiPolygon) {
768 "Unexpected geometry type from WKT string: " +
769 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
774 std::vector<int32_t>& ring_sizes,
775 std::vector<int32_t>& poly_rings,
776 std::vector<double>& bounds)
const {
777 const auto mpoly =
dynamic_cast<OGRMultiPolygon*
>(
geom_);
780 if (mpoly->IsEmpty()) {
782 throw GeoTypesError(
"MultiPolygon",
"'EMPTY' not supported");
792 for (
auto p = 0; p < mpoly->getNumGeometries(); p++) {
793 const auto mpoly_geom = mpoly->getGeometryRef(p);
795 const auto poly_geom =
dynamic_cast<OGRPolygon*
>(mpoly_geom);
798 "Failed to read polygon geometry from multipolygon");
800 const auto exterior_ring = poly_geom->getExteriorRing();
801 CHECK(exterior_ring);
803 if (exterior_ring->isClockwise()) {
804 exterior_ring->reverseWindingOrder();
807 ring_sizes.push_back(num_points_added);
809 for (
auto r = 0; r < poly_geom->getNumInteriorRings(); r++) {
810 auto interior_ring = poly_geom->getInteriorRing(r);
811 CHECK(interior_ring);
813 if (!interior_ring->isClockwise()) {
814 interior_ring->reverseWindingOrder();
817 ring_sizes.push_back(num_points_added);
819 poly_rings.push_back(poly_geom->getNumInteriorRings() + 1);
821 bounds.push_back(bbox.min.x);
822 bounds.push_back(bbox.min.y);
823 bounds.push_back(bbox.max.x);
824 bounds.push_back(bbox.max.y);
839 if (err != OGRERR_NONE) {
843 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbGeometryCollection) {
845 "Unexpected geometry type from WKT string: " +
846 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
855 table_[
static_cast<int>(
'1')] = 1;
856 table_[
static_cast<int>(
'2')] = 2;
857 table_[
static_cast<int>(
'3')] = 3;
858 table_[
static_cast<int>(
'4')] = 4;
859 table_[
static_cast<int>(
'5')] = 5;
860 table_[
static_cast<int>(
'6')] = 6;
861 table_[
static_cast<int>(
'7')] = 7;
862 table_[
static_cast<int>(
'8')] = 8;
863 table_[
static_cast<int>(
'9')] = 9;
864 table_[
static_cast<int>(
'a')] = 10;
865 table_[
static_cast<int>(
'A')] = 10;
866 table_[
static_cast<int>(
'b')] = 11;
867 table_[
static_cast<int>(
'B')] = 11;
868 table_[
static_cast<int>(
'c')] = 12;
869 table_[
static_cast<int>(
'C')] = 12;
870 table_[
static_cast<int>(
'd')] = 13;
871 table_[
static_cast<int>(
'D')] = 13;
872 table_[
static_cast<int>(
'e')] = 14;
873 table_[
static_cast<int>(
'E')] = 14;
874 table_[
static_cast<int>(
'f')] = 15;
875 table_[
static_cast<int>(
'F')] = 15;
878 return (hex_digit < 0) ? 0 : table_[
static_cast<int>(hex_digit)];
885 return (hex_digit_to_decimal_table[usb] << 4) | hex_digit_to_decimal_table[lsb];
889 auto num_bytes = wkb_hex.size() >> 1;
890 std::vector<uint8_t> wkb(num_bytes);
891 auto* chars = wkb_hex.data();
892 auto* bytes = wkb.data();
893 for (
size_t i = 0; i < num_bytes; i++) {
894 auto const& usb = *chars++;
895 auto const& lsb = *chars++;
904 OGRGeometry* geom =
nullptr;
905 OGRErr err = OGRERR_NONE;
906 if (wkt_or_wkb_hex.empty()) {
907 err = OGRERR_NOT_ENOUGH_DATA;
908 }
else if (wkt_or_wkb_hex[0] ==
'0') {
913 if (err != OGRERR_NONE) {
920 const std::string& wkt_or_wkb_hex) {
925 OGRGeometry* geom =
nullptr;
927 if (err != OGRERR_NONE) {
939 std::vector<double>& coords,
940 std::vector<double>& bounds,
941 std::vector<int>& ring_sizes,
942 std::vector<int>& poly_rings,
943 const bool promote_poly_to_mpoly) {
945 if (wkt_or_wkb_hex.empty() || wkt_or_wkb_hex ==
"NULL") {
947 ti, coords, bounds, ring_sizes, poly_rings, promote_poly_to_mpoly);
953 if (!geospatial_base || !geospatial_base->transform(ti)) {
963 promote_poly_to_mpoly);
965 }
catch (
const std::exception& e) {
966 LOG(
ERROR) <<
"Geospatial Import Error: " << e.what();
975 std::vector<double>& coords,
976 std::vector<double>& bounds,
977 std::vector<int>& ring_sizes,
978 std::vector<int>& poly_rings,
979 const bool promote_poly_to_mpoly) {
983 if (!geospatial_base || !geospatial_base->transform(ti)) {
993 promote_poly_to_mpoly);
995 }
catch (
const std::exception& e) {
996 LOG(
ERROR) <<
"Geospatial Import Error: " << e.what();
1005 std::vector<double>& coords,
1006 std::vector<double>& bounds,
1007 std::vector<int>& ring_sizes,
1008 std::vector<int>& poly_rings,
1009 const bool promote_poly_to_mpoly) {
1013 if (!geospatial_base || !geospatial_base->transform(ti)) {
1023 promote_poly_to_mpoly);
1025 }
catch (
const std::exception& e) {
1026 LOG(
ERROR) <<
"Geospatial Import Error: " << e.what();
1035 std::vector<std::vector<double>>& coords_column,
1036 std::vector<std::vector<double>>& bounds_column,
1037 std::vector<std::vector<int>>& ring_sizes_column,
1038 std::vector<std::vector<int>>& poly_rings_column,
1039 const bool promote_poly_to_mpoly) {
1041 for (
const auto& wkt_or_wkb_hex : *wkt_or_wkb_hex_column) {
1042 std::vector<double> coords;
1043 std::vector<double> bounds;
1044 std::vector<int> ring_sizes;
1045 std::vector<int> poly_rings;
1054 promote_poly_to_mpoly);
1055 if (ti.
get_type() != row_ti.get_type()) {
1058 throw GeoTypesError(
"GeoFactory",
"Columnar: Geometry type mismatch");
1061 coords_column.push_back(coords);
1062 bounds_column.push_back(bounds);
1063 ring_sizes_column.push_back(ring_sizes);
1064 poly_rings_column.push_back(poly_rings);
1067 }
catch (
const std::exception& e) {
1068 LOG(
ERROR) <<
"Geospatial column Import Error: " << e.what();
1076 const bool owns_geom_obj) {
1077 switch (wkbFlatten(geom->getGeometryType())) {
1079 return std::unique_ptr<GeoPoint>(
new GeoPoint(geom, owns_geom_obj));
1081 return std::unique_ptr<GeoLineString>(
new GeoLineString(geom, owns_geom_obj));
1083 return std::unique_ptr<GeoPolygon>(
new GeoPolygon(geom, owns_geom_obj));
1084 case wkbMultiPolygon:
1085 return std::unique_ptr<GeoMultiPolygon>(
new GeoMultiPolygon(geom, owns_geom_obj));
1086 case wkbGeometryCollection:
1087 return std::unique_ptr<GeoGeometryCollection>(
1092 "Unrecognized geometry type: " + std::string(geom->getGeometryName()));
1098 std::vector<double>& coords,
1099 std::vector<double>& bounds,
1100 std::vector<int>& ring_sizes,
1101 std::vector<int>& poly_rings,
1102 const bool promote_poly_to_mpoly) {
1103 switch (geospatial_base->getType()) {
1105 const auto geospatial_point =
dynamic_cast<GeoPoint*
>(geospatial_base.get());
1106 CHECK(geospatial_point);
1107 geospatial_point->getColumns(coords);
1112 const auto geospatial_linestring =
1114 CHECK(geospatial_linestring);
1115 geospatial_linestring->getColumns(coords, bounds);
1120 const auto geospatial_poly =
dynamic_cast<GeoPolygon*
>(geospatial_base.get());
1121 CHECK(geospatial_poly);
1122 geospatial_poly->getColumns(coords, ring_sizes, bounds);
1123 if (promote_poly_to_mpoly) {
1124 if (ring_sizes.size()) {
1126 poly_rings.push_back(1 + geospatial_poly->getNumInteriorRings());
1133 const auto geospatial_mpoly =
dynamic_cast<GeoMultiPolygon*
>(geospatial_base.get());
1134 CHECK(geospatial_mpoly);
1135 geospatial_mpoly->getColumns(coords, ring_sizes, poly_rings, bounds);
1142 throw std::runtime_error(
"Unrecognized geospatial type");
1147 std::vector<double>& coords,
1148 std::vector<double>& bounds,
1149 std::vector<int>& ring_sizes,
1150 std::vector<int>& poly_rings,
1151 const bool promote_poly_to_mpoly) {
1171 throw std::runtime_error(
"Unsupported NULL geo");
std::unique_ptr< GeoBase > optimized_run(GeoOp op, const GeoBase &other) const
static std::unique_ptr< GeoBase > createGeoType(const std::string &wkt_or_wkb_hex)
GeoPoint(const std::vector< double > &coords)
void getColumns(std::vector< double > &coords) const
int32_t getNumInteriorRings() const
#define SRID_NORTH_UTM_END
GeoMultiPolygon(const std::vector< double > &coords, const std::vector< int32_t > &ring_sizes, const std::vector< int32_t > &poly_rings)
constexpr auto DOUBLE_MAX
constexpr HexDigitToDecimalTable hex_digit_to_decimal_table
GeoLineString(const std::vector< double > &coords)
GeoGeometryCollection(const std::vector< double > &coords, const std::vector< int32_t > &ring_sizes, const std::vector< int32_t > &poly_rings, const std::vector< int32_t > &geo_kinds)
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)
Constants for Builtin SQL Types supported by HEAVY.AI.
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)
HOST DEVICE SQLTypes get_type() const
static std::unique_ptr< Geospatial::GeoBase > createGeoTypeImpl(OGRGeometry *geom, const bool owns_geom_obj=true)
bool getWkb(std::vector< uint8_t > &) const
constexpr uint8_t operator[](const char &hex_digit) const
static std::shared_ptr< OGRCoordinateTransformation > getTransformation(int32_t srid0, int32_t srid1)
std::unique_ptr< GeoBase > clone() const final
int process_poly_ring(OGRLinearRing *ring, std::vector< double > &coords, BoundingBox *bbox)
Coords(double x, double y)
void update(double x, double y)
static std::string OGRErrorToStr(const int ogr_err)
GeoGeometry(const std::vector< double > &coords, const std::vector< int32_t > &ring_sizes, const std::vector< int32_t > &poly_rings, const std::vector< int32_t > &geo_kinds)
#define SRID_NORTH_UTM_START
static int createFromWkb(const std::vector< uint8_t > &wkb, OGRGeometry **geom)
std::unique_ptr< GeoBase > clone() const override
void getColumns(std::vector< double > &coords, std::vector< int32_t > &ring_sizes, std::vector< int32_t > &poly_rings, std::vector< double > &bounds) const
static bool getGeoColumns(const std::string &wkt_or_wkb_hex, 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)
virtual bool operator==(const GeoBase &other) const
static OGRGeometry * createOGRGeometry(const std::string &wkt_or_wkb_hex)
std::unique_ptr< GeoBase > clone() const final
static int createFromWktString(const std::string &wkt, OGRGeometry **geom)
void getColumns(std::vector< double > &coords, std::vector< double > &bounds) const
constexpr HexDigitToDecimalTable()
std::mutex transformation_map_mutex_
std::unique_ptr< GeoBase > clone() const final
constexpr auto DOUBLE_MIN
HOST DEVICE int get_input_srid() const
bool transform(int32_t srid0, int32_t srid1)
#define NULL_ARRAY_DOUBLE
#define SRID_SOUTH_UTM_START
#define SRID_SOUTH_UTM_END
std::string getWktString() const
#define SRID_SOUTH_LAMBERT
#define SRID_WORLD_MERCATOR
std::unique_ptr< GeoBase > clone() const final
uint8_t hex_to_binary(const char &usb, const char &lsb)
std::unique_ptr< GeoBase > run(GeoOp op, const GeoBase &other) const
#define SRID_NORTH_LAMBERT
std::map< std::tuple< int32_t, int32_t >, std::shared_ptr< OGRCoordinateTransformation > > transformation_map_
std::unique_ptr< GeoBase > clone() const final
std::vector< uint8_t > hex_string_to_binary_vector(const std::string &wkb_hex)
void getColumns(std::vector< double > &coords, std::vector< int32_t > &ring_sizes, std::vector< double > &bounds) const
int32_t getBestPlanarSRID() const
GeoPolygon(const std::vector< double > &coords, const std::vector< int32_t > &ring_sizes)
HOST DEVICE int get_output_srid() const
HOST DEVICE void set_type(SQLTypes t)