PostGIS  2.5.0dev-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 , controls whether an npoints entry is added to the buffer (used to skip npoints for point types) , states the dimensionality of object this array is part of (0 = point, 1 = linear, 2 = areal)

Definition at line 106 of file lwout_twkb.c.

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(), and lwpoly_to_twkb_buf().

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