Datum geography_from_geometry(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
	LWGEOM *lwgeom = NULL;
	GSERIALIZED *g_ser = NULL;

	geography_valid_type(gserialized_get_type(geom));

	lwgeom = lwgeom_from_gserialized(geom);

	/* Force default SRID */
	if ( (int)lwgeom->srid <= 0 )
	{
		lwgeom->srid = SRID_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 )
	{
		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" )));
		}
	}

	/*
	** Serialize our lwgeom and set the geodetic flag so subsequent
	** functions do the right thing.
	*/
	lwgeom_set_geodetic(lwgeom, true);
	/* Recalculate the boxes after re-setting the geodetic bit */
	lwgeom_drop_bbox(lwgeom);
	lwgeom_add_bbox(lwgeom);
	g_ser = geography_serialize(lwgeom);

	/*
	** Replace the unaligned lwgeom with a new aligned one based on GSERIALIZED.
	*/
	lwgeom_free(lwgeom);

	PG_FREE_IF_COPY(geom, 0);
	PG_RETURN_POINTER(g_ser);

}
GSERIALIZED* gserialized_geography_from_lwgeom(LWGEOM *lwgeom, int32 geog_typmod)
{
	GSERIALIZED *g_ser = NULL;

	/* Set geodetic flag */
	lwgeom_set_geodetic(lwgeom, true);

	/* 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 )
	{
		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 */
	if ( (int)lwgeom->srid <= 0 )
		lwgeom->srid = SRID_DEFAULT;

	/*
	** Serialize our lwgeom and set the geodetic flag so subsequent
	** functions do the right thing.
	*/
	g_ser = geography_serialize(lwgeom);

	/* Check for typmod agreement */
	if ( geog_typmod >= 0 )
	{
		postgis_valid_typmod(g_ser, geog_typmod);
		POSTGIS_DEBUG(3, "typmod and geometry were consistent");
	}
	else
	{
		POSTGIS_DEBUG(3, "typmod was -1");
	}

	return g_ser;
}
Example #3
0
Datum geography_in(PG_FUNCTION_ARGS)
{
	char *str = PG_GETARG_CSTRING(0);
	/* Datum geog_oid = PG_GETARG_OID(1); Not needed. */
	int32 geog_typmod = PG_GETARG_INT32(2);
	LWGEOM_PARSER_RESULT lwg_parser_result;
	LWGEOM *lwgeom = NULL;
	GSERIALIZED *g_ser = NULL;

	lwgeom_parser_result_init(&lwg_parser_result);

	/* Empty string. */
	if ( str[0] == '\0' )
		ereport(ERROR,(errmsg("parse error - invalid geometry")));

	/* WKB? Let's find out. */
	if ( str[0] == '0' )
	{
		/* TODO: 20101206: No parser checks! This is inline with current 1.5 behavior, but needs discussion */
		lwgeom = lwgeom_from_hexwkb(str, LW_PARSER_CHECK_NONE);
		/* Error out if something went sideways */
		if ( ! lwgeom ) 
			ereport(ERROR,(errmsg("parse error - invalid geometry")));
	}
	/* WKT then. */
	else
	{
		if ( lwgeom_parse_wkt(&lwg_parser_result, str, LW_PARSER_CHECK_ALL) == LW_FAILURE )
			PG_PARSER_ERROR(lwg_parser_result);

		lwgeom = lwg_parser_result.geom;
	}

	/* Set geodetic flag */
	lwgeom_set_geodetic(lwgeom, true);

	/* 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 )
	{
		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 */
	if ( (int)lwgeom->srid <= 0 )
		lwgeom->srid = SRID_DEFAULT;

	if ( geog_typmod >= 0 )
	{
		postgis_valid_typmod(lwgeom, geog_typmod);
		POSTGIS_DEBUG(3, "typmod and geometry were consistent");
	}
	else
	{
		POSTGIS_DEBUG(3, "typmod was -1");
	}

	/*
	** Serialize our lwgeom and set the geodetic flag so subsequent
	** functions do the right thing.
	*/
	g_ser = geography_serialize(lwgeom);

	/* Clean up temporary object */
	lwgeom_free(lwgeom);

	PG_RETURN_POINTER(g_ser);

}