Example #1
0
int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox)
{
	if ( ! lwgeom ) return G_FAILURE;

	switch (TYPE_GETTYPE(lwgeom->type))
	{
	case POINTTYPE:
		return lwpoint_calculate_gbox((LWPOINT *)lwgeom, gbox);
	case LINETYPE:
		return lwline_calculate_gbox((LWLINE *)lwgeom, gbox);
	case CIRCSTRINGTYPE:
		return lwcircstring_calculate_gbox((LWCIRCSTRING *)lwgeom, gbox);
	case POLYGONTYPE:
		return lwpoly_calculate_gbox((LWPOLY *)lwgeom, gbox);
	case COMPOUNDTYPE:
	case CURVEPOLYTYPE:
	case MULTIPOINTTYPE:
	case MULTILINETYPE:
	case MULTICURVETYPE:
	case MULTIPOLYGONTYPE:
	case MULTISURFACETYPE:
	case COLLECTIONTYPE:
		return lwcollection_calculate_gbox((LWCOLLECTION *)lwgeom, gbox);
	}
	/* Never get here, please. */
	lwerror("unsupported type (%d)", TYPE_GETTYPE(lwgeom->type));
	return G_FAILURE;
}
Datum BOX2DFLOAT4_construct(PG_FUNCTION_ARGS)
{
	PG_LWGEOM *min = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
	PG_LWGEOM *max = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
	BOX2DFLOAT4 *result = palloc(sizeof(BOX2DFLOAT4));
	LWGEOM *minpoint, *maxpoint;
	POINT2D minp, maxp;

	minpoint = lwgeom_deserialize(SERIALIZED_FORM(min));
	maxpoint = lwgeom_deserialize(SERIALIZED_FORM(max));

	if ( TYPE_GETTYPE(minpoint->type) != POINTTYPE ||
	        TYPE_GETTYPE(maxpoint->type) != POINTTYPE )
	{
		elog(ERROR, "BOX2DFLOAT4_construct: args must be points");
		PG_RETURN_NULL();
	}

	errorIfSRIDMismatch(minpoint->SRID, maxpoint->SRID);

	getPoint2d_p(((LWPOINT *)minpoint)->point, 0, &minp);
	getPoint2d_p(((LWPOINT *)maxpoint)->point, 0, &maxp);

	result->xmax = maxp.x;
	result->ymax = maxp.y;

	result->xmin = minp.x;
	result->ymin = minp.y;

	PG_RETURN_POINTER(result);
}
Example #3
0
Datum LWGEOM_exteriorring_polygon(PG_FUNCTION_ARGS)
{
	PG_LWGEOM *geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
	LWPOLY *poly = NULL;
	LWCURVEPOLY *curvepoly = NULL;
	POINTARRAY *extring;
	LWGEOM *ring;
	LWLINE *line;
	PG_LWGEOM *result;
	BOX2DFLOAT4 *bbox=NULL;

	POSTGIS_DEBUG(2, "LWGEOM_exteriorring_polygon called.");

	if ( TYPE_GETTYPE(geom->type) != POLYGONTYPE &&
	        TYPE_GETTYPE(geom->type) != CURVEPOLYTYPE)
	{
		elog(ERROR, "ExteriorRing: geom is not a polygon");
		PG_RETURN_NULL();
	}
	if (lwgeom_getType((uchar)SERIALIZED_FORM(geom)[0]) == POLYGONTYPE)
	{
		poly = lwpoly_deserialize(SERIALIZED_FORM(geom));

		/* Ok, now we have a polygon. Here is its exterior ring. */
		extring = poly->rings[0];

		/*
		* This is a LWLINE constructed by exterior ring POINTARRAY
		* If the input geom has a bbox, use it for
		* the output geom, as exterior ring makes it up !
		*/
		if ( poly->bbox ) bbox=box2d_clone(poly->bbox);
		line = lwline_construct(poly->SRID, bbox, extring);

		result = pglwgeom_serialize((LWGEOM *)line);

		lwgeom_release((LWGEOM *)line);
		lwgeom_release((LWGEOM *)poly);
	}
	else
	{
		curvepoly = lwcurvepoly_deserialize(SERIALIZED_FORM(geom));
		ring = curvepoly->rings[0];
		result = pglwgeom_serialize(ring);
		lwgeom_release(ring);
	}

	PG_FREE_IF_COPY(geom, 0);


	PG_RETURN_POINTER(result);
}
Example #4
0
/*
 * Construct a LWLINE from an array of LWPOINTs
 * LWLINE dimensions are large enough to host all input dimensions.
 */
