Merge pull request #160 from mbredif/point_xyzm_test

Point xyzm test
This commit is contained in:
Éric Lemoine 2017-04-01 16:49:01 +02:00 committed by GitHub
commit 8a590cd206
13 changed files with 491 additions and 131 deletions

View File

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

View File

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

View File

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

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<pc:PointCloudSchema xmlns:pc="http://pointcloud.org/schemas/PC/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<pc:dimension>
<pc:position>1</pc:position>
<pc:size>4</pc:size>
<pc:description>X coordinate as a long integer. You must use the scale and offset information of the header to determine the double value.</pc:description>
<pc:name>X</pc:name>
<pc:interpretation>int32_t</pc:interpretation>
<pc:scale>1</pc:scale>
</pc:dimension>
<pc:dimension>
<pc:position>2</pc:position>
<pc:size>4</pc:size>
<pc:description>Y coordinate as a long integer. You must use the scale and offset information of the header to determine the double value.</pc:description>
<pc:name>Y</pc:name>
<pc:interpretation>int32_t</pc:interpretation>
<pc:scale>2</pc:scale>
</pc:dimension>
<pc:dimension>
<pc:position>3</pc:position>
<pc:size>2</pc:size>
<pc:description>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.</pc:description>
<pc:name>Intensity</pc:name>
<pc:interpretation>uint16_t</pc:interpretation>
<pc:scale>3</pc:scale>
</pc:dimension>
<pc:metadata>
<Metadata name="compression">dimensional</Metadata>
<Metadata name="ght_xmin"></Metadata>
<Metadata name="ght_ymin"></Metadata>
<Metadata name="ght_xmax"></Metadata>
<Metadata name="ght_ymax"></Metadata>
<Metadata name="ght_keylength"></Metadata>
<Metadata name="ght_depth"></Metadata>
<Metadata name="spatialreference" type="id">4326</Metadata>
</pc:metadata>
</pc:PointCloudSchema>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<pc:PointCloudSchema xmlns:pc="http://pointcloud.org/schemas/PC/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<pc:dimension>
<pc:position>1</pc:position>
<pc:size>4</pc:size>
<pc:description>X coordinate as a long integer. You must use the scale and offset information of the header to determine the double value.</pc:description>
<pc:name>X</pc:name>
<pc:interpretation>int32_t</pc:interpretation>
<pc:scale>1</pc:scale>
</pc:dimension>
<pc:dimension>
<pc:position>2</pc:position>
<pc:size>4</pc:size>
<pc:description>Y coordinate as a long integer. You must use the scale and offset information of the header to determine the double value.</pc:description>
<pc:name>Y</pc:name>
<pc:interpretation>int32_t</pc:interpretation>
<pc:scale>2</pc:scale>
</pc:dimension>
<pc:dimension>
<pc:position>3</pc:position>
<pc:size>4</pc:size>
<pc:description>M coordinate as a long integer. You must use the scale and offset information of the header to determine the double value.</pc:description>
<pc:name>M</pc:name>
<pc:interpretation>int32_t</pc:interpretation>
<pc:scale>4</pc:scale>
</pc:dimension>
<pc:dimension>
<pc:position>4</pc:position>
<pc:size>2</pc:size>
<pc:description>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.</pc:description>
<pc:name>Intensity</pc:name>
<pc:interpretation>uint16_t</pc:interpretation>
<pc:scale>3</pc:scale>
</pc:dimension>
<pc:metadata>
<Metadata name="compression">dimensional</Metadata>
<Metadata name="ght_xmin"></Metadata>
<Metadata name="ght_ymin"></Metadata>
<Metadata name="ght_xmax"></Metadata>
<Metadata name="ght_ymax"></Metadata>
<Metadata name="ght_keylength"></Metadata>
<Metadata name="ght_depth"></Metadata>
<Metadata name="spatialreference" type="id">4326</Metadata>
</pc:metadata>
</pc:PointCloudSchema>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<pc:PointCloudSchema xmlns:pc="http://pointcloud.org/schemas/PC/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<pc:dimension>
<pc:position>1</pc:position>
<pc:size>4</pc:size>
<pc:description>X coordinate as a long integer. You must use the scale and offset information of the header to determine the double value.</pc:description>
<pc:name>X</pc:name>
<pc:interpretation>int32_t</pc:interpretation>
<pc:scale>1</pc:scale>
</pc:dimension>
<pc:dimension>
<pc:position>2</pc:position>
<pc:size>4</pc:size>
<pc:description>Y coordinate as a long integer. You must use the scale and offset information of the header to determine the double value.</pc:description>
<pc:name>Y</pc:name>
<pc:interpretation>int32_t</pc:interpretation>
<pc:scale>2</pc:scale>
</pc:dimension>
<pc:dimension>
<pc:position>3</pc:position>
<pc:size>4</pc:size>
<pc:description>Z coordinate as a long integer. You must use the scale and offset information of the header to determine the double value.</pc:description>
<pc:name>Z</pc:name>
<pc:interpretation>int32_t</pc:interpretation>
<pc:scale>4</pc:scale>
</pc:dimension>
<pc:dimension>
<pc:position>4</pc:position>
<pc:size>2</pc:size>
<pc:description>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.</pc:description>
<pc:name>Intensity</pc:name>
<pc:interpretation>uint16_t</pc:interpretation>
<pc:scale>3</pc:scale>
</pc:dimension>
<pc:metadata>
<Metadata name="compression">dimensional</Metadata>
<Metadata name="ght_xmin"></Metadata>
<Metadata name="ght_ymin"></Metadata>
<Metadata name="ght_xmax"></Metadata>
<Metadata name="ght_ymax"></Metadata>
<Metadata name="ght_keylength"></Metadata>
<Metadata name="ght_depth"></Metadata>
<Metadata name="spatialreference" type="id">4326</Metadata>
</pc:metadata>
</pc:PointCloudSchema>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<pc:PointCloudSchema xmlns:pc="http://pointcloud.org/schemas/PC/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<pc:dimension>
<pc:position>1</pc:position>
<pc:size>4</pc:size>
<pc:description>X coordinate as a long integer. You must use the scale and offset information of the header to determine the double value.</pc:description>
<pc:name>X</pc:name>
<pc:interpretation>int32_t</pc:interpretation>
<pc:scale>1</pc:scale>
</pc:dimension>
<pc:dimension>
<pc:position>2</pc:position>
<pc:size>4</pc:size>
<pc:description>Y coordinate as a long integer. You must use the scale and offset information of the header to determine the double value.</pc:description>
<pc:name>Y</pc:name>
<pc:interpretation>int32_t</pc:interpretation>
<pc:scale>2</pc:scale>
</pc:dimension>
<pc:dimension>
<pc:position>3</pc:position>
<pc:size>4</pc:size>
<pc:description>Z coordinate as a long integer. You must use the scale and offset information of the header to determine the double value.</pc:description>
<pc:name>Z</pc:name>
<pc:interpretation>int32_t</pc:interpretation>
<pc:scale>4</pc:scale>
</pc:dimension>
<pc:dimension>
<pc:position>4</pc:position>
<pc:size>4</pc:size>
<pc:description>M coordinate as a long integer. You must use the scale and offset information of the header to determine the double value.</pc:description>
<pc:name>M</pc:name>
<pc:interpretation>int32_t</pc:interpretation>
<pc:scale>8</pc:scale>
</pc:dimension>
<pc:dimension>
<pc:position>5</pc:position>
<pc:size>2</pc:size>
<pc:description>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.</pc:description>
<pc:name>Intensity</pc:name>
<pc:interpretation>uint16_t</pc:interpretation>
<pc:scale>1</pc:scale>
</pc:dimension>
<pc:metadata>
<Metadata name="compression">dimensional</Metadata>
<Metadata name="ght_xmin"></Metadata>
<Metadata name="ght_ymin"></Metadata>
<Metadata name="ght_xmax"></Metadata>
<Metadata name="ght_ymax"></Metadata>
<Metadata name="ght_keylength"></Metadata>
<Metadata name="ght_depth"></Metadata>
<Metadata name="spatialreference" type="id">4326</Metadata>
</pc:metadata>
</pc:PointCloudSchema>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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