Beispiel #1
0
/**
* Writes a unsigned varInt to the buffer
*/
void 
bytebuffer_append_uvarint(bytebuffer_t *b, const uint64_t val)
{	
	size_t size;
	bytebuffer_makeroom(b, 8);
	size = varint_u64_encode_buf(val, b->writecursor);
	b->writecursor += size;
	return;
}
Beispiel #2
0
/**
* 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)
*/
static int ptarray_to_twkb_buf(const POINTARRAY *pa, TWKB_GLOBALS *globals, TWKB_STATE *ts, int register_npoints, int minpoints)
{
	int ndims = FLAGS_NDIMS(pa->flags);
	int i, j;
	bytebuffer_t b;
	bytebuffer_t *b_p;
	int64_t nextdelta[MAX_N_DIMS];
	int npoints = 0;
	size_t npoints_offset = 0;

	LWDEBUGF(2, "Entered %s", __func__);

	/* Dispense with the empty case right away */
	if ( pa->npoints == 0 && register_npoints )	
	{		
		LWDEBUGF(4, "Register npoints:%d", pa->npoints);
		bytebuffer_append_uvarint(ts->geom_buf, pa->npoints);
		return 0;
	}

	/* If npoints is more than 127 it is unpredictable how many bytes npoints will need */
	/* Then we have to store the deltas in a temp buffer to later add them after npoints */
	/* If noints is below 128 we know 1 byte will be needed */
	/* Then we can make room for that 1 byte at once and write to */
	/* ordinary buffer */
	if( pa->npoints > 127 )
	{
		/* Independent buffer to hold the coordinates, so we can put the npoints */
		/* into the stream once we know how many points we actually have */
		bytebuffer_init_with_size(&b, 3 * ndims * pa->npoints);
		b_p = &b;
	}
	else
	{
		/* We give an alias to our ordinary buffer */
		b_p = ts->geom_buf;
		if ( register_npoints )		
		{		
			/* We do not store a pointer to the place where we want the npoints value */
			/* Instead we store how far from the beginning of the buffer we want the value */
			/* That is because we otherwise will get in trouble if the buffer is reallocated */			
			npoints_offset = b_p->writecursor - b_p->buf_start;
			
			/* We just move the cursor 1 step to make room for npoints byte */
			/* We use the function append_byte even if we have no value yet, */
			/* since that gives us the check for big enough buffer and moves the cursor */
			bytebuffer_append_byte(b_p, 0);
		}
	}
	
	for ( i = 0; i < pa->npoints; i++ )
	{
		double *dbl_ptr = (double*)getPoint_internal(pa, i);
		int diff = 0;

		/* Write this coordinate to the buffer as a varint */
		for ( j = 0; j < ndims; j++ )
		{
			/* To get the relative coordinate we don't get the distance */
			/* from the last point but instead the distance from our */
			/* last accumulated point. This is important to not build up an */
			/* accumulated error when rounding the coordinates */
			nextdelta[j] = (int64_t) llround(globals->factor[j] * dbl_ptr[j]) - ts->accum_rels[j];
			LWDEBUGF(4, "deltavalue: %d, ", nextdelta[j]);
			diff += llabs(nextdelta[j]);
		}
		
		/* Skipping the first point is not allowed */
		/* If the sum(abs()) of all the deltas was zero, */
		/* then this was a duplicate point, so we can ignore it */
		if ( i > minpoints && diff == 0 )
			continue;
		
		/* We really added a point, so... */
		npoints++;
		
		/* Write this vertex to the temporary buffer as varints */
		for ( j = 0; j < ndims; j++ )
		{
			ts->accum_rels[j] += nextdelta[j];
			bytebuffer_append_varint(b_p, nextdelta[j]);
		}

		/* See if this coordinate expands the bounding box */
		if( globals->variant & TWKB_BBOX )
		{
			for ( j = 0; j < ndims; j++ )
			{
				if( ts->accum_rels[j] > ts->bbox_max[j] )
					ts->bbox_max[j] = ts->accum_rels[j];

				if( ts->accum_rels[j] < ts->bbox_min[j] )
					ts->bbox_min[j] = ts->accum_rels[j];
			}
		}

	}	

	if ( pa->npoints > 127 )
	{		
		/* Now write the temporary results into the main buffer */
		/* First the npoints */
		if ( register_npoints )	
			bytebuffer_append_uvarint(ts->geom_buf, npoints);
		/* Now the coordinates */
		bytebuffer_append_bytebuffer(ts->geom_buf, b_p);
		
		/* Clear our temporary buffer */
		lwfree(b.buf_start);
	}
	else
	{
		/* If we didn't use a temp buffer, we just write that npoints value */
		/* to where it belongs*/
		if ( register_npoints )	
			varint_u64_encode_buf(npoints, b_p->buf_start + npoints_offset);
	}
	
	return 0;
}