From: Nicklas Avén Date: Fri, 22 Aug 2014 20:39:50 +0000 (+0000) Subject: Added optional geometry size in TWKB. Also reworked the code so passing around *... X-Git-Tag: 2.2.0rc1~881 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d273edb1489a7ba76c5e06c04e6313415972244a;p=postgis Added optional geometry size in TWKB. Also reworked the code so passing around **buf instead of *buf. Also affects the varInt code git-svn-id: http://svn.osgeo.org/postgis/trunk@12907 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/doc/reference_output.xml b/doc/reference_output.xml index a168bba2c..ac3bd0f59 100644 --- a/doc/reference_output.xml +++ b/doc/reference_output.xml @@ -1173,6 +1173,19 @@ SELECT (ST_AsLatLonText('POINT (-302.2342342 -792.32498)')); integer decimaldigits int8 geometryID + + bytea ST_AsTWKB + geometry g1 + integer decimaldigits + int8 geometryID + boolean include sizes + + + bytea ST_AsTWKB + geometry g1 + integer decimaldigits + int8 geometryID + @@ -1181,8 +1194,9 @@ SELECT (ST_AsLatLonText('POINT (-302.2342342 -792.32498)')); Returns the geometry in TWKB format. TWKB is a new compressed binary format. The second parameter is an integer used to define the number of coordinate decimals in the output. The third parameter is optional. It is used to give each TWKB-geometry an unique ID + The fourth parameter is optional. If it is set to true, the size of the geometry is included - TWKB is still a moving target. The format is described here , and code for building a client can be found here + TWKB is still a moving target. The format is described https://github.com/nicklasaven/TWKB , and code for building a client can be found https://github.com/nicklasaven/twkb_web" @@ -1196,7 +1210,7 @@ SELECT (ST_AsLatLonText('POINT (-302.2342342 -792.32498)')); SELECT ST_AsTWKB('LINESTRING(1 1,5 5)'::geometry,0,1); st_astwkb -------------------------------------------- -\x0342010202020808 +\x0142020202020808 @@ -1235,8 +1249,9 @@ SELECT ST_AsTWKB('LINESTRING(1 1,5 5)'::geometry,0,1); This is the aggregate version of ST_AsTWKB. It aggregates and returns the geometry in TWKB-format. In the resulting TWKB-geometry each individual ID of the input geometries is stored. The second parameter is an integer used to define the number of coordinate decimals in the output. The third parameter is optional. It is used to give each TWKB-geometry an unique ID + The fourth parameter is optional. If it is set to true, the size of the geometry is included - TWKB is still a moving target. The format is described here , and code for building a client can be found here + TWKB is still a moving target. The format is described https://github.com/nicklasaven/TWKB , and code for building a client can be found https://github.com/nicklasaven/twkb_web @@ -1253,7 +1268,7 @@ UNION ALL SELECT 'LINESTRING(6 5, 1 7)'::geometry AS geom, 2 AS id) foo; st_astwkbagg ---------------------------------------------------------------------------- -\x035602010202020808020202000904 +\x015602020202020808040202000904 diff --git a/liblwgeom/cunit/cu_out_twkb.c b/liblwgeom/cunit/cu_out_twkb.c index d44ebd6f4..c2d611bce 100644 --- a/liblwgeom/cunit/cu_out_twkb.c +++ b/liblwgeom/cunit/cu_out_twkb.c @@ -56,7 +56,7 @@ static void cu_twkb(char *wkt,int8_t prec, int64_t id) { LWGEOM *g = lwgeom_from_wkt(wkt, LW_PARSER_CHECK_NONE); if ( s ) free(s); - s = (uint8_t*)lwgeom_to_twkb(g, TWKB_ID, &size,prec, id, 1); + s = (uint8_t*)lwgeom_to_twkb(g, TWKB_ID, &size,prec, id); lwgeom_free(g); } @@ -64,46 +64,46 @@ static void cu_twkb(char *wkt,int8_t prec, int64_t id) static void test_twkb_out_point(void) { cu_twkb("POINT(0 0 0 0)",0,1); - CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"03810200000000"); + CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"01810200000000"); // printf("TWKB: %s\n",hexbytes_from_bytes(s,size)); cu_twkb("SRID=4;POINTM(1 1 1)",0,1); - CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"036102020202"); + CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"016102020202"); // printf("TWKB: %s\n",hexbytes_from_bytes(s,size)); } static void test_twkb_out_linestring(void) { cu_twkb("LINESTRING(0 0,1 1)",0,1); - CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"0342020200000202"); + CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"0142020200000202"); // printf("TWKB: %s\n",hexbytes_from_bytes(s,size)); cu_twkb("LINESTRING(0 0 1,1 1 2,2 2 3)",0,1); - CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"03620203000002020202020202"); + CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"01620203000002020202020202"); cu_twkb("LINESTRING EMPTY",0,1); - CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"0301024200"); + CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"0101024200"); } static void test_twkb_out_polygon(void) { cu_twkb("SRID=4;POLYGON((0 0 0,0 1 0,1 1 0,1 0 0,0 0 0))",0,1); - CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"0363020105000000000200020000000100010000"); + CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"0163020105000000000200020000000100010000"); cu_twkb("SRID=14;POLYGON((0 0 0 1,0 1 0 2,1 1 0 3,1 0 0 4,0 0 0 5))",0,1); - CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"03830201050000000200020002020000020001000201000002"); + CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"01830201050000000200020002020000020001000201000002"); cu_twkb("POLYGON EMPTY",0,1); - CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"0301024300"); + CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"0101024300"); } static void test_twkb_out_multipoint(void) { cu_twkb("SRID=4;MULTIPOINT(0 0 0,0 1 0,1 1 0,1 0 0,0 0 0)",0,1); - CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"03640205000000000200020000000100010000"); + CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"01640205000000000200020000000100010000"); cu_twkb("MULTIPOINT(0 0 0, 0.26794919243112270647255365849413 1 3)",7,1); //printf("WKB: %s",s); - CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"73640202000000888BC70280DAC409808ECE1C"); + CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"71640202000000888BC70280DAC409808ECE1C"); // printf("TWKB: %s\n",hexbytes_from_bytes(s,size)); } @@ -112,16 +112,16 @@ static void test_twkb_out_multilinestring(void) {} static void test_twkb_out_multipolygon(void) { cu_twkb("SRID=14;MULTIPOLYGON(((0 0 0,0 1 0,1 1 0,1 0 0,0 0 0)),((-1 -1 0,-1 2 0,2 2 0,2 -1 0,-1 -1 0),(0 0 0,0 1 0,1 1 0,1 0 0,0 0 0)))",0,1); - CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"036602020105000000000200020000000100010000020501010000060006000000050005000005020200000200020000000100010000"); + CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"016602020105000000000200020000000100010000020501010000060006000000050005000005020200000200020000000100010000"); } static void test_twkb_out_collection(void) { cu_twkb("SRID=14;GEOMETRYCOLLECTION(POLYGON((0 0 0,0 1 0,1 1 0,1 0 0,0 0 0)),POINT(1 1 1))",0,1); - CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"0367020263010500000000020002000000010001000061020202"); + CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"0167020263010500000000020002000000010001000061020202"); cu_twkb("GEOMETRYCOLLECTION EMPTY",0,1); - CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"0301024700"); + CU_ASSERT_STRING_EQUAL(hexbytes_from_bytes(s,size),"0101024700"); } diff --git a/liblwgeom/cunit/cu_varint.c b/liblwgeom/cunit/cu_varint.c index 4e522d283..a398e6e57 100644 --- a/liblwgeom/cunit/cu_varint.c +++ b/liblwgeom/cunit/cu_varint.c @@ -22,81 +22,89 @@ static void do_test_u32_varint(uint32_t nr,int expected_size, char* expected_res) { - uint8_t buf[8]; + uint8_t *buf, *original; int size; char *hex; + buf = original=lwalloc(8); size = varint_u32_encoded_size(nr); if ( size != expected_size ) { printf("Expected: %d\nObtained: %d\n", expected_size, size); } CU_ASSERT_EQUAL(size,expected_size); - varint_u32_encode_buf(nr, buf); - hex = hexbytes_from_bytes(buf,size); + varint_u32_encode_buf(nr, &buf); + hex = hexbytes_from_bytes(original,size); if ( strcmp(hex,expected_res) ) { printf("Expected: %s\nObtained: %s\n", expected_res, hex); } CU_ASSERT_STRING_EQUAL(hex, expected_res); +lwfree(original); lwfree(hex); } static void do_test_s32_varint(int32_t nr,int expected_size, char* expected_res) { - uint8_t buf[8]; + uint8_t *buf, *original; int size; char *hex; + buf = original=lwalloc(8); size = varint_s32_encoded_size(nr); if ( size != expected_size ) { printf("Expected: %d\nObtained: %d\n", expected_size, size); } CU_ASSERT_EQUAL(size,expected_size); - varint_s32_encode_buf(nr, buf); - hex = hexbytes_from_bytes(buf,size); + varint_s32_encode_buf(nr, &buf); + hex = hexbytes_from_bytes(original,size); if ( strcmp(hex,expected_res) ) { printf("Expected: %s\nObtained: %s\n", expected_res, hex); } CU_ASSERT_STRING_EQUAL(hex, expected_res); +lwfree(original); lwfree(hex); } static void do_test_u64_varint(uint64_t nr,int expected_size, char* expected_res) { - uint8_t buf[8]; + uint8_t *buf, *original; int size; char *hex; + buf = original=lwalloc(8); size = varint_u64_encoded_size(nr); if ( size != expected_size ) { printf("Expected: %d\nObtained: %d\n", expected_size, size); } CU_ASSERT_EQUAL(size,expected_size); - varint_u64_encode_buf(nr, buf); - hex = hexbytes_from_bytes(buf,size); + varint_u64_encode_buf(nr, &buf); + hex = hexbytes_from_bytes(original,size); if ( strcmp(hex,expected_res) ) { printf("Expected: %s\nObtained: %s\n", expected_res, hex); } - CU_ASSERT_STRING_EQUAL(hex, expected_res); + CU_ASSERT_STRING_EQUAL(hex, expected_res); +lwfree(original); lwfree(hex); } static void do_test_s64_varint(int64_t nr,int expected_size, char* expected_res) { - uint8_t buf[8]; + uint8_t *buf, *original; int size; char *hex; + buf = original=lwalloc(8); size = varint_s64_encoded_size(nr); if ( size != expected_size ) { printf("Expected: %d\nObtained: %d\n", expected_size, size); } CU_ASSERT_EQUAL(size,expected_size); - varint_s64_encode_buf(nr, buf); - hex = hexbytes_from_bytes(buf,size); + varint_s64_encode_buf(nr, &buf); + hex = hexbytes_from_bytes(original,size); if ( strcmp(hex,expected_res) ) { printf("Expected: %s\nObtained: %s\n", expected_res, hex); } CU_ASSERT_STRING_EQUAL(hex, expected_res); +lwfree(original); lwfree(hex); } diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in index 597eefbd1..5d6ac29ba 100644 --- a/liblwgeom/liblwgeom.h.in +++ b/liblwgeom/liblwgeom.h.in @@ -1798,6 +1798,8 @@ LWGEOM_UNPARSER_RESULT; */ #define TWKB_ID 0x01 #define TWKB_NO_TYPE 0x02 +#define TWKB_SIZES 0x04 +#define TWKB_BBOXES 0x08 /* @@ -1817,8 +1819,8 @@ extern char* lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, */ extern uint8_t* lwgeom_to_wkb(const LWGEOM *geom, uint8_t variant, size_t *size_out); -extern uint8_t* lwgeom_to_twkb(const LWGEOM *geom, uint8_t variant, size_t *size_out,int8_t prec, int64_t id,int method); -extern uint8_t* lwgeom_agg_to_twkb(const twkb_geom_arrays *lwgeom_arrays,uint8_t variant , size_t *size_out,int8_t prec, int method); +extern uint8_t* lwgeom_to_twkb(const LWGEOM *geom, uint8_t variant, size_t *size_out,int8_t prec, int64_t id); +extern uint8_t* lwgeom_agg_to_twkb(const twkb_geom_arrays *lwgeom_arrays,uint8_t variant , size_t *size_out,int8_t prec); /** * @param lwgeom geometry to convert to HEXWKB diff --git a/liblwgeom/lwout_twkb.c b/liblwgeom/lwout_twkb.c index 356296587..140dbef16 100644 --- a/liblwgeom/lwout_twkb.c +++ b/liblwgeom/lwout_twkb.c @@ -92,12 +92,13 @@ static uint8_t lwgeom_twkb_type(const LWGEOM *geom, uint8_t variant) /** Function for putting a Byte value into the buffer */ -static uint8_t* uint8_to_twkb_buf(const uint8_t ival, uint8_t *buf) +static int uint8_to_twkb_buf(const uint8_t ival, uint8_t **buf) { LWDEBUGF(2, "Entered uint8_to_twkb_buf",0); LWDEBUGF(4, "Writing value %d",ival); - memcpy(buf, &ival, WKB_BYTE_SIZE); - return buf + 1; + memcpy(*buf, &ival, WKB_BYTE_SIZE); + (*buf)++; + return 0; } /* @@ -117,7 +118,7 @@ static size_t empty_to_twkb_size(const LWGEOM *geom, uint8_t variant, int64_t id return size; } -static uint8_t* empty_to_twkb_buf(const LWGEOM *geom, uint8_t *buf, uint8_t variant,int8_t prec, int64_t id) +static int empty_to_twkb_buf(const LWGEOM *geom, uint8_t **buf, uint8_t variant,int8_t prec, int64_t id) { LWDEBUGF(2, "Entered empty_to_twkb_buf",0); uint32_t wkb_type = lwgeom_twkb_type(geom, variant); @@ -130,51 +131,30 @@ static uint8_t* empty_to_twkb_buf(const LWGEOM *geom, uint8_t *buf, uint8_t vari uint8_t flag=0; /* Set the id flag */ - END_PREC_SET_ID(flag, ((variant & TWKB_ID) ? 1 : 0)); + FIRST_BYTE_SET_ID(flag, ((variant & TWKB_ID) ? 1 : 0)); /* Tell what precision to use*/ - END_PREC_SET_PRECISION(flag,prec); + FIRST_BYTE_SET_PRECISION(flag,prec); /*Copy the flag to the buffer*/ - buf = uint8_to_twkb_buf(flag,buf); + uint8_to_twkb_buf(flag,buf); /* Set the geometry id */ - buf = varint_s64_encode_buf(id, buf); + varint_s64_encode_buf(id, buf); /* Set the geometry type */ - buf = uint8_to_twkb_buf(wkb_type,buf); + uint8_to_twkb_buf(wkb_type,buf); /* Set nrings/npoints/ngeoms to zero */ - buf = varint_u64_encode_buf(0, buf); - return buf; -} - -/** -Chooses between encoding/compression methods for calculating the needed space -*/ -static size_t ptarray_to_twkb_size(const POINTARRAY *pa, uint8_t variant,int prec,int64_t accum_rel[],int method) -{ - LWDEBUGF(2, "Entered ptarray_to_twkb_size",0); - switch (method) - { - case 1: - return ptarray_to_twkb_size_m1(pa, variant,prec,accum_rel); - break; - /* Unknown method! */ - default: - lwerror("Unsupported compression method: %d",method ); - } - /*Just to make the compiler quiet*/ - return 0; + varint_u64_encode_buf(0, buf); + return 0; } - - /** Calculates the needed space for storing a specific pointarray as varInt-encoded */ -static size_t ptarray_to_twkb_size_m1(const POINTARRAY *pa, uint8_t variant,int prec,int64_t accum_rel[]) +static size_t ptarray_to_twkb_size(const POINTARRAY *pa, uint8_t variant,int prec,int64_t accum_rel[]) { LWDEBUGF(2, "Entered ptarray_to_twkb_size_m1",0); int64_t r; @@ -208,30 +188,11 @@ static size_t ptarray_to_twkb_size_m1(const POINTARRAY *pa, uint8_t variant,int return size; } -/** -Chooses between encoding/compression methods for storing the pointarray -*/ -static uint8_t* ptarray_to_twkb_buf(const POINTARRAY *pa, uint8_t *buf, uint8_t variant,int8_t prec,int64_t accum_rel[],int method) -{ - LWDEBUGF(2, "Entered ptarray_to_twkb_buf",0); - switch (method) - { - case 1: - buf = ptarray_to_twkb_buf_m1(pa, buf, variant,prec,accum_rel); - return buf; - break; - /* Unknown method! */ - default: - lwerror("Unsupported compression method: %d",method ); - } - /*Just to make the compiler quiet*/ - return 0; -} /** Stores a pointarray as varInts in the buffer */ -static uint8_t* ptarray_to_twkb_buf_m1(const POINTARRAY *pa, uint8_t *buf, uint8_t variant,int8_t prec,int64_t accum_rel[]) +static int ptarray_to_twkb_buf(const POINTARRAY *pa, uint8_t **buf, uint8_t variant,int8_t prec,int64_t accum_rel[]) { LWDEBUGF(2, "entered ptarray_to_twkb_buf_m1\n",0); int64_t r; @@ -245,7 +206,7 @@ static uint8_t* ptarray_to_twkb_buf_m1(const POINTARRAY *pa, uint8_t *buf, uint8 /* Set the number of points (if it's not a POINT type) */ if ( ! ( variant & WKB_NO_NPOINTS ) ) { - buf = varint_u64_encode_buf(pa->npoints,buf); + varint_u64_encode_buf(pa->npoints,buf); LWDEBUGF(4, "Register npoints:%d",pa->npoints); } @@ -259,13 +220,13 @@ static uint8_t* ptarray_to_twkb_buf_m1(const POINTARRAY *pa, uint8_t *buf, uint8 but instead the distance from our accumulated last point This is important to not build up a accumulated error when rounding the coordinates*/ r=(int64_t) lround(factor*dbl_ptr[j]-accum_rel[j]); -LWDEBUGF(4, "deltavalue: %d, ",r ); + LWDEBUGF(4, "deltavalue: %d, ",r ); accum_rel[j]+=r; - buf = varint_s64_encode_buf(r,buf); + varint_s64_encode_buf(r,buf); } } //LWDEBUGF(4, "Done (buf = %p)", buf); - return buf; + return 0; } /****************************************************************** @@ -274,7 +235,7 @@ POINTS /** Calculates needed storage size for aggregated points */ -static size_t lwgeom_agg_to_twkbpoint_size(lwgeom_id *geom_array,uint8_t variant,int n,int8_t prec,int64_t refpoint[],int method) +static size_t lwgeom_agg_to_twkbpoint_size(lwgeom_id *geom_array,uint8_t variant,int n,int8_t prec,int64_t refpoint[]) { lwgeom_id *li; /*One byte for type declaration*/ @@ -286,14 +247,14 @@ static size_t lwgeom_agg_to_twkbpoint_size(lwgeom_id *geom_array,uint8_t varian for (i=0;igeom),variant,prec,li->id,refpoint,method); + size += lwpoint_to_twkb_size((LWPOINT*) (li->geom),variant,prec,li->id,refpoint); } return size; } /** Calculates needed storage size for a point */ -static size_t lwpoint_to_twkb_size(const LWPOINT *pt,uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[],int method) +static size_t lwpoint_to_twkb_size(const LWPOINT *pt,uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[]) { size_t size = 0; /* geometry id, if not subgeometry in type 4,5 or 6*/ @@ -301,14 +262,14 @@ static size_t lwpoint_to_twkb_size(const LWPOINT *pt,uint8_t variant, int8_t pre size += varint_s64_encoded_size((int64_t) id); /* Points */ - size += ptarray_to_twkb_size(pt->point, variant | WKB_NO_NPOINTS, prec,refpoint,method); + size += ptarray_to_twkb_size(pt->point, variant | WKB_NO_NPOINTS, prec,refpoint); return size; } /** Iterates an aggregation of points */ -static uint8_t* lwgeom_agg_to_twkbpoint_buf(lwgeom_id* geom_array,int n, uint8_t *buf, uint8_t variant,int8_t prec, int64_t refpoint[],int method) +static int lwgeom_agg_to_twkbpoint_buf(lwgeom_id* geom_array,int n, uint8_t **buf, uint8_t variant,int8_t prec, int64_t refpoint[]) { lwgeom_id *li; @@ -324,36 +285,36 @@ static uint8_t* lwgeom_agg_to_twkbpoint_buf(lwgeom_id* geom_array,int n, uint8_t lwerror("TWKB only supports 4 dimensions"); TYPE_DIM_SET_DIM(type_flag,dims); LWDEBUGF(4, "Writing ndims '%d'", dims); - buf = uint8_to_twkb_buf(type_flag,buf); + uint8_to_twkb_buf(type_flag,buf); /* Set number of geometries */ - buf = varint_u64_encode_buf(n, buf); + varint_u64_encode_buf(n, buf); for (i=0;igeom),buf,variant,prec,li->id,refpoint,method); + lwpoint_to_twkb_buf((LWPOINT*) (li->geom),buf,variant,prec,li->id,refpoint); } - return buf; + return 0; } /** Sends a point to the buffer */ -static uint8_t* lwpoint_to_twkb_buf(const LWPOINT *pt, uint8_t *buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[],int method) +static int lwpoint_to_twkb_buf(const LWPOINT *pt, uint8_t **buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[]) { /* Set the geometry id, if not subgeometry in type 4,5 or 6*/ if (variant & TWKB_ID) - buf = varint_s64_encode_buf(id, buf); + varint_s64_encode_buf(id, buf); /* Set the coordinates */ - buf = ptarray_to_twkb_buf(pt->point, buf, variant | WKB_NO_NPOINTS,prec,refpoint,method); + ptarray_to_twkb_buf(pt->point, buf, variant | WKB_NO_NPOINTS,prec,refpoint); LWDEBUGF(4, "Pointarray set, buf = %p", buf); - return buf; + return 0; } /****************************************************************** @@ -362,7 +323,7 @@ LINESTRINGS /** Calculates needed storage size for aggregated lines */ -static size_t lwgeom_agg_to_twkbline_size(lwgeom_id* geom_array,uint8_t variant,int n,int8_t prec,int64_t refpoint[],int method) +static size_t lwgeom_agg_to_twkbline_size(lwgeom_id* geom_array,uint8_t variant,int n,int8_t prec,int64_t refpoint[]) { lwgeom_id *li; /*One byte for type declaration*/ @@ -373,14 +334,14 @@ static size_t lwgeom_agg_to_twkbline_size(lwgeom_id* geom_array,uint8_t variant for (i=0;igeom),variant,prec,li->id,refpoint,method); + size += lwline_to_twkb_size((LWLINE*) (li->geom),variant,prec,li->id,refpoint); } return size; } /** Calculates needed storage size for a line */ -static size_t lwline_to_twkb_size(const LWLINE *line,uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[],int method) +static size_t lwline_to_twkb_size(const LWLINE *line,uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[]) { size_t size = 0; /* geometry id, if not subgeometry in type 4,5 or 6*/ @@ -388,13 +349,13 @@ static size_t lwline_to_twkb_size(const LWLINE *line,uint8_t variant, int8_t pre size += varint_s64_encoded_size((int64_t) id); /* Size of point array */ - size += ptarray_to_twkb_size(line->points,variant,prec,refpoint,method); + size += ptarray_to_twkb_size(line->points,variant,prec,refpoint); return size; } /** Iterates an aggregation of lines */ -static uint8_t* lwgeom_agg_to_twkbline_buf(lwgeom_id* geom_array,int n, uint8_t *buf, uint8_t variant,int8_t prec, int64_t refpoint[],int method) +static int lwgeom_agg_to_twkbline_buf(lwgeom_id* geom_array,int n, uint8_t **buf, uint8_t variant,int8_t prec, int64_t refpoint[]) { lwgeom_id *li; @@ -410,32 +371,32 @@ static uint8_t* lwgeom_agg_to_twkbline_buf(lwgeom_id* geom_array,int n, uint8_t lwerror("TWKB only supports 4 dimensions"); TYPE_DIM_SET_DIM(type_flag,dims); LWDEBUGF(4, "Writing ndims '%d'", dims); - buf = uint8_to_twkb_buf(type_flag,buf); + uint8_to_twkb_buf(type_flag,buf); /* Set number of geometries */ - buf = varint_u64_encode_buf(n, buf); + varint_u64_encode_buf(n, buf); for (i=0;igeom,buf,variant,prec,li->id,refpoint,method); + lwline_to_twkb_buf((LWLINE*) li->geom,buf,variant,prec,li->id,refpoint); } - return buf; + return 0; } /** Sends a line to the buffer */ -static uint8_t* lwline_to_twkb_buf(const LWLINE *line, uint8_t *buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[],int method) +static int lwline_to_twkb_buf(const LWLINE *line, uint8_t **buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[]) { /* Set the geometry id, if not subgeometry in type 4,5 or 6*/ if (variant & TWKB_ID) - buf = varint_s64_encode_buf(id, buf); + varint_s64_encode_buf(id, buf); /* Set the coordinates */ - buf = ptarray_to_twkb_buf(line->points, buf, variant,prec,refpoint,method); - return buf; + ptarray_to_twkb_buf(line->points, buf, variant,prec,refpoint); + return 0; } /****************************************************************** @@ -444,7 +405,7 @@ POLYGONS /** Calculates needed storage size for aggregated polygon */ -static size_t lwgeom_agg_to_twkbpoly_size(lwgeom_id* geom_array,uint8_t variant,int n,int8_t prec,int64_t refpoint[],int method) +static size_t lwgeom_agg_to_twkbpoly_size(lwgeom_id* geom_array,uint8_t variant,int n,int8_t prec,int64_t refpoint[]) { lwgeom_id *li; /*One byte for type declaration*/ @@ -455,7 +416,7 @@ static size_t lwgeom_agg_to_twkbpoly_size(lwgeom_id* geom_array,uint8_t variant for (i=0;igeom),variant,prec,li->id,refpoint,method); + size += lwpoly_to_twkb_size((LWPOLY*) (li->geom),variant,prec,li->id,refpoint); } return size; } @@ -463,7 +424,7 @@ static size_t lwgeom_agg_to_twkbpoly_size(lwgeom_id* geom_array,uint8_t variant /** Calculates needed storage size for a polygon */ -static size_t lwpoly_to_twkb_size(const LWPOLY *poly,uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[],int method) +static size_t lwpoly_to_twkb_size(const LWPOLY *poly,uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[]) { LWDEBUGF(2, "lwpoly_to_twkb_size entered%d",0); int i; @@ -480,7 +441,7 @@ static size_t lwpoly_to_twkb_size(const LWPOLY *poly,uint8_t variant, int8_t pre for ( i = 0; i < poly->nrings; i++ ) { /* Size of ring point array */ - size += ptarray_to_twkb_size(poly->rings[i],variant,prec,refpoint,method); + size += ptarray_to_twkb_size(poly->rings[i],variant,prec,refpoint); } return size; @@ -489,7 +450,7 @@ static size_t lwpoly_to_twkb_size(const LWPOLY *poly,uint8_t variant, int8_t pre /** Iterates an aggregation of polygons */ -static uint8_t* lwgeom_agg_to_twkbpoly_buf(lwgeom_id* geom_array,int n, uint8_t *buf, uint8_t variant,int8_t prec, int64_t refpoint[],int method) +static int lwgeom_agg_to_twkbpoly_buf(lwgeom_id* geom_array,int n, uint8_t **buf, uint8_t variant,int8_t prec, int64_t refpoint[]) { lwgeom_id *li; @@ -505,38 +466,38 @@ static uint8_t* lwgeom_agg_to_twkbpoly_buf(lwgeom_id* geom_array,int n, uint8_t lwerror("TWKB only supports 4 dimensions"); TYPE_DIM_SET_DIM(type_flag,dims); LWDEBUGF(4, "Writing ndims '%d'", dims); - buf = uint8_to_twkb_buf(type_flag,buf); + uint8_to_twkb_buf(type_flag,buf); /* Set number of geometries */ - buf = varint_u64_encode_buf(n, buf); + varint_u64_encode_buf(n, buf); for (i=0;igeom),buf,variant,prec,li->id,refpoint,method); + lwpoly_to_twkb_buf((LWPOLY*) (li->geom),buf,variant,prec,li->id,refpoint); } - return buf; + return 0; } /** Sends a polygon to the buffer */ -static uint8_t* lwpoly_to_twkb_buf(const LWPOLY *poly, uint8_t *buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[],int method) +static int lwpoly_to_twkb_buf(const LWPOLY *poly, uint8_t **buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[]) { int i; /* Set the geometry id, if not subgeometry in type 4,5 or 6*/ if (variant & TWKB_ID) - buf = varint_s64_encode_buf(id, buf); + varint_s64_encode_buf(id, buf); /* Set the number of rings */ - buf = varint_u64_encode_buf(poly->nrings, buf); + varint_u64_encode_buf(poly->nrings, buf); for ( i = 0; i < poly->nrings; i++ ) { - buf = ptarray_to_twkb_buf(poly->rings[i], buf, variant,prec,refpoint,method); + ptarray_to_twkb_buf(poly->rings[i], buf, variant,prec,refpoint); } - return buf; + return 0; } /****************************************************************** @@ -545,7 +506,7 @@ COLLECTIONS /** Calculates needed storage size for aggregated collection */ -static size_t lwgeom_agg_to_twkbcollection_size(lwgeom_id* geom_array,uint8_t variant,int n,int8_t prec,int64_t refpoint[],int method) +static size_t lwgeom_agg_to_twkbcollection_size(lwgeom_id* geom_array,uint8_t variant,int n,int8_t prec,int64_t refpoint[]) { lwgeom_id *li; LWDEBUGF(4, "lwgeom_agg_to_twkbcollection_size entered with %d collections",n); @@ -557,7 +518,7 @@ static size_t lwgeom_agg_to_twkbcollection_size(lwgeom_id* geom_array,uint8_t v for (i=0;igeom),variant,prec,li->id,refpoint,method); + size += lwcollection_to_twkb_size((LWCOLLECTION*) (li->geom),variant,prec,li->id,refpoint); } return size; } @@ -565,7 +526,7 @@ static size_t lwgeom_agg_to_twkbcollection_size(lwgeom_id* geom_array,uint8_t v /** Calculates needed storage size for a collection */ -static size_t lwcollection_to_twkb_size(const LWCOLLECTION *col,uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[],int method) +static size_t lwcollection_to_twkb_size(const LWCOLLECTION *col,uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[]) { LWDEBUGF(2, "lwcollection_to_twkb_size entered, %d",0); size_t size = 0; @@ -579,7 +540,7 @@ static size_t lwcollection_to_twkb_size(const LWCOLLECTION *col,uint8_t variant, for ( i = 0; i < col->ngeoms; i++ ) { /* size of subgeom */ - size += lwgeom_to_twkb_size((LWGEOM*)col->geoms[i],variant & ~TWKB_ID, prec,id,refpoint,method); + size += lwgeom_to_twkb_size((LWGEOM*)col->geoms[i],variant & ~TWKB_ID, prec,id,refpoint); } return size; @@ -588,7 +549,7 @@ static size_t lwcollection_to_twkb_size(const LWCOLLECTION *col,uint8_t variant, /** Iterates an aggregation of collections */ -static uint8_t* lwgeom_agg_to_twkbcollection_buf(lwgeom_id* geom_array,int n, uint8_t *buf, uint8_t variant,int8_t prec, int64_t refpoint[],int method) +static int lwgeom_agg_to_twkbcollection_buf(lwgeom_id* geom_array,int n, uint8_t **buf, uint8_t variant,int8_t prec, int64_t refpoint[]) { lwgeom_id *li; @@ -604,40 +565,40 @@ static uint8_t* lwgeom_agg_to_twkbcollection_buf(lwgeom_id* geom_array,int n, ui lwerror("TWKB only supports 4 dimensions"); TYPE_DIM_SET_DIM(type_flag,dims); LWDEBUGF(4, "Writing ndims '%d'", dims); - buf = uint8_to_twkb_buf(type_flag,buf); + uint8_to_twkb_buf(type_flag,buf); /* Set number of geometries */ - buf = varint_u64_encode_buf(n, buf); + varint_u64_encode_buf(n, buf); for (i=0;igeom,buf,variant,prec,li->id,refpoint,method); + lwcollection_to_twkb_buf((LWCOLLECTION*) li->geom,buf,variant,prec,li->id,refpoint); } - return buf; + return 0; } /** Iterates a collection */ -static uint8_t* lwcollection_to_twkb_buf(const LWCOLLECTION *col, uint8_t *buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[],int method) +static int lwcollection_to_twkb_buf(const LWCOLLECTION *col, uint8_t **buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[]) { int i; /* Set the geometry id, if not subgeometry in type 4,5 or 6*/ if (variant & TWKB_ID) - buf = varint_s64_encode_buf(id, buf); + varint_s64_encode_buf(id, buf); /* Set the number of rings */ - buf = varint_u64_encode_buf(col->ngeoms, buf); + varint_u64_encode_buf(col->ngeoms, buf); /* Write the sub-geometries. Sub-geometries do not get SRIDs, they inherit from their parents. */ for ( i = 0; i < col->ngeoms; i++ ) { - buf = lwgeom_to_twkb_buf(col->geoms[i], buf, variant & ~TWKB_ID,prec,id,refpoint,method); + lwgeom_to_twkb_buf(col->geoms[i], buf, variant & ~TWKB_ID,prec,id,refpoint); } - return buf; + return 0; } @@ -648,7 +609,7 @@ Handle whole TWKB /** Calculates the needed space for a geometry as twkb */ -static size_t lwgeom_to_twkb_size(const LWGEOM *geom,uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[],int method) +static size_t lwgeom_to_twkb_size(const LWGEOM *geom,uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[]) { LWDEBUGF(2, "lwgeom_to_twkb_size entered %d",0); size_t size = 0; @@ -666,18 +627,18 @@ static size_t lwgeom_to_twkb_size(const LWGEOM *geom,uint8_t variant, int8_t pre switch ( geom->type ) { case POINTTYPE: - size += lwpoint_to_twkb_size((LWPOINT*)geom, variant, prec,id,refpoint,method); + size += lwpoint_to_twkb_size((LWPOINT*)geom, variant, prec,id,refpoint); break; /* LineString and CircularString both have points elements */ case CIRCSTRINGTYPE: case LINETYPE: - size += lwline_to_twkb_size((LWLINE*)geom, variant, prec,id,refpoint,method); + size += lwline_to_twkb_size((LWLINE*)geom, variant, prec,id,refpoint); break; /* Polygon has nrings and rings elements */ case POLYGONTYPE: - size += lwpoly_to_twkb_size((LWPOLY*)geom, variant, prec,id,refpoint,method); + size += lwpoly_to_twkb_size((LWPOLY*)geom, variant, prec,id,refpoint); break; /* Triangle has one ring of three points @@ -689,10 +650,10 @@ static size_t lwgeom_to_twkb_size(const LWGEOM *geom,uint8_t variant, int8_t pre case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: - size += lwcollection_to_twkb_size((LWCOLLECTION*)geom, variant | TWKB_NO_TYPE, prec,id,refpoint,method); + size += lwcollection_to_twkb_size((LWCOLLECTION*)geom, variant | TWKB_NO_TYPE, prec,id,refpoint); break; case COLLECTIONTYPE: - size += lwcollection_to_twkb_size((LWCOLLECTION*)geom, variant, prec,id,refpoint,method); + size += lwcollection_to_twkb_size((LWCOLLECTION*)geom, variant, prec,id,refpoint); break; /* Unknown type! */ @@ -704,7 +665,7 @@ static size_t lwgeom_to_twkb_size(const LWGEOM *geom,uint8_t variant, int8_t pre } -static uint8_t* lwgeom_to_twkb_buf(const LWGEOM *geom, uint8_t *buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[],int method) +static int lwgeom_to_twkb_buf(const LWGEOM *geom, uint8_t **buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[]) { if ( lwgeom_is_empty(geom) ) @@ -716,8 +677,8 @@ static uint8_t* lwgeom_to_twkb_buf(const LWGEOM *geom, uint8_t *buf, uint8_t var { LWDEBUGF(4,"Type found is Point, %d",geom->type); if (!(variant & TWKB_NO_TYPE)) - buf = uint8_to_twkb_buf(lwgeom_twkb_type(geom, variant),buf); - return lwpoint_to_twkb_buf((LWPOINT*)geom, buf, variant,prec,id,refpoint,method); + uint8_to_twkb_buf(lwgeom_twkb_type(geom, variant),buf); + return lwpoint_to_twkb_buf((LWPOINT*)geom, buf, variant,prec,id,refpoint); } /* LineString and CircularString both have 'points' elements */ case CIRCSTRINGTYPE: @@ -725,16 +686,16 @@ static uint8_t* lwgeom_to_twkb_buf(const LWGEOM *geom, uint8_t *buf, uint8_t var { LWDEBUGF(4,"Type found is Linestring, %d",geom->type); if (!(variant & TWKB_NO_TYPE)) - buf = uint8_to_twkb_buf(lwgeom_twkb_type(geom, variant),buf); - return lwline_to_twkb_buf((LWLINE*)geom, buf, variant,prec,id,refpoint,method); + uint8_to_twkb_buf(lwgeom_twkb_type(geom, variant),buf); + return lwline_to_twkb_buf((LWLINE*)geom, buf, variant,prec,id,refpoint); } /* Polygon has 'nrings' and 'rings' elements */ case POLYGONTYPE: { LWDEBUGF(4,"Type found is Polygon, %d",geom->type); if (!(variant & TWKB_NO_TYPE)) - buf = uint8_to_twkb_buf(lwgeom_twkb_type(geom, variant),buf); - return lwpoly_to_twkb_buf((LWPOLY*)geom, buf, variant,prec,id,refpoint,method); + uint8_to_twkb_buf(lwgeom_twkb_type(geom, variant),buf); + return lwpoly_to_twkb_buf((LWPOLY*)geom, buf, variant,prec,id,refpoint); } /* Triangle has one ring of three points case TRIANGLETYPE: @@ -746,15 +707,15 @@ static uint8_t* lwgeom_to_twkb_buf(const LWGEOM *geom, uint8_t *buf, uint8_t var case MULTIPOLYGONTYPE: { LWDEBUGF(4,"Type found is Multi, %d",geom->type); - buf = uint8_to_twkb_buf(lwgeom_twkb_type(geom, variant),buf); + uint8_to_twkb_buf(lwgeom_twkb_type(geom, variant),buf); /*the NO_TYPE flag tells that the type not shall be repeated for subgeometries*/ - return lwcollection_to_twkb_buf((LWCOLLECTION*)geom, buf, variant | TWKB_NO_TYPE,prec,id,refpoint,method); + return lwcollection_to_twkb_buf((LWCOLLECTION*)geom, buf, variant | TWKB_NO_TYPE,prec,id,refpoint); } case COLLECTIONTYPE: { LWDEBUGF(4,"Type found is collection, %d",geom->type); - buf = uint8_to_twkb_buf(lwgeom_twkb_type(geom, variant),buf); - return lwcollection_to_twkb_buf((LWCOLLECTION*)geom, buf, variant,prec,id,refpoint,method); + uint8_to_twkb_buf(lwgeom_twkb_type(geom, variant),buf); + return lwcollection_to_twkb_buf((LWCOLLECTION*)geom, buf, variant,prec,id,refpoint); } /* Unknown type! */ default: @@ -768,15 +729,13 @@ static uint8_t* lwgeom_to_twkb_buf(const LWGEOM *geom, uint8_t *buf, uint8_t var * Convert LWGEOM to a char* in TWKB format. Caller is responsible for freeing * the returned array. */ -uint8_t* lwgeom_to_twkb(const LWGEOM *geom, uint8_t variant, size_t *size_out,int8_t prec, int64_t id,int method) +uint8_t* lwgeom_to_twkb(const LWGEOM *geom, uint8_t variant, size_t *size_out,int8_t prec, int64_t id) { - size_t buf_size; + size_t buf_size=0,size_size=0; uint8_t *buf = NULL; uint8_t *wkb_out = NULL; uint8_t flag=0; - /*an integer array holding the reference point. In most cases the last used point - but in the case of pointcloud it is a user defined refpoint. - INT32_MIN indicates that the ref-point is not set yet*/ + /*an integer array holding the reference point, the last used point*/ int64_t refpoint[4]={0,0,0,0}; int64_t refpoint2[4]= {0,0,0,0}; @@ -793,8 +752,8 @@ uint8_t* lwgeom_to_twkb(const LWGEOM *geom, uint8_t variant, size_t *size_out,in /* Calculate the required size of the output buffer */ /*Adding the size for the first byte*/ - buf_size = 1; - buf_size += lwgeom_to_twkb_size(geom,variant,prec,id,refpoint,method); + buf_size += 1; + buf_size += lwgeom_to_twkb_size(geom,variant,prec,id,refpoint); LWDEBUGF(4, "WKB output size: %d", buf_size); if ( buf_size == 0 ) @@ -803,9 +762,12 @@ uint8_t* lwgeom_to_twkb(const LWGEOM *geom, uint8_t variant, size_t *size_out,in lwerror("Error calculating output TWKB buffer size."); return NULL; } - + /*If we want geometry sizes, we need space for that (the size we are going to store is the twkb_size - first byte and size value itself)*/ + if(variant & TWKB_SIZES) + size_size=varint_u64_encoded_size((uint64_t) (buf_size-1)); + /* Allocate the buffer */ - buf = lwalloc(buf_size); + buf = lwalloc(buf_size+size_size); if ( buf == NULL ) { LWDEBUGF(4,"Unable to allocate %d bytes for TWKB output buffer.", buf_size); @@ -819,24 +781,29 @@ uint8_t* lwgeom_to_twkb(const LWGEOM *geom, uint8_t variant, size_t *size_out,in /* set ID bit if ID*/ - END_PREC_SET_ID(flag, ((variant & TWKB_ID) ? 1 : 0)); - /* Tell what method to use*/ - END_PREC_SET_METHOD(flag, method); + FIRST_BYTE_SET_ID(flag, ((variant & TWKB_ID) ? 0xFF : 0)); + /* set second bit if we are going to store resulting size*/ + FIRST_BYTE_SET_SIZES(flag, ((variant & TWKB_SIZES) ? 0xFF : 0)); + /* set third bit if we are going to store bboxes*/ + FIRST_BYTE_SET_BBOXES(flag, ((variant & TWKB_BBOXES) ? 0xFF : 0)); + /* Tell what precision to use*/ - END_PREC_SET_PRECISION(flag,prec); + FIRST_BYTE_SET_PRECISION(flag,prec); /*Copy the flag to the buffer*/ - buf = uint8_to_twkb_buf(flag,buf); + uint8_to_twkb_buf(flag,&buf); - + /*Write the size of the geometry*/ + if(variant & TWKB_SIZES) + varint_u64_encode_buf((uint64_t) (buf_size-1), &buf); /* Write the WKB into the output buffer */ - buf = lwgeom_to_twkb_buf(geom, buf,variant, prec,id,refpoint2,method); + lwgeom_to_twkb_buf(geom, &buf,variant, prec,id,refpoint2); LWDEBUGF(4,"buf (%p) - wkb_out (%p) = %d", buf, wkb_out, buf - wkb_out); /* The buffer pointer should now land at the end of the allocated buffer space. Let's check. */ - if ( buf_size != (buf - wkb_out) ) + if ( (buf_size+size_size) != (buf - wkb_out) ) { LWDEBUG(4,"Output TWKB is not the same size as the allocated buffer."); lwerror("Output TWKB is not the same size as the allocated buffer (precalculated size:%d, allocated size:%d)", buf_size, (buf - wkb_out)); @@ -845,14 +812,14 @@ uint8_t* lwgeom_to_twkb(const LWGEOM *geom, uint8_t variant, size_t *size_out,in } /* Report output size */ - if ( size_out ) *size_out = buf_size; + if ( size_out ) *size_out = (buf_size+size_size); return wkb_out; } -uint8_t* lwgeom_agg_to_twkb(const twkb_geom_arrays *lwgeom_arrays,uint8_t variant , size_t *size_out,int8_t prec,int method) +uint8_t* lwgeom_agg_to_twkb(const twkb_geom_arrays *lwgeom_arrays,uint8_t variant , size_t *size_out,int8_t prec) { - size_t buf_size; + size_t buf_size=0,size_size=0; uint8_t *buf = NULL; uint8_t flag = 0; uint8_t *wkb_out = NULL; @@ -891,13 +858,13 @@ uint8_t* lwgeom_agg_to_twkb(const twkb_geom_arrays *lwgeom_arrays,uint8_t varian if (lwgeom_arrays->n_points > 0) - buf_size += lwgeom_agg_to_twkbpoint_size(lwgeom_arrays->points,variant,lwgeom_arrays->n_points, prec,refpoint,method); + buf_size += lwgeom_agg_to_twkbpoint_size(lwgeom_arrays->points,variant,lwgeom_arrays->n_points, prec,refpoint); if (lwgeom_arrays->n_linestrings > 0) - buf_size += lwgeom_agg_to_twkbline_size(lwgeom_arrays->linestrings,variant,lwgeom_arrays->n_linestrings, prec,refpoint,method); + buf_size += lwgeom_agg_to_twkbline_size(lwgeom_arrays->linestrings,variant,lwgeom_arrays->n_linestrings, prec,refpoint); if (lwgeom_arrays->n_polygons > 0) - buf_size += lwgeom_agg_to_twkbpoly_size(lwgeom_arrays->polygons,variant,lwgeom_arrays->n_polygons, prec,refpoint,method); + buf_size += lwgeom_agg_to_twkbpoly_size(lwgeom_arrays->polygons,variant,lwgeom_arrays->n_polygons, prec,refpoint); if (lwgeom_arrays->n_collections > 0) - buf_size += lwgeom_agg_to_twkbcollection_size(lwgeom_arrays->collections,variant,lwgeom_arrays->n_collections, prec,refpoint,method); + buf_size += lwgeom_agg_to_twkbcollection_size(lwgeom_arrays->collections,variant,lwgeom_arrays->n_collections, prec,refpoint); @@ -911,9 +878,13 @@ uint8_t* lwgeom_agg_to_twkb(const twkb_geom_arrays *lwgeom_arrays,uint8_t varian lwerror("Error calculating output TWKB buffer size."); return NULL; } - + + /*If we want geometry sizes, we need space for that (the size we are going to store is the twkb_size - first byte and size value itself)*/ + if(variant & TWKB_SIZES) + size_size=varint_u64_encoded_size((uint64_t) (buf_size-1)); + /* Allocate the buffer */ - buf = lwalloc(buf_size); + buf = lwalloc(buf_size+size_size); if ( buf == NULL ) { @@ -927,15 +898,21 @@ uint8_t* lwgeom_agg_to_twkb(const twkb_geom_arrays *lwgeom_arrays,uint8_t varian /* Set the id flag */ - END_PREC_SET_ID(flag, ((variant & TWKB_ID) ? 1 : 0)); - /* Tell what method to use*/ - END_PREC_SET_METHOD(flag, method); + FIRST_BYTE_SET_ID(flag, ((variant & TWKB_ID) ? 1 : 0)); + /* set second bit if we are going to store resulting size*/ + FIRST_BYTE_SET_SIZES(flag, ((variant & TWKB_SIZES) ? 0xFF : 0)); + /* set third bit if we are going to store bboxes*/ + FIRST_BYTE_SET_BBOXES(flag, ((variant & TWKB_BBOXES) ? 0xFF : 0)); /* Tell what precision to use*/ - END_PREC_SET_PRECISION(flag,prec); + FIRST_BYTE_SET_PRECISION(flag,prec); /*Copy the flag to the buffer*/ - buf = uint8_to_twkb_buf(flag,buf); + uint8_to_twkb_buf(flag,&buf); + /*Write the size of the geometry*/ + if(variant & TWKB_SIZES) + varint_u64_encode_buf((uint64_t) (buf_size-1), &buf); + /*set type and number of geometries for the top level, if more than 1 type og underlying geometries*/ if(chk_homogenity>1) { @@ -948,23 +925,23 @@ uint8_t* lwgeom_agg_to_twkb(const twkb_geom_arrays *lwgeom_arrays,uint8_t varian dims = 4; TYPE_DIM_SET_DIM(type_flag,dims); LWDEBUGF(4, "Writing ndims '%d'", dims); - buf = uint8_to_twkb_buf(type_flag,buf); + uint8_to_twkb_buf(type_flag,&buf); /* Set number of geometries */ - buf = varint_u64_encode_buf(chk_homogenity, buf); + varint_u64_encode_buf(chk_homogenity, &buf); } /* Write the WKB into the output buffer buf = lwgeom_to_twkb_buf(geom, buf,variant, prec,id,refpoint2);*/ if (lwgeom_arrays->n_points > 0) - buf =lwgeom_agg_to_twkbpoint_buf(lwgeom_arrays->points,lwgeom_arrays->n_points, buf,variant, prec,refpoint2,method); + lwgeom_agg_to_twkbpoint_buf(lwgeom_arrays->points,lwgeom_arrays->n_points, &buf,variant, prec,refpoint2); if (lwgeom_arrays->n_linestrings > 0) - buf =lwgeom_agg_to_twkbline_buf(lwgeom_arrays->linestrings,lwgeom_arrays->n_linestrings, buf,variant, prec,refpoint2,method); + lwgeom_agg_to_twkbline_buf(lwgeom_arrays->linestrings,lwgeom_arrays->n_linestrings, &buf,variant, prec,refpoint2); if (lwgeom_arrays->n_polygons > 0) - buf =lwgeom_agg_to_twkbpoly_buf(lwgeom_arrays->polygons,lwgeom_arrays->n_polygons, buf,variant, prec,refpoint2,method); + lwgeom_agg_to_twkbpoly_buf(lwgeom_arrays->polygons,lwgeom_arrays->n_polygons, &buf,variant, prec,refpoint2); if (lwgeom_arrays->n_collections > 0) - buf =lwgeom_agg_to_twkbcollection_buf(lwgeom_arrays->collections,lwgeom_arrays->n_collections, buf,variant, prec,refpoint2,method); + lwgeom_agg_to_twkbcollection_buf(lwgeom_arrays->collections,lwgeom_arrays->n_collections, &buf,variant, prec,refpoint2); @@ -972,7 +949,7 @@ uint8_t* lwgeom_agg_to_twkb(const twkb_geom_arrays *lwgeom_arrays,uint8_t varian LWDEBUGF(4,"buf (%p) - wkb_out (%p) = %d", buf, wkb_out, buf - wkb_out); /* The buffer pointer should now land at the end of the allocated buffer space. Let's check. */ - if ( buf_size != (buf - wkb_out) ) + if ( (buf_size+size_size) != (buf - wkb_out) ) { LWDEBUG(4,"Output TWKB is not the same size as the allocated buffer."); lwerror("Output TWKB is not the same size as the allocated buffer (precalculated size:%d, allocated size:%d)", buf_size, (buf - wkb_out)); @@ -981,7 +958,7 @@ uint8_t* lwgeom_agg_to_twkb(const twkb_geom_arrays *lwgeom_arrays,uint8_t varian } /* Report output size */ - if ( size_out ) *size_out = buf_size; + if ( size_out ) *size_out = (buf_size+size_size); return wkb_out; diff --git a/liblwgeom/lwout_twkb.h b/liblwgeom/lwout_twkb.h index e46423c6e..7db86948b 100644 --- a/liblwgeom/lwout_twkb.h +++ b/liblwgeom/lwout_twkb.h @@ -22,9 +22,12 @@ * Precision 4 bits */ -#define END_PREC_SET_ID(flag, id) ((flag) = (flag & 0xFE) | ((id & 0x01))) -#define END_PREC_SET_METHOD(flag, method) ((flag) = (flag & 0xF1) | ((method<<1) & 0x0E)) -#define END_PREC_SET_PRECISION(flag, prec) ((flag) = (flag & 0x0F) | ((prec<<4) & 0xF0)) + +#define FIRST_BYTE_SET_ID(flag, id) ((flag) = (flag & 0xFE) | ((id & 0x01))) +#define FIRST_BYTE_SET_SIZES(flag, sizes) ((flag) = (flag & 0xFD) | ((sizes & 0x02))) +#define FIRST_BYTE_SET_BBOXES(flag, bboxes) ((flag) = (flag & 0xFB) | ((bboxes & 0x04))) + +#define FIRST_BYTE_SET_PRECISION(flag, prec) ((flag) = (flag & 0x0F) | ((prec<<4) & 0xF0)) /** @@ -36,34 +39,31 @@ #define TYPE_DIM_SET_TYPE(flag, type) ((flag) = (flag & 0xE0) | ((type & 0x1F))) #define TYPE_DIM_SET_DIM(flag, dim) ((flag) = (flag & 0x1F) | ((dim & 0x07)<<5)) -static size_t ptarray_to_twkb_size(const POINTARRAY *pa, uint8_t variant,int prec,int64_t accum_rel[],int method); -static uint8_t* ptarray_to_twkb_buf(const POINTARRAY *pa, uint8_t *buf, uint8_t variant,int8_t prec,int64_t accum_rel[],int method); - -static size_t ptarray_to_twkb_size_m1(const POINTARRAY *pa, uint8_t variant,int prec,int64_t accum_rel[]); -static uint8_t* ptarray_to_twkb_buf_m1(const POINTARRAY *pa, uint8_t *buf, uint8_t variant,int8_t prec,int64_t accum_rel[]); +static size_t ptarray_to_twkb_size(const POINTARRAY *pa, uint8_t variant,int prec,int64_t accum_rel[]); +static int ptarray_to_twkb_buf(const POINTARRAY *pa, uint8_t **buf, uint8_t variant,int8_t prec,int64_t accum_rel[]); -static size_t lwgeom_agg_to_twkbpoint_size(lwgeom_id *geom_array, uint8_t variant,int n,int8_t prec,int64_t refpoint[],int method); -static size_t lwpoint_to_twkb_size(const LWPOINT *pt, uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[],int method); -static uint8_t* lwgeom_agg_to_twkbpoint_buf(lwgeom_id* geom_array,int n, uint8_t *buf, uint8_t variant,int8_t prec, int64_t refpoint[],int method); -static uint8_t* lwpoint_to_twkb_buf(const LWPOINT *pt, uint8_t *buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[],int method); +static size_t lwgeom_agg_to_twkbpoint_size(lwgeom_id *geom_array, uint8_t variant,int n,int8_t prec,int64_t refpoint[]); +static size_t lwpoint_to_twkb_size(const LWPOINT *pt, uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[]); +static int lwgeom_agg_to_twkbpoint_buf(lwgeom_id* geom_array,int n, uint8_t **buf, uint8_t variant,int8_t prec, int64_t refpoint[]); +static int lwpoint_to_twkb_buf(const LWPOINT *pt, uint8_t **buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[]); -static size_t lwgeom_agg_to_twkbline_size(lwgeom_id *geom_array, uint8_t variant,int n,int8_t prec,int64_t refpoint[],int method); -static size_t lwline_to_twkb_size(const LWLINE *line, uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[],int method); -static uint8_t* lwgeom_agg_to_twkbline_buf(lwgeom_id* geom_array,int n, uint8_t *buf, uint8_t variant,int8_t prec, int64_t refpoint[],int method); -static uint8_t* lwline_to_twkb_buf(const LWLINE *line, uint8_t *buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[],int method); +static size_t lwgeom_agg_to_twkbline_size(lwgeom_id *geom_array, uint8_t variant,int n,int8_t prec,int64_t refpoint[]); +static size_t lwline_to_twkb_size(const LWLINE *line, uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[]); +static int lwgeom_agg_to_twkbline_buf(lwgeom_id* geom_array,int n, uint8_t **buf, uint8_t variant,int8_t prec, int64_t refpoint[]); +static int lwline_to_twkb_buf(const LWLINE *line, uint8_t **buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[]); -static size_t lwgeom_agg_to_twkbpoly_size(lwgeom_id *geom_array, uint8_t variant,int n,int8_t prec,int64_t refpoint[],int method); -static size_t lwpoly_to_twkb_size(const LWPOLY *poly, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[],int method); -static uint8_t* lwgeom_agg_to_twkbpoly_buf(lwgeom_id* geom_array,int n, uint8_t *buf, uint8_t variant,int8_t prec, int64_t refpoint[],int method); -static uint8_t* lwpoly_to_twkb_buf(const LWPOLY *poly, uint8_t *buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[],int method); +static size_t lwgeom_agg_to_twkbpoly_size(lwgeom_id *geom_array, uint8_t variant,int n,int8_t prec,int64_t refpoint[]); +static size_t lwpoly_to_twkb_size(const LWPOLY *poly, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[]); +static int lwgeom_agg_to_twkbpoly_buf(lwgeom_id* geom_array,int n, uint8_t **buf, uint8_t variant,int8_t prec, int64_t refpoint[]); +static int lwpoly_to_twkb_buf(const LWPOLY *poly, uint8_t **buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[]); -static size_t lwgeom_agg_to_twkbcollection_size(lwgeom_id *geom_array, uint8_t variant,int n,int8_t prec,int64_t refpoint[],int method); -static size_t lwcollection_to_twkb_size(const LWCOLLECTION *col, uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[],int method); -static uint8_t* lwgeom_agg_to_twkbcollection_buf(lwgeom_id* geom_array,int n, uint8_t *buf, uint8_t variant,int8_t prec, int64_t refpoint[],int method); -static uint8_t* lwcollection_to_twkb_buf(const LWCOLLECTION *col, uint8_t *buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[],int method); +static size_t lwgeom_agg_to_twkbcollection_size(lwgeom_id *geom_array, uint8_t variant,int n,int8_t prec,int64_t refpoint[]); +static size_t lwcollection_to_twkb_size(const LWCOLLECTION *col, uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[]); +static int lwgeom_agg_to_twkbcollection_buf(lwgeom_id* geom_array,int n, uint8_t **buf, uint8_t variant,int8_t prec, int64_t refpoint[]); +static int lwcollection_to_twkb_buf(const LWCOLLECTION *col, uint8_t **buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[]); -static size_t lwgeom_to_twkb_size(const LWGEOM *geom, uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[],int method); -static uint8_t* lwgeom_to_twkb_buf(const LWGEOM *geom, uint8_t *buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[],int method); +static size_t lwgeom_to_twkb_size(const LWGEOM *geom, uint8_t variant, int8_t prec, int64_t id,int64_t refpoint[]); +static int lwgeom_to_twkb_buf(const LWGEOM *geom, uint8_t **buf, uint8_t variant,int8_t prec, int64_t id,int64_t refpoint[]); //static size_t lwgeom_to_twkb_size(const LWGEOM *geom, uint8_t variant,int8_t prec); diff --git a/liblwgeom/varint.c b/liblwgeom/varint.c index 1a965d63a..c920ca6bb 100644 --- a/liblwgeom/varint.c +++ b/liblwgeom/varint.c @@ -40,19 +40,31 @@ _varint_u64_encoded_size(uint64_t q) return ++n; } -static uint8_t* -_varint_u64_encode_buf(uint64_t q, uint8_t *buf) +static int +_varint_u64_encode_buf(uint64_t val, uint8_t **buf) { - int n=0, grp; - while ((q>>(7*(n+1))) >0) + uint8_t grp; + uint64_t q=val; + while (1) { - grp=128^(127&(q>>(7*n))); - buf[n++]=grp; + grp=127&q; //We put the 7 least significant bits in grp + q=q>>7; //We rightshift our input value 7 bits which means that the 7 next least significant bits becomes the 7 least significant + if(q>0) // Check if, after our rightshifting, we still have anything to read in our input value. + { + /*In the next line quite a lot is happening. + Since there is more to read in our input value we signalize that by setting the most siginicant bit in our byte to 1. + Then we put that byte in our buffer (**buf) and move the cursor to our buffer (*buf) one step*/ + *((*buf)++)=128^grp; + } + else + { + /*The same as above, but since there is nothing more to read in our input value we leave the most significant bit unset*/ + *((*buf)++)=grp; + // printf("grp1:%d\n",(int) grp); + return 0; + } } - grp=127&(q>>(7*n)); - buf[n++]=grp; - - return buf+=n; + return 0; } unsigned @@ -68,11 +80,12 @@ varint_u32_encoded_size(uint32_t val) return _varint_u64_encoded_size(val); /* implicit upcast to 64bit int */ } -uint8_t* -varint_u32_encode_buf(uint32_t val, uint8_t *buf) +int +varint_u32_encode_buf(uint32_t val, uint8_t **buf) { LWDEBUGF(2, "Entered varint_u32_encode_buf, value %u", val); - return _varint_u64_encode_buf(val, buf); /* implicit upcast to 64bit */ + _varint_u64_encode_buf(val, buf); /* implicit upcast to 64bit */ +return 0; } unsigned @@ -89,12 +102,14 @@ varint_s32_encoded_size(int32_t val) return _varint_u64_encoded_size(q); /* implicit upcast to 64bit int */ } -uint8_t* -varint_s32_encode_buf(int32_t val, uint8_t *buf) +int +varint_s32_encode_buf(int32_t val, uint8_t **buf) { - LWDEBUGF(2, "Entered varint_s32_encode_buf, value %d", val); - uint32_t q = (val << 1) ^ (val >> 31); /* zig-zag encode */ - return _varint_u64_encode_buf(q, buf); /* implicit upcast to 64bit */ + + uint32_t q; + q = (val << 1) ^ (val >> 31);/* zig-zag encode */ + _varint_u64_encode_buf(q, buf);/* implicit upcast to 64bit */ + return 0; } unsigned @@ -111,13 +126,13 @@ varint_s64_encoded_size(int64_t val) return _varint_u64_encoded_size(q); } -uint8_t* -varint_s64_encode_buf(int64_t val, uint8_t *buf) +int +varint_s64_encode_buf(int64_t val, uint8_t **buf) { - LWDEBUGF(2, "Entered varint_s64_encode_buf, value %ld", val); - - uint64_t q = (val << 1) ^ (val >> 63); /* zig-zag encode */ - return _varint_u64_encode_buf(q, buf); + uint64_t q; + q = (val << 1) ^ (val >> 63); + varint_u64_encode_buf(q, buf); + return 0; } unsigned @@ -133,9 +148,10 @@ varint_u64_encoded_size(uint64_t val) return _varint_u64_encoded_size(val); } -uint8_t* -varint_u64_encode_buf(uint64_t val, uint8_t *buf) +int +varint_u64_encode_buf(uint64_t val, uint8_t **buf) { LWDEBUGF(2, "Entered varint_u64_encode_buf, value %lu", val); - return _varint_u64_encode_buf(val, buf); + _varint_u64_encode_buf(val, buf); + return 0; } diff --git a/liblwgeom/varint.h b/liblwgeom/varint.h index db363e2c1..36914c8a5 100644 --- a/liblwgeom/varint.h +++ b/liblwgeom/varint.h @@ -25,24 +25,24 @@ unsigned varint_u32_encoded_size(uint32_t val); /* Encode unsigned 32bit integer */ -uint8_t* varint_u32_encode_buf(uint32_t val, uint8_t *buf); +int varint_u32_encode_buf(uint32_t val, uint8_t **buf); /* Find encoded size for signed 32bit integer */ unsigned varint_s32_encoded_size(int32_t val); /* Encode signed 32bit integer */ -uint8_t* varint_s32_encode_buf(int32_t val, uint8_t *buf); +int varint_s32_encode_buf(int32_t val, uint8_t **buf); /* Find encoded size for unsigned 64bit integer */ unsigned varint_u64_encoded_size(uint64_t val); /* Encode unsigned 64bit integer */ -uint8_t* varint_u64_encode_buf(uint64_t val, uint8_t *buf); +int varint_u64_encode_buf(uint64_t val, uint8_t **buf); /* Find encoded size for signed 64bit integer */ unsigned varint_s64_encoded_size(int64_t val); /* Encode unsigned 64bit integer */ -uint8_t* varint_s64_encode_buf(int64_t val, uint8_t *buf); +int varint_s64_encode_buf(int64_t val, uint8_t **buf); #endif /* !defined _LIBLWGEOM_VARINT_H */ \ No newline at end of file diff --git a/postgis/lwgeom_accum.c b/postgis/lwgeom_accum.c index b66542c76..427c16c9d 100644 --- a/postgis/lwgeom_accum.c +++ b/postgis/lwgeom_accum.c @@ -82,7 +82,6 @@ typedef struct int n_rows; int max_rows; geom_id *geoms; - int method; } twkb_state; @@ -192,11 +191,7 @@ if (!AggCheckCallContext(fcinfo, &aggcontext)) state->n_rows = 0; /* If user specified precision, respect it */ - state->precision = PG_ARGISNULL(2) ? (int) 0 : PG_GETARG_INT32(2); - - /* There is no input for user to choose encoding method, but it is still defined here if we need it again */ - state->method = 1; - + state->precision = PG_ARGISNULL(2) ? (int) 0 : PG_GETARG_INT32(2); } else { @@ -228,6 +223,19 @@ if (!AggCheckCallContext(fcinfo, &aggcontext)) variant = variant & ~TWKB_ID; ((state->geoms)+state->n_rows)->id = 0; } + + /* If user wants registered twkb sizes */ + if ( (PG_NARGS()>4) && (!PG_ARGISNULL(4)) && PG_GETARG_BOOL(4) ) + variant = variant | (TWKB_SIZES); + else + variant = variant & ~TWKB_SIZES; + + /* If user wants bounding boxes */ + if ( (PG_NARGS()>5) && (!PG_ARGISNULL(5)) && PG_GETARG_BOOL(5) ) + variant = variant | (TWKB_BBOXES); + else + variant = variant & ~TWKB_BBOXES; + state->variant=variant; (state->n_rows)++; } @@ -416,7 +424,7 @@ pgis_twkb_accum_finalfn(PG_FUNCTION_ARGS) } } - twkb = lwgeom_agg_to_twkb(&lwgeom_arrays, state->variant , &twkb_size,(int8_t) state->precision,state->method); + twkb = lwgeom_agg_to_twkb(&lwgeom_arrays, state->variant , &twkb_size,(int8_t) state->precision); /* Clean up and return */ diff --git a/postgis/lwgeom_inout.c b/postgis/lwgeom_inout.c index be46b7d21..6bf84f906 100644 --- a/postgis/lwgeom_inout.c +++ b/postgis/lwgeom_inout.c @@ -413,7 +413,7 @@ Datum TWKBFromLWGEOM(PG_FUNCTION_ARGS) uint8_t variant = 0; bytea *result; int64_t id; - int prec,method; + int prec; /* If user specified precision, respect it */ if ( (PG_NARGS()>1) && (!PG_ARGISNULL(1)) ) @@ -435,20 +435,24 @@ Datum TWKBFromLWGEOM(PG_FUNCTION_ARGS) { variant = variant & ~TWKB_ID; id=0; - } + } + + /* If user wants registered twkb sizes */ + if ( (PG_NARGS()>3) && (!PG_ARGISNULL(3)) && PG_GETARG_BOOL(3) ) + variant = variant | (TWKB_SIZES); + else + variant = variant & ~TWKB_SIZES; + + /* If user wants bounding boxes */ + if ( (PG_NARGS()>4) && (!PG_ARGISNULL(4)) && PG_GETARG_BOOL(4) ) + variant = variant | (TWKB_BBOXES); + else + variant = variant & ~TWKB_BBOXES; - /* If user specified method, respect it - This will probably be taken away when we can decide which compression method that is best */ - if ( (PG_NARGS()>4) && (!PG_ARGISNULL(4)) ) - { - method = PG_GETARG_INT32(4); - } - else - method=1; /* Create TWKB bin string */ lwgeom = lwgeom_from_gserialized(geom); - twkb = lwgeom_to_twkb(lwgeom, variant , &twkb_size,(int8_t) prec,(int64_t) id,method); + twkb = lwgeom_to_twkb(lwgeom, variant , &twkb_size,(int8_t) prec,(int64_t) id); lwgeom_free(lwgeom); /* Prepare the PgSQL text return type */ diff --git a/postgis/postgis.sql.in b/postgis/postgis.sql.in index 7de642875..0811c6e9a 100644 --- a/postgis/postgis.sql.in +++ b/postgis/postgis.sql.in @@ -1399,6 +1399,12 @@ CREATE OR REPLACE FUNCTION ST_AsTWKB(geometry,int4,int8) AS 'MODULE_PATHNAME','TWKBFromLWGEOM' LANGUAGE 'c' IMMUTABLE STRICT; +-- Availability: 2.2.0 +CREATE OR REPLACE FUNCTION ST_AsTWKB(geometry,int4,int8,boolean,boolean default false) + RETURNS bytea + AS 'MODULE_PATHNAME','TWKBFromLWGEOM' + LANGUAGE 'c' IMMUTABLE STRICT; + -- Availability: 1.2.2 CREATE OR REPLACE FUNCTION ST_AsEWKB(geometry) RETURNS BYTEA @@ -3387,6 +3393,12 @@ CREATE OR REPLACE FUNCTION pgis_twkb_accum_transfn(internal, geometry,int,int8) AS 'MODULE_PATHNAME' LANGUAGE c ; +-- Availability: 2.2.0 +CREATE OR REPLACE FUNCTION pgis_twkb_accum_transfn(internal, geometry,int,int8,boolean) + RETURNS internal + AS 'MODULE_PATHNAME' + LANGUAGE c ; + -- Availability: 2.2.0 CREATE OR REPLACE FUNCTION pgis_twkb_accum_finalfn(internal) RETURNS bytea @@ -3407,6 +3419,13 @@ CREATE AGGREGATE st_astwkbagg(geometry,int,int8) ( FINALFUNC=pgis_twkb_accum_finalfn ); +-- Availability: 2.2.0 +CREATE AGGREGATE st_astwkbagg(geometry,int,int8,boolean) ( + SFUNC=pgis_twkb_accum_transfn, + STYPE=internal, + FINALFUNC=pgis_twkb_accum_finalfn +); + -- Availability: 1.2.2 CREATE AGGREGATE ST_Accum ( sfunc = pgis_geometry_accum_transfn, diff --git a/regress/twkb_expected b/regress/twkb_expected index e641f94e1..4d3c903f1 100644 --- a/regress/twkb_expected +++ b/regress/twkb_expected @@ -1,17 +1,17 @@ -POINT(1 1)|02410202 -POINT(1 1)|0341020202 -POINT(78 -78)|0341139c019b01 -POINT(123.456789 987.654321)|2241f4c0019a870c -LINESTRING(120 10, -50 20, 300 -2)|0342d80403f00114d30214bc052b -LINESTRING(120 10, -50 20, 300 -2)|2342d80403c0bb01d00fcf8902d00ff0a204af22 -LINESTRING(120.54 10.78, -50.2 20.878, 300.789 -21)|0342d80403f20116d50214be0553 -POLYGON((1 1, 1 2, 2 2, 2 1, 1 1))|034302010502020002020000010100 -POLYGON((1 1, 1 20, 20 20, 20 1, 1 1),(3 3,3 4, 4 4,4 3,3 3))|0343020205020200262600002525000504040002020000010100 -MULTIPOINT((1 1),(2 2))|02440202020202 -MULTILINESTRING((1 1,1 2,2 2),(3 3,3 4,4 4))|0245020302020002020003020200020200 -MULTIPOLYGON(((1 1, 1 2, 2 2, 2 1, 1 1)),((3 3,3 4,4 4,4 3,3 3)))|03460202010502020002020000010100010504040002020000010100 -MULTIPOLYGON(((1 1, 1 20, 20 20, 20 1, 1 1),(3 3,3 4, 4 4,4 3,3 3)),((-1 1, -1 20, -20 20, -20 1, -1 1),(-3 3,-3 4, -4 4,-4 3,-3 3)))|0346020202050202002626000025250005040400020200000101000205070300262500002526000503040002010000010200 -GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(2 2,3 3))|024702410202420202020202 -GEOMETRYCOLLECTION(MULTIPOINT(1 1,2 2),POINT(78 -78),POLYGON((1 1,1 2,2 2,2 1,1 1)))|0247034402020202024198019f0143010599019e010002020000010100 -MULTIPOINT(1 1,2 2)|035502060202040202 -GEOMETRYCOLLECTION(MULTIPOINT(1 1,2 2),POINT(78 -78),POLYGON((1 1,1 2,2 2,2 1,1 1)))|0387035501c8439c019b015701bd08010599019e01000202000001010058010602410000410202 +POINT(1 1)|00410202 +POINT(1 1)|0141020202 +POINT(78 -78)|0141139c019b01 +POINT(123.456789 987.654321)|2041f4c0019a870c +LINESTRING(120 10, -50 20, 300 -2)|0142d80403f00114d30214bc052b +LINESTRING(120 10, -50 20, 300 -2)|2142d80403c0bb01d00fcf8902d00ff0a204af22 +LINESTRING(120.54 10.78, -50.2 20.878, 300.789 -21)|0142d80403f20116d50214be0553 +POLYGON((1 1, 1 2, 2 2, 2 1, 1 1))|014302010502020002020000010100 +POLYGON((1 1, 1 20, 20 20, 20 1, 1 1),(3 3,3 4, 4 4,4 3,3 3))|0143020205020200262600002525000504040002020000010100 +MULTIPOINT((1 1),(2 2))|00440202020202 +MULTILINESTRING((1 1,1 2,2 2),(3 3,3 4,4 4))|0045020302020002020003020200020200 +MULTIPOLYGON(((1 1, 1 2, 2 2, 2 1, 1 1)),((3 3,3 4,4 4,4 3,3 3)))|01460202010502020002020000010100010504040002020000010100 +MULTIPOLYGON(((1 1, 1 20, 20 20, 20 1, 1 1),(3 3,3 4, 4 4,4 3,3 3)),((-1 1, -1 20, -20 20, -20 1, -1 1),(-3 3,-3 4, -4 4,-4 3,-3 3)))|0146020202050202002626000025250005040400020200000101000205070300262500002526000503040002010000010200 +GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(2 2,3 3))|004702410202420202020202 +GEOMETRYCOLLECTION(MULTIPOINT(1 1,2 2),POINT(78 -78),POLYGON((1 1,1 2,2 2,2 1,1 1)))|0047034402020202024198019f0143010599019e010002020000010100 +MULTIPOINT(1 1,2 2)|015502060202040202 +GEOMETRYCOLLECTION(MULTIPOINT(1 1,2 2),POINT(78 -78),POLYGON((1 1,1 2,2 2,2 1,1 1)))|0187035501c8439c019b015701bd08010599019e01000202000001010058010602410000410202