diff --git a/lib/cunit/cu_pc_schema.c b/lib/cunit/cu_pc_schema.c index 15fbcf0..c09b7e1 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 0ae5f74..f5fe75e 100644 --- a/lib/pc_api.h +++ b/lib/pc_api.h @@ -88,8 +88,10 @@ typedef struct size_t size; /* How wide (bytes) is a point with this schema? */ PCDIMENSION **dims; /* Array of dimension pointers */ 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 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; @@ -283,8 +285,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); @@ -344,12 +346,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); diff --git a/lib/pc_point.c b/lib/pc_point.c index 353cc56..35d539a 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,32 @@ uint8_t * pc_point_to_geometry_wkb(const PCPOINT *pt, size_t *wkbsize) { static uint32_t srid_mask = 0x20000000; + 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; + uint32_t srid = pt->schema->srid; + double x, y, z, m; - x = pc_point_get_x(pt); - y = pc_point_get_y(pt); - - if ( pt->schema->srid > 0 ) + if ( srid != 0 ) { - has_srid = PC_TRUE; wkbtype |= srid_mask; size += 4; - srid = pt->schema->srid; } - if ( pc_point_get_double_by_name(pt, "Z", &z) ) + if ( pt->schema->z_position > -1 ) { - has_z = PC_TRUE; wkbtype |= z_mask; size += 8; } + if ( pt->schema->m_position > -1 ) + { + wkbtype |= m_mask; + size += 8; + } + wkb = pcalloc(size); ptr = wkb; @@ -328,24 +356,34 @@ pc_point_to_geometry_wkb(const PCPOINT *pt, size_t *wkbsize) memcpy(ptr, &wkbtype, 4); /* WKB type */ ptr += 4; - if ( has_srid ) + if ( srid != 0 ) { 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_z(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 5b97b2a..cc39046 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++ ) @@ -347,17 +351,32 @@ void pc_schema_check_xy(PCSCHEMA *s) 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 || + strcasecmp(dimname, "GPSTime") == 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; } } @@ -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 ) @@ -525,14 +529,6 @@ pc_schema_from_xml(const char *xml_str, PCSCHEMA **schema) 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 @@ -550,8 +546,8 @@ 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); + /* Check XYZM positions */ + pc_schema_check_xyzm(s); } xmlXPathFreeObject(xpath_obj);