static void test_dimension_get() { PCDIMENSION *d; d = pc_schema_get_dimension(schema, 0); CU_ASSERT_EQUAL(d->position, 0); CU_ASSERT_STRING_EQUAL(d->name, "X"); d = pc_schema_get_dimension(schema, 1); CU_ASSERT_EQUAL(d->position, 1); CU_ASSERT_STRING_EQUAL(d->name, "Y"); d = pc_schema_get_dimension_by_name(schema, "nothinghere"); CU_ASSERT_EQUAL(d, NULL); d = pc_schema_get_dimension_by_name(schema, "Z"); CU_ASSERT_EQUAL(d->position, 2); CU_ASSERT_STRING_EQUAL(d->name, "Z"); d = pc_schema_get_dimension_by_name(schema, "z"); CU_ASSERT_EQUAL(d->position, 2); CU_ASSERT_STRING_EQUAL(d->name, "Z"); d = pc_schema_get_dimension_by_name(schema, "y"); // printf("name %s\n", d->name); // printf("position %d\n", d->position); CU_ASSERT_EQUAL(d->position, 1); CU_ASSERT_STRING_EQUAL(d->name, "Y"); }
PCPOINTLIST * pc_pointlist_from_dimensional(const PCPATCH_DIMENSIONAL *pdl) { PCPOINTLIST *pl; PCPATCH_DIMENSIONAL *pdl_uncompressed; const PCSCHEMA *schema = pdl->schema; int i, j, ndims, npoints; assert(pdl); pdl_uncompressed = pc_patch_dimensional_decompress(pdl); ndims = schema->ndims; npoints = pdl->npoints; pl = pc_pointlist_make(npoints); for ( i = 0; i < npoints; i++ ) { PCPOINT *pt = pc_point_make(schema); for ( j = 0; j < ndims; j++ ) { PCDIMENSION *dim = pc_schema_get_dimension(schema, j); uint8_t *in = pdl_uncompressed->bytes[j].bytes + dim->size * i; uint8_t *out = pt->data + dim->byteoffset; memcpy(out, in, dim->size); } pc_pointlist_add_point(pl, pt); } pc_patch_dimensional_free(pdl_uncompressed); return pl; }
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); }
int pc_point_get_double_by_index(const PCPOINT *pt, uint32_t idx, double *val) { PCDIMENSION *dim; dim = pc_schema_get_dimension(pt->schema, idx); return pc_point_get_double(pt, dim, val); }
int pc_point_get_double_by_index(const PCPOINT *pt, uint32_t idx, double *d) { PCDIMENSION *dim; dim = pc_schema_get_dimension(pt->schema, idx); if ( ! dim ) return PC_FAILURE; return pc_point_get_double(pt, dim, d); }
/** get point n, 0-based, positive */ PCPOINT *pc_patch_dimensional_pointn(const PCPATCH_DIMENSIONAL *pdl, int n) { assert(pdl); assert(pdl->schema); int i; int ndims = pdl->schema->ndims; PCPOINT *pt = pc_point_make(pdl->schema); uint8_t *buf = pt->data; for ( i = 0; i < ndims; i++ ) { PCDIMENSION *dim = pc_schema_get_dimension(pdl->schema, i); pc_bytes_to_ptr(buf+dim->byteoffset,pdl->bytes[i], n); } return pt; }
PCPATCH_UNCOMPRESSED * pc_patch_uncompressed_from_dimensional(const PCPATCH_DIMENSIONAL *pdl) { int i, j, npoints; PCPATCH_UNCOMPRESSED *patch; PCPATCH_DIMENSIONAL *pdl_uncompressed; const PCSCHEMA *schema; uint8_t *buf; npoints = pdl->npoints; schema = pdl->schema; patch = pcalloc(sizeof(PCPATCH_UNCOMPRESSED)); patch->type = PC_NONE; patch->readonly = PC_FALSE; patch->schema = schema; patch->npoints = npoints; patch->maxpoints = npoints; patch->bounds = pdl->bounds; patch->stats = pc_stats_clone(pdl->stats); patch->datasize = schema->size * pdl->npoints; patch->data = pcalloc(patch->datasize); buf = patch->data; /* Can only read from uncompressed dimensions */ pdl_uncompressed = pc_patch_dimensional_decompress(pdl); for ( i = 0; i < npoints; i++ ) { for ( j = 0; j < schema->ndims; j++ ) { PCDIMENSION *dim = pc_schema_get_dimension(schema, j); uint8_t *in = pdl_uncompressed->bytes[j].bytes + dim->size * i; uint8_t *out = buf + dim->byteoffset; memcpy(out, in, dim->size); } buf += schema->size; } pc_patch_dimensional_free(pdl_uncompressed); return patch; }
PCPATCH_DIMENSIONAL * pc_patch_dimensional_from_uncompressed(const PCPATCH_UNCOMPRESSED *pa) { PCPATCH_DIMENSIONAL *pdl; const PCSCHEMA *schema; int i, j, ndims, npoints; assert(pa); npoints = pa->npoints; schema = pa->schema; ndims = schema->ndims; /* Cannot handle empty patches */ if ( npoints == 0 ) return NULL; /* Initialize dimensional */ pdl = pcalloc(sizeof(PCPATCH_DIMENSIONAL)); pdl->type = PC_DIMENSIONAL; pdl->readonly = PC_FALSE; pdl->schema = schema; pdl->npoints = npoints; pdl->bounds = pa->bounds; pdl->stats = pc_stats_clone(pa->stats); pdl->bytes = pcalloc(ndims * sizeof(PCBYTES)); for ( i = 0; i < ndims; i++ ) { PCDIMENSION *dim = pc_schema_get_dimension(schema, i); pdl->bytes[i] = pc_bytes_make(dim, npoints); for ( j = 0; j < npoints; j++ ) { uint8_t *to = pdl->bytes[i].bytes + dim->size * j; uint8_t *from = pa->data + schema->size * j + dim->byteoffset; memcpy(to, from, dim->size); } } return pdl; }
static void test_dimension_byteoffsets() { PCDIMENSION *d; int i; int prev_byteoffset; int prev_size; int pc_size; for ( i = 0; i < schema->ndims; i++ ) { d = pc_schema_get_dimension(schema, i); // printf("d=%d name='%s' size=%d byteoffset=%d\n", i, d->name, d->size, d->byteoffset); if ( i > 0 ) { CU_ASSERT_EQUAL(prev_size, pc_size); CU_ASSERT_EQUAL(prev_size, d->byteoffset - prev_byteoffset); } prev_byteoffset = d->byteoffset; prev_size = d->size; pc_size = pc_interpretation_size(d->interpretation); } }
PCPATCH_GHT * pc_patch_ght_filter(const PCPATCH_GHT *patch, uint32_t dimnum, PC_FILTERTYPE filter, double val1, double val2) { #ifndef HAVE_LIBGHT pcerror("%s: libght support is not enabled", __func__); return NULL; #else /* byte: endianness (1 = NDR, 0 = XDR) uint32: pcid (key to POINTCLOUD_SCHEMAS) uint32: compression (0 = no compression, 1 = dimensional, 2 = GHT) uint32: npoints uint32: ghtsize uint8[]: ghtbuffer */ GhtTreePtr tree; GhtTreePtr tree_filtered; GhtErr err; GhtWriterPtr writer; GhtArea area; const char *dimname; const PCDIMENSION *dim; PCPATCH_GHT *paght; int npoints; /* Echo null back */ if ( ! patch ) return NULL; /* Get a tree */ tree = ght_tree_from_pc_patch(patch); if ( ! tree ) pcerror("%s: call to ght_tree_from_pc_patch failed", __func__); /* Get dimname */ dim = pc_schema_get_dimension(patch->schema, dimnum); if ( ! dim ) pcerror("%s: invalid dimension number (%d)", __func__, dimnum); dimname = dim->name; switch ( filter ) { case PC_GT: err = ght_tree_filter_greater_than(tree, dimname, val1 > val2 ? val1 : val2, &tree_filtered); break; case PC_LT: err = ght_tree_filter_less_than(tree, dimname, val1 < val2 ? val1 : val2, &tree_filtered); break; case PC_EQUAL: err = ght_tree_filter_equal(tree, dimname, val1, &tree_filtered); break; case PC_BETWEEN: err = ght_tree_filter_between(tree, dimname, val1, val2, &tree_filtered); break; default: pcerror("%s: invalid filter type (%d)", __func__, filter); return NULL; } /* ght_tree_filter_* returns a tree with NULL tree element and npoints == 0 */ /* for empty filter results (everything got filtered away) */ if ( err != GHT_OK || ! tree_filtered ) pcerror("%s: ght_tree_filter failed", __func__); /* Read numpoints left in patch */ ght_tree_get_numpoints(tree_filtered, &(npoints)); /* Allocate a fresh GHT patch for output */ paght = pcalloc(sizeof(PCPATCH_GHT)); paght->type = PC_GHT; paght->readonly = PC_FALSE; paght->schema = patch->schema; paght->npoints = npoints; /* No points, not much to do... */ if ( ! npoints ) { paght->ghtsize = 0; paght->ght = NULL; } else { /* Calculate bounds and save */ if ( GHT_OK != ght_tree_get_extent(tree_filtered, &area) ) pcerror("%s: ght_tree_get_extent failed", __func__); paght->bounds.xmin = area.x.min; paght->bounds.xmax = area.x.max; paght->bounds.ymin = area.y.min; paght->bounds.ymax = area.y.max; /* TODO: Replace this; need to update stats too */ paght->stats = pc_stats_clone(patch->stats); /* Convert the tree to a memory buffer */ ght_writer_new_mem(&writer); ght_tree_write(tree_filtered, writer); ght_writer_get_size(writer, &(paght->ghtsize)); paght->ght = pcalloc(paght->ghtsize); ght_writer_get_bytes(writer, paght->ght); ght_writer_free(writer); } // ght_tree_free(tree_filtered); // ght_tree_free(tree); return paght; #endif }
PCPATCH_GHT * pc_patch_ght_from_uncompressed(const PCPATCH_UNCOMPRESSED *pa) { #ifndef HAVE_LIBGHT pcerror("%s: libght support is not enabled", __func__); return NULL; #else int i, j; int pointcount = 0; GhtSchemaPtr schema; GhtTreePtr tree; GhtCoordinate coord; GhtNodePtr node; PCPOINT pt; PCDIMENSION *xdim, *ydim; PCPATCH_GHT *paght = NULL; size_t pt_size = pa->schema->size; /* Cannot handle empty patches */ if ( ! pa || ! pa->npoints ) return NULL; pt.schema = pa->schema; pt.readonly = PC_TRUE; xdim = pa->schema->dims[pa->schema->x_position]; ydim = pa->schema->dims[pa->schema->y_position]; schema = ght_schema_from_pc_schema(pa->schema); if ( ght_tree_new(schema, &tree) != GHT_OK ) { pcerror("ght_tree_new failed"); return NULL; } /* Build up the tree from the points. */ for ( i = 0; i < pa->npoints; i++ ) { pt.data = pa->data + pt_size * i; pc_point_get_double(&pt, xdim, &(coord.x)); pc_point_get_double(&pt, ydim, &(coord.y)); /* Build a node from the x/y information */ /* TODO, make resolution configurable from the schema */ if ( ght_node_new_from_coordinate(&coord, GHT_MAX_HASH_LENGTH, &node) == GHT_OK ) { unsigned int num_dims; ght_schema_get_num_dimensions(schema, &num_dims); /* Add attributes to the node */ for ( j = 0; j < num_dims; j++ ) { PCDIMENSION *dim; GhtDimensionPtr ghtdim; GhtAttributePtr attr; double val; /* Don't add X or Y as attributes, they are already embodied in the hash */ if ( j == pa->schema->x_position || j == pa->schema->y_position ) continue; dim = pc_schema_get_dimension(pa->schema, j); pc_point_get_double(&pt, dim, &val); ght_schema_get_dimension_by_index(schema, j, &ghtdim); ght_attribute_new_from_double(ghtdim, val, &attr); ght_node_add_attribute(node, attr); } /* Add the node to the tree */ /* TODO, make duplicate handling configurable from the schema */ if ( ght_tree_insert_node(tree, node) == GHT_OK ) { pointcount++; } else { // ght_tree_free(tree); pcerror("ght_tree_insert_node failed"); return NULL; } } else { ght_tree_free(tree); pcerror("ght_node_new_from_coordinate failed"); return NULL; } } /* Compact the tree */ if ( ght_tree_compact_attributes(tree) == GHT_OK ) { GhtWriterPtr writer; paght = pcalloc(sizeof(PCPATCH_GHT)); paght->type = PC_GHT; paght->readonly = PC_FALSE; paght->schema = pa->schema; paght->npoints = pointcount; paght->bounds = pa->bounds; paght->stats = pc_stats_clone(pa->stats); /* Convert the tree to a memory buffer */ ght_writer_new_mem(&writer); ght_tree_write(tree, writer); ght_writer_get_size(writer, &(paght->ghtsize)); paght->ght = pcalloc(paght->ghtsize); ght_writer_get_bytes(writer, paght->ght); ght_writer_free(writer); } // Let the hierarchical memory manager clean up the tree // ght_tree_free(tree); return paght; #endif }