Skip to content

Commit

Permalink
Methods for getting geobin rect and point
Browse files Browse the repository at this point in the history
  • Loading branch information
tidwall committed Jan 10, 2025
1 parent 28ab306 commit 403acb1
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 2 deletions.
3 changes: 1 addition & 2 deletions docs/GEOBIN.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ dimensions, followed by a series of coordinates that define the rectangle.
- 1-byte integer: number of dimensions (4)
- 8-byte float[8]: `[xmin, ymin, zmin, mmin, xmax, ymax, zmax, mmax]`

GeoBIN only supports 2, 3, or 4 dimensions; or zero to omit this section
altogether.
GeoBIN only supports 2, 3, or 4 dimensions.

### Extra JSON Section

Expand Down
25 changes: 25 additions & 0 deletions tests/test_geobin.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,30 @@ void perfect_match(const char *geojson_or_wkt, const char *expect, int dims, dou

cmpfullrect(gdims, gmin, gmax, dims, min, max);

struct tg_rect rect = tg_geobin_rect(geobin, geobinlen);
gdims = 2;
gmin[0] = rect.min.x;
gmin[1] = rect.min.y;
gmax[0] = rect.max.x;
gmax[1] = rect.max.y;
cmpfullrect(gdims, gmin, gmax, 2, min, max);

struct tg_point point = tg_geobin_point(geobin, geobinlen);
gdims = 2;
gmin[0] = point.x;
gmin[1] = point.y;
gmax[0] = point.x;
gmax[1] = point.y;

double min2[4], max2[4];
min2[0] = (gmin[0]+gmax[0])/2;
min2[1] = (gmin[1]+gmax[1])/2;
max2[0] = min2[0];
max2[1] = min2[1];
cmpfullrect(gdims, gmin, gmax, 2, min2, max2);



char geojson_or_wkt2[100000];
size_t geojson_or_wkt2len;
if (geojson_or_wkt[0] == '{') {
Expand Down Expand Up @@ -169,5 +193,6 @@ int main(int argc, char **argv) {
do_test(test_geobin_fail);
do_test(test_geobin_max_depth);
do_chaos_test(test_geobin_chaos);
do_test(test_geobin_basic_syntax);
return 0;
}
54 changes: 54 additions & 0 deletions tg.c
Original file line number Diff line number Diff line change
Expand Up @@ -14810,3 +14810,57 @@ int tg_geobin_fullrect(const uint8_t *geobin, size_t len, double min[4],
}
return dims;
}

struct tg_rect tg_geobin_rect(const uint8_t *geobin, size_t len) {
struct tg_rect rect = { 0 };
if (geobin && len > 2 && geobin[0] >= 0x01 && geobin[0] <= 0x04) {
if (geobin[0] == 0x01 && len >= 21) {
// Read Point
uint32_t type;
memcpy(&type, geobin+1, 4);
if (type == 1 || type == 1001 || type == 2001 || type == 3001) {
memcpy(&rect.min.x, geobin+5, 8);
memcpy(&rect.min.y, geobin+5+8, 8);
rect.max.x = rect.min.x;
rect.max.y = rect.min.y;
}
} else if (geobin[0] != 0x01 && len >= 2+8*(size_t)geobin[1]*2){
// Read MBR
int dims = geobin[1];
if (dims >= 2) {
memcpy(&rect.min.x, geobin+2, 8);
memcpy(&rect.min.y, geobin+2+8, 8);
memcpy(&rect.max.x, geobin+2+8*dims, 8);
memcpy(&rect.max.y, geobin+2+8*dims+8, 8);
}
}
}
return rect;
}

struct tg_point tg_geobin_point(const uint8_t *geobin, size_t len) {
struct tg_point point = { 0 };
if (geobin && len > 2 && geobin[0] >= 0x01 && geobin[0] <= 0x04) {
if (geobin[0] == 0x01 && len >= 21) {
// Read Point
uint32_t type;
memcpy(&type, geobin+1, 4);
if (type == 1 || type == 1001 || type == 2001 || type == 3001) {
memcpy(&point.x, geobin+5, 8);
memcpy(&point.y, geobin+5+8, 8);
}
} else if (geobin[0] != 0x01 && len >= 2+8*(size_t)geobin[1]*2){
// Read MBR
struct tg_rect rect = { 0 };
int dims = geobin[1];
if (dims >= 2) {
memcpy(&rect.min.x, geobin+2, 8);
memcpy(&rect.min.y, geobin+2+8, 8);
memcpy(&rect.max.x, geobin+2+8*dims, 8);
memcpy(&rect.max.y, geobin+2+8*dims+8, 8);
}
point = tg_rect_center(rect);
}
}
return point;
}
2 changes: 2 additions & 0 deletions tg.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ struct tg_geom *tg_parse(const void *data, size_t len);
struct tg_geom *tg_parse_ix(const void *data, size_t len, enum tg_index ix);
const char *tg_geom_error(const struct tg_geom *geom);
int tg_geobin_fullrect(const uint8_t *geobin, size_t len, double min[4], double max[4]);
struct tg_rect tg_geobin_rect(const uint8_t *geobin, size_t len);
struct tg_point tg_geobin_point(const uint8_t *geobin, size_t len);

/// @}

Expand Down

0 comments on commit 403acb1

Please sign in to comment.