LWLINE *
lwline_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points)
{
	int zmflag=0;
	unsigned int i;
	POINTARRAY *pa;
	uchar *newpoints, *ptr;
	size_t ptsize, size;

	/*
	 * Find output dimensions, check integrity
	 */
	for (i=0; i<npoints; i++)
	{
		if ( TYPE_GETTYPE(points[i]->type) != POINTTYPE )
		{
			lwerror("lwline_from_lwpointarray: invalid input type: %s",
			        lwgeom_typename(TYPE_GETTYPE(points[i]->type)));
			return NULL;
		}
		if ( TYPE_HASZ(points[i]->type) ) zmflag |= 2;
		if ( TYPE_HASM(points[i]->type) ) zmflag |= 1;
		if ( zmflag == 3 ) break;
	}

	if ( zmflag == 0 ) ptsize=2*sizeof(double);
	else if ( zmflag == 3 ) ptsize=4*sizeof(double);
	else ptsize=3*sizeof(double);

	/*
	 * Allocate output points array
	 */
	size = ptsize*npoints;
	newpoints = lwalloc(size);
	memset(newpoints, 0, size);

	ptr=newpoints;
	for (i=0; i<npoints; i++)
	{
		size=pointArray_ptsize(points[i]->point);
		memcpy(ptr, getPoint_internal(points[i]->point, 0), size);
		ptr+=ptsize;
	}

	pa = pointArray_construct(newpoints, zmflag&2, zmflag&1, npoints);

	return lwline_construct(SRID, NULL, pa);
}
Example #5
0
char *
lwgeom_summary(LWGEOM *lwgeom, int offset)
{
	char *result;

	switch (TYPE_GETTYPE(lwgeom->type))
	{
	case POINTTYPE:
		return lwpoint_summary((LWPOINT *)lwgeom, offset);

	case LINETYPE:
		return lwline_summary((LWLINE *)lwgeom, offset);

	case POLYGONTYPE:
		return lwpoly_summary((LWPOLY *)lwgeom, offset);

	case MULTIPOINTTYPE:
	case MULTILINETYPE:
	case MULTIPOLYGONTYPE:
	case COLLECTIONTYPE:
		return lwcollection_summary((LWCOLLECTION *)lwgeom, offset);
	default:
		result = palloc(256);
		sprintf(result, "Object is of unknown type: %d",
		        lwgeom->type);
		return result;
	}

	return NULL;
}
Example #6
0
char *
lwpoly_summary(LWPOLY *poly, int offset)
{
	char tmp[256];
	size_t size = 64*(poly->nrings+1)+128;
	char *result;
	int i;
	char *pad="";

	LWDEBUG(2, "lwpoly_summary called");

	result = lwalloc(size);

	sprintf(result, "%*.s%s[%s] with %i rings\n",
	        offset, pad, lwgeom_typename(TYPE_GETTYPE(poly->type)),
	        lwgeom_typeflags(poly->type),
	        poly->nrings);

	for (i=0; i<poly->nrings; i++)
	{
		sprintf(tmp,"%s   ring %i has %i points\n",
		        pad, i, poly->rings[i]->npoints);
		strcat(result,tmp);
	}

	LWDEBUG(3, "lwpoly_summary returning");

	return result;
}
Example #7
0
char *
lwcollection_summary(LWCOLLECTION *col, int offset)
{
	size_t size = 128;
	char *result;
	char *tmp;
	int i;
	char *pad="";

	LWDEBUG(2, "lwcollection_summary called");

	result = (char *)lwalloc(size);

	sprintf(result, "%*.s%s[%s] with %d elements\n",
	        offset, pad, lwgeom_typename(TYPE_GETTYPE(col->type)),
	        lwgeom_typeflags(col->type),
	        col->ngeoms);

	for (i=0; i<col->ngeoms; i++)
	{
		tmp = lwgeom_summary(col->geoms[i], offset+2);
		size += strlen(tmp)+1;
		result = lwrealloc(result, size);

		LWDEBUGF(4, "Reallocated %d bytes for result", size);

		strcat(result, tmp);
		lwfree(tmp);
	}

	LWDEBUG(3, "lwcollection_summary returning");

	return result;
}
Example #8
0
/*
 * Add 'what' to this string at position 'where'
 * where=0 == prepend
 * where=-1 == append
 * Returns a COMPOUND or a GEOMETRYCOLLECTION
 */
