]> granicus.if.org Git - postgis/commitdiff
Add in ST_DistanceTree for testing purposes. Do not document.
authorPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 3 Jul 2012 18:44:21 +0000 (18:44 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 3 Jul 2012 18:44:21 +0000 (18:44 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@10013 b70326c6-7e19-0410-871a-916f4a2858ee

postgis/geography.sql.in.c
postgis/geography_measurement.c
postgis/geography_measurement_trees.c
postgis/geography_measurement_trees.h

index d257bced2c64ed7ce7dfbbafa0332cead71ce196..47e319b858a63cbc776b844e979be80847e94ebe 100644 (file)
@@ -558,6 +558,17 @@ CREATE OR REPLACE FUNCTION ST_DistanceCached(geography, geography, boolean)
        AS 'SELECT _ST_DistanceCached($1, $2, 0.0, $3)'
        LANGUAGE 'sql' IMMUTABLE STRICT;
 
+CREATE OR REPLACE FUNCTION _ST_DistanceTree(geography, geography, float8, boolean)
+       RETURNS float8
+       AS 'MODULE_PATHNAME','geography_distance_tree'
+       LANGUAGE 'c' IMMUTABLE STRICT
+       COST 100;
+
+CREATE OR REPLACE FUNCTION ST_DistanceTree(geography, geography)
+       RETURNS float8
+       AS 'SELECT _ST_DistanceTree($1, $2, 0.0, true)'
+       LANGUAGE 'sql' IMMUTABLE STRICT;
+
 CREATE OR REPLACE FUNCTION ST_DistanceCached(geography, geography)
        RETURNS float8
        AS 'SELECT _ST_DistanceCached($1, $2, 0.0, true)'
index dc843ac2b745184e6220c62f3df3c247c78e93ab..ae54df620c8cc4a29476e627c5df764326e17dc2 100644 (file)
@@ -29,6 +29,7 @@
 
 Datum geography_distance(PG_FUNCTION_ARGS);
 Datum geography_distance_cached(PG_FUNCTION_ARGS);
+Datum geography_distance_tree(PG_FUNCTION_ARGS);
 Datum geography_dwithin(PG_FUNCTION_ARGS);
 Datum geography_dwithin_cached(PG_FUNCTION_ARGS);
 Datum geography_area(PG_FUNCTION_ARGS);
@@ -229,6 +230,73 @@ Datum geography_dwithin_cached(PG_FUNCTION_ARGS)
 }
 
 
+/*
+** geography_dwithin(GSERIALIZED *g1, GSERIALIZED *g2, double tolerance, boolean use_spheroid)
+** returns double distance in meters
+*/
+PG_FUNCTION_INFO_V1(geography_distance_tree);
+Datum geography_distance_tree(PG_FUNCTION_ARGS)
+{
+       GSERIALIZED *g1 = NULL;
+       GSERIALIZED *g2 = NULL;
+       double tolerance;
+       double distance;
+       bool use_spheroid;
+       SPHEROID s;
+       CIRC_NODE* circ_tree1 = NULL;
+       CIRC_NODE* circ_tree2 = NULL;
+       LWGEOM* lwgeom1 = NULL;
+       LWGEOM* lwgeom2 = NULL;
+       
+
+       /* Get our geometry objects loaded into memory. */
+       g1 = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       g2 = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+
+       /* Read our tolerance value. */
+       tolerance = PG_GETARG_FLOAT8(2);
+
+       /* Read our calculation type. */
+       use_spheroid = PG_GETARG_BOOL(3);
+
+       /* Initialize spheroid */
+       spheroid_init_from_srid(fcinfo, gserialized_get_srid(g1), &s);
+
+       /* Set to sphere if requested */
+       if ( ! use_spheroid )
+               s.a = s.b = s.radius;
+
+       /* Return FALSE on empty arguments. */
+       if ( gserialized_is_empty(g1) || gserialized_is_empty(g2) )
+       {
+               PG_FREE_IF_COPY(g1, 0);
+               PG_FREE_IF_COPY(g2, 1);
+               PG_RETURN_FLOAT8(0.0);
+       }
+
+       lwgeom1 = lwgeom_from_gserialized(g1);
+       lwgeom2 = lwgeom_from_gserialized(g2);
+       circ_tree1 = lwgeom_calculate_circ_tree(lwgeom1);
+       circ_tree2 = lwgeom_calculate_circ_tree(lwgeom2);
+       
+       if ( CircTreePIP(circ_tree1, g1, lwgeom2) || CircTreePIP(circ_tree2, g2, lwgeom1) )
+       {
+               PG_RETURN_BOOL(FALSE);
+       }
+       
+       /* Calculate tree/tree distance */
+       distance = circ_tree_distance_tree(circ_tree1, circ_tree2, &s, tolerance);
+       circ_tree_free(circ_tree1);
+       circ_tree_free(circ_tree2);
+       
+       lwgeom_free(lwgeom1);
+       lwgeom_free(lwgeom2);
+       
+       PG_RETURN_FLOAT8(distance);
+}
+
+
+
 /*
 ** geography_dwithin(GSERIALIZED *g1, GSERIALIZED *g2, double tolerance, boolean use_spheroid)
 ** returns double distance in meters
index bad94e6ed3032667e50c079e25141acbe550321e..93b7c706cd6a70155e05dea2648fd07e60019264 100644 (file)
@@ -76,8 +76,8 @@ GetCircTreeGeomCache(FunctionCallInfoData* fcinfo, const GSERIALIZED* g1, const
        return (CircTreeGeomCache*)GetGeomCache(fcinfo, &CircTreeCacheMethods, g1, g2);
 }
 
-static int
-CircTreePIP(const CircTreeGeomCache* tree_cache, const GSERIALIZED* g, const LWGEOM* lwgeom)
+int
+CircTreePIP(const CIRC_NODE* tree, const GSERIALIZED* g, const LWGEOM* lwgeom)
 {
        int tree_type = gserialized_get_type(g);
        GBOX gbox;
@@ -120,7 +120,7 @@ CircTreePIP(const CircTreeGeomCache* tree_cache, const GSERIALIZED* g, const LWG
                        /* Calculate a definitive outside point */
                        gbox_pt_outside(&gbox, &pt_outside);
                        /* Test the candidate point for strict containment */
-                       return circ_tree_contains_point(tree_cache->index, &pt_inside, &pt_outside, NULL);
+                       return circ_tree_contains_point(tree, &pt_inside, &pt_outside, NULL);
                }
                
        }
