6

is there anyway to set tolerance in Postgis, in Arcgis tolerance is the minimum distance which could separate two points, if the distance between them is smaller than the tolerance so the points are considered overlapped. i need to set this parameter because i get some weird results using functions like ST_Intersects, ST_equals, ST_difference. in this conditions i check intersecting points by ST_Distance(p1 , p2) < tolerance but i would like to get a more robust and general solution.

in my use case i need only 1cm to 1mm precision, but for example sometimes ST_Intersects do not give expected results because of some microns (0.000001).

SELECT ST_Intersects('POINT(0.00000000000000001 0)'::geometry, 'LINESTRING ( 0 0, 0 2 )'::geometry);
5
  • As far as I know PostGIS does not support such tolerance. ST_SnapToGrid is often a good help if can use it inside your queries. Sometimes ST_Snap can be used as well.
    – user30184
    Aug 5, 2015 at 10:58
  • How many decimal places do you geometries have? Aug 5, 2015 at 12:08
  • @JohnBarça i have geometries with coordinates like 123456.78
    – geogeek
    Aug 5, 2015 at 12:23
  • I would be very surprised if ST_Intersects is misbehaving due to a couple of decimal places. I think it has double precision. Perhaps you could post a couple of geometries that should/should not intersect, ie, where you are getting what you say are unexpected results. Aug 5, 2015 at 12:28
  • this is an example SELECT ST_Intersects('POINT(0.00000000000000001 0)'::geometry, 'LINESTRING ( 0 0, 0 2 )'::geometry);
    – geogeek
    Aug 5, 2015 at 13:45

1 Answer 1

7

The most robust strategy for determining a geometry intersection is to use ST_DWithin(g1, g2, dist). But if you are using geometry overlay tools like ST_Difference or ST_Intersection, then the nodes need to be "snapped" to each other, so try ST_Snap(geometry input, geometry reference, float tolerance). Here is a an example of several techniques.

SELECT ST_Intersects(a, b) AS intersects_without_snap,
  ST_AsText(ST_Snap(a, b, tol)) AS a_snapped_on_b,
  ST_Intersects(ST_Snap(a, b, tol), b) AS intersects_with_a_snapped_on_b,
  ST_AsText(ST_Snap(b, a, tol)) AS b_snapped_on_a,
  ST_Intersects(ST_Snap(b, a, tol), b) AS intersects_with_b_snapped_on_a,
  ST_DWithin(a, b, tol),
  ST_Distance(a, b) < tol AS distance_lt_tol
FROM (
  SELECT 'POINT(0.00000000000000001 0)'::geometry AS a,
    'LINESTRING ( 0 0, 0 2 )'::geometry AS b,
    0.001 AS tol
) f;
-[ RECORD 1 ]------------------+-------------------------
intersects_without_snap        | f
a_snapped_on_b                 | POINT(0 0)
intersects_with_a_snapped_on_b | t
b_snapped_on_a                 | LINESTRING(1e-017 0,0 2)
intersects_with_b_snapped_on_a | t
st_dwithin                     | t
distance_lt_tol                | t

Again, the simplistic for the question is ST_DWithin. (ST_Snap sometimes does unexpected things, in my experience)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.