I have a problem to check if a Linestring contains a Point. I consider the straight line y = 0.1 x , and take by it a segment l='Linestring( 0 0 , 4 0.4 )' and a Point p on segment l, p = 'Point(1.5 0.15)'. If I check ST_Contains(l,p) the result is false and the distance ST_Distance(l,p) is near to zero, but this is wrong because the Point is on the Linestring. If I try with p= 'Point(2 0.2)' the result is right.
What is the problem?
WITH
l AS (
SELECT ST_GeomFromText('Linestring( 0 0 , 4 0.4 )') AS geom -- segment of the straight line y = 0.1 x
),
p AS (
SELECT ST_GeomFromText('Point(1.5 0.15)') AS geom -- point on the straight line y = 0.1 x
)
SELECT ST_AsText(ST_Intersection(p.geom,l.geom)) as ST_Intersection,
ST_Distance(p.geom,l.geom),
ST_Contains(l.geom,p.geom),
ST_Intersects(p.geom,l.geom),
ST_AsText(ST_Line_Interpolate_Point(l.geom,1.5/4)) as ST_Substring -- point in position 1.5/4 of l
FROM l,p
EDIT: My origin problem was: LineString L1 contains Linestring L2 but if I do ST_SymDifference(l1.geom,l2.geom) the result is incorrect.
WITH
l1 AS (
SELECT ST_GeomFromText('Linestring( 0 0 , 4 0.4 )') AS geom -- segment of the straight line y = 0.1 x
),
l2 AS (
SELECT ST_GeomFromText('LineString(0 0 , 1.5 0.15)') AS geom -- segment of the straight line y = 0.1 x
)
SELECT ST_AsText(ST_SymDifference(l1.geom,l2.geom)) as ST_Intersection
FROM l1,l2
Answer
Overlay operators like Contains, Intersection, SymDifference, etc. require exact noding. This is because there are floating point differences on the order of 1e-14 when interpolations are performed between two lines that are not equal. And while 1e-14 is a tiny number, it is still not zero.
Use ST_Snap to help "snap" vertices from one geometry onto another to get exact noding. For example:
SELECT ST_AsText(ST_Intersection(p, ST_Snap(l, p, 1e-14))) as ST_Intersection,
ST_Distance(p, ST_Snap(l, p, 1e-14)),
ST_Contains(ST_Snap(l, p, 1e-14), p),
ST_Intersects(p, ST_Snap(l, p, 1e-14))
FROM (
SELECT 'Linestring(0 0, 4 0.4)'::geometry l, 'Point(1.5 0.15)'::geometry p
) f;
st_intersection | st_distance | st_contains | st_intersects
-----------------+-------------+-------------+---------------
POINT(1.5 0.15) | 0 | t | t
(1 row)
No comments:
Post a Comment