@@ -164,7 +164,7 @@ geography_distance_cache(FunctionCallInfoData* fcinfo, const GSERIALIZED* g1, co
                else
                        lwerror("geography_distance_cache failed! This will never happen!");
 
-               if ( LW_TRUE == CircTreePIP(tree_cache, g, lwgeom) )
+               if ( LW_TRUE == CircTreePIP(tree_cache->index, g, lwgeom) )
                {
                        *distance = 0.0;
                        lwgeom_free(lwgeom);
@@ -220,7 +220,7 @@ geography_dwithin_cache(FunctionCallInfoData* fcinfo, const GSERIALIZED* g1, con
                else
                        lwerror("geography_dwithin_cache failed! This will never happen!");
 
-               if ( LW_TRUE == CircTreePIP(tree_cache, g, lwgeom) )
+               if ( LW_TRUE == CircTreePIP(tree_cache->index, g, lwgeom) )
                {
                        *dwithin = LW_TRUE;
                        lwgeom_free(lwgeom);
index 3c7bc240bfd972d243819903e1de8b24d4a90aa8..49fb9abf72d18f83990562083f1ebd7d3c988eec 100644 (file)
@@ -4,3 +4,4 @@
 
 int geography_dwithin_cache(FunctionCallInfoData* fcinfo, const GSERIALIZED* g1, const GSERIALIZED* g2, const SPHEROID* s, double tolerance, int* dwithin);
 int geography_distance_cache(FunctionCallInfoData* fcinfo, const GSERIALIZED* g1, const GSERIALIZED* g2, const SPHEROID* s, double* distance);
+int CircTreePIP(const CIRC_NODE* tree, const GSERIALIZED* g, const LWGEOM* lwgeom);