Opened 12 years ago
Closed 12 years ago
#884 closed defect (fixed)
Unstable results with ST_Within, ST_Intersects
|Reported by:||strk||Owned by:||chodgson|
Description (last modified by )
This is pretty puzzling. Load attached dataset, then: (I suspect it affects all functions that used prepared geometry - does same with ST_Intersects)
-- This query says none of the 3 polygons contain the point =# select gid, ST_Within( ST_GeomFromText('POINT (-115.04252 36.05137)', -1), the_geom ) from foo_reload; -- This query says polygon 3 does contain the point =# select gid, ST_Within( ST_GeomFromText('POINT (-115.04252 36.05137)', -1), the_geom ) from foo_reload where gid = 3;
Storing the point geometry into a table makes no difference. Geometry number 3 really contains the point. The other two don't.
I've tested this with PostgreSQL 8.4.3, PostGIS 2.0.0SVN and GEOS 3.3.0dev
Change History (26)
comment:1 by , 12 years ago
comment:2 by , 12 years ago
Oops wrong output - but still the same result
select gid, ST_IsValid(the_geom), ST_Within(ST_GeomFromText('POINT (-115.04252 36.05137)', -1), the_geom) from foo_reload where gid !=2; gid | st_isvalid | st_within -----+------------+----------- 1 | t | f 3 | t | t
comment:3 by , 12 years ago
I think it has to do with prepared geometries too. You get true where gid > 2 and two falses where gid > 1.
comment:4 by , 12 years ago
|Milestone:||PostGIS 2.0.0 → PostGIS 1.5.3|
|Version:||trunk → 1.5.X|
Reporter says this bug is in 1.5.2, calling for an 1.5.3 on bugfix here (but not planning to fix this myself, not in the short term at least)
comment:5 by , 12 years ago
|Summary:||Unstable results from ST_Within → Unstable results with Prepared Geometry (ST_Within, ST_Intersects)|
I think this highly points the finger at prepared geometry
select gid, ST_IsValid(the_geom), ST_Intersects(ST_GeomFromText('POINT (-115.04252 36.05137)', -1), the_geom) from foo_reload; gid | st_isvalid | st_intersects -----+------------+--------------- 1 | t | f 2 | t | f 3 | t | f
comment:6 by , 12 years ago
|Summary:||Unstable results with Prepared Geometry (ST_Within, ST_Intersects) → Unstable results with ST_Within, ST_Intersects|
Lookin at the code the ST_Within case isn't strictly using geos prepared geometries, but a custom caching thing, takin to point_in_multipolygon_rtree
comment:7 by , 12 years ago
Actually, also ST_Interscets has a non-GEOS implementation, based on cached rings.
comment:8 by , 12 years ago
what about ST_Intersects?
comment:9 by , 12 years ago
As I commented earlier, ST_Intersects is hitting the cache code (out of GEOS). We're probably talking about lwgeom_rtree
comment:10 by , 12 years ago
both ST_Intersects and ST_Within, ONLY in the failing case, are callin point_in_multipolygon_rtree.
comment:11 by , 12 years ago
ST_CoveredBy is another such case. As well pointing at point_in_multipolygon_rtree
comment:12 by , 12 years ago
I don't see the attached dataset.
It seems to be very close in the code to #852, but I cannot see how that would give this behavior.
But what I found in #852 is that the tolerance doesn't work on vertical and horizontal boundary lines and that the tolerance is not a tolerance of 1e-12 map units as expected but depends on the length of the boundary segment that it is checked against.
by , 12 years ago
comment:13 by , 12 years ago
comment:14 by , 12 years ago
regress-testing this becomes of upmost importance. Easier if outside of postgresql, with unit testing.
comment:15 by , 12 years ago
comment:16 by , 12 years ago
Have there been any updates on this bug? I was able to workaround this problem by creating thin bridges from the island sub-polygon to the mainland sub-polygon, thus converting the multipolygon to a polygon. However, we've come across this problem again in our production system with a very complicated multi-polygon that will be difficult to fix with the workaround.
comment:17 by , 12 years ago
|Status:||new → assigned|
The logic used in point_in_multipolygon_rtree() was different that the logic in point_in_multipolygon(), and gave the wrong answer for the specific case of a point inside a polygon that is inside a hole of a larger polygon (island in a lake inside a larger area).
I modified the multipolygon rtree cache structure to use the standard polygon order for multipolygons instead of the goofy list of all outer rings first followed by a list of all inner rings, which then make it possible to use the right logic in the rtree case.
Committed fix for 1.5 branch in r7136.
comment:18 by , 12 years ago
Chris: can you add a regression test for this in regress/tickets.sql ?
comment:19 by , 12 years ago
Yah I'm working on it right now - that's why the ticket's not closed
comment:20 by , 12 years ago
comment:21 by , 12 years ago
|Status:||assigned → closed|
comment:22 by , 12 years ago
comment:23 by , 12 years ago
comment:24 by , 12 years ago
|Status:||closed → reopened|
lreeder found a new case which breaks my earlier fix.
comment:25 by , 12 years ago
|Status:||reopened → closed|
Just to add to strk — me too, and see ST_DWithin works fine and since ST_Within works fine with just one record, and I don't think ST_DWithin uses prepared geometry, that rules out Geos and any weirdness in PostgreSQL. So I'm guessing prepared geometry hashing. Check this out: