Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -264,12 +264,12 @@ Now that you have created two tables, you'll see entries for them in the `pointc
>
> 1

**PC_Envelope(p pcpatch)** returns **bytea**
**PC_Envelope_AsBinary(p pcpatch)** returns **bytea**

> Return the OGC "well-known binary" format for *bounds* of the patch.
> Useful for performing intersection tests with geometries.
>
> SELECT PC_Envelope(pa) FROM patches LIMIT 1;
> SELECT PC_Envelope_AsBinary(pa) FROM patches LIMIT 1;
>
> \x0103000000010000000500000090c2f5285cbf5fc0e17a
> 14ae4781464090c2f5285cbf5fc0ec51b81e858b46400ad7
Expand DownExpand Up@@ -493,6 +493,11 @@ The `pointcloud_postgis` extension adds functions that allow you to use PostgreS
>
> POINT Z (-127 45 124)

**PC_Envelope(pcpatch)** returns **geometry**<br/>
**pcpatch::geometry** returns **geometry**

> Get the PcPatch bounds as a PostGIS geometry

## Compressions ##

One of the issues with LIDAR data is that there is a lot of it. To deal with data volumes, PostgreSQL Pointcloud allows schemas to declare their preferred compression method in the `<pc:metadata>` block of the schema document. In the example schema, we declared our compression as follows:
Expand Down
21 changes: 18 additions & 3 deletions lib/cunit/cu_pc_patch.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -446,8 +446,11 @@ test_patch_wkb()
PCPOINTLIST *pl1;
PCPATCH_UNCOMPRESSED *pu1, *pu2;
PCPATCH *pa1, *pa2, *pa3, *pa4;
size_t z1, z2;
uint8_t *wkb1, *wkb2;
size_t z1, z2, z3;
uint8_t *wkb1, *wkb2, *wkb3, *hexwkb;

static char *hexresult_ndr = "01030000000100000005000000000000000000000000000000000000000000000000000000CDCCCCCCCC8C4B40EC51B81E852B4440CDCCCCCCCC8C4B40EC51B81E852B4440000000000000000000000000000000000000000000000000";
static char *hexresult_xdr = "00000000030000000100000005000000000000000000000000000000000000000000000000404B8CCCCCCCCCCD40442B851EB851EC404B8CCCCCCCCCCD40442B851EB851EC000000000000000000000000000000000000000000000000";

pl1 = pc_pointlist_make(npts);

Expand All@@ -466,6 +469,7 @@ test_patch_wkb()
// str = hexbytes_from_bytes(wkb1, z1);
// printf("str\n%s\n",str);
pa2 = pc_patch_from_wkb(simpleschema, wkb1, z1);
pcfree(wkb1);

// printf("pa2\n%s\n",pc_patch_to_string(pa2));

Expand All@@ -489,6 +493,18 @@ test_patch_wkb()
CU_ASSERT_EQUAL(pu1->npoints, pu2->npoints);
CU_ASSERT(memcmp(pu1->data, pu2->data, pu1->datasize) == 0);

wkb3 = pc_bounds_to_wkb(&pa1->bounds,simpleschema->srid,&z3);
hexwkb = hexbytes_from_bytes(wkb3,z3);
if ( machine_endian() == PC_NDR )
{
CU_ASSERT_STRING_EQUAL(hexwkb, hexresult_ndr);
}
else
{
CU_ASSERT_STRING_EQUAL(hexwkb, hexresult_xdr);
}
pcfree(hexwkb);
pcfree(wkb3);

pc_pointlist_free(pl1);
pc_patch_free(pa1);
Expand All@@ -497,7 +513,6 @@ test_patch_wkb()
pc_patch_free(pa4);
pc_patch_free((PCPATCH*)pu1);
pc_patch_free((PCPATCH*)pu2);
pcfree(wkb1);
}


Expand Down
3 changes: 3 additions & 0 deletions lib/pc_api.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -409,6 +409,9 @@ int pc_patch_compute_extent(PCPATCH *patch);
/** True/false if bounds intersect */
int pc_bounds_intersects(const PCBOUNDS *b1, const PCBOUNDS *b2);

/** Returns the bounds as an OGC WKB polygon */
uint8_t *pc_bounds_to_wkb(const PCBOUNDS *bounds, uint32_t srid, size_t *wkbsize);

/** Subset batch based on less-than condition on dimension */
PCPATCH* pc_patch_filter_lt_by_name(const PCPATCH *pa, const char *name, double val);

Expand Down
99 changes: 99 additions & 0 deletions lib/pc_util.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -263,3 +263,102 @@ void pc_bounds_merge(PCBOUNDS *b1, const PCBOUNDS *b2)
if ( b2->ymax > b1->ymax ) b1->ymax = b2->ymax;
}


uint8_t *
wkb_set_double(uint8_t *wkb, double d)
{
memcpy(wkb, &d, 8);
wkb += 8;
return wkb;
}

uint8_t *
wkb_set_uint32(uint8_t *wkb, uint32_t i)
{
memcpy(wkb, &i, 4);
wkb += 4;
return wkb;
}

uint8_t *
wkb_set_char(uint8_t *wkb, char c)
{
memcpy(wkb, &c, 1);
wkb += 1;
return wkb;
}

uint8_t *
pc_bounds_to_wkb(const PCBOUNDS *bounds, uint32_t srid, size_t *wkbsize)
{
/* Bounds! */
double xmin = bounds->xmin;
double ymin = bounds->ymin;
double xmax = bounds->xmax;
double ymax = bounds->ymax;

static uint32_t srid_mask = 0x20000000;
static uint32_t nrings = 1;
static uint32_t npoints_by_type[] = { 0, 1, 2, 5 };
uint32_t wkbtype = 1 + (xmin!=xmax) + (ymin!=ymax); /* WKB POINT, LINESTRING or POLYGON */
uint32_t npoints = npoints_by_type[wkbtype];
uint8_t *wkb, *ptr;
size_t size = 1 + wkbtype*4 + npoints*2*8; /* endian + type + (nrings?) + (npoints?) + npoints dbl pt */

if ( srid )
{
wkbtype |= srid_mask;
size += 4;
}

if ( wkbsize ) *wkbsize = size;
wkb = pcalloc(size);
ptr = wkb;

ptr = wkb_set_char(ptr, machine_endian()); /* Endian flag */

ptr = wkb_set_uint32(ptr, wkbtype); /* TYPE = POINT, LINESTRING or POLYGON */

if ( srid )
{
ptr = wkb_set_uint32(ptr, srid); /* SRID */
}


switch( npoints )
{
case 5 : ptr = wkb_set_uint32(ptr, nrings); /* NRINGS = 1 */
case 2 : ptr = wkb_set_uint32(ptr, npoints); /* NPOINTS = 1, 2 or 5 */
}

/* Point 0 */
ptr = wkb_set_double(ptr, xmin);
ptr = wkb_set_double(ptr, ymin);

if(npoints==2) // LINESTRING
{
/* Point 1 */
ptr = wkb_set_double(ptr, xmax);
ptr = wkb_set_double(ptr, ymax);
}
else if(npoints==5) // POLYGON
{
/* Point 1 */
ptr = wkb_set_double(ptr, xmin);
ptr = wkb_set_double(ptr, ymax);

/* Point 2 */
ptr = wkb_set_double(ptr, xmax);
ptr = wkb_set_double(ptr, ymax);

/* Point 3 */
ptr = wkb_set_double(ptr, xmax);
ptr = wkb_set_double(ptr, ymin);

/* Point 4 */
ptr = wkb_set_double(ptr, xmin);
ptr = wkb_set_double(ptr, ymin);
}

return wkb;
}
6 changes: 3 additions & 3 deletions pgsql/expected/pointcloud.out
Original file line numberDiff line numberDiff line change
Expand Up@@ -291,10 +291,10 @@ SELECT PC_AsText(pa) FROM pa_test;
{"pcid":1,"pts":[[0.06,0.07,0.05,6],[0.09,0.1,0.05,10]]}
(4 rows)

SELECT PC_Envelope(pa) from pa_test;
pc_envelope
SELECT PC_Envelope_AsBinary(pa) from pa_test;
pc_envelope_asbinary
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
\x010300000001000000050000007b14ae47e17a943fb81e85eb51b89e3f7b14ae47e17a943fb81e85eb51b89e3f7b14ae47e17a943fb81e85eb51b89e3f7b14ae47e17a943fb81e85eb51b89e3f7b14ae47e17a943fb81e85eb51b89e3f
\x01010000007b14ae47e17a943fb81e85eb51b89e3f
\x01030000000100000005000000b81e85eb51b8ae3fec51b81e85ebb13fb81e85eb51b8ae3f9a9999999999b93f0ad7a3703d0ab73f9a9999999999b93f0ad7a3703d0ab73fec51b81e85ebb13fb81e85eb51b8ae3fec51b81e85ebb13f
\x01030000000100000005000000b81e85eb51b8ae3fec51b81e85ebb13fb81e85eb51b8ae3f9a9999999999b93f0ad7a3703d0ab73f9a9999999999b93f0ad7a3703d0ab73fec51b81e85ebb13fb81e85eb51b8ae3fec51b81e85ebb13f
\x01030000000100000005000000b81e85eb51b8ae3fec51b81e85ebb13fb81e85eb51b8ae3f9a9999999999b93f0ad7a3703d0ab73f9a9999999999b93f0ad7a3703d0ab73fec51b81e85ebb13fb81e85eb51b8ae3fec51b81e85ebb13f
Expand Down
10 changes: 5 additions & 5 deletions pgsql/pc_inout.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -31,7 +31,7 @@ Datum pcpoint_from_double_array(PG_FUNCTION_ARGS);
Datum pcpoint_as_text(PG_FUNCTION_ARGS);
Datum pcpatch_as_text(PG_FUNCTION_ARGS);
Datum pcpoint_as_bytea(PG_FUNCTION_ARGS);
Datum pcpatch_bytea_envelope(PG_FUNCTION_ARGS);
Datum pcpatch_envelope_as_bytea(PG_FUNCTION_ARGS);


static void
Expand DownExpand Up@@ -293,8 +293,8 @@ Datum pcpoint_as_bytea(PG_FUNCTION_ARGS)
PG_RETURN_BYTEA_P(wkb);
}

PG_FUNCTION_INFO_V1(pcpatch_bytea_envelope);
Datum pcpatch_bytea_envelope(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(pcpatch_envelope_as_bytea);
Datum pcpatch_envelope_as_bytea(PG_FUNCTION_ARGS)
{
uint8 *bytes;
size_t bytes_size;
Expand All@@ -303,13 +303,13 @@ Datum pcpatch_bytea_envelope(PG_FUNCTION_ARGS)
SERIALIZED_PATCH *serpatch = PG_GETHEADER_SERPATCH_P(0);
PCSCHEMA *schema = pc_schema_from_pcid(serpatch->pcid, fcinfo);

bytes = pc_patch_to_geometry_wkb_envelope(serpatch, schema, &bytes_size);
bytes = pc_bounds_to_wkb(&serpatch->bounds, schema->srid, &bytes_size);
wkb_size = VARHDRSZ + bytes_size;
wkb = palloc(wkb_size);
memcpy(VARDATA(wkb), bytes, bytes_size);
SET_VARSIZE(wkb, wkb_size);

pfree(bytes);
pcfree(bytes);

PG_RETURN_BYTEA_P(wkb);
}
Expand Down
100 changes: 0 additions & 100 deletions pgsql/pc_pgsql.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -895,103 +895,3 @@ pc_patch_deserialize(const SERIALIZED_PATCH *serpatch, const PCSCHEMA *schema)
pcerror("%s: unsupported compression type", __func__);
return NULL;
}


static uint8_t *
pc_patch_wkb_set_double(uint8_t *wkb, double d)
{
memcpy(wkb, &d, 8);
wkb += 8;
return wkb;
}

static uint8_t *
pc_patch_wkb_set_int32(uint8_t *wkb, uint32_t i)
{
memcpy(wkb, &i, 8);
wkb += 4;
return wkb;
}

static uint8_t *
pc_patch_wkb_set_char(uint8_t *wkb, char c)
{
memcpy(wkb, &c, 1);
wkb += 1;
return wkb;
}

static char
machine_endian(void)
{
static int check_int = 1; /* dont modify this!!! */
return *((char *) &check_int); /* 0 = big endian | xdr,
* 1 = little endian | ndr */
}

uint8_t *
pc_patch_to_geometry_wkb_envelope(const SERIALIZED_PATCH *pa, const PCSCHEMA *schema, size_t *wkbsize)
{
static uint32_t srid_mask = 0x20000000;
static uint32_t nrings = 1;
static uint32_t npoints = 5;
uint32_t wkbtype = 3; /* WKB POLYGON */
uint8_t *wkb, *ptr;
int has_srid = false;
size_t size = 1 + 4 + 4 + 4 + 2*npoints*8; /* endian + type + nrings + npoints + 5 dbl pts */

/* Bounds! */
double xmin = pa->bounds.xmin;
double ymin = pa->bounds.ymin;
double xmax = pa->bounds.xmax;
double ymax = pa->bounds.ymax;

/* Make sure they're slightly bigger than a point */
if ( xmin == xmax ) xmax += xmax * 0.0000001;
if ( ymin == ymax ) ymax += ymax * 0.0000001;

if ( schema->srid > 0 )
{
has_srid = true;
wkbtype |= srid_mask;
size += 4;
}

wkb = palloc(size);
ptr = wkb;

ptr = pc_patch_wkb_set_char(ptr, machine_endian()); /* Endian flag */

ptr = pc_patch_wkb_set_int32(ptr, wkbtype); /* TYPE = Polygon */

if ( has_srid )
{
ptr = pc_patch_wkb_set_int32(ptr, schema->srid); /* SRID */
}

ptr = pc_patch_wkb_set_int32(ptr, nrings); /* NRINGS = 1 */
ptr = pc_patch_wkb_set_int32(ptr, npoints); /* NPOINTS = 5 */

/* Point 0 */
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmin);
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymin);

/* Point 1 */
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmin);
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymax);

/* Point 2 */
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmax);
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymax);

/* Point 3 */
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmax);
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymin);

/* Point 4 */
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmin);
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymin);

if ( wkbsize ) *wkbsize = size;
return wkb;
}
4 changes: 2 additions & 2 deletions pgsql/pointcloud.sql.in
Original file line numberDiff line numberDiff line change
Expand Up@@ -194,8 +194,8 @@ CREATE OR REPLACE FUNCTION PC_AsText(p pcpatch)
RETURNS text AS 'MODULE_PATHNAME', 'pcpatch_as_text'
LANGUAGE 'c' IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION PC_Envelope(p pcpatch)
RETURNS bytea AS 'MODULE_PATHNAME', 'pcpatch_bytea_envelope'
CREATE OR REPLACE FUNCTION PC_Envelope_AsBinary(p pcpatch)
RETURNS bytea AS 'MODULE_PATHNAME', 'pcpatch_envelope_as_bytea'
LANGUAGE 'c' IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION PC_Uncompress(p pcpatch)
Expand Down
2 changes: 1 addition & 1 deletion pgsql/sql/pointcloud.sql
Original file line numberDiff line numberDiff line change
Expand Up@@ -228,7 +228,7 @@ INSERT INTO pa_test (pa) VALUES ('0000000001000000000000000200000006000000070000
SELECT PC_Uncompress(pa) FROM pa_test LIMIT 1;

SELECT PC_AsText(pa) FROM pa_test;
SELECT PC_Envelope(pa) from pa_test;
SELECT PC_Envelope_AsBinary(pa) from pa_test;
SELECT PC_AsText(PC_Union(pa)) FROM pa_test;
SELECT sum(PC_NumPoints(pa)) FROM pa_test;

Expand Down
8 changes: 4 additions & 4 deletions pgsql_postgis/pointcloud_postgis--1.0.sql
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,14 +16,14 @@ CREATE OR REPLACE FUNCTION PC_Intersection(pcpatch, geometry)
-----------------------------------------------------------------------------
-- Cast from pcpatch to polygon
--
CREATE OR REPLACE FUNCTION geometry(pcpatch)
CREATE OR REPLACE FUNCTION PC_Envelope(pcpatch)
RETURNS geometry AS
$$
SELECT ST_GeomFromEWKB(PC_Envelope($1))
SELECT ST_GeomFromEWKB(PC_Envelope_AsBinary($1))
$$
LANGUAGE 'sql';

CREATE CAST (pcpatch AS geometry) WITH FUNCTION geometry(pcpatch);
CREATE CAST (pcpatch AS geometry) WITH FUNCTION PC_Envelope(pcpatch);

-----------------------------------------------------------------------------
-- Cast from pcpoint to point
Expand All@@ -44,7 +44,7 @@ CREATE CAST (pcpoint AS geometry) WITH FUNCTION geometry(pcpoint);
CREATE OR REPLACE FUNCTION PC_Intersects(pcpatch, geometry)
RETURNS boolean AS
$$
SELECT ST_Intersects($2, geometry($1))
SELECT ST_Intersects($2, PC_Envelope($1))
$$
LANGUAGE 'sql';

Expand Down