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;