diff --git a/lib/cunit/cu_pc_patch.c b/lib/cunit/cu_pc_patch.c index f4fb5eb0..b31f9ef1 100644 --- a/lib/cunit/cu_pc_patch.c +++ b/lib/cunit/cu_pc_patch.c @@ -513,8 +513,12 @@ test_patch_wkb() PCPOINTLIST *pl1; PCPATCH_UNCOMPRESSED *pu1, *pu2; PCPATCH *pa1, *pa2, *pa3, *pa4; - size_t z1, z2; - uint8_t *wkb1, *wkb2; + size_t z1, z2, z3; + uint8_t *wkb1, *wkb2, *wkb3; + char *hexwkb; + + static char *hexresult_ndr = "01030000000100000005000000000000000000000000000000000000000000000000000000CDCCCCCCCC8C4B40EC51B81E852B4440CDCCCCCCCC8C4B40EC51B81E852B4440000000000000000000000000000000000000000000000000"; + static char *hexresult_xdr = "00000000030000000100000005000000000000000000000000000000000000000000000000404B8CCCCCCCCCCD40442B851EB851EC404B8CCCCCCCCCCD40442B851EB851EC000000000000000000000000000000000000000000000000"; pl1 = pc_pointlist_make(npts); @@ -533,6 +537,7 @@ test_patch_wkb() // str = pc_hexbytes_from_bytes(wkb1, z1); // printf("str\n%s\n",str); pa2 = pc_patch_from_wkb(simpleschema, wkb1, z1); + pcfree(wkb1); // printf("pa2\n%s\n",pc_patch_to_string(pa2)); @@ -556,6 +561,18 @@ test_patch_wkb() CU_ASSERT_EQUAL(pu1->npoints, pu2->npoints); CU_ASSERT(memcmp(pu1->data, pu2->data, pu1->datasize) == 0); + wkb3 = pc_bounds_to_geometry_wkb(&pa1->bounds, simpleschema->srid, &z3); + hexwkb = pc_hexbytes_from_bytes(wkb3, z3); + if ( machine_endian() == PC_NDR ) + { + CU_ASSERT_STRING_EQUAL(hexwkb, hexresult_ndr); + } + else + { + CU_ASSERT_STRING_EQUAL(hexwkb, hexresult_xdr); + } + pcfree(hexwkb); + pcfree(wkb3); pc_pointlist_free(pl1); pc_patch_free(pa1); @@ -564,7 +581,6 @@ test_patch_wkb() pc_patch_free(pa4); pc_patch_free((PCPATCH*)pu1); pc_patch_free((PCPATCH*)pu2); - pcfree(wkb1); } diff --git a/lib/pc_api.h b/lib/pc_api.h index eba7358b..c027eeb3 100644 --- a/lib/pc_api.h +++ b/lib/pc_api.h @@ -441,6 +441,9 @@ int pc_patch_compute_extent(PCPATCH *patch); /** True/false if bounds intersect */ int pc_bounds_intersects(const PCBOUNDS *b1, const PCBOUNDS *b2); +/** Return the bounds as an OGC WKB geometry */ +uint8_t *pc_bounds_to_geometry_wkb(const PCBOUNDS *bounds, uint32_t srid, size_t *wkbsize); + /** Returns OGC WKB of the bounding diagonal of XY bounds */ uint8_t* pc_bounding_diagonal_wkb_from_bounds(const PCBOUNDS *bounds, const PCSCHEMA *schema, size_t *wkbsize); diff --git a/lib/pc_util.c b/lib/pc_util.c index 9ccc2ed6..9ec0bf8a 100644 --- a/lib/pc_util.c +++ b/lib/pc_util.c @@ -290,6 +290,83 @@ static uint32_t srid_mask = 0x20000000; static uint32_t m_mask = 0x40000000; static uint32_t z_mask = 0x80000000; +uint8_t * +pc_bounds_to_geometry_wkb(const PCBOUNDS *bounds, uint32_t srid, size_t *wkbsize) +{ + /* Bounds! */ + double xmin = bounds->xmin; + double ymin = bounds->ymin; + double xmax = bounds->xmax; + double ymax = bounds->ymax; + + static uint32_t srid_mask = 0x20000000; + static uint32_t npoints_by_type[] = { 0, 1, 2, 5 }; + /* WKB POINT, LINESTRING or POLYGON */ + uint32_t wkbtype = 1 + (xmin != xmax) + (ymin != ymax); + uint32_t npoints = npoints_by_type[wkbtype]; + uint8_t *wkb, *ptr; + /* endian + (type + nrings? + npoints?) + npoints dbl pt */ + size_t size = 1 + wkbtype * 4 + npoints * 2 * 8; + + if ( srid ) + { + wkbtype |= srid_mask; + size += 4; + } + + wkb = pcalloc(size); + ptr = wkb; + + ptr = wkb_set_char(ptr, machine_endian()); /* Endian flag */ + + ptr = wkb_set_uint32(ptr, wkbtype); /* TYPE = POINT, LINESTRING or POLYGON */ + + if ( srid ) + { + ptr = wkb_set_uint32(ptr, srid); /* SRID */ + } + + switch ( wkbtype ) + { + case 3 /* POLYGON */ : ptr = wkb_set_uint32(ptr, 1); /* NRINGS */ + case 2 /* LINESTRING */ : ptr = wkb_set_uint32(ptr, npoints); /* NPOINTS */ + } + + /* Point 0 */ + ptr = wkb_set_double(ptr, xmin); + ptr = wkb_set_double(ptr, ymin); + + if ( wkbtype == 2 ) // LINESTRING + { + /* Point 1 */ + ptr = wkb_set_double(ptr, xmax); + ptr = wkb_set_double(ptr, ymax); + } + else if( wkbtype == 3 ) // POLYGON + { + /* Point 1 */ + ptr = wkb_set_double(ptr, xmin); + ptr = wkb_set_double(ptr, ymax); + + /* Point 2 */ + ptr = wkb_set_double(ptr, xmax); + ptr = wkb_set_double(ptr, ymax); + + /* Point 3 */ + ptr = wkb_set_double(ptr, xmax); + ptr = wkb_set_double(ptr, ymin); + + /* Point 4 */ + ptr = wkb_set_double(ptr, xmin); + ptr = wkb_set_double(ptr, ymin); + } + + if ( wkbsize ) + *wkbsize = size; + + return wkb; +} + uint8_t * pc_bounding_diagonal_wkb_from_bounds( const PCBOUNDS *bounds, const PCSCHEMA *schema, size_t *wkbsize) diff --git a/pgsql/expected/pointcloud.out b/pgsql/expected/pointcloud.out index 6338fb0a..1cd5c782 100644 --- a/pgsql/expected/pointcloud.out +++ b/pgsql/expected/pointcloud.out @@ -337,7 +337,7 @@ SELECT PC_AsText(pa) FROM pa_test; SELECT PC_EnvelopeAsBinary(pa) from pa_test; pc_envelopeasbinary ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - \x010300000001000000050000007b14ae47e17a943fb81e85eb51b89e3f7b14ae47e17a943fb81e85eb51b89e3f7b14ae47e17a943fb81e85eb51b89e3f7b14ae47e17a943fb81e85eb51b89e3f7b14ae47e17a943fb81e85eb51b89e3f + \x01010000007b14ae47e17a943fb81e85eb51b89e3f \x01030000000100000005000000b81e85eb51b8ae3fec51b81e85ebb13fb81e85eb51b8ae3f9a9999999999b93f0ad7a3703d0ab73f9a9999999999b93f0ad7a3703d0ab73fec51b81e85ebb13fb81e85eb51b8ae3fec51b81e85ebb13f \x01030000000100000005000000b81e85eb51b8ae3fec51b81e85ebb13fb81e85eb51b8ae3f9a9999999999b93f0ad7a3703d0ab73f9a9999999999b93f0ad7a3703d0ab73fec51b81e85ebb13fb81e85eb51b8ae3fec51b81e85ebb13f \x01030000000100000005000000b81e85eb51b8ae3fec51b81e85ebb13fb81e85eb51b8ae3f9a9999999999b93f0ad7a3703d0ab73f9a9999999999b93f0ad7a3703d0ab73fec51b81e85ebb13fb81e85eb51b8ae3fec51b81e85ebb13f @@ -346,7 +346,7 @@ SELECT PC_EnvelopeAsBinary(pa) from pa_test; SELECT PC_Envelope(pa) from pa_test; pc_envelope ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - \x010300000001000000050000007b14ae47e17a943fb81e85eb51b89e3f7b14ae47e17a943fb81e85eb51b89e3f7b14ae47e17a943fb81e85eb51b89e3f7b14ae47e17a943fb81e85eb51b89e3f7b14ae47e17a943fb81e85eb51b89e3f + \x01010000007b14ae47e17a943fb81e85eb51b89e3f \x01030000000100000005000000b81e85eb51b8ae3fec51b81e85ebb13fb81e85eb51b8ae3f9a9999999999b93f0ad7a3703d0ab73f9a9999999999b93f0ad7a3703d0ab73fec51b81e85ebb13fb81e85eb51b8ae3fec51b81e85ebb13f \x01030000000100000005000000b81e85eb51b8ae3fec51b81e85ebb13fb81e85eb51b8ae3f9a9999999999b93f0ad7a3703d0ab73f9a9999999999b93f0ad7a3703d0ab73fec51b81e85ebb13fb81e85eb51b8ae3fec51b81e85ebb13f \x01030000000100000005000000b81e85eb51b8ae3fec51b81e85ebb13fb81e85eb51b8ae3f9a9999999999b93f0ad7a3703d0ab73f9a9999999999b93f0ad7a3703d0ab73fec51b81e85ebb13fb81e85eb51b8ae3fec51b81e85ebb13f diff --git a/pgsql/pc_inout.c b/pgsql/pc_inout.c index 1378a80b..93f638ee 100644 --- a/pgsql/pc_inout.c +++ b/pgsql/pc_inout.c @@ -303,13 +303,13 @@ Datum pcpatch_envelope_as_bytea(PG_FUNCTION_ARGS) SERIALIZED_PATCH *serpatch = PG_GETHEADER_SERPATCH_P(0); PCSCHEMA *schema = pc_schema_from_pcid(serpatch->pcid, fcinfo); - bytes = pc_patch_to_geometry_wkb_envelope(serpatch, schema, &bytes_size); + bytes = pc_bounds_to_geometry_wkb(&serpatch->bounds, schema->srid, &bytes_size); wkb_size = VARHDRSZ + bytes_size; wkb = palloc(wkb_size); memcpy(VARDATA(wkb), bytes, bytes_size); SET_VARSIZE(wkb, wkb_size); - pfree(bytes); + pcfree(bytes); PG_RETURN_BYTEA_P(wkb); } diff --git a/pgsql/pc_pgsql.c b/pgsql/pc_pgsql.c index 4623bf6a..ae638e48 100644 --- a/pgsql/pc_pgsql.c +++ b/pgsql/pc_pgsql.c @@ -847,104 +847,3 @@ pc_patch_deserialize(const SERIALIZED_PATCH *serpatch, const PCSCHEMA *schema) pcerror("%s: unsupported compression type", __func__); return NULL; } - - -static uint8_t * -pc_patch_wkb_set_double(uint8_t *wkb, double d) -{ - memcpy(wkb, &d, 8); - wkb += 8; - return wkb; -} - -static uint8_t * -pc_patch_wkb_set_int32(uint8_t *wkb, uint32_t i) -{ - memcpy(wkb, &i, 4); - wkb += 4; - return wkb; -} - -static uint8_t * -pc_patch_wkb_set_char(uint8_t *wkb, char c) -{ - memcpy(wkb, &c, 1); - wkb += 1; - return wkb; -} - -/* 0 = xdr | big endian */ -/* 1 = ndr | little endian */ -static char -machine_endian(void) -{ - static int check_int = 1; /* dont modify this!!! */ - return *((char *) &check_int); -} - -uint8_t * -pc_patch_to_geometry_wkb_envelope(const SERIALIZED_PATCH *pa, const PCSCHEMA *schema, size_t *wkbsize) -{ - static uint32_t srid_mask = 0x20000000; - static uint32_t nrings = 1; - static uint32_t npoints = 5; - uint32_t wkbtype = 3; /* WKB POLYGON */ - uint8_t *wkb, *ptr; - int has_srid = false; - size_t size = 1 + 4 + 4 + 4 + 2*npoints*8; /* endian + type + nrings + npoints + 5 dbl pts */ - - /* Bounds! */ - double xmin = pa->bounds.xmin; - double ymin = pa->bounds.ymin; - double xmax = pa->bounds.xmax; - double ymax = pa->bounds.ymax; - - /* Make sure they're slightly bigger than a point */ - if ( xmin == xmax ) xmax += xmax * 0.0000001; - if ( ymin == ymax ) ymax += ymax * 0.0000001; - - if ( schema->srid > 0 ) - { - has_srid = true; - wkbtype |= srid_mask; - size += 4; - } - - wkb = palloc(size); - ptr = wkb; - - ptr = pc_patch_wkb_set_char(ptr, machine_endian()); /* Endian flag */ - - ptr = pc_patch_wkb_set_int32(ptr, wkbtype); /* TYPE = Polygon */ - - if ( has_srid ) - { - ptr = pc_patch_wkb_set_int32(ptr, schema->srid); /* SRID */ - } - - ptr = pc_patch_wkb_set_int32(ptr, nrings); /* NRINGS = 1 */ - ptr = pc_patch_wkb_set_int32(ptr, npoints); /* NPOINTS = 5 */ - - /* Point 0 */ - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmin); - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymin); - - /* Point 1 */ - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmin); - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymax); - - /* Point 2 */ - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmax); - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymax); - - /* Point 3 */ - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmax); - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymin); - - /* Point 4 */ - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmin); - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymin); - - if ( wkbsize ) *wkbsize = size; - return wkb; -}