lwerror("unsupported type passed to lwgeom_length_sphere");
return 0.0;
}
+
+/**
+* When features are snapped or sometimes they are just this way, they are very close to
+* the geodetic bounds but slightly over. This routine nudges those points, and only
+* those points, back over to the bounds.
+* http://trac.osgeo.org/postgis/ticket/1292
+*/
+int ptarray_nudge_geodetic(POINTARRAY *pa)
+{
+ int i;
+ POINT4D p;
+ int altered = LW_FALSE;
+ int rv = LW_FALSE;
+ static double tolerance = 1e-10;
+ if ( ! pa ) return;
+ for(i = 0; i < pa->npoints; i++ )
+ {
+ getPoint4d_p(pa, i, &p);
+ if ( p.x < -180.0 && (-180.0 - p.x < tolerance) )
+ {
+ p.x = -180.0;
+ altered = LW_TRUE;
+ }
+ else if ( p.x > 180.0 && (p.x - 180.0 < tolerance) )
+ {
+ p.x = 180.0;
+ altered = LW_TRUE;
+ }
+ else if ( p.y < -90.0 && (-90.0 - p.y < tolerance) )
+ {
+ p.y = -90.0;
+ altered = LW_TRUE;
+ }
+ else if ( p.y > 90.0 && (p.y - 90.0 < tolerance) )
+ {
+ p.y = 90.0;
+ altered = LW_TRUE;
+ }
+ if ( altered == LW_TRUE )
+ {
+ ptarray_set_point4d(pa, i, &p);
+ altered = LW_FALSE;
+ rv = LW_TRUE;
+ }
+ }
+ return rv;
+}
+
+/**
+* When features are snapped or sometimes they are just this way, they are very close to
+* the geodetic bounds but slightly over. This routine nudges those points, and only
+* those points, back over to the bounds.
+* http://trac.osgeo.org/postgis/ticket/1292
+*/
+int lwgeom_nudge_geodetic(LWGEOM *geom)
+{
+ int type;
+ int i = 0;
+ int rv = LW_FALSE;
+
+ assert(geom);
+
+ /* No points in nothing */
+ if ( lwgeom_is_empty(geom) )
+ return LW_FALSE;
+
+ type = geom->type;
+
+ if ( type == POINTTYPE )
+ return ptarray_nudge_geodetic(((LWPOINT*)geom)->point);
+
+ if ( type == LINETYPE )
+ return ptarray_nudge_geodetic(((LWLINE*)geom)->points);
+
+ if ( type == POLYGONTYPE )
+ {
+ LWPOLY *poly = (LWPOLY*)geom;
+ for ( i = 0; i < poly->nrings; i++ )
+ {
+ rv = (rv == LW_TRUE ? rv : ptarray_nudge_geodetic(poly->rings[i]));
+ }
+ return rv;
+ }
+
+ if ( type == TRIANGLETYPE )
+ return ptarray_nudge_geodetic(((LWTRIANGLE*)geom)->points);
+
+ if ( lwtype_is_collection( type ) )
+ {
+ LWCOLLECTION *col = (LWCOLLECTION*)geom;
+
+ for ( i = 0; i < col->ngeoms; i++ )
+ {
+ rv = (rv == LW_TRUE ? rv : ptarray_nudge_geodetic(col->geoms[i]));
+ }
+ return rv;
+ }
+
+ lwerror("unsupported type (%s) passed to lwgeom_nudge_geodetic", lwtype_name(type));
+ return rv;
+}
\ No newline at end of file
/* Check that the coordinates are in range */
if ( lwgeom_check_geodetic(lwgeom) == LW_FALSE )
{
- ereport(ERROR, (
- errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("Coordinate values are out of range [-180 -90, 180 90] for GEOGRAPHY type" )));
+ if ( (! lwgeom_nudge_geodetic(lwgeom)) || lwgeom_check_geodetic(lwgeom) == LW_FALSE )
+ {
+ ereport(ERROR, (
+ errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("Coordinate values are out of range [-180 -90, 180 90] for GEOGRAPHY type" )));
+ }
}
/* Force default SRID to the default */
/* Check if the geography has valid coordinate range. */
if ( lwgeom_check_geodetic(lwgeom) == LW_FALSE )
{
- ereport(ERROR, (
- errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("Coordinate values are out of range [-180 -90, 180 90] for GEOGRAPHY type" )));
+ if ( (! lwgeom_nudge_geodetic(lwgeom)) || lwgeom_check_geodetic(lwgeom) == LW_FALSE )
+ {
+ ereport(ERROR, (
+ errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("Coordinate values are out of range [-180 -90, 180 90] for GEOGRAPHY type" )));
+ }
}
/*