mirror of
https://github.com/pgpointcloud/pointcloud.git
synced 2025-12-08 20:36:04 +00:00
Add PC_Range(p PCPATCH, first int4, count int4)
This commit adds a PC_Range function. This function returns a patch of "count" points. These points are selected from the start-th point in the input patch.
This commit is contained in:
parent
da831e50b6
commit
fb5f1dcca4
1
NEWS
1
NEWS
@ -10,6 +10,7 @@
|
||||
- PC_Lib_Version(), PC_Script_Version() (#40)
|
||||
- PC_Sort(pcpatch,text[]) (#106)
|
||||
- PC_IsSorted(pcpatch,text[],boolean) (#106)
|
||||
- PC_Range(pcpatch, int, int) returns pcpatch (#152)
|
||||
- Enhancements
|
||||
- Support sigbits encoding for 64bit integers (#61)
|
||||
- Warn about truncated values (#68)
|
||||
|
||||
@ -471,6 +471,9 @@ Now that you have created two tables, you'll see entries for them in the `pointc
|
||||
|
||||
> Returns a copy of the input patch lexicographically sorted along the given dimensions.
|
||||
|
||||
**PC_Range(p pcpatch, start int4, n int4)** returns **pcpatch**
|
||||
|
||||
> Returns a patch containing *n* points. These points are selected from the *start*-th point with 1-based indexing.
|
||||
|
||||
## PostGIS Integration ##
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/***********************************************************************
|
||||
* cu_pc_schema.c
|
||||
*
|
||||
* Testing for the schema API functions
|
||||
* Testing for the schema API functions
|
||||
*
|
||||
* Portions Copyright (c) 2012, OpenGeo
|
||||
*
|
||||
@ -594,7 +594,7 @@ test_patch_compress_from_ght_to_lazperf()
|
||||
pc_patch_free((PCPATCH *)patch_ght);
|
||||
pc_patch_free((PCPATCH *)patch_lazperf);
|
||||
}
|
||||
#endif /* defined(HAVE_LIBGHT) && defined(HAVE_LAZPERF) */
|
||||
#endif /* defined(HAVE_LIBGHT) && defined(HAVE_LAZPERF) */
|
||||
|
||||
static void
|
||||
test_patch_pointn_last_first()
|
||||
@ -765,6 +765,232 @@ test_patch_pointn_ght_compression()
|
||||
pc_pointlist_free(li);
|
||||
}
|
||||
|
||||
static void
|
||||
test_patch_range_compression_none()
|
||||
{
|
||||
int i;
|
||||
int npts = 20;
|
||||
PCPOINTLIST *pl;
|
||||
PCPATCH *pa;
|
||||
PCPATCH *par;
|
||||
char *str;
|
||||
|
||||
pl = pc_pointlist_make(npts);
|
||||
|
||||
for ( i = 0; i < npts; i++ )
|
||||
{
|
||||
PCPOINT *pt = pc_point_make(simpleschema);
|
||||
pc_point_set_double_by_name(pt, "X", i);
|
||||
pc_point_set_double_by_name(pt, "Y", i);
|
||||
pc_point_set_double_by_name(pt, "Z", i * 0.1);
|
||||
pc_point_set_double_by_name(pt, "Intensity", 100 - i);
|
||||
pc_pointlist_add_point(pl, pt);
|
||||
}
|
||||
|
||||
pa = (PCPATCH*)pc_patch_uncompressed_from_pointlist(pl);
|
||||
par = pc_patch_range(pa, 16, 4);
|
||||
str = pc_patch_to_string(par);
|
||||
|
||||
CU_ASSERT_STRING_EQUAL(str,
|
||||
"{\"pcid\":0,\"pts\":[[15,15,1.5,85],[16,16,1.6,84],[17,17,1.7,83],[18,18,1.8,82]]}");
|
||||
|
||||
pcfree(str);
|
||||
pc_patch_free(par);
|
||||
pc_patch_free(pa);
|
||||
pc_pointlist_free(pl);
|
||||
}
|
||||
|
||||
static void
|
||||
test_patch_range_compression_none_with_full_range()
|
||||
{
|
||||
int i;
|
||||
int npts = 4;
|
||||
PCPOINTLIST *pl;
|
||||
PCPATCH *pa;
|
||||
PCPATCH *par;
|
||||
char *str;
|
||||
|
||||
pl = pc_pointlist_make(npts);
|
||||
|
||||
for ( i = 0; i < npts; i++ )
|
||||
{
|
||||
PCPOINT *pt = pc_point_make(simpleschema);
|
||||
pc_point_set_double_by_name(pt, "X", i);
|
||||
pc_point_set_double_by_name(pt, "Y", i);
|
||||
pc_point_set_double_by_name(pt, "Z", i * 0.1);
|
||||
pc_point_set_double_by_name(pt, "Intensity", 100 - i);
|
||||
pc_pointlist_add_point(pl, pt);
|
||||
}
|
||||
|
||||
pa = (PCPATCH*)pc_patch_uncompressed_from_pointlist(pl);
|
||||
par = pc_patch_range(pa, 1, npts);
|
||||
CU_ASSERT(pa == par);
|
||||
|
||||
str = pc_patch_to_string(par);
|
||||
CU_ASSERT_STRING_EQUAL(str,
|
||||
"{\"pcid\":0,\"pts\":[[0,0,0,100],[1,1,0.1,99],[2,2,0.2,98],[3,3,0.3,97]]}");
|
||||
|
||||
pcfree(str);
|
||||
pc_patch_free(pa);
|
||||
pc_pointlist_free(pl);
|
||||
}
|
||||
|
||||
static void
|
||||
test_patch_range_compression_none_with_bad_arguments(int first, int count)
|
||||
{
|
||||
int i;
|
||||
int npts = 20;
|
||||
PCPOINTLIST *pl;
|
||||
PCPATCH *pa;
|
||||
PCPATCH *par;
|
||||
|
||||
pl = pc_pointlist_make(npts);
|
||||
|
||||
for ( i = 0; i < npts; i++ )
|
||||
{
|
||||
PCPOINT *pt = pc_point_make(simpleschema);
|
||||
pc_point_set_double_by_name(pt, "X", i);
|
||||
pc_point_set_double_by_name(pt, "Y", i);
|
||||
pc_point_set_double_by_name(pt, "Z", i * 0.1);
|
||||
pc_point_set_double_by_name(pt, "Intensity", 100 - i);
|
||||
pc_pointlist_add_point(pl, pt);
|
||||
}
|
||||
|
||||
pa = (PCPATCH*)pc_patch_uncompressed_from_pointlist(pl);
|
||||
par = pc_patch_range(pa, first, count);
|
||||
CU_ASSERT(par == NULL);
|
||||
|
||||
pc_patch_free(pa);
|
||||
pc_pointlist_free(pl);
|
||||
}
|
||||
|
||||
static void
|
||||
test_patch_range_compression_none_with_zero_count()
|
||||
{
|
||||
test_patch_range_compression_none_with_bad_arguments(1, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_patch_range_compression_none_with_zero_first()
|
||||
{
|
||||
test_patch_range_compression_none_with_bad_arguments(0, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_patch_range_compression_none_with_out_of_bounds_first()
|
||||
{
|
||||
test_patch_range_compression_none_with_bad_arguments(21, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_patch_range_compression_lazperf()
|
||||
{
|
||||
int i;
|
||||
int npts = 20;
|
||||
PCPOINTLIST *pl;
|
||||
PCPATCH *pa;
|
||||
PCPATCH *par;
|
||||
char *str;
|
||||
|
||||
pl = pc_pointlist_make(npts);
|
||||
|
||||
for ( i = 0; i < npts; i++ )
|
||||
{
|
||||
PCPOINT *pt = pc_point_make(simpleschema);
|
||||
pc_point_set_double_by_name(pt, "X", i);
|
||||
pc_point_set_double_by_name(pt, "Y", i);
|
||||
pc_point_set_double_by_name(pt, "Z", i * 0.1);
|
||||
pc_point_set_double_by_name(pt, "Intensity", 100 - i);
|
||||
pc_pointlist_add_point(pl, pt);
|
||||
}
|
||||
|
||||
pa = (PCPATCH*)pc_patch_lazperf_from_pointlist(pl);
|
||||
par = pc_patch_range(pa, 16, 4);
|
||||
str = pc_patch_to_string(par);
|
||||
|
||||
CU_ASSERT_STRING_EQUAL(str,
|
||||
"{\"pcid\":0,\"pts\":[[15,15,1.5,85],[16,16,1.6,84],[17,17,1.7,83],[18,18,1.8,82]]}");
|
||||
|
||||
pcfree(str);
|
||||
pc_patch_free(par);
|
||||
pc_patch_free(pa);
|
||||
pc_pointlist_free(pl);
|
||||
}
|
||||
|
||||
static void
|
||||
test_patch_range_compression_dimensional(enum DIMCOMPRESSIONS dimcomp)
|
||||
{
|
||||
int i;
|
||||
PCPOINTLIST *pl;
|
||||
PCPATCH *pa;
|
||||
PCPATCH *par;
|
||||
PCPATCH_DIMENSIONAL *pad;
|
||||
PCPOINT *pt;
|
||||
char *str;
|
||||
int npts = PCDIMSTATS_MIN_SAMPLE+1; // force to keep custom compression
|
||||
|
||||
// build a dimensional patch
|
||||
pl = pc_pointlist_make(npts);
|
||||
|
||||
for ( i = npts; i >= 0; i-- )
|
||||
{
|
||||
pt = pc_point_make(simpleschema);
|
||||
pc_point_set_double_by_name(pt, "X", i);
|
||||
pc_point_set_double_by_name(pt, "Y", i);
|
||||
pc_point_set_double_by_name(pt, "Z", i);
|
||||
pc_point_set_double_by_name(pt, "Intensity", 10);
|
||||
pc_pointlist_add_point(pl, pt);
|
||||
}
|
||||
|
||||
pad = pc_patch_dimensional_from_pointlist(pl);
|
||||
|
||||
// set dimensional compression for each dimension
|
||||
PCDIMSTATS *stats = pc_dimstats_make(simpleschema);
|
||||
pc_dimstats_update(stats, pad);
|
||||
for ( i = 0; i<pad->schema->ndims; i++ )
|
||||
stats->stats[i].recommended_compression = dimcomp;
|
||||
|
||||
// compress patch
|
||||
pa = (PCPATCH*) pc_patch_dimensional_compress(pad, stats);
|
||||
|
||||
par = pc_patch_range(pa, 16, 4);
|
||||
str = pc_patch_to_string(par);
|
||||
|
||||
CU_ASSERT_STRING_EQUAL(str,
|
||||
"{\"pcid\":0,\"pts\":[[9986,9986,9986,10],[9985,9985,9985,10],[9984,9984,9984,10],[9983,9983,9983,10]]}");
|
||||
|
||||
pcfree(str);
|
||||
pc_patch_free(par);
|
||||
pc_patch_free((PCPATCH *)pad);
|
||||
pc_dimstats_free(stats);
|
||||
pc_patch_free(pa);
|
||||
pc_pointlist_free(pl);
|
||||
}
|
||||
|
||||
static void
|
||||
test_patch_range_compression_dimensional_none()
|
||||
{
|
||||
test_patch_range_compression_dimensional(PC_DIM_NONE);
|
||||
}
|
||||
|
||||
static void
|
||||
test_patch_range_compression_dimensional_zlib()
|
||||
{
|
||||
test_patch_range_compression_dimensional(PC_DIM_ZLIB);
|
||||
}
|
||||
|
||||
static void
|
||||
test_patch_range_compression_dimensional_sigbits()
|
||||
{
|
||||
test_patch_range_compression_dimensional(PC_DIM_SIGBITS);
|
||||
}
|
||||
|
||||
static void
|
||||
test_patch_range_compression_dimensional_rle()
|
||||
{
|
||||
test_patch_range_compression_dimensional(PC_DIM_RLE);
|
||||
}
|
||||
|
||||
/* REGISTER ***********************************************************/
|
||||
|
||||
CU_TestInfo patch_tests[] = {
|
||||
@ -788,6 +1014,18 @@ CU_TestInfo patch_tests[] = {
|
||||
PC_TEST(test_patch_pointn_dimensional_compression_sigbits),
|
||||
PC_TEST(test_patch_pointn_dimensional_compression_rle),
|
||||
PC_TEST(test_patch_pointn_ght_compression),
|
||||
PC_TEST(test_patch_range_compression_none),
|
||||
PC_TEST(test_patch_range_compression_none_with_full_range),
|
||||
PC_TEST(test_patch_range_compression_none_with_zero_count),
|
||||
PC_TEST(test_patch_range_compression_none_with_zero_first),
|
||||
PC_TEST(test_patch_range_compression_none_with_out_of_bounds_first),
|
||||
PC_TEST(test_patch_range_compression_dimensional_none),
|
||||
PC_TEST(test_patch_range_compression_dimensional_zlib),
|
||||
PC_TEST(test_patch_range_compression_dimensional_sigbits),
|
||||
PC_TEST(test_patch_range_compression_dimensional_rle),
|
||||
#ifdef HAVE_LAZPERF
|
||||
PC_TEST(test_patch_range_compression_lazperf),
|
||||
#endif
|
||||
CU_TEST_INFO_NULL
|
||||
};
|
||||
|
||||
|
||||
@ -458,4 +458,7 @@ PCPATCH *pc_patch_sort(const PCPATCH *pa, const char **name, int ndims);
|
||||
/** True/false if the patch is sorted on dimension */
|
||||
uint32_t pc_patch_is_sorted(const PCPATCH *pa, const char **name, int ndims, char strict);
|
||||
|
||||
/** Subset batch based on index */
|
||||
PCPATCH* pc_patch_range(const PCPATCH *pa, int first, int count);
|
||||
|
||||
#endif /* _PC_API_H */
|
||||
|
||||
@ -306,7 +306,7 @@ PCPATCH *
|
||||
pc_patch_from_wkb(const PCSCHEMA *s, uint8_t *wkb, size_t wkbsize)
|
||||
{
|
||||
/*
|
||||
byte: endianness (1 = NDR, 0 = XDR)
|
||||
byte: endianness (1 = NDR, 0 = XDR)
|
||||
uint32: pcid (key to POINTCLOUD_SCHEMAS)
|
||||
uint32: compression (0 = no compression, 1 = dimensional, 2 = GHT)
|
||||
uchar[]: data (interpret relative to pcid and compression)
|
||||
@ -378,7 +378,7 @@ uint8_t *
|
||||
pc_patch_to_wkb(const PCPATCH *patch, size_t *wkbsize)
|
||||
{
|
||||
/*
|
||||
byte: endianness (1 = NDR, 0 = XDR)
|
||||
byte: endianness (1 = NDR, 0 = XDR)
|
||||
uint32: pcid (key to POINTCLOUD_SCHEMAS)
|
||||
uint32: compression (0 = no compression, 1 = dimensional, 2 = GHT)
|
||||
uchar[]: data (interpret relative to pcid and compression)
|
||||
@ -522,6 +522,68 @@ pc_patch_from_patchlist(PCPATCH **palist, int numpatches)
|
||||
return (PCPATCH*)paout;
|
||||
}
|
||||
|
||||
// first: the first element to select (1-based indexing)
|
||||
// count: the number of points to select
|
||||
PCPATCH *
|
||||
pc_patch_range(const PCPATCH *pa, int first, int count)
|
||||
{
|
||||
PCPATCH_UNCOMPRESSED *paout, *pu;
|
||||
int countmax;
|
||||
uint8_t *buf;
|
||||
size_t size;
|
||||
size_t start;
|
||||
|
||||
assert(pa);
|
||||
|
||||
first--;
|
||||
countmax = pa->npoints - first;
|
||||
|
||||
if ( count > countmax )
|
||||
count = countmax;
|
||||
|
||||
if ( first < 0 || count <= 0 )
|
||||
return NULL;
|
||||
|
||||
if ( count == pa->npoints )
|
||||
return (PCPATCH *) pa;
|
||||
|
||||
paout = pc_patch_uncompressed_make(pa->schema, count);
|
||||
if ( !paout )
|
||||
return NULL;
|
||||
paout->npoints = count;
|
||||
|
||||
pu = (PCPATCH_UNCOMPRESSED *) pc_patch_uncompress(pa);
|
||||
if ( !pu )
|
||||
{
|
||||
pc_patch_free((PCPATCH *) paout);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = paout->data;
|
||||
start = pa->schema->size * first;
|
||||
size = pa->schema->size * count;
|
||||
|
||||
memcpy(buf, pu->data + start, size);
|
||||
|
||||
if ( ((PCPATCH *) pu) != pa )
|
||||
pc_patch_free((PCPATCH *) pu);
|
||||
|
||||
if ( PC_FAILURE == pc_patch_uncompressed_compute_extent(paout) )
|
||||
{
|
||||
pcerror("%s: extent computation failed", __func__);
|
||||
pc_patch_free((PCPATCH *) paout);
|
||||
return NULL;
|
||||
}
|
||||
if ( PC_FAILURE == pc_patch_uncompressed_compute_stats(paout) )
|
||||
{
|
||||
pcerror("%s: stats computation failed", __func__);
|
||||
pc_patch_free((PCPATCH *) paout);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (PCPATCH *) paout;
|
||||
}
|
||||
|
||||
/** get point n from patch */
|
||||
/** positive 1-based: 1=first point, npoints=last point */
|
||||
/** negative 1-based: -1=last point, -npoints=first point */
|
||||
|
||||
@ -312,6 +312,15 @@ SELECT sum(PC_NumPoints(pa)) FROM pa_test;
|
||||
8
|
||||
(1 row)
|
||||
|
||||
SELECT PC_AsText(PC_Range(pa, 1, 1)) FROM pa_test;
|
||||
pc_astext
|
||||
---------------------------------------
|
||||
{"pcid":1,"pts":[[0.02,0.03,0.05,6]]}
|
||||
{"pcid":1,"pts":[[0.06,0.07,0.05,6]]}
|
||||
{"pcid":1,"pts":[[0.06,0.07,0.05,6]]}
|
||||
{"pcid":1,"pts":[[0.06,0.07,0.05,6]]}
|
||||
(4 rows)
|
||||
|
||||
CREATE TABLE IF NOT EXISTS pa_test_dim (
|
||||
pa PCPATCH(3)
|
||||
);
|
||||
|
||||
@ -28,6 +28,7 @@ Datum pcpatch_uncompress(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_compress(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_numpoints(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_pointn(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_range(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_pcid(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_summary(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_compression(PG_FUNCTION_ARGS);
|
||||
@ -677,6 +678,29 @@ Datum pcpatch_pointn(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_POINTER(serpt);
|
||||
}
|
||||
|
||||
PG_FUNCTION_INFO_V1(pcpatch_range);
|
||||
Datum pcpatch_range(PG_FUNCTION_ARGS)
|
||||
{
|
||||
SERIALIZED_PATCH *serpaout;
|
||||
SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0);
|
||||
int32 first = PG_GETARG_INT32(1);
|
||||
int32 count = PG_GETARG_INT32(2);
|
||||
PCSCHEMA *schema = pc_schema_from_pcid(serpa->pcid, fcinfo);
|
||||
PCPATCH *patch = pc_patch_deserialize(serpa, schema);
|
||||
PCPATCH *patchout = NULL;
|
||||
if ( patch )
|
||||
{
|
||||
patchout = pc_patch_range(patch, first, count);
|
||||
if ( patchout != patch )
|
||||
pc_patch_free(patch);
|
||||
}
|
||||
if ( !patchout )
|
||||
PG_RETURN_NULL();
|
||||
serpaout = pc_patch_serialize(patchout, NULL);
|
||||
pc_patch_free(patchout);
|
||||
PG_RETURN_POINTER(serpaout);
|
||||
}
|
||||
|
||||
PG_FUNCTION_INFO_V1(pcpatch_pcid);
|
||||
Datum pcpatch_pcid(PG_FUNCTION_ARGS)
|
||||
{
|
||||
|
||||
@ -309,6 +309,10 @@ CREATE OR REPLACE FUNCTION PC_IsSorted(p pcpatch, attr text[], strict boolean de
|
||||
RETURNS boolean AS 'MODULE_PATHNAME', 'pcpatch_is_sorted'
|
||||
LANGUAGE 'c' IMMUTABLE STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION PC_Range(p pcpatch, first int4, count int4)
|
||||
RETURNS pcpatch AS 'MODULE_PATHNAME', 'pcpatch_range'
|
||||
LANGUAGE 'c' IMMUTABLE STRICT;
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- POINTCLOUD_COLUMNS
|
||||
-------------------------------------------------------------------
|
||||
|
||||
@ -232,6 +232,8 @@ SELECT PC_Envelope(pa) from pa_test;
|
||||
SELECT PC_AsText(PC_Union(pa)) FROM pa_test;
|
||||
SELECT sum(PC_NumPoints(pa)) FROM pa_test;
|
||||
|
||||
SELECT PC_AsText(PC_Range(pa, 1, 1)) FROM pa_test;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS pa_test_dim (
|
||||
pa PCPATCH(3)
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user