# PostGIS - Linestring doesn't contain a Point - Problem

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
``````

• Point on line is always difficult, even when matching a vertex. Use distance to line and then decide if the return distance is small enough to make the point 'on' the line. May 6 '16 at 0:28

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)
``````