merge wm_isolated_bends and wm_bend_attrs

This commit is contained in:
Motiejus Jakštys 2021-05-19 22:57:49 +03:00 committed by Motiejus Jakštys
parent 63bde6c7f5
commit 12b0784840

131
wm.sql
View File

@ -81,8 +81,7 @@ begin
dbgpolygon = null;
if st_npoints(bends[i]) >= 3 then
dbgpolygon = st_makepolygon(
st_addpoint(bends[i],
st_startpoint(bends[i]))
st_addpoint(bends[i], st_startpoint(bends[i]))
);
end if;
insert into wm_debug(stage, name, gen, nbend, way) values(
@ -321,13 +320,11 @@ begin
end $$ language plpgsql;
drop function if exists wm_bend_attrs;
drop function if exists wm_isolated_bends;
drop function if exists wm_elimination;
drop function if exists wm_exaggeration;
drop function if exists wm_st_intersects_neighbors;
drop type if exists wm_t_attrs;
create type wm_t_attrs as (
area real,
adjsize real,
baselinelength real,
curvature real,
@ -337,37 +334,65 @@ create function wm_bend_attrs(
bends geometry[],
dbgname text default null,
dbggen integer default null
) returns setof wm_t_attrs as $$
) returns wm_t_attrs[] as $$
declare
cmp float;
i int4;
polygon geometry;
isolation_threshold constant real default 0.5;
attrs wm_t_attrs[];
attr wm_t_attrs;
bend geometry;
res wm_t_attrs;
i int4;
needs_curvature real;
skip_next boolean;
dbglastid integer;
begin
for i in 1..array_length(bends, 1) loop
bend = bends[i];
res = null;
res.adjsize = 0;
res.baselinelength = st_distance(st_startpoint(bend), st_endpoint(bend));
res.curvature = wm_inflection_angle(bend) / st_length(bend);
res.isolated = false;
attr.adjsize = 0;
attr.baselinelength = st_distance(st_startpoint(bend), st_endpoint(bend));
attr.curvature = wm_inflection_angle(bend) / st_length(bend);
attr.isolated = false;
if st_numpoints(bend) >= 3 then
res.adjsize = wm_adjsize(bend);
attr.adjsize = wm_adjsize(bend);
end if;
attrs[i] = attr;
end loop;
for i in 1..array_length(attrs, 1) loop
if dbgname is not null then
insert into wm_debug (stage, name, gen, nbend, way, props) values(
'ebendattrs', dbgname, dbggen, i, bend,
jsonb_build_object(
'adjsize', res.adjsize,
'baselinelength', res.baselinelength,
'curvature', res.curvature
'adjsize', attrs[i].adjsize,
'baselinelength', attrs[i].baselinelength,
'curvature', attrs[i].curvature,
'isolated', false
)
);
) returning id into dbglastid;
end if;
-- first and last bends can never be isolated by definition
if skip_next or i = 1 or i = array_length(attrs, 1) then
skip_next = false;
continue;
end if;
needs_curvature = attrs[i].curvature * isolation_threshold;
if attrs[i-1].curvature < needs_curvature and
attrs[i+1].curvature < needs_curvature then
attr = attrs[i];
attr.isolated = true;
attrs[i] = attr;
skip_next = true;
if dbgname is not null then
update wm_debug
set props=props || jsonb_build_object('isolated', true)
where id=dbglastid;
end if;
end if;
return next res;
end loop;
return attrs;
end $$ language plpgsql;
-- sm_st_split a line by a point in a more robust way than st_split.
@ -574,7 +599,6 @@ declare
leftsize float;
rightsize float;
i int4;
bend geometry;
begin
mutated = false;
@ -624,55 +648,6 @@ begin
end if;
end $$ language plpgsql;
create function wm_isolated_bends(
INOUT attrs wm_t_attrs[],
bends geometry[],
dbgname text default null,
dbggen integer default null
) as $$
declare
-- if neighbor's curvatures are within this fraction of the current bend
isolation_threshold constant real default 0.5;
this real;
skip_next bool;
res wm_t_attrs;
i int4;
last_id integer;
begin
for i in 1..array_length(attrs, 1) loop
if dbgname is not null then
insert into wm_debug (stage, name, gen, nbend, way, props) values(
'fisolated_bends', dbgname, dbggen, i, bends[i],
jsonb_build_object('isolated', false)
) returning id into last_id;
end if;
-- first and last bends cannot be isolated
if i = 1 or i = array_length(attrs, 1) then
continue;
end if;
res = attrs[i];
if skip_next then
skip_next = false;
else
this = attrs[i].curvature * isolation_threshold;
if attrs[i-1].curvature < this and
attrs[i+1].curvature < this then
res.isolated = true;
attrs[i] = res;
skip_next = true;
if dbgname is not null then
update wm_debug
set props=props || jsonb_build_object('isolated', true)
where id=last_id;
end if;
end if;
end if;
end loop;
end $$ language plpgsql;
drop function if exists ST_SimplifyWM_Estimate;
create function ST_SimplifyWM_Estimate(
geom geometry,
@ -753,8 +728,7 @@ begin
select * from wm_self_crossing(bends, dbgname, gen) into bends, mutated;
if not mutated then
attrs = array((select wm_bend_attrs(bends, dbgname, gen)));
attrs = wm_isolated_bends(attrs, bends, dbgname, gen);
attrs = wm_bend_attrs(bends, dbgname, gen);
select * from wm_exaggeration(
bends, attrs, dhalfcircle, intersect_patience, dbgname, gen
@ -772,16 +746,17 @@ begin
lines[i] = st_linemerge(st_union(bends));
if st_geometrytype(lines[i]) != 'ST_LineString' then
-- For manual debugging, usually when wm_exaggeration returns
-- ST_MultiLineString. Uncomment the code below and `raise notice`.
--insert into wm_manual(name, way)
--select 'non-linestring-' || a.path[1], a.geom
--from st_dump(lines[i]) a
--order by a.path[1];
raise 'Got % (in %) instead of ST_LineString. '
'Does the exaggerated bend intersect with the line? '
'If so, try increasing intersect_patience.',
st_geometrytype(lines[i]), dbgname;
-- For manual debugging, usually when wm_exaggeration returns
-- ST_MultiLineString. Uncomment the code below and change `raise`
-- to `raise notice` above.
--insert into wm_manual(name, way)
--select 'non-linestring-' || a.path[1], a.geom
--from st_dump(lines[i]) a
--order by a.path[1];
--exit lineloop;
end if;
gen = gen + 1;