Beispiel #1
0
/**
* COLLECTION, MULTIPOINTTYPE, MULTILINETYPE, MULTIPOLYGONTYPE, COMPOUNDTYPE,
* MULTICURVETYPE, MULTISURFACETYPE,
* TINTYPE
*/
static LWCOLLECTION* lwcollection_from_wkb_state(wkb_parse_state *s)
{
	uint32_t ngeoms = integer_from_wkb_state(s);
	LWCOLLECTION *col = lwcollection_construct_empty(s->lwtype, s->srid, s->has_z, s->has_m);
	LWGEOM *geom = NULL;
	int i;

	LWDEBUGF(4,"Collection has %d components", ngeoms);

	/* Empty collection? */
	if ( ngeoms == 0 )
		return col;

	/* Be strict in polyhedral surface closures */
	if ( s->lwtype == POLYHEDRALSURFACETYPE )
		s->check |= LW_PARSER_CHECK_ZCLOSURE;

	for ( i = 0; i < ngeoms; i++ )
	{
		geom = lwgeom_from_wkb_state(s);
		if ( lwcollection_add_lwgeom(col, geom) == NULL )
		{
			lwerror("Unable to add geometry (%p) to collection (%p)", geom, col);
			return NULL;
		}
	}

	return col;
}
Beispiel #2
0
/**
* POINTARRAY
* Read a dynamically sized point array and advance the parse state forward.
* First read the number of points, then read the points.
*/
static POINTARRAY* ptarray_from_wkb_state(wkb_parse_state *s)
{
	POINTARRAY *pa = NULL;
	size_t pa_size;
	uint32_t ndims = 2;
	uint32_t npoints = 0;
	static uint32_t maxpoints = 4294967295 / WKB_DOUBLE_SIZE / 4;

	/* Calculate the size of this point array. */
	npoints = integer_from_wkb_state(s);
	if (npoints > maxpoints)
	{
		lwerror("point array length (%d) is too large");
	}

	LWDEBUGF(4,"Pointarray has %d points", npoints);

	if( s->has_z ) ndims++;
	if( s->has_m ) ndims++;
	pa_size = npoints * ndims * WKB_DOUBLE_SIZE;

	/* Empty! */
	if( npoints == 0 )
		return ptarray_construct(s->has_z, s->has_m, npoints);

	/* Does the data we want to read exist? */
	wkb_parse_state_check(s, pa_size);

	/* If we're in a native endianness, we can just copy the data directly! */
	if( ! s->swap_bytes )
	{
		pa = ptarray_construct_copy_data(s->has_z, s->has_m, npoints, (uint8_t*)s->pos);
		s->pos += pa_size;
	}
	/* Otherwise we have to read each double, separately. */
	else
	{
		int i = 0;
		double *dlist;
		pa = ptarray_construct(s->has_z, s->has_m, npoints);
		dlist = (double*)(pa->serialized_pointlist);
		for( i = 0; i < npoints * ndims; i++ )
		{
			dlist[i] = double_from_wkb_state(s);
		}
	}

	return pa;
}
Beispiel #3
0
/**
* TRIANGLE
* Read a WKB triangle, starting just after the endian byte, 
* type number and optional srid number. Advance the parse state 
* forward appropriately. 
* Triangles are encoded like polygons in WKB, but more like linestrings
* as lwgeometries.
*/
static LWTRIANGLE* lwtriangle_from_wkb_state(wkb_parse_state *s)
{
	uint32_t nrings = integer_from_wkb_state(s);
	LWTRIANGLE *tri = lwtriangle_construct_empty(s->srid, s->has_z, s->has_m);
	POINTARRAY *pa = NULL;

	/* Empty triangle? */
	if( nrings == 0 )
		return tri;

	/* Should be only one ring. */
	if ( nrings != 1 )
		lwerror("Triangle has wrong number of rings: %d", nrings);

	/* There's only one ring, we hope? */	
	pa = ptarray_from_wkb_state(s);

	/* If there's no points, return an empty triangle. */
	if( pa == NULL )
		return tri;

	/* Check for at least four points. */
	if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
	{
		LWDEBUGF(2, "%s must have at least four points", lwtype_name(s->lwtype));
		lwerror("%s must have at least four points", lwtype_name(s->lwtype));
		return NULL;
	}

	if( s->check & LW_PARSER_CHECK_CLOSURE && ! ptarray_is_closed(pa) )
	{
		lwerror("%s must have closed rings", lwtype_name(s->lwtype));
		return NULL;
	}

	if( s->check & LW_PARSER_CHECK_ZCLOSURE && ! ptarray_is_closed_z(pa) )
	{
		lwerror("%s must have closed rings", lwtype_name(s->lwtype));
		return NULL;
	}

	/* Empty TRIANGLE starts w/ empty POINTARRAY, free it first */
	if (tri->points)
		ptarray_free(tri->points);
	
	tri->points = pa;	
	return tri;
}
Beispiel #4
0
/**
* POLYGON
* Read a WKB polygon, starting just after the endian byte,
* type number and optional srid number. Advance the parse state
* forward appropriately.
* First read the number of rings, then read each ring
* (which are structured as point arrays)
*/
static LWPOLY* lwpoly_from_wkb_state(wkb_parse_state *s)
{
	uint32_t nrings = integer_from_wkb_state(s);
	int i = 0;
	LWPOLY *poly = lwpoly_construct_empty(s->srid, s->has_z, s->has_m);

	LWDEBUGF(4,"Polygon has %d rings", nrings);

	/* Empty polygon? */
	if( nrings == 0 )
		return poly;

	for( i = 0; i < nrings; i++ )
	{
		POINTARRAY *pa = ptarray_from_wkb_state(s);
		if( pa == NULL )
			continue;

		/* Check for at least four points. */
		if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
		{
			LWDEBUGF(2, "%s must have at least four points in each ring", lwtype_name(s->lwtype));
			lwerror("%s must have at least four points in each ring", lwtype_name(s->lwtype));
			return NULL;
		}

		/* Check that first and last points are the same. */
		if( s->check & LW_PARSER_CHECK_CLOSURE && ! ptarray_is_closed_2d(pa) )
		{
			LWDEBUGF(2, "%s must have closed rings", lwtype_name(s->lwtype));
			lwerror("%s must have closed rings", lwtype_name(s->lwtype));
			return NULL;
		}

		/* Add ring to polygon */
		if ( lwpoly_add_ring(poly, pa) == LW_FAILURE )
		{
			LWDEBUG(2, "Unable to add ring to polygon");
			lwerror("Unable to add ring to polygon");
		}

	}
	return poly;
}
Beispiel #5
0
/**
* CURVEPOLYTYPE
*/
static LWCURVEPOLY* lwcurvepoly_from_wkb_state(wkb_parse_state *s)
{
	uint32_t ngeoms = integer_from_wkb_state(s);
	LWCURVEPOLY *cp = lwcurvepoly_construct_empty(s->srid, s->has_z, s->has_m);
	LWGEOM *geom = NULL;
	int i;

	/* Empty collection? */
	if ( ngeoms == 0 )
		return cp;

	for ( i = 0; i < ngeoms; i++ )
	{
		geom = lwgeom_from_wkb_state(s);
		if ( lwcurvepoly_add_ring(cp, geom) == LW_FAILURE )
			lwerror("Unable to add geometry (%p) to curvepoly (%p)", geom, cp);
	}

	return cp;
}
Beispiel #6
0
/**
* GEOMETRY
* Generic handling for WKB geometries. The front of every WKB geometry
* (including those embedded in collections) is an endian byte, a type
* number and an optional srid number. We handle all those here, then pass
* to the appropriate handler for the specific type.
*/
LWGEOM* lwgeom_from_wkb_state(wkb_parse_state *s)
{
	char wkb_little_endian;
	uint32_t wkb_type;

	LWDEBUG(4,"Entered function");

	/* Fail when handed incorrect starting byte */
	wkb_little_endian = byte_from_wkb_state(s);
	if( wkb_little_endian != 1 && wkb_little_endian != 0 )
	{
		LWDEBUG(4,"Leaving due to bad first byte!");
		lwerror("Invalid endian flag value encountered.");
		return NULL;
	}

	/* Check the endianness of our input  */
	s->swap_bytes = LW_FALSE;
	if( getMachineEndian() == NDR ) /* Machine arch is little */
	{
		if ( ! wkb_little_endian )    /* Data is big! */
			s->swap_bytes = LW_TRUE;
	}
	else                              /* Machine arch is big */
	{
		if ( wkb_little_endian )      /* Data is little! */
			s->swap_bytes = LW_TRUE;
	}

	/* Read the type number */
	wkb_type = integer_from_wkb_state(s);
	LWDEBUGF(4,"Got WKB type number: 0x%X", wkb_type);
	lwtype_from_wkb_state(s, wkb_type);

	/* Read the SRID, if necessary */
	if( s->has_srid )
	{
		s->srid = clamp_srid(integer_from_wkb_state(s));
		/* TODO: warn on explicit UNKNOWN srid ? */
		LWDEBUGF(4,"Got SRID: %u", s->srid);
	}

	/* Do the right thing */
	switch( s->lwtype )
	{
		case POINTTYPE:
			return (LWGEOM*)lwpoint_from_wkb_state(s);
			break;
		case LINETYPE:
			return (LWGEOM*)lwline_from_wkb_state(s);
			break;
		case CIRCSTRINGTYPE:
			return (LWGEOM*)lwcircstring_from_wkb_state(s);
			break;
		case POLYGONTYPE:
			return (LWGEOM*)lwpoly_from_wkb_state(s);
			break;
		case TRIANGLETYPE:
			return (LWGEOM*)lwtriangle_from_wkb_state(s);
			break;
		case CURVEPOLYTYPE:
			return (LWGEOM*)lwcurvepoly_from_wkb_state(s);
			break;
		case MULTIPOINTTYPE:
		case MULTILINETYPE:
		case MULTIPOLYGONTYPE:
		case COMPOUNDTYPE:
		case MULTICURVETYPE:
		case MULTISURFACETYPE:
		case POLYHEDRALSURFACETYPE:
		case TINTYPE:
		case COLLECTIONTYPE:
			return (LWGEOM*)lwcollection_from_wkb_state(s);
			break;

		/* Unknown type! */
		default:
			lwerror("Unsupported geometry type: %s [%d]", lwtype_name(s->lwtype), s->lwtype);
	}

	/* Return value to keep compiler happy. */
	return NULL;

}