more self-crossing and documentation

This commit is contained in:
Motiejus Jakštys 2021-05-19 22:57:45 +03:00 committed by Motiejus Jakštys
parent d66d1ac248
commit 87849132d1
3 changed files with 52 additions and 22 deletions

View File

@ -1,14 +1,22 @@
Definition of a bend: ends of the line should always be bends, otherwise not
Definition of a bend
--------------------
Ends of the line should always be bends, otherwise not
all line vertices are covered by bends (definition elsewhere).
Gentle inflection at the end of the bend: the article does not specify how many
vertices should be included when calculating the end-of-bend inflection. We
chose the iterative approach -- as long as the angle is "right" and the
distance is (greedily) decreasing, keep going.
Gentle inflection at the end of the bend
----------------------------------------
Self-line crossing when cutting a bend: the self-line-crossing may happen
after a few bends have been skipped. E.g. ends of A<->B cross the line, but
"swallow" a few more in between:
The article does not specify how many vertices should be included when
calculating the end-of-bend inflection. We chose the iterative approach -- as
long as the angle is "right" and the distance is (greedily) decreasing, keep
going.
Self-line crossing when cutting a bend
--------------------------------------
The self-line-crossing may happen after a few bends have been skipped. E.g.
ends of A<->B cross the line, but "swallow" a few more in between:
,______
/ \
@ -36,3 +44,24 @@ This may be simplified: if other bend's endpoints (A' and B') are in the same
sub-plane as divided by AB, then the bend can be skipped from checking if it
intersects with AB. Some intersections may be missed (see the last example),
but they will be eliminated by joining A and B anyway.
Also, there is another way to remove self-crossing, without removing most of
the bend. E.g. from:
\ \
B\ | __
| | / \
| |____/A |
\__________|
To:
\ \_
B\ `-,_.__
| A' \
| |
\__________|
But perhaps it doesn't look quite as natural. I will trust the original
article to do the right thing here.

View File

@ -18,7 +18,7 @@ insert into figures (name, way) values ('fig3',ST_GeomFromText('LINESTRING(0 0,1
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)'));
insert into figures (name, way) values ('fig6',ST_GeomFromText('LINESTRING(84 47,91 59,114 64,122 80,116 92,110 93,106 106,117 118,136 107,135 76,120 45,125 39,141 39,147 32)'));
insert into figures (name, way) values ('fig6-rev',st_reverse(st_translate((select way from figures where name='fig6'), 80, 0)));
insert into figures (name, way) values ('fig6-rev',ST_Reverse(ST_Translate((select way from figures where name='fig6'), 80, 0)));
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)'));
-- DETECT BENDS

27
wm.sql
View File

@ -191,28 +191,29 @@ begin
p2 = p1;
p1 = p0;
continue when p3 is null;
angle = angle + abs(pi - st_angle(p1, p2, p3));
end loop;
continue when abs(angle) <= pi;
-- sum of inflection angles for this bend is >180, so it may be self-crossing.
-- now try to find another bend in this line that crosses this one.
-- sum of inflection angles for this bend is >180, so it may be
-- self-crossing. now try to find another bend in this line that
-- crosses an imaginary line of end-vertices
p0 = st_pointn(bends[i], 1);
p1 = st_pointn(bends[i], -1);
-- go through each bend in this line, and see if has a potential to cross bends[i].
-- optimization: we care only about bends which beginning and end start at different
-- sides of the plane, separated by endpoints p0 and p1.
-- go through each bend in the given line, and see if has a potential to
-- cross bends[i]. optimization: we care only about bends which beginning
-- and end start at different sides of the plane, separated by endpoints
-- p0 and p1.
for j in 1..array_length(bends, 1) loop
continue when i = j;
p2 = st_pointn(bends[j], 1);
p3 = st_pointn(bends[j], -1);
-- are p2 and p3 on the same side of (p0,p1)? vector multiplication
-- https://stackoverflow.com/questions/1560492/
-- are p2 and p3 on the different sides of line(p0,p1)? vector
-- multiplication; https://stackoverflow.com/questions/1560492/
s2 = (st_x(p0)-st_x(p1)*(st_y(p2)-st_y(p1))-(st_y(p0)-st_y(p1))*(st_x(p2)-st_x(p1)));
s3 = (st_x(p0)-st_x(p1)*(st_y(p3)-st_y(p1))-(st_y(p0)-st_y(p1))*(st_x(p3)-st_x(p1)));
continue when sign(s2) = sign(s3);
@ -222,16 +223,16 @@ begin
multi = st_split(bends[j], this);
continue when st_numgeometries(multi) = 1;
-- self-crossing detected!
-- real self-crossing detected! Remove it.
-- if j < i:
-- bends[j] = multi[1][1...n-1]; that will have all the vertices of bends[j],
-- except the crossing itself.
-- except the crossing and what comes after it.
-- bends[j] = append(bends[j], bends[i][-1])
-- remove bends from bends[j+1] to bends[i] inclusive.
-- elif j > i:
-- remove bends from bends[i+1] to bends[j-1] inclusive.
-- bends[j] = multi[2][2..n]
-- bends[i]
-- bends[i] = bends[i][1]
-- bends[i] = append(bends[i], multi[2][2..n])
-- remove bends from bends[i+1] to bends[j] inclusive.
end loop;