예제 #1
0
PCPATCH_DIMENSIONAL *
pc_patch_dimensional_compress(const PCPATCH_DIMENSIONAL *pdl, PCDIMSTATS *pds_in)
{
	int i;
	int ndims = pdl->schema->ndims;
	PCPATCH_DIMENSIONAL *pdl_compressed;
	PCDIMSTATS *pds = pds_in;

	assert(pdl);
	assert(pdl->schema);

	if ( ! pds )
		pds = pc_dimstats_make(pdl->schema);

	/* Still sampling, update stats */
	if ( pds->total_points < PCDIMSTATS_MIN_SAMPLE )
		pc_dimstats_update(pds, pdl);

	pdl_compressed = pcalloc(sizeof(PCPATCH_DIMENSIONAL));
	memcpy(pdl_compressed, pdl, sizeof(PCPATCH_DIMENSIONAL));
	pdl_compressed->bytes = pcalloc(ndims*sizeof(PCBYTES));
	pdl_compressed->stats = pc_stats_clone(pdl->stats);

	/* Compress each dimension as dictated by stats */
	for ( i = 0; i < ndims; i++ )
	{
		pdl_compressed->bytes[i] = pc_bytes_encode(pdl->bytes[i], pds->stats[i].recommended_compression);
	}

	if ( pds != pds_in ) pc_dimstats_free(pds);

	return pdl_compressed;
}
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;
}
예제 #3
0
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;
}
예제 #4
0
static PCPATCH_DIMENSIONAL *
pc_patch_dimensional_filter(const PCPATCH_DIMENSIONAL *pdl, const PCBITMAP *map)
{
	int i = 0;
	PCPATCH_DIMENSIONAL *fpdl = pc_patch_dimensional_clone(pdl);

    fpdl->stats = pc_stats_clone(pdl->stats);
	fpdl->npoints = map->nset;

	for ( i = 0; i < pdl->schema->ndims; i++ )
	{
        PCDOUBLESTAT stats;
        stats.min = FLT_MAX;
        stats.max = FLT_MIN;
        stats.sum = 0;
		fpdl->bytes[i] = pc_bytes_filter(&(pdl->bytes[i]), map, &stats);

		/* Save the X/Y stats for use in bounds later */
		if ( i == pdl->schema->x_position )
		{
            fpdl->bounds.xmin = stats.min;
            fpdl->bounds.xmax = stats.max;
        }
		else if ( i == pdl->schema->y_position )
		{
            fpdl->bounds.ymin = stats.min;
            fpdl->bounds.ymax = stats.max;
        }

        pc_point_set_double_by_index(&(fpdl->stats->min), i, stats.min);
        pc_point_set_double_by_index(&(fpdl->stats->max), i, stats.max);
        pc_point_set_double_by_index(&(fpdl->stats->avg), i, stats.sum/fpdl->npoints);
	}

	return fpdl;
}
예제 #5
0
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
}
예제 #6
0
PCPATCH_UNCOMPRESSED *
pc_patch_uncompressed_from_ght(const PCPATCH_GHT *paght)
{
#ifndef HAVE_LIBGHT
	pcerror("%s: libght support is not enabled", __func__);
	return NULL;
#else
	int i, npoints;
	PCPATCH_UNCOMPRESSED *patch;
	PCPOINT point;
	const PCSCHEMA *schema;
	GhtNodeListPtr nodelist;
	GhtCoordinate coord;
	GhtNodePtr node;
	GhtTreePtr tree;
	GhtAttributePtr attr;

	/* Build a structured tree from the tree serialization */
	if ( ! paght || ! paght->ght ) return NULL;
	tree = ght_tree_from_pc_patch(paght);
	if ( ! tree ) return NULL;

	/* Convert tree to nodelist */
	ght_nodelist_new(paght->npoints, &nodelist);
	ght_tree_to_nodelist(tree, nodelist);

	/* Allocate uncompressed patch */
	ght_nodelist_get_num_nodes(nodelist, &npoints);
	schema = paght->schema;
	patch = pcalloc(sizeof(PCPATCH_UNCOMPRESSED));
	patch->type = PC_NONE;
	patch->readonly = PC_FALSE;
	patch->schema = schema;
	patch->npoints = npoints;
	patch->bounds = paght->bounds;
	patch->stats = pc_stats_clone(paght->stats);
	patch->maxpoints = npoints;
	patch->datasize = schema->size * npoints;
	patch->data = pcalloc(patch->datasize);

	/* Set up utility point */
	point.schema = schema;
	point.readonly = PC_FALSE;
	point.data = patch->data;

	/* Process each point... */
	for ( i = 0; i < npoints; i++ )
	{
		double val;

		/* Read and set X and Y */
		ght_nodelist_get_node(nodelist, i, &node);
		ght_node_get_coordinate(node, &coord);
		pc_point_set_x(&point, coord.x);
		pc_point_set_y(&point, coord.y);

		/* Read and set all the attributes */
		ght_node_get_attributes(node, &attr);
		while ( attr )
		{
			GhtDimensionPtr dim;
			const char *name;
			ght_attribute_get_value(attr, &val);
			ght_attribute_get_dimension(attr, &dim);
			ght_dimension_get_name(dim, &name);
			pc_point_set_double_by_name(&point, name, val);
			ght_attribute_get_next(attr, &attr);
		}
		point.data += schema->size;
	}

	/* Done w/ nodelist and tree */
	ght_nodelist_free_deep(nodelist);
	// ght_tree_free(tree);

	/* Done */
	return patch;
#endif
}
예제 #7
0
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
}