$(SQL_OBJS): %.in: %.in.c
$(CPP) -traditional-cpp $< | grep -v '^#' > $@
-topology.sql.in: sql/sqlmm.sql sql/populate.sql sql/gml.sql
+topology.sql.in: sql/sqlmm.sql sql/populate.sql sql/gml.sql sql/query/getnodebypoint.sql
check: topology.sql
$(MAKE) -C test $@
--- /dev/null
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+--
+-- 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
+--
+-- getnodebypoint(atopology, point, tolerance)
+--
+-- Retrieve a Node ID given a POINT and a tolerance
+-- tolerance = 0 mean exactly intersection
+--
+-- Returns the integer ID if there is a Node on the Point.
+--
+-- If there isn't any node in the Point, GetNodeByPoint return 0.
+--
+-- if near the point there are two or more nodes it throw an exception.
+--
+CREATE OR REPLACE FUNCTION topology.GetNodeByPoint(atopology varchar, apoint geometry, tol1 float8)
+ RETURNS int
+AS
+$$
+DECLARE
+ sql text;
+ idnode 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.node_id FROM '
+ || quote_ident(atopology)
+ || '.node as a WHERE '
+ || '(a.geom && ' || quote_literal(apoint::text)||'::geometry) '
+ || ' AND (ST_Intersects(a.geom,' || quote_literal(apoint::text)||'::geometry) );';
+ else
+ sql := 'SELECT a.node_id FROM '
+ || quote_ident(atopology)
+ || '.node as a WHERE '
+ || '(ST_DWithin(a.geom,' || quote_literal(apoint::text)||'::geometry,' || tol1::text || ') );';
+ end if;
+
+ BEGIN
+ EXECUTE sql INTO STRICT idnode;
+ EXCEPTION
+ WHEN NO_DATA_FOUND THEN
+ idnode = 0;
+ WHEN TOO_MANY_ROWS THEN
+ RAISE EXCEPTION 'Two or more nodes founded';
+ END;
+
+ RETURN idnode;
+
+END
+$$
+LANGUAGE 'plpgsql' STRICT;
+--} GetNodeByPoint
+
regress/topoelementarray_agg.sql \
regress/droptopology.sql \
regress/createtopogeom.sql \
- regress/gml.sql
+ regress/gml.sql \
+ regress/getnodebypoint.sql
check: topo_predicates.sql load_topology.sql load_topology-4326.sql
$(MAKE) -C ../../regress postgis.sql staged-install
--- /dev/null
+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 on a Point with tolerance zero
+select topology.GetNodeByPoint('schema_topo',ST_GeomFromText('POINT(5 5)'), 0::float8);
+
+-- ask on a Point on a node with tolerance
+select topology.GetNodeByPoint('schema_topo',ST_GeomFromText('POINT(4 4)'), 0::float8);
+
+-- Ask for a point outside from an edge with a tolerance sufficient to include one node
+select topology.GetNodeByPoint('schema_topo',ST_GeomFromText('POINT(4.1 4)'), 0.3::float8);
+
+-- Ask for a point where there isn't a node
+select topology.GetNodeByPoint('schema_topo',ST_GeomFromText('POINT(5 5.5)'), 0::float8) = 0;
+
+
+-- Failing cases (should all raise exceptions) -------
+
+-- Ask for a Point with a tollerance too high
+select topology.GetNodeByPoint('schema_topo',ST_GeomFromText('POINT(4 7)'), 5::float8);
+
+
+SELECT topology.DropTopology('schema_topo');
--- /dev/null
+t
+t
+t
+t
+t
+t
+0
+5
+5
+t
+ERROR: Two or more nodes founded
+Topology 'schema_topo' dropped
--=} POSTGIS-SPECIFIC topology predicates
+-- Querying
+#include "sql/query/getnodebypoint.sql"
+
-- Editing
#include "sql/populate.sql"