Ejemplo n.º 1
0
static void
test_sort_simple()
{
	// 00 endian (big)
	// 00000000 pcid
	// 00000000 compression
	// 00000002 npoints
	// 0000000800000003000000050006 pt1 (XYZi)
	// 0000000200000001000000040008 pt2 (XYZi)

	// init data
	PCPOINTLIST *lisort;
	PCPATCH *pasort;
	double d1;
	double d2;
	char *hexbuf = "0000000000000000000000000200000008000000030000000500060000000200000001000000040008";
	size_t hexsize = strlen(hexbuf);

	uint8_t *wkb = bytes_from_hexbytes(hexbuf, hexsize);
	PCPATCH *pa = pc_patch_from_wkb(schema, wkb, hexsize/2);
	PCPOINTLIST *li = pc_pointlist_from_patch(pa);
	const char *X[] = {"X"};

	// check that initial data are not sorted
	pc_point_get_double_by_name(pc_pointlist_get_point(li, 0), "X", &d1);
	pc_point_get_double_by_name(pc_pointlist_get_point(li, 1), "X", &d2);

	CU_ASSERT_DOUBLE_EQUAL(d1, 0.08, precision);
	CU_ASSERT_DOUBLE_EQUAL(d2, 0.02, precision);

	// sort on X attribute and check if data are well sorted
	pasort = pc_patch_sort(pa, X, 1);
	lisort = pc_pointlist_from_patch(pasort);

	pc_point_get_double_by_name(pc_pointlist_get_point(lisort, 0), "X", &d1);
	pc_point_get_double_by_name(pc_pointlist_get_point(lisort, 1), "X", &d2);

	CU_ASSERT_DOUBLE_EQUAL(d1, 0.02, precision);
	CU_ASSERT_DOUBLE_EQUAL(d2, 0.08, precision);

	// free
	pc_pointlist_free(li);
	pc_pointlist_free(lisort);
	pc_patch_free(pa);
	pc_patch_free(pasort);
	pcfree(wkb);
}
Ejemplo n.º 2
0
static void
test_patch_hex_in()
{
	// 00 endian (big)
	// 00000000 pcid
	// 00000000 compression
	// 00000002 npoints
	// 0000000200000003000000050006 pt1 (XYZi)
	// 0000000200000003000000050008 pt2 (XYZi)
	char *hexbuf = "0000000000000000000000000200000002000000030000000500060000000200000003000000050008";

	double d;
	char *str;
	size_t hexsize = strlen(hexbuf);
	uint8_t *wkb = bytes_from_hexbytes(hexbuf, hexsize);
	PCPATCH *pa = pc_patch_from_wkb(simpleschema, wkb, hexsize/2);
	PCPOINTLIST *pl = pc_pointlist_from_patch(pa);

	pc_point_get_double_by_name(pc_pointlist_get_point(pl, 0), "X", &d);
	CU_ASSERT_DOUBLE_EQUAL(d, 0.02, 0.000001);
	pc_point_get_double_by_name(pc_pointlist_get_point(pl, 1), "Intensity", &d);
	CU_ASSERT_DOUBLE_EQUAL(d, 8, 0.000001);

	pc_point_get_double_by_name(&(pa->stats->min), "Intensity", &d);
	CU_ASSERT_DOUBLE_EQUAL(d, 6, 0.000001);
	pc_point_get_double_by_name(&(pa->stats->max), "Intensity", &d);
	CU_ASSERT_DOUBLE_EQUAL(d, 8, 0.000001);
	pc_point_get_double_by_name(&(pa->stats->avg), "Intensity", &d);
	CU_ASSERT_DOUBLE_EQUAL(d, 7, 0.000001);

	str = pc_patch_to_string(pa);
	CU_ASSERT_STRING_EQUAL(str, "{\"pcid\":0,\"pts\":[[0.02,0.03,0.05,6],[0.02,0.03,0.05,8]]}");
	// printf("\n%s\n",str);
	pcfree(str);

	pc_pointlist_free(pl);
	pc_patch_free(pa);
	pcfree(wkb);
}
Ejemplo n.º 3
0
/**
* Pivot a pointlist into a dimlist and back.
* Test for data loss or alteration.
*/
static void
test_patch_dimensional()
{
	PCPOINT *pt;
	int i;
	int npts = 10;
	PCPOINTLIST *pl1, *pl2;
	PCPATCH_DIMENSIONAL *pdl;
	PCDIMSTATS *pds;

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

	pdl = pc_patch_dimensional_from_pointlist(pl1);
	pl2 = pc_pointlist_from_dimensional(pdl);

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

	pds = pc_dimstats_make(simpleschema);
	pc_dimstats_update(pds, pdl);
	pc_dimstats_update(pds, pdl);


	pc_patch_free((PCPATCH*)pdl);
	pc_pointlist_free(pl1);
	pc_pointlist_free(pl2);
	pc_dimstats_free(pds);
}
/* TODO: expose to API ? Would require also exposing stringbuffer
*  See https://github.com/pgpointcloud/pointcloud/issues/74
*/
static int
pc_patch_uncompressed_to_stringbuffer(const PCPATCH_UNCOMPRESSED *patch, stringbuffer_t *sb)
{
	PCPOINTLIST *pl;
	int i, j;

	/* { "pcid":1, "points":[[<dim1>, <dim2>, <dim3>, <dim4>],[<dim1>, <dim2>, <dim3>, <dim4>]] }*/

	/* TODO: reserve space in buffer ? */

	pl = pc_pointlist_from_uncompressed(patch);
	stringbuffer_aprintf(sb, "{\"pcid\":%d,\"pts\":[", patch->schema->pcid);
	for ( i = 0; i < pl->npoints; i++ )
	{
		PCPOINT *pt = pc_pointlist_get_point(pl, i);
		if ( i ) stringbuffer_append(sb, ",[");
		else stringbuffer_append(sb, "[");
		for ( j = 0; j < pt->schema->ndims; j++ )
		{
			double d;
			if ( ! pc_point_get_double_by_index(pt, j, &d))
			{
				pcerror("%s: unable to read double at index %d", __func__, j);
				return PC_FAILURE;
			}
			if ( j ) stringbuffer_aprintf(sb, ",%g", d);
			else stringbuffer_aprintf(sb, "%g", d);
		}
		stringbuffer_append(sb, "]");
	}
	stringbuffer_append(sb, "]}");

	/* All done, copy and clean up */
	pc_pointlist_free(pl);

	return PC_SUCCESS;
}
PCPATCH_UNCOMPRESSED *
pc_patch_uncompressed_from_pointlist(const PCPOINTLIST *pl)
{
	PCPATCH_UNCOMPRESSED *pch;
	const PCSCHEMA *s;
	PCPOINT *pt;
	uint8_t *ptr;
	int i;
	uint32_t numpts;

	if ( ! pl )
	{
		pcerror("%s: null PCPOINTLIST passed in", __func__);
		return NULL;
	}

	numpts = pl->npoints;
	if ( ! numpts )
	{
		pcerror("%s: zero size PCPOINTLIST passed in", __func__);
		return NULL;
	}

	/* Assume the first PCSCHEMA is the same as the rest for now */
	/* We will check this as we go along */
	pt = pc_pointlist_get_point(pl, 0);
	s = pt->schema;

	/* Confirm we have a schema pointer */
	if ( ! s )
	{
		pcerror("%s: null schema encountered", __func__);
		return NULL;
	}

	/* Confirm width of a point data buffer */
	if ( ! s->size )
	{
		pcerror("%s: invalid point size", __func__);
		return NULL;
	}

	/* Make our own data area */
	pch = pcalloc(sizeof(PCPATCH_UNCOMPRESSED));
	pch->datasize = s->size * numpts;
	pch->data = pcalloc(pch->datasize);
	ptr = pch->data;

	/* Initialize bounds */
	pc_bounds_init(&(pch->bounds));

	/* Set up basic info */
	pch->readonly = PC_FALSE;
	pch->maxpoints = numpts;
	pch->type = PC_NONE;
	pch->schema = s;
	pch->npoints = 0;

	for ( i = 0; i < numpts; i++ )
	{
		pt = pc_pointlist_get_point(pl, i);
		if ( pt )
		{
			if ( pt->schema->pcid != s->pcid )
			{
				pcerror("%s: points do not share a schema", __func__);
				return NULL;
			}
			memcpy(ptr, pt->data, s->size);
			pch->npoints++;
			ptr += s->size;
		}
		else
		{
			pcwarn("%s: encountered null point", __func__);
		}
	}

	if ( PC_FAILURE == pc_patch_uncompressed_compute_extent(pch) )
	{
		pcerror("%s: failed to compute patch extent", __func__);
		return NULL;
	}

	if ( PC_FAILURE == pc_patch_uncompressed_compute_stats(pch) )
	{
		pcerror("%s: failed to compute patch stats", __func__);
		return NULL;
	}

	return pch;
}
Ejemplo n.º 6
0
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_free((PCPATCH*)pch1);
	pc_patch_free((PCPATCH*)pch2);
	pc_pointlist_free(pl1);
	pc_pointlist_free(pl2);
	if ( pds ) pc_dimstats_free(pds);
}
Ejemplo n.º 7
0
Datum pcpatch_unnest(PG_FUNCTION_ARGS)
{
	typedef struct
	{
		int nextelem;
		int numelems;
		PCPOINTLIST *pointlist;
	} pcpatch_unnest_fctx;

	FuncCallContext *funcctx;
	pcpatch_unnest_fctx *fctx;
	MemoryContext oldcontext;

	/* stuff done only on the first call of the function */
	if (SRF_IS_FIRSTCALL())
	{		
		PCPATCH *patch;
		SERIALIZED_PATCH *serpatch;
		
		/* create a function context for cross-call persistence */
		funcctx = SRF_FIRSTCALL_INIT();

		/*
		* switch to memory context appropriate for multiple function calls
		*/
		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

		/*
		* Get the patch value and detoast if needed.  We can't do this
		* earlier because if we have to detoast, we want the detoasted copy
		* to be in multi_call_memory_ctx, so it will go away when we're done
		* and not before.      (If no detoast happens, we assume the originally
		* passed array will stick around till then.)
		*/
		serpatch = PG_GETARG_SERPATCH_P(0);
		patch = pc_patch_deserialize(serpatch, pc_schema_from_pcid_uncached(serpatch->pcid));

		/* allocate memory for user context */
		fctx = (pcpatch_unnest_fctx *) palloc(sizeof(pcpatch_unnest_fctx));

		/* initialize state */
		fctx->nextelem = 0;
		fctx->numelems = patch->npoints;
		fctx->pointlist = pc_pointlist_from_patch(patch);

		/* save user context, switch back to function context */
		funcctx->user_fctx = fctx;
		MemoryContextSwitchTo(oldcontext);
	}

	/* stuff done on every call of the function */
	funcctx = SRF_PERCALL_SETUP();
	fctx = funcctx->user_fctx;

	if (fctx->nextelem < fctx->numelems)
	{
		Datum elem;
		PCPOINT *pt = pc_pointlist_get_point(fctx->pointlist, fctx->nextelem);
		SERIALIZED_POINT *serpt = pc_point_serialize(pt);
		fctx->nextelem++;
		elem = PointerGetDatum(serpt);
		SRF_RETURN_NEXT(funcctx, elem);
	}
	else
	{
		/* do when there is no more left */
		SRF_RETURN_DONE(funcctx);
	}
}