1-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2--
3-- PostGIS - Spatial Types for PostgreSQL
4-- http://postgis.net
5--
6-- Copyright (C) 2011 2012 Sandro Santilli <strk@kbt.io>
7--
8-- This is free software; you can redistribute and/or modify it under
9-- the terms of the GNU General Public Licence. See the COPYING file.
10--
11-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
12--
13-- Developed by Sandro Santilli <strk@kbt.io>
14-- for Faunalia (http://www.faunalia.it) with funding from
15-- Regione Toscana - Sistema Informativo per la Gestione del Territorio
16-- e dell' Ambiente [RT-SIGTA].
17-- For the project: "Sviluppo strumenti software per il trattamento di dati
18-- geografici basati su QuantumGIS e Postgis (CIG 0494241492)"
19--
20-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
21
22--{
23--
24-- Return a list of edges (sequence, id) resulting by starting from the
25-- given edge and following the leftmost turn at each encountered node.
26--
27-- Edge ids are signed, they are negative if traversed backward.
28-- Sequence numbers start with 1.
29--
30-- Use a negative starting_edge to follow its rigth face rather than
31-- left face (to start traversing it in reverse).
32--
33-- Optionally pass a limit on the number of edges to traverse. This is a
34-- safety measure against not-properly linked topologies, where you may
35-- end up looping forever (single edge loops edge are detected but longer
36-- ones are not). Default is no limit (good luck!)
37--
38-- GetRingEdges(atopology, anedge, [maxedges])
39--
40CREATE OR REPLACE FUNCTION topology.GetRingEdges(atopology varchar, anedge int, maxedges int DEFAULT null)
41	RETURNS SETOF topology.GetFaceEdges_ReturnType
42AS
43$$
44DECLARE
45  rec RECORD;
46  retrec topology.GetFaceEdges_ReturnType;
47  n int;
48  sql text;
49BEGIN
50  sql := 'WITH RECURSIVE edgering AS ( SELECT '
51    || anedge
52    || ' as signed_edge_id, edge_id, next_left_edge, next_right_edge FROM '
53    || quote_ident(atopology)
54    || '.edge_data WHERE edge_id = '
55    || abs(anedge)
56    || ' UNION '
57    || ' SELECT CASE WHEN p.signed_edge_id < 0 THEN p.next_right_edge '
58    || ' ELSE p.next_left_edge END, e.edge_id, e.next_left_edge, e.next_right_edge '
59    || ' FROM ' || quote_ident(atopology)
60    || '.edge_data e, edgering p WHERE e.edge_id = CASE WHEN p.signed_edge_id < 0 '
61    || 'THEN abs(p.next_right_edge) ELSE abs(p.next_left_edge) END ) SELECT * FROM edgering';
62
63  n := 1;
64  FOR rec IN EXECUTE sql
65  LOOP
66    retrec.sequence := n;
67    retrec.edge := rec.signed_edge_id;
68    RETURN NEXT retrec;
69
70    n := n + 1;
71
72    IF n > maxedges THEN
73      RAISE EXCEPTION 'Max traversing limit hit: %', maxedges;
74    END IF;
75  END LOOP;
76
77END
78$$
79LANGUAGE 'plpgsql' STABLE;
80--} GetRingEdges
81