-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_int(low int, high int) 
	RETURNS int AS $$
BEGIN
	RETURN floor(random()* (high-low + 1) + low);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, random_int(1, 20) AS i
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_float(low float, high float) 
	RETURNS float AS $$
BEGIN
	RETURN random()* (high-low + 1) + low;
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, random_float(1, 20) AS f
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geompoint(lowx float, highx float, lowy float, highy float) 
	RETURNS geometry AS $$
BEGIN
	RETURN st_point(random_float(lowx, highx), random_float(lowy, highy));
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, random_geompoint(0, 100, 0, 100) AS g
FROM generate_series(1,10) k;

SELECT k, st_astext(random_geompoint(0, 100, 0, 100))
FROM generate_series(1,10) k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geompointz(lowx float, highx float, lowy float, highy float, lowz float, highz float) 
	RETURNS geometry AS $$
BEGIN
	RETURN st_makepoint(random_float(lowx, highx), random_float(lowy, highy), random_float(lowz, highz));
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, random_geompointz(0, 100, 0, 100, 0, 100) AS g
FROM generate_series(1,10) k;

SELECT k, st_astext(random_geompointz(0, 100, 0, 100, 0, 100))
FROM generate_series(1,10) k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geompointm(lowx float, highx float, lowy float, highy float, 
	lowm float, highm float) 
	RETURNS geometry AS $$
BEGIN
	RETURN st_makepointm(random_float(lowx, highx), random_float(lowy, highy), 
		random_float(lowm, highm));
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, random_geompointm(0, 100, 0, 100, 0, 100) AS g
FROM generate_series(1,10) k;

SELECT k, st_astext(random_geompointm(0, 100, 0, 100, 0, 100))
FROM generate_series(1,10) k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geompointzm(lowx float, highx float, lowy float, highy float, 
	lowz float, highz float, lowm float, highm float) 
	RETURNS geometry AS $$
BEGIN
	RETURN st_makepoint(random_float(lowx, highx), random_float(lowy, highy), 
		random_float(lowz, highz), random_float(lowm, highm));
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, random_geompointzm(0, 100, 0, 100, 0, 100, 0, 100) AS g
FROM generate_series(1,10) k;

SELECT k, st_astext(random_geompointzm(0, 100, 0, 100, 0, 100, 0, 100))
FROM generate_series(1,10) k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geogpoint(lowx float, highx float, lowy float, highy float) 
	RETURNS geography AS $$
BEGIN
	RETURN st_setsrid(st_point(random_float(lowx, highx), random_float(lowy, highy)),4326);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, random_geogpoint(0, 90, 0, 90) AS g
FROM generate_series(1,10) k;

SELECT k, st_astext(random_geogpoint(0, 90, 0, 90))
FROM generate_series(1,10) k;

-------------------------------------------------------------------------------
		