LWGEOM *
lwcompound_add(const LWCOMPOUND *to, uint32 where, const LWGEOM *what)
{
        LWCOLLECTION *col;
        LWGEOM **geoms;
        int newtype;

        LWDEBUG(2, "lwcompound_add called.");

        if(where != -1 && where != 0)
        {
                lwerror("lwcompound_add only supports 0 or -1 as a second argument, not %d", where);
                return NULL;
        }

        /* dimensions compatibility are checked by caller */

        /* Construct geoms array */
        geoms = lwalloc(sizeof(LWGEOM *)*2);
        if(where == -1) /* append */
        {
                geoms[0] = lwgeom_clone((LWGEOM *)to);
                geoms[1] = lwgeom_clone(what);
        }
        else /* prepend */
        {
                geoms[0] = lwgeom_clone(what);
                geoms[1] = lwgeom_clone((LWGEOM *)to);
        }

        /* reset SRID and wantbbox flag from component types */
        geoms[0]->SRID = geoms[1]->SRID = -1;
        TYPE_SETHASSRID(geoms[0]->type, 0);
        TYPE_SETHASSRID(geoms[1]->type, 0);
        TYPE_SETHASBBOX(geoms[0]->type, 0);
        TYPE_SETHASBBOX(geoms[1]->type, 0);

        /* Find appropriate geom type */
        if(TYPE_GETTYPE(what->type) == LINETYPE || TYPE_GETTYPE(what->type) == CIRCSTRINGTYPE) newtype = COMPOUNDTYPE;
        else newtype = COLLECTIONTYPE;

        col = lwcollection_construct(newtype,
                to->SRID, NULL, 2, geoms);

        return (LWGEOM *)col;
}
Example #9
0
/**
* Re-write the measure ordinate (or add one, if it isn't already there) interpolating
* the measure between the supplied start and end values.
*/
LWLINE*
lwline_measured_from_lwline(const LWLINE *lwline, double m_start, double m_end)
{
	int i = 0;
	int hasm = 0, hasz = 0;
	int npoints = 0;
	double length = 0.0;
	double length_so_far = 0.0;
	double m_range = m_end - m_start;
	double m;
	POINTARRAY *pa = NULL;
	POINT3DZ p1, p2;

	if ( TYPE_GETTYPE(lwline->type) != LINETYPE )
	{
		lwerror("lwline_construct_from_lwline: only line types supported");
		return NULL;
	}

	hasz = TYPE_HASZ(lwline->type);
	hasm = 1;

	/* Null points or npoints == 0 will result in empty return geometry */
	if ( lwline->points )
	{
		npoints = lwline->points->npoints;
		length = lwgeom_pointarray_length2d(lwline->points);
		getPoint3dz_p(lwline->points, 0, &p1);
	}

	pa = ptarray_construct(hasz, hasm, npoints);

	for ( i = 0; i < npoints; i++ )
	{
		POINT4D q;
		POINT2D a, b;
		getPoint3dz_p(lwline->points, i, &p2);
		a.x = p1.x;
		a.y = p1.y;
		b.x = p2.x;
		b.y = p2.y;
		length_so_far += distance2d_pt_pt(&a, &b);
		if ( length > 0.0 )
			m = m_start + m_range * length_so_far / length;
		else
			m = 0.0;
		q.x = p2.x;
		q.y = p2.y;
		q.z = p2.z;
		q.m = m;
		setPoint4d(pa, i, &q);
		p1 = p2;
	}

	return lwline_construct(lwline->SRID, NULL, pa);
}
Example #10
0
/**
* Calculate the area of an LWGEOM. Anything except POLYGON, MULTIPOLYGON
* and GEOMETRYCOLLECTION return zero immediately. Multi's recurse, polygons
* calculate external ring area and subtract internal ring area. A GBOX is
* required to check relationship to equator an outside point.
* WARNING: Does NOT WORK for polygons over equator or pole.
*/
double lwgeom_area_spheroid(const LWGEOM *lwgeom, const GBOX *gbox, const SPHEROID *spheroid)
{
	int type;

	assert(lwgeom);

	/* No area in nothing */
	if ( lwgeom_is_empty(lwgeom) )
		return 0.0;

	/* Read the geometry type number */
	type = TYPE_GETTYPE(lwgeom->type);

	/* Anything but polygons and collections returns zero */
	if ( ! ( type == POLYGONTYPE || type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE ) )
		return 0.0;

	/* Actually calculate area */
	if ( type == POLYGONTYPE )
	{
		LWPOLY *poly = (LWPOLY*)lwgeom;
		int i;
		double area = 0.0;

		/* Just in case there's no rings */
		if ( poly->nrings < 1 )
			return 0.0;

		/* First, the area of the outer ring */
		area += ptarray_area_spheroid(poly->rings[0], spheroid);

		/* Subtract areas of inner rings */
		for ( i = 1; i < poly->nrings; i++ )
		{
			area -=  ptarray_area_spheroid(poly->rings[i], spheroid);
		}
		return area;
	}

	/* Recurse into sub-geometries to get area */
	if ( type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE )
	{
		LWCOLLECTION *col = (LWCOLLECTION*)lwgeom;
		int i;
		double area = 0.0;

		for ( i = 0; i < col->ngeoms; i++ )
		{
			area += lwgeom_area_spheroid(col->geoms[i], gbox, spheroid);
		}
		return area;
	}

	/* Shouldn't get here. */
	return 0.0;
}
Example #11
0
/*
 * Add 'what' to this multisurface at position 'where'
 * where=0 == prepend
 * where=-1 == append
 * Returns a MULTISURFACE or a COLLECTION
 */
