Opened 12 years ago

Closed 12 years ago

#1613 closed defect (fixed)

Cannot achieve toTopoGeom

Reported by: 3nids Owned by: strk
Priority: medium Milestone: PostGIS 2.0.0
Component: topology Version: 2.0.x
Keywords: Cc:

Description

With the given example, I get the following error ERROR: SQL/MM Spatial exception - point not on edge

Attachments (1)

strk.demo.sql (1.1 KB ) - added by 3nids 12 years ago.

Download all attachments as: .zip

Change History (9)

by 3nids, 12 years ago

Attachment: strk.demo.sql added

comment:1 by strk, 12 years ago

Status: newassigned

comment:2 by strk, 12 years ago

Confirmed, it does happen

comment:3 by strk, 12 years ago

Further reduced inputs:

'LINESTRING(556267.562954 144887.066638, 556267.566750 144887.414190)'
'LINESTRING(556254.67 144886.62, 556267.66 144887.07, 556310.04 144888.17)'

The end point of the first is close but not equal to the middle point of the second

comment:4 by strk, 12 years ago

Ok, what's happening is that the code fails snapping the first line to the intersection with the second line.

Try this:

select ST_AsText(ST_Snap('LINESTRING(556267.562954 144887.066638,556267 144887.4)'::geometry, 'POINT(556267.55881132 144887.069091153)'::geometry, 1e-12));

You'll see the edge remains a 2-points edge.

1e-12 is an arbitrary tolerance hard-coded into the TopoGeo_AddPoint, only because ST_Snap needs a tolerance to do its thing. If you make it bigger you get the 3-vertex result. If you make it too big it gets back to 2 vertex snapping to the first vertex whose distance is below the tolerance.

Not an easy problem to solve. The whole reason to snap is because the ST_ModEdgeSplit (and ST_NewEdgesSplit) insist on the "splitting-vertex" to be _within_ the edge, which is close to impossible to achieve… The SQL/MM specs do not include any reference about accepting tolerances in there.

Finally, it turns out that ST_Within and ST_DWithin(0) disagree about the matter being:

is '010100000070841C1ED7F9204187A97F8DB8AF0141'::geometry
within '010200000002000000B6813B20D7F92041F5807988B8AF014100000000D6F9204133333333BBAF0141'::geometry ?

So bottomline:

=# with inp as ( select '010100000070841C1ED7F9204187A97F8DB8AF0141'::geometry as p, '010200000002000000B6813B20D7F92041F5807988B8AF014100000000D6F9204133333333BBAF0141'::geometry as l ) select ST_AsText(l) as l, ST_AsText(p) as p, ST_Within(p, l) as within, ST_DWithin(p, l, 0) as dwithin from inp;
-[ RECORD 1 ]----------------------------------------------------
l       | LINESTRING(556267.562954 144887.066638,556267 144887.4)
p       | POINT(556267.55881132 144887.069091153)
within  | f
dwithin | t

Worth a sub-ticket

comment:5 by strk, 12 years ago

#1625 is the subticket

comment:6 by strk, 12 years ago

The question to answer for finding a good snap tolerance value would be: how far could a projected point be from the segment over which it is projected ? The float grid size changes as we use more numbers on the left side of the comma….

comment:8 by strk, 12 years ago

Resolution: fixed
Status: assignedclosed

Alright, the magic "what's small enough while still good" heuristic was added in r9330, fixing this specific case. Ready for next topology ticket, none left !

Note: See TracTickets for help on using tickets.