[postgis-users] Chained Intersections?
Curtis W. Ruck
ruckc at yahoo.com
Mon Oct 9 22:23:53 PDT 2006
This is a requirement given to me. (I had no say in it, but it would make my application ultra cool)
I need to have the ability to output from the database all possible intersections over a set of polygons. I wrote a pl/pgsql function Intersection(GeometryCollection) that iterates over the geometry collection and returns the intersection of all given polygons. The problem is that if all of the polygons don't share an area then it returns nothing. I need to write a pl/pgsql function that takes a GeometryCollection and outputs a set of polygons and integers. Each polygon would have an integer showing how many polygons intersected to create that polygon.
For example, if you look at http://orbyn.mine.nu/intersections/4polys.png (to save the mailing list the attachment) the input polygons (red, green, blue) should return (yellow, cyan, purple, white) from the function where yellow, cyan, purple have a value of 2 and white has a value of 3.
I wrote a pl/pgsql function that i thought would do this, far below labeled Intersection_All. The problem with this is that it needs to be called from a FROM clause because it returns a SETOF records, but within a FROM clause i can't do an aggregate method collect(the_geom). (I also tried a subquery in the FROM clause).
Does anyone have any suggestions on how to warp Postgres/PostGIS into doing this?
Curtis W. Ruck
<unnamed large entity>
CREATE OR REPLACE FUNCTION intersection_all(in_polys geometry, OUT intersection_count int, OUT the_geom geometry)
RETURNS SETOF record AS
$BODY$
DECLARE
total_count int := 0;
current_level_count int := 0;
first_id_of_previous_level int := 0;
last_id_of_previous_level int:= 0;
num_intersections int ARRAY[0];
geometries geometry ARRAY[0];
temp_geom geometry;
BEGIN
FOR i IN 1..NumGeometries(in_polys) LOOP
FOR j IN i+1..NumGeometries(in_polys) LOOP
IF Intersects(GeometryN(in_polys,i),GeometryN(in_polys,j)) THEN
temp_geom := Intersection(GeometryN(in_polys,i),GeometryN(in_polys,j));
geometries := geometries || temp_geom;
num_intersections := num_intersections || 1;
last_id_of_previous_level := last_id_of_previous_level+1;
total_count := total_count +1;
END IF;
END LOOP;
END LOOP;
FOR level IN 2..100 LOOP
FOR i IN first_id_of_previous_level..last_id_of_previous_level LOOP
FOR j IN i+1..last_id_of_previous_level LOOP
IF Intersects(geometries[i],geometries[j]) THEN
temp_geom := Intersection(geometries[i],geometries[j]);
current_level_count := current_level_count+1;
geometries := geometries || temp_geom;
num_intersections := num_intersections || level;
total_count := total_count +1;
END IF;
END LOOP;
END LOOP;
IF current_level_count > 0 THEN
first_id_of_previous_level := last_id_of_previous_level+1;
last_id_of_previous_level := first_id_of_previous_level+current_level_count;
current_level_count := 0;
ELSE
EXIT;
END IF;
END LOOP;
FOR i IN 1..total_count LOOP
the_geom = geometries[i];
intersection_count = num_intersections[i];
RETURN NEXT;
END LOOP;
RETURN;
END;
$BODY$
LANGUAGE 'plpgsql' IMMUTABLE;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/postgis-users/attachments/20061009/39b47680/attachment.html>
More information about the postgis-users
mailing list