From 581c4ed3929db95d1c9af54751992d7684259dbe Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Thu, 29 Dec 2011 07:04:39 +0000 Subject: [PATCH] Tabs to spaces, a few TODO items... git-svn-id: http://svn.osgeo.org/postgis/trunk@8607 b70326c6-7e19-0410-871a-916f4a2858ee --- topology/sql/predicates.sql | 917 ++++++++++++++++++------------------ 1 file changed, 458 insertions(+), 459 deletions(-) diff --git a/topology/sql/predicates.sql b/topology/sql/predicates.sql index 1dd5caefb..1750b82e4 100644 --- a/topology/sql/predicates.sql +++ b/topology/sql/predicates.sql @@ -21,431 +21,431 @@ -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --{ --- Intersects(TopoGeometry, TopoGeometry) +-- intersects(TopoGeometry, TopoGeometry) -- -CREATE OR REPLACE FUNCTION topology.intersects(topology.TopoGeometry, topology.TopoGeometry) - RETURNS bool +CREATE OR REPLACE FUNCTION topology.intersects(tg1 topology.TopoGeometry, tg2 topology.TopoGeometry) + RETURNS bool AS $$ DECLARE - tg1 alias for $1; - tg2 alias for $2; - tgbuf topology.TopoGeometry; - rec RECORD; - toponame varchar; - query text; + 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; + IF tg1.topology_id != tg2.topology_id THEN + -- TODO: revert to ::geometry instead ? + 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; + -- 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 + -- TODO: revert to ::geometry instead ? + 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; @@ -454,62 +454,61 @@ LANGUAGE 'plpgsql' VOLATILE STRICT; --{ -- equals(TopoGeometry, TopoGeometry) -- -CREATE OR REPLACE FUNCTION topology.equals(topology.TopoGeometry, topology.TopoGeometry) - RETURNS bool +CREATE OR REPLACE FUNCTION topology.equals(tg1 topology.TopoGeometry, tg2 topology.TopoGeometry) + RETURNS bool AS $$ DECLARE - tg1 alias for $1; - tg2 alias for $2; - rec RECORD; - toponame varchar; - query text; + 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; + IF tg1.topology_id != tg2.topology_id THEN + -- TODO: revert to ::geometry instead ? + 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; + -- 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; + -- 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; + -- 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; -- 2.40.0