From 38944e72dfeaff3595d78033eb2d0cb25aa5e5ad Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Fri, 15 May 2015 13:35:56 +0200 Subject: [PATCH] Implement PC_Patch{Min,Max,Avg}(PcPatch) returns PcPoint Closes #77 NOTE: changes the C function signature so you need to properly upgrade scripts for things to work again. --- NEWS | 1 + README.md | 27 ++++++++++++++++ pgsql/expected/pointcloud.out | 19 +++++++++++ pgsql/pc_access.c | 61 +++++++++++++++++++++++------------ pgsql/pointcloud.sql.in | 37 ++++++++++++++++++--- pgsql/sql/pointcloud.sql | 6 ++++ 6 files changed, 126 insertions(+), 25 deletions(-) diff --git a/NEWS b/NEWS index 8d3e19b..ccbba77 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ - PC_PCId(pcpoint|pcpatch) - PC_Get(pcpoint) returns float8[] - PC_Summary(pcpatch) + - PC_Patch{Min,Max,Avg}(pcpatch) returns pcpoint (#77) - Enhancements - Support sigbits encoding for 64bit integers (#61) - Warn about truncated values (#68) diff --git a/README.md b/README.md index 6224037..5c6df95 100644 --- a/README.md +++ b/README.md @@ -380,6 +380,33 @@ Now that you have created two tables, you'll see entries for them in the `pointc > > 45.5 +**PC_PatchAvg(p pcpatch,)** returns **pcpoint** (from 1.1.0) + +> Returns a PcPoint with the *average* values of each dimension in the patch. +> +> SELECT PC_AsText(PC_PatchAvg(pa)) +> FROM patches WHERE id = 7; +> +> {"pcid":1,"pt":[-126.46,45.54,54.5,5]} + +**PC_PatchMax(p pcpatch)** returns **pcpoint** (from 1.1.0) + +> Returns a PcPoint with the *maximum* values of each dimension in the patch. +> +> SELECT PC_PatchMax(pa) +> FROM patches WHERE id = 7; +> +> {"pcid":1,"pt":[-126.41,45.59,59,5]} + +**PC_PatchMin(p pcpatch)** returns **pcpoint** (from 1.1.0) + +> Returns a PcPoint with the *minimum* values of each dimension in the patch. +> +> SELECT PC_PatchMin(pa) +> FROM patches WHERE id = 7; +> +> {"pcid":1,"pt":[-126.5,45.5,50,5]} + **PC_FilterGreaterThan(p pcpatch, dimname text, float8 value)** returns **pcpatch** > Returns a patch with only points whose values are greater than the supplied value diff --git a/pgsql/expected/pointcloud.out b/pgsql/expected/pointcloud.out index a28ad36..bd0a06c 100644 --- a/pgsql/expected/pointcloud.out +++ b/pgsql/expected/pointcloud.out @@ -391,6 +391,25 @@ SELECT Min(PC_PatchMin(pa,'z')) FROM pa_test_dim; 1 (1 row) +-- https://github.com/pgpointcloud/pointcloud/issues/77 +SELECT PC_Get(PC_PatchMax(pa)) FROM pa_test_dim order by 1 limit 1; + pc_get +------------------------ + {-123.01,48.99,399,39} +(1 row) + +SELECT PC_Get(PC_PatchMin(pa)) FROM pa_test_dim order by 1 limit 1; + pc_get +--------------------- + {-126.99,45.01,1,0} +(1 row) + +SELECT PC_Get(PC_PatchAvg(pa)) FROM pa_test_dim order by 1 limit 1; + pc_get +------------------ + {-125,47,200,20} +(1 row) + SELECT PC_Summary(pa) summary FROM pa_test_dim order by 1 limit 1; summary ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/pgsql/pc_access.c b/pgsql/pc_access.c index 4be40d9..b9ea76e 100644 --- a/pgsql/pc_access.c +++ b/pgsql/pc_access.c @@ -819,6 +819,9 @@ Datum pc_version(PG_FUNCTION_ARGS) * PC_PatchMax(patch pcpatch, dimname text) returns Numeric * PC_PatchMin(patch pcpatch, dimname text) returns Numeric * PC_PatchAvg(patch pcpatch, dimname text) returns Numeric +* PC_PatchMax(patch pcpatch) returns PcPoint +* PC_PatchMin(patch pcpatch) returns PcPoint +* PC_PatchAvg(patch pcpatch) returns PcPoint */ PG_FUNCTION_INFO_V1(pcpatch_get_stat); Datum pcpatch_get_stat(PG_FUNCTION_ARGS) @@ -826,11 +829,19 @@ Datum pcpatch_get_stat(PG_FUNCTION_ARGS) static int stats_size_guess = 400; SERIALIZED_PATCH *serpa = PG_GETHEADERX_SERPATCH_P(0, stats_size_guess); PCSCHEMA *schema = pc_schema_from_pcid(serpa->pcid, fcinfo); - char *dim_str = text_to_cstring(PG_GETARG_TEXT_P(1)); - char *stat_str = text_to_cstring(PG_GETARG_TEXT_P(2)); + int32 statno = PG_GETARG_INT32(1); + char *dim_str = 0; PCSTATS *stats; + const PCPOINT *pt; + SERIALIZED_POINT *serpt = NULL; float8 double_result; - int rv = 0; + int rv = 1; + + + if ( PG_NARGS() > 2 ) { + /* TODO: only get small slice ? */ + dim_str = text_to_cstring(PG_GETARG_TEXT_P(2)); + } if ( stats_size_guess < pc_stats_size(schema) ) { @@ -842,30 +853,40 @@ Datum pcpatch_get_stat(PG_FUNCTION_ARGS) if ( ! stats ) PG_RETURN_NULL(); - /* Max */ - if ( 0 == strcasecmp("max", stat_str) ) - rv = pc_point_get_double_by_name(&(stats->max), dim_str, &double_result); /* Min */ - else if ( 0 == strcasecmp("min", stat_str) ) - rv = pc_point_get_double_by_name(&(stats->min), dim_str, &double_result); + if ( 0 == statno ) + pt = &(stats->min); + /* Max */ + else if ( 1 == statno ) + pt = &(stats->max); /* Avg */ - else if ( 0 == strcasecmp("avg", stat_str) ) - rv = pc_point_get_double_by_name(&(stats->avg), dim_str, &double_result); + else if ( 2 == statno ) + pt = &(stats->avg); /* Unsupported */ else - elog(ERROR, "stat type \"%s\" is not supported", stat_str); + elog(ERROR, "stat number \"%d\" is not supported", statno); - pfree(stat_str); - pc_stats_free(stats); - - if ( ! rv ) - elog(ERROR, "dimension \"%s\" does not exist in schema", dim_str); - - pfree(dim_str); - PG_RETURN_DATUM(DirectFunctionCall1(float8_numeric, Float8GetDatum(double_result))); + /* empty dim string means we want the whole point */ + if ( ! dim_str ) + { + serpt = pc_point_serialize(pt); + pc_stats_free(stats); + PG_RETURN_POINTER(serpt); + } + else + { + rv = pc_point_get_double_by_name(pt, dim_str, &double_result); + pc_stats_free(stats); + if ( ! rv ) + { + elog(ERROR, "dimension \"%s\" does not exist in schema", dim_str); + PG_RETURN_NULL(); + } + pfree(dim_str); + PG_RETURN_DATUM(DirectFunctionCall1(float8_numeric, Float8GetDatum(double_result))); + } } - /** * PC_FilterLessThan(patch pcpatch, dimname text, value) returns PcPatch * PC_FilterGreaterThan(patch pcpatch, dimname text, value) returns PcPatch diff --git a/pgsql/pointcloud.sql.in b/pgsql/pointcloud.sql.in index 46bf6d1..50fa49c 100644 --- a/pgsql/pointcloud.sql.in +++ b/pgsql/pointcloud.sql.in @@ -176,17 +176,44 @@ CREATE OR REPLACE FUNCTION PC_PCId(p pcpoint) RETURNS int4 AS 'MODULE_PATHNAME', 'pcpoint_pcid' LANGUAGE 'c' IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION PC_PatchMax(p pcpatch, attr text, stat text default 'max') +-- Availability: 1.1.0 +-- @param statno 0:min 1:max 2:avg +CREATE OR REPLACE FUNCTION _PC_PatchStat(p pcpatch, statno int) + RETURNS pcpoint AS 'MODULE_PATHNAME', 'pcpatch_get_stat' + LANGUAGE 'c' IMMUTABLE STRICT; + +-- Availability: 1.1.0 +CREATE OR REPLACE FUNCTION PC_PatchMin(p pcpatch) + RETURNS pcpoint AS $$ SELECT _PC_PatchStat(p, 0) $$ + LANGUAGE 'sql' IMMUTABLE STRICT; + +-- Availability: 1.1.0 +CREATE OR REPLACE FUNCTION PC_PatchMax(p pcpatch) + RETURNS pcpoint AS $$ SELECT _PC_PatchStat(p, 1) $$ + LANGUAGE 'sql' IMMUTABLE STRICT; + +-- Availability: 1.1.0 +CREATE OR REPLACE FUNCTION PC_PatchAvg(p pcpatch) + RETURNS pcpoint AS $$ SELECT _PC_PatchStat(p, 2) $$ + LANGUAGE 'sql' IMMUTABLE STRICT; + +-- Availability: 1.1.0 +-- @param statno 0:min 1:max 2:avg +CREATE OR REPLACE FUNCTION _PC_PatchStat(p pcpatch, statno int, attr text) RETURNS numeric AS 'MODULE_PATHNAME', 'pcpatch_get_stat' LANGUAGE 'c' IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION PC_PatchMin(p pcpatch, attr text, stat text default 'min') - RETURNS numeric AS 'MODULE_PATHNAME', 'pcpatch_get_stat' - LANGUAGE 'c' IMMUTABLE STRICT; + RETURNS numeric AS $$ SELECT _PC_PatchStat(p, 0, attr) $$ + LANGUAGE 'sql' IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION PC_PatchMax(p pcpatch, attr text, stat text default 'max') + RETURNS numeric AS $$ SELECT _PC_PatchStat(p, 1, attr) $$ + LANGUAGE 'sql' IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION PC_PatchAvg(p pcpatch, attr text, stat text default 'avg') - RETURNS numeric AS 'MODULE_PATHNAME', 'pcpatch_get_stat' - LANGUAGE 'c' IMMUTABLE STRICT; + RETURNS numeric AS $$ SELECT _PC_PatchStat(p, 2, attr) $$ + LANGUAGE 'sql' IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION PC_FilterLessThan(p pcpatch, attr text, v1 float8 default 0.0, v2 float8 default 0.0, mode int4 default 0) RETURNS pcpatch AS 'MODULE_PATHNAME', 'pcpatch_filter' diff --git a/pgsql/sql/pointcloud.sql b/pgsql/sql/pointcloud.sql index a9ce066..0d295f5 100644 --- a/pgsql/sql/pointcloud.sql +++ b/pgsql/sql/pointcloud.sql @@ -267,6 +267,12 @@ SELECT Max(PC_PatchMax(pa,'x')) FROM pa_test_dim; SELECT Min(PC_PatchMin(pa,'x')) FROM pa_test_dim; SELECT Min(PC_PatchMin(pa,'z')) FROM pa_test_dim; +-- https://github.com/pgpointcloud/pointcloud/issues/77 +SELECT PC_Get(PC_PatchMax(pa)) FROM pa_test_dim order by 1 limit 1; +SELECT PC_Get(PC_PatchMin(pa)) FROM pa_test_dim order by 1 limit 1; +SELECT PC_Get(PC_PatchAvg(pa)) FROM pa_test_dim order by 1 limit 1; + + SELECT PC_Summary(pa) summary FROM pa_test_dim order by 1 limit 1;