commit dd80541453a606305c429e88e4f34f871fbe26d1 (tree)
parent 8094d21ded392f4129f1972cca92988c2dd505a6
Author: Motiejus Jakštys <motiejus@uber.com>
Date: Thu, 6 May 2021 13:39:36 +0300
wip: intersect_patience
Diffstat:
4 files changed, 63 insertions(+), 8 deletions(-)
diff --git a/IV/mj-msc.tex b/IV/mj-msc.tex
@@ -589,7 +589,7 @@ table~\ref{table:scale-halfcirlce-diameter}.
Sometimes, when working with {\WM}, it is useful to convert between
half-circle's diameter $D$ and adjusted size $A_{adj}$. These easily derive
-from circle's area formula $A = 2\pi r^2$. Diameter:
+from circle's area formula $A = 2\pi \frac{D}{2}^2$:
\[
D = 2\sqrt{\frac{2 A_{adj}}{\pi}}
@@ -868,7 +868,7 @@ The smaller the distance $d$, the more similar the bends are.
\subsection{Elimination Operator}
-NOTE: not implemented.
+NOTE: implemented, explain.
\subsection{Combination Operator}
@@ -876,7 +876,7 @@ NOTE: not implemented.
\subsection{Exaggeration Operator}
-NOTE: not implemented.
+NOTE: implemented, explain. Also {\texttt intersection\_tolerance} parameter.
\section{Program Implementation}
diff --git a/IV/test-rivers.sql b/IV/test-rivers.sql
@@ -109,4 +109,4 @@ end $$ language plpgsql;
delete from wm_debug where name in (select distinct name from wm_rivers);
delete from wm_demo where name in (select distinct name from wm_rivers);
-insert into wm_demo (name, way) select name, ST_SimplifyWM(way, 37.5, name) from wm_rivers;
+insert into wm_demo (name, way) select name, ST_SimplifyWM(way, 37.5, null, name) from wm_rivers;
diff --git a/IV/test.sql b/IV/test.sql
@@ -56,8 +56,8 @@ insert into wm_figures (name, way) values ('isolated-2', 'LINESTRING(250 100,246
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);
-insert into wm_demo (name, way) select name, ST_SimplifyWM(way, .1, name) from wm_figures where name not in ('fig8', 'isolated-1');
-insert into wm_demo (name, way) select name, ST_SimplifyWM(way, 14, name) from wm_figures where name in ('fig8', 'isolated-1', 'isolated-2');
+insert into wm_demo (name, way) select name, ST_SimplifyWM(way, .1, null, name) from wm_figures where name not in ('fig8', 'isolated-1');
+insert into wm_demo (name, way) select name, ST_SimplifyWM(way, 14, null, name) from wm_figures where name in ('fig8', 'isolated-1', 'isolated-2');
drop function if exists wm_debug_get;
create function wm_debug_get(
diff --git a/IV/wm.sql b/IV/wm.sql
@@ -481,6 +481,7 @@ $$ language plpgsql;
create function wm_exaggeration(
INOUT bendattrs wm_t_bend_attrs[],
dhalfcircle float,
+ intersect_patience integer,
dbgname text default null,
dbggen integer default null,
OUT mutated boolean
@@ -489,19 +490,56 @@ declare
desired_size constant float default pi()*(dhalfcircle^2)/8;
tmpbendattr wm_t_bend_attrs;
i integer;
+ n integer;
last_id integer;
begin
mutated = false;
+ <<bendloop>>
for i in 1..array_length(bendattrs, 1) loop
if bendattrs[i].isolated and bendattrs[i].adjsize < desired_size then
- mutated = true;
tmpbendattr.bend = wm_exaggerate_bend(
bendattrs[i].bend,
bendattrs[i].adjsize,
desired_size
);
+
+ -- does tmpbendattrs.bend intersect with the previous or next
+ -- intersect_patience bends? If they do, abort exaggeration for this one.
+
bendattrs[i] = tmpbendattr;
+ -- Do close-by bends intersect with this one? Special
+ -- handling first, because 2 vertices need to be removed before checking.
+ n = st_npoints(bendattrs[i-1].bend);
+ if n > 3 then
+ continue when st_overlaps(tmpbendattr.bend,
+ st_removepoint(st_removepoint(bendattrs[i-1].bend, n-1), n-2));
+ end if;
+
+ n = st_npoints(bendattrs[i+1].bend);
+ if n > 3 then
+ continue when st_intersects(tmpbendattr.bend,
+ st_removepoint(st_removepoint(bendattrs[i+1].bend, 0), 0));
+ end if;
+
+ -- now loop over the next intersect_patience
+ for n in -intersect_patience+1..intersect_patience-1 loop
+ continue when n in (-1, 0, 1);
+ continue when i+n < 1;
+ continue when i+n > array_length(bendattrs, 1);
+
+ if st_overlaps(tmpbendattr.bend, bendattrs[i+n].bend) then
+ insert into wm_manual(name, way) values
+ ('intersecter', tmpbendattr.bend),
+ ('intersectee', bendattrs[i+n].bend);
+ raise notice '[%] % intersects with %', dbggen, i, i+n;
+ continue bendloop;
+ end if;
+ end loop;
+
+ -- no intersections within intersect_patience. Mutate bend.
+ mutated = true;
+
-- remove last vertex of the previous bend and
-- first vertex of the next bend, because bends always
-- share a line segment together
@@ -690,6 +728,7 @@ drop function if exists ST_SimplifyWM;
create function ST_SimplifyWM(
geom geometry,
dhalfcircle float,
+ intersect_patience integer default 10,
dbgname text default null
) returns geometry as $$
declare
@@ -703,6 +742,9 @@ declare
mutated boolean;
l_type text;
begin
+ if intersect_patience is null then
+ intersect_patience = 10;
+ end if;
l_type = st_geometrytype(geom);
if l_type = 'ST_LineString' then
lines = array[geom];
@@ -736,7 +778,8 @@ begin
bendattrs = wm_isolated_bends(bendattrs, dbgname, gen);
select * from wm_exaggeration(
- bendattrs, dhalfcircle, dbgname, gen) into bendattrs, mutated;
+ bendattrs, dhalfcircle, intersect_patience, dbgname, gen
+ ) into bendattrs, mutated;
-- TODO: wm_combination
@@ -750,6 +793,18 @@ begin
bends[j] = bendattrs[j].bend;
end loop;
lines[i] = st_linemerge(st_union(bends));
+ if st_geometrytype(lines[i]) != 'ST_LineString' then
+ raise 'Got % instead of ST_LineString. '
+ 'Does the exaggerated bend intersect? '
+ 'If so, try increasing intersect_patience.',
+ st_geometrytype(lines[i]);
+
+ 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;
+ end if;
gen = gen + 1;
continue;
end if;