24 #include <ogr_geometry.h>
25 #include <ogrsf_frmts.h>
41 constexpr
auto DOUBLE_MAX = std::numeric_limits<double>::max();
42 constexpr
auto DOUBLE_MIN = std::numeric_limits<double>::lowest();
47 Coords(
double x,
double y) : x(x), y(y) {}
53 BoundingBox() : min(DOUBLE_MAX, DOUBLE_MAX), max(DOUBLE_MIN, DOUBLE_MIN) {}
72 std::vector<double>& coords,
75 size_t first_index = coords.size();
76 int num_points_added = 0;
77 int num_points_in_ring = ring->getNumPoints();
78 if (num_points_in_ring < 3) {
81 "All poly rings must have more than 3 points. Found ring with " +
84 for (
auto i = 0; i < num_points_in_ring; i++) {
86 ring->getPoint(i, &point);
87 last_x = point.getX();
88 last_y = point.getY();
89 coords.push_back(last_x);
90 coords.push_back(last_y);
92 bbox->
update(last_x, last_y);
97 if ((coords[first_index] == last_x) && (coords[first_index + 1] == last_y)) {
101 if (num_points_added < 3) {
104 "All exterior rings must have more than 3 points. Found ring with " +
108 return num_points_added;
113 namespace Geospatial {
116 std::map<std::tuple<int32_t, int32_t>, std::shared_ptr<OGRCoordinateTransformation>>
121 case OGRERR_NOT_ENOUGH_DATA:
122 return std::string(
"not enough input data");
123 case OGRERR_NOT_ENOUGH_MEMORY:
124 return std::string(
"not enough memory");
125 case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
126 return std::string(
"unsupported geometry type");
127 case OGRERR_UNSUPPORTED_OPERATION:
128 return std::string(
"unsupported operation");
129 case OGRERR_CORRUPT_DATA:
130 return std::string(
"corrupt input data");
132 return std::string(
"ogr failure");
133 case OGRERR_UNSUPPORTED_SRS:
134 return std::string(
"unsupported spatial reference system");
135 case OGRERR_INVALID_HANDLE:
136 return std::string(
"invalid file handle");
137 #if (GDAL_VERSION_MAJOR > 1)
138 case OGRERR_NON_EXISTING_FEATURE:
139 return std::string(
"feature does not exist in input geometry");
142 return std::string(
"Unknown OGOR error encountered: ") +
std::to_string(ogr_err);
151 OGRGeometryFactory::destroyGeometry(
geom_);
156 #if (GDAL_VERSION_MAJOR > 2) || (GDAL_VERSION_MAJOR == 2 && GDAL_VERSION_MINOR >= 3)
157 OGRErr ogr_status = OGRGeometryFactory::createFromWkt(wkt.c_str(),
nullptr, geom);
159 auto data = (
char*)wkt.c_str();
160 OGRErr ogr_status = OGRGeometryFactory::createFromWkt(&data, NULL, geom);
167 geom_->exportToWkt(&wkt);
169 std::string wkt_str(wkt);
175 #if (GDAL_VERSION_MAJOR > 2) || (GDAL_VERSION_MAJOR == 2 && GDAL_VERSION_MINOR >= 3)
177 OGRGeometryFactory::createFromWkb(wkb_view.
ptr_,
nullptr, geom, wkb_view.
size_);
188 auto size =
geom_->WkbSize();
191 geom_->exportToWkb(wkbNDR, wkb.data());
209 #define SRID_WORLD_MERCATOR 999000
211 #define SRID_NORTH_UTM_START 999001
213 #define SRID_NORTH_UTM_END 999060
215 #define SRID_NORTH_LAMBERT 999061
217 #define SRID_SOUTH_UTM_START 999101
219 #define SRID_SOUTH_UTM_END 999160
221 #define SRID_SOUTH_LAMBERT 999161
223 #define SRID_LAEA_START 999163
225 #define SRID_LAEA_END 999283
231 double cx, cy, xwidth, ywidth;
232 OGREnvelope envelope;
233 geom_->getEnvelope(&envelope);
237 cx = (envelope.MaxX + envelope.MinX) / 2.0;
238 cy = (envelope.MaxY + envelope.MinY) / 2.0;
239 xwidth = envelope.MaxX - envelope.MinX;
240 ywidth = envelope.MaxY - envelope.MinY;
243 if (cy > 70.0 && ywidth < 45.0) {
247 if (cy < -70.0 && ywidth < 45.0) {
253 int zone = floor((cx + 180.0) / 6.0);
271 int zone = floor((cx + 180.0) / 6.0);
287 int yzone = 3 + floor(cy / 30.0);
288 if ((yzone == 2 || yzone == 3) && xwidth < 30.0) {
290 xzone = 6 + floor(cx / 30.0);
291 }
else if ((yzone == 1 || yzone == 4) && xwidth < 45.0) {
293 xzone = 4 + floor(cx / 45.0);
294 }
else if ((yzone == 0 || yzone == 5) && xwidth < 90.0) {
296 xzone = 2 + floor(cx / 90.0);
311 std::tuple<int32_t, int32_t> key{srid0, srid1};
316 auto setSpatialReference = [&](OGRSpatialReference* sr, int32_t srid) ->
bool {
317 OGRErr status = OGRERR_NONE;
319 status = sr->importFromEPSG(4326);
323 status = sr->importFromEPSG(3574);
327 status = sr->importFromEPSG(3409);
331 status = sr->importFromEPSG(32701 + zone);
335 status = sr->importFromEPSG(32601 + zone);
341 status = sr->importFromEPSG(3395);
345 status = sr->importFromEPSG(3395);
346 }
else if (srid > 0) {
348 status = sr->importFromEPSG(srid);
352 #if GDAL_VERSION_MAJOR >= 3
356 if (status == OGRERR_NONE) {
357 sr->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
360 return (status == OGRERR_NONE);
366 OGRSpatialReference sr0;
367 if (!setSpatialReference(&sr0, srid0)) {
370 OGRSpatialReference sr1;
371 if (!setSpatialReference(&sr1, srid1)) {
378 std::shared_ptr<OGRCoordinateTransformation> new_transformation;
379 new_transformation.reset(OGRCreateCoordinateTransformation(&sr0, &sr1));
381 return new_transformation;
386 if (!coordinate_transformation) {
389 auto ogr_status =
geom_->transform(coordinate_transformation.get());
390 return (ogr_status == OGRERR_NONE);
397 if (srid0 > 0 && srid0 != 4326) {
408 OGRGeometry*
result =
nullptr;
426 if (!result || result->IsEmpty() ||
427 !(result->getGeometryType() == wkbPolygon ||
428 result->getGeometryType() == wkbMultiPolygon)) {
442 OGRGeometry*
result =
nullptr;
445 auto gc1 =
geom_->toGeometryCollection();
446 auto gc2 = other.
geom_->toGeometryCollection();
447 if (!gc1 || !gc2 || gc1->IsEmpty() || gc2->IsEmpty()) {
450 for (
int i1 = 0; i1 < gc1->getNumGeometries(); i1++) {
451 auto g1 = gc1->getGeometryRef(i1);
453 if (!g1 || g1->IsEmpty() ) {
457 g1->getEnvelope(&ge1);
458 for (
int i2 = 0; i2 < gc2->getNumGeometries(); i2++) {
459 auto g2 = gc2->getGeometryRef(i2);
461 if (!g2 || g2->IsEmpty() ) {
466 g2->getEnvelope(&ge2);
467 if (!ge1.Intersects(ge2)) {
471 auto intermediate_result = g1->Intersection(g2);
472 if (!intermediate_result || intermediate_result->IsEmpty()) {
476 result = intermediate_result;
478 result = result->Union(intermediate_result);
484 if (!result || result->IsEmpty() ||
485 !(result->getGeometryType() == wkbPolygon ||
486 result->getGeometryType() == wkbMultiPolygon)) {
499 OGRGeometry*
result =
nullptr;
502 result =
geom_->Buffer(param);
508 if (!result || result->IsEmpty() ||
509 !(result->getGeometryType() == wkbPolygon ||
510 result->getGeometryType() == wkbMultiPolygon)) {
539 return std::unique_ptr<GeoBase>(
new GeoPoint(
geom_->clone(),
true));
543 if (coords.size() != 2) {
546 " supplied. Expected 2.");
548 geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbPoint);
549 OGRPoint* point =
dynamic_cast<OGRPoint*
>(
geom_);
551 point->setX(coords[0]);
552 point->setY(coords[1]);
557 if (err != OGRERR_NONE) {
561 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbPoint) {
563 "Unexpected geometry type from WKT string: " +
564 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
569 const auto point_geom =
dynamic_cast<OGRPoint*
>(
geom_);
572 if (point_geom->IsEmpty()) {
582 coords.push_back(point_geom->getX());
583 coords.push_back(point_geom->getY());
592 geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbMultiPoint);
593 OGRMultiPoint* multipoint =
dynamic_cast<OGRMultiPoint*
>(
geom_);
595 for (
size_t i = 0; i < coords.size(); i += 2) {
596 OGRPoint pt(coords[i], coords[i + 1]);
597 multipoint->addGeometry(&pt);
603 if (err != OGRERR_NONE) {
607 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbMultiPoint) {
609 "Unexpected geometry type from WKT string: " +
610 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
615 std::vector<double>& bounds)
const {
616 auto multipoint_geom =
dynamic_cast<OGRMultiPoint*
>(
geom_);
617 CHECK(multipoint_geom);
619 if (multipoint_geom->IsEmpty()) {
631 for (
auto i = 0; i < multipoint_geom->getNumGeometries(); i++) {
632 OGRPoint* point =
dynamic_cast<OGRPoint*
>(multipoint_geom->getGeometryRef(i));
634 double x = point->getX();
635 double y = point->getY();
640 bounds.push_back(bbox.min.x);
641 bounds.push_back(bbox.min.y);
642 bounds.push_back(bbox.max.x);
643 bounds.push_back(bbox.max.y);
652 geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbLineString);
653 OGRLineString*
line =
dynamic_cast<OGRLineString*
>(
geom_);
655 for (
size_t i = 0; i < coords.size(); i += 2) {
656 line->addPoint(coords[i], coords[i + 1]);
662 if (err != OGRERR_NONE) {
666 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbLineString) {
668 "Unexpected geometry type from WKT string: " +
669 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
674 std::vector<double>& bounds)
const {
675 auto linestring_geom =
dynamic_cast<OGRLineString*
>(
geom_);
676 CHECK(linestring_geom);
678 if (linestring_geom->IsEmpty()) {
690 for (
auto i = 0; i < linestring_geom->getNumPoints(); i++) {
692 linestring_geom->getPoint(i, &point);
693 double x = point.getX();
694 double y = point.getY();
699 bounds.push_back(bbox.min.x);
700 bounds.push_back(bbox.min.y);
701 bounds.push_back(bbox.max.x);
702 bounds.push_back(bbox.max.y);
711 const std::vector<int32_t>& linestring_sizes) {
712 geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbMultiLineString);
713 OGRMultiLineString* multilinestring =
dynamic_cast<OGRMultiLineString*
>(
geom_);
714 CHECK(multilinestring);
716 size_t coords_ctr = 0;
717 for (
const auto linestring_sz : linestring_sizes) {
718 OGRLineString linestring;
719 auto next_coords_ctr = coords_ctr + 2 * linestring_sz;
720 CHECK(next_coords_ctr <= coords.size());
721 for (
auto i = coords_ctr; i < next_coords_ctr; i += 2) {
722 linestring.addPoint(coords[i], coords[i + 1]);
724 coords_ctr = next_coords_ctr;
725 multilinestring->addGeometry(&linestring);
731 if (err != OGRERR_NONE) {
735 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbMultiLineString) {
737 "Unexpected geometry type from WKT string: " +
738 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
743 std::vector<int32_t>& linestring_sizes,
744 std::vector<double>& bounds)
const {
745 auto multilinestring =
dynamic_cast<OGRMultiLineString*
>(
geom_);
746 CHECK(multilinestring);
748 if (multilinestring->IsEmpty()) {
750 throw GeoTypesError(
"MultiLineString",
"'EMPTY' not supported");
760 for (
auto l = 0; l < multilinestring->getNumGeometries(); l++) {
761 const auto geom = multilinestring->getGeometryRef(l);
763 const auto linestring =
dynamic_cast<OGRLineString*
>(geom);
766 "Failed to read linestring geometry from multilinestring");
768 auto linestring_sz = linestring->getNumPoints();
769 linestring_sizes.push_back(linestring_sz);
770 for (
auto i = 0; i < linestring_sz; i++) {
772 linestring->getPoint(i, &point);
773 double x = point.getX();
774 double y = point.getY();
780 bounds.push_back(bbox.min.x);
781 bounds.push_back(bbox.min.y);
782 bounds.push_back(bbox.max.x);
783 bounds.push_back(bbox.max.y);
792 const std::vector<int32_t>& ring_sizes) {
793 geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbPolygon);
794 OGRPolygon* poly =
dynamic_cast<OGRPolygon*
>(
geom_);
797 size_t coords_ctr = 0;
798 for (
size_t r = 0; r < ring_sizes.size(); r++) {
800 const auto ring_sz = ring_sizes[r];
801 for (
auto i = 0; i < 2 * ring_sz; i += 2) {
802 ring.addPoint(coords[coords_ctr + i], coords[coords_ctr + i + 1]);
804 ring.addPoint(coords[coords_ctr], coords[coords_ctr + 1]);
805 coords_ctr += 2 * ring_sz;
806 poly->addRing(&ring);
812 if (err != OGRERR_NONE) {
816 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbPolygon) {
818 "Unexpected geometry type from WKT string: " +
819 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
824 std::vector<int32_t>& ring_sizes,
825 std::vector<double>& bounds)
const {
826 const auto poly_geom =
dynamic_cast<OGRPolygon*
>(
geom_);
829 if (poly_geom->IsEmpty()) {
841 const auto exterior_ring = poly_geom->getExteriorRing();
842 CHECK(exterior_ring);
844 if (exterior_ring->isClockwise()) {
845 exterior_ring->reverseWindingOrder();
848 ring_sizes.push_back(num_points_added);
849 for (
auto r = 0; r < poly_geom->getNumInteriorRings(); r++) {
850 auto interior_ring = poly_geom->getInteriorRing(r);
851 CHECK(interior_ring);
853 if (!interior_ring->isClockwise()) {
854 interior_ring->reverseWindingOrder();
857 ring_sizes.push_back(num_points_added);
859 bounds.push_back(bbox.min.x);
860 bounds.push_back(bbox.min.y);
861 bounds.push_back(bbox.max.x);
862 bounds.push_back(bbox.max.y);
866 const auto poly_geom =
dynamic_cast<OGRPolygon*
>(
geom_);
868 return poly_geom->getNumInteriorRings();
877 const std::vector<int32_t>& ring_sizes,
878 const std::vector<int32_t>& poly_rings) {
879 geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbMultiPolygon);
880 OGRMultiPolygon* multipoly =
dynamic_cast<OGRMultiPolygon*
>(
geom_);
884 size_t coords_ctr = 0;
885 for (
const auto& rings_in_poly : poly_rings) {
887 for (
auto r = 0; r < rings_in_poly; r++) {
889 const auto ring_sz = ring_sizes[ring_ctr];
890 for (
auto i = 0; i < 2 * ring_sz; i += 2) {
891 ring.addPoint(coords[coords_ctr + i], coords[coords_ctr + i + 1]);
893 ring.addPoint(coords[coords_ctr], coords[coords_ctr + 1]);
894 coords_ctr += 2 * ring_sz;
898 multipoly->addGeometry(&poly);
904 if (err != OGRERR_NONE) {
908 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbMultiPolygon) {
910 "Unexpected geometry type from WKT string: " +
911 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
916 std::vector<int32_t>& ring_sizes,
917 std::vector<int32_t>& poly_rings,
918 std::vector<double>& bounds)
const {
919 const auto mpoly =
dynamic_cast<OGRMultiPolygon*
>(
geom_);
922 if (mpoly->IsEmpty()) {
924 throw GeoTypesError(
"MultiPolygon",
"'EMPTY' not supported");
934 for (
auto p = 0; p < mpoly->getNumGeometries(); p++) {
935 const auto mpoly_geom = mpoly->getGeometryRef(p);
937 const auto poly_geom =
dynamic_cast<OGRPolygon*
>(mpoly_geom);
940 "Failed to read polygon geometry from multipolygon");
942 const auto exterior_ring = poly_geom->getExteriorRing();
943 CHECK(exterior_ring);
945 if (exterior_ring->isClockwise()) {
946 exterior_ring->reverseWindingOrder();
949 ring_sizes.push_back(num_points_added);
951 for (
auto r = 0; r < poly_geom->getNumInteriorRings(); r++) {
952 auto interior_ring = poly_geom->getInteriorRing(r);
953 CHECK(interior_ring);
955 if (!interior_ring->isClockwise()) {
956 interior_ring->reverseWindingOrder();
959 ring_sizes.push_back(num_points_added);
961 poly_rings.push_back(poly_geom->getNumInteriorRings() + 1);
963 bounds.push_back(bbox.min.x);
964 bounds.push_back(bbox.min.y);
965 bounds.push_back(bbox.max.x);
966 bounds.push_back(bbox.max.y);
981 if (err != OGRERR_NONE) {
985 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbGeometryCollection) {
987 "Unexpected geometry type from WKT string: " +
988 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
997 table_[
static_cast<int>(
'1')] = 1;
998 table_[
static_cast<int>(
'2')] = 2;
999 table_[
static_cast<int>(
'3')] = 3;
1000 table_[
static_cast<int>(
'4')] = 4;
1001 table_[
static_cast<int>(
'5')] = 5;
1002 table_[
static_cast<int>(
'6')] = 6;
1003 table_[
static_cast<int>(
'7')] = 7;
1004 table_[
static_cast<int>(
'8')] = 8;
1005 table_[
static_cast<int>(
'9')] = 9;
1006 table_[
static_cast<int>(
'a')] = 10;
1007 table_[
static_cast<int>(
'A')] = 10;
1008 table_[
static_cast<int>(
'b')] = 11;
1009 table_[
static_cast<int>(
'B')] = 11;
1010 table_[
static_cast<int>(
'c')] = 12;
1011 table_[
static_cast<int>(
'C')] = 12;
1012 table_[
static_cast<int>(
'd')] = 13;
1013 table_[
static_cast<int>(
'D')] = 13;
1014 table_[
static_cast<int>(
'e')] = 14;
1015 table_[
static_cast<int>(
'E')] = 14;
1016 table_[
static_cast<int>(
'f')] = 15;
1017 table_[
static_cast<int>(
'F')] = 15;
1020 return (hex_digit < 0) ? 0 : table_[
static_cast<int>(hex_digit)];
1027 return (hex_digit_to_decimal_table[usb] << 4) | hex_digit_to_decimal_table[lsb];
1031 auto num_bytes = wkb_hex.size() >> 1;
1032 std::vector<uint8_t> wkb(num_bytes);
1033 auto* chars = wkb_hex.data();
1034 auto* bytes = wkb.data();
1035 for (
size_t i = 0; i < num_bytes; i++) {
1036 auto const& usb = *chars++;
1037 auto const& lsb = *chars++;
1044 auto const wkb_type = wkbFlatten(geom->getGeometryType());
1046 return (wkb_type == wkbPolygon) || (wkb_type == wkbMultiPolygon);
1052 auto const wkb_size = geom->WkbSize();
1053 std::vector<unsigned char> wkb(wkb_size);
1054 auto const err = geom->exportToWkb(wkbNDR, wkb.data());
1064 const std::string& wkt_or_wkb_hex,
1065 const bool validate_with_geos_if_available) {
1066 OGRGeometry* geom =
nullptr;
1067 OGRErr err = OGRERR_NONE;
1068 if (wkt_or_wkb_hex.empty()) {
1069 err = OGRERR_NOT_ENOUGH_DATA;
1070 }
else if (wkt_or_wkb_hex[0] ==
'0') {
1076 if (err != OGRERR_NONE) {
1079 if (validate_with_geos_if_available) {
1086 const std::string& wkt_or_wkb_hex,
1087 const bool validate_with_geos_if_available) {
1090 if (validate_with_geos_if_available) {
1098 const bool validate_with_geos_if_available) {
1099 OGRGeometry* geom =
nullptr;
1101 if (err != OGRERR_NONE) {
1105 if (validate_with_geos_if_available) {
1113 const bool validate_with_geos_if_available) {
1115 if (validate_with_geos_if_available) {
1123 std::vector<double>& coords,
1124 std::vector<double>& bounds,
1125 std::vector<int>& ring_sizes,
1126 std::vector<int>& poly_rings,
1127 const bool validate_with_geos_if_available) {
1129 if (wkt_or_wkb_hex.empty() || wkt_or_wkb_hex ==
"NULL") {
1134 const auto geospatial_base =
1137 if (!geospatial_base || !geospatial_base->transform(ti)) {
1143 }
catch (
const std::exception& e) {
1144 LOG(
ERROR) <<
"Geospatial Import Error: " << e.what();
1153 std::vector<double>& coords,
1154 std::vector<double>& bounds,
1155 std::vector<int>& ring_sizes,
1156 std::vector<int>& poly_rings,
1157 const bool validate_with_geos_if_available) {
1160 {wkb.data(), wkb.size()}, validate_with_geos_if_available);
1162 if (!geospatial_base || !geospatial_base->transform(ti)) {
1168 }
catch (
const std::exception& e) {
1169 LOG(
ERROR) <<
"Geospatial Import Error: " << e.what();
1178 std::vector<double>& coords,
1179 std::vector<double>& bounds,
1180 std::vector<int>& ring_sizes,
1181 std::vector<int>& poly_rings,
1182 const bool validate_with_geos_if_available) {
1184 const auto geospatial_base =
1187 if (!geospatial_base || !geospatial_base->transform(ti)) {
1193 }
catch (
const std::exception& e) {
1194 LOG(
ERROR) <<
"Geospatial Import Error: " << e.what();
1203 std::vector<std::vector<double>>& coords_column,
1204 std::vector<std::vector<double>>& bounds_column,
1205 std::vector<std::vector<int>>& ring_sizes_column,
1206 std::vector<std::vector<int>>& poly_rings_column,
1207 const bool validate_with_geos_if_available) {
1209 for (
const auto& wkt_or_wkb_hex : *wkt_or_wkb_hex_column) {
1210 std::vector<double> coords;
1211 std::vector<double> bounds;
1212 std::vector<int> ring_sizes;
1213 std::vector<int> poly_rings;
1222 validate_with_geos_if_available);
1225 throw GeoTypesError(
"GeoFactory",
"Columnar: Geometry type mismatch");
1227 coords_column.push_back(coords);
1228 bounds_column.push_back(bounds);
1229 ring_sizes_column.push_back(ring_sizes);
1230 poly_rings_column.push_back(poly_rings);
1233 }
catch (
const std::exception& e) {
1234 LOG(
ERROR) <<
"Geospatial column Import Error: " << e.what();
1242 const bool owns_geom_obj) {
1243 switch (wkbFlatten(geom->getGeometryType())) {
1245 return std::unique_ptr<GeoPoint>(
new GeoPoint(geom, owns_geom_obj));
1247 return std::unique_ptr<GeoMultiPoint>(
new GeoMultiPoint(geom, owns_geom_obj));
1249 return std::unique_ptr<GeoLineString>(
new GeoLineString(geom, owns_geom_obj));
1250 case wkbMultiLineString:
1251 return std::unique_ptr<GeoMultiLineString>(
1254 return std::unique_ptr<GeoPolygon>(
new GeoPolygon(geom, owns_geom_obj));
1255 case wkbMultiPolygon:
1256 return std::unique_ptr<GeoMultiPolygon>(
new GeoMultiPolygon(geom, owns_geom_obj));
1257 case wkbGeometryCollection:
1258 return std::unique_ptr<GeoGeometryCollection>(
1263 "Unrecognized geometry type: " + std::string(geom->getGeometryName()));
1269 std::vector<double>& coords,
1270 std::vector<double>& bounds,
1271 std::vector<int>& ring_sizes,
1272 std::vector<int>& poly_rings) {
1273 switch (geospatial_base->getType()) {
1275 const auto geospatial_point =
dynamic_cast<GeoPoint*
>(geospatial_base.get());
1276 CHECK(geospatial_point);
1277 geospatial_point->getColumns(coords);
1282 bounds.push_back(coords[0]);
1283 bounds.push_back(coords[1]);
1284 bounds.push_back(coords[0]);
1285 bounds.push_back(coords[1]);
1289 const auto geospatial_multipoint =
1291 CHECK(geospatial_multipoint);
1292 geospatial_multipoint->getColumns(coords, bounds);
1297 const auto geospatial_linestring =
1299 CHECK(geospatial_linestring);
1300 geospatial_linestring->getColumns(coords, bounds);
1303 ring_sizes.push_back(coords.size() / 2);
1307 const auto geospatial_multilinestring =
1309 CHECK(geospatial_multilinestring);
1310 geospatial_multilinestring->getColumns(coords, ring_sizes, bounds);
1315 const auto geospatial_poly =
dynamic_cast<GeoPolygon*
>(geospatial_base.get());
1316 CHECK(geospatial_poly);
1317 geospatial_poly->getColumns(coords, ring_sizes, bounds);
1320 if (ring_sizes.size()) {
1322 poly_rings.push_back(1 + geospatial_poly->getNumInteriorRings());
1324 poly_rings.push_back(0);
1329 const auto geospatial_mpoly =
dynamic_cast<GeoMultiPolygon*
>(geospatial_base.get());
1330 CHECK(geospatial_mpoly);
1331 geospatial_mpoly->getColumns(coords, ring_sizes, poly_rings, bounds);
1338 throw std::runtime_error(
"Unrecognized geospatial type");
1343 std::vector<double>& coords,
1344 std::vector<double>& bounds,
1345 std::vector<int>& ring_sizes,
1346 std::vector<int>& poly_rings) {
1368 throw std::runtime_error(
"Unsupported NULL geo");
std::unique_ptr< GeoBase > clone() const final
bool geo_promoted_type_match(const SQLTypes a, const SQLTypes b)
std::unique_ptr< GeoBase > optimized_run(GeoOp op, const GeoBase &other) 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
GeoMultiPoint(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)
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)
HOST DEVICE SQLTypes get_type() const
void validate_ogr(const OGRGeometry *geom)
static std::unique_ptr< Geospatial::GeoBase > createGeoTypeImpl(OGRGeometry *geom, const bool owns_geom_obj=true)
bool getWkb(std::vector< uint8_t > &) const
void getColumns(std::vector< double > &coords) 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
GeoMultiLineString(const std::vector< double > &coords, const std::vector< int32_t > &linestring_sizes)
bool geos_validate_wkb(const unsigned char *, const size_t)
bool validation_enabled_for_type(const OGRGeometry *geom)
bool geos_validation_available()
int process_poly_ring(OGRLinearRing *ring, std::vector< double > &coords, BoundingBox *bbox)
Coords(double x, double y)
std::unique_ptr< GeoBase > clone() const final
static int createFromWkbView(OGRGeometry **geom, WkbView const)
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)
void getColumns(std::vector< double > &coords, std::vector< double > &bounds) const
void update(double x, double y)
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 validate_with_geos_if_available)
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
void getColumns(std::vector< double > &coords, std::vector< int32_t > &ring_sizes, std::vector< int32_t > &poly_rings, std::vector< double > &bounds) const
std::unique_ptr< GeoBase > clone() const override
void getColumns(std::vector< double > &coords, std::vector< double > &bounds) const
virtual bool operator==(const GeoBase &other) const
std::unique_ptr< GeoBase > clone() const final
std::unique_ptr< GeoBase > clone() const final
static std::unique_ptr< GeoBase > createGeoType(const std::string &wkt_or_wkb_hex, const bool validate_with_geos_if_available)
static int createFromWktString(const std::string &wkt, OGRGeometry **geom)
void getColumns(std::vector< double > &coords, std::vector< int32_t > &linestring_sizes, std::vector< double > &bounds) const
static OGRGeometry * createOGRGeometry(const std::string &wkt_or_wkb_hex, const bool validate_with_geos_if_available)
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
GeoPoint(const std::vector< double > &coords)
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
GeoLineString(const std::vector< double > &coords)
HOST DEVICE void set_type(SQLTypes t)