diff --git a/lib/pc_api.h b/lib/pc_api.h index 5474c2b..4e7c3c1 100644 --- a/lib/pc_api.h +++ b/lib/pc_api.h @@ -320,6 +320,9 @@ void pc_patch_free(PCPATCH *patch); /** Create a compressed copy, using the compression schema referenced in the PCSCHEMA */ PCPATCH* pc_patch_compress(const PCPATCH *patch, void *userdata); +/** Create an uncompressed copy */ +PCPATCH * pc_patch_uncompress(const PCPATCH *patch); + /** Create a new readwrite PCPOINT from a byte array */ PCPATCH* pc_patch_from_wkb(const PCSCHEMA *s, uint8_t *wkb, size_t wkbsize); diff --git a/lib/pc_patch.c b/lib/pc_patch.c index 2e5a1c3..f7151e3 100644 --- a/lib/pc_patch.c +++ b/lib/pc_patch.c @@ -126,6 +126,33 @@ pc_patch_compress(const PCPATCH *patch, void *userdata) } +PCPATCH * +pc_patch_uncompress(const PCPATCH *patch) +{ + uint32_t patch_compression = patch->type; + + if ( patch_compression == PC_DIMENSIONAL ) + { + PCPATCH_UNCOMPRESSED *pu = pc_patch_uncompressed_from_dimensional((PCPATCH_DIMENSIONAL*)patch); + return (PCPATCH*)pu; + } + + if ( patch_compression == PC_NONE ) + { + return (PCPATCH*)patch; + } + + if ( patch_compression == PC_GHT ) + { + pcerror("pc_patch_uncompress: GHT compression not yet supported"); + return NULL; + } + + return NULL; +} + + + PCPATCH * pc_patch_from_wkb(const PCSCHEMA *s, uint8_t *wkb, size_t wkbsize) { diff --git a/pgsql/expected/pointcloud.out b/pgsql/expected/pointcloud.out index cdc7d3c..4d857a7 100644 --- a/pgsql/expected/pointcloud.out +++ b/pgsql/expected/pointcloud.out @@ -100,6 +100,11 @@ INSERT INTO pa_test (pa) VALUES ('0000000002000000000000000200000002000000030000 ERROR: no entry in "pointcloud_formats" for pcid = 2 LINE 1: INSERT INTO pa_test (pa) VALUES ('00000000020000000000000002... ^ +SELECT PC_Uncompress(pa) FROM pa_test LIMIT 1; + pc_uncompress +--------------- +(0 rows) + INSERT INTO pa_test (pa) VALUES ('0000000001000000000000000200000002000000030000000500060000000200000003000000050008'); INSERT INTO pa_test (pa) VALUES ('000000000100000000000000020000000600000007000000050006000000090000000A00000005000A'); INSERT INTO pa_test (pa) VALUES ('000000000100000000000000020000000600000007000000050006000000090000000A00000005000A'); @@ -142,6 +147,18 @@ SELECT PC_AsText(PC_Union(pa)) FROM pa_test; {"pcid":1,"pts":[[0.02,0.03,0.05,6],[0.02,0.03,0.05,8],[0.06,0.07,0.05,6],[0.09,0.1,0.05,10],[0.06,0.07,0.05,6],[0.09,0.1,0.05,10],[0.06,0.07,0.05,6],[0.09,0.1,0.05,10]]} (1 row) +SELECT sum(PC_NumPoints(pa)) FROM pa_test ; + sum +----- + 8 +(1 row) + +SELECT sum(PC_NumPoints(pa)) FROM pa_test ; + sum +----- + 8 +(1 row) + --DROP TABLE pts_collection; --DROP TABLE pt_test; --DROP TABLE pa_test; diff --git a/pgsql/pc_access.c b/pgsql/pc_access.c index f2ea1e5..66d23c2 100644 --- a/pgsql/pc_access.c +++ b/pgsql/pc_access.c @@ -11,10 +11,12 @@ #include "utils/numeric.h" #include "funcapi.h" -/* Other SQL functions */ +/* General SQL functions */ Datum pcpoint_get_value(PG_FUNCTION_ARGS); Datum pcpatch_from_pcpoint_array(PG_FUNCTION_ARGS); Datum pcpatch_from_pcpatch_array(PG_FUNCTION_ARGS); +Datum pcpatch_uncompress(PG_FUNCTION_ARGS); +Datum pcpatch_numpoints(PG_FUNCTION_ARGS); /* Generic aggregation functions */ Datum pointcloud_agg_transfn(PG_FUNCTION_ARGS); @@ -508,4 +510,21 @@ Datum pcpatch_unnest(PG_FUNCTION_ARGS) } } +PG_FUNCTION_INFO_V1(pcpatch_uncompress); +Datum pcpatch_uncompress(PG_FUNCTION_ARGS) +{ + SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); + PCSCHEMA *schema = pc_schema_from_pcid(serpa->pcid, fcinfo); + PCPATCH *patch = pc_patch_deserialize(serpa, schema); + SERIALIZED_PATCH *serpa_out = pc_patch_serialize_uncompressed(patch); + pc_patch_free(patch); + PG_RETURN_POINTER(serpa_out); +} + +PG_FUNCTION_INFO_V1(pcpatch_numpoints); +Datum pcpatch_numpoints(PG_FUNCTION_ARGS) +{ + SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); + PG_RETURN_INT32(serpa->npoints); +} diff --git a/pgsql/pc_pgsql.c b/pgsql/pc_pgsql.c index 31eb397..25b1980 100644 --- a/pgsql/pc_pgsql.c +++ b/pgsql/pc_pgsql.c @@ -562,6 +562,30 @@ pc_patch_serialize(const PCPATCH *patch_in, void *userdata) } +/** +* Convert struct to byte array. +* Userdata is currently only PCDIMSTATS, hopefully updated across +* a number of iterations and saved. +*/ +SERIALIZED_PATCH * +pc_patch_serialize_uncompressed(const PCPATCH *patch_in) +{ + PCPATCH *patch = (PCPATCH*)patch_in; + SERIALIZED_PATCH *serpatch; + + /* Convert the patch to uncompressed, if necessary */ + if ( patch->type != PC_NONE ) + { + patch = pc_patch_uncompress(patch_in); + } + + serpatch = pc_patch_uncompressed_serialize(patch); + + if ( patch != patch_in ) + pc_patch_free(patch); + + return serpatch; +} static PCPATCH * pc_patch_uncompressed_deserialize(const SERIALIZED_PATCH *serpatch, const PCSCHEMA *schema) diff --git a/pgsql/pc_pgsql.h b/pgsql/pc_pgsql.h index d4395d4..893ae1a 100644 --- a/pgsql/pc_pgsql.h +++ b/pgsql/pc_pgsql.h @@ -92,6 +92,9 @@ size_t pc_patch_serialized_size(const PCPATCH *patch); /** Turn a PCPATCH into a byte buffer suitable for saving in PgSQL */ SERIALIZED_PATCH* pc_patch_serialize(const PCPATCH *patch, void *userdata); +/** Turn a PCPATCH into an uncompressed byte buffer */ +SERIALIZED_PATCH* pc_patch_serialize_uncompressed(const PCPATCH *patch); + /** Turn a byte buffer into a PCPATCH for processing */ PCPATCH* pc_patch_deserialize(const SERIALIZED_PATCH *serpatch, const PCSCHEMA *schema); diff --git a/pgsql/pointcloud--1.0.sql b/pgsql/pointcloud--1.0.sql index e385dc8..99a00b2 100644 --- a/pgsql/pointcloud--1.0.sql +++ b/pgsql/pointcloud--1.0.sql @@ -122,6 +122,13 @@ CREATE OR REPLACE FUNCTION PC_Envelope(p pcpatch) RETURNS bytea AS 'MODULE_PATHNAME', 'pcpatch_bytea_envelope' LANGUAGE 'c' IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION PC_Uncompress(p pcpatch) + RETURNS pcpatch AS 'MODULE_PATHNAME', 'pcpatch_uncompress' + LANGUAGE 'c' IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION PC_NumPoints(p pcpatch) + RETURNS int4 AS 'MODULE_PATHNAME', 'pcpatch_numpoints' + LANGUAGE 'c' IMMUTABLE STRICT; ------------------------------------------------------------------- -- POINTCLOUD_COLUMNS diff --git a/pgsql/sql/pointcloud.sql b/pgsql/sql/pointcloud.sql index 6be4d6a..50ec349 100644 --- a/pgsql/sql/pointcloud.sql +++ b/pgsql/sql/pointcloud.sql @@ -72,6 +72,7 @@ CREATE TABLE IF NOT EXISTS pa_test ( DELETE FROM pa_test; INSERT INTO pa_test (pa) VALUES ('0000000002000000000000000200000002000000030000000500060000000200000003000000050008'); +SELECT PC_Uncompress(pa) FROM pa_test LIMIT 1; INSERT INTO pa_test (pa) VALUES ('0000000001000000000000000200000002000000030000000500060000000200000003000000050008'); INSERT INTO pa_test (pa) VALUES ('000000000100000000000000020000000600000007000000050006000000090000000A00000005000A'); INSERT INTO pa_test (pa) VALUES ('000000000100000000000000020000000600000007000000050006000000090000000A00000005000A'); @@ -86,6 +87,9 @@ SELECT PC_AsText(PC_Explode(PC_Patch(pt))) FROM pt_test; SELECT PC_AsText(PC_Union(pa)) FROM pa_test; +SELECT sum(PC_NumPoints(pa)) FROM pa_test ; +SELECT sum(PC_NumPoints(pa)) FROM pa_test ; + --DROP TABLE pts_collection; --DROP TABLE pt_test; --DROP TABLE pa_test;