From: Sandro Santilli Date: Fri, 25 Feb 2011 08:56:01 +0000 (+0000) Subject: topology.GetEdgeByPoint: implementation and regress test, by Andrea Peri. Ticket... X-Git-Tag: 2.0.0alpha1~1936 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e13426764b7f487ca9ce2eea3aa7f1bc004e913e;p=postgis topology.GetEdgeByPoint: implementation and regress test, by Andrea Peri. Ticket #791. Note that previous commit (for #793) was GetNodeByPoint. My mistake, sorry. git-svn-id: http://svn.osgeo.org/postgis/trunk@6865 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/topology/Makefile.in b/topology/Makefile.in index 5cd4eb33b..5193f5270 100644 --- a/topology/Makefile.in +++ b/topology/Makefile.in @@ -42,7 +42,7 @@ endif $(SQL_OBJS): %.in: %.in.c $(CPP) -traditional-cpp $< | grep -v '^#' > $@ -topology.sql.in: sql/sqlmm.sql sql/populate.sql sql/gml.sql sql/query/getnodebypoint.sql +topology.sql.in: sql/sqlmm.sql sql/populate.sql sql/gml.sql sql/query/getnodebypoint.sql sql/query/getedgebypoint.sql check: topology.sql $(MAKE) -C test $@ diff --git a/topology/sql/query/getedgebypoint.sql b/topology/sql/query/getedgebypoint.sql new file mode 100644 index 000000000..b8febef7d --- /dev/null +++ b/topology/sql/query/getedgebypoint.sql @@ -0,0 +1,91 @@ +-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-- +-- PostGIS - Spatial Types for PostgreSQL +-- http://postgis.refractions.net +-- +-- Copyright (C) 2011 Andrea Peri +-- +-- This is free software; you can redistribute and/or modify it under +-- the terms of the GNU General Public Licence. See the COPYING file. +-- +-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +--{ +-- +-- Andrea Peri (19 Jan 2011) creation +-- Andrea Peri (14 Feb 2011) minor issues +-- +-- GetEdgeByPoint(atopology, point, tol) +-- +-- Retrieve an Edge ID given a POINT and a tolerance +-- tolerance = 0 mean exactly intersection +-- +-- Returns return the integer ID if there is an edge on the Point. +-- +-- When the Point is even a Node it raise an exception. +-- This case is testable with the GetNodeByPoint(atopology, apoint, tol) +-- +-- If there isn't any edge in the Point, GetEdgeByPoint return 0. +-- +-- if near the point there are two or more edges it throw an exception. +-- +CREATE OR REPLACE FUNCTION topology.GetEdgeByPoint(atopology varchar, apoint geometry, tol1 float8) + RETURNS int +AS +$$ +DECLARE + sql text; + idedge int; +BEGIN + -- + -- Atopology and apoint are required + -- + IF atopology IS NULL OR apoint IS NULL THEN + RAISE EXCEPTION 'Invalid null argument'; + END IF; + + -- + -- Apoint must be a point + -- + IF substring(geometrytype(apoint), 1, 5) != 'POINT' + THEN + RAISE EXCEPTION 'Node geometry must be a point'; + END IF; + + -- + -- Tolerance must be >= 0 + -- + IF tol1 < 0 + THEN + RAISE EXCEPTION 'Tolerance must be >=0'; + END IF; + + + if tol1 = 0 then + sql := 'SELECT a.edge_id FROM ' + || quote_ident(atopology) + || '.edge_data as a WHERE ' + || '(a.geom && ' || quote_literal(apoint::text)||'::geometry) ' + || ' AND (ST_Intersects(a.geom,' || quote_literal(apoint::text)||'::geometry) );'; + else + sql := 'SELECT a.edge_id FROM ' + || quote_ident(atopology) + || '.edge_data as a WHERE ' + || '(ST_DWithin(a.geom,' || quote_literal(apoint::text)||'::geometry,' || tol1::text || ') );'; + end if; + + BEGIN + EXECUTE sql INTO STRICT idedge; + EXCEPTION + WHEN NO_DATA_FOUND THEN + idedge = 0; + WHEN TOO_MANY_ROWS THEN + RAISE EXCEPTION 'Two or more edges founded'; + END; + + RETURN idedge; + +END +$$ +LANGUAGE 'plpgsql' STRICT; +--} GetEdgeByPoint diff --git a/topology/test/Makefile b/topology/test/Makefile index 2de17963a..7980de407 100644 --- a/topology/test/Makefile +++ b/topology/test/Makefile @@ -32,7 +32,8 @@ TESTS = regress/legacy_validate.sql regress/legacy_predicate.sql \ regress/droptopology.sql \ regress/createtopogeom.sql \ regress/gml.sql \ - regress/getnodebypoint.sql + regress/getnodebypoint.sql \ + regress/getedgebypoint.sql check: topo_predicates.sql load_topology.sql load_topology-4326.sql $(MAKE) -C ../../regress postgis.sql staged-install diff --git a/topology/test/regress/getedgebypoint.sql b/topology/test/regress/getedgebypoint.sql new file mode 100644 index 000000000..6dd8d19e1 --- /dev/null +++ b/topology/test/regress/getedgebypoint.sql @@ -0,0 +1,33 @@ +set client_min_messages to WARNING; + +SELECT topology.CreateTopology('schema_topo') > 0; + +select topology.AddEdge('schema_topo',ST_GeomFromText('LINESTRING(1 4, 4 7)')) = 1; +select topology.AddEdge('schema_topo',ST_GeomFromText('LINESTRING(4 7, 6 9)')) = 2; +select topology.AddEdge('schema_topo',ST_GeomFromText('LINESTRING(2 2, 4 4)')) = 3; +select topology.AddEdge('schema_topo',ST_GeomFromText('LINESTRING(4 4, 5 5, 6 6)')) = 4; +select topology.AddEdge('schema_topo',ST_GeomFromText('LINESTRING(6 6, 6 9)')) = 5; + +-- ask for a Point with tolerance zero +select topology.GetEdgeByPoint('schema_topo',ST_GeomFromText('POINT(5 5)'), 0::float8)::int = 4; + +-- ask for a point on an edge +select topology.GetEdgeByPoint('schema_topo',ST_GeomFromText('POINT(5 5)'), 0.1::float8)::int = 4; + +-- Ask for a point outside from an edge with a tolerance sufficient to include one edge +select topology.GetEdgeByPoint('schema_topo',ST_GeomFromText('POINT(5 5.5)'), 0.7::float8)::int = 4; + +-- Ask for a point where there isn't an edge +select topology.GetEdgeByPoint('schema_topo',ST_GeomFromText('POINT(5 5.5)'), 0::float8) = 0; + + +-- Failing cases (should all raise exceptions) ------- + +-- Ask for Point in a Node +select topology.GetEdgeByPoint('schema_topo',ST_GeomFromText('POINT(4 7)'), 1::float8); + +-- Ask for a Point with a tollerance too high +select topology.GetEdgeByPoint('schema_topo',ST_GeomFromText('POINT(5 5)'), 2::float8); + + +SELECT topology.DropTopology('schema_topo'); diff --git a/topology/test/regress/getedgebypoint_expected b/topology/test/regress/getedgebypoint_expected new file mode 100644 index 000000000..1ed60c8fb --- /dev/null +++ b/topology/test/regress/getedgebypoint_expected @@ -0,0 +1,13 @@ +t +t +t +t +t +t +t +t +t +t +ERROR: Two or more edges founded +ERROR: Two or more edges founded +Topology 'schema_topo' dropped diff --git a/topology/topology.sql.in.c b/topology/topology.sql.in.c index 3914c6143..7ff49c6ae 100644 --- a/topology/topology.sql.in.c +++ b/topology/topology.sql.in.c @@ -2413,6 +2413,7 @@ LANGUAGE 'plpgsql' VOLATILE STRICT; -- Querying #include "sql/query/getnodebypoint.sql" +#include "sql/query/getedgebypoint.sql" -- Editing #include "sql/populate.sql"