]> granicus.if.org Git - postgis/commitdiff
topology.GetEdgeByPoint: implementation and regress test, by Andrea Peri. Ticket...
authorSandro Santilli <strk@keybit.net>
Fri, 25 Feb 2011 08:56:01 +0000 (08:56 +0000)
committerSandro Santilli <strk@keybit.net>
Fri, 25 Feb 2011 08:56:01 +0000 (08:56 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@6865 b70326c6-7e19-0410-871a-916f4a2858ee

topology/Makefile.in
topology/sql/query/getedgebypoint.sql [new file with mode: 0644]
topology/test/Makefile
topology/test/regress/getedgebypoint.sql [new file with mode: 0644]
topology/test/regress/getedgebypoint_expected [new file with mode: 0644]
topology/topology.sql.in.c

index 5cd4eb33b8cd2988975e9667dbc96741feb7cffa..5193f52706807cba70df1766ee6ef545b1e7cb2f 100644 (file)
@@ -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 (file)
index 0000000..b8febef
--- /dev/null
@@ -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
index 2de17963a53a98253b72976d7a008dea39334449..7980de4075f27895c46440abc1a338ce34263f7d 100644 (file)
@@ -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 (file)
index 0000000..6dd8d19
--- /dev/null
@@ -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 (file)
index 0000000..1ed60c8
--- /dev/null
@@ -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
index 3914c6143102679aec59a5cb0920a51ca6921072..7ff49c6ae5302bb3ba871874cdcaf4d87188550c 100644 (file)
@@ -2413,6 +2413,7 @@ LANGUAGE 'plpgsql' VOLATILE STRICT;
 
 --  Querying
 #include "sql/query/getnodebypoint.sql"
+#include "sql/query/getedgebypoint.sql"
 
 --  Editing
 #include "sql/populate.sql"