Opened 12 years ago

Last modified 4 weeks ago

#2038 assigned defect

Exception of topogeo_AddLineString() of a line string with a part colinear with an existing one.

Reported by: wimned Owned by: strk
Priority: medium Milestone: PostGIS Fund Me
Component: topology Version: master
Keywords: robustness Cc:

Description

version: POSTGIS="2.1.0SVN r10365" GEOS="3.3.4-CAPI-1.7.3" PROJ="Rel. 4.7.1, 23 September 2009" LIBXML="2.7.8" TOPOLOGY

the message:

ERROR:  SQL/MM Spatial exception - geometry crosses edge 2
CONTEXT:  PL/pgSQL function "topogeo_addlinestring" line 124 at assignment
SQL statement "SELECT topogeo_AddLineString('wimpy', line1)

The code:

CREATE OR REPLACE FUNCTION test_AddLineString2()
 returns void as
$$
    declare line0 geometry;
    declare line1 geometry;
BEGIN
    raise notice 'version: %', postgis_full_version();
    
    perform CreateTopology('wimpy', 4326);
    line0 = ST_GeometryFromText(
        'LINESTRING( 72.91981 20.95009,72.91082 20.95759)',4326);

    line1 = ST_GeometryFromText(
        'LINESTRING(72.9123215921439 20.9563372813038,72.9122229474764 20.9564195766326,
            72.9130010661966 20.9562352183313,72.9123215921439 20.9563372813038)', 4326);

    perform topogeo_AddLineString('wimpy', line0);
    perform topogeo_AddLineString('wimpy', line1);
END
$$
LANGUAGE plpgsql;

Attachments (1)

colinearity_exception.jpg (5.0 KB ) - added by wimned 12 years ago.

Download all attachments as: .zip

Change History (26)

comment:1 by strk, 12 years ago

Milestone: PostGIS 2.1.0PostGIS 2.0.2
Status: newassigned

