-- Copyright (C) 2010 Sandro Santilli <strk@keybit.net>
-- 
-- This work is placed into the public domain.
--
-- SYNOPSYS:
--   longitudeWrap(geometry, wrap float8, move float8)
--
-- DESCRIPTION:
--
--   This function moves every component of input geometry
--   whose bounding box falls completely on the right (for
--   negative 'move') or on the left (for positive 'move')
--   of given 'wrap' line in the direction specified
--   by the 'move' parameter. 
--
--   It is useful to "recenter" long-lat input to have features
--   of interest not spawned from one side to the other.
--
-- USAGE:
--
--	-- Move all components of the given geometries whose bounding box
--	-- falls completely on the left of x=0 to +360
--	select longitudeWrap(the_geom, 0, 360); 
--
--	-- Move all components of the given geometries whose bounding box
--	-- falls completely on the left of x=-30 to +360
--	select longitudeWrap(the_geom, -30, 360); 
--
--
CREATE OR REPLACE FUNCTION longitudeWrap(geom_in geometry, cutx float8, amount float8)
RETURNS geometry AS $$
DECLARE
	geom_out geometry;
	srid int;
BEGIN
	SELECT ST_SRID(geom_in) INTO srid;

	IF amount = 0 THEN
		RETURN geom_in;
	ELSIF amount < 0 THEN
		-- move left what is completely on the right of cutx
		SELECT ST_Collect(component) INTO geom_out FROM (
			SELECT
			CASE WHEN geom >> ST_SetSrid(ST_MakePoint(cutx, 0), srid) THEN
				ST_Translate(geom, amount, 0)
			ELSE
				geom
			END as component
			FROM (
				SELECT (ST_Dump(geom_in)).geom 
			) as dump
		) as processed;
	ELSE -- amount > 0
		-- move right what is completely on the left of cutx
		SELECT ST_Collect(component) INTO geom_out FROM (
			SELECT
			CASE WHEN geom << ST_SetSrid(ST_MakePoint(cutx, 0), srid) THEN
				ST_Translate(geom, amount, 0)
			ELSE
				geom
			END as component
			FROM (
				SELECT (ST_Dump(geom_in)).geom 
			) as dump
		) as processed;
	END IF;

	RETURN geom_out;
END
$$ LANGUAGE 'plpgsql';
