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