Az egyik beadandómhoz környezeti rekonstrukciót kell készítenem (kettőnknek, úgyhogy készítenünk). A feladat erdők, mezők, települések, tehát felületek digitalizálása. Sajnos a postgis 2.0-át még nem követte a QGIS, így az adatbáziskezelőhöz írt legújabb fejlesztést a topológikus adattárolást, csak mint elemi geometriát képes megjeleníteni (nodes, edges, faces). Pedig nekem ezekre nincs szükségem. Viszont arra igen, hogy még szándékosan se lehessen olyan poligont beszúrni, ami fed már egy korábban létrehozott poligont.
Ezt a feladatot életem első trigger funkciójával oldottam meg.
A teljes fájl letölthető innen.
CREATE TABLE felulet (tipus int,pk_gid serial not null primary key);
SELECT addgeometrycolumn('felulet','the_geom', 23700, 'POLYGON', 2);
CREATE OR REPLACE FUNCTION rewrite_overlap() RETURNS TRIGGER AS $foo$
DECLARE
--Kurzor megnyitása és adott sorokra szűkítése
cur CURSOR FOR SELECT * FROM felulet WHERE ST_INTERSECTS(the_geom,NEW.the_geom);
--Kurzor adott sorait ebbe a változóba mentem, ezt kötelező itt deklarálni
temp_row felulet%ROWTYPE;
BEGIN
--kurzor aktiválása
OPEN cur;
--Ha beszúrás történi akkor
IF TG_OP = 'INSERT' THEN
-- Ciklus eleje, ciklusra azért van szükség, mert több poligonnal is találkozhat
LOOP
-- Kurzor soron következő sorát olvassa be a temp_row változóba
FETCH cur INTO temp_row;
-- Ha nincs kiolvasandó érték a ciklus érjen véget
EXIT WHEN NOT FOUND;
-- Abban az esetben, ha azonos típusú felület érintkezik (pl erdő-erdővel) olvassza egybe
IF NEW.tipus = temp_row.tipus THEN
--Az új geometriában egyesítődnek az érintkező azonos típusú felületek
NEW.the_geom = (SELECT ST_UNION(NEW.the_geom,temp_row.the_geom)) as the_geom;
--A beolvasztott felületek törlésre kerűlnek
DELETE FROM felulet WHERE CURRENT OF cur;
ELSE
--Ha különböző típusú felülettel találkozik, akkor vágja ki a fedésben lévő részt az újból
NEW.the_geom = (SELECT ST_DIFFERENCE(NEW.the_geom,temp_row.the_geom)) as the_geom;
END IF;
END LOOP; -- ciklus vége
END IF;
IF TG_OP = 'UPDATE' THEN
LOOP
FETCH cur INTO temp_row;
EXIT WHEN NOT FOUND;
--Update, vagyis módosítás esetén ki kell emelni a módosítandó geometriát
IF NEW.pk_gid <> temp_row.pk_gid THEN
IF NEW.tipus = temp_row.tipus THEN
NEW.the_geom = (SELECT ST_UNION(NEW.the_geom,temp_row.the_geom)) as the_geom;
DELETE FROM felulet WHERE CURRENT OF cur;
ELSE
NEW.the_geom = (SELECT ST_DIFFERENCE(NEW.the_geom,temp_row.the_geom)) as the_geom;
END IF;
END IF;
END LOOP;
END IF;
CLOSE cur;
RETURN NEW;
END
$foo$
LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS teszt ON felulet CASCADE;
--Trigger regisztrálása
CREATE TRIGGER teszt BEFORE INSERT OR UPDATE ON felulet FOR EACH ROW EXECUTE PROCEDURE rewrite_overlap();
Vígan lehet digitalizálni, és végre értelmet nyer, az ötpercenkénti mentés is:)
Az erdőt mocsár veszi körbe, a trigger automatikusan kivágja az erdőt (jó mi?) |
Tessék, ki van vágva az erdő... Kössz trigger :) |
Nincsenek megjegyzések:
Megjegyzés küldése