CREATE OR REPLACE FUNCTION random_geomlinestring(lowx float, highx float, 
		lowy float, highy float, maxvertices int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geompoint(lowx, highx, lowy, highy)) INTO result
	FROM generate_series (1, random_int(2, maxvertices)) AS x;
	RETURN st_geometryn(st_unaryunion(ST_LineFromMultiPoint(st_collect(result))),1);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geomlinestring(0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT distinct st_issimple(random_geomlinestring(0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_length(random_geomlinestring(0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geomlinestring(0, 100, 0, 100, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geomlinestringz(lowx float, highx float, 
		lowy float, highy float, lowz float, highz float, maxvertices int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geompointz(lowx, highx, lowy, highy, lowz, highz)) INTO result
	FROM generate_series (1, random_int(2, maxvertices)) AS x;
	RETURN st_geometryn(st_unaryunion(ST_LineFromMultiPoint(st_collect(result))),1);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geomlinestringz(0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT distinct st_issimple(random_geomlinestringz(0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_length(random_geomlinestringz(0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geomlinestringz(0, 100, 0, 100, 0, 100, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------
-- Since we cannot use the function st_unaryunion because it looses the m 
-- dimension, the resulting linestrings are not necessarily simple

CREATE OR REPLACE FUNCTION random_geomlinestringm(lowx float, highx float, 
		lowy float, highy float, lowm float, highm float, maxvertices int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geompointm(lowx, highx, lowy, highy, lowm, highm)) INTO result
	FROM generate_series (1, random_int(2, maxvertices)) AS x;
	RETURN ST_LineFromMultiPoint(st_collect(result));
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geomlinestringm(0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT distinct st_issimple(random_geomlinestringm(0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_length(random_geomlinestringm(0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------
-- Since we cannot use the function st_unaryunion because it looses the m 
-- dimension, the resulting linestrings are not necessarily simple

CREATE OR REPLACE FUNCTION random_geomlinestringzm(lowx float, highx float, 
		lowy float, highy float, lowz float, highz float, lowm float, highm float, maxvertices int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geompointzm(lowx, highx, lowy, highy, lowz, highz, lowm, highm)) INTO result
	FROM generate_series (1, random_int(2, maxvertices)) AS x;
	RETURN ST_LineFromMultiPoint(st_collect(result));
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geomlinestringzm(0, 100, 0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT distinct st_issimple(random_geomlinestringzm(0, 100, 0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_length(random_geomlinestringzm(0, 100, 0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------
		
CREATE OR REPLACE FUNCTION random_geoglinestring(lowx float, highx float, 
		lowy float, highy float, maxvertices int) 
	RETURNS geography AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geompoint(lowx, highx, lowy, highy)) INTO result
	FROM generate_series (1, random_int(2, maxvertices)) AS x;
	RETURN st_setsrid(st_geometryn(st_unaryunion(ST_LineFromMultiPoint(st_collect(result))),1),4326);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geoglinestring(0, 80, 0, 80, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_length(random_geoglinestring(0, 80, 0, 80, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geoglinestring(0, 80, 0, 80, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geompolygon(lowx float, highx float, 
	lowy float, highy float, maxvertices int)
	RETURNS geometry AS $$
DECLARE
	pointarr geometry[];
	noVertices int;
	valid geometry;
BEGIN
	noVertices = random_int(3, maxvertices);
	for i in 1..noVertices 
	loop
		pointarr[i] = random_geompoint(lowx, highx, lowy, highy);
	end loop;
	pointarr[noVertices+1] = pointarr[1];
	return st_geometryn(st_makevalid(st_makepolygon(st_makeline(pointarr))),1);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, random_geompolygon(0, 100, 0, 100, 10) AS g
FROM generate_series(1,10) k;

SELECT distinct st_isvalid(random_geompolygon(0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_astext(random_geompolygon(0, 100, 0, 100, 10)) AS g
FROM generate_series(1,10) k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geompolygonz(lowx float, highx float, 
	lowy float, highy float, lowz float, highz float, maxvertices int)
	RETURNS geometry AS $$
DECLARE
	pointarr geometry[];
	noVertices int;
	t timestamptz;
	valid geometry;
BEGIN
	noVertices = random_int(3, maxvertices);
	for i in 1..noVertices 
	loop
		pointarr[i] = random_geompointz(lowx, highx, lowy, highy, lowz, highz);
	end loop;
	pointarr[noVertices+1] = pointarr[1];
	return st_geometryn(st_makevalid(st_makepolygon(st_makeline(pointarr))),1);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, random_geompolygonz(0, 100, 0, 100, 0, 100, 10) AS g
FROM generate_series(1,10) k;

SELECT distinct st_isvalid(random_geompolygonz(0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_astext(random_geompolygonz(0, 100, 0, 0, 100, 100, 10)) AS g
FROM generate_series(1,10) k;

-------------------------------------------------------------------------------
-- Since we cannot use the function st_makevalid because it looses the m 
-- dimension, the resulting polygons are not necessarily valid

CREATE OR REPLACE FUNCTION random_geompolygonm(lowx float, highx float, 
	lowy float, highy float, lowm float, highm float, maxvertices int)
	RETURNS geometry AS $$
DECLARE
	pointarr geometry[];
	noVertices int;
	valid geometry;
BEGIN
	noVertices = random_int(3, maxvertices);
	for i in 1..noVertices 
	loop
		pointarr[i] = random_geompointm(lowx, highx, lowy, highy, lowm, highm);
	end loop;
	pointarr[noVertices+1] = pointarr[1];
	-- return st_geometryn(st_makevalid(st_makepolygon(st_makeline(pointarr))),1);
	return st_makepolygon(st_makeline(pointarr));
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, random_geompolygonm(0, 100, 0, 100, 0, 100, 10) AS g
FROM generate_series(1,10) k;

SELECT distinct st_isvalid(random_geompolygonm(0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_astext(random_geompolygonm(0, 100, 0, 0, 100, 100, 10)) AS g
FROM generate_series(1,10) k;

-------------------------------------------------------------------------------
-- Since we cannot use the function st_makevalid because it looses the m 
-- dimension, the resulting polygons are not necessarily valid

CREATE OR REPLACE FUNCTION random_geompolygonzm(lowx float, highx float, 
	lowy float, highy float, lowz float, highz float, lowm float, highm float, maxvertices int)
	RETURNS geometry AS $$
DECLARE
	pointarr geometry[];
	noVertices int;
	valid geometry;
BEGIN
	noVertices = random_int(3, maxvertices);
	for i in 1..noVertices 
	loop
		pointarr[i] = random_geompointzm(lowx, highx, lowy, highy, lowz, highz, lowm, highm);
	end loop;
	pointarr[noVertices+1] = pointarr[1];
	-- return st_geometryn(st_makevalid(st_makepolygon(st_makeline(pointarr))),1);
	return st_makepolygon(st_makeline(pointarr));
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, random_geompolygonzm(0, 100, 0, 100, 0, 100, 0, 100, 10) AS g
FROM generate_series(1,10) k;

SELECT distinct st_isvalid(random_geompolygonzm(0, 100, 0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_astext(random_geompolygonzm(0, 100, 0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series(1,10) k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geogpolygon(lowx float, highx float, 
	lowy float, highy float, maxvertices int)
	RETURNS geography AS $$
DECLARE
	pointarr geometry[];
	noVertices int;
	t timestamptz;
BEGIN
	noVertices = random_int(3, maxvertices);
	for i in 1..noVertices 
	loop
		pointarr[i] = random_geompoint(lowx, highx, lowy, highy);
	end loop;
	pointarr[noVertices+1] = pointarr[1];
	RETURN st_setsrid(st_geometryn(st_makevalid(st_makepolygon(st_makeline(pointarr))),1),4326);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, random_geogpolygon(0, 80, 0, 80, 10) AS g
FROM generate_series(1,10) k;

SELECT k, st_astext(random_geogpolygon(0, 80, 0, 80, 10)) AS g
FROM generate_series(1,10) k;

SELECT k, st_area(random_geogpolygon(0, 80, 0, 80, 10)) AS g
FROM generate_series(1,10) k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geommultipoint(lowx float, highx float, 
		lowy float, highy float, maxcard int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geompoint(lowx, highx, lowy, highy)) INTO result
	FROM generate_series (1, random_int(1, maxcard)) AS x;
	RETURN st_collect(result);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geommultipoint(0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geommultipoint(0, 100, 0, 100, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geommultipointz(lowx float, highx float, 
		lowy float, highy float, lowz float, highz float, maxcard int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geompointz(lowx, highx, lowy, highy, lowz, highz)) INTO result
	FROM generate_series (1, random_int(1, maxcard)) AS x;
	RETURN st_collect(result);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geommultipointz(0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geommultipointz(0, 100, 0, 100, 0, 100, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geommultipointm(lowx float, highx float, 
		lowy float, highy float, lowm float, highm float, maxcard int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geompointm(lowx, highx, lowy, highy, lowm, highm)) INTO result
	FROM generate_series (1, random_int(1, maxcard)) AS x;
	RETURN st_collect(result);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geommultipointm(0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geommultipointm(0, 100, 0, 100, 0, 100, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geommultipointzm(lowx float, highx float, 
		lowy float, highy float, lowz float, highz float, lowm float, highm float, maxcard int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geompointzm(lowx, highx, lowy, highy, lowz, highz, lowm, highm)) INTO result
	FROM generate_series (1, random_int(1, maxcard)) AS x;
	RETURN st_collect(result);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geommultipointzm(0, 100, 0, 100, 0, 100, 0, 100, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geommultipointzm(0, 100, 0, 100, 0, 100, 0, 100, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geogmultipoint(lowx float, highx float, 
		lowy float, highy float, maxcard int) 
	RETURNS geography AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geompoint(lowx, highx, lowy, highy)) INTO result
	FROM generate_series (1, random_int(1, maxcard)) AS x;
	RETURN st_setsrid(st_collect(result),4326);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geogmultipoint(0, 80, 0, 80, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geogmultipoint(0, 80, 0, 80, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geommultilinestring(lowx float, highx float, 
		lowy float, highy float, maxvertices int, maxcard int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geomlinestring(lowx, highx, lowy, highy, maxvertices)) INTO result
	FROM generate_series (1, random_int(2, maxcard)) AS x;
	RETURN st_unaryunion(st_collect(result));
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geommultilinestring(0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_length(random_geommultilinestring(0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geommultilinestring(0, 100, 0, 100, 10, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geommultilinestringz(lowx float, highx float, 
		lowy float, highy float, lowz float, highz float, maxvertices int, maxcard int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geomlinestringz(lowx, highx, lowy, highy, lowz, highz, maxvertices)) INTO result
	FROM generate_series (1, random_int(2, maxcard)) AS x;
	RETURN st_unaryunion(st_collect(result));
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geommultilinestringz(0, 100, 0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_length(random_geommultilinestringz(0, 100, 0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geommultilinestringz(0, 100, 0, 100, 0, 100, 10, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------
-- Since we cannot use the function st_unaryunion because it looses the m 
-- dimension, the resulting linestrings are not necessarily simple

CREATE OR REPLACE FUNCTION random_geommultilinestringm(lowx float, highx float, 
		lowy float, highy float, lowm float, highm float, maxvertices int, maxcard int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geomlinestringm(lowx, highx, lowy, highy, lowm, highm, maxvertices)) INTO result
	FROM generate_series (1, random_int(2, maxcard)) AS x;
	-- RETURN st_unaryunion(st_collect(result));
	RETURN st_collect(result);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geommultilinestringm(0, 100, 0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_length(random_geommultilinestringm(0, 100, 0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geommultilinestringm(0, 100, 0, 100, 0, 100, 10, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------
-- Since we cannot use the function st_unaryunion because it looses the m 
-- dimension,1028	 the resulting linestrings are not necessarily simple

CREATE OR REPLACE FUNCTION random_geommultilinestringzm(lowx float, highx float, 
		lowy float, highy float, lowz float, highz float, lowm float, highm float, maxvertices int, maxcard int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geomlinestringzm(lowx, highx, lowy, highy, lowz, highz, lowm, highm, maxvertices)) INTO result
	FROM generate_series (1, random_int(2, maxcard)) AS x;
	-- RETURN st_unaryunion(st_collect(result));
	RETURN st_collect(result);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geommultilinestringzm(0, 100, 0, 100, 0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_length(random_geommultilinestringzm(0, 100, 0, 100, 0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geommultilinestringzm(0, 100, 0, 100, 0, 100, 0, 100, 10, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geogmultilinestring(lowx float, highx float, 
		lowy float, highy float, maxvertices int, maxcard int) 
	RETURNS geography AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geomlinestring(lowx, highx, lowy, highy, maxvertices)) INTO result
	FROM generate_series (1, random_int(2, maxcard)) AS x;
	RETURN st_setsrid(st_unaryunion(st_collect(result)),4326);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geogmultilinestring(0, 80, 0, 80, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_length(random_geogmultilinestring(0, 80, 0, 80, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geogmultilinestring(0, 80, 0, 80, 10, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geommultipolygon(lowx float, highx float, 
		lowy float, highy float, maxvertices int, maxcard int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geompolygon(lowx, highx, lowy, highy, maxvertices)) INTO result
	FROM generate_series (1, random_int(2, maxcard)) AS x;
	RETURN st_makevalid(st_collect(result));
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geommultipolygon(0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_area(random_geommultipolygon(0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geommultipolygon(0, 100, 0, 100, 10, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geommultipolygonz(lowx float, highx float, 
		lowy float, highy float, lowz float, highz float, maxvertices int, maxcard int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geompolygonz(lowx, highx, lowy, highy, lowz, highz, maxvertices)) INTO result
	FROM generate_series (1, random_int(2, maxcard)) AS x;
	RETURN st_makevalid(st_collect(result));
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geommultipolygonz(0, 100, 0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_area(random_geommultipolygonz(0, 100, 0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geommultipolygonz(0, 100, 0, 100, 0, 100, 10, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------
-- Since we cannot use the function st_makevalid because it looses the m 
-- dimension, the resulting polygons are not necessarily valid

CREATE OR REPLACE FUNCTION random_geommultipolygonm(lowx float, highx float, 
		lowy float, highy float, lowm float, highm float, maxvertices int, maxcard int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geompolygonm(lowx, highx, lowy, highy, lowm, highm, maxvertices)) INTO result
	FROM generate_series (1, random_int(2, maxcard)) AS x;
	-- RETURN st_makevalid(st_collect(result));
	RETURN st_collect(result);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geommultipolygonm(0, 100, 0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_area(random_geommultipolygonm(0, 100, 0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geommultipolygonm(0, 100, 0, 100, 0, 100, 10, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------
-- Since we cannot use the function st_makevalid because it looses the m 
-- dimension, the resulting polygons are not necessarily valid

CREATE OR REPLACE FUNCTION random_geommultipolygonzm(lowx float, highx float, 
		lowy float, highy float, lowz float, highz float, lowm float, highm float, maxvertices int, maxcard int) 
	RETURNS geometry AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geompolygonzm(lowx, highx, lowy, highy, lowz, highz, lowm, highm, maxvertices)) INTO result
	FROM generate_series (1, random_int(2, maxcard)) AS x;
	-- RETURN st_makevalid(st_collect(result));
	RETURN st_collect(result);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geommultipolygonzm(0, 100, 0, 100, 0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_area(random_geommultipolygonzm(0, 100, 0, 100, 0, 100, 0, 100, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geommultipolygonzm(0, 100, 0, 100, 0, 100, 0, 100, 10, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION random_geogmultipolygon(lowx float, highx float, 
		lowy float, highy float, maxvertices int, maxcard int) 
	RETURNS geography AS $$
DECLARE
	result geometry[];
BEGIN
	SELECT array_agg(random_geompolygon(lowx, highx, lowy, highy, maxvertices)) INTO result
	FROM generate_series (1, random_int(2, maxcard)) AS x;
	RETURN st_setsrid(st_makevalid(st_collect(result)),4326);
END;
$$ LANGUAGE 'plpgsql' STRICT;

SELECT k, st_astext(random_geogmultipolygon(0, 80, 0, 80, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, st_area(random_geogmultipolygon(0, 80, 0, 80, 10, 10)) AS g
FROM generate_series (1, 15) AS k;

SELECT k, random_geogmultipolygon(0, 80, 0, 80, 10, 10) AS g
FROM generate_series (1, 15) AS k;

-------------------------------------------------------------------------------
