wm_elimination does not break existing tests

This commit is contained in:
Motiejus Jakštys 2021-05-19 22:57:49 +03:00 committed by Motiejus Jakštys
parent 675d228b50
commit cf2a4962e6
2 changed files with 99 additions and 36 deletions

View File

@ -53,7 +53,7 @@ insert into wm_figures (name, way) values ('selfcrossing-1-rev',ST_Reverse(ST_Tr
delete from wm_debug where name in (select distinct name from wm_figures); delete from wm_debug where name in (select distinct name from wm_figures);
delete from wm_demo where name in (select distinct name from wm_figures); delete from wm_demo where name in (select distinct name from wm_figures);
insert into wm_demo (name, way) select name, ST_SimplifyWM(way, null, name) from wm_figures; insert into wm_demo (name, way) select name, ST_SimplifyWM(way, 100, name) from wm_figures;
do $$ do $$
declare fig6b1 geometry; declare fig6b1 geometry;

133
wm.sql
View File

@ -6,7 +6,7 @@ drop function if exists wm_detect_bends;
create function wm_detect_bends( create function wm_detect_bends(
line geometry, line geometry,
dbgname text default null, dbgname text default null,
dbgstagenum integer default null, dbggen integer default null,
OUT bends geometry[] OUT bends geometry[]
) as $$ ) as $$
declare declare
@ -79,7 +79,7 @@ begin
insert into wm_debug(stage, name, gen, nbend, way) values( insert into wm_debug(stage, name, gen, nbend, way) values(
'bbends', 'bbends',
dbgname, dbgname,
dbgstagenum, dbggen,
i, i,
bends[i] bends[i]
); );
@ -91,7 +91,7 @@ begin
insert into wm_debug(stage, name, gen, nbend, way) values( insert into wm_debug(stage, name, gen, nbend, way) values(
'bbends-polygon', 'bbends-polygon',
dbgname, dbgname,
dbgstagenum, dbggen,
i, i,
dbgpolygon dbgpolygon
); );
@ -109,10 +109,11 @@ $$ language plpgsql;
-- --
-- The implementation could be significantly optimized to avoid `st_reverse` -- The implementation could be significantly optimized to avoid `st_reverse`
-- and array reversals, trading for complexity in wm_fix_gentle_inflections1. -- and array reversals, trading for complexity in wm_fix_gentle_inflections1.
create or replace function wm_fix_gentle_inflections( drop function if exists wm_fix_gentle_inflections;
create function wm_fix_gentle_inflections(
INOUT bends geometry[], INOUT bends geometry[],
dbgname text default null, dbgname text default null,
dbgstagenum integer default null dbggen integer default null
) as $$ ) as $$
declare declare
len int4; len int4;
@ -136,7 +137,7 @@ begin
insert into wm_debug(stage, name, gen, nbend, way) values( insert into wm_debug(stage, name, gen, nbend, way) values(
'cinflections', 'cinflections',
dbgname, dbgname,
dbgstagenum, dbggen,
i, i,
bends[i] bends[i]
); );
@ -149,7 +150,7 @@ begin
insert into wm_debug(stage, name, gen, nbend, way) values( insert into wm_debug(stage, name, gen, nbend, way) values(
'cinflections-polygon', 'cinflections-polygon',
dbgname, dbgname,
dbgstagenum, dbggen,
i, i,
dbgpolygon dbgpolygon
); );
@ -335,9 +336,9 @@ begin
end end
$$ language plpgsql; $$ language plpgsql;
drop function if exists wm_bend_attrs; drop function if exists wm_bend_attrs;
drop function if exists wm_isolated_bends; drop function if exists wm_isolated_bends;
drop function if exists wm_elimination;
drop type if exists wm_t_bend_attrs; drop type if exists wm_t_bend_attrs;
create type wm_t_bend_attrs as ( create type wm_t_bend_attrs as (
bend geometry, bend geometry,
@ -406,6 +407,72 @@ begin
end; end;
$$ language plpgsql; $$ language plpgsql;
create function wm_elimination(
INOUT bendattrs wm_t_bend_attrs[],
dhalfcircle float,
dbgname text,
dbggen int4,
OUT mutated boolean
) as $$
declare
area_threshold float;
leftsize float;
rightsize float;
i int4;
j int4;
tmpbendattrs wm_t_bend_attrs;
dbgbends geometry[];
begin
area_threshold = radians(180) * ((dhalfcircle/2)^2)/2;
mutated = false;
i = 1;
while i < array_length(bendattrs, 1)-1 loop
i = i + 1;
continue when area_threshold >= bendattrs[i].adjsize;
if i = 2 then
leftsize = bendattrs[i].adjsize + 1;
else
leftsize = bendattrs[i-1].adjsize;
end if;
if i = array_length(bendattrs, 1)-1 then
rightsize = bendattrs[i].adjsize + 1;
else
rightsize = bendattrs[i+1].adjsize;
end if;
continue when leftsize <= bendattrs[i].adjsize;
continue when rightsize <= bendattrs[i].adjsize;
-- Local minimum. Elminate!
mutated = true;
tmpbendattrs.bend = st_makeline(
st_pointn(bendattrs[i].bend, 1),
st_pointn(bendattrs[i].bend, -1)
);
bendattrs[i] = tmpbendattrs;
-- jump over the next bend, because the current bend disappeared,
-- and there is no way the other one can be a "local minima".
i = i + 1;
end loop;
if dbgname is not null then
for j in 1..array_length(bendattrs, 1) loop
dbgbends[j] = bendattrs[j].bend;
end loop;
insert into wm_debug(stage, name, gen, nbend, way) values(
'eelimination',
dbgname,
dbggen,
generate_subscripts(dbgbends, 1),
unnest(dbgbends)
);
end if;
end
$$ language plpgsql;
create function wm_isolated_bends( create function wm_isolated_bends(
INOUT bendattrs wm_t_bend_attrs[], INOUT bendattrs wm_t_bend_attrs[],
dbgname text default null dbgname text default null
@ -484,22 +551,23 @@ $$ language plpgsql;
-- 1998. -- 1998.
-- Input parameters: -- Input parameters:
-- - geom: ST_LineString or ST_MultiLineString: the geometry to be simplified -- - geom: ST_LineString or ST_MultiLineString: the geometry to be simplified
-- - diameter: the diameter of a half-circle, whose area is an approximate -- - dhalfcircle: the diameter of a half-circle, whose area is an approximate
-- threshold for small bend elimination. If bend's area is larger than that, -- threshold for small bend elimination. If bend's area is larger than that,
-- the bend will be left alone. -- the bend will be left alone.
drop function if exists ST_SimplifyWM; drop function if exists ST_SimplifyWM;
create function ST_SimplifyWM( create function ST_SimplifyWM(
geom geometry, geom geometry,
diameter float, dhalfcircle float,
dbgname text default null dbgname text default null
) returns geometry as $$ ) returns geometry as $$
declare declare
stagenum integer; gen integer;
i integer; i integer;
j integer;
line geometry; line geometry;
lines geometry[]; lines geometry[];
bends geometry[]; bends geometry[];
bend_attrs wm_t_bend_attrs[]; bendattrs wm_t_bend_attrs[];
mutated boolean; mutated boolean;
l_type text; l_type text;
begin begin
@ -514,20 +582,20 @@ begin
for i in 1..array_length(lines, 1) loop for i in 1..array_length(lines, 1) loop
mutated = true; mutated = true;
stagenum = 1; gen = 1;
while mutated loop while mutated loop
if dbgname is not null then if dbgname is not null then
insert into wm_debug (stage, name, gen, nbend, way) values( insert into wm_debug (stage, name, gen, nbend, way) values(
'afigures', 'afigures',
dbgname, dbgname,
stagenum, gen,
i, i,
lines[i] lines[i]
); );
end if; end if;
bends = wm_detect_bends(lines[i], dbgname, stagenum); bends = wm_detect_bends(lines[i], dbgname, gen);
bends = wm_fix_gentle_inflections(bends, dbgname, stagenum); bends = wm_fix_gentle_inflections(bends, dbgname, gen);
select * from wm_self_crossing(bends) into bends, mutated; select * from wm_self_crossing(bends) into bends, mutated;
@ -535,7 +603,7 @@ begin
insert into wm_debug(stage, name, gen, nbend, way) values( insert into wm_debug(stage, name, gen, nbend, way) values(
'dcrossings', 'dcrossings',
dbgname, dbgname,
stagenum, gen,
generate_subscripts(bends, 1), generate_subscripts(bends, 1),
unnest(bends) unnest(bends)
); );
@ -543,30 +611,25 @@ begin
if mutated then if mutated then
lines[i] = st_linemerge(st_union(bends)); lines[i] = st_linemerge(st_union(bends));
stagenum = stagenum + 1; gen = gen + 1;
continue; continue;
end if; end if;
--select * from wm_elimination(bends, diameter) into bends, mutated; bendattrs = array((select wm_bend_attrs(bends, dbgname)));
--if dbgname is not null then select * from wm_elimination(
-- insert into wm_debug(stage, name, gen, nbend, way) values( bendattrs, dhalfcircle, dbgname, gen) into bendattrs, mutated;
-- 'eelimination',
-- dbgname,
-- stagenum,
-- generate_subscripts(bends, 1),
-- unnest(bends)
-- );
--end if;
--if mutated then if mutated then
-- lines[i] = st_linemerge(st_union(bends)); for j in 1..array_length(bendattrs, 1) loop
-- stagenum = stagenum + 1; bends[j] = bendattrs[j].bend;
-- continue; end loop;
--end if; lines[i] = st_linemerge(st_union(bends));
gen = gen + 1;
continue;
end if;
bend_attrs = array((select wm_bend_attrs(bends, dbgname))); perform wm_isolated_bends(bendattrs, dbgname);
perform wm_isolated_bends(bend_attrs, dbgname);
end loop; end loop;
end loop; end loop;