From 79d72839fe75446bbeb7292a339d0129c157c51e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Thu, 4 Mar 2021 17:59:26 +0200 Subject: [PATCH] wip self-crossing --- IV/notes.txt | 4 ++-- IV/tests.sql | 1 + IV/wm.sql | 24 +++++++++++++++++++----- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/IV/notes.txt b/IV/notes.txt index 61c8b2c..90f5a39 100644 --- a/IV/notes.txt +++ b/IV/notes.txt @@ -12,13 +12,13 @@ after a few bends have been skipped. E.g. ends of A<->B cross the line, but ,______ / \ - |___A | \ | + |___A | \ \ \ | B\ | __ \ | | | / \ / | | |___,---,___/A | / | \_________________| \ | - \ | \ | + \ | \ \ / / B\ | _ __ ----/ / | | / \ / \ / ,____/ | |___/ \___/A | diff --git a/IV/tests.sql b/IV/tests.sql index 5ab4143..228e2fc 100644 --- a/IV/tests.sql +++ b/IV/tests.sql @@ -18,6 +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 ('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 diff --git a/IV/wm.sql b/IV/wm.sql index 4379b5f..b115070 100644 --- a/IV/wm.sql +++ b/IV/wm.sql @@ -175,6 +175,8 @@ declare s2 real; s3 real; bend geometry; + this geometry; + multi geometry; begin pi = radians(180); @@ -199,7 +201,6 @@ begin -- now try to find another bend in this line that crosses this one. p0 = st_pointn(bends[i], 1); p1 = st_pointn(bends[i], -1); - --this = st_makeline(st_pointn(bends[i], 1), 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 @@ -210,14 +211,27 @@ begin p2 = st_pointn(bends[j], 1); p3 = st_pointn(bends[j], -1); - -- https://stackoverflow.com/questions/1560492 + -- are p2 and p3 on the same side of (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); - -- bend j may be crossing bend i, and it has a chance to be "important" -- - -- p2 and p3 are in different sides of the plane as delimited by p0 and p1. - -- now does it really cross the line (p0, p1)? + -- do end vertices of bend[i] cross bend[j]? + this = st_makeline(st_pointn(bends[i], 1), st_pointn(bends[i], -1)); + multi = st_split(bends[j], this); + continue when st_numgeometries(multi) = 1; + + -- self-crossing detected! + -- if j < i: + -- bends[j] = multi[1][1...n-1]; that will have all the vertices of bends[j], + -- except the crossing itself. + -- 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] end loop;