LWGEOM *
lwmsurface_add(const LWMSURFACE *to, uint32 where, const LWGEOM *what)
{
	LWCOLLECTION *col;
	LWGEOM **geoms;
	int newtype;
	uint32 i;

	if (where == -1) where = to->ngeoms;
	else if (where < -1 || where > to->ngeoms)
	{
		lwerror("lwmsurface_add: add position out of range %d..%d",
		        -1, to->ngeoms);
		return NULL;
	}

	/* dimensions compatibility are checked by caller */

	/* Construct geoms array */
	geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
	for (i = 0; i < where; i++)
	{
		geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]);
	}
	geoms[where] = lwgeom_clone(what);
	for (i = where; i < to->ngeoms; i++)
	{
		geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]);
	}

	if (TYPE_GETTYPE(what->type) == POLYGONTYPE ||
	        TYPE_GETTYPE(what->type) == CURVEPOLYTYPE)
		newtype = MULTISURFACETYPE;
	else newtype = COLLECTIONTYPE;

	col = lwcollection_construct(newtype,
	                             to->SRID, NULL, to->ngeoms + 1, geoms);

	return (LWGEOM *)col;
}
Example #12
0
/*
 * Returns an alloced string containing summary for the LWGEOM object
 */
char *
lwpoint_summary(LWPOINT *point, int offset)
{
	char *result;
	char *pad="";

	result = lwalloc(128+offset);

	sprintf(result, "%*.s%s[%s]\n",
	        offset, pad, lwgeom_typename(TYPE_GETTYPE(point->type)),
	        lwgeom_typeflags(point->type));
	return result;
}
Example #13
0
char *
lwline_summary(LWLINE *line, int offset)
{
	char *result;
	char *pad="";

	result = lwalloc(128+offset);

	sprintf(result, "%*.s%s[%s] with %d points\n",
	        offset, pad, lwgeom_typename(TYPE_GETTYPE(line->type)),
	        lwgeom_typeflags(line->type),
	        line->points->npoints);
	return result;
}
Example #14
0
/*
 * Add 'what' to this point at position 'where'.
 * where=0 == prepend
 * where=-1 == append
 * Returns a MULTIPOINT or a GEOMETRYCOLLECTION
 */
