diff --git a/lib/cunit/cu_pc_point.c b/lib/cunit/cu_pc_point.c index f0f311d..e5cc1e9 100644 --- a/lib/cunit/cu_pc_point.c +++ b/lib/cunit/cu_pc_point.c @@ -13,7 +13,15 @@ /* GLOBALS ************************************************************/ static PCSCHEMA *schema = NULL; -static const char *xmlfile = "data/simple-schema.xml"; +static PCSCHEMA *schema_xy = NULL; +static PCSCHEMA *schema_xyz = NULL; +static PCSCHEMA *schema_xym = NULL; +static PCSCHEMA *schema_xyzm = NULL; +static const char *xmlfile = "data/simple-schema.xml"; +static const char *xmlfile_xy = "data/simple-schema-xy.xml"; +static const char *xmlfile_xyz = "data/simple-schema-xyz.xml"; +static const char *xmlfile_xym = "data/simple-schema-xym.xml"; +static const char *xmlfile_xyzm = "data/simple-schema-xyzm.xml"; // SIMPLE SCHEMA // int32_t x @@ -25,10 +33,32 @@ static const char *xmlfile = "data/simple-schema.xml"; static int init_suite(void) { - char *xmlstr = file_to_str(xmlfile); + char *xmlstr; + + xmlstr = file_to_str(xmlfile); schema = pc_schema_from_xml(xmlstr); pcfree(xmlstr); if ( !schema ) return 1; + + xmlstr = file_to_str(xmlfile_xy); + schema_xy = pc_schema_from_xml(xmlstr); + pcfree(xmlstr); + if ( !schema_xy ) return 1; + + xmlstr = file_to_str(xmlfile_xyz); + schema_xyz = pc_schema_from_xml(xmlstr); + pcfree(xmlstr); + if ( !schema_xyz ) return 1; + + xmlstr = file_to_str(xmlfile_xym); + schema_xym = pc_schema_from_xml(xmlstr); + pcfree(xmlstr); + if ( !schema_xym ) return 1; + + xmlstr = file_to_str(xmlfile_xyzm); + schema_xyzm = pc_schema_from_xml(xmlstr); + pcfree(xmlstr); + if ( !schema_xyzm ) return 1; return 0; } @@ -36,6 +66,10 @@ static int clean_suite(void) { pc_schema_free(schema); + pc_schema_free(schema_xy); + pc_schema_free(schema_xyz); + pc_schema_free(schema_xym); + pc_schema_free(schema_xyzm); return 0; } @@ -54,14 +88,15 @@ test_point_hex_inout() size_t hexsize = strlen(hexbuf); uint8_t *wkb = bytes_from_hexbytes(hexbuf, hexsize); PCPOINT *pt = pc_point_from_wkb(schema, wkb, hexsize/2); - pc_point_get_double_by_name(pt, "X", &d); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "X", &d)); CU_ASSERT_DOUBLE_EQUAL(d, 0.01, 0.000001); - pc_point_get_double_by_name(pt, "Y", &d); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "Y", &d)); CU_ASSERT_DOUBLE_EQUAL(d, 0.02, 0.000001); - pc_point_get_double_by_name(pt, "Z", &d); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "Z", &d)); CU_ASSERT_DOUBLE_EQUAL(d, 0.03, 0.000001); - pc_point_get_double_by_name(pt, "Intensity", &d); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "Intensity", &d)); CU_ASSERT_DOUBLE_EQUAL(d, 4, 0.0001); + CU_ASSERT_FAILURE(pc_point_get_double_by_name(pt, "M", &d)); pc_point_free(pt); pcfree(wkb); @@ -69,14 +104,15 @@ test_point_hex_inout() hexsize = strlen(hexbuf); wkb = bytes_from_hexbytes(hexbuf, hexsize); pt = pc_point_from_wkb(schema, wkb, hexsize/2); - pc_point_get_double_by_name(pt, "X", &d); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "X", &d)); CU_ASSERT_DOUBLE_EQUAL(d, 0.01, 0.000001); - pc_point_get_double_by_name(pt, "Y", &d); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "Y", &d)); CU_ASSERT_DOUBLE_EQUAL(d, 0.02, 0.000001); - pc_point_get_double_by_name(pt, "Z", &d); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "Z", &d)); CU_ASSERT_DOUBLE_EQUAL(d, 0.03, 0.000001); - pc_point_get_double_by_name(pt, "Intensity", &d); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "Intensity", &d)); CU_ASSERT_DOUBLE_EQUAL(d, 5, 0.0001); + CU_ASSERT_FAILURE(pc_point_get_double_by_name(pt, "M", &d)); pc_point_free(pt); pcfree(wkb); @@ -91,25 +127,25 @@ test_point_access() double *allvals; pt = pc_point_make(schema); - CU_ASSERT( pt != NULL ); + CU_ASSERT_PTR_NOT_NULL( pt ); /* One at a time */ idx = 0; a1 = 1.5; - pc_point_set_double_by_index(pt, idx, a1); - pc_point_get_double_by_index(pt, idx, &b1); + CU_ASSERT_SUCCESS(pc_point_set_double_by_index(pt, idx, a1)); + CU_ASSERT_SUCCESS(pc_point_get_double_by_index(pt, idx, &b1)); // printf("d1=%g, d2=%g\n", a1, b1); CU_ASSERT_DOUBLE_EQUAL(a1, b1, 0.0000001); idx = 2; a2 = 1501500.12; - pc_point_set_double_by_index(pt, idx, a2); - pc_point_get_double_by_index(pt, idx, &b2); + CU_ASSERT_SUCCESS(pc_point_set_double_by_index(pt, idx, a2)); + CU_ASSERT_SUCCESS(pc_point_get_double_by_index(pt, idx, &b2)); CU_ASSERT_DOUBLE_EQUAL(a2, b2, 0.0000001); a3 = 91; - pc_point_set_double_by_name(pt, "Intensity", a3); - pc_point_get_double_by_name(pt, "Intensity", &b3); + CU_ASSERT_SUCCESS(pc_point_set_double_by_name(pt, "Intensity", a3)); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "Intensity", &b3)); CU_ASSERT_DOUBLE_EQUAL(a3, b3, 0.0000001); pc_point_free(pt); @@ -120,14 +156,14 @@ test_point_access() a2 = 1501500.12; a3 = 91; a4 = 200; - pc_point_set_double_by_index(pt, 0, a1); - pc_point_set_double_by_index(pt, 1, a2); - pc_point_set_double_by_name(pt, "Intensity", a3); - pc_point_set_double_by_name(pt, "Z", a4); - pc_point_get_double_by_index(pt, 0, &b1); - pc_point_get_double_by_index(pt, 1, &b2); - pc_point_get_double_by_name(pt, "Intensity", &b3); - pc_point_get_double_by_name(pt, "Z", &b4); + CU_ASSERT_SUCCESS(pc_point_set_double_by_index(pt, 0, a1)); + CU_ASSERT_SUCCESS(pc_point_set_double_by_index(pt, 1, a2)); + CU_ASSERT_SUCCESS(pc_point_set_double_by_name(pt, "Intensity", a3)); + CU_ASSERT_SUCCESS(pc_point_set_double_by_name(pt, "Z", a4)); + CU_ASSERT_SUCCESS(pc_point_get_double_by_index(pt, 0, &b1)); + CU_ASSERT_SUCCESS(pc_point_get_double_by_index(pt, 1, &b2)); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "Intensity", &b3)); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "Z", &b4)); CU_ASSERT_DOUBLE_EQUAL(a1, b1, 0.0000001); CU_ASSERT_DOUBLE_EQUAL(a2, b2, 0.0000001); CU_ASSERT_DOUBLE_EQUAL(a3, b3, 0.0000001); @@ -151,11 +187,145 @@ test_point_access() } +static void +test_point_xyzm() +{ + PCPOINT *pt; + double x = 1; + double y = 40; + double z = 160; + double m = 640; + double d; + + pt = pc_point_make(schema_xyz); + CU_ASSERT_PTR_NOT_NULL( pt ); + + CU_ASSERT_SUCCESS(pc_point_set_x(pt, x)); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "X", &d)); + CU_ASSERT_DOUBLE_EQUAL(d, x, 0.000001); + CU_ASSERT_SUCCESS(pc_point_get_x(pt, &d)); + CU_ASSERT_DOUBLE_EQUAL(d, x, 0.000001); + + CU_ASSERT_SUCCESS(pc_point_set_y(pt, y)); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "Y", &d)); + CU_ASSERT_DOUBLE_EQUAL(d, y, 0.000001); + CU_ASSERT_SUCCESS(pc_point_get_y(pt, &d)); + CU_ASSERT_DOUBLE_EQUAL(d, y, 0.000001); + + CU_ASSERT_SUCCESS(pc_point_set_z(pt, z)); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "Z", &d)); + CU_ASSERT_DOUBLE_EQUAL(d, z, 0.000001); + CU_ASSERT_SUCCESS(pc_point_get_z(pt, &d)); + CU_ASSERT_DOUBLE_EQUAL(d, z, 0.000001); + + CU_ASSERT_FAILURE(pc_point_set_m(pt, m)); + CU_ASSERT_FAILURE(pc_point_get_double_by_name(pt, "M", &d)); + CU_ASSERT_FAILURE(pc_point_get_m(pt, &d)); + + pc_point_free(pt); + + pt = pc_point_make(schema_xyzm); + CU_ASSERT_PTR_NOT_NULL( pt ); + + CU_ASSERT_SUCCESS(pc_point_set_x(pt, x)); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "X", &d)); + CU_ASSERT_DOUBLE_EQUAL(d, x, 0.000001); + CU_ASSERT_SUCCESS(pc_point_get_x(pt, &d)); + CU_ASSERT_DOUBLE_EQUAL(d, x, 0.000001); + + CU_ASSERT_SUCCESS(pc_point_set_y(pt, y)); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "Y", &d)); + CU_ASSERT_DOUBLE_EQUAL(d, y, 0.000001); + CU_ASSERT_SUCCESS(pc_point_get_y(pt, &d)); + CU_ASSERT_DOUBLE_EQUAL(d, y, 0.000001); + + CU_ASSERT_SUCCESS(pc_point_set_z(pt, z)); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "Z", &d)); + CU_ASSERT_DOUBLE_EQUAL(d, z, 0.000001); + CU_ASSERT_SUCCESS(pc_point_get_z(pt, &d)); + CU_ASSERT_DOUBLE_EQUAL(d, z, 0.000001); + + CU_ASSERT_SUCCESS(pc_point_set_m(pt, m)); + CU_ASSERT_SUCCESS(pc_point_get_double_by_name(pt, "M", &d)); + CU_ASSERT_DOUBLE_EQUAL(d, m, 0.000001); + CU_ASSERT_SUCCESS(pc_point_get_m(pt, &d)); + CU_ASSERT_DOUBLE_EQUAL(d, m, 0.000001); + + pc_point_free(pt); +} + +void test_point_geometry_bytes(const PCSCHEMA *s, size_t expectedgeomwkbsize, + const char *pthexbytes, const char *expectedgeomhexbytes) +{ + /* point + byte: endianness (1 = NDR, 0 = XDR) + uint32: pcid (key to POINTCLOUD_SCHEMAS) + uchar[]: data (interpret relative to pcid) + */ + + /* geometry + byte: endianness (1 = NDR, 0 = XDR) + uint32: point type (XYZ=01000080, XYM=01000040, XY=01000000, XYZM=010000C0) + double[]: XY(Z?)(M?) coordinates + */ + + PCPOINT *pt; + uint8_t *ptwkb, *geomwkb; + char *geomhexbytes; + size_t pthexsize, geomwkbsize; + + pthexsize = strlen(pthexbytes); + ptwkb = bytes_from_hexbytes(pthexbytes, pthexsize); + pt = pc_point_from_wkb(s, ptwkb, pthexsize/2); + CU_ASSERT_PTR_NOT_NULL(pt); + geomwkb = pc_point_to_geometry_wkb(pt, &geomwkbsize); + CU_ASSERT_EQUAL(geomwkbsize,expectedgeomwkbsize); + geomhexbytes = hexbytes_from_bytes(geomwkb,geomwkbsize); + CU_ASSERT_STRING_EQUAL(geomhexbytes, expectedgeomhexbytes); + + pcfree(geomhexbytes); + pcfree(geomwkb); + pc_point_free(pt); + pcfree(ptwkb); +} + + +static void +test_point_geometry() +{ + // pt XYI = 1 2 3, scale = 1 2 1, geom XY = 1 4 + test_point_geometry_bytes(schema_xy, 5+2*8, + "000000000100000001000000020003", + "0101000000000000000000F03F0000000000001040" + ); + + // pt XYZI = 1 2 3 4, scale = 1 2 4 1, geom XYZ = 1 2 3 + test_point_geometry_bytes(schema_xyz, 5+3*8, + "00000000010000000100000002000000030004", + "0101000080000000000000F03F00000000000010400000000000002840" + ); + + // pt XYMI = 1 2 3 4, scale = 1 2 4 1, geom XYM = 1 4 12 + test_point_geometry_bytes(schema_xym, 5+3*8, + "00000000010000000100000002000000030004", + "0101000040000000000000F03F00000000000010400000000000002840" + ); + + // pt XYZMI = 1 2 3 4 5, scale = 1 2 4 8 1, geom XYZM = 1 4 12 32 + test_point_geometry_bytes(schema_xyzm, 5+4*8, + "0000000001000000010000000200000003000000040005", + "01010000C0000000000000F03F000000000000104000000000000028400000000000004040" + ); + +} + /* REGISTER ***********************************************************/ CU_TestInfo point_tests[] = { PC_TEST(test_point_hex_inout), PC_TEST(test_point_access), + PC_TEST(test_point_xyzm), + PC_TEST(test_point_geometry), CU_TEST_INFO_NULL }; diff --git a/lib/cunit/cu_pc_schema.c b/lib/cunit/cu_pc_schema.c index 76abdd4..54034ad 100644 --- a/lib/cunit/cu_pc_schema.c +++ b/lib/cunit/cu_pc_schema.c @@ -201,13 +201,17 @@ test_schema_clone(void) CU_ASSERT_EQUAL(clone->ndims, schema->ndims); CU_ASSERT_EQUAL(clone->size, schema->size); 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->xdim->position, schema->xdim->position); + CU_ASSERT_EQUAL(clone->ydim->position, schema->ydim->position); + CU_ASSERT_EQUAL(clone->zdim->position, schema->zdim->position); + CU_ASSERT_EQUAL(clone->mdim->position, schema->mdim->position); CU_ASSERT_EQUAL(clone->compression, schema->compression); - CU_ASSERT(clone->dims != schema->dims); /* deep clone */ - CU_ASSERT(clone->namehash != schema->namehash); /* deep clone */ + CU_ASSERT_NOT_EQUAL(clone->xdim, schema->xdim); /* deep clone */ + CU_ASSERT_NOT_EQUAL(clone->ydim, schema->ydim); /* deep clone */ + CU_ASSERT_NOT_EQUAL(clone->zdim, schema->zdim); /* deep clone */ + CU_ASSERT_NOT_EQUAL(clone->mdim, schema->mdim); /* deep clone */ + CU_ASSERT_NOT_EQUAL(clone->dims, schema->dims); /* deep clone */ + CU_ASSERT_NOT_EQUAL(clone->namehash, schema->namehash); /* deep clone */ hash = schema->namehash; chash = clone->namehash; CU_ASSERT_EQUAL(chash->tablelength, hash->tablelength); diff --git a/lib/cunit/cu_tester.h b/lib/cunit/cu_tester.h index 455ef95..1c195cf 100644 --- a/lib/cunit/cu_tester.h +++ b/lib/cunit/cu_tester.h @@ -11,6 +11,8 @@ #define PC_TEST(test_func) { #test_func, test_func } #define MAX_CUNIT_MSG_LENGTH 512 +#define CU_ASSERT_SUCCESS(rv) CU_ASSERT( (rv) == PC_SUCCESS ) +#define CU_ASSERT_FAILURE(rv) CU_ASSERT( (rv) == PC_FAILURE ) /* Contains the most recent error message generated by rterror. */ char cu_error_msg[MAX_CUNIT_MSG_LENGTH+1]; diff --git a/lib/cunit/data/simple-schema-xy.xml b/lib/cunit/data/simple-schema-xy.xml new file mode 100644 index 0000000..7bf8954 --- /dev/null +++ b/lib/cunit/data/simple-schema-xy.xml @@ -0,0 +1,37 @@ + + + + 1 + 4 + X coordinate as a long integer. You must use the scale and offset information of the header to determine the double value. + X + int32_t + 1 + + + 2 + 4 + Y coordinate as a long integer. You must use the scale and offset information of the header to determine the double value. + Y + int32_t + 2 + + + 3 + 2 + The intensity value is the integer representation of the pulse return magnitude. This value is optional and system specific. However, it should always be included if available. + Intensity + uint16_t + 3 + + + dimensional + + + + + + + 4326 + + diff --git a/lib/cunit/data/simple-schema-xym.xml b/lib/cunit/data/simple-schema-xym.xml new file mode 100644 index 0000000..3421d48 --- /dev/null +++ b/lib/cunit/data/simple-schema-xym.xml @@ -0,0 +1,45 @@ + + + + 1 + 4 + X coordinate as a long integer. You must use the scale and offset information of the header to determine the double value. + X + int32_t + 1 + + + 2 + 4 + Y coordinate as a long integer. You must use the scale and offset information of the header to determine the double value. + Y + int32_t + 2 + + + 3 + 4 + M coordinate as a long integer. You must use the scale and offset information of the header to determine the double value. + M + int32_t + 4 + + + 4 + 2 + The intensity value is the integer representation of the pulse return magnitude. This value is optional and system specific. However, it should always be included if available. + Intensity + uint16_t + 3 + + + dimensional + + + + + + + 4326 + + diff --git a/lib/cunit/data/simple-schema-xyz.xml b/lib/cunit/data/simple-schema-xyz.xml new file mode 100644 index 0000000..944512a --- /dev/null +++ b/lib/cunit/data/simple-schema-xyz.xml @@ -0,0 +1,45 @@ + + + + 1 + 4 + X coordinate as a long integer. You must use the scale and offset information of the header to determine the double value. + X + int32_t + 1 + + + 2 + 4 + Y coordinate as a long integer. You must use the scale and offset information of the header to determine the double value. + Y + int32_t + 2 + + + 3 + 4 + Z coordinate as a long integer. You must use the scale and offset information of the header to determine the double value. + Z + int32_t + 4 + + + 4 + 2 + The intensity value is the integer representation of the pulse return magnitude. This value is optional and system specific. However, it should always be included if available. + Intensity + uint16_t + 3 + + + dimensional + + + + + + + 4326 + + diff --git a/lib/cunit/data/simple-schema-xyzm.xml b/lib/cunit/data/simple-schema-xyzm.xml new file mode 100644 index 0000000..517fbeb --- /dev/null +++ b/lib/cunit/data/simple-schema-xyzm.xml @@ -0,0 +1,53 @@ + + + + 1 + 4 + X coordinate as a long integer. You must use the scale and offset information of the header to determine the double value. + X + int32_t + 1 + + + 2 + 4 + Y coordinate as a long integer. You must use the scale and offset information of the header to determine the double value. + Y + int32_t + 2 + + + 3 + 4 + Z coordinate as a long integer. You must use the scale and offset information of the header to determine the double value. + Z + int32_t + 4 + + + 4 + 4 + M coordinate as a long integer. You must use the scale and offset information of the header to determine the double value. + M + int32_t + 8 + + + 5 + 2 + The intensity value is the integer representation of the pulse return magnitude. This value is optional and system specific. However, it should always be included if available. + Intensity + uint16_t + 1 + + + dimensional + + + + + + + 4326 + + diff --git a/lib/pc_api.h b/lib/pc_api.h index b83c219..94c3d1a 100644 --- a/lib/pc_api.h +++ b/lib/pc_api.h @@ -88,10 +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 z_position; /* What entry is the z coordinate at? */ - int32_t m_position; /* What entry is the m coordinate at? */ + PCDIMENSION *xdim; /* pointer to the x dimension within dims */ + PCDIMENSION *ydim; /* pointer to the y dimension within dims */ + PCDIMENSION *zdim; /* pointer to the z dimension within dims */ + PCDIMENSION *mdim; /* pointer to the m dimension within dims */ uint32_t compression; /* Compression type applied to the data */ hashtable *namehash; /* Look-up from dimension name to pointer */ } PCSCHEMA; @@ -331,38 +331,47 @@ double* pc_point_to_double_array(const PCPOINT *pt); /** Frees the PTPOINT and data (if not readonly). Does not free referenced schema */ void pc_point_free(PCPOINT *pt); -/** Casts named dimension value to double and scale/offset appropriately before returning */ -int pc_point_get_double_by_name(const PCPOINT *pt, const char *name, double *d); +/** Get dimension value by dimension name */ +int pc_point_get_double_by_name(const PCPOINT *pt, const char *name, double *val); -/** Casts dimension value to double and scale/offset appropriately before returning */ -int pc_point_get_double_by_index(const PCPOINT *pt, uint32_t idx, double *d); +/** Get dimension value by dimension index */ +int pc_point_get_double_by_index(const PCPOINT *pt, uint32_t idx, double *val); -/** Reads a double right off the data area */ -int pc_point_get_double(const PCPOINT *pt, const PCDIMENSION *dim, double *d); +/** Read a double right off the data area, applying scale/offset */ +int pc_point_get_double(const PCPOINT *pt, const PCDIMENSION *dim, double *val); + +/** Set dimension value by dimension name */ +int pc_point_set_double_by_name(PCPOINT *pt, const char *name, double val); + +/** Set dimension value by dimension index */ +int pc_point_set_double_by_index(PCPOINT *pt, uint32_t idx, double val); + +/** Write a double to the data area after unapplying scale/offset */ +int pc_point_set_double(PCPOINT *pt, const PCDIMENSION *dim, double val); /** Returns X coordinate */ -double pc_point_get_x(const PCPOINT *pt); +int pc_point_get_x(const PCPOINT *pt, double *val); /** Returns Y coordinate */ -double pc_point_get_y(const PCPOINT *pt); +int pc_point_get_y(const PCPOINT *pt, double *val); /** Returns Z coordinate */ -double pc_point_get_z(const PCPOINT *pt); +int pc_point_get_z(const PCPOINT *pt, double *val); /** Returns M coordinate */ -double pc_point_get_m(const PCPOINT *pt); +int pc_point_get_m(const PCPOINT *pt, double *val); /** Set the X coordinate */ -double pc_point_set_x(PCPOINT *pt, double val); +int pc_point_set_x(PCPOINT *pt, double val); /** Set the Y coordinate */ -double pc_point_set_y(PCPOINT *pt, double val); +int pc_point_set_y(PCPOINT *pt, double val); /** Set the Z coordinate */ -double pc_point_set_z(PCPOINT *pt, double val); +int pc_point_set_z(PCPOINT *pt, double val); /** Set the M coordinate */ -double pc_point_set_m(PCPOINT *pt, double val); +int 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_filter.c b/lib/pc_filter.c index 595f086..4d353c8 100644 --- a/lib/pc_filter.c +++ b/lib/pc_filter.c @@ -166,12 +166,12 @@ pc_patch_dimensional_filter(const PCPATCH_DIMENSIONAL *pdl, const PCBITMAP *map) stats.sum = pc_value_scale_offset(stats.sum, dim); /* Save the X/Y stats for use in bounds later */ - if ( i == pdl->schema->x_position ) + if ( dim == pdl->schema->xdim ) { fpdl->bounds.xmin = stats.min; fpdl->bounds.xmax = stats.max; } - else if ( i == pdl->schema->y_position ) + else if ( dim == pdl->schema->ydim ) { fpdl->bounds.ymin = stats.min; fpdl->bounds.ymax = stats.max; @@ -353,5 +353,3 @@ pc_patch_filter_between_by_name(const PCPATCH *pa, const char *name, double val1 return pc_patch_filter(pa, d->position, PC_BETWEEN, val1, val2); } - - diff --git a/lib/pc_patch_dimensional.c b/lib/pc_patch_dimensional.c index 840f44b..01ac1cb 100644 --- a/lib/pc_patch_dimensional.c +++ b/lib/pc_patch_dimensional.c @@ -185,22 +185,24 @@ pc_patch_dimensional_compute_extent(PCPATCH_DIMENSIONAL *pdl) assert(pdl); assert(pdl->schema); + assert(pdl->schema->xdim); + assert(pdl->schema->ydim); /* Get x extremes */ - pcb = &(pdl->bytes[pdl->schema->x_position]); + pcb = &(pdl->bytes[pdl->schema->xdim->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]); + xmin = pc_value_scale_offset(xmin, pdl->schema->xdim); + xmax = pc_value_scale_offset(xmax, pdl->schema->xdim); pdl->bounds.xmin = xmin; pdl->bounds.xmax = xmax; /* Get y extremes */ - pcb = &(pdl->bytes[pdl->schema->y_position]); + pcb = &(pdl->bytes[pdl->schema->ydim->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]); + ymin = pc_value_scale_offset(ymin, pdl->schema->ydim); + ymax = pc_value_scale_offset(ymax, pdl->schema->ydim); pdl->bounds.ymin = ymin; pdl->bounds.ymax = ymax; diff --git a/lib/pc_patch_uncompressed.c b/lib/pc_patch_uncompressed.c index 810f6e3..7d19f5f 100644 --- a/lib/pc_patch_uncompressed.c +++ b/lib/pc_patch_uncompressed.c @@ -199,8 +199,8 @@ 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); + pc_point_get_x(pt, &x); + pc_point_get_y(pt, &y); if ( b.xmin > x ) b.xmin = x; if ( b.ymin > y ) b.ymin = y; if ( b.xmax < x ) b.xmax = x; @@ -418,8 +418,8 @@ pc_patch_uncompressed_add_point(PCPATCH_UNCOMPRESSED *c, const PCPOINT *p) c->npoints += 1; /* Update bounding box */ - x = pc_point_get_x(p); - y = pc_point_get_y(p); + pc_point_get_x(p, &x); + pc_point_get_y(p, &y); if ( c->bounds.xmin > x ) c->bounds.xmin = x; if ( c->bounds.ymin > y ) c->bounds.ymin = y; if ( c->bounds.xmax < x ) c->bounds.xmax = x; diff --git a/lib/pc_point.c b/lib/pc_point.c index 01fb523..f958ade 100644 --- a/lib/pc_point.c +++ b/lib/pc_point.c @@ -76,36 +76,36 @@ pc_point_free(PCPOINT *pt) } int -pc_point_get_double(const PCPOINT *pt, const PCDIMENSION *dim, double *d) +pc_point_get_double(const PCPOINT *pt, const PCDIMENSION *dim, double *val) { uint8_t *ptr; - double val; + double d; + + if ( ! dim ) return PC_FAILURE; /* Read raw value from byte buffer */ ptr = pt->data + dim->byteoffset; - val = pc_double_from_ptr(ptr, dim->interpretation); - val = pc_value_scale_offset(val, dim); + d = pc_double_from_ptr(ptr, dim->interpretation); + d = pc_value_scale_offset(d, dim); - *d = val; + *val = d; return PC_SUCCESS; } int -pc_point_get_double_by_name(const PCPOINT *pt, const char *name, double *d) +pc_point_get_double_by_name(const PCPOINT *pt, const char *name, double *val) { PCDIMENSION *dim; dim = pc_schema_get_dimension_by_name(pt->schema, name); - if ( ! dim ) return PC_FAILURE; - return pc_point_get_double(pt, dim, d); + return pc_point_get_double(pt, dim, val); } int -pc_point_get_double_by_index(const PCPOINT *pt, uint32_t idx, double *d) +pc_point_get_double_by_index(const PCPOINT *pt, uint32_t idx, double *val) { PCDIMENSION *dim; dim = pc_schema_get_dimension(pt->schema, idx); - if ( ! dim ) return PC_FAILURE; - return pc_point_get_double(pt, dim, d); + return pc_point_get_double(pt, dim, val); } int @@ -113,6 +113,8 @@ pc_point_set_double(PCPOINT *pt, const PCDIMENSION *dim, double val) { uint8_t *ptr; + if ( ! dim ) return PC_FAILURE; + /* Remove scale and offsets */ val = pc_value_unscale_unoffset(val, dim); @@ -125,73 +127,66 @@ pc_point_set_double(PCPOINT *pt, const PCDIMENSION *dim, double val) int pc_point_set_double_by_index(PCPOINT *pt, uint32_t idx, double val) { - PCDIMENSION *d; - d = pc_schema_get_dimension(pt->schema, idx); - return pc_point_set_double(pt, d, val); + PCDIMENSION *dim; + dim = pc_schema_get_dimension(pt->schema, idx); + return pc_point_set_double(pt, dim, val); } int pc_point_set_double_by_name(PCPOINT *pt, const char *name, double val) { - PCDIMENSION *d; - d = pc_schema_get_dimension_by_name(pt->schema, name); - return pc_point_set_double(pt, d, val); + PCDIMENSION *dim; + dim = pc_schema_get_dimension_by_name(pt->schema, name); + return pc_point_set_double(pt, dim, val); } -double -pc_point_get_x(const PCPOINT *pt) +int +pc_point_get_x(const PCPOINT *pt, double *val) { - double d; - pc_point_get_double_by_index(pt, pt->schema->x_position, &d); - return d; + return pc_point_get_double(pt, pt->schema->xdim, val); } -double -pc_point_get_y(const PCPOINT *pt) +int +pc_point_get_y(const PCPOINT *pt, double *val) { - double d; - pc_point_get_double_by_index(pt, pt->schema->y_position, &d); - return d; + return pc_point_get_double(pt, pt->schema->ydim, val); } -double -pc_point_get_z(const PCPOINT *pt) +int +pc_point_get_z(const PCPOINT *pt, double *val) { - double d; - pc_point_get_double_by_index(pt, pt->schema->z_position, &d); - return d; + return pc_point_get_double(pt, pt->schema->zdim, val); } -double -pc_point_get_m(const PCPOINT *pt) +int +pc_point_get_m(const PCPOINT *pt, double *val) { - double d; - pc_point_get_double_by_index(pt, pt->schema->m_position, &d); - return d; + return pc_point_get_double(pt, pt->schema->mdim, val); } -double + +int pc_point_set_x(PCPOINT *pt, double val) { - return pc_point_set_double_by_index(pt, pt->schema->x_position, val); + return pc_point_set_double(pt, pt->schema->xdim, val); } -double +int pc_point_set_y(PCPOINT *pt, double val) { - return pc_point_set_double_by_index(pt, pt->schema->y_position, val); + return pc_point_set_double(pt, pt->schema->ydim, val); } -double +int pc_point_set_z(PCPOINT *pt, double val) { - return pc_point_set_double_by_index(pt, pt->schema->z_position, val); + return pc_point_set_double(pt, pt->schema->zdim, val); } -double +int pc_point_set_m(PCPOINT *pt, double val) { - return pc_point_set_double_by_index(pt, pt->schema->m_position, val); + return pc_point_set_double(pt, pt->schema->mdim, val); } char * @@ -328,20 +323,27 @@ pc_point_to_geometry_wkb(const PCPOINT *pt, size_t *wkbsize) uint8_t *wkb, *ptr; uint32_t srid = pt->schema->srid; double x, y, z, m; + int has_x = pc_point_get_x(pt, &x) == PC_SUCCESS; + int has_y = pc_point_get_y(pt, &y) == PC_SUCCESS; + int has_z = pc_point_get_z(pt, &z) == PC_SUCCESS; + int has_m = pc_point_get_m(pt, &m) == PC_SUCCESS; - if ( srid != 0 ) + if ( ! ( has_x && has_y ) ) + return NULL; + + if ( srid ) { wkbtype |= srid_mask; size += 4; } - if ( pt->schema->z_position > -1 ) + if ( has_z ) { wkbtype |= z_mask; size += 8; } - if ( pt->schema->m_position > -1 ) + if ( has_m ) { wkbtype |= m_mask; size += 8; @@ -362,24 +364,20 @@ pc_point_to_geometry_wkb(const PCPOINT *pt, size_t *wkbsize) 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 ( pt->schema->z_position > -1 ) + if ( has_z ) { - z = pc_point_get_z(pt); memcpy(ptr, &z, 8); /* Z */ ptr += 8; } - if ( pt->schema->m_position > -1 ) + if ( has_m ) { - m = pc_point_get_m(pt); memcpy(ptr, &m, 8); /* M */ ptr += 8; } diff --git a/lib/pc_schema.c b/lib/pc_schema.c index b900410..e56f6dd 100644 --- a/lib/pc_schema.c +++ b/lib/pc_schema.c @@ -196,10 +196,7 @@ pc_schema_new(uint32_t ndims) pcs->dims = pcalloc(sizeof(PCDIMENSION*) * ndims); pcs->namehash = create_string_hashtable(); pcs->ndims = ndims; - pcs->x_position = -1; - pcs->y_position = -1; - pcs->z_position = -1; - pcs->m_position = -1; + /* pcalloc memsets to 0, so xdim,ydim,zdim and mdim are already NULL */ return pcs; } @@ -237,10 +234,6 @@ pc_schema_clone(const PCSCHEMA *s) PCSCHEMA *pcs = pc_schema_new(s->ndims); pcs->pcid = s->pcid; 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++ ) { @@ -249,6 +242,10 @@ pc_schema_clone(const PCSCHEMA *s) pc_schema_set_dimension(pcs, pc_dimension_clone(s->dims[i])); } } + pcs->xdim = s->xdim ? pcs->dims[s->xdim->position] : NULL; + pcs->ydim = s->ydim ? pcs->dims[s->ydim->position] : NULL; + pcs->zdim = s->zdim ? pcs->dims[s->zdim->position] : NULL; + pcs->mdim = s->mdim ? pcs->dims[s->mdim->position] : NULL; pc_schema_calculate_byteoffsets(pcs); return pcs; } @@ -341,21 +338,21 @@ void pc_schema_check_xyzm(PCSCHEMA *s) strcasecmp(dimname, "Longitude") == 0 || strcasecmp(dimname, "Lon") == 0 ) { - s->x_position = i; + s->xdim = s->dims[i]; continue; } if ( strcasecmp(dimname, "Y") == 0 || strcasecmp(dimname, "Latitude") == 0 || strcasecmp(dimname, "Lat") == 0 ) { - s->y_position = i; + s->ydim = s->dims[i]; continue; } if ( strcasecmp(dimname, "Z") == 0 || strcasecmp(dimname, "H") == 0 || strcasecmp(dimname, "Height") == 0 ) { - s->z_position = i; + s->zdim = s->dims[i]; continue; } if ( strcasecmp(dimname, "M") == 0 || @@ -363,7 +360,7 @@ void pc_schema_check_xyzm(PCSCHEMA *s) strcasecmp(dimname, "Time") == 0 || strcasecmp(dimname, "GPSTime") == 0 ) { - s->m_position = i; + s->mdim = s->dims[i]; continue; } } @@ -584,13 +581,13 @@ pc_schema_is_valid(const PCSCHEMA *s) { int i; - if ( s->x_position < 0 ) + if ( ! s->xdim ) { pcwarn("schema does not include an X coordinate"); return PC_FALSE; } - if ( s->y_position < 0 ) + if ( ! s->ydim ) { pcwarn("schema does not include a Y coordinate"); return PC_FALSE;