]> granicus.if.org Git - postgis/commitdiff
#3133, add <<->> recheck supporrt and rip out <<#>>
authorPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 3 Jun 2015 19:08:23 +0000 (19:08 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 3 Jun 2015 19:08:23 +0000 (19:08 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@13607 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/liblwgeom.h.in
liblwgeom/measures.c
postgis/gserialized_gist_nd.c
postgis/lwgeom_functions_analytic.c
postgis/postgis.sql.in
regress/knn.sql
regress/knn_expected
regress/operators.sql
regress/operators_expected

index 601d17f74f58b0ca8ac1afd82d700b86b2bece80..4db291c3014b1cf86a42148a2d892bab3d308bb7 100644 (file)
@@ -1168,7 +1168,6 @@ extern double lwgeom_mindistance3d_tolerance(const LWGEOM *lw1, const LWGEOM *lw
 extern double lwgeom_maxdistance3d(const LWGEOM *lw1, const LWGEOM *lw2);
 extern double lwgeom_maxdistance3d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance);
 
-
 extern double lwgeom_area(const LWGEOM *geom);
 extern double lwgeom_length(const LWGEOM *geom);
 extern double lwgeom_length_2d(const LWGEOM *geom);
index 26567a179aca0e2eac4df95b73f24de2cea94d69..5142884509ea9cb0cafc5ea27e207382651ce2df 100644 (file)
@@ -18,6 +18,7 @@
 #include "lwgeom_log.h"
 
 
+
 /*------------------------------------------------------------------------------------------------------------
 Initializing functions
 The functions starting the distance-calculation processses
index 8be385ee234d6049fdeea2a9a0f631d90e75d3ac..620ee2f7b5b0a350a0a5dcc58c7b661f3d9b34bd 100644 (file)
@@ -86,8 +86,7 @@ Datum gserialized_gist_geog_distance(PG_FUNCTION_ARGS);
 Datum gserialized_overlaps(PG_FUNCTION_ARGS);
 Datum gserialized_contains(PG_FUNCTION_ARGS);
 Datum gserialized_within(PG_FUNCTION_ARGS);
-Datum gserialized_distance_box_nd(PG_FUNCTION_ARGS);
-Datum gserialized_distance_centroid_nd(PG_FUNCTION_ARGS);
+Datum gserialized_distance_nd(PG_FUNCTION_ARGS);
 
 /*
 ** GIDX true/false test function type
@@ -618,34 +617,16 @@ gserialized_expand(GSERIALIZED *g, double distance)
 * GiST N-D Index Operator Functions
 */
 
-PG_FUNCTION_INFO_V1(gserialized_distance_box_nd);
-Datum gserialized_distance_box_nd(PG_FUNCTION_ARGS)
-{
-       char bmem1[GIDX_MAX_SIZE];
-       GIDX *b1 = (GIDX*)bmem1;
-       char bmem2[GIDX_MAX_SIZE];
-       GIDX *b2 = (GIDX*)bmem2;
-       Datum gs1 = PG_GETARG_DATUM(0);
-       Datum gs2 = PG_GETARG_DATUM(1);
-       double distance;
-
-       POSTGIS_DEBUG(3, "entered function");
-
-       /* Must be able to build box for each argument (ie, not empty geometry). */
-       if ( (gserialized_datum_get_gidx_p(gs1, b1) == LW_SUCCESS) &&
-            (gserialized_datum_get_gidx_p(gs2, b2) == LW_SUCCESS) )
-       {
-               distance = gidx_distance(b1, b2);
-               POSTGIS_DEBUGF(3, "got boxes %s and %s", gidx_to_string(b1), gidx_to_string(b2));
-               PG_RETURN_FLOAT8(distance);
-       }
-       PG_RETURN_FLOAT8(FLT_MAX);
-}
-
-
-PG_FUNCTION_INFO_V1(gserialized_distance_centroid_nd);
-Datum gserialized_distance_centroid_nd(PG_FUNCTION_ARGS)
+/* 
+* Do centroid to centroid n-d distance if you don't have 
+* re-check available (PgSQL 9.5+), do "real" n-d distance
+* if you do
+*/
+PG_FUNCTION_INFO_V1(gserialized_distance_nd);
+Datum gserialized_distance_nd(PG_FUNCTION_ARGS)
 {
+#if POSTGIS_PGSQL_VERSION < 95
+       /* Centroid-to-centroid distance */
        char b1mem[GIDX_MAX_SIZE];
        GIDX *b1 = (GIDX*)b1mem;
        char b2mem[GIDX_MAX_SIZE];
@@ -658,13 +639,56 @@ Datum gserialized_distance_centroid_nd(PG_FUNCTION_ARGS)
 
        /* Must be able to build box for each argument (ie, not empty geometry). */
        if ( (gserialized_datum_get_gidx_p(gs1, b1) == LW_SUCCESS) &&
-                        (gserialized_datum_get_gidx_p(gs2, b2) == LW_SUCCESS) )
+            (gserialized_datum_get_gidx_p(gs2, b2) == LW_SUCCESS) )
        {
                distance = gidx_distance_leaf_centroid(b1, b2);
                POSTGIS_DEBUGF(3, "got boxes %s and %s", gidx_to_string(b1), gidx_to_string(b2));
                PG_RETURN_FLOAT8(distance);
        }
        PG_RETURN_FLOAT8(FLT_MAX);
+#else
+       /* Feature-to-feature distance */
+       GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
+       GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
+       LWGEOM *lw1 = lwgeom_from_gserialized(geom1);
+       LWGEOM *lw2 = lwgeom_from_gserialized(geom2);
+       LWGEOM *closest;
+       double dist;
+
+       /* Find an exact shortest line w/ the dimensions we support */
+       if ( lwgeom_has_z(lw1) && lwgeom_has_z(lw2) )
+       {
+               closest = lwgeom_closest_line_3d(lw1, lw2);
+               dist = lwgeom_length(closest);
+       }
+       else
+       {
+               closest = lwgeom_closest_line(lw1, lw2);
+               dist = lwgeom_length_2d(closest);
+       }
+
+       /* Un-sqrt the distance so we can add extra terms */
+       dist = dist*dist;
+
+       /* Can only add the M term if both objects have M */
+       if ( lwgeom_has_m(lw1) && lwgeom_has_m(lw2) )
+       {
+               double m1, m2;
+               LWPOINT *lwp1 = lwline_get_lwpoint(closest, 0);
+               LWPOINT *lwp2 = lwline_get_lwpoint(closest, 1);
+               m1 = lwgeom_interpolate_point(lw1, lpw1);
+               m2 = lwgeom_interpolate_point(lw2, lpw2);
+               lwpoint_free(lwp1);
+               lwpoint_free(lwp2);
+               dist += (m1-m2)*(m1-m2);
+       }
+
+       lwgeom_free(closest);
+
+       PG_FREE_IF_COPY(geom1, 0);
+       PG_FREE_IF_COPY(geom2, 1);
+       PG_RETURN_FLOAT8(sqtr(dist));
+#endif
 }
 
 /*
@@ -1113,8 +1137,7 @@ Datum gserialized_gist_geog_distance(PG_FUNCTION_ARGS)
 ** represents the distance to the index entry; for an internal tree node, the
 ** result must be the smallest distance that any child entry could have.
 **
-** Strategy 13 = centroid-based distance tests
-** Strategy 14 = box-based distance tests (not implemented)
+** Strategy 13 = centroid-based distance tests <<->>
 */
 PG_FUNCTION_INFO_V1(gserialized_gist_distance);
 Datum gserialized_gist_distance(PG_FUNCTION_ARGS)
@@ -1124,13 +1147,16 @@ Datum gserialized_gist_distance(PG_FUNCTION_ARGS)
        char query_box_mem[GIDX_MAX_SIZE];
        GIDX *query_box = (GIDX*)query_box_mem;
        GIDX *entry_box;
+#if POSTGIS_PGSQL_VERSION >= 95
+       bool *recheck = (bool *) PG_GETARG_POINTER(4);
+#endif
+       
        double distance;
 
        POSTGIS_DEBUG(4, "[GIST] 'distance' function called");
  
-       /* We are using '13' as the gist distance-betweeen-centroids strategy number
-        *  and '14' as the gist distance-between-boxes strategy number */
-       if ( strategy != 13 && strategy != 14 ) {
+       /* We are using '13' as the gist distance strategy number for <<->> */
+       if ( strategy != 13 ) {
                elog(ERROR, "unrecognized strategy number: %d", strategy);
                PG_RETURN_FLOAT8(FLT_MAX);
        }
@@ -1145,27 +1171,25 @@ Datum gserialized_gist_distance(PG_FUNCTION_ARGS)
        /* Get the entry box */
        entry_box = (GIDX*)DatumGetPointer(entry->key);
 
-       /* Box-style distance test <<#>> */
-       if ( strategy == 14 )
+#if POSTGIS_PGSQL_VERSION >= 95
+
+       distance = gidx_distance(entry_box, query_box);
+       /* Treat leaf node tests different from internal nodes */
+       if (GIST_LEAF(entry))
+               *recheck = true;
+#else
+       /* Treat leaf node tests different from internal nodes */
+       if (GIST_LEAF(entry))
        {
-               distance = gidx_distance(entry_box, query_box);
+               /* Calculate distance to leaves */
+               distance = (double)gidx_distance_leaf_centroid(entry_box, query_box);
        }
-       /* Centroid-style distance test <<->> */
        else
        {
-               /* Treat leaf node tests different from internal nodes */
-               if (GIST_LEAF(entry))
-               {
-                       /* Calculate distance to leaves */
-                       distance = (double)gidx_distance_leaf_centroid(entry_box, query_box);
-               }
-               else
-               {
-                       /* Calculate distance for internal nodes */
-                       distance = (double)gidx_distance_node_centroid(entry_box, query_box);
-               }
+               /* Calculate distance for internal nodes */
+               distance = (double)gidx_distance_node_centroid(entry_box, query_box);
        }
-
+#endif
        PG_RETURN_FLOAT8(distance);
 }
 
index c8f91c61790cd2929ac05316a2c3548eef612e24..09003d816d408764c4ff7cb0a57bce0998eabdc6 100644 (file)
@@ -34,6 +34,7 @@ Datum LWGEOM_simplify2d(PG_FUNCTION_ARGS);
 Datum LWGEOM_SetEffectiveArea(PG_FUNCTION_ARGS);
 Datum ST_LineCrossingDirection(PG_FUNCTION_ARGS);
 
+
 double determineSide(POINT2D *seg1, POINT2D *seg2, POINT2D *point);
 int isOnSegment(POINT2D *seg1, POINT2D *seg2, POINT2D *point);
 int point_in_ring(POINTARRAY *pts, POINT2D *point);
index 6171d4b8aa468f8368539fbf6ad1c3c0a9df9f38..446d4af1c093c5badde05b67f063634889846d86 100644 (file)
@@ -818,7 +818,7 @@ CREATE OPERATOR &&& (
 -- Availability: 2.2.0
 CREATE OR REPLACE FUNCTION geometry_distance_centroid_nd(geometry,geometry)
        RETURNS float8
-       AS 'MODULE_PATHNAME', 'gserialized_distance_centroid_nd'
+       AS 'MODULE_PATHNAME', 'gserialized_distance_nd'
        LANGUAGE 'c' IMMUTABLE STRICT;
 
 -- Availability: 2.2.0
@@ -828,19 +828,6 @@ CREATE OPERATOR <<->> (
     COMMUTATOR = '<<->>'
 );
 
--- Availability: 2.2.0
-CREATE OR REPLACE FUNCTION geometry_distance_box_nd(geom1 geometry, geom2 geometry)
-       RETURNS float8
-       AS 'MODULE_PATHNAME' ,'gserialized_distance_box_nd'
-       LANGUAGE 'c' IMMUTABLE STRICT;
-
--- Availability: 2.2.0
-CREATE OPERATOR <<#>> (
-    LEFTARG = geometry, RIGHTARG = geometry,
-    PROCEDURE = geometry_distance_box_nd,
-    COMMUTATOR = '<<#>>'
-);
-
 -- Availability: 2.2.0
 CREATE OR REPLACE FUNCTION geometry_gist_distance_nd(internal,geometry,int4)
        RETURNS float8
@@ -860,8 +847,6 @@ CREATE OPERATOR CLASS gist_geometry_ops_nd
        -- Availability: 2.2.0
        OPERATOR        13       <<->> FOR ORDER BY pg_catalog.float_ops,
        -- Availability: 2.2.0
-       OPERATOR        14       <<#>> FOR ORDER BY pg_catalog.float_ops,
-       -- Availability: 2.2.0
        FUNCTION        8        geometry_gist_distance_nd (internal, geometry, int4),
 #endif
        FUNCTION        1        geometry_gist_consistent_nd (internal, geometry, int4),
index 266f0a7ce0a90846295aa679e14e17a91a61f82f..60197503c2822db25ab35e6805d4992b7c373ed6 100644 (file)
@@ -48,7 +48,6 @@ UPDATE test set the_geom = ST_MakePoint(
     num, -num);
 
 SELECT '<<->> seq', qnodes('select * from test order by the_geom <<->> ST_MakePoint(0,0)');
-SELECT '<<#>> seq', qnodes('select * from test order by the_geom <<#>> ST_MakePoint(0,0)');
 
 CREATE INDEX test_gist_nd on test using gist (the_geom gist_geometry_ops_nd);
 
@@ -78,25 +77,6 @@ SELECT '<<->> res3',num,
   ST_astext(the_geom) from test
   order by the_geom <<->> 'POINT(631 729 25023 -25022)'::geometry LIMIT 1;
 
---  EXT       X                Y          Z        M
--- min    0.0439142361 |   0.0197799355|     1| -50000
--- max  999.955261     | 999.993652    | 50000|     -1
-SELECT '<<#>> idx', qnodes('select * from test order by the_geom <<#>> ST_MakePoint(0,0) LIMIT 1');
-SELECT '<<#>> res1',num,
-  (the_geom <<#>> 'LINESTRING(1000 0,1005 5)'::geometry)::numeric(10,2),
-  ST_astext(the_geom) from test
-  order by the_geom <<#>> 'LINESTRING(1000 0,1005 5)'::geometry LIMIT 1;
--- <<#>> res2|1|2.00|POINT ZM (529.522339 509.260284 1 -1)
-SELECT '<<#>> res2',num,
-  (the_geom <<#>> 'LINESTRING ZM (0 0 -10 -10,1000 1000 -1 -1)'::geometry)::numeric(10,2),
-  ST_astext(the_geom) from test
-  order by the_geom <<#>> 'LINESTRING ZM (0 0 -10 -10,1000 1000 -1 -1)'::geometry LIMIT 1;
--- <<#>> res3|50000|1.00|POINT ZM (912.12323 831.139587 50000 -50000)
-SELECT '<<#>> res3',num,
-  (the_geom <<#>> 'LINESTRING ZM (0 0 1 -60000,1000 1000 50000 -50001)'::geometry)::numeric(10,2),
-  ST_astext(the_geom) from test
-  order by the_geom <<#>> 'LINESTRING ZM (0 0 1 -60000,1000 1000 50000 -50001)'::geometry LIMIT 1;
-
 
 -- Cleanup
 
index 209fcf014770ed98b027905288a7121efde31997..3c9326bdb2125ce8441392e226d8318809cfd53b 100644 (file)
@@ -3,12 +3,7 @@
 <#> idx|Index Scan
 <#> res1|2057|0.83|POINT(999.173279 3.92185807)
 <<->> seq|Seq Scan
-<<#>> seq|Seq Scan
 <<->> idx|Index Scan
 <<->> res1|48589|0.17|POINT ZM (2.33793712 2.44566727 48589 -48589)
 <<->> res2|25025|1.20|POINT ZM (95.6546249 23.0995369 25025 -25025)
 <<->> res3|25023|1.27|POINT ZM (631.060242 729.787354 25023 -25023)
-<<#>> idx|Index Scan
-<<#>> res1|2057|0.83|POINT ZM (999.173279 3.92185807 2057 -2057)
-<<#>> res2|1|2.00|POINT ZM (529.522339 509.260284 1 -1)
-<<#>> res3|50000|1.00|POINT ZM (912.12323 831.139587 50000 -50000)
index 8ca49e32132fb0d2021d1a26d85bbaf28ef309cc..2422dd52a52652308f7c23f0e79afa12fffb7bb9 100644 (file)
@@ -155,25 +155,3 @@ select 'ndcd5', 'POINTZM(1 2 3 4)'::geometry <<->>
 select 'ndcd6', 'POINTZM(9 9 3 4)'::geometry <<->>
                 'POINT(9 8)'::geometry; -- 1, higher dimensions overlapping
 
--- nd box distance  <<#>>
-
-select 'ndbd1', 'LINESTRING(0 0,0 10,10 10)'::geometry <<#>>
-                'LINESTRING(6 2,6 8)'::geometry; -- 0, overlap
-select 'ndbd2', 'LINESTRING(0 0,0 10,10 10)'::geometry <<#>>
-                'LINESTRING(11 0,19 10)'::geometry; -- 1 on the right
-select 'ndbd3', 'LINESTRING(0 0,10 10)'::geometry <<#>>
-                'LINESTRING(-11 0,-2 10)'::geometry; -- 2 on the left
-select 'ndbd4', 'LINESTRING(0 0,10 10)'::geometry <<#>>
-                'LINESTRING(0 13,5 14)'::geometry; -- 3 above
-select 'ndbd5', 'LINESTRING(0 0,10 10)'::geometry <<#>>
-                'LINESTRING(0 -20,5 -4)'::geometry; -- 4 below
-select 'ndbd6', 'LINESTRINGM(0 0 0,1 1 1)'::geometry <<#>>
-                'LINESTRING(0 0,1 1)'::geometry; -- 0 overlap, mixed
-select 'ndbd7', 'LINESTRINGM(0 0 0,1 1 1)'::geometry <<#>>
-                'LINESTRINGM(1 1 2,1 1 3)'::geometry; -- 1
-select 'ndbd8', 'LINESTRINGZ(0 0 0,1 1 1)'::geometry <<#>>
-                'LINESTRINGZ(1 1 3,1 1 5)'::geometry; -- 2
-select 'ndbd9', 'LINESTRINGZ(0 0 0,1 1 1)'::geometry <<#>>
-                'LINESTRINGM(1 1 3,1 1 5)'::geometry; -- 0, overlap, mixed
-select 'ndbd10', 'LINESTRINGZM(0 0 0 0,1 2 3 4)'::geometry <<#>>
-                 'LINESTRINGZM(3 4 5 6,4 5 6 7)'::geometry; -- 4
index f416bf1f0d885cc99662b5fb971284ba4ce86a85..80545921cf61414311981c50f7ec40fea555b0b3 100644 (file)
@@ -62,13 +62,3 @@ ndcd3|5
 ndcd4|5
 ndcd5|2
 ndcd6|1
-ndbd1|0
-ndbd2|1
-ndbd3|2
-ndbd4|3
-ndbd5|4
-ndbd6|0
-ndbd7|1
-ndbd8|2
-ndbd9|0
-ndbd10|4