]> granicus.if.org Git - postgis/commitdiff
#3127 revert back to use sphere distance (spheroid doesn't work with knn recheck...
authorRegina Obe <lr@pcorp.us>
Sun, 31 May 2015 20:14:32 +0000 (20:14 +0000)
committerRegina Obe <lr@pcorp.us>
Sun, 31 May 2015 20:14:32 +0000 (20:14 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@13593 b70326c6-7e19-0410-871a-916f4a2858ee

doc/reference_operator.xml
postgis/geography_measurement.c
regress/knn_recheck.sql
regress/knn_recheck_expected

index 1e0ae7a74da30d8404f7f13db19b28a04d212302..7a314d0477828ef410d9f39fad0396130be0781e 100644 (file)
@@ -1069,7 +1069,7 @@ select 'LINESTRING(0 0, 1 1)'::geometry ~= 'LINESTRING(0 1, 1 0)'::geometry as e
                        <refname>&lt;-&gt;</refname>
 
                        <refpurpose>
-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
                        </refpurpose>
                  </refnamediv>
 
@@ -1087,6 +1087,22 @@ Returns the 2D distance between A and B. Used in the "ORDER BY" clause to provid
                                <paramdef>
                                  <type>geometry </type>
 
+                                 <parameter>B</parameter>
+                               </paramdef>
+                         </funcprototype>
+                         
+                          <funcprototype>
+                               <funcdef>double precision <function>&lt;-&gt;</function></funcdef>
+
+                               <paramdef>
+                                 <type>geography </type>
+
+                                 <parameter>A</parameter>
+                               </paramdef>
+
+                               <paramdef>
+                                 <type>geography </type>
+
                                  <parameter>B</parameter>
                                </paramdef>
                          </funcprototype>
@@ -1104,7 +1120,7 @@ nearest neighbor distance ordering.</para>
                        <note><para>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</para></note>
                        <para>Refer to <ulink url="http://workshops.opengeo.org/postgis-intro/knn.html">OpenGeo workshop: Nearest-Neighbour Searching</ulink> for real live example.</para>
 
-                        <para>Enhanced: 2.2.0 -- True KNN ("K nearest neighbor") behavior and geography support for PostgreSQL 9.5+</para>
+                        <para>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.</para>
                         <para>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.</para>
                         <para>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+</para>
                                
index 1b9b6722a8f850851fac91a7e47772b463059f7b..d77cd0764ea98873738e90a7f7db190279c85ebb 100644 (file)
@@ -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. */
index 61816da778dde9882f3efa991d86311e88a363cf..294dab5984f875337beabcbf4508411c62c723cc 100644 (file)
@@ -1,4 +1,4 @@
--- create table\r
+-- create table\r
 CREATE TABLE knn_recheck_geom(gid serial primary key, geom geometry);\r
 INSERT INTO knn_recheck_geom(gid,geom)\r
 SELECT ROW_NUMBER() OVER(ORDER BY x,y) AS gid, ST_Point(x*0.777,y*0.777) As geom\r
@@ -77,46 +77,47 @@ FROM knn_recheck_geog
 WHERE gid IN(1000, 10000, 2000, 2614, 40000);\r
 \r
 \r
-SELECT gid, RANK() OVER(ORDER BY ST_Distance( 'POINT(95 10)'::geography, geog) )\r
+SELECT gid, RANK() OVER(ORDER BY ST_Distance( 'POINT(95 10)'::geography, geog,false) )\r
 FROM knn_recheck_geog\r
 ORDER BY 'POINT(95 10)'::geography <-> geog LIMIT 5;\r
 \r
-SELECT gid, RANK() OVER(ORDER BY ST_Distance( 'POINT(-95 -10)'::geography, geog) )\r
+SELECT gid, RANK() OVER(ORDER BY ST_Distance( 'POINT(-95 -10)'::geography, geog, false) )\r
 FROM knn_recheck_geog\r
 ORDER BY 'POINT(-95 -10)'::geography <-> geog LIMIT 5;\r
 \r
 -- lateral check before index\r
-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\r
+SELECT a.gid,  ARRAY(SELECT  gid\r
+                       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\r
+                       FROM knn_recheck_geog As g WHERE a.gid <> g.gid ORDER BY a.geog <-> g.geog LIMIT 5) As dist_order_agree\r
 FROM knn_recheck_geog As a \r
-       LEFT JOIN \r
-               LATERAL ( SELECT  gid, geog,  a.geog <-> g.geog  As dist\r
-                       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\r
        WHERE a.gid IN(500000,500010,1000,2614)\r
-ORDER BY a.gid, knn_rn;\r
+ORDER BY a.gid;\r
+\r
 \r
 -- create index and repeat\r
 CREATE INDEX idx_knn_recheck_geog_gist ON knn_recheck_geog USING gist(geog);\r
 \r
-SELECT gid, RANK() OVER(ORDER BY ST_Distance( 'POINT(95 10)'::geography, geog) )\r
+SELECT gid\r
 FROM knn_recheck_geog\r
 ORDER BY 'POINT(95 10)'::geography <-> geog LIMIT 5;\r
 \r
-SELECT gid, RANK() OVER(ORDER BY ST_Distance( 'POINT(-95 -10)'::geography, geog) )\r
+SELECT gid\r
 FROM knn_recheck_geog\r
 ORDER BY 'POINT(-95 -10)'::geography <-> geog LIMIT 5;\r
 \r
--- lateral check before index\r
-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\r
+-- check after index\r
+set enable_seqscan = false;  --sometimes doesn't want to use index\r
+SELECT a.gid,  ARRAY(SELECT  gid\r
+                       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\r
+                       FROM knn_recheck_geog As g WHERE a.gid <> g.gid ORDER BY a.geog <-> g.geog LIMIT 5) As dist_order_agree\r
 FROM knn_recheck_geog As a \r
-       LEFT JOIN \r
-               LATERAL ( SELECT  gid, geog,  a.geog <-> g.geog  As dist\r
-                       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\r
        WHERE a.gid IN(500000,500010,1000,2614)\r
-ORDER BY a.gid, knn_rn;\r
+ORDER BY a.gid;\r
 \r
 DROP TABLE knn_recheck_geog;\r
 \r
 --\r
 -- Delete inserted spatial data\r
 --\r
-DELETE FROM spatial_ref_sys WHERE srid = 4326;
\ No newline at end of file
+DELETE FROM spatial_ref_sys WHERE srid = 4326;\r
+\r
index 1b06c81d38f67fa86cd090f9b3af5d6b9168728d..709bb71880ee9ab2a2709a66e506a551e5d152e2 100644 (file)
 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