size_t pc_patch_serialized_size(const PCPATCH *patch) { size_t stats_size = pc_stats_size(patch->schema); size_t common_size = sizeof(SERIALIZED_PATCH) - 1; switch( patch->type ) { case PC_NONE: { PCPATCH_UNCOMPRESSED *pu = (PCPATCH_UNCOMPRESSED*)patch; return common_size + stats_size + pu->datasize; } case PC_GHT: { static size_t ghtsize_size = 4; PCPATCH_GHT *pg = (PCPATCH_GHT*)patch; return common_size + stats_size + ghtsize_size + pg->ghtsize; } case PC_DIMENSIONAL: { return common_size + stats_size + pc_patch_dimensional_serialized_size((PCPATCH_DIMENSIONAL*)patch); } default: { pcerror("%s: unknown compresed %d", __func__, patch->type); } } return -1; }
size_t pc_patch_serialized_size(const PCPATCH *patch) { switch( patch->type ) { case PC_NONE: { PCPATCH_UNCOMPRESSED *pu = (PCPATCH_UNCOMPRESSED*)patch; return sizeof(SERIALIZED_PATCH) - 1 + pu->datasize; } case PC_GHT: { pcerror("pc_patch_serialized_size: GHT format not yet supported"); } case PC_DIMENSIONAL: { return sizeof(SERIALIZED_PATCH) - 1 + pc_patch_dimensional_serialized_size((PCPATCH_DIMENSIONAL*)patch); } default: { pcerror("pc_patch_serialized_size: unknown compresed %d", patch->type); } } return -1; }
uint8_t * pc_patch_dimensional_to_wkb(const PCPATCH_DIMENSIONAL *patch, size_t *wkbsize) { /* byte: endianness (1 = NDR, 0 = XDR) uint32: pcid (key to POINTCLOUD_SCHEMAS) uint32: compression (0 = no compression, 1 = dimensional, 2 = GHT) uint32: npoints dimensions[]: pcbytes (interpret relative to pcid and compressions) */ int ndims = patch->schema->ndims; int i; uint8_t *buf; char endian = machine_endian(); /* endian + pcid + compression + npoints + datasize */ size_t size = 1 + 4 + 4 + 4 + pc_patch_dimensional_serialized_size(patch); uint8_t *wkb = pcalloc(size); uint32_t compression = patch->type; uint32_t npoints = patch->npoints; uint32_t pcid = patch->schema->pcid; wkb[0] = endian; /* Write endian flag */ memcpy(wkb + 1, &pcid, 4); /* Write PCID */ memcpy(wkb + 5, &compression, 4); /* Write compression */ memcpy(wkb + 9, &npoints, 4); /* Write npoints */ buf = wkb + 13; for ( i = 0; i < ndims; i++ ) { size_t bsz; PCBYTES *pcb = &(patch->bytes[i]); // XXX printf("pcb->(size=%d, interp=%d, npoints=%d, compression=%d, readonly=%d)\n",pcb->size, pcb->interpretation, pcb->npoints, pcb->compression, pcb->readonly); pc_bytes_serialize(pcb, buf, &bsz); buf += bsz; } if ( wkbsize ) *wkbsize = size; return wkb; }
static void test_patch_dimensional_compression() { PCPOINT *pt; int i; int npts = 400; PCPOINTLIST *pl1, *pl2; PCPATCH_DIMENSIONAL *pch1, *pch2; PCDIMSTATS *pds = NULL; size_t z1, z2; char *str; pl1 = pc_pointlist_make(npts); for ( i = 0; i < npts; i++ ) { pt = pc_point_make(simpleschema); pc_point_set_double_by_name(pt, "x", i*2.0); pc_point_set_double_by_name(pt, "y", i*1.9); pc_point_set_double_by_name(pt, "Z", i*0.34); pc_point_set_double_by_name(pt, "intensity", 10); pc_pointlist_add_point(pl1, pt); } pch1 = pc_patch_dimensional_from_pointlist(pl1); z1 = pc_patch_dimensional_serialized_size(pch1); // printf("z1 %ld\n", z1); pds = pc_dimstats_make(simpleschema); pc_dimstats_update(pds, pch1); pc_dimstats_update(pds, pch1); pch2 = pc_patch_dimensional_compress(pch1, pds); z2 = pc_patch_dimensional_serialized_size(pch2); // printf("z2 %ld\n", z2); str = pc_dimstats_to_string(pds); CU_ASSERT_STRING_EQUAL(str, "{\"ndims\":4,\"total_points\":1200,\"total_patches\":3,\"dims\":[{\"total_runs\":1200,\"total_commonbits\":45,\"recommended_compression\":2},{\"total_runs\":1200,\"total_commonbits\":45,\"recommended_compression\":2},{\"total_runs\":1200,\"total_commonbits\":54,\"recommended_compression\":2},{\"total_runs\":3,\"total_commonbits\":48,\"recommended_compression\":1}]}"); // printf("%s\n", str); pcfree(str); pl2 = pc_pointlist_from_dimensional(pch2); for ( i = 0; i < npts; i++ ) { pt = pc_pointlist_get_point(pl2, i); double v1, v2, v3, v4; pc_point_get_double_by_name(pt, "x", &v1); pc_point_get_double_by_name(pt, "y", &v2); pc_point_get_double_by_name(pt, "Z", &v3); pc_point_get_double_by_name(pt, "intensity", &v4); // printf("%g\n", v4); CU_ASSERT_DOUBLE_EQUAL(v1, i*2.0, 0.001); CU_ASSERT_DOUBLE_EQUAL(v2, i*1.9, 0.001); CU_ASSERT_DOUBLE_EQUAL(v3, i*0.34, 0.001); CU_ASSERT_DOUBLE_EQUAL(v4, 10, 0.001); } pc_patch_dimensional_free(pch1); pc_patch_dimensional_free(pch2); // pc_patch_dimensional_free(pch3); pc_pointlist_free(pl1); pc_pointlist_free(pl2); if ( pds ) pc_dimstats_free(pds); }