diff --git a/tests/test_geojson.c b/tests/test_geojson.c index 081a91e..dc20b8e 100644 --- a/tests/test_geojson.c +++ b/tests/test_geojson.c @@ -1028,6 +1028,25 @@ void test_geojson_big_shapes() { tg_geom_free(geom2); } +void test_geojson_geometrycollection() { + struct tg_geom *g1 = tg_parse_wkt("POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))"); + assert(!tg_geom_error(g1)); + struct tg_geom *g2 = tg_parse_wkt("POLYGON ((300 100, 400 400, 200 400, 100 200, 300 100))"); + assert(!tg_geom_error(g2)); + struct tg_geom *collection = tg_geom_new_geometrycollection((const struct tg_geom*const[]) {g1, g2}, 2); + assert(!tg_geom_error(collection)); + char dst1[1024]; + char dst2[1024]; + tg_geom_geojson(tg_geom_geometry_at(collection, 1), dst1, sizeof(dst1)); + struct tg_geom *g3 = tg_parse_geojson(dst1); + tg_geom_geojson(g3, dst2, sizeof(dst2)); + assert(strcmp(dst1, dst2) == 0); + tg_geom_free(g1); + tg_geom_free(g2); + tg_geom_free(collection); + tg_geom_free(g3); +} + int main(int argc, char **argv) { seedrand(); do_test(test_geojson_basic_syntax); @@ -1035,5 +1054,6 @@ int main(int argc, char **argv) { do_test(test_geojson_various); do_test(test_geojson_big_shapes); do_chaos_test(test_geojson_chaos); + do_test(test_geojson_geometrycollection); return 0; } diff --git a/tests/test_wkb.c b/tests/test_wkb.c index c3dc372..98b6f62 100644 --- a/tests/test_wkb.c +++ b/tests/test_wkb.c @@ -801,6 +801,26 @@ void test_wkb_big_shapes() { tg_geom_free(geom2); } +void test_wkb_geometrycollection() { + struct tg_geom *g1 = tg_parse_wkt("POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))"); + assert(!tg_geom_error(g1)); + struct tg_geom *g2 = tg_parse_wkt("POLYGON ((300 100, 400 400, 200 400, 100 200, 300 100))"); + assert(!tg_geom_error(g2)); + struct tg_geom *collection = tg_geom_new_geometrycollection((const struct tg_geom*const[]) {g1, g2}, 2); + assert(!tg_geom_error(collection)); + uint8_t dst1[1024]; + uint8_t dst2[1024]; + size_t sz1 = tg_geom_wkb(tg_geom_geometry_at(collection, 1), dst1, sizeof(dst1)); + struct tg_geom *g3 = tg_parse_wkb(dst1, sz1); + size_t sz2 = tg_geom_wkb(g3, dst2, sizeof(dst2)); + assert(sz1 == sz2 && memcmp(dst1, dst2, sz1) == 0); + tg_geom_free(g1); + tg_geom_free(g2); + tg_geom_free(collection); + tg_geom_free(g3); +} + + int main(int argc, char **argv) { do_test(test_wkb_basic_syntax); do_test(test_wkb_max_depth); @@ -810,5 +830,6 @@ int main(int argc, char **argv) { do_test(test_wkb_with_srid); do_test(test_wkb_various); do_test(test_wkb_big_shapes); + do_test(test_wkb_geometrycollection); return 0; } diff --git a/tests/test_wkt.c b/tests/test_wkt.c index cfe58bf..0fa4fe6 100644 --- a/tests/test_wkt.c +++ b/tests/test_wkt.c @@ -715,6 +715,24 @@ void test_wkt_various() { tg_geom_free(geom); } +void test_wkt_geometrycollection() { + struct tg_geom *g1 = tg_parse_wkt("POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))"); + assert(!tg_geom_error(g1)); + struct tg_geom *g2 = tg_parse_wkt("POLYGON ((300 100, 400 400, 200 400, 100 200, 300 100))"); + assert(!tg_geom_error(g2)); + struct tg_geom *collection = tg_geom_new_geometrycollection((const struct tg_geom*const[]) {g1, g2}, 2); + assert(!tg_geom_error(collection)); + char dst1[1024]; + char dst2[1024]; + tg_geom_wkt(tg_geom_geometry_at(collection, 1), dst1, sizeof(dst1)); + struct tg_geom *g3 = tg_parse_wkt(dst1); + tg_geom_wkt(g3, dst2, sizeof(dst2)); + assert(strcmp(dst1, dst2) == 0); + tg_geom_free(g1); + tg_geom_free(g2); + tg_geom_free(collection); + tg_geom_free(g3); +} int main(int argc, char **argv) { seedrand(); @@ -722,5 +740,6 @@ int main(int argc, char **argv) { do_test(test_wkt_max_depth); do_chaos_test(test_wkt_chaos); do_test(test_wkt_various); + do_test(test_wkt_geometrycollection); return 0; } diff --git a/tg.c b/tg.c index fd55cdd..026c1da 100644 --- a/tg.c +++ b/tg.c @@ -10600,7 +10600,9 @@ static void write_geom_geometrycollection_geojson(const struct tg_geom *geom, write_char(wr, '}'); } -static void write_geom_geojson(const struct tg_geom *geom, struct writer *wr) { +static void write_base_geom_geojson(const struct tg_geom *geom, + struct writer *wr) +{ if ((geom->head.flags&IS_ERROR) == IS_ERROR) { // sigh, just write us an empty point ... write_string(wr, "{\"type\":\"Point\",\"coordinates\":[]}"); @@ -10775,6 +10777,26 @@ static void write_poly_geojson(const struct tg_poly *poly, struct writer *wr) { } } +static void write_geom_geojson(const struct tg_geom *geom, struct writer *wr) { + switch (geom->head.base) { + case BASE_GEOM: + write_base_geom_geojson(geom, wr); + break; + case BASE_POINT: + write_point_geojson((struct boxed_point*)geom, wr); + break; + case BASE_LINE: + write_line_geojson((struct tg_line*)geom, wr); + break; + case BASE_RING: + write_ring_geojson((struct tg_ring*)geom, wr); + break; + case BASE_POLY: + write_poly_geojson((struct tg_poly*)geom, wr); + break; + } +} + /// Writes a GeoJSON representation of a geometry. /// /// The content is stored as a C string in the buffer pointed to by dst. @@ -10804,23 +10826,7 @@ static void write_poly_geojson(const struct tg_poly *poly, struct writer *wr) { size_t tg_geom_geojson(const struct tg_geom *geom, char *dst, size_t n) { if (!geom) return 0; struct writer wr = { .dst = (uint8_t*)dst, .n = n }; - switch (geom->head.base) { - case BASE_GEOM: - write_geom_geojson(geom, &wr); - break; - case BASE_POINT: - write_point_geojson((struct boxed_point*)geom, &wr); - break; - case BASE_LINE: - write_line_geojson((struct tg_line*)geom, &wr); - break; - case BASE_RING: - write_ring_geojson((struct tg_ring*)geom, &wr); - break; - case BASE_POLY: - write_poly_geojson((struct tg_poly*)geom, &wr); - break; - } + write_geom_geojson(geom, &wr); write_nullterm(&wr); return wr.count; } @@ -12129,7 +12135,7 @@ static void write_geom_geometrycollection_wkt(const struct tg_geom *geom, write_char(wr, ')'); } -static void write_geom_wkt(const struct tg_geom *geom, struct writer *wr) { +static void write_base_geom_wkt(const struct tg_geom *geom, struct writer *wr) { switch (geom->head.type) { case TG_POINT: write_geom_point_wkt(geom, wr); @@ -12155,6 +12161,26 @@ static void write_geom_wkt(const struct tg_geom *geom, struct writer *wr) { } } +static void write_geom_wkt(const struct tg_geom *geom, struct writer *wr) { + switch (geom->head.base) { + case BASE_GEOM: + write_base_geom_wkt(geom, wr); + break; + case BASE_POINT: + write_point_wkt((struct boxed_point*)geom, wr); + break; + case BASE_LINE: + write_line_wkt((struct tg_line*)geom, wr); + break; + case BASE_RING: + write_ring_wkt((struct tg_ring*)geom, wr); + break; + case BASE_POLY: + write_poly_wkt((struct tg_poly*)geom, wr); + break; + } +} + /// Writes a Well-known text (WKT) representation of a geometry. /// /// The content is stored as a C string in the buffer pointed to by dst. @@ -12184,23 +12210,7 @@ static void write_geom_wkt(const struct tg_geom *geom, struct writer *wr) { size_t tg_geom_wkt(const struct tg_geom *geom, char *dst, size_t n) { if (!geom) return 0; struct writer wr = { .dst = (uint8_t*)dst, .n = n }; - switch (geom->head.base) { - case BASE_GEOM: - write_geom_wkt(geom, &wr); - break; - case BASE_POINT: - write_point_wkt((struct boxed_point*)geom, &wr); - break; - case BASE_LINE: - write_line_wkt((struct tg_line*)geom, &wr); - break; - case BASE_RING: - write_ring_wkt((struct tg_ring*)geom, &wr); - break; - case BASE_POLY: - write_poly_wkt((struct tg_poly*)geom, &wr); - break; - } + write_geom_wkt(geom, &wr); write_nullterm(&wr); return wr.count; } @@ -13284,7 +13294,7 @@ static void write_geom_geometrycollection_wkb(const struct tg_geom *geom, } } -static void write_geom_wkb(const struct tg_geom *geom, struct writer *wr) { +static void write_base_geom_wkb(const struct tg_geom *geom, struct writer *wr) { switch (geom->head.type) { case TG_POINT: write_geom_point_wkb(geom, wr); @@ -13310,6 +13320,26 @@ static void write_geom_wkb(const struct tg_geom *geom, struct writer *wr) { } } +static void write_geom_wkb(const struct tg_geom *geom, struct writer *wr) { + switch (geom->head.base) { + case BASE_GEOM: + write_base_geom_wkb(geom, wr); + break; + case BASE_POINT: + write_point_wkb((struct boxed_point*)geom, wr); + break; + case BASE_LINE: + write_line_wkb((struct tg_line*)geom, wr); + break; + case BASE_RING: + write_ring_wkb((struct tg_ring*)geom, wr); + break; + case BASE_POLY: + write_poly_wkb((struct tg_poly*)geom, wr); + break; + } +} + /// Writes a Well-known binary (WKB) representation of a geometry. /// /// The content is stored in the buffer pointed by dst. @@ -13337,23 +13367,7 @@ static void write_geom_wkb(const struct tg_geom *geom, struct writer *wr) { size_t tg_geom_wkb(const struct tg_geom *geom, uint8_t *dst, size_t n) { if (!geom) return 0; struct writer wr = { .dst = dst, .n = n }; - switch (geom->head.base) { - case BASE_GEOM: - write_geom_wkb(geom, &wr); - break; - case BASE_POINT: - write_point_wkb((struct boxed_point*)geom, &wr); - break; - case BASE_LINE: - write_line_wkb((struct tg_line*)geom, &wr); - break; - case BASE_RING: - write_ring_wkb((struct tg_ring*)geom, &wr); - break; - case BASE_POLY: - write_poly_wkb((struct tg_poly*)geom, &wr); - break; - } + write_geom_wkb(geom, &wr); return wr.count; }