]> granicus.if.org Git - postgis/commitdiff
Put overridden (for topology) spatial predicates in their own file
authorSandro Santilli <strk@keybit.net>
Thu, 29 Dec 2011 07:04:29 +0000 (07:04 +0000)
committerSandro Santilli <strk@keybit.net>
Thu, 29 Dec 2011 07:04:29 +0000 (07:04 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@8606 b70326c6-7e19-0410-871a-916f4a2858ee

topology/Makefile.in
topology/sql/predicates.sql [new file with mode: 0644]
topology/topology.sql.in.c

index f694126dc86224a5033a577dd6ead6eb4a8a8661..81a709c8e82295cea7aceab995a75d3ddc41f995 100644 (file)
@@ -66,7 +66,7 @@ topology_upgrade_20_minor.sql:  topology.sql
                 -e '/^\(CREATE\|ALTER\) \(CAST\|TYPE\|TABLE\|SCHEMA\|DOMAIN\|TRIGGER\)/,/\;/d' \
                 $< > $@
 
-topology.sql.in: sql/sqlmm.sql sql/populate.sql sql/polygonize.sql sql/gml.sql sql/query/getnodebypoint.sql sql/query/getedgebypoint.sql sql/query/getfacebypoint.sql sql/query/GetRingEdges.sql sql/manage/TopologySummary.sql sql/manage/CopyTopology.sql sql/manage/ManageHelper.sql sql/topoelement/topoelement_agg.sql sql/topogeometry/type.sql sql/topogeometry/totopogeom.sql
+topology.sql.in: sql/sqlmm.sql sql/populate.sql sql/polygonize.sql sql/gml.sql sql/query/getnodebypoint.sql sql/query/getedgebypoint.sql sql/query/getfacebypoint.sql sql/query/GetRingEdges.sql sql/manage/TopologySummary.sql sql/manage/CopyTopology.sql sql/manage/ManageHelper.sql sql/topoelement/topoelement_agg.sql sql/topogeometry/type.sql sql/topogeometry/totopogeom.sql sql/predicates.sql
 
 uninstall_topology.sql: topology.sql ../utils/create_undef.pl 
        $(PERL) ../utils/create_undef.pl $< $(POSTGIS_PGSQL_VERSION) > $@
diff --git a/topology/sql/predicates.sql b/topology/sql/predicates.sql
new file mode 100644 (file)
index 0000000..1dd5cae
--- /dev/null
@@ -0,0 +1,517 @@
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+--
+-- PostGIS - Spatial Types for PostgreSQL
+-- http://postgis.refractions.net
+--
+-- Copyright (C) 2011-2012 Sandro Santilli <strk@keybit.net>
+-- Copyright (C) 2005 Refractions Research Inc.
+--
+-- This is free software; you can redistribute and/or modify it under
+-- the terms of the GNU General Public Licence. See the COPYING file.
+--
+-- Author: Sandro Santilli <strk@keybit.net>
+--  
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+--
+--  Overloaded spatial predicates for TopoGeometry inputs
+--
+--   FUNCTION intersects(TopoGeometry, TopoGeometry)
+--   FUNCTION equals(TopoGeometry, TopoGeometry)
+--
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+--{
+-- Intersects(TopoGeometry, TopoGeometry)
+--
+CREATE OR REPLACE FUNCTION topology.intersects(topology.TopoGeometry, topology.TopoGeometry)
+       RETURNS bool
+AS
+$$
+DECLARE
+       tg1 alias for $1;
+       tg2 alias for $2;
+       tgbuf topology.TopoGeometry;
+       rec RECORD;
+       toponame varchar;
+       query text;
+BEGIN
+       IF tg1.topology_id != tg2.topology_id THEN
+               RAISE EXCEPTION 'Cannot compute intersection between TopoGeometries from different topologies';
+       END IF;
+
+       -- Order TopoGeometries so that tg1 has less-or-same
+       -- dimensionality of tg1 (point,line,polygon,collection)
+       IF tg1.type > tg2.type THEN
+               tgbuf := tg2;
+               tg2 := tg1;
+               tg1 := tgbuf;
+       END IF;
+
+       --RAISE NOTICE 'tg1.id:% tg2.id:%', tg1.id, tg2.id;
+       -- Geometry collection are not currently supported
+       IF tg2.type = 4 THEN
+               RAISE EXCEPTION 'GeometryCollection are not supported by intersects()';
+       END IF;
+
+        -- Get topology name
+        SELECT name FROM topology.topology into toponame
+                WHERE id = tg1.topology_id;
+
+       -- Hierarchical TopoGeometries are not currently supported
+       query = 'SELECT level FROM topology.layer'
+               || ' WHERE '
+               || ' topology_id = ' || tg1.topology_id
+               || ' AND '
+               || '( layer_id = ' || tg1.layer_id
+               || ' OR layer_id = ' || tg2.layer_id
+               || ' ) '
+               || ' AND level > 0 ';
+
+       --RAISE NOTICE '%', query;
+
+       FOR rec IN EXECUTE query
+       LOOP
+               RAISE EXCEPTION 'Hierarchical TopoGeometries are not currently supported by intersects()';
+       END LOOP;
+
+       IF tg1.type = 1 THEN -- [multi]point
+
+
+               IF tg2.type = 1 THEN -- point/point
+       ---------------------------------------------------------
+       -- 
+       --  Two [multi]point features intersect if they share
+       --  any Node 
+       --
+       --
+       --
+                       query =
+                               'SELECT a.topogeo_id FROM '
+                               || quote_ident(toponame) ||
+                               '.relation a, '
+                               || quote_ident(toponame) ||
+                               '.relation b '
+                               || 'WHERE a.layer_id = ' || tg1.layer_id
+                               || ' AND b.layer_id = ' || tg2.layer_id
+                               || ' AND a.topogeo_id = ' || tg1.id
+                               || ' AND b.topogeo_id = ' || tg2.id
+                               || ' AND a.element_id = b.element_id '
+                               || ' LIMIT 1';
+                       --RAISE NOTICE '%', query;
+                       FOR rec IN EXECUTE query
+                       LOOP
+                               RETURN TRUE; -- they share an element
+                       END LOOP;
+                       RETURN FALSE; -- no elements shared
+       --
+       ---------------------------------------------------------
+                       
+
+               ELSIF tg2.type = 2 THEN -- point/line
+       ---------------------------------------------------------
+       -- 
+       --  A [multi]point intersects a [multi]line if they share
+       --  any Node. 
+       --
+       --
+       --
+                       query =
+                               'SELECT a.topogeo_id FROM '
+                               || quote_ident(toponame) ||
+                               '.relation a, '
+                               || quote_ident(toponame) ||
+                               '.relation b, '
+                               || quote_ident(toponame) ||
+                               '.edge_data e '
+                               || 'WHERE a.layer_id = ' || tg1.layer_id
+                               || ' AND b.layer_id = ' || tg2.layer_id
+                               || ' AND a.topogeo_id = ' || tg1.id
+                               || ' AND b.topogeo_id = ' || tg2.id
+                               || ' AND abs(b.element_id) = e.edge_id '
+                               || ' AND ( '
+                                       || ' e.start_node = a.element_id '
+                                       || ' OR '
+                                       || ' e.end_node = a.element_id '
+                               || ' )'
+                               || ' LIMIT 1';
+                       --RAISE NOTICE '%', query;
+                       FOR rec IN EXECUTE query
+                       LOOP
+                               RETURN TRUE; -- they share an element
+                       END LOOP;
+                       RETURN FALSE; -- no elements shared
+       --
+       ---------------------------------------------------------
+
+               ELSIF tg2.type = 3 THEN -- point/polygon
+       ---------------------------------------------------------
+       -- 
+       --  A [multi]point intersects a [multi]polygon if any
+       --  Node of the point is contained in any face of the
+       --  polygon OR ( is end_node or start_node of any edge
+       --  of any polygon face ).
+       --
+       --  We assume the Node-in-Face check is faster becasue
+       --  there will be less Faces then Edges in any polygon.
+       --
+       --
+       --
+       --
+                       -- Check if any node is contained in a face
+                       query =
+                               'SELECT n.node_id as id FROM '
+                               || quote_ident(toponame) ||
+                               '.relation r1, '
+                               || quote_ident(toponame) ||
+                               '.relation r2, '
+                               || quote_ident(toponame) ||
+                               '.node n '
+                               || 'WHERE r1.layer_id = ' || tg1.layer_id
+                               || ' AND r2.layer_id = ' || tg2.layer_id
+                               || ' AND r1.topogeo_id = ' || tg1.id
+                               || ' AND r2.topogeo_id = ' || tg2.id
+                               || ' AND n.node_id = r1.element_id '
+                               || ' AND r2.element_id = n.containing_face '
+                               || ' LIMIT 1';
+                       --RAISE NOTICE '%', query;
+                       FOR rec IN EXECUTE query
+                       LOOP
+                               --RAISE NOTICE 'Node % in polygon face', rec.id;
+                               RETURN TRUE; -- one (or more) nodes are
+                                            -- contained in a polygon face
+                       END LOOP;
+
+                       -- Check if any node is start or end of any polygon
+                       -- face edge
+                       query =
+                               'SELECT n.node_id as nid, e.edge_id as eid '
+                               || ' FROM '
+                               || quote_ident(toponame) ||
+                               '.relation r1, '
+                               || quote_ident(toponame) ||
+                               '.relation r2, '
+                               || quote_ident(toponame) ||
+                               '.edge_data e, '
+                               || quote_ident(toponame) ||
+                               '.node n '
+                               || 'WHERE r1.layer_id = ' || tg1.layer_id
+                               || ' AND r2.layer_id = ' || tg2.layer_id
+                               || ' AND r1.topogeo_id = ' || tg1.id
+                               || ' AND r2.topogeo_id = ' || tg2.id
+                               || ' AND n.node_id = r1.element_id '
+                               || ' AND ( '
+                               || ' e.left_face = r2.element_id '
+                               || ' OR '
+                               || ' e.right_face = r2.element_id '
+                               || ' ) '
+                               || ' AND ( '
+                               || ' e.start_node = r1.element_id '
+                               || ' OR '
+                               || ' e.end_node = r1.element_id '
+                               || ' ) '
+                               || ' LIMIT 1';
+                       --RAISE NOTICE '%', query;
+                       FOR rec IN EXECUTE query
+                       LOOP
+                               --RAISE NOTICE 'Node % on edge % bound', rec.nid, rec.eid;
+                               RETURN TRUE; -- one node is start or end
+                                            -- of a face edge
+                       END LOOP;
+
+                       RETURN FALSE; -- no intersection
+       --
+       ---------------------------------------------------------
+
+               ELSIF tg2.type = 4 THEN -- point/collection
+                       RAISE EXCEPTION 'Intersection point/collection not implemented yet';
+
+               ELSE
+                       RAISE EXCEPTION 'Invalid TopoGeometry type', tg2.type;
+               END IF;
+
+       ELSIF tg1.type = 2 THEN -- [multi]line
+               IF tg2.type = 2 THEN -- line/line
+       ---------------------------------------------------------
+       -- 
+       --  A [multi]line intersects a [multi]line if they share
+       --  any Node. 
+       --
+       --
+       --
+                       query =
+                               'SELECT e1.start_node FROM '
+                               || quote_ident(toponame) ||
+                               '.relation r1, '
+                               || quote_ident(toponame) ||
+                               '.relation r2, '
+                               || quote_ident(toponame) ||
+                               '.edge_data e1, '
+                               || quote_ident(toponame) ||
+                               '.edge_data e2 '
+                               || 'WHERE r1.layer_id = ' || tg1.layer_id
+                               || ' AND r2.layer_id = ' || tg2.layer_id
+                               || ' AND r1.topogeo_id = ' || tg1.id
+                               || ' AND r2.topogeo_id = ' || tg2.id
+                               || ' AND abs(r1.element_id) = e1.edge_id '
+                               || ' AND abs(r2.element_id) = e2.edge_id '
+                               || ' AND ( '
+                                       || ' e1.start_node = e2.start_node '
+                                       || ' OR '
+                                       || ' e1.start_node = e2.end_node '
+                                       || ' OR '
+                                       || ' e1.end_node = e2.start_node '
+                                       || ' OR '
+                                       || ' e1.end_node = e2.end_node '
+                               || ' )'
+                               || ' LIMIT 1';
+                       --RAISE NOTICE '%', query;
+                       FOR rec IN EXECUTE query
+                       LOOP
+                               RETURN TRUE; -- they share an element
+                       END LOOP;
+                       RETURN FALSE; -- no elements shared
+       --
+       ---------------------------------------------------------
+
+               ELSIF tg2.type = 3 THEN -- line/polygon
+       ---------------------------------------------------------
+       -- 
+       -- A [multi]line intersects a [multi]polygon if they share
+       -- any Node (touch-only case), or if any line edge has any
+       -- polygon face on the left or right (full-containment case
+       -- + edge crossing case).
+       --
+       --
+                       -- E1 are line edges, E2 are polygon edges
+                       -- R1 are line relations.
+                       -- R2 are polygon relations.
+                       -- R2.element_id are FACE ids
+                       query =
+                               'SELECT e1.edge_id'
+                               || ' FROM '
+                               || quote_ident(toponame) ||
+                               '.relation r1, '
+                               || quote_ident(toponame) ||
+                               '.relation r2, '
+                               || quote_ident(toponame) ||
+                               '.edge_data e1, '
+                               || quote_ident(toponame) ||
+                               '.edge_data e2 '
+                               || 'WHERE r1.layer_id = ' || tg1.layer_id
+                               || ' AND r2.layer_id = ' || tg2.layer_id
+                               || ' AND r1.topogeo_id = ' || tg1.id
+                               || ' AND r2.topogeo_id = ' || tg2.id
+
+                               -- E1 are line edges
+                               || ' AND e1.edge_id = abs(r1.element_id) '
+
+                               -- E2 are face edges
+                               || ' AND ( e2.left_face = r2.element_id '
+                               || '   OR e2.right_face = r2.element_id ) '
+
+                               || ' AND ( '
+
+                               -- Check if E1 have left-or-right face 
+                               -- being part of R2.element_id
+                               || ' e1.left_face = r2.element_id '
+                               || ' OR '
+                               || ' e1.right_face = r2.element_id '
+
+                               -- Check if E1 share start-or-end node
+                               -- with any E2.
+                               || ' OR '
+                               || ' e1.start_node = e2.start_node '
+                               || ' OR '
+                               || ' e1.start_node = e2.end_node '
+                               || ' OR '
+                               || ' e1.end_node = e2.start_node '
+                               || ' OR '
+                               || ' e1.end_node = e2.end_node '
+
+                               || ' ) '
+
+                               || ' LIMIT 1';
+                       --RAISE NOTICE '%', query;
+                       FOR rec IN EXECUTE query
+                       LOOP
+                               RETURN TRUE; -- either common node
+                                            -- or edge-in-face
+                       END LOOP;
+
+                       RETURN FALSE; -- no intersection
+       --
+       ---------------------------------------------------------
+
+               ELSIF tg2.type = 4 THEN -- line/collection
+                       RAISE EXCEPTION 'Intersection line/collection not implemented yet', tg1.type, tg2.type;
+
+               ELSE
+                       RAISE EXCEPTION 'Invalid TopoGeometry type', tg2.type;
+               END IF;
+
+
+       ELSIF tg1.type = 3 THEN -- [multi]polygon
+
+               IF tg2.type = 3 THEN -- polygon/polygon
+       ---------------------------------------------------------
+       -- 
+       -- A [multi]polygon intersects a [multi]polygon if they share
+       -- any Node (touch-only case), or if any face edge has any of the
+       -- other polygon face on the left or right (full-containment case
+       -- + edge crossing case).
+       --
+       --
+                       -- E1 are poly1 edges.
+                       -- E2 are poly2 edges
+                       -- R1 are poly1 relations.
+                       -- R2 are poly2 relations.
+                       -- R1.element_id are poly1 FACE ids
+                       -- R2.element_id are poly2 FACE ids
+                       query =
+                               'SELECT e1.edge_id'
+                               || ' FROM '
+                               || quote_ident(toponame) ||
+                               '.relation r1, '
+                               || quote_ident(toponame) ||
+                               '.relation r2, '
+                               || quote_ident(toponame) ||
+                               '.edge_data e1, '
+                               || quote_ident(toponame) ||
+                               '.edge_data e2 '
+                               || 'WHERE r1.layer_id = ' || tg1.layer_id
+                               || ' AND r2.layer_id = ' || tg2.layer_id
+                               || ' AND r1.topogeo_id = ' || tg1.id
+                               || ' AND r2.topogeo_id = ' || tg2.id
+
+                               -- E1 are poly1 edges
+                               || ' AND ( e1.left_face = r1.element_id '
+                               || '   OR e1.right_face = r1.element_id ) '
+
+                               -- E2 are poly2 edges
+                               || ' AND ( e2.left_face = r2.element_id '
+                               || '   OR e2.right_face = r2.element_id ) '
+
+                               || ' AND ( '
+
+                               -- Check if any edge from a polygon face
+                               -- has any of the other polygon face
+                               -- on the left or right 
+                               || ' e1.left_face = r2.element_id '
+                               || ' OR '
+                               || ' e1.right_face = r2.element_id '
+                               || ' OR '
+                               || ' e2.left_face = r1.element_id '
+                               || ' OR '
+                               || ' e2.right_face = r1.element_id '
+
+                               -- Check if E1 share start-or-end node
+                               -- with any E2.
+                               || ' OR '
+                               || ' e1.start_node = e2.start_node '
+                               || ' OR '
+                               || ' e1.start_node = e2.end_node '
+                               || ' OR '
+                               || ' e1.end_node = e2.start_node '
+                               || ' OR '
+                               || ' e1.end_node = e2.end_node '
+
+                               || ' ) '
+
+                               || ' LIMIT 1';
+                       --RAISE NOTICE '%', query;
+                       FOR rec IN EXECUTE query
+                       LOOP
+                               RETURN TRUE; -- either common node
+                                            -- or edge-in-face
+                       END LOOP;
+
+                       RETURN FALSE; -- no intersection
+       --
+       ---------------------------------------------------------
+
+               ELSIF tg2.type = 4 THEN -- polygon/collection
+                       RAISE EXCEPTION 'Intersection poly/collection not implemented yet', tg1.type, tg2.type;
+
+               ELSE
+                       RAISE EXCEPTION 'Invalid TopoGeometry type', tg2.type;
+               END IF;
+
+       ELSIF tg1.type = 4 THEN -- collection
+               IF tg2.type = 4 THEN -- collection/collection
+                       RAISE EXCEPTION 'Intersection collection/collection not implemented yet', tg1.type, tg2.type;
+               ELSE
+                       RAISE EXCEPTION 'Invalid TopoGeometry type', tg2.type;
+               END IF;
+
+       ELSE
+               RAISE EXCEPTION 'Invalid TopoGeometry type %', tg1.type;
+       END IF;
+END
+$$
+LANGUAGE 'plpgsql' VOLATILE STRICT;
+--} intersects(TopoGeometry, TopoGeometry)
+
+--{
+--  equals(TopoGeometry, TopoGeometry)
+--
+CREATE OR REPLACE FUNCTION topology.equals(topology.TopoGeometry, topology.TopoGeometry)
+       RETURNS bool
+AS
+$$
+DECLARE
+       tg1 alias for $1;
+       tg2 alias for $2;
+       rec RECORD;
+       toponame varchar;
+       query text;
+BEGIN
+
+       IF tg1.topology_id != tg2.topology_id THEN
+               RAISE EXCEPTION 'Cannot compare TopoGeometries from different topologies';
+       END IF;
+
+       -- Not the same type, not equal
+       IF tg1.type != tg2.type THEN
+               RETURN FALSE;
+       END IF;
+
+       -- Geometry collection are not currently supported
+       IF tg2.type = 4 THEN
+               RAISE EXCEPTION 'GeometryCollection are not supported by equals()';
+       END IF;
+
+        -- Get topology name
+        SELECT name FROM topology.topology into toponame
+                WHERE id = tg1.topology_id;
+
+       -- Two geometries are equal if they are composed by 
+       -- the same TopoElements
+       FOR rec IN EXECUTE 'SELECT * FROM '
+               || ' topology.GetTopoGeomElements('
+               || quote_literal(toponame) || ', '
+               || tg1.layer_id || ',' || tg1.id || ') '
+               || ' EXCEPT SELECT * FROM '
+               || ' topology.GetTopogeomElements('
+               || quote_literal(toponame) || ', '
+               || tg2.layer_id || ',' || tg2.id || ');'
+       LOOP
+               RETURN FALSE;
+       END LOOP;
+
+       FOR rec IN EXECUTE 'SELECT * FROM '
+               || ' topology.GetTopoGeomElements('
+               || quote_literal(toponame) || ', '
+               || tg2.layer_id || ',' || tg2.id || ')'
+               || ' EXCEPT SELECT * FROM '
+               || ' topology.GetTopogeomElements('
+               || quote_literal(toponame) || ', '
+               || tg1.layer_id || ',' || tg1.id || '); '
+       LOOP
+               RETURN FALSE;
+       END LOOP;
+       RETURN TRUE;
+END
+$$
+LANGUAGE 'plpgsql' VOLATILE STRICT;
+--} equals(TopoGeometry, TopoGeometry)
+
index 9f1052b27a8e5cf12eeac72a8b8000eaa985a1ab..663ec2bed8f74535702de5650fd827a74ecf7c54 100644 (file)
@@ -1933,509 +1933,8 @@ LANGUAGE 'plpgsql' VOLATILE STRICT;
 #include "sql/manage/TopologySummary.sql"
 #include "sql/manage/CopyTopology.sql"
 
---={ ----------------------------------------------------------------
---  POSTGIS-SPECIFIC topology predicates
---
---  This part contains function NOT in the SQL/MM specification
---
----------------------------------------------------------------------
-
---{
--- Intersects(TopoGeometry, TopoGeometry)
---
-CREATE OR REPLACE FUNCTION topology.intersects(topology.TopoGeometry, topology.TopoGeometry)
-       RETURNS bool
-AS
-$$
-DECLARE
-       tg1 alias for $1;
-       tg2 alias for $2;
-       tgbuf topology.TopoGeometry;
-       rec RECORD;
-       toponame varchar;
-       query text;
-BEGIN
-       IF tg1.topology_id != tg2.topology_id THEN
-               RAISE EXCEPTION 'Cannot compute intersection between TopoGeometries from different topologies';
-       END IF;
-
-       -- Order TopoGeometries so that tg1 has less-or-same
-       -- dimensionality of tg1 (point,line,polygon,collection)
-       IF tg1.type > tg2.type THEN
-               tgbuf := tg2;
-               tg2 := tg1;
-               tg1 := tgbuf;
-       END IF;
-
-       --RAISE NOTICE 'tg1.id:% tg2.id:%', tg1.id, tg2.id;
-       -- Geometry collection are not currently supported
-       IF tg2.type = 4 THEN
-               RAISE EXCEPTION 'GeometryCollection are not supported by intersects()';
-       END IF;
-
-        -- Get topology name
-        SELECT name FROM topology.topology into toponame
-                WHERE id = tg1.topology_id;
-
-       -- Hierarchical TopoGeometries are not currently supported
-       query = 'SELECT level FROM topology.layer'
-               || ' WHERE '
-               || ' topology_id = ' || tg1.topology_id
-               || ' AND '
-               || '( layer_id = ' || tg1.layer_id
-               || ' OR layer_id = ' || tg2.layer_id
-               || ' ) '
-               || ' AND level > 0 ';
-
-       --RAISE NOTICE '%', query;
-
-       FOR rec IN EXECUTE query
-       LOOP
-               RAISE EXCEPTION 'Hierarchical TopoGeometries are not currently supported by intersects()';
-       END LOOP;
-
-       IF tg1.type = 1 THEN -- [multi]point
-
-
-               IF tg2.type = 1 THEN -- point/point
-       ---------------------------------------------------------
-       -- 
-       --  Two [multi]point features intersect if they share
-       --  any Node 
-       --
-       --
-       --
-                       query =
-                               'SELECT a.topogeo_id FROM '
-                               || quote_ident(toponame) ||
-                               '.relation a, '
-                               || quote_ident(toponame) ||
-                               '.relation b '
-                               || 'WHERE a.layer_id = ' || tg1.layer_id
-                               || ' AND b.layer_id = ' || tg2.layer_id
-                               || ' AND a.topogeo_id = ' || tg1.id
-                               || ' AND b.topogeo_id = ' || tg2.id
-                               || ' AND a.element_id = b.element_id '
-                               || ' LIMIT 1';
-                       --RAISE NOTICE '%', query;
-                       FOR rec IN EXECUTE query
-                       LOOP
-                               RETURN TRUE; -- they share an element
-                       END LOOP;
-                       RETURN FALSE; -- no elements shared
-       --
-       ---------------------------------------------------------
-                       
-
-               ELSIF tg2.type = 2 THEN -- point/line
-       ---------------------------------------------------------
-       -- 
-       --  A [multi]point intersects a [multi]line if they share
-       --  any Node. 
-       --
-       --
-       --
-                       query =
-                               'SELECT a.topogeo_id FROM '
-                               || quote_ident(toponame) ||
-                               '.relation a, '
-                               || quote_ident(toponame) ||
-                               '.relation b, '
-                               || quote_ident(toponame) ||
-                               '.edge_data e '
-                               || 'WHERE a.layer_id = ' || tg1.layer_id
-                               || ' AND b.layer_id = ' || tg2.layer_id
-                               || ' AND a.topogeo_id = ' || tg1.id
-                               || ' AND b.topogeo_id = ' || tg2.id
-                               || ' AND abs(b.element_id) = e.edge_id '
-                               || ' AND ( '
-                                       || ' e.start_node = a.element_id '
-                                       || ' OR '
-                                       || ' e.end_node = a.element_id '
-                               || ' )'
-                               || ' LIMIT 1';
-                       --RAISE NOTICE '%', query;
-                       FOR rec IN EXECUTE query
-                       LOOP
-                               RETURN TRUE; -- they share an element
-                       END LOOP;
-                       RETURN FALSE; -- no elements shared
-       --
-       ---------------------------------------------------------
-
-               ELSIF tg2.type = 3 THEN -- point/polygon
-       ---------------------------------------------------------
-       -- 
-       --  A [multi]point intersects a [multi]polygon if any
-       --  Node of the point is contained in any face of the
-       --  polygon OR ( is end_node or start_node of any edge
-       --  of any polygon face ).
-       --
-       --  We assume the Node-in-Face check is faster becasue
-       --  there will be less Faces then Edges in any polygon.
-       --
-       --
-       --
-       --
-                       -- Check if any node is contained in a face
-                       query =
-                               'SELECT n.node_id as id FROM '
-                               || quote_ident(toponame) ||
-                               '.relation r1, '
-                               || quote_ident(toponame) ||
-                               '.relation r2, '
-                               || quote_ident(toponame) ||
-                               '.node n '
-                               || 'WHERE r1.layer_id = ' || tg1.layer_id
-                               || ' AND r2.layer_id = ' || tg2.layer_id
-                               || ' AND r1.topogeo_id = ' || tg1.id
-                               || ' AND r2.topogeo_id = ' || tg2.id
-                               || ' AND n.node_id = r1.element_id '
-                               || ' AND r2.element_id = n.containing_face '
-                               || ' LIMIT 1';
-                       --RAISE NOTICE '%', query;
-                       FOR rec IN EXECUTE query
-                       LOOP
-                               --RAISE NOTICE 'Node % in polygon face', rec.id;
-                               RETURN TRUE; -- one (or more) nodes are
-                                            -- contained in a polygon face
-                       END LOOP;
-
-                       -- Check if any node is start or end of any polygon
-                       -- face edge
-                       query =
-                               'SELECT n.node_id as nid, e.edge_id as eid '
-                               || ' FROM '
-                               || quote_ident(toponame) ||
-                               '.relation r1, '
-                               || quote_ident(toponame) ||
-                               '.relation r2, '
-                               || quote_ident(toponame) ||
-                               '.edge_data e, '
-                               || quote_ident(toponame) ||
-                               '.node n '
-                               || 'WHERE r1.layer_id = ' || tg1.layer_id
-                               || ' AND r2.layer_id = ' || tg2.layer_id
-                               || ' AND r1.topogeo_id = ' || tg1.id
-                               || ' AND r2.topogeo_id = ' || tg2.id
-                               || ' AND n.node_id = r1.element_id '
-                               || ' AND ( '
-                               || ' e.left_face = r2.element_id '
-                               || ' OR '
-                               || ' e.right_face = r2.element_id '
-                               || ' ) '
-                               || ' AND ( '
-                               || ' e.start_node = r1.element_id '
-                               || ' OR '
-                               || ' e.end_node = r1.element_id '
-                               || ' ) '
-                               || ' LIMIT 1';
-                       --RAISE NOTICE '%', query;
-                       FOR rec IN EXECUTE query
-                       LOOP
-                               --RAISE NOTICE 'Node % on edge % bound', rec.nid, rec.eid;
-                               RETURN TRUE; -- one node is start or end
-                                            -- of a face edge
-                       END LOOP;
-
-                       RETURN FALSE; -- no intersection
-       --
-       ---------------------------------------------------------
-
-               ELSIF tg2.type = 4 THEN -- point/collection
-                       RAISE EXCEPTION 'Intersection point/collection not implemented yet';
-
-               ELSE
-                       RAISE EXCEPTION 'Invalid TopoGeometry type', tg2.type;
-               END IF;
-
-       ELSIF tg1.type = 2 THEN -- [multi]line
-               IF tg2.type = 2 THEN -- line/line
-       ---------------------------------------------------------
-       -- 
-       --  A [multi]line intersects a [multi]line if they share
-       --  any Node. 
-       --
-       --
-       --
-                       query =
-                               'SELECT e1.start_node FROM '
-                               || quote_ident(toponame) ||
-                               '.relation r1, '
-                               || quote_ident(toponame) ||
-                               '.relation r2, '
-                               || quote_ident(toponame) ||
-                               '.edge_data e1, '
-                               || quote_ident(toponame) ||
-                               '.edge_data e2 '
-                               || 'WHERE r1.layer_id = ' || tg1.layer_id
-                               || ' AND r2.layer_id = ' || tg2.layer_id
-                               || ' AND r1.topogeo_id = ' || tg1.id
-                               || ' AND r2.topogeo_id = ' || tg2.id
-                               || ' AND abs(r1.element_id) = e1.edge_id '
-                               || ' AND abs(r2.element_id) = e2.edge_id '
-                               || ' AND ( '
-                                       || ' e1.start_node = e2.start_node '
-                                       || ' OR '
-                                       || ' e1.start_node = e2.end_node '
-                                       || ' OR '
-                                       || ' e1.end_node = e2.start_node '
-                                       || ' OR '
-                                       || ' e1.end_node = e2.end_node '
-                               || ' )'
-                               || ' LIMIT 1';
-                       --RAISE NOTICE '%', query;
-                       FOR rec IN EXECUTE query
-                       LOOP
-                               RETURN TRUE; -- they share an element
-                       END LOOP;
-                       RETURN FALSE; -- no elements shared
-       --
-       ---------------------------------------------------------
-
-               ELSIF tg2.type = 3 THEN -- line/polygon
-       ---------------------------------------------------------
-       -- 
-       -- A [multi]line intersects a [multi]polygon if they share
-       -- any Node (touch-only case), or if any line edge has any
-       -- polygon face on the left or right (full-containment case
-       -- + edge crossing case).
-       --
-       --
-                       -- E1 are line edges, E2 are polygon edges
-                       -- R1 are line relations.
-                       -- R2 are polygon relations.
-                       -- R2.element_id are FACE ids
-                       query =
-                               'SELECT e1.edge_id'
-                               || ' FROM '
-                               || quote_ident(toponame) ||
-                               '.relation r1, '
-                               || quote_ident(toponame) ||
-                               '.relation r2, '
-                               || quote_ident(toponame) ||
-                               '.edge_data e1, '
-                               || quote_ident(toponame) ||
-                               '.edge_data e2 '
-                               || 'WHERE r1.layer_id = ' || tg1.layer_id
-                               || ' AND r2.layer_id = ' || tg2.layer_id
-                               || ' AND r1.topogeo_id = ' || tg1.id
-                               || ' AND r2.topogeo_id = ' || tg2.id
-
-                               -- E1 are line edges
-                               || ' AND e1.edge_id = abs(r1.element_id) '
-
-                               -- E2 are face edges
-                               || ' AND ( e2.left_face = r2.element_id '
-                               || '   OR e2.right_face = r2.element_id ) '
-
-                               || ' AND ( '
-
-                               -- Check if E1 have left-or-right face 
-                               -- being part of R2.element_id
-                               || ' e1.left_face = r2.element_id '
-                               || ' OR '
-                               || ' e1.right_face = r2.element_id '
-
-                               -- Check if E1 share start-or-end node
-                               -- with any E2.
-                               || ' OR '
-                               || ' e1.start_node = e2.start_node '
-                               || ' OR '
-                               || ' e1.start_node = e2.end_node '
-                               || ' OR '
-                               || ' e1.end_node = e2.start_node '
-                               || ' OR '
-                               || ' e1.end_node = e2.end_node '
-
-                               || ' ) '
-
-                               || ' LIMIT 1';
-                       --RAISE NOTICE '%', query;
-                       FOR rec IN EXECUTE query
-                       LOOP
-                               RETURN TRUE; -- either common node
-                                            -- or edge-in-face
-                       END LOOP;
-
-                       RETURN FALSE; -- no intersection
-       --
-       ---------------------------------------------------------
-
-               ELSIF tg2.type = 4 THEN -- line/collection
-                       RAISE EXCEPTION 'Intersection line/collection not implemented yet', tg1.type, tg2.type;
-
-               ELSE
-                       RAISE EXCEPTION 'Invalid TopoGeometry type', tg2.type;
-               END IF;
-
-
-       ELSIF tg1.type = 3 THEN -- [multi]polygon
-
-               IF tg2.type = 3 THEN -- polygon/polygon
-       ---------------------------------------------------------
-       -- 
-       -- A [multi]polygon intersects a [multi]polygon if they share
-       -- any Node (touch-only case), or if any face edge has any of the
-       -- other polygon face on the left or right (full-containment case
-       -- + edge crossing case).
-       --
-       --
-                       -- E1 are poly1 edges.
-                       -- E2 are poly2 edges
-                       -- R1 are poly1 relations.
-                       -- R2 are poly2 relations.
-                       -- R1.element_id are poly1 FACE ids
-                       -- R2.element_id are poly2 FACE ids
-                       query =
-                               'SELECT e1.edge_id'
-                               || ' FROM '
-                               || quote_ident(toponame) ||
-                               '.relation r1, '
-                               || quote_ident(toponame) ||
-                               '.relation r2, '
-                               || quote_ident(toponame) ||
-                               '.edge_data e1, '
-                               || quote_ident(toponame) ||
-                               '.edge_data e2 '
-                               || 'WHERE r1.layer_id = ' || tg1.layer_id
-                               || ' AND r2.layer_id = ' || tg2.layer_id
-                               || ' AND r1.topogeo_id = ' || tg1.id
-                               || ' AND r2.topogeo_id = ' || tg2.id
-
-                               -- E1 are poly1 edges
-                               || ' AND ( e1.left_face = r1.element_id '
-                               || '   OR e1.right_face = r1.element_id ) '
-
-                               -- E2 are poly2 edges
-                               || ' AND ( e2.left_face = r2.element_id '
-                               || '   OR e2.right_face = r2.element_id ) '
-
-                               || ' AND ( '
-
-                               -- Check if any edge from a polygon face
-                               -- has any of the other polygon face
-                               -- on the left or right 
-                               || ' e1.left_face = r2.element_id '
-                               || ' OR '
-                               || ' e1.right_face = r2.element_id '
-                               || ' OR '
-                               || ' e2.left_face = r1.element_id '
-                               || ' OR '
-                               || ' e2.right_face = r1.element_id '
-
-                               -- Check if E1 share start-or-end node
-                               -- with any E2.
-                               || ' OR '
-                               || ' e1.start_node = e2.start_node '
-                               || ' OR '
-                               || ' e1.start_node = e2.end_node '
-                               || ' OR '
-                               || ' e1.end_node = e2.start_node '
-                               || ' OR '
-                               || ' e1.end_node = e2.end_node '
-
-                               || ' ) '
-
-                               || ' LIMIT 1';
-                       --RAISE NOTICE '%', query;
-                       FOR rec IN EXECUTE query
-                       LOOP
-                               RETURN TRUE; -- either common node
-                                            -- or edge-in-face
-                       END LOOP;
-
-                       RETURN FALSE; -- no intersection
-       --
-       ---------------------------------------------------------
-
-               ELSIF tg2.type = 4 THEN -- polygon/collection
-                       RAISE EXCEPTION 'Intersection poly/collection not implemented yet', tg1.type, tg2.type;
-
-               ELSE
-                       RAISE EXCEPTION 'Invalid TopoGeometry type', tg2.type;
-               END IF;
-
-       ELSIF tg1.type = 4 THEN -- collection
-               IF tg2.type = 4 THEN -- collection/collection
-                       RAISE EXCEPTION 'Intersection collection/collection not implemented yet', tg1.type, tg2.type;
-               ELSE
-                       RAISE EXCEPTION 'Invalid TopoGeometry type', tg2.type;
-               END IF;
-
-       ELSE
-               RAISE EXCEPTION 'Invalid TopoGeometry type %', tg1.type;
-       END IF;
-END
-$$
-LANGUAGE 'plpgsql' VOLATILE STRICT;
---} intersects(TopoGeometry, TopoGeometry)
-
---{
---  equals(TopoGeometry, TopoGeometry)
---
-CREATE OR REPLACE FUNCTION topology.equals(topology.TopoGeometry, topology.TopoGeometry)
-       RETURNS bool
-AS
-$$
-DECLARE
-       tg1 alias for $1;
-       tg2 alias for $2;
-       rec RECORD;
-       toponame varchar;
-       query text;
-BEGIN
-
-       IF tg1.topology_id != tg2.topology_id THEN
-               RAISE EXCEPTION 'Cannot compare TopoGeometries from different topologies';
-       END IF;
-
-       -- Not the same type, not equal
-       IF tg1.type != tg2.type THEN
-               RETURN FALSE;
-       END IF;
-
-       -- Geometry collection are not currently supported
-       IF tg2.type = 4 THEN
-               RAISE EXCEPTION 'GeometryCollection are not supported by equals()';
-       END IF;
-
-        -- Get topology name
-        SELECT name FROM topology.topology into toponame
-                WHERE id = tg1.topology_id;
-
-       -- Two geometries are equal if they are composed by 
-       -- the same TopoElements
-       FOR rec IN EXECUTE 'SELECT * FROM '
-               || ' topology.GetTopoGeomElements('
-               || quote_literal(toponame) || ', '
-               || tg1.layer_id || ',' || tg1.id || ') '
-               || ' EXCEPT SELECT * FROM '
-               || ' topology.GetTopogeomElements('
-               || quote_literal(toponame) || ', '
-               || tg2.layer_id || ',' || tg2.id || ');'
-       LOOP
-               RETURN FALSE;
-       END LOOP;
-
-       FOR rec IN EXECUTE 'SELECT * FROM '
-               || ' topology.GetTopoGeomElements('
-               || quote_literal(toponame) || ', '
-               || tg2.layer_id || ',' || tg2.id || ')'
-               || ' EXCEPT SELECT * FROM '
-               || ' topology.GetTopogeomElements('
-               || quote_literal(toponame) || ', '
-               || tg1.layer_id || ',' || tg1.id || '); '
-       LOOP
-               RETURN FALSE;
-       END LOOP;
-       RETURN TRUE;
-END
-$$
-LANGUAGE 'plpgsql' VOLATILE STRICT;
---} equals(TopoGeometry, TopoGeometry)
-
---=} POSTGIS-SPECIFIC topology predicates
+-- Spatial predicates
+#include "sql/predicates.sql"
 
 --  Querying
 #include "sql/query/getnodebypoint.sql"