Commit 6b44574d authored by Paul Ramsey's avatar Paul Ramsey

#3133, add <<->> recheck supporrt and rip out <<#>>


git-svn-id: http://svn.osgeo.org/postgis/trunk@13607 b70326c6-7e19-0410-871a-916f4a2858ee
parent f5747bdb
......@@ -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);
......
......@@ -18,6 +18,7 @@
#include "lwgeom_log.h"
/*------------------------------------------------------------------------------------------------------------
Initializing functions
The functions starting the distance-calculation processses
......
......@@ -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);
}
......
......@@ -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);
......
......@@ -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),
......
......@@ -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
......
......@@ -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)
......@@ -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
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment