diff --git a/README.md b/README.md
index 795bea5c..1df4448e 100644
--- a/README.md
+++ b/README.md
@@ -276,12 +276,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
@@ -519,6 +519,11 @@ The `pointcloud_postgis` extension adds functions that allow you to use PostgreS
>
> POINT Z (-127 45 124)
+**PC_Envelope(pcpatch)** returns **geometry**
+**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 `` block of the schema document. In the example schema, we declared our compression as follows:
diff --git a/lib/cunit/cu_pc_patch.c b/lib/cunit/cu_pc_patch.c
index babb6131..a5225160 100644
--- a/lib/cunit/cu_pc_patch.c
+++ b/lib/cunit/cu_pc_patch.c
@@ -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);
@@ -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));
@@ -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_geometry_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);
@@ -497,7 +513,6 @@ test_patch_wkb()
pc_patch_free(pa4);
pc_patch_free((PCPATCH*)pu1);
pc_patch_free((PCPATCH*)pu2);
- pcfree(wkb1);
}
diff --git a/lib/cunit/cu_pc_schema.c b/lib/cunit/cu_pc_schema.c
index b43e6132..dafe1d0e 100644
--- a/lib/cunit/cu_pc_schema.c
+++ b/lib/cunit/cu_pc_schema.c
@@ -171,6 +171,8 @@ test_schema_clone(void)
CU_ASSERT_EQUAL(clone->srid, schema->srid);
CU_ASSERT_EQUAL(clone->x_position, schema->x_position);
CU_ASSERT_EQUAL(clone->y_position, schema->y_position);
+ CU_ASSERT_EQUAL(clone->z_position, schema->z_position);
+ CU_ASSERT_EQUAL(clone->m_position, schema->m_position);
CU_ASSERT_EQUAL(clone->compression, schema->compression);
CU_ASSERT(clone->dims != schema->dims); /* deep clone */
CU_ASSERT(clone->namehash != schema->namehash); /* deep clone */
diff --git a/lib/pc_api.h b/lib/pc_api.h
index 418bd6da..a3568cc1 100644
--- a/lib/pc_api.h
+++ b/lib/pc_api.h
@@ -90,6 +90,8 @@ typedef struct
uint32_t srid; /* Foreign key reference to SPATIAL_REF_SYS */
int32_t x_position; /* What entry is the x coordinate at? */
int32_t y_position; /* What entry is the y coordinate at? */
+ int32_t z_position; /* What entry is the z coordinate at? */
+ int32_t m_position; /* What entry is the m coordinate at? */
uint32_t compression; /* Compression type applied to the data */
hashtable *namehash; /* Look-up from dimension name to pointer */
} PCSCHEMA;
@@ -148,8 +150,19 @@ typedef struct
double xmax;
double ymin;
double ymax;
+ double zmin;
+ double zmax;
+ double mmin;
+ double mmax;
} PCBOUNDS;
+typedef struct
+{
+ double xmin, ymin, zmin;
+ double xmax, ymax, zmax;
+ int32_t srid;
+} PCBOX3D;
+
/* Used for generic patch statistics */
typedef struct
{
@@ -281,8 +294,8 @@ uint32_t pc_schema_is_valid(const PCSCHEMA *s);
PCSCHEMA* pc_schema_clone(const PCSCHEMA *s);
/** Add/overwrite a dimension in a schema */
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);
+/** Check/set the xyzm positions in the dimension list */
+void pc_schema_check_xyzm(PCSCHEMA *s);
/** Get the width in bytes of a single point in the schema */
size_t pc_schema_get_size(const PCSCHEMA *s);
@@ -342,12 +355,24 @@ double pc_point_get_x(const PCPOINT *pt);
/** Returns Y coordinate */
double pc_point_get_y(const PCPOINT *pt);
+/** Returns Z coordinate */
+double pc_point_get_z(const PCPOINT *pt);
+
+/** Returns M coordinate */
+double pc_point_get_m(const PCPOINT *pt);
+
/** Set the X coordinate */
double pc_point_set_x(PCPOINT *pt, double val);
/** Set the Y coordinate */
double pc_point_set_y(PCPOINT *pt, double val);
+/** Set the Z coordinate */
+double pc_point_set_z(PCPOINT *pt, double val);
+
+/** Set the M coordinate */
+double pc_point_set_m(PCPOINT *pt, double val);
+
/** Create a new readwrite PCPOINT from a hex byte array */
PCPOINT* pc_point_from_wkb(const PCSCHEMA *s, uint8_t *wkb, size_t wkbsize);
@@ -421,6 +446,12 @@ 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 geometry */
+uint8_t *pc_bounds_to_geometry_wkb(const PCBOUNDS *bounds, uint32_t srid, size_t *wkbsize);
+
+/** Returns the bounds as a BOX3D */
+PCBOX3D *pc_bounds_to_box3d(const PCBOUNDS *bounds, uint32_t srid);
+
/** Subset batch based on less-than condition on dimension */
PCPATCH* pc_patch_filter_lt_by_name(const PCPATCH *pa, const char *name, double val);
diff --git a/lib/pc_filter.c b/lib/pc_filter.c
index a1be182e..d5e4f56d 100644
--- a/lib/pc_filter.c
+++ b/lib/pc_filter.c
@@ -146,16 +146,16 @@ pc_patch_dimensional_filter(const PCPATCH_DIMENSIONAL *pdl, const PCBITMAP *map)
int i = 0;
PCPATCH_DIMENSIONAL *fpdl = pc_patch_dimensional_clone(pdl);
- fpdl->stats = pc_stats_clone(pdl->stats);
+ fpdl->stats = pc_stats_clone(pdl->stats);
fpdl->npoints = map->nset;
for ( i = 0; i < pdl->schema->ndims; i++ )
{
PCDIMENSION *dim;
- PCDOUBLESTAT stats;
- stats.min = FLT_MAX;
- stats.max = -1*FLT_MAX;
- stats.sum = 0;
+ PCDOUBLESTAT stats;
+ stats.min = FLT_MAX;
+ stats.max = -1*FLT_MAX;
+ stats.sum = 0;
fpdl->bytes[i] = pc_bytes_filter(&(pdl->bytes[i]), map, &stats);
@@ -168,18 +168,28 @@ pc_patch_dimensional_filter(const PCPATCH_DIMENSIONAL *pdl, const PCBITMAP *map)
/* Save the X/Y stats for use in bounds later */
if ( i == pdl->schema->x_position )
{
- fpdl->bounds.xmin = stats.min;
- fpdl->bounds.xmax = stats.max;
- }
+ fpdl->bounds.xmin = stats.min;
+ fpdl->bounds.xmax = stats.max;
+ }
else if ( i == pdl->schema->y_position )
{
- fpdl->bounds.ymin = stats.min;
- fpdl->bounds.ymax = stats.max;
- }
+ fpdl->bounds.ymin = stats.min;
+ fpdl->bounds.ymax = stats.max;
+ }
+ else if ( i == pdl->schema->z_position )
+ {
+ fpdl->bounds.zmin = stats.min;
+ fpdl->bounds.zmax = stats.max;
+ }
+ else if ( i == pdl->schema->m_position )
+ {
+ fpdl->bounds.mmin = stats.min;
+ fpdl->bounds.mmax = stats.max;
+ }
- pc_point_set_double_by_index(&(fpdl->stats->min), i, stats.min);
- pc_point_set_double_by_index(&(fpdl->stats->max), i, stats.max);
- pc_point_set_double_by_index(&(fpdl->stats->avg), i, stats.sum/fpdl->npoints);
+ pc_point_set_double_by_index(&(fpdl->stats->min), i, stats.min);
+ pc_point_set_double_by_index(&(fpdl->stats->max), i, stats.max);
+ pc_point_set_double_by_index(&(fpdl->stats->avg), i, stats.sum/fpdl->npoints);
}
return fpdl;
diff --git a/lib/pc_patch_dimensional.c b/lib/pc_patch_dimensional.c
index 4e3e579f..43148341 100644
--- a/lib/pc_patch_dimensional.c
+++ b/lib/pc_patch_dimensional.c
@@ -17,13 +17,13 @@
/*
typedef struct
{
- int type;
+ int type;
int8_t readonly;
const PCSCHEMA *schema;
uint32_t npoints;
- double xmin, xmax, ymin, ymax;
+ double xmin, xmax, ymin, ymax, zmin, zmax, mmin, mmax;
PCSTATS *stats;
- PCBYTES *bytes;
+ PCBYTES *bytes;
} PCPATCH_DIMENSIONAL;
*/
@@ -179,7 +179,7 @@ pc_patch_dimensional_free(PCPATCH_DIMENSIONAL *pdl)
int
pc_patch_dimensional_compute_extent(PCPATCH_DIMENSIONAL *pdl)
{
- double xmin, xmax, ymin, ymax, xavg, yavg;
+ double min, max, avg;
int rv;
PCBYTES *pcb;
@@ -187,22 +187,44 @@ pc_patch_dimensional_compute_extent(PCPATCH_DIMENSIONAL *pdl)
assert(pdl->schema);
/* Get x extremes */
- pcb = &(pdl->bytes[pdl->schema->x_position]);
- rv = pc_bytes_minmax(pcb, &xmin, &xmax, &xavg);
- if ( PC_FAILURE == rv ) return PC_FAILURE;
- xmin = pc_value_scale_offset(xmin, pdl->schema->dims[pdl->schema->x_position]);
- xmax = pc_value_scale_offset(xmax, pdl->schema->dims[pdl->schema->x_position]);
- pdl->bounds.xmin = xmin;
- pdl->bounds.xmax = xmax;
+ if(pdl->schema->x_position!=-1)
+ {
+ pcb = &(pdl->bytes[pdl->schema->x_position]);
+ rv = pc_bytes_minmax(pcb, &min, &max, &avg);
+ if ( PC_FAILURE == rv ) return PC_FAILURE;
+ pdl->bounds.xmin = pc_value_scale_offset(min, pdl->schema->dims[pdl->schema->x_position]);
+ pdl->bounds.xmax = pc_value_scale_offset(max, pdl->schema->dims[pdl->schema->x_position]);
+ }
/* Get y extremes */
- pcb = &(pdl->bytes[pdl->schema->y_position]);
- rv = pc_bytes_minmax(pcb, &ymin, &ymax, &yavg);
- if ( PC_FAILURE == rv ) return PC_FAILURE;
- ymin = pc_value_scale_offset(ymin, pdl->schema->dims[pdl->schema->y_position]);
- ymax = pc_value_scale_offset(ymax, pdl->schema->dims[pdl->schema->y_position]);
- pdl->bounds.ymin = ymin;
- pdl->bounds.ymax = ymax;
+ if(pdl->schema->y_position!=-1)
+ {
+ pcb = &(pdl->bytes[pdl->schema->y_position]);
+ rv = pc_bytes_minmax(pcb, &min, &max, &avg);
+ if ( PC_FAILURE == rv ) return PC_FAILURE;
+ pdl->bounds.ymin = pc_value_scale_offset(min, pdl->schema->dims[pdl->schema->y_position]);
+ pdl->bounds.ymax = pc_value_scale_offset(max, pdl->schema->dims[pdl->schema->y_position]);
+ }
+
+ /* Get z extremes */
+ if(pdl->schema->z_position!=-1)
+ {
+ pcb = &(pdl->bytes[pdl->schema->z_position]);
+ rv = pc_bytes_minmax(pcb, &min, &max, &avg);
+ if ( PC_FAILURE == rv ) return PC_FAILURE;
+ pdl->bounds.zmin = pc_value_scale_offset(min, pdl->schema->dims[pdl->schema->z_position]);
+ pdl->bounds.zmax = pc_value_scale_offset(max, pdl->schema->dims[pdl->schema->z_position]);
+ }
+
+ /* Get m extremes */
+ if(pdl->schema->m_position!=-1)
+ {
+ pcb = &(pdl->bytes[pdl->schema->m_position]);
+ rv = pc_bytes_minmax(pcb, &min, &max, &avg);
+ if ( PC_FAILURE == rv ) return PC_FAILURE;
+ pdl->bounds.mmin = pc_value_scale_offset(min, pdl->schema->dims[pdl->schema->m_position]);
+ pdl->bounds.mmax = pc_value_scale_offset(max, pdl->schema->dims[pdl->schema->m_position]);
+ }
return PC_SUCCESS;
}
@@ -307,17 +329,17 @@ pc_patch_dimensional_from_pointlist(const PCPOINTLIST *pdl)
/** get point n, 0-based, positive */
PCPOINT *pc_patch_dimensional_pointn(const PCPATCH_DIMENSIONAL *pdl, int n)
{
- assert(pdl);
- assert(pdl->schema);
- int i;
- int ndims = pdl->schema->ndims;
- PCPOINT *pt = pc_point_make(pdl->schema);
- uint8_t *buf = pt->data;
- for ( i = 0; i < ndims; i++ )
- {
- PCDIMENSION *dim = pc_schema_get_dimension(pdl->schema, i);
- pc_bytes_to_ptr(buf+dim->byteoffset,pdl->bytes[i], n);
- }
-
- return pt;
+ assert(pdl);
+ assert(pdl->schema);
+ int i;
+ int ndims = pdl->schema->ndims;
+ PCPOINT *pt = pc_point_make(pdl->schema);
+ uint8_t *buf = pt->data;
+ for ( i = 0; i < ndims; i++ )
+ {
+ PCDIMENSION *dim = pc_schema_get_dimension(pdl->schema, i);
+ pc_bytes_to_ptr(buf+dim->byteoffset,pdl->bytes[i], n);
+ }
+
+ return pt;
}
diff --git a/lib/pc_patch_uncompressed.c b/lib/pc_patch_uncompressed.c
index 9c437201..040e151b 100644
--- a/lib/pc_patch_uncompressed.c
+++ b/lib/pc_patch_uncompressed.c
@@ -57,13 +57,13 @@ pc_patch_uncompressed_to_stringbuffer(const PCPATCH_UNCOMPRESSED *patch, stringb
char *
pc_patch_uncompressed_to_string(const PCPATCH_UNCOMPRESSED *patch)
{
- stringbuffer_t *sb = stringbuffer_create();
- char *str;
- if ( PC_FAILURE == pc_patch_uncompressed_to_stringbuffer(patch, sb) )
- return NULL;
- str = stringbuffer_release_string(sb);
- stringbuffer_destroy(sb);
- return str;
+ stringbuffer_t *sb = stringbuffer_create();
+ char *str;
+ if ( PC_FAILURE == pc_patch_uncompressed_to_stringbuffer(patch, sb) )
+ return NULL;
+ str = stringbuffer_release_string(sb);
+ stringbuffer_destroy(sb);
+ return str;
}
uint8_t *
@@ -175,10 +175,10 @@ pc_patch_uncompressed_make(const PCSCHEMA *s, uint32_t maxpoints)
/* Make our own data area */
datasize = s->size * maxpoints;
pch->datasize = datasize;
- pch->data = NULL;
+ pch->data = NULL;
if ( datasize )
{
- pch->data = pcalloc(datasize);
+ pch->data = pcalloc(datasize);
}
pc_bounds_init(&(pch->bounds));
@@ -191,7 +191,7 @@ pc_patch_uncompressed_compute_extent(PCPATCH_UNCOMPRESSED *patch)
int i;
PCPOINT *pt = pc_point_from_data(patch->schema, patch->data);
PCBOUNDS b;
- double x, y;
+ double v;
/* Calculate bounds */
pc_bounds_init(&b);
@@ -199,12 +199,26 @@ pc_patch_uncompressed_compute_extent(PCPATCH_UNCOMPRESSED *patch)
{
/* Just push the data buffer forward by one point at a time */
pt->data = patch->data + i * patch->schema->size;
- x = pc_point_get_x(pt);
- y = pc_point_get_y(pt);
- if ( b.xmin > x ) b.xmin = x;
- if ( b.ymin > y ) b.ymin = y;
- if ( b.xmax < x ) b.xmax = x;
- if ( b.ymax < y ) b.ymax = y;
+ if ( patch->schema->x_position > -1 ) {
+ v = pc_point_get_x(pt);
+ if ( b.xmin > v ) b.xmin = v;
+ if ( b.xmax < v ) b.xmax = v;
+ }
+ if ( patch->schema->y_position > -1 ) {
+ v = pc_point_get_y(pt);
+ if ( b.ymin > v ) b.ymin = v;
+ if ( b.ymax < v ) b.ymax = v;
+ }
+ if ( patch->schema->z_position > -1 ) {
+ v = pc_point_get_z(pt);
+ if ( b.zmin > v ) b.zmin = v;
+ if ( b.zmax < v ) b.zmax = v;
+ }
+ if ( patch->schema->m_position > -1 ) {
+ v = pc_point_get_m(pt);
+ if ( b.mmin > v ) b.mmin = v;
+ if ( b.mmax < v ) b.mmax = v;
+ }
}
patch->bounds = b;
@@ -336,7 +350,7 @@ pc_patch_uncompressed_from_dimensional(const PCPATCH_DIMENSIONAL *pdl)
patch->npoints = npoints;
patch->maxpoints = npoints;
patch->bounds = pdl->bounds;
- patch->stats = pc_stats_clone(pdl->stats);
+ patch->stats = pc_stats_clone(pdl->stats);
patch->datasize = schema->size * pdl->npoints;
patch->data = pcalloc(patch->datasize);
buf = patch->data;
diff --git a/lib/pc_point.c b/lib/pc_point.c
index 043fb334..1c62da52 100644
--- a/lib/pc_point.c
+++ b/lib/pc_point.c
@@ -154,6 +154,22 @@ pc_point_get_y(const PCPOINT *pt)
return d;
}
+double
+pc_point_get_z(const PCPOINT *pt)
+{
+ double d;
+ pc_point_get_double_by_index(pt, pt->schema->z_position, &d);
+ return d;
+}
+
+double
+pc_point_get_m(const PCPOINT *pt)
+{
+ double d;
+ pc_point_get_double_by_index(pt, pt->schema->m_position, &d);
+ return d;
+}
+
double
pc_point_set_x(PCPOINT *pt, double val)
{
@@ -166,6 +182,18 @@ pc_point_set_y(PCPOINT *pt, double val)
return pc_point_set_double_by_index(pt, pt->schema->y_position, val);
}
+double
+pc_point_set_z(PCPOINT *pt, double val)
+{
+ return pc_point_set_double_by_index(pt, pt->schema->z_position, val);
+}
+
+double
+pc_point_set_m(PCPOINT *pt, double val)
+{
+ return pc_point_set_double_by_index(pt, pt->schema->m_position, val);
+}
+
char *
pc_point_to_string(const PCPOINT *pt)
{
@@ -293,32 +321,36 @@ uint8_t *
pc_point_to_geometry_wkb(const PCPOINT *pt, size_t *wkbsize)
{
static uint32_t srid_mask = 0x20000000;
- static uint32_t z_mask = 0x80000000;
+ static uint32_t m_mask = 0x40000000;
+ static uint32_t z_mask = 0x80000000;
uint32_t wkbtype = 1; /* WKB POINT */
size_t size = 1 + 4 + 8 + 8; /* endian + type + dblX, + dblY */
uint8_t *wkb, *ptr;
uint32_t srid;
- int has_srid = PC_FALSE, has_z = PC_FALSE;
- double x, y, z;
+ double x, y, z, m;
- x = pc_point_get_x(pt);
- y = pc_point_get_y(pt);
+ if (pt->schema->x_position < 0 || pt->schema->y_position < 0 )
+ return NULL;
- if ( pt->schema->srid > 0 )
+ if ( pt->schema->z_position > -1 )
{
- has_srid = PC_TRUE;
- wkbtype |= srid_mask;
- size += 4;
- srid = pt->schema->srid;
+ wkbtype |= z_mask;
+ size += 8;
}
- if ( pc_point_get_double_by_name(pt, "Z", &z) )
+ if ( pt->schema->m_position > -1 )
{
- has_z = PC_TRUE;
- wkbtype |= z_mask;
+ wkbtype |= m_mask;
size += 8;
}
+ if ( pt->schema->srid != 0 )
+ {
+ wkbtype |= srid_mask;
+ size += 4;
+ }
+
+
wkb = pcalloc(size);
ptr = wkb;
@@ -328,24 +360,35 @@ pc_point_to_geometry_wkb(const PCPOINT *pt, size_t *wkbsize)
memcpy(ptr, &wkbtype, 4); /* WKB type */
ptr += 4;
- if ( has_srid )
+ if ( pt->schema->srid != 0 )
{
+ srid = pt->schema->srid;
memcpy(ptr, &srid, 4); /* SRID */
ptr += 4;
}
+ x = pc_point_get_x(pt);
memcpy(ptr, &x, 8); /* X */
ptr += 8;
+ y = pc_point_get_y(pt);
memcpy(ptr, &y, 8); /* Y */
ptr += 8;
- if ( has_z )
+ if ( pt->schema->z_position > -1 )
{
+ z = pc_point_get_z(pt);
memcpy(ptr, &z, 8); /* Z */
ptr += 8;
}
+ if ( pt->schema->m_position > -1 )
+ {
+ m = pc_point_get_m(pt);
+ memcpy(ptr, &m, 8); /* M */
+ ptr += 8;
+ }
+
if ( wkbsize ) *wkbsize = size;
return wkb;
}
diff --git a/lib/pc_schema.c b/lib/pc_schema.c
index 2384f2bc..02352146 100644
--- a/lib/pc_schema.c
+++ b/lib/pc_schema.c
@@ -198,6 +198,8 @@ pc_schema_new(uint32_t ndims)
pcs->ndims = ndims;
pcs->x_position = -1;
pcs->y_position = -1;
+ pcs->z_position = -1;
+ pcs->m_position = -1;
return pcs;
}
@@ -237,6 +239,8 @@ pc_schema_clone(const PCSCHEMA *s)
pcs->srid = s->srid;
pcs->x_position = s->x_position;
pcs->y_position = s->y_position;
+ pcs->z_position = s->z_position;
+ pcs->m_position = s->m_position;
pcs->compression = s->compression;
for ( i = 0; i < pcs->ndims; i++ )
{
@@ -326,7 +330,7 @@ pc_schema_to_json(const PCSCHEMA *pcs)
return str;
}
-void pc_schema_check_xy(PCSCHEMA *s)
+void pc_schema_check_xyzm(PCSCHEMA *s)
{
int i;
for ( i = 0; i < s->ndims; i++ )
@@ -334,34 +338,49 @@ void pc_schema_check_xy(PCSCHEMA *s)
char *dimname = s->dims[i]->name;
if ( ! dimname ) continue;
if ( strcasecmp(dimname, "X") == 0 ||
- strcasecmp(dimname, "Longitude") == 0 ||
- strcasecmp(dimname, "Lon") == 0 )
+ strcasecmp(dimname, "Longitude") == 0 ||
+ strcasecmp(dimname, "Lon") == 0 )
{
s->x_position = i;
continue;
}
if ( strcasecmp(dimname, "Y") == 0 ||
- strcasecmp(dimname, "Latitude") == 0 ||
- strcasecmp(dimname, "Lat") == 0 )
+ strcasecmp(dimname, "Latitude") == 0 ||
+ strcasecmp(dimname, "Lat") == 0 )
{
s->y_position = i;
continue;
}
+ if ( strcasecmp(dimname, "Z") == 0 ||
+ strcasecmp(dimname, "H") == 0 ||
+ strcasecmp(dimname, "Height") == 0 )
+ {
+ s->z_position = i;
+ continue;
+ }
+ if ( strcasecmp(dimname, "M") == 0 ||
+ strcasecmp(dimname, "T") == 0 ||
+ strcasecmp(dimname, "Time") == 0 )
+ {
+ s->m_position = i;
+ continue;
+ }
}
if ( s->x_position < 0 )
{
- pcerror("pc_schema_check_xy: invalid x_position '%d'", s->x_position);
+ pcerror("pc_schema_check_xyzm: invalid x_position '%d'", s->x_position);
return;
}
if ( s->y_position < 0 )
{
- pcerror("pc_schema_check_xy: invalid y_position '%d'", s->y_position);
+ pcerror("pc_schema_check_xyzm: invalid y_position '%d'", s->y_position);
return;
}
}
+
static char *
xml_node_get_content(xmlNodePtr node)
{
@@ -461,7 +480,6 @@ pc_schema_from_xml(const char *xml_str, PCSCHEMA **schema)
xmlNodePtr cur = nodes->nodeTab[i];
xmlNodePtr child;
PCDIMENSION *d = pc_dimension_new();
- char xydim = 0;
/* These are the values of the dimension */
for ( child = cur->children; child; child = child->next )
@@ -471,21 +489,7 @@ pc_schema_from_xml(const char *xml_str, PCSCHEMA **schema)
char *content = (char*)(child->children->content);
char *name = (char*)(child->name);
if ( strcmp(name, "name") == 0 )
- {
- if ( strcasecmp(content, "X") == 0 ||
- strcasecmp(content, "Longitude") == 0 ||
- strcasecmp(content, "Lon") == 0 )
- {
- xydim = 'x';
- }
- if ( strcasecmp(content, "Y") == 0 ||
- strcasecmp(content, "Latitude") == 0 ||
- strcasecmp(content, "Lat") == 0 )
- {
- xydim = 'y';
- }
d->name = pcstrdup(content);
- }
else if ( strcmp(name, "description") == 0 )
d->description = pcstrdup(content);
else if ( strcmp(name, "size") == 0 )
@@ -520,19 +524,11 @@ pc_schema_from_xml(const char *xml_str, PCSCHEMA **schema)
xmlXPathFreeObject(xpath_obj);
xmlXPathFreeContext(xpath_ctx);
xmlFreeDoc(xml_doc);
- xmlCleanupParser();
+ xmlCleanupParser();
pc_schema_free(s);
pcwarn("schema dimension at position \"%d\" is declared twice", d->position + 1, ndims);
return PC_FAILURE;
}
- if ( xydim == 'x' )
- {
- s->x_position = d->position;
- }
- if ( xydim == 'y' )
- {
- s->y_position = d->position;
- }
pc_schema_set_dimension(s, d);
}
else
@@ -541,7 +537,7 @@ pc_schema_from_xml(const char *xml_str, PCSCHEMA **schema)
xmlXPathFreeContext(xpath_ctx);
xmlFreeDoc(xml_doc);
xmlCleanupParser();
- pc_schema_free(s);
+ pc_schema_free(s);
pcwarn("schema dimension states position \"%d\", but number of XML dimensions is \"%d\"", d->position + 1, ndims);
return PC_FAILURE;
}
@@ -551,7 +547,7 @@ pc_schema_from_xml(const char *xml_str, PCSCHEMA **schema)
/* Complete the byte offsets of dimensions from the ordered sizes */
pc_schema_calculate_byteoffsets(s);
/* Check X/Y positions */
- pc_schema_check_xy(s);
+ pc_schema_check_xyzm(s);
}
xmlXPathFreeObject(xpath_obj);
diff --git a/lib/pc_util.c b/lib/pc_util.c
index a6a2c055..ba65e9f4 100644
--- a/lib/pc_util.c
+++ b/lib/pc_util.c
@@ -100,8 +100,8 @@ machine_endian(void)
{
static int check_int = 1; /* dont modify this!!! */
return *((char *) &check_int); /* 0 = big endian | xdr,
- * 1 = little endian | ndr
- */
+ * 1 = little endian | ndr
+ */
}
int32_t
@@ -239,9 +239,13 @@ int
pc_bounds_intersects(const PCBOUNDS *b1, const PCBOUNDS *b2)
{
if ( b1->xmin > b2->xmax ||
- b1->xmax < b2->xmin ||
- b1->ymin > b2->ymax ||
- b1->ymax < b2->ymin )
+ b1->xmax < b2->xmin ||
+ b1->ymin > b2->ymax ||
+ b1->ymax < b2->ymin ||
+ b1->zmin > b2->zmax ||
+ b1->zmax < b2->zmin ||
+ b1->mmin > b2->mmax ||
+ b1->mmax < b2->mmin )
{
return PC_FALSE;
}
@@ -251,15 +255,131 @@ pc_bounds_intersects(const PCBOUNDS *b1, const PCBOUNDS *b2)
void
pc_bounds_init(PCBOUNDS *b)
{
- b->xmin = b->ymin = DBL_MAX;
- b->xmax = b->ymax = -1*DBL_MAX;
+ b->xmin = b->ymin = b->zmin = b->mmin = DBL_MAX;
+ b->xmax = b->ymax = b->zmax = b->mmax = -1*DBL_MAX;
}
void pc_bounds_merge(PCBOUNDS *b1, const PCBOUNDS *b2)
{
if ( b2->xmin < b1->xmin ) b1->xmin = b2->xmin;
if ( b2->ymin < b1->ymin ) b1->ymin = b2->ymin;
+ if ( b2->zmin < b1->zmin ) b1->zmin = b2->zmin;
+ if ( b2->mmin < b1->mmin ) b1->mmin = b2->mmin;
if ( b2->xmax > b1->xmax ) b1->xmax = b2->xmax;
if ( b2->ymax > b1->ymax ) b1->ymax = b2->ymax;
+ if ( b2->zmax > b1->zmax ) b1->zmax = b2->zmax;
+ if ( b2->mmax > b1->mmax ) b1->mmax = b2->mmax;
}
+
+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_geometry_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;
+}
+
+PCBOX3D *
+pc_bounds_to_box3d(const PCBOUNDS *bounds, uint32_t srid)
+{
+ PCBOX3D *box = (PCBOX3D *) pcalloc(sizeof(PCBOX3D));
+ box->xmin = bounds->xmin;
+ box->ymin = bounds->ymin;
+ box->zmin = bounds->zmin;
+ box->xmax = bounds->xmax;
+ box->ymax = bounds->ymax;
+ box->zmax = bounds->zmax;
+ box->srid = srid;
+ return box;
+}
diff --git a/pgsql/CMakeLists.txt b/pgsql/CMakeLists.txt
index ffe2e2a7..0eff01c2 100644
--- a/pgsql/CMakeLists.txt
+++ b/pgsql/CMakeLists.txt
@@ -10,7 +10,7 @@ set ( PC_HEADERS
pc_pgsql.h
)
-set ( PC_INSTALL_EXENSIONS
+set ( PC_INSTALL_EXTENSIONS
"${PROJECT_BINARY_DIR}/pgsql/pointcloud--${POINTCLOUD_VERSION}.sql"
"${PROJECT_BINARY_DIR}/pgsql/pointcloud.control"
)
@@ -64,7 +64,7 @@ install (
)
install (
- FILES ${PC_INSTALL_EXENSIONS}
+ FILES ${PC_INSTALL_EXTENSIONS}
DESTINATION "${PGSQL_SHAREDIR}/extension"
)
diff --git a/pgsql/Makefile b/pgsql/Makefile
index eba5329e..a9d32ae5 100644
--- a/pgsql/Makefile
+++ b/pgsql/Makefile
@@ -56,4 +56,4 @@ $(EXTENSION)--%--$(EXTVERSION).sql: $(EXTENSION)--$(EXTVERSION).sql ../util/proc
cat $< | ../util/proc_upgrade.pl > $@
$(EXTENSION)--%--$(EXTVERSION)next.sql: $(EXTENSION)--$(EXTVERSION)next--$(EXTVERSION).sql
- ln -f $< $@
+ cp $< $@
diff --git a/pgsql/expected/pointcloud-ght.out b/pgsql/expected/pointcloud-ght.out
index 06ea485b..172adcc4 100644
--- a/pgsql/expected/pointcloud-ght.out
+++ b/pgsql/expected/pointcloud-ght.out
@@ -62,7 +62,7 @@ SELECT Sum(PC_NumPoints(pa)) FROM pa_test_ght;
SELECT Sum(PC_MemSize(pa)) FROM pa_test_ght;
sum
-----
- 582
+ 710
(1 row)
SELECT Sum(PC_PatchMax(pa,'x')) FROM pa_test_ght;
@@ -98,7 +98,7 @@ SELECT Sum(PC_NumPoints(pa)) FROM pa_test_ght;
SELECT Sum(PC_MemSize(pa)) FROM pa_test_ght;
sum
-------
- 38681
+ 38809
(1 row)
SELECT Max(PC_PatchMax(pa,'x')) FROM pa_test_ght;
diff --git a/pgsql/expected/pointcloud-laz.out b/pgsql/expected/pointcloud-laz.out
index ccc9bece..46d35fb2 100644
--- a/pgsql/expected/pointcloud-laz.out
+++ b/pgsql/expected/pointcloud-laz.out
@@ -96,7 +96,7 @@ SELECT Sum(PC_NumPoints(pa)) FROM pa_test_laz;
SELECT Sum(PC_MemSize(pa)) FROM pa_test_laz;
sum
-----
- 487
+ 615
(1 row)
SELECT Sum(PC_PatchMax(pa,'x')) FROM pa_test_laz;
@@ -192,7 +192,7 @@ SELECT Sum(PC_NumPoints(pa)) FROM pa_test_laz;
SELECT Sum(PC_MemSize(pa)) FROM pa_test_laz;
sum
------
- 1499
+ 1659
(1 row)
SELECT Max(PC_PatchMax(pa,'x')) FROM pa_test_laz;
diff --git a/pgsql/expected/pointcloud.out b/pgsql/expected/pointcloud.out
index 4fa56e28..53c4621f 100644
--- a/pgsql/expected/pointcloud.out
+++ b/pgsql/expected/pointcloud.out
@@ -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
@@ -334,7 +334,7 @@ SELECT Sum(PC_NumPoints(pa)) FROM pa_test_dim;
SELECT Sum(PC_MemSize(pa)) FROM pa_test_dim;
sum
-----
- 684
+ 812
(1 row)
SELECT Sum(PC_PatchMax(pa,'x')) FROM pa_test_dim;
@@ -370,7 +370,7 @@ SELECT Sum(PC_NumPoints(pa)) FROM pa_test_dim;
SELECT Sum(PC_MemSize(pa)) FROM pa_test_dim;
sum
------
- 8733
+ 8893
(1 row)
SELECT Max(PC_PatchMax(pa,'x')) FROM pa_test_dim;
diff --git a/pgsql/pc_inout.c b/pgsql/pc_inout.c
index eeb5ae05..035fee0b 100644
--- a/pgsql/pc_inout.c
+++ b/pgsql/pc_inout.c
@@ -31,7 +31,8 @@ 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);
+Datum pcpatch_box3d(PG_FUNCTION_ARGS);
static void
@@ -293,8 +294,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;
@@ -303,17 +304,27 @@ 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_geometry_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);
}
+PG_FUNCTION_INFO_V1(pcpatch_box3d);
+Datum pcpatch_box3d(PG_FUNCTION_ARGS)
+{
+ SERIALIZED_PATCH *serpatch = PG_GETHEADER_SERPATCH_P(0);
+ PCSCHEMA *schema = pc_schema_from_pcid(serpatch->pcid, fcinfo);
+ PCBOX3D *box = pc_bounds_to_box3d(&serpatch->bounds, schema->srid);
+ PG_RETURN_POINTER(box);
+}
+
+
PG_FUNCTION_INFO_V1(pc_typmod_in);
Datum pc_typmod_in(PG_FUNCTION_ARGS)
{
diff --git a/pgsql/pc_pgsql.c b/pgsql/pc_pgsql.c
index 2749f6b1..23206c19 100644
--- a/pgsql/pc_pgsql.c
+++ b/pgsql/pc_pgsql.c
@@ -993,103 +993,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;
-}
diff --git a/pgsql/pointcloud.sql.in b/pgsql/pointcloud.sql.in
index 2208a588..c3e0d582 100644
--- a/pgsql/pointcloud.sql.in
+++ b/pgsql/pointcloud.sql.in
@@ -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)
diff --git a/pgsql/sql/pointcloud.sql b/pgsql/sql/pointcloud.sql
index a0669abc..32050043 100644
--- a/pgsql/sql/pointcloud.sql
+++ b/pgsql/sql/pointcloud.sql
@@ -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;
diff --git a/pgsql_postgis/CMakeLists.txt b/pgsql_postgis/CMakeLists.txt
index 6796ca4f..68dd877c 100644
--- a/pgsql_postgis/CMakeLists.txt
+++ b/pgsql_postgis/CMakeLists.txt
@@ -1,11 +1,21 @@
-set ( PCPG_INSTALL_EXENSIONS
- pointcloud_postgis--1.0.sql
- pointcloud_postgis.control
+configure_file(
+ pointcloud_postgis.sql.in
+ "${PROJECT_BINARY_DIR}/pgsql/pointcloud_postgis--${POINTCLOUD_VERSION}.sql"
)
-
+
+configure_file(
+ pointcloud_postgis.control.in
+ "${PROJECT_BINARY_DIR}/pgsql/pointcloud_postgis.control"
+ )
+
+set ( PCPG_INSTALL_EXTENSIONS
+ "${PROJECT_BINARY_DIR}/pgsql/pointcloud_postgis--${POINTCLOUD_VERSION}.sql"
+ "${PROJECT_BINARY_DIR}/pgsql/pointcloud_postgis.control"
+ )
+
install (
- FILES ${PCPG_INSTALL_EXENSIONS}
+ FILES ${PCPG_INSTALL_EXTENSIONS}
DESTINATION "${PGSQL_SHAREDIR}/extension"
)
diff --git a/pgsql_postgis/Makefile b/pgsql_postgis/Makefile
index 8f17bf99..e3637585 100644
--- a/pgsql_postgis/Makefile
+++ b/pgsql_postgis/Makefile
@@ -4,8 +4,11 @@ include ../config.mk
#MODULE_big = pointcloud_postgis
#OBJS =
+SED = sed
EXTENSION = pointcloud_postgis
-DATA = $(EXTENSION)--1.0.sql
+EXTVERSION=$(shell cat ../Version.config)
+EXTVERSION_MAJOR=$(shell cut -d. -f1,2 ../Version.config)
+DATA = $(EXTENSION)--$(EXTVERSION).sql
#REGRESS = pointcloud
@@ -15,3 +18,10 @@ DATA = $(EXTENSION)--1.0.sql
# We are going to use PGXS for sure
include $(PGXS)
+
+$(EXTENSION).control: $(EXTENSION).control.in Makefile
+ $(SED) -e 's/@POINTCLOUD_VERSION@/$(EXTVERSION)/' \
+ -e 's/@POINTCLOUD_VERSION_MAJOR@/$(EXTVERSION_MAJOR)/' $< > $@
+
+$(EXTENSION)--$(EXTVERSION).sql: $(EXTENSION).sql.in Makefile
+ $(SED) -e 's/@POINTCLOUD_VERSION@/$(EXTVERSION)/' $< > $@
diff --git a/pgsql_postgis/pointcloud_postgis--1.0.sql b/pgsql_postgis/pointcloud_postgis--1.0.sql
index 872d1365..7641d70e 100644
--- a/pgsql_postgis/pointcloud_postgis--1.0.sql
+++ b/pgsql_postgis/pointcloud_postgis--1.0.sql
@@ -10,20 +10,20 @@ CREATE OR REPLACE FUNCTION PC_Intersection(pcpatch, geometry)
ipts AS (SELECT pt FROM pgpts WHERE ST_Intersects(pgpt, $2)),
ipch AS (SELECT PC_Patch(pt) AS pch FROM ipts)
SELECT pch FROM ipch;
- $$
+ $$
LANGUAGE 'sql';
-----------------------------------------------------------------------------
-- 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
@@ -32,7 +32,7 @@ CREATE OR REPLACE FUNCTION geometry(pcpoint)
RETURNS geometry AS
$$
SELECT ST_GeomFromEWKB(PC_AsBinary($1))
- $$
+ $$
LANGUAGE 'sql';
CREATE CAST (pcpoint AS geometry) WITH FUNCTION geometry(pcpoint);
@@ -44,14 +44,22 @@ 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';
CREATE OR REPLACE FUNCTION PC_Intersects(geometry, pcpatch)
RETURNS boolean AS
$$
SELECT PC_Intersects($2, $1)
- $$
+ $$
LANGUAGE 'sql';
+-----------------------------------------------------------------------------
+-- Cast a pcpatch as a box3d
+--
+CREATE OR REPLACE FUNCTION Box3D(p pcpatch)
+ RETURNS BOX3D AS 'MODULE_PATHNAME', 'pcpatch_box3d'
+ LANGUAGE 'c' IMMUTABLE STRICT;
+
+CREATE CAST (pcpatch AS BOX3D) WITH FUNCTION Box3D(pcpatch);
diff --git a/pgsql_postgis/pointcloud_postgis.control b/pgsql_postgis/pointcloud_postgis.control
index 01431da0..d9afe4ce 100644
--- a/pgsql_postgis/pointcloud_postgis.control
+++ b/pgsql_postgis/pointcloud_postgis.control
@@ -1,6 +1,7 @@
# pointcloud postgis integration extension
comment = 'integration for pointcloud LIDAR data and PostGIS geometry data'
-default_version = '1.0'
+default_version = '1.1.0'
+module_pathname = '$libdir/pointcloud-1.1'
relocatable = true
superuser = false
requires = 'postgis, pointcloud'
diff --git a/pgsql_postgis/pointcloud_postgis.control.in b/pgsql_postgis/pointcloud_postgis.control.in
new file mode 100644
index 00000000..925afc07
--- /dev/null
+++ b/pgsql_postgis/pointcloud_postgis.control.in
@@ -0,0 +1,7 @@
+# pointcloud postgis integration extension
+comment = 'integration for pointcloud LIDAR data and PostGIS geometry data'
+default_version = '@POINTCLOUD_VERSION@'
+module_pathname = '$libdir/pointcloud-@POINTCLOUD_VERSION_MAJOR@'
+relocatable = true
+superuser = false
+requires = 'postgis, pointcloud'
diff --git a/pgsql_postgis/pointcloud_postgis.sql.in b/pgsql_postgis/pointcloud_postgis.sql.in
new file mode 100644
index 00000000..d621ea7e
--- /dev/null
+++ b/pgsql_postgis/pointcloud_postgis.sql.in
@@ -0,0 +1,65 @@
+-----------------------------------------------------------------------------
+-- Function to overlap polygon on patch
+--
+CREATE OR REPLACE FUNCTION PC_Intersection(pcpatch, geometry)
+ RETURNS pcpatch AS
+ $$
+ WITH
+ pts AS (SELECT PC_Explode($1) AS pt),
+ pgpts AS (SELECT ST_GeomFromEWKB(PC_AsBinary(pt)) AS pgpt, pt FROM pts),
+ ipts AS (SELECT pt FROM pgpts WHERE ST_Intersects(pgpt, $2)),
+ ipch AS (SELECT PC_Patch(pt) AS pch FROM ipts)
+ SELECT pch FROM ipch;
+ $$
+ LANGUAGE 'sql';
+
+-----------------------------------------------------------------------------
+-- Cast from pcpatch to polygon
+--
+CREATE OR REPLACE FUNCTION PC_Envelope(pcpatch)
+ RETURNS geometry AS
+ $$
+ SELECT ST_GeomFromEWKB(PC_Envelope_AsBinary($1))
+ $$
+ LANGUAGE 'sql';
+
+CREATE CAST (pcpatch AS geometry) WITH FUNCTION PC_Envelope(pcpatch);
+
+-----------------------------------------------------------------------------
+-- Cast from pcpoint to point
+--
+CREATE OR REPLACE FUNCTION geometry(pcpoint)
+ RETURNS geometry AS
+ $$
+ SELECT ST_GeomFromEWKB(PC_AsBinary($1))
+ $$
+ LANGUAGE 'sql';
+
+CREATE CAST (pcpoint AS geometry) WITH FUNCTION geometry(pcpoint);
+
+
+-----------------------------------------------------------------------------
+-- Function to overlap polygon on patch
+--
+CREATE OR REPLACE FUNCTION PC_Intersects(pcpatch, geometry)
+ RETURNS boolean AS
+ $$
+ SELECT ST_Intersects($2, PC_Envelope($1))
+ $$
+ LANGUAGE 'sql';
+
+CREATE OR REPLACE FUNCTION PC_Intersects(geometry, pcpatch)
+ RETURNS boolean AS
+ $$
+ SELECT PC_Intersects($2, $1)
+ $$
+ LANGUAGE 'sql';
+
+-----------------------------------------------------------------------------
+-- Cast a pcpatch as a box3d
+--
+CREATE OR REPLACE FUNCTION Box3D(p pcpatch)
+ RETURNS BOX3D AS 'MODULE_PATHNAME', 'pcpatch_box3d'
+ LANGUAGE 'c' IMMUTABLE STRICT;
+
+CREATE CAST (pcpatch AS BOX3D) WITH FUNCTION Box3D(pcpatch);