From: Regina Obe Date: Sun, 31 May 2015 20:14:32 +0000 (+0000) Subject: #3127 revert back to use sphere distance (spheroid doesn't work with knn recheck... X-Git-Tag: 2.2.0rc1~422 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d16c2a7aa98a605d25ad180a306aaf4c8093c3be;p=postgis #3127 revert back to use sphere distance (spheroid doesn't work with knn recheck), document that <-> is on sphere, change tests to be based on sphere instead of spheroid., #3131 reverting fixes index returned tuples wrong order issue git-svn-id: http://svn.osgeo.org/postgis/trunk@13593 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/doc/reference_operator.xml b/doc/reference_operator.xml index 1e0ae7a74..7a314d047 100644 --- a/doc/reference_operator.xml +++ b/doc/reference_operator.xml @@ -1069,7 +1069,7 @@ select 'LINESTRING(0 0, 1 1)'::geometry ~= 'LINESTRING(0 1, 1 0)'::geometry as e <-> -Returns the 2D distance between A and B. Used in the "ORDER BY" clause to provide index-assisted nearest-neighbor result sets. For PostgreSQL below 9.5 only gives centroid distance of bounding boxes and for PostgreSQL 9.5+, does true KNN distance search giving true distance between geometries +Returns the 2D distance between A and B. Used in the "ORDER BY" clause to provide index-assisted nearest-neighbor result sets. For PostgreSQL below 9.5 only gives centroid distance of bounding boxes and for PostgreSQL 9.5+, does true KNN distance search giving true distance between geometries, and distance sphere for geographies @@ -1087,6 +1087,22 @@ Returns the 2D distance between A and B. Used in the "ORDER BY" clause to provid geometry + B + + + + + double precision <-> + + + geography + + A + + + + geography + B @@ -1104,7 +1120,7 @@ nearest neighbor distance ordering. Index only kicks in if one of the geometries is a constant (not in a subquery/cte). e.g. 'SRID=3005;POINT(1011102 450541)'::geometry instead of a.geom Refer to OpenGeo workshop: Nearest-Neighbour Searching for real live example. - Enhanced: 2.2.0 -- True KNN ("K nearest neighbor") behavior and geography support for PostgreSQL 9.5+ + Enhanced: 2.2.0 -- True KNN ("K nearest neighbor") behavior for geometry and geography for PostgreSQL 9.5+. Note for geography KNN is based on sphere rather than spheroid. For PostgreSQL 9.4 and below, geography support is new but only supports centroid box. Changed: 2.2.0 -- For PostgreSQL 9.5 users, old Hybrid syntax may be slower, so you'll want to get rid of that hack if you are running your code only on PostGIS 2.2+ 9.5+. See examples below. Availability: 2.0.0 -- Weak KNN provides nearest neighbors based on geometry centroid distances instead of true distances. Exact results for points, inexact for all other types. Available for PostgreSQL 9.1+ diff --git a/postgis/geography_measurement.c b/postgis/geography_measurement.c index 1b9b6722a..d77cd0764 100644 --- a/postgis/geography_measurement.c +++ b/postgis/geography_measurement.c @@ -61,7 +61,7 @@ Datum geography_distance_knn(PG_FUNCTION_ARGS) GSERIALIZED *g2 = NULL; double distance; double tolerance = FP_TOLERANCE; - bool use_spheroid = true; + bool use_spheroid = false; /**switched back to use sphere, can get index to harmonize with sphoeroid **/ SPHEROID s; /* Get our geometry objects loaded into memory. */ diff --git a/regress/knn_recheck.sql b/regress/knn_recheck.sql index 61816da77..294dab598 100644 --- a/regress/knn_recheck.sql +++ b/regress/knn_recheck.sql @@ -1,4 +1,4 @@ --- create table +-- create table CREATE TABLE knn_recheck_geom(gid serial primary key, geom geometry); INSERT INTO knn_recheck_geom(gid,geom) SELECT ROW_NUMBER() OVER(ORDER BY x,y) AS gid, ST_Point(x*0.777,y*0.777) As geom @@ -77,46 +77,47 @@ FROM knn_recheck_geog WHERE gid IN(1000, 10000, 2000, 2614, 40000); -SELECT gid, RANK() OVER(ORDER BY ST_Distance( 'POINT(95 10)'::geography, geog) ) +SELECT gid, RANK() OVER(ORDER BY ST_Distance( 'POINT(95 10)'::geography, geog,false) ) FROM knn_recheck_geog ORDER BY 'POINT(95 10)'::geography <-> geog LIMIT 5; -SELECT gid, RANK() OVER(ORDER BY ST_Distance( 'POINT(-95 -10)'::geography, geog) ) +SELECT gid, RANK() OVER(ORDER BY ST_Distance( 'POINT(-95 -10)'::geography, geog, false) ) FROM knn_recheck_geog ORDER BY 'POINT(-95 -10)'::geography <-> geog LIMIT 5; -- lateral check before index -SELECT a.gid, b.gid As match, ROW_NUMBER() OVER(PARTITION BY a.gid ORDER BY ST_Distance(a.geog, b.geog, true)::numeric(16,0), b.gid ) As true_rn, ROW_NUMBER() OVER(PARTITION BY a.gid ORDER BY b.dist::numeric, b.gid) As knn_rn +SELECT a.gid, ARRAY(SELECT gid + FROM knn_recheck_geog As g WHERE a.gid <> g.gid ORDER BY ST_Distance(a.geog, g.geog, false) LIMIT 5) = ARRAY(SELECT gid + FROM knn_recheck_geog As g WHERE a.gid <> g.gid ORDER BY a.geog <-> g.geog LIMIT 5) As dist_order_agree FROM knn_recheck_geog As a - LEFT JOIN - LATERAL ( SELECT gid, geog, a.geog <-> g.geog As dist - FROM knn_recheck_geog As g WHERE a.gid <> g.gid ORDER BY a.geog <-> g.geog, g.gid LIMIT 5) As b ON true WHERE a.gid IN(500000,500010,1000,2614) -ORDER BY a.gid, knn_rn; +ORDER BY a.gid; + -- create index and repeat CREATE INDEX idx_knn_recheck_geog_gist ON knn_recheck_geog USING gist(geog); -SELECT gid, RANK() OVER(ORDER BY ST_Distance( 'POINT(95 10)'::geography, geog) ) +SELECT gid FROM knn_recheck_geog ORDER BY 'POINT(95 10)'::geography <-> geog LIMIT 5; -SELECT gid, RANK() OVER(ORDER BY ST_Distance( 'POINT(-95 -10)'::geography, geog) ) +SELECT gid FROM knn_recheck_geog ORDER BY 'POINT(-95 -10)'::geography <-> geog LIMIT 5; --- lateral check before index -SELECT a.gid, b.gid As match, ROW_NUMBER() OVER(PARTITION BY a.gid ORDER BY ST_Distance(a.geog, b.geog, true)::numeric(16,0), b.gid ) As true_rn, ROW_NUMBER() OVER(PARTITION BY a.gid ORDER BY b.dist::numeric, b.gid) As knn_rn +-- check after index +set enable_seqscan = false; --sometimes doesn't want to use index +SELECT a.gid, ARRAY(SELECT gid + FROM knn_recheck_geog As g WHERE a.gid <> g.gid ORDER BY ST_Distance(a.geog, g.geog, false) LIMIT 5) = ARRAY(SELECT gid + FROM knn_recheck_geog As g WHERE a.gid <> g.gid ORDER BY a.geog <-> g.geog LIMIT 5) As dist_order_agree FROM knn_recheck_geog As a - LEFT JOIN - LATERAL ( SELECT gid, geog, a.geog <-> g.geog As dist - FROM knn_recheck_geog As g WHERE a.gid <> g.gid ORDER BY a.geog <-> g.geog, g.gid LIMIT 5) As b ON true WHERE a.gid IN(500000,500010,1000,2614) -ORDER BY a.gid, knn_rn; +ORDER BY a.gid; DROP TABLE knn_recheck_geog; -- -- Delete inserted spatial data -- -DELETE FROM spatial_ref_sys WHERE srid = 4326; \ No newline at end of file +DELETE FROM spatial_ref_sys WHERE srid = 4326; + diff --git a/regress/knn_recheck_expected b/regress/knn_recheck_expected index 1b06c81d3..709bb7188 100644 --- a/regress/knn_recheck_expected +++ b/regress/knn_recheck_expected @@ -63,43 +63,19 @@ 2614|3 2615|4 2795|5 -1000|600001|1|1 -1000|999|2|2 -1000|1001|3|3 -1000|819|4|4 -1000|1181|5|5 -2614|600003|1|1 -2614|500000|2|2 -2614|2615|3|3 -2614|2613|4|4 -2614|2433|5|5 -500000|13732|1|1 -500000|17345|2|2 -500000|11912|3|3 -500000|15725|4|4 -500000|12273|5|5 -33768|1 -33767|2 -33587|3 -33586|4 -33769|5 -500000|1 -600003|2 -2614|3 -2615|4 -2795|5 -1000|600001|1|1 -1000|999|2|2 -1000|1001|3|3 -1000|819|4|4 -1000|1181|5|5 -2614|600003|1|1 -2614|500000|2|2 -2614|2615|3|3 -2614|2613|4|4 -2614|2433|5|5 -500000|13732|1|1 -500000|17345|2|2 -500000|11912|3|3 -500000|15725|4|4 -500000|12273|5|5 +1000|t +2614|t +500000|t +33768 +33767 +33587 +33586 +33769 +500000 +600003 +2614 +2615 +2795 +1000|t +2614|t +500000|t