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_view.
ptr_,
nullptr, geom, wkb_view.
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::wkbMultiPoint);
592 OGRMultiPoint* multipoint =
dynamic_cast<OGRMultiPoint*
>(
geom_);
594 for (
size_t i = 0; i < coords.size(); i += 2) {
595 OGRPoint pt(coords[i], coords[i + 1]);
596 multipoint->addGeometry(&pt);
602 if (err != OGRERR_NONE) {
606 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbMultiPoint) {
608 "Unexpected geometry type from WKT string: " +
609 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
614 std::vector<double>& bounds)
const {
615 auto multipoint_geom =
dynamic_cast<OGRMultiPoint*
>(
geom_);
616 CHECK(multipoint_geom);
618 if (multipoint_geom->IsEmpty()) {
630 for (
auto i = 0; i < multipoint_geom->getNumGeometries(); i++) {
631 OGRPoint* point =
dynamic_cast<OGRPoint*
>(multipoint_geom->getGeometryRef(i));
633 double x = point->getX();
634 double y = point->getY();
639 bounds.push_back(bbox.min.x);
640 bounds.push_back(bbox.min.y);
641 bounds.push_back(bbox.max.x);
642 bounds.push_back(bbox.max.y);
651 geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbLineString);
652 OGRLineString*
line =
dynamic_cast<OGRLineString*
>(
geom_);
654 for (
size_t i = 0; i < coords.size(); i += 2) {
655 line->addPoint(coords[i], coords[i + 1]);
661 if (err != OGRERR_NONE) {
665 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbLineString) {
667 "Unexpected geometry type from WKT string: " +
668 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
673 std::vector<double>& bounds)
const {
674 auto linestring_geom =
dynamic_cast<OGRLineString*
>(
geom_);
675 CHECK(linestring_geom);
677 if (linestring_geom->IsEmpty()) {
689 for (
auto i = 0; i < linestring_geom->getNumPoints(); i++) {
691 linestring_geom->getPoint(i, &point);
692 double x = point.getX();
693 double y = point.getY();
698 bounds.push_back(bbox.min.x);
699 bounds.push_back(bbox.min.y);
700 bounds.push_back(bbox.max.x);
701 bounds.push_back(bbox.max.y);
710 const std::vector<int32_t>& linestring_sizes) {
711 geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbMultiLineString);
712 OGRMultiLineString* multilinestring =
dynamic_cast<OGRMultiLineString*
>(
geom_);
713 CHECK(multilinestring);
715 size_t coords_ctr = 0;
716 for (
const auto linestring_sz : linestring_sizes) {
717 OGRLineString linestring;
718 auto next_coords_ctr = coords_ctr + 2 * linestring_sz;
719 CHECK(next_coords_ctr <= coords.size());
720 for (
auto i = coords_ctr; i < next_coords_ctr; i += 2) {
721 linestring.addPoint(coords[i], coords[i + 1]);
723 coords_ctr = next_coords_ctr;
724 multilinestring->addGeometry(&linestring);
730 if (err != OGRERR_NONE) {
734 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbMultiLineString) {
736 "Unexpected geometry type from WKT string: " +
737 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
742 std::vector<int32_t>& linestring_sizes,
743 std::vector<double>& bounds)
const {
744 auto multilinestring =
dynamic_cast<OGRMultiLineString*
>(
geom_);
745 CHECK(multilinestring);
747 if (multilinestring->IsEmpty()) {
749 throw GeoTypesError(
"MultiLineString",
"'EMPTY' not supported");
759 for (
auto l = 0; l < multilinestring->getNumGeometries(); l++) {
760 const auto geom = multilinestring->getGeometryRef(l);
762 const auto linestring =
dynamic_cast<OGRLineString*
>(geom);
765 "Failed to read linestring geometry from multilinestring");
767 auto linestring_sz = linestring->getNumPoints();
768 linestring_sizes.push_back(linestring_sz);
769 for (
auto i = 0; i < linestring_sz; i++) {
771 linestring->getPoint(i, &point);
772 double x = point.getX();
773 double y = point.getY();
779 bounds.push_back(bbox.min.x);
780 bounds.push_back(bbox.min.y);
781 bounds.push_back(bbox.max.x);
782 bounds.push_back(bbox.max.y);
791 const std::vector<int32_t>& ring_sizes) {
792 geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbPolygon);
793 OGRPolygon* poly =
dynamic_cast<OGRPolygon*
>(
geom_);
796 size_t coords_ctr = 0;
797 for (
size_t r = 0; r < ring_sizes.size(); r++) {
799 const auto ring_sz = ring_sizes[r];
800 for (
auto i = 0; i < 2 * ring_sz; i += 2) {
801 ring.addPoint(coords[coords_ctr + i], coords[coords_ctr + i + 1]);
803 ring.addPoint(coords[coords_ctr], coords[coords_ctr + 1]);
804 coords_ctr += 2 * ring_sz;
805 poly->addRing(&ring);
811 if (err != OGRERR_NONE) {
815 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbPolygon) {
817 "Unexpected geometry type from WKT string: " +
818 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
823 std::vector<int32_t>& ring_sizes,
824 std::vector<double>& bounds)
const {
825 const auto poly_geom =
dynamic_cast<OGRPolygon*
>(
geom_);
828 if (poly_geom->IsEmpty()) {
840 const auto exterior_ring = poly_geom->getExteriorRing();
841 CHECK(exterior_ring);
843 if (exterior_ring->isClockwise()) {
844 exterior_ring->reverseWindingOrder();
847 ring_sizes.push_back(num_points_added);
848 for (
auto r = 0; r < poly_geom->getNumInteriorRings(); r++) {
849 auto interior_ring = poly_geom->getInteriorRing(r);
850 CHECK(interior_ring);
852 if (!interior_ring->isClockwise()) {
853 interior_ring->reverseWindingOrder();
856 ring_sizes.push_back(num_points_added);
858 bounds.push_back(bbox.min.x);
859 bounds.push_back(bbox.min.y);
860 bounds.push_back(bbox.max.x);
861 bounds.push_back(bbox.max.y);
865 const auto poly_geom =
dynamic_cast<OGRPolygon*
>(
geom_);
867 return poly_geom->getNumInteriorRings();
876 const std::vector<int32_t>& ring_sizes,
877 const std::vector<int32_t>& poly_rings) {
878 geom_ = OGRGeometryFactory::createGeometry(OGRwkbGeometryType::wkbMultiPolygon);
879 OGRMultiPolygon* multipoly =
dynamic_cast<OGRMultiPolygon*
>(
geom_);
883 size_t coords_ctr = 0;
884 for (
const auto& rings_in_poly : poly_rings) {
886 for (
auto r = 0; r < rings_in_poly; r++) {
888 const auto ring_sz = ring_sizes[ring_ctr];
889 for (
auto i = 0; i < 2 * ring_sz; i += 2) {
890 ring.addPoint(coords[coords_ctr + i], coords[coords_ctr + i + 1]);
892 ring.addPoint(coords[coords_ctr], coords[coords_ctr + 1]);
893 coords_ctr += 2 * ring_sz;
897 multipoly->addGeometry(&poly);
903 if (err != OGRERR_NONE) {
907 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbMultiPolygon) {
909 "Unexpected geometry type from WKT string: " +
910 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
915 std::vector<int32_t>& ring_sizes,
916 std::vector<int32_t>& poly_rings,
917 std::vector<double>& bounds)
const {
918 const auto mpoly =
dynamic_cast<OGRMultiPolygon*
>(
geom_);
921 if (mpoly->IsEmpty()) {
923 throw GeoTypesError(
"MultiPolygon",
"'EMPTY' not supported");
933 for (
auto p = 0; p < mpoly->getNumGeometries(); p++) {
934 const auto mpoly_geom = mpoly->getGeometryRef(p);
936 const auto poly_geom =
dynamic_cast<OGRPolygon*
>(mpoly_geom);
939 "Failed to read polygon geometry from multipolygon");
941 const auto exterior_ring = poly_geom->getExteriorRing();
942 CHECK(exterior_ring);
944 if (exterior_ring->isClockwise()) {
945 exterior_ring->reverseWindingOrder();
948 ring_sizes.push_back(num_points_added);
950 for (
auto r = 0; r < poly_geom->getNumInteriorRings(); r++) {
951 auto interior_ring = poly_geom->getInteriorRing(r);
952 CHECK(interior_ring);
954 if (!interior_ring->isClockwise()) {
955 interior_ring->reverseWindingOrder();
958 ring_sizes.push_back(num_points_added);
960 poly_rings.push_back(poly_geom->getNumInteriorRings() + 1);
962 bounds.push_back(bbox.min.x);
963 bounds.push_back(bbox.min.y);
964 bounds.push_back(bbox.max.x);
965 bounds.push_back(bbox.max.y);
980 if (err != OGRERR_NONE) {
984 if (wkbFlatten(
geom_->getGeometryType()) != OGRwkbGeometryType::wkbGeometryCollection) {
986 "Unexpected geometry type from WKT string: " +
987 std::string(OGRGeometryTypeToName(
geom_->getGeometryType())));
996 table_[
static_cast<int>(
'1')] = 1;
997 table_[
static_cast<int>(
'2')] = 2;
998 table_[
static_cast<int>(
'3')] = 3;
999 table_[
static_cast<int>(
'4')] = 4;
1000 table_[
static_cast<int>(
'5')] = 5;
1001 table_[
static_cast<int>(
'6')] = 6;
1002 table_[
static_cast<int>(
'7')] = 7;
1003 table_[
static_cast<int>(
'8')] = 8;
1004 table_[
static_cast<int>(
'9')] = 9;
1005 table_[
static_cast<int>(
'a')] = 10;
1006 table_[
static_cast<int>(
'A')] = 10;
1007 table_[
static_cast<int>(
'b')] = 11;
1008 table_[
static_cast<int>(
'B')] = 11;
1009 table_[
static_cast<int>(
'c')] = 12;
1010 table_[
static_cast<int>(
'C')] = 12;
1011 table_[
static_cast<int>(
'd')] = 13;
1012 table_[
static_cast<int>(
'D')] = 13;
1013 table_[
static_cast<int>(
'e')] = 14;
1014 table_[
static_cast<int>(
'E')] = 14;
1015 table_[
static_cast<int>(
'f')] = 15;
1016 table_[
static_cast<int>(
'F')] = 15;
1019 return (hex_digit < 0) ? 0 : table_[
static_cast<int>(hex_digit)];
1026 return (hex_digit_to_decimal_table[usb] << 4) | hex_digit_to_decimal_table[lsb];
1030 auto num_bytes = wkb_hex.size() >> 1;
1031 std::vector<uint8_t> wkb(num_bytes);
1032 auto* chars = wkb_hex.data();
1033 auto* bytes = wkb.data();
1034 for (
size_t i = 0; i < num_bytes; i++) {
1035 auto const& usb = *chars++;
1036 auto const& lsb = *chars++;
1045 OGRGeometry* geom =
nullptr;
1046 OGRErr err = OGRERR_NONE;
1047 if (wkt_or_wkb_hex.empty()) {
1048 err = OGRERR_NOT_ENOUGH_DATA;
1049 }
else if (wkt_or_wkb_hex[0] ==
'0') {
1055 if (err != OGRERR_NONE) {
1062 const std::string& wkt_or_wkb_hex) {
1067 OGRGeometry* geom =
nullptr;
1069 if (err != OGRERR_NONE) {
1081 std::vector<double>& coords,
1082 std::vector<double>& bounds,
1083 std::vector<int>& ring_sizes,
1084 std::vector<int>& poly_rings,
1085 const bool promote_poly_to_mpoly) {
1087 if (wkt_or_wkb_hex.empty() || wkt_or_wkb_hex ==
"NULL") {
1089 ti, coords, bounds, ring_sizes, poly_rings, promote_poly_to_mpoly);
1095 if (!geospatial_base || !geospatial_base->transform(ti)) {
1105 promote_poly_to_mpoly);
1107 }
catch (
const std::exception& e) {
1108 LOG(
ERROR) <<
"Geospatial Import Error: " << e.what();
1117 std::vector<double>& coords,
1118 std::vector<double>& bounds,
1119 std::vector<int>& ring_sizes,
1120 std::vector<int>& poly_rings,
1121 const bool promote_poly_to_mpoly) {
1125 if (!geospatial_base || !geospatial_base->transform(ti)) {
1135 promote_poly_to_mpoly);
1137 }
catch (
const std::exception& e) {
1138 LOG(
ERROR) <<
"Geospatial Import Error: " << e.what();
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) {
1155 if (!geospatial_base || !geospatial_base->transform(ti)) {
1165 promote_poly_to_mpoly);
1167 }
catch (
const std::exception& e) {
1168 LOG(
ERROR) <<
"Geospatial Import Error: " << e.what();
1177 std::vector<std::vector<double>>& coords_column,
1178 std::vector<std::vector<double>>& bounds_column,
1179 std::vector<std::vector<int>>& ring_sizes_column,
1180 std::vector<std::vector<int>>& poly_rings_column,
1181 const bool promote_poly_to_mpoly) {
1183 for (
const auto& wkt_or_wkb_hex : *wkt_or_wkb_hex_column) {
1184 std::vector<double> coords;
1185 std::vector<double> bounds;
1186 std::vector<int> ring_sizes;
1187 std::vector<int> poly_rings;
1196 promote_poly_to_mpoly);
1197 if (ti.
get_type() != row_ti.get_type()) {
1200 throw GeoTypesError(
"GeoFactory",
"Columnar: Geometry type mismatch");
1203 coords_column.push_back(coords);
1204 bounds_column.push_back(bounds);
1205 ring_sizes_column.push_back(ring_sizes);
1206 poly_rings_column.push_back(poly_rings);
1209 }
catch (
const std::exception& e) {
1210 LOG(
ERROR) <<
"Geospatial column Import Error: " << e.what();
1218 const bool owns_geom_obj) {
1219 switch (wkbFlatten(geom->getGeometryType())) {
1221 return std::unique_ptr<GeoPoint>(
new GeoPoint(geom, owns_geom_obj));
1223 return std::unique_ptr<GeoMultiPoint>(
new GeoMultiPoint(geom, owns_geom_obj));
1225 return std::unique_ptr<GeoLineString>(
new GeoLineString(geom, owns_geom_obj));
1226 case wkbMultiLineString:
1227 return std::unique_ptr<GeoMultiLineString>(
1230 return std::unique_ptr<GeoPolygon>(
new GeoPolygon(geom, owns_geom_obj));
1231 case wkbMultiPolygon:
1232 return std::unique_ptr<GeoMultiPolygon>(
new GeoMultiPolygon(geom, owns_geom_obj));
1233 case wkbGeometryCollection:
1234 return std::unique_ptr<GeoGeometryCollection>(
1239 "Unrecognized geometry type: " + std::string(geom->getGeometryName()));
1245 std::vector<double>& coords,
1246 std::vector<double>& bounds,
1247 std::vector<int>& ring_sizes,
1248 std::vector<int>& poly_rings,
1249 const bool promote_poly_to_mpoly) {
1250 switch (geospatial_base->getType()) {
1252 const auto geospatial_point =
dynamic_cast<GeoPoint*
>(geospatial_base.get());
1253 CHECK(geospatial_point);
1254 geospatial_point->getColumns(coords);
1259 const auto geospatial_multipoint =
1261 CHECK(geospatial_multipoint);
1262 geospatial_multipoint->getColumns(coords, bounds);
1267 const auto geospatial_linestring =
1269 CHECK(geospatial_linestring);
1270 geospatial_linestring->getColumns(coords, bounds);
1275 const auto geospatial_multilinestring =
1277 CHECK(geospatial_multilinestring);
1278 geospatial_multilinestring->getColumns(coords, ring_sizes, bounds);
1283 const auto geospatial_poly =
dynamic_cast<GeoPolygon*
>(geospatial_base.get());
1284 CHECK(geospatial_poly);
1285 geospatial_poly->getColumns(coords, ring_sizes, bounds);
1286 if (promote_poly_to_mpoly) {
1287 if (ring_sizes.size()) {
1289 poly_rings.push_back(1 + geospatial_poly->getNumInteriorRings());
1296 const auto geospatial_mpoly =
dynamic_cast<GeoMultiPolygon*
>(geospatial_base.get());
1297 CHECK(geospatial_mpoly);
1298 geospatial_mpoly->getColumns(coords, ring_sizes, poly_rings, bounds);
1305 throw std::runtime_error(
"Unrecognized geospatial type");
1310 std::vector<double>& coords,
1311 std::vector<double>& bounds,
1312 std::vector<int>& ring_sizes,
1313 std::vector<int>& poly_rings,
1314 const bool promote_poly_to_mpoly) {
1336 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, std::vector< double > &bounds) const
void getColumns(std::vector< double > &coords) const
int32_t getNumInteriorRings() const
#define SRID_NORTH_UTM_END
std::unique_ptr< GeoBase > clone() const final
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)
GeoMultiLineString(const std::vector< double > &coords, const std::vector< int32_t > &linestring_sizes)
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)
static int createFromWkbView(OGRGeometry **geom, WkbView const)
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
std::unique_ptr< GeoBase > clone() const override
void getColumns(std::vector< double > &coords, std::vector< int32_t > &linestring_sizes, std::vector< double > &bounds) const
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
GeoMultiPoint(const std::vector< double > &coords)
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::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)