PostGIS  2.2.7dev-r@@SVN_REVISION@@
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 92 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_init_with_size(), TWKB_GLOBALS::factor, POINTARRAY::flags, FLAGS_NDIMS, TWKB_STATE::geom_buf, getPoint_internal(), LWDEBUGF, lwfree(), 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().

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

Here is the call graph for this function:

Here is the caller graph for this function: