From fdc27ea55dec258ae6aaaea7874fc71f260cc6b2 Mon Sep 17 00:00:00 2001 From: Paul Ramsey Date: Mon, 3 Jun 2013 16:20:03 -0700 Subject: [PATCH] Tests for filtering (need more!) --- lib/cunit/cu_pc_patch.c | 65 ++++++++++++++++++++++++++++++++++++++ lib/pc_api_internal.h | 4 +++ lib/pc_bytes.c | 3 -- lib/pc_filter.c | 28 ++++++++++++---- lib/pc_patch_dimensional.c | 11 +++++++ lib/pc_point.c | 24 ++++---------- lib/pc_val.c | 14 ++++++++ 7 files changed, 121 insertions(+), 28 deletions(-) diff --git a/lib/cunit/cu_pc_patch.c b/lib/cunit/cu_pc_patch.c index 780e683..dbb3e52 100644 --- a/lib/cunit/cu_pc_patch.c +++ b/lib/cunit/cu_pc_patch.c @@ -761,6 +761,70 @@ test_patch_wkb() } +static void +test_patch_filter() +{ + int i; + int npts = 20; + PCPOINTLIST *pl1, *pl2; + PCPATCH_UNCOMPRESSED *pu1, *pu2; + PCPATCH *pa1, *pa2, *pa3, *pa4; + PCDIMSTATS *pds = NULL; + size_t z1, z2; + uint8_t *wkb1, *wkb2; + char *str1, *str2; + + pl1 = pc_pointlist_make(npts); + pl2 = pc_pointlist_make(npts); + + for ( i = 0; i < npts; i++ ) + { + PCPOINT *pt1 = pc_point_make(simpleschema); + PCPOINT *pt2 = pc_point_make(simpleschema); + pc_point_set_double_by_name(pt1, "x", i); + pc_point_set_double_by_name(pt1, "y", i); + pc_point_set_double_by_name(pt1, "Z", i*0.1); + pc_point_set_double_by_name(pt1, "intensity", 100-i); + pc_pointlist_add_point(pl1, pt1); + pc_point_set_double_by_name(pt2, "x", i); + pc_point_set_double_by_name(pt2, "y", i); + pc_point_set_double_by_name(pt2, "Z", i*0.1); + pc_point_set_double_by_name(pt2, "intensity", 100-i); + pc_pointlist_add_point(pl2, pt2); + } + + // PCPATCH* pc_patch_filter(const PCPATCH *pa, uint32_t dimnum, PC_FILTERTYPE filter, double val1, double val2); + + pa1 = (PCPATCH*)pc_patch_dimensional_from_pointlist(pl1); + // printf("pa1\n%s\n", pc_patch_to_string(pa1)); + pa2 = pc_patch_filter(pa1, 0, PC_GT, 17, 20); + str1 = pc_patch_to_string(pa2); + // printf("pa2\n%s\n", str1); + CU_ASSERT_STRING_EQUAL(str1, "{\"pcid\":0,\"pts\":[[18,18,1.8,82],[19,19,1.9,81]]}"); + + pa3 = (PCPATCH*)pc_patch_uncompressed_from_pointlist(pl2); + // printf("\npa3\n%s\n", pc_patch_to_string(pa3)); + pa4 = pc_patch_filter(pa3, 0, PC_GT, 17, 20); + str2 = pc_patch_to_string(pa4); + // printf("\npa4\n%s\n", str2); + CU_ASSERT_STRING_EQUAL(str2, "{\"pcid\":0,\"pts\":[[18,18,1.8,82],[19,19,1.9,81]]}"); + + pcfree(str1); + pcfree(str2); + + pc_pointlist_free(pl1); + pc_pointlist_free(pl2); + pc_patch_free(pa1); + pc_patch_free(pa3); + pc_patch_free(pa4); + pc_patch_free(pa2); + + return; + + + +} + /* REGISTER ***********************************************************/ CU_TestInfo patch_tests[] = { @@ -775,6 +839,7 @@ CU_TestInfo patch_tests[] = { PC_TEST(test_patch_dimensional_compression), PC_TEST(test_patch_union), PC_TEST(test_patch_wkb), + PC_TEST(test_patch_filter), CU_TEST_INFO_NULL }; diff --git a/lib/pc_api_internal.h b/lib/pc_api_internal.h index 6018889..0f14094 100644 --- a/lib/pc_api_internal.h +++ b/lib/pc_api_internal.h @@ -112,6 +112,9 @@ uint8_t* uncompressed_bytes_flip_endian(const uint8_t *bytebuf, const PCSCHEMA * /** Update a value using the scale/offset info from a dimension */ double pc_value_scale_offset(double val, const PCDIMENSION *dim); +/** Remove the scale/offset values from a number before storage */ +double pc_value_unscale_unoffset(double val, const PCDIMENSION *dim); + /** Read interpretation type from buffer and cast to double */ double pc_double_from_ptr(const uint8_t *ptr, uint32_t interpretation); @@ -157,6 +160,7 @@ uint8_t* pc_patch_dimensional_to_wkb(const PCPATCH_DIMENSIONAL *patch, size_t *w PCPATCH* pc_patch_dimensional_from_wkb(const PCSCHEMA *schema, const uint8_t *wkb, size_t wkbsize); PCPATCH_DIMENSIONAL* pc_patch_dimensional_from_pointlist(const PCPOINTLIST *pdl); PCPOINTLIST* pc_pointlist_from_dimensional(const PCPATCH_DIMENSIONAL *pdl); +PCPATCH_DIMENSIONAL* pc_patch_dimensional_clone(const PCPATCH_DIMENSIONAL *patch); /* UNCOMPRESSED PATCHES */ char* pc_patch_uncompressed_to_string(const PCPATCH_UNCOMPRESSED *patch); diff --git a/lib/pc_bytes.c b/lib/pc_bytes.c index 6e40775..0afc4e3 100644 --- a/lib/pc_bytes.c +++ b/lib/pc_bytes.c @@ -1270,9 +1270,6 @@ pc_bytes_minmax(const PCBYTES *pcb, double *min, double *max) return PC_FAILURE; } - - - static PCBYTES pc_bytes_uncompressed_filter(const PCBYTES *pcb, const PCBITMAP *map) { diff --git a/lib/pc_filter.c b/lib/pc_filter.c index 7bf8637..5efed81 100644 --- a/lib/pc_filter.c +++ b/lib/pc_filter.c @@ -138,15 +138,17 @@ static PCBITMAP * pc_patch_dimensional_bitmap(const PCPATCH_DIMENSIONAL *pdl, uint32_t dimnum, PC_FILTERTYPE filter, double val1, double val2) { assert(dimnum < pdl->schema->ndims); - return pc_bytes_bitmap(&(pdl->bytes[dimnum]), filter, val1, val2); + double unscaled1 = pc_value_unscale_unoffset(val1, pdl->schema->dims[dimnum]); + double unscaled2 = pc_value_unscale_unoffset(val2, pdl->schema->dims[dimnum]); + + return pc_bytes_bitmap(&(pdl->bytes[dimnum]), filter, unscaled1, unscaled2); } static PCPATCH_DIMENSIONAL * pc_patch_dimensional_filter(const PCPATCH_DIMENSIONAL *pdl, const PCBITMAP *map) { int i = 0; - PCPATCH_DIMENSIONAL *fpdl = pcalloc(sizeof(PCPATCH_DIMENSIONAL)); - memcpy(fpdl, pdl, sizeof(PCPATCH_DIMENSIONAL)); + PCPATCH_DIMENSIONAL *fpdl = pc_patch_dimensional_clone(pdl); for ( i = 0; i < pdl->schema->ndims; i++ ) { @@ -162,6 +164,8 @@ PCPATCH * pc_patch_filter(const PCPATCH *pa, uint32_t dimnum, PC_FILTERTYPE filter, double val1, double val2) { if ( ! pa ) return NULL; + PCPATCH *paout; + switch ( pa->type ) { case PC_NONE: @@ -169,7 +173,8 @@ pc_patch_filter(const PCPATCH *pa, uint32_t dimnum, PC_FILTERTYPE filter, double PCBITMAP *map = pc_patch_uncompressed_bitmap((PCPATCH_UNCOMPRESSED*)pa, dimnum, filter, val1, val2); PCPATCH_UNCOMPRESSED *pu = pc_patch_uncompressed_filter((PCPATCH_UNCOMPRESSED*)pa, map); pc_bitmap_free(map); - return (PCPATCH*)pu; + paout = (PCPATCH*)pu; + break; } case PC_GHT: { @@ -179,17 +184,26 @@ pc_patch_filter(const PCPATCH *pa, uint32_t dimnum, PC_FILTERTYPE filter, double PCPATCH_GHT *pgh = pc_patch_ght_from_uncompressed(pu2); pc_patch_free((PCPATCH*)pu); pc_patch_free((PCPATCH*)pu2); - return (PCPATCH*)pgh; + paout = (PCPATCH*)pgh; + break; } case PC_DIMENSIONAL: { PCBITMAP *map = pc_patch_dimensional_bitmap((PCPATCH_DIMENSIONAL*)pa, dimnum, filter, val1, val2); PCPATCH_DIMENSIONAL *pdl = pc_patch_dimensional_filter((PCPATCH_DIMENSIONAL*)pa, map); pc_bitmap_free(map); - return (PCPATCH*)pdl; + paout = (PCPATCH*)pdl; + break; } default: pcerror("%s: failure", __func__); } - return NULL; + + if ( PC_FAILURE == pc_patch_compute_extent(paout) ) + pcerror("%s: pc_patch_compute_extent failed", __func__); + + if ( PC_FAILURE == pc_patch_compute_stats(paout) ) + pcerror("%s: pc_patch_compute_stats failed", __func__); + + return paout; } diff --git a/lib/pc_patch_dimensional.c b/lib/pc_patch_dimensional.c index 4f88a9b..4021123 100644 --- a/lib/pc_patch_dimensional.c +++ b/lib/pc_patch_dimensional.c @@ -28,6 +28,17 @@ typedef struct */ +PCPATCH_DIMENSIONAL * +pc_patch_dimensional_clone(const PCPATCH_DIMENSIONAL *patch) +{ + PCPATCH_DIMENSIONAL *pdl = pcalloc(sizeof(PCPATCH_DIMENSIONAL)); + memcpy(pdl, patch, sizeof(PCPATCH_DIMENSIONAL)); + pdl->bytes = pcalloc(patch->schema->ndims * sizeof(PCBYTES)); + pdl->npoints = 0; + pdl->stats = NULL; + return pdl; +} + size_t pc_patch_dimensional_serialized_size(const PCPATCH_DIMENSIONAL *patch) { diff --git a/lib/pc_point.c b/lib/pc_point.c index 97862f4..ea9ea0f 100644 --- a/lib/pc_point.c +++ b/lib/pc_point.c @@ -86,14 +86,7 @@ pc_point_get_double(const PCPOINT *pt, const PCDIMENSION *dim, double *d) /* Read raw value from byte buffer */ ptr = pt->data + dim->byteoffset; val = pc_double_from_ptr(ptr, dim->interpretation); - - /* Scale value */ - if ( dim->scale != 1 ) - val *= dim->scale; - - /* Offset value */ - if ( dim->offset ) - val += dim->offset; + val = pc_value_scale_offset(val, dim); *d = val; return PC_SUCCESS; @@ -118,22 +111,17 @@ pc_point_get_double_by_index(const PCPOINT *pt, uint32_t idx, double *d) } int -pc_point_set_double(PCPOINT *pt, const PCDIMENSION *d, double val) +pc_point_set_double(PCPOINT *pt, const PCDIMENSION *dim, double val) { uint8_t *ptr; - /* Offset value */ - if ( d->offset ) - val -= d->offset; - - /* Scale value */ - if ( d->scale != 1 ) - val /= d->scale; + /* Remove scale and offsets */ + val = pc_value_unscale_unoffset(val, dim); /* Get pointer into byte buffer */ - ptr = pt->data + d->byteoffset; + ptr = pt->data + dim->byteoffset; - return pc_double_to_ptr(ptr, d->interpretation, val); + return pc_double_to_ptr(ptr, dim->interpretation, val); } int diff --git a/lib/pc_val.c b/lib/pc_val.c index 6c0c3e8..8ddc265 100644 --- a/lib/pc_val.c +++ b/lib/pc_val.c @@ -13,6 +13,20 @@ #include "pc_api_internal.h" +double pc_value_unscale_unoffset(double val, const PCDIMENSION *dim) +{ + /* Offset value */ + if ( dim->offset ) + val -= dim->offset; + + /* Scale value */ + if ( dim->scale != 1 ) + val /= dim->scale; + + return val; +} + + double pc_value_scale_offset(double val, const PCDIMENSION *dim) { /* Scale value */