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