docs and inflections
This commit is contained in:
parent
e76efda436
commit
eaedce3976
31
tests.sql
31
tests.sql
@ -16,8 +16,9 @@ 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',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 ('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 ('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(100 14,114 20,133 20,145 15,145 0,136 5,123 7,114 7,111 2)'));
|
insert into figures (name, way) values ('inflection-1',ST_GeomFromText('LINESTRING(110 24,114 20,133 20,145 15,145 0,136 5,123 7,114 7,111 2)'));
|
||||||
|
|
||||||
|
-- `bends` is for manual inspection using, say, qgis
|
||||||
drop table if exists bends;
|
drop table if exists bends;
|
||||||
create table bends (way geometry);
|
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='fig3')));
|
||||||
@ -26,17 +27,27 @@ insert into bends select unnest(detect_bends((select way from figures where name
|
|||||||
|
|
||||||
do $$
|
do $$
|
||||||
declare
|
declare
|
||||||
bends geometry[];
|
vbends geometry[];
|
||||||
begin
|
begin
|
||||||
select detect_bends((select way from figures where name='fig3')) into bends;
|
-- DETECT BENDS
|
||||||
perform assert_equals(5, array_length(bends, 1));
|
select detect_bends((select way from figures where name='fig3')) into vbends;
|
||||||
perform assert_equals('LINESTRING(0 0,12 0,13 4)', st_astext(bends[1]));
|
perform assert_equals(5, array_length(vbends, 1));
|
||||||
perform assert_equals('LINESTRING(12 0,13 4,20 2,20 0)', st_astext(bends[2]));
|
perform assert_equals('LINESTRING(0 0,12 0,13 4)', st_astext(vbends[1]));
|
||||||
perform assert_equals('LINESTRING(20 2,20 0,32 0,33 10)', st_astext(bends[3]));
|
perform assert_equals('LINESTRING(12 0,13 4,20 2,20 0)', st_astext(vbends[2]));
|
||||||
perform assert_equals('LINESTRING(32 0,33 10,38 16,43 15,44 10,44 0)', st_astext(bends[4]));
|
perform assert_equals('LINESTRING(20 2,20 0,32 0,33 10)', st_astext(vbends[3]));
|
||||||
|
perform assert_equals('LINESTRING(32 0,33 10,38 16,43 15,44 10,44 0)', st_astext(vbends[4]));
|
||||||
|
|
||||||
perform assert_equals(4, array_length(detect_bends((select way from figures where name='fig3-1')), 1));
|
perform assert_equals(4, array_length(detect_bends((select way from figures where name='fig3-1')), 1));
|
||||||
|
|
||||||
select detect_bends((select way from figures where name='fig5')) into bends;
|
select detect_bends((select way from figures where name='fig5')) into vbends;
|
||||||
perform assert_equals(3, array_length(bends, 1));
|
perform assert_equals(3, array_length(vbends, 1));
|
||||||
|
|
||||||
|
-- FIX BEND INFLECTIONS
|
||||||
|
select detect_bends((select way from figures where name='inflection-1')) into vbends;
|
||||||
|
|
||||||
|
drop table if exists inflections;
|
||||||
|
create table inflections (way geometry);
|
||||||
|
--insert into inflections select unnest(fix_gentle_inflections(vbends));
|
||||||
|
select fix_gentle_inflections(vbends);
|
||||||
|
|
||||||
end $$ language plpgsql;
|
end $$ language plpgsql;
|
||||||
|
61
wm.sql
61
wm.sql
@ -73,19 +73,21 @@ $$ language plpgsql;
|
|||||||
--
|
--
|
||||||
-- The text does not specify how many vertices can be "adjusted"; it can
|
-- 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
|
-- equally be one or many. This function is adjusting many, as long as the
|
||||||
-- commulative inflection angle is less than pi/6 (30 deg).
|
-- commulative inflection angle small (see variable below).
|
||||||
create or replace function fix_gentle_inflections(INOUT bends geometry[]) as $$
|
create or replace function fix_gentle_inflections(INOUT bends geometry[]) as $$
|
||||||
declare
|
declare
|
||||||
prev_bend geometry;
|
small_angle real;
|
||||||
bend geometry;
|
phead geometry; -- head point of head bend
|
||||||
p geometry;
|
ptail geometry[]; -- 3 head points of tail bend
|
||||||
p1 geometry;
|
i int4; -- bends[i] is the current head
|
||||||
p2 geometry;
|
|
||||||
p3 geometry;
|
|
||||||
begin
|
begin
|
||||||
foreach bend in array bends loop
|
-- the threshold when the angle is still "small", so gentle inflections can
|
||||||
if prev_bend is null then
|
-- be joined
|
||||||
prev_bend = bend;
|
small_angle := radians(30);
|
||||||
|
|
||||||
|
<<bend_loop>>
|
||||||
|
for i in select generate_subscripts(bends, 1) loop
|
||||||
|
if i = 1 then
|
||||||
continue;
|
continue;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
@ -101,31 +103,36 @@ begin
|
|||||||
--
|
--
|
||||||
-- Assume this curve (figure `inflection-1`):
|
-- Assume this curve (figure `inflection-1`):
|
||||||
--
|
--
|
||||||
-- A______B
|
-- \______B
|
||||||
-- ---' `-------. C
|
-- A `-------. C
|
||||||
-- |
|
-- |
|
||||||
-- G___ F |
|
-- G___ F |
|
||||||
-- / `-----.____+ D
|
-- / `-----.____+ D
|
||||||
-- E
|
-- E
|
||||||
--
|
--
|
||||||
-- After processing the curve following the definition of a bend, the bend
|
-- After processing the curve following the definition of a bend, the bend
|
||||||
-- [A-E] would be detected. Assuming inflection point E and F are "small",
|
-- [A-E] would be detected. Assuming inflection point E and F are "small",
|
||||||
-- the bend needs to be extended by two edges to [A,G].
|
-- the bend needs to be extended by two edges to [A,G].
|
||||||
--
|
select geom from st_dumppoints(bends[i]) order by path[1] desc limit 1 into phead;
|
||||||
-- Assuming the direction in this example is clock-wise, the first set of
|
while true loop
|
||||||
-- `p` variables will be: p1=C, p2=B, p3=A.
|
-- copy last 3 points of bends[i-1] (tail) to ptail
|
||||||
for p in (select geom from st_dumppoints(prev_bend) order by path[1] desc) loop
|
select array_agg(geom) from st_dumppoints(bends[i-1]) order by path[1] desc limit 3 into ptail;
|
||||||
p3 = p2;
|
|
||||||
p2 = p1;
|
-- if inflection angle between ptail[1:3] "large", stop processing this bend
|
||||||
p1 = p;
|
if abs(st_angle(ptail[1], ptail[2], ptail[2], ptail[3]) - pi) > small_angle then
|
||||||
if p3 is null then
|
exit bend_loop;
|
||||||
continue;
|
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- (p2, p1) is shared with the current bend.
|
-- distance from last vertex should be larger than second-last vertex
|
||||||
|
if st_distance(phead, ptail[2]) < st_distance(phead, ptail[3]) then
|
||||||
|
exit bend_loop;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- detected a gentle inflection. Move head of the tail to the tail of head
|
||||||
|
bends[i] = st_addpoint(bends[i], ptail[3]);
|
||||||
|
bends[i-1] = st_removepoint(bends[i-1], st_npoints(bends[i-1])-1);
|
||||||
end loop;
|
end loop;
|
||||||
|
|
||||||
prev_bend = bend;
|
|
||||||
end loop;
|
end loop;
|
||||||
end
|
end
|
||||||
$$ language plpgsql;
|
$$ language plpgsql;
|
||||||
|
Loading…
Reference in New Issue
Block a user