*/
extern int32_t lwgeom_get_srid(const LWGEOM *geom);
+/**
+* Return LWTYPE number
+*/
+extern uint32_t lwgeom_get_type(const LWGEOM *geom);
+
/**
* Return #LW_TRUE if geometry has Z ordinates
*/
extern GSERIALIZED* gserialized_copy(const GSERIALIZED *g);
/**
-* Check that coordinates of LWGEOM are all within the geodetic range.
+* Check that coordinates of LWGEOM are all within the geodetic range (-180, -90, 180, 90)
*/
extern int lwgeom_check_geodetic(const LWGEOM *geom);
/**
-* Check that coordinates of LWGEOM are all within the geodetic range.
+* Gently move coordinates of LWGEOM if they are close enough into geodetic range.
*/
extern int lwgeom_nudge_geodetic(LWGEOM *geom);
+/**
+* Force coordinates of LWGEOM into geodetic range (-180, -90, 180, 90)
+*/
+extern int lwgeom_force_geodetic(LWGEOM *geom);
+
/**
* Set the FLAGS geodetic bit on geometry an all sub-geometries and pointlists
*/
return LW_FALSE;
}
+static int ptarray_force_geodetic(POINTARRAY *pa)
+{
+ int t;
+ int changed = LW_FALSE;
+ POINT4D pt;
+
+ assert(pa);
+
+ for ( t=0; t < pa->npoints; t++ )
+ {
+ getPoint4d_p(pa, t, &pt);
+ if ( pt.x < -180.0 || pt.x > 180.0 || pt.y < -90.0 || pt.y > 90.0 )
+ {
+ pt.x = longitude_degrees_normalize(pt.x);
+ pt.y = latitude_degrees_normalize(pt.y);
+ ptarray_set_point4d(pa, t, &pt);
+ changed = LW_TRUE;
+ }
+ }
+ return changed;
+}
+
+static int lwpoint_force_geodetic(LWPOINT *point)
+{
+ assert(point);
+ return ptarray_force_geodetic(point->point);
+}
+
+static int lwline_force_geodetic(LWLINE *line)
+{
+ assert(line);
+ return ptarray_force_geodetic(line->points);
+}
+
+static int lwpoly_force_geodetic(LWPOLY *poly)
+{
+ int i = 0;
+ int changed = LW_FALSE;
+ assert(poly);
+
+ for ( i = 0; i < poly->nrings; i++ )
+ {
+ if ( ptarray_force_geodetic(poly->rings[i]) == LW_TRUE )
+ changed = LW_TRUE;
+ }
+ return changed;
+}
+
+static int lwcollection_force_geodetic(LWCOLLECTION *col)
+{
+ int i = 0;
+ int changed = LW_FALSE;
+ assert(col);
+
+ for ( i = 0; i < col->ngeoms; i++ )
+ {
+ if ( lwgeom_force_geodetic(col->geoms[i]) == LW_TRUE )
+ changed = LW_TRUE;
+ }
+ return changed;
+}
+
+int lwgeom_force_geodetic(LWGEOM *geom)
+{
+ switch ( lwgeom_get_type(geom) )
+ {
+ case POINTTYPE:
+ return lwpoint_force_geodetic((LWPOINT *)geom);
+ case LINETYPE:
+ return lwline_force_geodetic((LWLINE *)geom);
+ case POLYGONTYPE:
+ return lwpoly_force_geodetic((LWPOLY *)geom);
+ case MULTIPOINTTYPE:
+ case MULTILINETYPE:
+ case MULTIPOLYGONTYPE:
+ case COLLECTIONTYPE:
+ return lwcollection_force_geodetic((LWCOLLECTION *)geom);
+ default:
+ lwerror("unsupported input geometry type: %d", lwgeom_get_type(geom));
+ }
+ return LW_FALSE;
+}
+
+
double ptarray_length_spheroid(const POINTARRAY *pa, const SPHEROID *s)
{
GEOGRAPHIC_POINT a, b;
return geom->srid;
}
+uint32_t
+lwgeom_get_type(const LWGEOM *geom)
+{
+ if ( ! geom ) return 0;
+ return geom->type;
+}
+
int
lwgeom_has_z(const LWGEOM *geom)
{
/* Check that this is a type we can handle */
geography_valid_type(lwgeom->type);
- /* Check that the coordinates are in range */
- if ( lwgeom_check_geodetic(lwgeom) == LW_FALSE )
+ /* Force the geometry to have valid geodetic coordinate range. */
+ if ( lwgeom_force_geodetic(lwgeom) == LW_TRUE )
{
- 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" )));
- }
+ ereport(NOTICE, (
+ errmsg_internal("Coordinate values were coerced into range [-180 -90, 180 90] for GEOGRAPHY" ))
+ );
}
/* Force default SRID to the default */
/* Error on any SRID != default */
srid_is_latlong(fcinfo, lwgeom->srid);
- /* Check if the geography has valid coordinate range. */
- if ( lwgeom_check_geodetic(lwgeom) == LW_FALSE )
+ /* Force the geometry to have valid geodetic coordinate range. */
+ if ( lwgeom_force_geodetic(lwgeom) == LW_TRUE )
{
- 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" )));
- }
+ ereport(NOTICE, (
+ errmsg_internal("Coordinate values were coerced into range [-180 -90, 180 90] for GEOGRAPHY" ))
+ );
}
/*
ERROR: AddToPROJ4SRSCache: could not parse proj4 string ''
#1038|
#1042|2
+NOTICE: Coordinate values were coerced into range [-180 -90, 180 90] for GEOGRAPHY
#1170|90
#1264|t
#1398a|POINT(-119.093153 45.632669)