mirror of
https://github.com/pgpointcloud/pointcloud.git
synced 2025-12-08 20:36:04 +00:00
Finish implementation of patch-level stats
This commit is contained in:
parent
89611f6101
commit
8174fa4ca3
@ -111,11 +111,19 @@ test_patch_hex_in()
|
||||
uint8_t *wkb = bytes_from_hexbytes(hexbuf, hexsize);
|
||||
PCPATCH *pa = pc_patch_from_wkb(simpleschema, wkb, hexsize/2);
|
||||
PCPOINTLIST *pl = pc_pointlist_from_patch(pa);
|
||||
|
||||
pc_point_get_double_by_name(pc_pointlist_get_point(pl, 0), "X", &d);
|
||||
CU_ASSERT_DOUBLE_EQUAL(d, 0.02, 0.000001);
|
||||
pc_point_get_double_by_name(pc_pointlist_get_point(pl, 1), "Intensity", &d);
|
||||
CU_ASSERT_DOUBLE_EQUAL(d, 8, 0.000001);
|
||||
|
||||
pc_point_get_double_by_name(&(pa->stats->min), "Intensity", &d);
|
||||
CU_ASSERT_DOUBLE_EQUAL(d, 6, 0.000001);
|
||||
pc_point_get_double_by_name(&(pa->stats->max), "Intensity", &d);
|
||||
CU_ASSERT_DOUBLE_EQUAL(d, 8, 0.000001);
|
||||
pc_point_get_double_by_name(&(pa->stats->avg), "Intensity", &d);
|
||||
CU_ASSERT_DOUBLE_EQUAL(d, 7, 0.000001);
|
||||
|
||||
str = pc_patch_to_string(pa);
|
||||
CU_ASSERT_STRING_EQUAL(str, "{\"pcid\":0,\"pts\":[[0.02,0.03,0.05,6],[0.02,0.03,0.05,8]]}");
|
||||
// printf("\n%s\n",str);
|
||||
|
||||
@ -142,8 +142,8 @@ typedef struct
|
||||
/* Used for generic patch statistics */
|
||||
typedef struct
|
||||
{
|
||||
PCPOINT max;
|
||||
PCPOINT min;
|
||||
PCPOINT max;
|
||||
PCPOINT avg;
|
||||
}
|
||||
PCSTATS;
|
||||
@ -263,6 +263,8 @@ PCSCHEMA* pc_schema_clone(const PCSCHEMA *s);
|
||||
void pc_schema_set_dimension(PCSCHEMA *s, PCDIMENSION *d);
|
||||
/** Check/set the x/y position in the dimension list */
|
||||
void pc_schema_check_xy(PCSCHEMA *s);
|
||||
/** Get the width in bytes of a single point in the schema */
|
||||
size_t pc_schema_get_size(const PCSCHEMA *s);
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
@ -376,7 +378,10 @@ int pc_bytes_serialize(const PCBYTES *pcb, uint8_t *buf, size_t *size);
|
||||
int pc_bytes_deserialize(const uint8_t *buf, const PCDIMENSION *dim, PCBYTES *pcb, int readonly, int flip_endian);
|
||||
|
||||
/** Wrap serialized stats in a new stats objects */
|
||||
PCSTATS* pc_stats_new_from_data(const PCSCHEMA *schema, const uint8_t *mindata, const uint8_t *maxdata, const uint8_t *avgdata);\
|
||||
PCSTATS* pc_stats_new_from_data(const PCSCHEMA *schema, const uint8_t *mindata, const uint8_t *maxdata, const uint8_t *avgdata);
|
||||
|
||||
/** Free a stats object */
|
||||
void pc_stats_free(PCSTATS *stats);
|
||||
|
||||
/** Calculate stats from an existing patch */
|
||||
int pc_patch_compute_stats(PCPATCH *patch);
|
||||
|
||||
@ -599,3 +599,9 @@ pc_schema_get_dimension_by_name(const PCSCHEMA *s, const char *name)
|
||||
return hashtable_search(s->namehash, name);
|
||||
}
|
||||
|
||||
size_t
|
||||
pc_schema_get_size(const PCSCHEMA *s)
|
||||
{
|
||||
return s->size;
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ CREATE EXTENSION pointcloud;
|
||||
SELECT PC_Version();
|
||||
pc_version
|
||||
------------
|
||||
1.0
|
||||
0.1
|
||||
(1 row)
|
||||
|
||||
INSERT INTO pointcloud_formats (pcid, srid, schema)
|
||||
@ -272,7 +272,7 @@ SELECT Sum(PC_NumPoints(pa)) FROM pa_test_dim;
|
||||
SELECT Sum(PC_MemSize(pa)) FROM pa_test_dim;
|
||||
sum
|
||||
-----
|
||||
516
|
||||
684
|
||||
(1 row)
|
||||
|
||||
SELECT Sum(PC_PatchMax(pa,'x')) FROM pa_test_dim;
|
||||
@ -308,7 +308,7 @@ SELECT Sum(PC_NumPoints(pa)) FROM pa_test_dim;
|
||||
SELECT Sum(PC_MemSize(pa)) FROM pa_test_dim;
|
||||
sum
|
||||
------
|
||||
8523
|
||||
8733
|
||||
(1 row)
|
||||
|
||||
SELECT Max(PC_PatchMax(pa,'x')) FROM pa_test_dim;
|
||||
@ -351,7 +351,7 @@ SELECT Sum(PC_NumPoints(pa)) FROM pa_test_ght;
|
||||
SELECT Sum(PC_MemSize(pa)) FROM pa_test_ght;
|
||||
sum
|
||||
-----
|
||||
420
|
||||
588
|
||||
(1 row)
|
||||
|
||||
SELECT Sum(PC_PatchMax(pa,'x')) FROM pa_test_ght;
|
||||
@ -387,7 +387,7 @@ SELECT Sum(PC_NumPoints(pa)) FROM pa_test_ght;
|
||||
SELECT Sum(PC_MemSize(pa)) FROM pa_test_ght;
|
||||
sum
|
||||
-------
|
||||
38471
|
||||
38681
|
||||
(1 row)
|
||||
|
||||
SELECT Max(PC_PatchMax(pa,'x')) FROM pa_test_ght;
|
||||
|
||||
@ -21,6 +21,7 @@ Datum pcpatch_uncompress(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_numpoints(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_compression(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_intersects(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_get_stat(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_size(PG_FUNCTION_ARGS);
|
||||
Datum pcpoint_size(PG_FUNCTION_ARGS);
|
||||
Datum pc_version(PG_FUNCTION_ARGS);
|
||||
@ -582,3 +583,53 @@ Datum pc_version(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_TEXT_P(version_text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a named dimension statistic from a PCPATCH
|
||||
* PC_PatchMax(patch pcpatch, dimname text) returns Numeric
|
||||
* PC_PatchMin(patch pcpatch, dimname text) returns Numeric
|
||||
* PC_PatchAvg(patch pcpatch, dimname text) returns Numeric
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(pcpatch_get_stat);
|
||||
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));
|
||||
PCSTATS *stats;
|
||||
float8 double_result;
|
||||
int rv;
|
||||
|
||||
if ( stats_size_guess < 3*schema->size )
|
||||
{
|
||||
serpa = PG_GETHEADERX_SERPATCH_P(0, 3*schema->size);
|
||||
}
|
||||
|
||||
stats = pc_patch_stats_deserialize(schema, serpa->data);
|
||||
|
||||
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);
|
||||
/* Avg */
|
||||
else if ( 0 == strcasecmp("avg", stat_str) )
|
||||
rv = pc_point_get_double_by_name(&(stats->avg), dim_str, &double_result);
|
||||
/* Unsupported */
|
||||
else
|
||||
elog(ERROR, "stat type \"%s\" is not supported", stat_str);
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
@ -471,24 +471,18 @@ pc_patch_serialized_size(const PCPATCH *patch)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint8_t *
|
||||
static size_t
|
||||
pc_patch_stats_serialize(uint8_t *buf, const PCSCHEMA *schema, const PCSTATS *stats)
|
||||
{
|
||||
size_t sz = schema->size;
|
||||
|
||||
/* Copy min */
|
||||
memcpy(buf, stats->min.data, sz);
|
||||
buf += sz;
|
||||
|
||||
/* Copy max */
|
||||
memcpy(buf, stats->max.data, sz);
|
||||
buf += sz;
|
||||
|
||||
memcpy(buf + sz, stats->max.data, sz);
|
||||
/* Copy avg */
|
||||
memcpy(buf, stats->avg.data, sz);
|
||||
buf += sz;
|
||||
|
||||
return buf;
|
||||
memcpy(buf + 2*sz, stats->avg.data, sz);
|
||||
|
||||
return sz*3;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -496,7 +490,7 @@ pc_patch_stats_serialize(uint8_t *buf, const PCSCHEMA *schema, const PCSTATS *st
|
||||
* min, max, avg. Their size is the uncompressed buffer size for
|
||||
* a point, the schema->size.
|
||||
*/
|
||||
static PCSTATS *
|
||||
PCSTATS *
|
||||
pc_patch_stats_deserialize(const PCSCHEMA *schema, const uint8_t *buf)
|
||||
{
|
||||
size_t sz = schema->size;
|
||||
@ -540,7 +534,7 @@ pc_patch_dimensional_serialize(const PCPATCH *patch_in)
|
||||
/* Write stats into the buffer */
|
||||
if ( patch->stats )
|
||||
{
|
||||
buf = pc_patch_stats_serialize(buf, patch->schema, patch->stats);
|
||||
buf += pc_patch_stats_serialize(buf, patch->schema, patch->stats);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -592,7 +586,7 @@ pc_patch_ght_serialize(const PCPATCH *patch_in)
|
||||
/* Write stats into the buffer first */
|
||||
if ( patch->stats )
|
||||
{
|
||||
buf = pc_patch_stats_serialize(buf, patch->schema, patch->stats);
|
||||
buf += pc_patch_stats_serialize(buf, patch->schema, patch->stats);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -638,7 +632,7 @@ pc_patch_uncompressed_serialize(const PCPATCH *patch_in)
|
||||
buf = serpch->data;
|
||||
if ( patch->stats )
|
||||
{
|
||||
buf = pc_patch_stats_serialize(buf, patch->schema, patch->stats);
|
||||
buf += pc_patch_stats_serialize(buf, patch->schema, patch->stats);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -753,18 +747,9 @@ pc_patch_uncompressed_deserialize(const SERIALIZED_PATCH *serpatch, const PCSCHE
|
||||
// }
|
||||
// SERIALIZED_PATCH;
|
||||
|
||||
PCPATCH_UNCOMPRESSED *patch;
|
||||
uint8_t *buf = (uint8_t*)serpatch->data;
|
||||
uint8_t *buf;
|
||||
size_t stats_size = 3*schema->size; // 3 pcpoints worth of stats
|
||||
|
||||
/* Reference the external data */
|
||||
patch = pcalloc(sizeof(PCPATCH_UNCOMPRESSED));
|
||||
/* Advance data pointer past the stats serialization */
|
||||
patch->data = buf + stats_size;
|
||||
/* Calculate the point data buffer size */
|
||||
patch->datasize = VARSIZE(serpatch) - sizeof(SERIALIZED_PATCH) + 1 - stats_size;
|
||||
/* Point into the stats area */
|
||||
patch->stats = pc_patch_stats_deserialize(schema, serpatch->data);
|
||||
PCPATCH_UNCOMPRESSED *patch = pcalloc(sizeof(PCPATCH_UNCOMPRESSED));
|
||||
|
||||
/* Set up basic info */
|
||||
patch->type = serpatch->compression;
|
||||
@ -774,6 +759,17 @@ pc_patch_uncompressed_deserialize(const SERIALIZED_PATCH *serpatch, const PCSCHE
|
||||
patch->maxpoints = 0;
|
||||
patch->bounds = serpatch->bounds;
|
||||
|
||||
buf = (uint8_t*)serpatch->data;
|
||||
|
||||
/* Point into the stats area */
|
||||
patch->stats = pc_patch_stats_deserialize(schema, buf);
|
||||
|
||||
/* Advance data pointer past the stats serialization */
|
||||
patch->data = buf + stats_size;
|
||||
|
||||
/* Calculate the point data buffer size */
|
||||
patch->datasize = VARSIZE(serpatch) - sizeof(SERIALIZED_PATCH) + 1 - stats_size;
|
||||
|
||||
return (PCPATCH*)patch;
|
||||
}
|
||||
|
||||
|
||||
@ -29,6 +29,10 @@
|
||||
|
||||
#define PG_GETHEADER_SERPATCH_P(argnum) (SERIALIZED_PATCH*)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(argnum), 0, sizeof(SERIALIZED_PATCH))
|
||||
|
||||
#define PG_GETHEADERX_SERPATCH_P(argnum, extra) (SERIALIZED_PATCH*)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(argnum), 0, sizeof(SERIALIZED_PATCH)+extra)
|
||||
|
||||
#define PG_GETHEADER_STATS_P(argnum, statsize) (uint8_t*)(((SERIALIZED_PATCH*)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(argnum), 0, sizeof(SERIALIZED_PATCH) + statsize))->data)
|
||||
|
||||
#define AUTOCOMPRESS_NO 0
|
||||
#define AUTOCOMPRESS_YES 1
|
||||
|
||||
@ -113,4 +117,6 @@ char* pc_patch_to_hexwkb(const PCPATCH *patch);
|
||||
uint8_t* pc_patch_to_geometry_wkb_envelope(const SERIALIZED_PATCH *pa, const PCSCHEMA *schema, size_t *wkbsize);
|
||||
|
||||
/** Read the first few bytes off an object to get the datum */
|
||||
uint32 pcid_from_datum(Datum d);
|
||||
uint32 pcid_from_datum(Datum d);
|
||||
|
||||
PCSTATS* pc_patch_stats_deserialize(const PCSCHEMA *schema, const uint8_t *buf);
|
||||
|
||||
@ -284,22 +284,16 @@ CREATE OR REPLACE FUNCTION PC_Explode(p pcpatch)
|
||||
-- SQL Utility Functions
|
||||
-------------------------------------------------------------------
|
||||
|
||||
-- Utility to get AVERAGE value from patch
|
||||
CREATE OR REPLACE FUNCTION PC_PatchAvg(p pcpatch, attr text)
|
||||
RETURNS numeric AS
|
||||
'WITH pts AS ( SELECT PC_Explode($1) AS pt) SELECT avg(PC_Get(pt, $2)) FROM pts'
|
||||
LANGUAGE 'sql';
|
||||
|
||||
-- Utility to get MAXIMUM value from patch
|
||||
CREATE OR REPLACE FUNCTION PC_PatchMax(p pcpatch, attr text)
|
||||
RETURNS numeric AS
|
||||
'WITH pts AS ( SELECT PC_Explode($1) AS pt) SELECT max(PC_Get(pt, $2)) FROM pts'
|
||||
LANGUAGE 'sql';
|
||||
CREATE OR REPLACE FUNCTION PC_PatchMax(p pcpatch, attr text, stat text default 'max')
|
||||
RETURNS numeric AS 'MODULE_PATHNAME', 'pcpatch_get_stat'
|
||||
LANGUAGE 'c' IMMUTABLE STRICT;
|
||||
|
||||
-- Utility to get MINIMUM value from patch
|
||||
CREATE OR REPLACE FUNCTION PC_PatchMin(p pcpatch, attr text)
|
||||
RETURNS numeric AS
|
||||
'WITH pts AS ( SELECT PC_Explode($1) AS pt) SELECT min(PC_Get(pt, $2)) FROM pts'
|
||||
LANGUAGE 'sql';
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user