commit f26073151bcda8f14955e932ca4cdeec53d1b780 (tree)
parent 28bad3583fbca7ae144268575f026363fab34817
Author: Motiejus Jakštys <motiejus@uber.com>
Date: Tue, 2 Mar 2021 14:54:44 +0200
beginnings of self-crossing
Diffstat:
3 files changed, 40 insertions(+), 8 deletions(-)
diff --git a/IV/notes.txt b/IV/notes.txt
@@ -27,13 +27,12 @@ after a few bends have been skipped. E.g. ends of A<->B cross the line, but
-If a bend with 180+ deg inflection is found, its line between inflection angles
-(AB in our examples) must be crossed with all the other bends to detect a
-possible line-crossing. This is O(N*M), where N is the total number of line
-segments, and M is the number of qualifying bends. In other words, can be very
-computationally expensive.
+If a bend with 180+ deg sum of inflection angles is found, its line between
+inflection angles (AB in our examples) must be crossed with all the other bends
+to detect a possible line-crossing. This is O(N*M), where N is the total number
+of line segments, and M is the number of qualifying bends. It is expensive.
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 example), but
-they will be eliminated by just joining A and B.
+intersects with AB. Some intersections may be missed (see the last example),
+but they will be eliminated by joining A and B anyway.
diff --git a/IV/tests.sql b/IV/tests.sql
@@ -47,7 +47,7 @@ drop table if exists inflections, demo_inflections;
create table inflections (name text, ways geometry[]);
insert into inflections select name, fix_gentle_inflections(ways) from bends;
create table demo_inflections (name text, i bigint, way geometry);
-insert into demo_inflections select a.name, generate_subscripts(a.ways, 1), unnest(a.ways) from inflections a;
+insert into demo_inflections select name, generate_subscripts(ways, 1), unnest(ways) from inflections;
do $$
declare
@@ -67,3 +67,10 @@ begin
perform assert_equals('LINESTRING(114 20,133 20,145 15,145 0,136 5,123 7,114 7)', st_astext(vinflections[2]));
perform assert_equals('LINESTRING(123 7,114 7,111 2)', st_astext(vinflections[3]));
end $$ language plpgsql;
+
+-- SELF-LINE CROSSING
+drop table if exists selfcrossing, demo_selfcrossing;
+create table selfcrossing (name text, ways geometry[]);
+insert into selfcrossing select name, self_crossing(ways) from inflections;
+create table demo_selfcrossing (name text, i bigint, way geometry);
+insert into demo_selfcrossing select name, generate_subscripts(ways, 1), unnest(ways) from selfcrossing;
diff --git a/IV/wm.sql b/IV/wm.sql
@@ -170,9 +170,35 @@ $$ language plpgsql;
create or replace function self_crossing(INOUT bends geometry[]) as $$
declare
pi real;
+ angle real;
+ p geometry;
+ p1 geometry;
+ p2 geometry;
+ p3 geometry;
+ bend geometry;
begin
+ pi = radians(180);
+ -- go through the bends and find one where sum of inflection angle is >180
+ foreach bend in array bends loop
+ angle = 0;
+ p3 = null;
+ p2 = null;
+ p1 = null;
+ for p in (select geom from st_dumppoints(bend) order by path[1] asc) loop
+ p3 = p2;
+ p2 = p1;
+ p1 = p;
+ if p3 is null then
+ continue;
+ end if;
+ angle = angle + abs(pi - st_angle(p1, p2, p3));
+ end loop;
+ if abs(angle) > pi then
+ raise notice 'maybe self-crossing bend %: %', st_astext(bend), round(degrees(abs(angle)));
+ end if;
+ end loop;
end
$$ language plpgsql;