beginnings of self-crossing

This commit is contained in:
Motiejus Jakštys 2021-03-02 14:54:44 +02:00
parent 28bad3583f
commit f26073151b
3 changed files with 40 additions and 8 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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;