From: Sandro Santilli Date: Tue, 3 Jan 2012 10:10:15 +0000 (+0000) Subject: Move TopoGeom_addXXX functions to populate.sql and refine signatures X-Git-Tag: 2.0.0alpha1~225 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e7a29fe26a4353e1443237c9e0ea59955dd705b7;p=postgis Move TopoGeom_addXXX functions to populate.sql and refine signatures Implement TopoGeom_addPoint (misses regression testing yet) git-svn-id: http://svn.osgeo.org/postgis/trunk@8650 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/topology/sql/populate.sql b/topology/sql/populate.sql index cf89137fd..7e1f054e0 100644 --- a/topology/sql/populate.sql +++ b/topology/sql/populate.sql @@ -13,15 +13,6 @@ -- Functions used to populate a topology -- -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --- --- Developed by Sandro Santilli --- for Faunalia (http://www.faunalia.it) with funding from --- Regione Toscana - Sistema Informativo per la Gestione del Territorio --- e dell' Ambiente [RT-SIGTA]. --- For the project: "Sviluppo strumenti software per il trattamento di dati --- geografici basati su QuantumGIS e Postgis (CIG 0494241492)" --- --- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --{ @@ -36,6 +27,13 @@ -- -- The newly added nodes have no containing face. -- +-- Developed by Sandro Santilli +-- for Faunalia (http://www.faunalia.it) with funding from +-- Regione Toscana - Sistema Informativo per la Gestione del Territorio +-- e dell' Ambiente [RT-SIGTA]. +-- For the project: "Sviluppo strumenti software per il trattamento di dati +-- geografici basati su QuantumGIS e Postgis (CIG 0494241492)" +-- -- }{ CREATE OR REPLACE FUNCTION topology.AddNode(atopology varchar, apoint geometry, allowEdgeSplitting boolean, setContainingFace boolean DEFAULT false) RETURNS int @@ -157,6 +155,12 @@ LANGUAGE 'sql' VOLATILE; -- and links to itself as per next left/right edge. -- Calling code is expected to do further linking. -- +-- Developed by Sandro Santilli +-- for Faunalia (http://www.faunalia.it) with funding from +-- Regione Toscana - Sistema Informativo per la Gestione del Territorio +-- e dell' Ambiente [RT-SIGTA]. +-- For the project: "Sviluppo strumenti software per il trattamento di dati +-- geografici basati su QuantumGIS e Postgis (CIG 0494241492)" -- CREATE OR REPLACE FUNCTION topology.AddEdge(atopology varchar, aline geometry) RETURNS int @@ -345,6 +349,12 @@ LANGUAGE 'plpgsql' VOLATILE; -- o The polygon boundary is not fully defined by existing edges. -- o The polygon overlaps an existing face. -- +-- Developed by Sandro Santilli +-- for Faunalia (http://www.faunalia.it) with funding from +-- Regione Toscana - Sistema Informativo per la Gestione del Territorio +-- e dell' Ambiente [RT-SIGTA]. +-- For the project: "Sviluppo strumenti software per il trattamento di dati +-- geografici basati su QuantumGIS e Postgis (CIG 0494241492)" -- CREATE OR REPLACE FUNCTION topology.AddFace(atopology varchar, apoly geometry, force_new boolean DEFAULT FALSE) RETURNS int @@ -609,3 +619,126 @@ END $$ LANGUAGE 'plpgsql' VOLATILE; --} AddFace + +-- ---------------------------------------------------------------------------- +-- +-- Functions to incrementally populate a topology +-- +-- ---------------------------------------------------------------------------- + +--{ +-- TopoGeo_AddPoint(toponame, pointgeom, tolerance) +-- +-- Add a Point into a topology, with an optional tolerance +-- +CREATE OR REPLACE FUNCTION topology.TopoGeo_AddPoint(atopology varchar, apoint geometry, tolerance float8 DEFAULT 0) + RETURNS int AS +$$ +DECLARE + id integer; + rec RECORD; + sql text; + prj GEOMETRY; + snapedge GEOMETRY; +BEGIN + + -- 1. Check if any existing node falls within tolerance + -- and if so pick the closest + sql := 'SELECT a.node_id FROM ' + || quote_ident(atopology) + || '.node as a WHERE ST_DWithin(a.geom,' + || quote_literal(apoint::text) || '::geometry,' + || tolerance || ') ORDER BY ST_Distance(' + || quote_literal(apoint::text) + || '::geometry, a.geom) LIMIT 1;'; + RAISE DEBUG '%', sql; + EXECUTE sql INTO id; + IF id IS NOT NULL THEN + RETURN id; + END IF; + + RAISE DEBUG 'No existing node within tolerance distance'; + + -- 2. Check if any existing edge falls within tolerance + -- and if so split it by a point projected on it + sql := 'SELECT a.edge_id, a.geom FROM ' + || quote_ident(atopology) + || '.edge as a WHERE ST_DWithin(a.geom,' + || quote_literal(apoint::text) || '::geometry,' + || tolerance || ') ORDER BY ST_Distance(' + || quote_literal(apoint::text) + || '::geometry, a.geom) LIMIT 1;'; + RAISE DEBUG '%', sql; + EXECUTE sql INTO rec; + IF rec IS NOT NULL THEN + RAISE DEBUG 'Splitting edge %', rec.edge_id; + -- project point to line, split edge by point + prj := st_closestpoint(rec.geom, apoint); + IF NOT ST_Contains(rec.geom, prj) THEN + RAISE DEBUG ' Snapping edge to contain closest point'; + -- Snap the edge geometry to the projected point + -- The tolerance is an arbitrary number. + -- How much would be enough to ensure any projected point is within + -- that distance ? ST_Distance() may very well return 0. + snapedge := ST_Snap(rec.geom, prj, 1e-12); -- arbitrarely low number + PERFORM ST_ChangeEdgeGeom(atopology, rec.edge_id, snapedge); + END IF; + id := topology.ST_ModEdgeSplit(atopology, rec.edge_id, prj); + ELSE + RAISE DEBUG 'No existing edge within tolerance distance'; + id := ST_AddIsoNode(atopology, NULL, apoint); + END IF; + + RETURN id; +END +$$ +LANGUAGE 'plpgsql' VOLATILE; +--} TopoGeo_AddPoint + +--{ +-- TopoGeo_addLinestring(toponame, linegeom, tolerance) +-- +-- Add a LineString into a topology +-- +CREATE OR REPLACE FUNCTION topology.TopoGeo_addLinestring(atopology varchar, aline geometry, tolerance float8 DEFAULT 0) + RETURNS void AS +$$ +DECLARE +BEGIN + RAISE EXCEPTION 'TopoGeo_AddLineString not implemented yet'; +END +$$ +LANGUAGE 'plpgsql'; +--} TopoGeo_addLinestring + +--{ +-- TopoGeo_AddPolygon(toponame, polygeom, tolerance) +-- +-- Add a Polygon into a topology +-- +CREATE OR REPLACE FUNCTION topology.TopoGeo_AddPolygon(atopology varchar, apoly geometry, tolerance float8 DEFAULT 0) + RETURNS void AS +$$ +DECLARE +BEGIN + RAISE EXCEPTION 'TopoGeo_AddPolygon not implemented yet'; +END +$$ +LANGUAGE 'plpgsql'; +--} TopoGeo_AddPolygon + +--{ +-- TopoGeo_AddGeometry(toponame, geom, tolerance) +-- +-- Add a Geometry into a topology +-- +CREATE OR REPLACE FUNCTION topology.TopoGeo_AddGeometry(atopology varchar, ageom geometry, tolerance float8 DEFAULT 0) + RETURNS void AS +$$ +DECLARE +BEGIN + RAISE EXCEPTION 'TopoGeo_AddGeometry not implemented yet'; +END +$$ +LANGUAGE 'plpgsql'; +--} TopoGeo_AddGeometry diff --git a/topology/topology.sql.in.c b/topology/topology.sql.in.c index f26d6be99..ff078370d 100644 --- a/topology/topology.sql.in.c +++ b/topology/topology.sql.in.c @@ -1525,93 +1525,6 @@ $$ LANGUAGE 'plpgsql' VOLATILE STRICT; -- } ValidateTopology(toponame) ---{ --- TopoGeo_AddPoint(toponame, pointgeom, layer_id, topogeom_id) --- --- Add a Point (node) into a topology --- -CREATE OR REPLACE FUNCTION topology.TopoGeo_AddPoint(atopology varchar, apoint geometry, integer, integer) - RETURNS int AS -$$ -DECLARE - ret int; -BEGIN - - -- Add nodes (contained in NO face) - SELECT topology.ST_AddIsoNode(atopology, NULL, apoint) INTO ret; - - RAISE NOTICE 'TopoGeo_AddPoint: node: %', ret; - - RETURN ret; - -END -$$ -LANGUAGE 'plpgsql' VOLATILE; ---} TopoGeo_AddPoint - ---{ --- TopoGeo_addLinestring --- --- Add a LineString into a topology --- -CREATE OR REPLACE FUNCTION topology.TopoGeo_addLinestring(atopology varchar, aline geometry) - RETURNS int AS -$$ -DECLARE - rec RECORD; - query text; - firstpoint geometry; - lastpoint geometry; - firstnode int; - lastnode int; - edgeid int; -BEGIN - RAISE DEBUG 'Line: %', ST_asEWKT(aline); - - firstpoint = ST_StartPoint(aline); - lastpoint = ST_EndPoint(aline); - - RAISE DEBUG 'First point: %, Last point: %', - ST_asEWKT(firstpoint), - ST_asEWKT(lastpoint); - - -- Add first and last point nodes (contained in NO face) - SELECT topology.ST_AddIsoNode(atopology, NULL, firstpoint) INTO firstnode; - SELECT topology.ST_AddIsoNode(atopology, NULL, lastpoint) INTO lastnode; - - RAISE NOTICE 'First node: %, Last node: %', firstnode, lastnode; - - -- Add edge - SELECT topology.ST_AddIsoEdge(atopology, firstnode, lastnode, aline) - INTO edgeid; - - RAISE DEBUG 'Edge: %', edgeid; - - RETURN edgeid; -END -$$ -LANGUAGE 'plpgsql'; ---} TopoGeo_addLinestring - ---{ --- TopoGeo_AddPolygon --- --- Add a Polygon into a topology --- -CREATE OR REPLACE FUNCTION topology.TopoGeo_AddPolygon(varchar, geometry) - RETURNS int AS -$$ -DECLARE - rec RECORD; - query text; -BEGIN - - RAISE EXCEPTION 'TopoGeo_AddPolygon not implemented yet'; -END -$$ -LANGUAGE 'plpgsql'; ---} TopoGeo_AddPolygon - --{ -- CreateTopology(name, SRID, precision, hasZ) --