*
* This is free software; you can redistribute and/or modify it under
* the terms of the GNU General Public Licence. See the COPYING file.
- *
+ *
**********************************************************************/
#include "lwgeom_geos.h"
#include "lwgeom_geos_prepared.h"
-/*
+/**
** NOTE: Buffer-based GeomUnion has been disabled due to
** limitations in the GEOS code (it would only work against polygons)
-** TODO: Implement cascaded GeomUnion and remove old buffer-based code.
+** DONE: Implement cascaded GeomUnion and remove old buffer-based code.
*/
-/*
+/*
** Prototypes for SQL-bound functions
*/
Datum relate_full(PG_FUNCTION_ARGS);
Datum postgis_geos_version(PG_FUNCTION_ARGS);
Datum centroid(PG_FUNCTION_ARGS);
Datum polygonize_garray(PG_FUNCTION_ARGS);
-Datum LWGEOM_buildarea(PG_FUNCTION_ARGS); /* TODO: rename to match others */
+Datum LWGEOM_buildarea(PG_FUNCTION_ARGS); /* TODO: rename to match others
+*/
Datum linemerge(PG_FUNCTION_ARGS);
Datum coveredby(PG_FUNCTION_ARGS);
Datum pgis_union_geometry_array(PG_FUNCTION_ARGS);
-/* TODO: move these to a lwgeom_functions_analytic.h */
+/** @todo TODO: move these to a lwgeom_functions_analytic.h
+ */
int point_in_polygon_rtree(RTREE_NODE **root, int ringCount, LWPOINT *point);
int point_in_multipolygon_rtree(RTREE_NODE **root, int polyCount, int ringCount, LWPOINT *point);
int point_in_polygon(LWPOLY *polygon, LWPOINT *point);
int point_in_multipolygon(LWMPOLY *mpolygon, LWPOINT *pont);
-/*
-** Prototypes end
+/*
+** Prototypes end
*/
PG_RETURN_POINTER(result);
}
-/*
- * This is the final function for GeomUnion
- * aggregate. Will have as input an array of Geometries.
- * Will iteratively call GEOSUnion on the GEOS-converted
- * versions of them and return PGIS-converted version back.
- * Changing combination order *might* speed up performance.
+/**
+ * @brief This is the final function for GeomUnion
+ * aggregate. Will have as input an array of Geometries.
+ * Will iteratively call GEOSUnion on the GEOS-converted
+ * versions of them and return PGIS-converted version back.
+ * Changing combination order *might* speed up performance.
*/
PG_FUNCTION_INFO_V1(pgis_union_geometry_array);
Datum pgis_union_geometry_array(PG_FUNCTION_ARGS)
#if POSTGIS_GEOS_VERSION >= 31
/*
- ** First, see if all our elements are POLYGON/MULTIPOLYGON
+ ** First, see if all our elements are POLYGON/MULTIPOLYGON
** If they are, we can use UnionCascaded for faster results.
*/
offset = 0;
- for ( i = 0; i < nelems; i++ )
+ for ( i = 0; i < nelems; i++ )
{
PG_LWGEOM *pggeom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
int pgtype = TYPE_GETTYPE(pggeom->type);
}
}
- if ( allpolys )
+ if ( allpolys )
{
/*
** Everything is polygonal, so let's run the cascaded polygon union!
** First make an array of GEOS Polygons.
*/
offset = 0;
- for( i = 0; i < nelems; i++ )
+ for( i = 0; i < nelems; i++ )
{
PG_LWGEOM *pggeom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
int pgtype = TYPE_GETTYPE(pggeom->type);
offset += INTALIGN(VARSIZE(pggeom));
- if( pgtype == POLYGONTYPE )
+ if( pgtype == POLYGONTYPE )
{
if( curgeom == geoms_size )
{
LWPOLY *lwpoly = NULL;
int k = 0;
if( curgeom == geoms_size )
- {
+ {
geoms_size *= 2;
geoms = repalloc( geoms, sizeof(GEOSGeom) * geoms_size );
}
/* This builds a LWPOLY on top of the serialized form */
- lwpoly = lwgeom_getpoly_inspected(lwgeom, j);
+ lwpoly = lwgeom_getpoly_inspected(lwgeom, j);
geoms[curgeom] = LWGEOM2GEOS(lwpoly_as_lwgeom(lwpoly));
/* We delicately free the LWPOLY and POINTARRAY structs, leaving the serialized form below untouched. */
- for( k = 0; k < lwpoly->nrings; k++ )
+ for( k = 0; k < lwpoly->nrings; k++ )
{
lwfree(lwpoly->rings[k]);
}
if ( g1 ) GEOSGeom_destroy((GEOSGeometry *)g1);
if ( g2 ) GEOSGeom_destroy(g2);
}
- else
+ else
{
#endif /* POSTGIS_GEOS_VERSION >= 31 */
/*
g1 = POSTGIS2GEOS(pgis_geom);
POSTGIS_DEBUGF(3, "unite_garray(%d): adding geom %d to union (%s)",
- call, i, lwgeom_typename(TYPE_GETTYPE(geom->type)));
+ call, i, lwgeom_typename(TYPE_GETTYPE(geom->type)));
g2 = GEOSUnion(g1, geos_result);
if ( g2 == NULL )
#if POSTGIS_GEOS_VERSION >= 31
}
#endif
-
+
if ( result == NULL )
{
elog(ERROR, "Union returned a NULL geometry.");
}
-/*
- * select geomunion(
+/**
+ * @example geomunion {@link #geomunion} SELECT geomunion(
* 'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
* 'POLYGON((5 5, 15 5, 15 7, 5 7, 5 5))'
* );
geom2 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
is3d = ( TYPE_HASZ(geom1->type) ) ||
- ( TYPE_HASZ(geom2->type) );
+ ( TYPE_HASZ(geom2->type) );
SRID = pglwgeom_getSRID(geom1);
errorIfSRIDMismatch(SRID, pglwgeom_getSRID(geom2));
}
-/*
- * select symdifference(
+/**
+ * @example symdifference {@link #symdifference} - SELECT symdifference(
* 'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
* 'POLYGON((5 5, 15 5, 15 7, 5 7, 5 5))');
*/
geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
is3d = ( TYPE_HASZ(geom1->type) ) ||
- ( TYPE_HASZ(geom2->type) );
+ ( TYPE_HASZ(geom2->type) );
SRID = pglwgeom_getSRID(geom1);
errorIfSRIDMismatch(SRID, pglwgeom_getSRID(geom2));
geom2 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
is3d = ( TYPE_HASZ(geom1->type) ) ||
- ( TYPE_HASZ(geom2->type) );
+ ( TYPE_HASZ(geom2->type) );
SRID = pglwgeom_getSRID(geom1);
errorIfSRIDMismatch(SRID, pglwgeom_getSRID(geom2));
PG_RETURN_POINTER(result);
}
-/*
- * select difference(
+/**
+ * @example difference {@link #difference} - SELECT difference(
* 'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
* 'POLYGON((5 5, 15 5, 15 7, 5 7, 5 5))');
*/
geom2 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
is3d = ( TYPE_HASZ(geom1->type) ) ||
- ( TYPE_HASZ(geom2->type) );
+ ( TYPE_HASZ(geom2->type) );
SRID = pglwgeom_getSRID(geom1);
errorIfSRIDMismatch(SRID, pglwgeom_getSRID(geom2));
}
-/* select pointonsurface('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))'); */
+/**
+ @example pointonsurface - {@link #pointonsurface} SELECT pointonsurface('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))');
+*/
PG_FUNCTION_INFO_V1(pointonsurface);
Datum pointonsurface(PG_FUNCTION_ARGS)
{
/*---------------------------------------------*/
-/*
- * Throws an ereport ERROR if either geometry is a COLLECTIONTYPE. Additionally
- * displays a HINT of the first 80 characters of the WKT representation of the
- * problematic geometry so a user knows which parameter and which geometry
- * is causing the problem.
+/**
+ * @brief Throws an ereport ERROR if either geometry is a COLLECTIONTYPE. Additionally
+ * displays a HINT of the first 80 characters of the WKT representation of the
+ * problematic geometry so a user knows which parameter and which geometry
+ * is causing the problem.
*/
void errorIfGeometryCollection(PG_LWGEOM *g1, PG_LWGEOM *g2)
{
int t1 = lwgeom_getType(g1->type);
int t2 = lwgeom_getType(g2->type);
-
+
LWGEOM_UNPARSER_RESULT lwg_unparser_result;
int result;
char* hintmsg;
ereport(ERROR,
(errmsg("Relate Operation called with a LWGEOMCOLLECTION type. This is unsupported."),
errhint("Change argument 1: '%s'", hintmsg))
- );
+ );
pfree(hintmsg);
}
else if (t2 == COLLECTIONTYPE) {
ereport(ERROR,
(errmsg("Relate Operation called with a LWGEOMCOLLECTION type. This is unsupported."),
errhint("Change argument 2: '%s'", hintmsg))
- );
+ );
pfree(hintmsg);
}
}
}
#if POSTGIS_GEOS_VERSION >= 31
-/*
+/*
** IsValidReason is only available in the GEOS
-** C API > version 3.0
+** C API > version 3.0
*/
PG_FUNCTION_INFO_V1(isvalidreason);
Datum isvalidreason(PG_FUNCTION_ARGS)
reason_str = GEOSisValidReason(g1);
GEOSGeom_destroy((GEOSGeometry *)g1);
-
+
if (reason_str == NULL)
{
elog(ERROR,"GEOS isvalidreason() threw an error!");
PG_FREE_IF_COPY(geom, 0);
PG_RETURN_POINTER(result);
-
+
}
#endif
-/*
+/**
* overlaps(PG_LWGEOM g1,PG_LWGEOM g2)
- * returns if GEOS::g1->overlaps(g2) returns true
- * throws an error (elog(ERROR,...)) if GEOS throws an error
+ * @param g1
+ * @param g2
+ * @return if GEOS::g1->overlaps(g2) returns true
+ * @throw an error (elog(ERROR,...)) if GEOS throws an error
*/
PG_FUNCTION_INFO_V1(overlaps);
Datum overlaps(PG_FUNCTION_ARGS)
* Do the test IFF BOUNDING BOX AVAILABLE.
*/
if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) &&
- getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
+ getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
{
if ( box2.xmax < box1.xmin ) PG_RETURN_BOOL(FALSE);
if ( box2.xmin > box1.xmax ) PG_RETURN_BOOL(FALSE);
** Do the test IFF BOUNDING BOX AVAILABLE.
*/
if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) &&
- getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
+ getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
{
if ( ( box2.xmin < box1.xmin ) || ( box2.xmax > box1.xmax ) ||
- ( box2.ymin < box1.ymin ) || ( box2.ymax > box1.ymax ) )
+ ( box2.ymin < box1.ymin ) || ( box2.ymax > box1.ymax ) )
{
PG_RETURN_BOOL(FALSE);
}
/*
* Switch the context to the function-scope context,
- * retrieve the appropriate cache object, cache it for
+ * retrieve the appropriate cache object, cache it for
* future use, then switch back to the local context.
*/
old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
* Do the test IFF BOUNDING BOX AVAILABLE.
*/
if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) &&
- getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
+ getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
{
if (( box2.xmin < box1.xmin ) || ( box2.xmax > box1.xmax ) ||
- ( box2.ymin < box1.ymin ) || ( box2.ymax > box1.ymax ))
+ ( box2.ymin < box1.ymin ) || ( box2.ymax > box1.ymax ))
PG_RETURN_BOOL(FALSE);
}
* Do the test IFF BOUNDING BOX AVAILABLE.
*/
if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) &&
- getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
+ getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
{
if (( box2.xmin < box1.xmin ) || ( box2.xmax > box1.xmax ) ||
- ( box2.ymin < box1.ymin ) || ( box2.ymax > box1.ymax ))
+ ( box2.ymin < box1.ymin ) || ( box2.ymax > box1.ymax ))
{
PG_RETURN_BOOL(FALSE);
}
/*
* Switch the context to the function-scope context,
- * retrieve the appropriate cache object, cache it for
+ * retrieve the appropriate cache object, cache it for
* future use, then switch back to the local context.
*/
old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
* Do the test IFF BOUNDING BOX AVAILABLE.
*/
if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) &&
- getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
+ getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
{
if ( ( box1.xmin < box2.xmin ) || ( box1.xmax > box2.xmax ) ||
- ( box1.ymin < box2.ymin ) || ( box1.ymax > box2.ymax ) )
+ ( box1.ymin < box2.ymin ) || ( box1.ymax > box2.ymax ) )
{
PG_RETURN_BOOL(FALSE);
}
/*
* Switch the context to the function-scope context,
- * retrieve the appropriate cache object, cache it for
+ * retrieve the appropriate cache object, cache it for
* future use, then switch back to the local context.
*/
old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
* Do the test IFF BOUNDING BOX AVAILABLE.
*/
if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) &&
- getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
+ getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
{
if ( ( box1.xmin < box2.xmin ) || ( box1.xmax > box2.xmax ) ||
- ( box1.ymin < box2.ymin ) || ( box1.ymax > box2.ymax ) )
+ ( box1.ymin < box2.ymin ) || ( box1.ymax > box2.ymax ) )
{
PG_RETURN_BOOL(FALSE);
}
/*
* Switch the context to the function-scope context,
- * retrieve the appropriate cache object, cache it for
+ * retrieve the appropriate cache object, cache it for
* future use, then switch back to the local context.
*/
old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
* Do the test IFF BOUNDING BOX AVAILABLE.
*/
if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) &&
- getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
+ getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
{
if ( ( box2.xmax < box1.xmin ) || ( box2.xmin > box1.xmax ) ||
- ( box2.ymax < box1.ymin ) || ( box2.ymin > box2.ymax ) )
+ ( box2.ymax < box1.ymin ) || ( box2.ymin > box2.ymax ) )
{
PG_RETURN_BOOL(FALSE);
}
* Do the test IFF BOUNDING BOX AVAILABLE.
*/
if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) &&
- getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
+ getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
{
if ( ( box2.xmax < box1.xmin ) || ( box2.xmin > box1.xmax ) ||
- ( box2.ymax < box1.ymin ) || ( box2.ymin > box1.ymax ) )
+ ( box2.ymax < box1.ymin ) || ( box2.ymin > box1.ymax ) )
{
PG_RETURN_BOOL(FALSE);
}
type1 = lwgeom_getType((uchar)SERIALIZED_FORM(geom1)[0]);
type2 = lwgeom_getType((uchar)SERIALIZED_FORM(geom2)[0]);
if ( (type1 == POINTTYPE && (type2 == POLYGONTYPE || type2 == MULTIPOLYGONTYPE)) ||
- (type2 == POINTTYPE && (type1 == POLYGONTYPE || type1 == MULTIPOLYGONTYPE)))
+ (type2 == POINTTYPE && (type1 == POLYGONTYPE || type1 == MULTIPOLYGONTYPE)))
{
POSTGIS_DEBUG(3, "Point in Polygon test requested...short-circuiting.");
}
/*
* Switch the context to the function-scope context,
- * retrieve the appropriate cache object, cache it for
+ * retrieve the appropriate cache object, cache it for
* future use, then switch back to the local context.
*/
old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
* Do the test IFF BOUNDING BOX AVAILABLE.
*/
if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) &&
- getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
+ getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
{
if ( ( box2.xmax < box1.xmin ) || ( box2.xmin > box1.xmax ) ||
- ( box2.ymax < box1.ymin ) || ( box2.ymin > box1.ymax ) )
+ ( box2.ymax < box1.ymin ) || ( box2.ymin > box1.ymax ) )
{
PG_RETURN_BOOL(FALSE);
}
* Do the test IFF BOUNDING BOX AVAILABLE.
*/
if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) &&
- getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
+ getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
{
if ( ( box2.xmax < box1.xmin ) || ( box2.xmin > box1.xmax ) ||
- ( box2.ymax < box1.ymin ) || ( box2.ymin > box1.ymax ) )
+ ( box2.ymax < box1.ymin ) || ( box2.ymin > box1.ymax ) )
{
PG_RETURN_BOOL(TRUE);
}
g2 = (GEOSGeometry *)POSTGIS2GEOS(geom2);
patt = DatumGetCString(DirectFunctionCall1(textout,
- PointerGetDatum(PG_GETARG_DATUM(2))));
+ PointerGetDatum(PG_GETARG_DATUM(2))));
/*
- ** Need to make sure 't' and 'f' are upper-case before handing to GEOS
+ ** Need to make sure 't' and 'f' are upper-case before handing to GEOS
*/
for ( i = 0; i < strlen(patt); i++ )
{
* Do the test IFF BOUNDING BOX AVAILABLE.
*/
if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) &&
- getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
+ getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
{
if ( box2.xmax != box1.xmax ) PG_RETURN_BOOL(FALSE);
if ( box2.xmin != box1.xmin ) PG_RETURN_BOOL(FALSE);
g = GEOSGetInteriorRingN(geom, i);
cs = GEOSGeom_getCoordSeq(g);
ppaa[i+1] = ptarray_from_GEOSCoordSeq(cs,
- want3d);
+ want3d);
}
return (LWGEOM *)lwpoly_construct(SRID, NULL,
- ngeoms+1, ppaa);
+ ngeoms+1, ppaa);
case GEOS_MULTIPOINT:
case GEOS_MULTILINESTRING:
}
}
return (LWGEOM *)lwcollection_construct(type,
- SRID, NULL, ngeoms, geoms);
+ SRID, NULL, ngeoms, geoms);
default:
lwerror("GEOS2LWGEOM: unknown geometry type: %d", type);
GEOSGeometry *geosgeom;
PG_LWGEOM *lwgeom_result;
#if POSTGIS_DEBUG_LEVEL > 0
- int result;
+ int result;
LWGEOM_UNPARSER_RESULT lwg_unparser_result;
#endif
result = serialized_lwgeom_to_ewkt(&lwg_unparser_result, SERIALIZED_FORM(lwgeom_result), PARSER_CHECK_NONE);
POSTGIS_DEBUGF(4, "GEOSnoop: OUT: %s", lwg_unparser_result.wkoutput);
#endif
-
+
PG_FREE_IF_COPY(geom, 0);
PG_RETURN_POINTER(lwgeom_result);
* a LinearRing clone.
*/
sq=GEOSCoordSeq_clone(GEOSGeom_getCoordSeq(
- GEOSGetExteriorRing(GEOSGetGeometryN( geos_result, i))
- ));
+ GEOSGetExteriorRing(GEOSGetGeometryN( geos_result, i))
+ ));
extring = GEOSGeom_createPolygon(
- GEOSGeom_createLinearRing(sq),
- NULL, 0
- );
+ GEOSGeom_createLinearRing(sq),
+ NULL, 0
+ );
if ( extring == NULL ) /* exception */
{