PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ ptarray_to_twkb_buf()

static int ptarray_to_twkb_buf ( const POINTARRAY pa,
TWKB_GLOBALS globals,
TWKB_STATE ts,
int  register_npoints,
uint32_t  minpoints 
)
static

Stores a pointarray as varints in the buffer @register_npoints, controls whether an npoints entry is added to the buffer (used to skip npoints for point types) @dimension, states the dimensionality of object this array is part of (0 = point, 1 = linear, 2 = areal)

Definition at line 107 of file lwout_twkb.c.

108{
109 uint32_t ndims = FLAGS_NDIMS(pa->flags);
110 uint32_t i, j;
111 bytebuffer_t b;
112 bytebuffer_t *b_p;
113 int64_t nextdelta[MAX_N_DIMS];
114 int npoints = 0;
115 size_t npoints_offset = 0;
116 uint32_t max_points_left = pa->npoints;
117
118 LWDEBUGF(2, "Entered %s", __func__);
119
120 /* Dispense with the empty case right away */
121 if ( pa->npoints == 0 && register_npoints )
122 {
123 LWDEBUGF(4, "Register npoints:%d", pa->npoints);
125 return 0;
126 }
127
128 /* If npoints is more than 127 it is unpredictable how many bytes npoints will need */
129 /* Then we have to store the deltas in a temp buffer to later add them after npoints */
130 /* If noints is below 128 we know 1 byte will be needed */
131 /* Then we can make room for that 1 byte at once and write to */
132 /* ordinary buffer */
133 if( pa->npoints > 127 )
134 {
135 /* Independent buffer to hold the coordinates, so we can put the npoints */
136 /* into the stream once we know how many points we actually have */
137 bytebuffer_init_with_size(&b, (size_t)3 * ndims * pa->npoints);
138 b_p = &b;
139 }
140 else
141 {
142 /* We give an alias to our ordinary buffer */
143 b_p = ts->geom_buf;
144 if ( register_npoints )
145 {
146 /* We do not store a pointer to the place where we want the npoints value */
147 /* Instead we store how far from the beginning of the buffer we want the value */
148 /* That is because we otherwise will get in trouble if the buffer is reallocated */
149 npoints_offset = b_p->writecursor - b_p->buf_start;
150
151 /* We just move the cursor 1 step to make room for npoints byte */
152 /* We use the function append_byte even if we have no value yet, */
153 /* since that gives us the check for big enough buffer and moves the cursor */
155 }
156 }
157
158 for ( i = 0; i < pa->npoints; i++ )
159 {
160 double *dbl_ptr = (double*)getPoint_internal(pa, i);
161 int64_t diff = 0;
162
163 /* Write this coordinate to the buffer as a varint */
164 for ( j = 0; j < ndims; j++ )
165 {
166 /* To get the relative coordinate we don't get the distance */
167 /* from the last point but instead the distance from our */
168 /* last accumulated point. This is important to not build up an */
169 /* accumulated error when rounding the coordinates */
170 nextdelta[j] = (int64_t) llround(globals->factor[j] * dbl_ptr[j]) - ts->accum_rels[j];
171 LWDEBUGF(4, "deltavalue: %lld, ", nextdelta[j]);
172 diff += llabs(nextdelta[j]);
173 }
174
175 /* Skipping the first point is not allowed */
176 /* If the sum(abs()) of all the deltas was zero, */
177 /* then this was a duplicate point, so we can ignore it */
178 if ( i > 0 && diff == 0 && max_points_left > minpoints )
179 {
180 max_points_left--;
181 continue;
182 }
183
184 /* We really added a point, so... */
185 npoints++;
186
187 /* Write this vertex to the temporary buffer as varints */
188 for ( j = 0; j < ndims; j++ )
189 {
190 ts->accum_rels[j] += nextdelta[j];
191 bytebuffer_append_varint(b_p, nextdelta[j]);
192 }
193
194 /* See if this coordinate expands the bounding box */
195 if( globals->variant & TWKB_BBOX )
196 {
197 for ( j = 0; j < ndims; j++ )
198 {
199 if( ts->accum_rels[j] > ts->bbox_max[j] )
200 ts->bbox_max[j] = ts->accum_rels[j];
201
202 if( ts->accum_rels[j] < ts->bbox_min[j] )
203 ts->bbox_min[j] = ts->accum_rels[j];
204 }
205 }
206
207 }
208
209 if ( pa->npoints > 127 )
210 {
211 /* Now write the temporary results into the main buffer */
212 /* First the npoints */
213 if ( register_npoints )
215 /* Now the coordinates */
217
218 /* Clear our temporary buffer */
220 }
221 else
222 {
223 /* If we didn't use a temp buffer, we just write that npoints value */
224 /* to where it belongs*/
225 if ( register_npoints )
226 varint_u64_encode_buf(npoints, b_p->buf_start + npoints_offset);
227 }
228
229 return 0;
230}
void bytebuffer_destroy_buffer(bytebuffer_t *s)
Free the bytebuffer_t and all memory managed within it.
Definition bytebuffer.c:56
void bytebuffer_append_bytebuffer(bytebuffer_t *write_to, bytebuffer_t *write_from)
Writes a uint8_t value to the buffer.
Definition bytebuffer.c:140
void bytebuffer_append_byte(bytebuffer_t *s, const uint8_t val)
Writes a uint8_t value to the buffer.
Definition bytebuffer.c:127
void bytebuffer_append_uvarint(bytebuffer_t *b, const uint64_t val)
Writes a unsigned varInt to the buffer.
Definition bytebuffer.c:165
void bytebuffer_append_varint(bytebuffer_t *b, const int64_t val)
Writes a signed varInt to the buffer.
Definition bytebuffer.c:154
void bytebuffer_init_with_size(bytebuffer_t *s, size_t size)
Allocate just the internal buffer of an existing bytebuffer_t struct.
Definition bytebuffer.c:36
#define FLAGS_NDIMS(flags)
Definition liblwgeom.h:179
#define TWKB_BBOX
Definition liblwgeom.h:2227
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:106
static uint8_t * getPoint_internal(const POINTARRAY *pa, uint32_t n)
Definition lwinline.h:75
#define MAX_N_DIMS
Definition lwout_twkb.h:43
lwflags_t flags
Definition liblwgeom.h:431
uint32_t npoints
Definition liblwgeom.h:427
uint8_t variant
Definition lwout_twkb.h:78
float factor[4]
Definition lwout_twkb.h:82
int64_t bbox_min[MAX_N_DIMS]
Definition lwout_twkb.h:93
bytebuffer_t * geom_buf
Definition lwout_twkb.h:89
int64_t accum_rels[MAX_N_DIMS]
Definition lwout_twkb.h:95
int64_t bbox_max[MAX_N_DIMS]
Definition lwout_twkb.h:94
uint8_t * writecursor
Definition bytebuffer.h:44
uint8_t * buf_start
Definition bytebuffer.h:43
size_t varint_u64_encode_buf(uint64_t val, uint8_t *buf)
Definition varint.c:76

References TWKB_STATE::accum_rels, TWKB_STATE::bbox_max, TWKB_STATE::bbox_min, bytebuffer_t::buf_start, bytebuffer_append_byte(), bytebuffer_append_bytebuffer(), bytebuffer_append_uvarint(), bytebuffer_append_varint(), bytebuffer_destroy_buffer(), bytebuffer_init_with_size(), TWKB_GLOBALS::factor, POINTARRAY::flags, FLAGS_NDIMS, TWKB_STATE::geom_buf, getPoint_internal(), LWDEBUGF, MAX_N_DIMS, POINTARRAY::npoints, TWKB_BBOX, TWKB_GLOBALS::variant, varint_u64_encode_buf(), and bytebuffer_t::writecursor.

Referenced by lwline_to_twkb_buf(), lwpoint_to_twkb_buf(), lwpoly_to_twkb_buf(), and lwtriangle_to_twkb_buf().

Here is the call graph for this function:
Here is the caller graph for this function: