geometry cast of pcpoint with optional srid, z and m values, using caching of Z and M positions in schema.

This commit is contained in:
Mathieu Brédif 2017-02-13 13:02:46 +01:00 committed by Sandro Santilli
parent 9f19f32536
commit 165d9ea7be
4 changed files with 95 additions and 45 deletions

View File

@ -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 */

View File

@ -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);

View File

@ -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;
}

View File

@ -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);