LWGEOM *
lwpoint_add(const LWPOINT *to, uint32 where, const LWGEOM *what)
{
	LWCOLLECTION *col;
	LWGEOM **geoms;
	int newtype;

	if ( where != -1 && where != 0 )
	{
		lwerror("lwpoint_add only supports 0 or -1 as second argument, got %d", where);
		return NULL;
	}

	/* dimensions compatibility are checked by caller */


	/* Construct geoms array */
	geoms = lwalloc(sizeof(LWGEOM *)*2);
	if ( where == -1 ) /* append */
	{
		geoms[0] = lwgeom_clone((LWGEOM *)to);
		geoms[1] = lwgeom_clone(what);
	}
	else /* prepend */
	{
		geoms[0] = lwgeom_clone(what);
		geoms[1] = lwgeom_clone((LWGEOM *)to);
	}
	/* reset SRID and wantbbox flag from component types */
	lwgeom_dropSRID(geoms[0]);
	lwgeom_drop_bbox(geoms[0]);
	lwgeom_dropSRID(geoms[1]);
	lwgeom_drop_bbox(geoms[1]);

	/* Find appropriate geom type */
	if ( TYPE_GETTYPE(what->type) == POINTTYPE ) newtype = MULTIPOINTTYPE;
	else newtype = COLLECTIONTYPE;

	col = lwcollection_construct(newtype,
		to->SRID, NULL,
		2, geoms);
	
	return (LWGEOM *)col;
}
Example #15
0
Datum LWGEOM_y_point(PG_FUNCTION_ARGS)
{
	PG_LWGEOM *geom;
	LWPOINT *point = NULL;
	POINT2D p;

	geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));

	if ( TYPE_GETTYPE(geom->type) != POINTTYPE )
		lwerror("Argument to Y() must be a point");

	point = lwgeom_getpoint(SERIALIZED_FORM(geom), 0);

	getPoint2d_p(point->point, 0, &p);

	PG_FREE_IF_COPY(geom, 0);

	PG_RETURN_FLOAT8(p.y);
}
Example #16
0
Datum LWGEOM_m_point(PG_FUNCTION_ARGS)
{
	PG_LWGEOM *geom;
	LWPOINT *point = NULL;
	POINT3DM p;

	geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));

	if ( TYPE_GETTYPE(geom->type) != POINTTYPE )
		lwerror("Argument to M() must be a point");

	point = lwgeom_getpoint(SERIALIZED_FORM(geom), 0);

	/* no M in input */
	if ( ! TYPE_HASM(point->type) ) PG_RETURN_NULL();

	getPoint3dm_p(point->point, 0, &p);

	PG_FREE_IF_COPY(geom, 0);

	PG_RETURN_FLOAT8(p.m);
}
Example #17
0
Datum LWGEOM_interiorringn_polygon(PG_FUNCTION_ARGS)
{
	PG_LWGEOM *geom;
	int32 wanted_index;
	LWCURVEPOLY *curvepoly = NULL;
	LWPOLY *poly = NULL;
	POINTARRAY *ring;
	LWLINE *line;
	PG_LWGEOM *result;
	BOX2DFLOAT4 *bbox = NULL;

	POSTGIS_DEBUG(2, "LWGEOM_interierringn_polygon called.");

	wanted_index = PG_GETARG_INT32(1);
	if ( wanted_index < 1 )
	{
		/* elog(ERROR, "InteriorRingN: ring number is 1-based"); */
		PG_RETURN_NULL(); /* index out of range */
	}

	geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));

	if ( TYPE_GETTYPE(geom->type) != POLYGONTYPE &&
	        TYPE_GETTYPE(geom->type) != CURVEPOLYTYPE )
	{
		PG_FREE_IF_COPY(geom, 0);
		elog(ERROR, "InteriorRingN: geom is not a polygon");
		PG_RETURN_NULL();
	}
	if ( TYPE_GETTYPE(geom->type) == POLYGONTYPE)
	{
		poly = lwpoly_deserialize(SERIALIZED_FORM(geom));

		/* Ok, now we have a polygon. Let's see if it has enough holes */
		if ( wanted_index >= poly->nrings )
		{
			PG_FREE_IF_COPY(geom, 0);
			lwgeom_release((LWGEOM *)poly);
			PG_RETURN_NULL();
		}

		ring = poly->rings[wanted_index];

		/* COMPUTE_BBOX==TAINTING */
		if ( poly->bbox ) bbox = ptarray_compute_box2d(ring);

		/* This is a LWLINE constructed by interior ring POINTARRAY */
		line = lwline_construct(poly->SRID, bbox, ring);

		/* Copy SRID from polygon */
		line->SRID = poly->SRID;

		result = pglwgeom_serialize((LWGEOM *)line);
		lwgeom_release((LWGEOM *)line);
		lwgeom_release((LWGEOM *)poly);
	}
	else
	{
		curvepoly = lwcurvepoly_deserialize(SERIALIZED_FORM(geom));

		if (wanted_index >= curvepoly->nrings)
		{
			PG_FREE_IF_COPY(geom, 0);
			lwgeom_release((LWGEOM *)curvepoly);
			PG_RETURN_NULL();
		}

		result = pglwgeom_serialize(curvepoly->rings[wanted_index]);
		lwgeom_release((LWGEOM *)curvepoly);
	}


	PG_FREE_IF_COPY(geom, 0);

	PG_RETURN_POINTER(result);
}