PostGIS  3.0.6dev-r@@SVN_REVISION@@

◆ 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, 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 */
154  bytebuffer_append_byte(b_p, 0);
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: %d, ", 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 )
214  bytebuffer_append_uvarint(ts->geom_buf, 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:141
void bytebuffer_append_byte(bytebuffer_t *s, const uint8_t val)
Writes a uint8_t value to the buffer.
Definition: bytebuffer.c:128
void bytebuffer_append_uvarint(bytebuffer_t *b, const uint64_t val)
Writes a unsigned varInt to the buffer.
Definition: bytebuffer.c:166
void bytebuffer_append_varint(bytebuffer_t *b, const int64_t val)
Writes a signed varInt to the buffer.
Definition: bytebuffer.c:155
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:193
#define TWKB_BBOX
Definition: liblwgeom.h:2138
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
static uint8_t * getPoint_internal(const POINTARRAY *pa, uint32_t n)
Definition: lwinline.h:67
#define MAX_N_DIMS
Definition: lwout_twkb.h:43
lwflags_t flags
Definition: liblwgeom.h:417
uint32_t npoints
Definition: liblwgeom.h:413
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:42
uint8_t * buf_start
Definition: bytebuffer.h:41
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: