From 198ea6d0e35c6ceee93a45b810c171fdb77b1003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Wed, 19 May 2021 22:57:45 +0300 Subject: [PATCH] gentle inflection of a bend --- tests.sql | 2 ++ wm.sql | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/tests.sql b/tests.sql index 7c66c87..f8d3931 100644 --- a/tests.sql +++ b/tests.sql @@ -16,11 +16,13 @@ create table figures (name text, way geometry); insert into figures (name, way) values ('fig3',ST_GeomFromText('LINESTRING(0 0,12 0,13 4,20 2,20 0,32 0,33 10,38 16,43 15,44 10,44 0,60 0)')); insert into figures (name, way) values ('fig3-1',ST_GeomFromText('LINESTRING(0 0,12 0,13 4,20 2,20 0,32 0,33 10,38 16,43 15,44 10,44 0)')); insert into figures (name, way) values ('fig5',ST_GeomFromText('LINESTRING(0 39,19 52,27 77,26 104,41 115,49 115,65 103,65 75,53 45,63 15,91 0,91 0)')); +insert into figures (name, way) values ('inflection-1',ST_GeomFromText('LINESTRING(129 45,131 56,130 82,128 99,147 104,149 89,147 68,141 52)')); drop table if exists bends; create table bends (way geometry); insert into bends select unnest(detect_bends((select way from figures where name='fig3'))); insert into bends select unnest(detect_bends((select way from figures where name='fig5'))); +insert into bends select unnest(detect_bends((select way from figures where name='inflection-1'))); do $$ declare diff --git a/wm.sql b/wm.sql index 1bea587..89e93ac 100644 --- a/wm.sql +++ b/wm.sql @@ -70,7 +70,59 @@ $$ language plpgsql; -- fix_gentle_inflections moves bend endpoints following "Gentle Inflection at -- End of a Bend" section. +-- +-- The text does not specify how many vertices can be "adjusted"; it can +-- equally be one or many. This function is adjusting many, as long as the +-- commulative inflection angle is less than pi/6 (30 deg). create or replace function fix_gentle_inflections(INOUT bends geometry[]) as $$ +declare + prev_bend geometry; + bend geometry; + p geometry; + p1 geometry; + p2 geometry; + p3 geometry; begin + foreach bend in array bends loop + if prev_bend is null then + prev_bend = bend; + continue; + end if; + + -- Predicate: two bends will always share an edge. Assuming (A,B,C,D,E,F) + -- is a bend: + -- C________D + -- / \ + -- \________/ \_______/ + -- A B E F + -- + -- Then edges (A,B) and (E,F) are shared with the neighboring bends. + -- + -- + -- Assume this curve: + -- + -- A______B + -- ---' `---.___. E + -- C D | + -- _I | + -- '---.________ | + -- H G'---+ F + -- + -- After processing the curve following the definition of a bend, the bend + -- [A-G] would be detected. Assuming inflection point G and H are "small", + -- the bend would be extended by two edges to [A,I]. + for p in (select geom from st_dumppoints(prev_bend) order by path[1] desc) loop + p3 = p2; + p2 = p1; + p1 = p; + if p3 is null then + continue; + end if; + + -- (p2, p1) is shared with the current bend. + end loop; + + prev_bend = bend; + end loop; end $$ language plpgsql;