Do you feel like attaching and putting inline an small image showing the lines ? You can use the {{ No image "imagename.png" attached to Ticket #2038 }} syntax for inlining an image

comment:2 by strk, 12 years ago

Well, my attempt at quoting the image attach syntax clearly didn't work, but you can use the Mona Lisa icon :)

by wimned, 12 years ago

Attachment: colinearity_exception.jpg added

comment:3 by wimned, 12 years ago

the shortest side of the triangle seems to cause the trouble.

Looks to be exactly colinear, zooming far in in qgis shows no gap.

comment:4 by strk, 12 years ago

Yeah QGis is very unhelpful with these kind of problems. See http://hub.qgis.org/issues/1337 — would be nice to see that fixed. How did you produce the above image ?

It would be helpful to know which line is the first linestring and which one is the second, and which edges get which identifiers…

comment:5 by strk, 12 years ago

Simplest testcase, to put in regression testsuite:

SELECT CreateTopology('t2038');
SELECT TopoGeo_addLineString('t2038', 'LINESTRING( 72.91981 20.95009,72.91082 20.95759)');
SELECT TopoGeo_addLineString('t2038', 'LINESTRING(72.9123215921439 20.9563372813038,72.9122229474764 20.9564195766326, 72.9130010661966 20.9562352183313,72.9123215921439 20.9563372813038)');

There's a single edge and two nodes after first addition, so edge2 comes out from splitting the second line, which is simple in itself.

comment:6 by strk, 12 years ago

The two lines are DISJOINT, according to ST_Relate. When it comes to adding the first point of the new line, the code computes its own tolerance based on what's the minimum drift representable with floating points at point ordinate distance from origin. In this case the number comes out as ~ 2e-13:

DEBUG:  Tolerance for snapping to point POINT(72.9123215921439 20.9563372813038) = 2.62484357731718e-13

This will basically split the first edge. You can obtain the same result by running:

SELECT TopoGeo_addPoint('t2038', ST_StartPoint('LINESTRING(72.9123215921439 20.9563372813038,72.9122229474764 20.9564195766326, 72.9130010661966 20.9562352183313,72.9123215921439 20.9563372813038)'));

BUT if you do, then adding the linestring _will_work_ ! So I guess this is about a missing re-snap after the splitting

comment:7 by strk, 12 years ago

Another interesting number is the distance between the two lines, according to ST_Distance:

3.5527136788005e-15

Which is two orders of magnitude smaller than the computed tolerance, btw, proving the tolerance computer badly wrong…

comment:8 by strk, 12 years ago

So to recap:

1: the first geometry creates the straight edge on the left 2: the second geometry is DISJOINT from the first, but its starting node (the bottom one on the left) is found to be within the min tolerance from the first edge, thus splitting it 3: the upper portion of former first edge, as split by the new node, results as having an interior-interior intersection with the second geometry

I guess we could re-iterate over AddLineString after the split. Would be a recursive call, until there's no more edge splitting…

comment:9 by strk, 12 years ago

I confirm that a recursion would fix, as shown by the TopoGeo_addPoint(ST_StartPoint()) trick shown above.

comment:10 by strk, 12 years ago

More possibly interesting numbers about the outcome of ST_ClosestPoint

NOTICE: ClosestPoint is at distance 3.5527136788005e-15 from line and 2.86428933843956e-14 from point (which is at distance 2.86428933843956e-14 from the line)

comment:11 by wimned, 12 years ago

Seems like a rare situation. I can make a list of patch points. When they match the input I'll do a topogeo_AddPoint before adding linestrings, until this is repaired.

comment:12 by strk, 12 years ago

Yes, the suggested workaround could work.

This case falls in the general problem of adding a node to edge without moving the edge.

It's clearly impossible NOT to move the edge, due to the finite nature of the numbers being used to represent points. But it should theoretically be possible to ensure that such a drift never introduces further intersections. Only pretty hard to do in practice (and we know topology building is already being very slow..)

comment:13 by strk, 12 years ago

Since we're at it, the test with one vertex removed (so we have 5 vertices in total). Can still reproduce the issue:

SELECT CreateTopology('t2038');
SELECT TopoGeo_addLineString('t2038', 'LINESTRING( 72.91981 20.95009,72.91082 20.95759)');
SELECT TopoGeo_addLineString('t2038', 'LINESTRING(72.9123215921439 20.9563372813038,72.9122229474764 20.9564195766326, 72.9130010661966 20.9562352183313)');

comment:14 by strk, 11 years ago

Milestone: PostGIS 2.0.2PostGIS 2.0.3

comment:15 by pramsey, 11 years ago

Milestone: PostGIS 2.0.4PostGIS 2.0.5

comment:16 by pramsey, 10 years ago

Milestone: PostGIS 2.0.5PostGIS 2.0.6

comment:17 by pramsey, 9 years ago

Milestone: PostGIS 2.0.7PostGIS 2.0.8

comment:18 by pramsey, 7 years ago

Milestone: PostGIS 2.0.8PostGIS 2.2.6

comment:19 by pramsey, 7 years ago

Milestone: PostGIS 2.2.6PostGIS 2.2.7

comment:20 by robe, 6 years ago

Milestone: PostGIS 2.2.7PostGIS 2.5.0

comment:21 by robe, 6 years ago

Milestone: PostGIS 2.5.0PostGIS next

comment:22 by robe, 6 years ago

Milestone: PostGIS nextPostGIS 3.0.0

Milestone renamed

comment:23 by robe, 5 years ago

Milestone: PostGIS 3.0.0PostGIS Fund Me

comment:24 by strk, 4 weeks ago

Keywords: robustness added

comment:25 by strk, 4 weeks ago

For the record: this problem persists as of current master branch ( [ff91a5acd205638bf6230c02391048883e0a4a35/git] 3.5.0dev )

See also #5699 for a similar case

Note: See TracTickets for help on using tickets.