1 /***********************************************************************
2 * pc_pointlist.c
3 *
4 *  Point list handling. Create, get and set values from the
5 *  basic PCPOINTLIST structure.
6 *
7 *  PgSQL Pointcloud is free and open source software provided
8 *  by the Government of Canada
9 *  Copyright (c) 2013 Natural Resources Canada
10 *
11 ***********************************************************************/
12 
13 #include "pc_api_internal.h"
14 #include <assert.h>
15 
16 PCPOINTLIST *
pc_pointlist_make(uint32_t npoints)17 pc_pointlist_make(uint32_t npoints)
18 {
19 	PCPOINTLIST *pl = pcalloc(sizeof(PCPOINTLIST));
20 	pl->points = pcalloc(sizeof(PCPOINT*) * npoints);
21 	pl->maxpoints = npoints;
22 	pl->npoints = 0;
23 	pl->mem = NULL;
24 	return pl;
25 }
26 
27 void
pc_pointlist_free(PCPOINTLIST * pl)28 pc_pointlist_free(PCPOINTLIST *pl)
29 {
30 	int i;
31 	for ( i = 0; i < pl->npoints; i++ )
32 	{
33 		pc_point_free(pl->points[i]);
34 	}
35 	if ( pl->mem )
36 		pcfree(pl->mem);
37 	pcfree(pl->points);
38 	pcfree(pl);
39 	return;
40 }
41 
42 void
pc_pointlist_add_point(PCPOINTLIST * pl,PCPOINT * pt)43 pc_pointlist_add_point(PCPOINTLIST *pl, PCPOINT *pt)
44 {
45 	if ( pl->npoints >= pl->maxpoints )
46 	{
47 		if ( pl->maxpoints < 1 ) pl->maxpoints = 1;
48 		pl->maxpoints *= 2;
49 		pl->points = pcrealloc(pl->points, pl->maxpoints * sizeof(PCPOINT*));
50 	}
51 
52 	pl->points[pl->npoints] = pt;
53 	pl->npoints += 1;
54 	return;
55 }
56 
57 PCPOINT *
pc_pointlist_get_point(const PCPOINTLIST * pl,int i)58 pc_pointlist_get_point(const PCPOINTLIST *pl, int i)
59 {
60 	return pl->points[i];
61 }
62 
63 PCPOINTLIST *
pc_pointlist_from_dimensional(const PCPATCH_DIMENSIONAL * pdl)64 pc_pointlist_from_dimensional(const PCPATCH_DIMENSIONAL *pdl)
65 {
66 	PCPOINTLIST *pl;
67 	PCPATCH_DIMENSIONAL *pdl_uncompressed;
68 	const PCSCHEMA *schema = pdl->schema;
69 	int i, j, ndims, npoints;
70 	uint8_t *data;
71 	assert(pdl);
72 
73 	pdl_uncompressed = pc_patch_dimensional_decompress(pdl);
74 
75 	ndims = schema->ndims;
76 	npoints = pdl->npoints;
77 	pl = pc_pointlist_make(npoints);
78 	pl->mem = data = pcalloc(npoints * schema->size);
79 
80 	for ( i = 0; i < npoints; i++ )
81 	{
82 		PCPOINT *pt = pc_point_from_data(schema,data);
83 		for ( j = 0; j < ndims; j++ )
84 		{
85 			PCDIMENSION *dim = pc_schema_get_dimension(schema, j);
86 
87 			uint8_t *in = pdl_uncompressed->bytes[j].bytes + dim->size * i;
88 			uint8_t *out = data + dim->byteoffset;
89 			memcpy(out, in, dim->size);
90 		}
91 		pc_pointlist_add_point(pl, pt);
92 		data += schema->size;
93 	}
94 	pc_patch_dimensional_free(pdl_uncompressed);
95 
96 	return pl;
97 }
98 
99 PCPOINTLIST *
pc_pointlist_from_uncompressed(const PCPATCH_UNCOMPRESSED * patch)100 pc_pointlist_from_uncompressed(const PCPATCH_UNCOMPRESSED *patch)
101 {
102 	int i;
103 	PCPOINTLIST *pl;
104 	size_t pt_size = patch->schema->size;
105 	uint32_t npoints = patch->npoints;
106 
107 	pl = pc_pointlist_make(npoints);
108 	for ( i = 0; i < npoints; i++ )
109 	{
110 		pc_pointlist_add_point(pl, pc_point_from_data(patch->schema, patch->data + i*pt_size));
111 	}
112 	return pl;
113 }
114 
115 PCPOINTLIST *
pc_pointlist_from_patch(const PCPATCH * patch)116 pc_pointlist_from_patch(const PCPATCH *patch)
117 {
118 	switch ( patch->type )
119 	{
120 	case PC_NONE:
121 	{
122 		return pc_pointlist_from_uncompressed((PCPATCH_UNCOMPRESSED*)patch);
123 	}
124 	case PC_DIMENSIONAL:
125 	{
126 		return pc_pointlist_from_dimensional((PCPATCH_DIMENSIONAL*)patch);
127 	}
128 	case PC_LAZPERF:
129 	{
130 		return pc_pointlist_from_lazperf((PCPATCH_LAZPERF*)patch);
131 	}
132 	}
133 
134 	/* Don't get here */
135 	pcerror("pc_pointlist_from_patch: unsupported compression type %d", patch->type);
136 	return NULL;
137 }
138