]> granicus.if.org Git - postgis/commitdiff
Merge Nicklas Aven's distance spike into trunk. (#63, #231)
authorPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 25 Nov 2009 19:15:57 +0000 (19:15 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 25 Nov 2009 19:15:57 +0000 (19:15 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@4894 b70326c6-7e19-0410-871a-916f4a2858ee

doc/reference_measure.xml
liblwgeom/cunit/cu_measures.c
liblwgeom/cunit/cu_measures.h
liblwgeom/liblwgeom.h
liblwgeom/measures.c
liblwgeom/measures.h [new file with mode: 0644]
postgis/lwgeom_functions_basic.c
postgis/postgis.sql.in.c
postgis/uninstall_postgis.sql.in.c
regress/measures.sql
regress/measures_expected

index 1e27045c47e80eeccb07323925df711847d815e3..1ea8ff6fbded0ef1793dbbd2bd2b0b6b464fd201 100644 (file)
@@ -1248,7 +1248,7 @@ FROM (SELECT
          <refsection>
                <title>See Also</title>
 
-               <para><xref linkend="ST_DWithin"/>, <xref linkend="ST_Distance_Sphere"/>, <xref linkend="ST_Distance_Spheroid"/>, <xref linkend="ST_Max_Distance" />, <xref linkend="ST_Transform" /></para>
+               <para><xref linkend="ST_DWithin"/>, <xref linkend="ST_Distance_Sphere"/>, <xref linkend="ST_Distance_Spheroid"/>, <xref linkend="ST_MaxDistance" />, <xref linkend="ST_Transform" /></para>
          </refsection>
        </refentry>
 
@@ -1332,6 +1332,163 @@ The current implementation supports only vertices as the discrete locations. Thi
          </refsection>
        </refentry>
 
+<refentry id="ST_MaxDistance">
+  <refnamediv>
+    <refname>ST_MaxDistance</refname>
+
+    <refpurpose>Returns the 2-dimensional largest distance between two geometries in
+               projected units.</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+        <funcdef>float <function>ST_MaxDistance</function></funcdef>
+        <paramdef><type>geometry </type> <parameter>g1</parameter></paramdef>
+        <paramdef><type>geometry </type> <parameter>g2</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsection>
+    <title>Description</title>
+
+    <para>Some useful description here.</para>
+
+    <!-- optionally mention that this function uses indexes if appropriate -->
+    <note>
+      <para>Returns the 2-dimensional maximum distance between two linestrings in
+               projected units. If g1 and g2 is the same geometry the function will return the distance between
+               the two vertices most far from each other in that geometry.</para>
+    </note>
+
+       <para>Availability: Postgis 1.5</para>
+  </refsection>
+  <refsection>
+    <title>Examples</title>
+
+               <programlisting>postgis=# SELECT ST_MaxDistance('POINT(0 0)'::geometry, 'LINESTRING ( 2 0, 0 2 )'::geometry);
+   st_maxdistance
+-----------------
+ 2
+(1 row)
+
+postgis=# SELECT ST_MaxDistance('POINT(0 0)'::geometry, 'LINESTRING ( 2 2, 2 2 )'::geometry);
+  st_maxdistance  
+------------------
+ 2.82842712474619
+(1 row)</programlisting>
+  </refsection>
+
+  <!-- Optionally add a "See Also" section -->
+  <refsection>
+    <title>See Also</title>
+<para><xref linkend="ST_Distance"/><xref linkend="ST_LongestLine"/></para>
+  </refsection>
+</refentry>
+
+       <refentry id="ST_ShortestLine">
+         <refnamediv>
+               <refname>ST_ShortestLine</refname>
+
+               <refpurpose>Returns the 2-dimensional shortest line between two geometries</refpurpose>
+         </refnamediv>
+
+         <refsynopsisdiv>
+               <funcsynopsis>
+                 <funcprototype>
+                       <funcdef>geometry <function>ST_ShortestLine</function></funcdef>
+
+                       <paramdef><type>geometry </type>
+                       <parameter>g1</parameter></paramdef>
+
+                       <paramdef><type>geometry </type>
+                       <parameter>g2</parameter></paramdef>
+                 </funcprototype>
+               </funcsynopsis>
+         </refsynopsisdiv>
+
+         <refsection>
+               <title>Description</title>
+
+               <para>Returns the 2-dimensional shortest line between two geometries. The function will
+               only return the first shortest line if more than one, that the function finds.
+               If g1 and g2 intersects in just one point the function will return a line with both start
+               and end in that intersection-point.
+               If g1 and g2 are intersecting with more than one point the function will return a line with start
+               and end in the same point but it can be any of the intersecting points.
+               The line returned will always start in g1 and end in g2.
+               The length of the line this function returns will always be the same as st_distance returns for g1 and g2.      
+               </para>
+
+         </refsection>
+
+         <refsection>
+               <title>Examples</title>
+
+               <programlisting>postgis=# SELECT astext(st_shortestline('POINT(0 0)'::geometry, 'LINESTRING ( 2 0, 0 2 )'::geometry)) as st_shortestline;
+   st_shortestline
+-----------------
+ LINESTRING(0 0,1 1)
+(1 row)</programlisting>
+         </refsection>
+
+         <refsection>
+               <title>See Also</title>
+
+               <para><xref linkend="ST_Distance"/><xref linkend="ST_LongestLine"/></para>
+         </refsection>
+       </refentry>
+       
+               <refentry id="ST_LongestLine">
+         <refnamediv>
+               <refname>ST_LongestLine</refname>
+
+               <refpurpose>Returns the 2-dimensional longest line points of two geometries.
+               The function will only return the first longest line if more than one, that the function finds.
+               The line returned will always start in g1 and end in g2.
+               The length of the line this function returns will always be the same as st_maxdistance returns for g1 and g2.</refpurpose>
+         </refnamediv>
+
+         <refsynopsisdiv>
+               <funcsynopsis>
+                 <funcprototype>
+                       <funcdef>geometry <function>ST_LongestLine</function></funcdef>
+
+                       <paramdef><type>geometry </type>
+                       <parameter>g1</parameter></paramdef>
+
+                       <paramdef><type>geometry </type>
+                       <parameter>g2</parameter></paramdef>
+                 </funcprototype>
+               </funcsynopsis>
+         </refsynopsisdiv>
+
+         <refsection>
+               <title>Description</title>
+
+               <para>Returns the 2-dimensional longest line between the points of two geometries. 
+               </para>
+
+         </refsection>
+
+         <refsection>
+               <title>Examples</title>
+
+               <programlisting>postgis=# SELECT astext(st_longestline('POINT(0 0)'::geometry, 'LINESTRING ( 2 0, 0 2 )'::geometry)) as st_longestline;
+   st_longestline
+-----------------
+ LINESTRING(0 0,2 0)
+(1 row)</programlisting>
+         </refsection>
+
+         <refsection>
+               <title>See Also</title>
+
+               <para><xref linkend="ST_MaxDistance"/><xref linkend="ST_ShortestLine"/></para>
+         </refsection>
+       </refentry>
+
        <refentry id="ST_Distance_Sphere">
          <refnamediv>
                <refname>ST_Distance_Sphere</refname>
@@ -1565,6 +1722,127 @@ SELECT s.gid, s.school_name
          </refsection>
        </refentry>
 
+       <refentry id="ST_DFullyWithin">
+         <refnamediv>
+               <refname>ST_DFullyWithin</refname>
+
+               <refpurpose>Returns true if all of the geometries are within the specified
+               distance of one another</refpurpose>
+         </refnamediv>
+
+         <refsynopsisdiv>
+               <funcsynopsis>
+                 <funcprototype>
+                       <funcdef>boolean <function>ST_DFullyWithin</function></funcdef>
+
+                       <paramdef><type>geometry </type>
+                       <parameter>g1</parameter></paramdef>
+
+                       <paramdef><type>geometry </type>
+                       <parameter>g2</parameter></paramdef>
+
+                       <paramdef><type>double precision </type>
+                       <parameter>distance</parameter></paramdef>
+                 </funcprototype>
+               </funcsynopsis>
+         </refsynopsisdiv>
+
+         <refsection>
+               <title>Description</title>
+
+               <para>Returns true if the geometries is fully within the specified distance
+               of one another. The distance is specified in units defined by the
+               spatial reference system of the geometries.  For this function to make
+               sense, the source geometries must both be of the same coordinate projection,
+               having the same SRID.</para>
+
+               <note>
+                 <para>This function call will automatically include a bounding box
+                 comparison that will make use of any indexes that are available on
+                 the geometries.</para>
+               </note>
+
+
+         </refsection>
+
+         <refsection>
+               <title>Examples</title>
+               <programlisting>postgis=# SELECT ST_DFullyWithin(geom_a, geom_b, 10) as DFullyWithin10, ST_DWithin(geom_a, geom_b, 10) as DWithin10, ST_DFullyWithin(geom_a, geom_b, 20) as DFullyWithin20 from 
+               (select ST_GeomFromText('POINT(1 1)') as geom_a,ST_GeomFromText('LINESTRING(1 5, 2 7, 1 9, 14 12)') as geom_b) t1;
+   
+-----------------
+ DFullyWithin10 | DWithin10 | DFullyWithin20 |
+---------------+----------+---------------+
+ f             | t        | t             |  </programlisting>
+         </refsection>
+
+         <refsection>
+               <title>See Also</title>
+
+               <para><xref linkend="ST_MaxDistance"/>, <xref linkend="ST_DWithin"/></para>
+         </refsection>
+       </refentry>
+       <refentry id="ST_DFullyWithin">
+         <refnamediv>
+               <refname>ST_DFullyWithin</refname>
+
+               <refpurpose>Returns true if all of the geometries are within the specified
+               distance of one another</refpurpose>
+         </refnamediv>
+
+         <refsynopsisdiv>
+               <funcsynopsis>
+                 <funcprototype>
+                       <funcdef>boolean <function>ST_DFullyWithin</function></funcdef>
+
+                       <paramdef><type>geometry </type>
+                       <parameter>g1</parameter></paramdef>
+
+                       <paramdef><type>geometry </type>
+                       <parameter>g2</parameter></paramdef>
+
+                       <paramdef><type>double precision </type>
+                       <parameter>distance</parameter></paramdef>
+                 </funcprototype>
+               </funcsynopsis>
+         </refsynopsisdiv>
+
+         <refsection>
+               <title>Description</title>
+
+               <para>Returns true if the geometries is fully within the specified distance
+               of one another. The distance is specified in units defined by the
+               spatial reference system of the geometries.  For this function to make
+               sense, the source geometries must both be of the same coordinate projection,
+               having the same SRID.</para>
+
+               <note>
+                 <para>This function call will automatically include a bounding box
+                 comparison that will make use of any indexes that are available on
+                 the geometries.</para>
+               </note>
+
+
+         </refsection>
+
+         <refsection>
+               <title>Examples</title>
+               <programlisting>postgis=# SELECT ST_DFullyWithin(geom_a, geom_b, 10) as DFullyWithin10, ST_DWithin(geom_a, geom_b, 10) as DWithin10, ST_DFullyWithin(geom_a, geom_b, 20) as DFullyWithin20 from 
+               (select ST_GeomFromText('POINT(1 1)') as geom_a,ST_GeomFromText('LINESTRING(1 5, 2 7, 1 9, 14 12)') as geom_b) t1;
+   
+-----------------
+ DFullyWithin10 | DWithin10 | DFullyWithin20 |
+---------------+----------+---------------+
+ f             | t        | t             |  </programlisting>
+         </refsection>
+
+         <refsection>
+               <title>See Also</title>
+
+               <para><xref linkend="ST_MaxDistance"/>, <xref linkend="ST_DWithin"/></para>
+         </refsection>
+       </refentry>
+       
        <refentry id="ST_Equals">
          <refnamediv>
                <refname>ST_Equals</refname>
@@ -2141,53 +2419,6 @@ CAST('SPHEROID["GRS_1980",6378137,298.257222101]' As spheroid) As sph_m)  as foo
          </refsection>
        </refentry>
 
-
-
-
-       <refentry id="ST_Max_Distance">
-         <refnamediv>
-               <refname>ST_Max_Distance</refname>
-
-               <refpurpose>Returns the 2-dimensional largest distance between two geometries in
-               projected units.</refpurpose>
-         </refnamediv>
-
-         <refsynopsisdiv>
-               <funcsynopsis>
-                 <funcprototype>
-                       <funcdef>float <function>ST_Max_Distance</function></funcdef>
-
-                       <paramdef><type>geometry </type>
-                       <parameter>g1</parameter></paramdef>
-
-                       <paramdef><type>geometry </type>
-                       <parameter>g2</parameter></paramdef>
-                 </funcprototype>
-               </funcsynopsis>
-         </refsynopsisdiv>
-
-         <refsection>
-               <title>Description</title>
-
-               <para>Returns the 2-dimensional maximum cartesian distance between two linestrings in
-               projected units.</para>
-
-         </refsection>
-
-         <refsection>
-               <title>Examples</title>
-
-               <programlisting>--ALL EXAMPLES current throw NOT YET IMPLEMENTED</programlisting>
-         </refsection>
-
-         <refsection>
-               <title>See Also</title>
-
-               <para><xref linkend="ST_Distance"/></para>
-         </refsection>
-       </refentry>
-
-
        <refentry id="ST_OrderingEquals">
          <refnamediv>
                <refname>ST_OrderingEquals</refname>
index 3106c275c6561810951e77d8f59096bc87187291..bbf3b24a06d6bf22afb46ce9ebb081e74b560f64 100644 (file)
@@ -26,7 +26,7 @@ CU_pSuite register_measures_suite(void)
        }
 
        if (
-           (NULL == CU_add_test(pSuite, "test_mindistance2d_recursive_tolerance()", test_mindistance2d_recursive_tolerance))
+           (NULL == CU_add_test(pSuite, "test_mindistance2d_tolerance()", test_mindistance2d_tolerance))
        )
        {
                CU_cleanup_registry();
@@ -53,7 +53,7 @@ int clean_measures_suite(void)
        return 0;
 }
 
-void test_mindistance2d_recursive_tolerance(void)
+void test_mindistance2d_tolerance(void)
 {
        LWGEOM_PARSER_RESULT gp1;
        LWGEOM_PARSER_RESULT gp2;
@@ -65,7 +65,7 @@ void test_mindistance2d_recursive_tolerance(void)
        */
        result1 = serialized_lwgeom_from_ewkt(&gp1, "POINT(0 0)", PARSER_CHECK_NONE);
        result2 = serialized_lwgeom_from_ewkt(&gp2, "MULTIPOINT(0 1.5,0 2,0 2.5)", PARSER_CHECK_NONE);
-       distance = lwgeom_mindistance2d_recursive_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
+       distance = lwgeom_mindistance2d_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
        //printf("\ndistance #1 = %g\n",distance);
        CU_ASSERT_EQUAL(distance, 1.5);
        free(gp1.serialized_lwgeom);
@@ -76,7 +76,7 @@ void test_mindistance2d_recursive_tolerance(void)
        */
        result1 = serialized_lwgeom_from_ewkt(&gp1, "POINT(0 0)", PARSER_CHECK_NONE);
        result2 = serialized_lwgeom_from_ewkt(&gp2, "GEOMETRYCOLLECTION(POINT(3 4))", PARSER_CHECK_NONE);
-       distance = lwgeom_mindistance2d_recursive_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
+       distance = lwgeom_mindistance2d_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
        //printf("distance #2 = %g\n",distance);
        CU_ASSERT_EQUAL(distance, 5.0);
        free(gp1.serialized_lwgeom);
@@ -87,7 +87,7 @@ void test_mindistance2d_recursive_tolerance(void)
        */
        result1 = serialized_lwgeom_from_ewkt(&gp1, "POINT(0 0)", PARSER_CHECK_NONE);
        result2 = serialized_lwgeom_from_ewkt(&gp2, "GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(3 4)))", PARSER_CHECK_NONE);
-       distance = lwgeom_mindistance2d_recursive_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
+       distance = lwgeom_mindistance2d_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
        //printf("distance #3 = %g\n",distance);
        CU_ASSERT_EQUAL(distance, 5.0);
        free(gp1.serialized_lwgeom);
@@ -98,7 +98,7 @@ void test_mindistance2d_recursive_tolerance(void)
        */
        result1 = serialized_lwgeom_from_ewkt(&gp1, "POINT(0 0)", PARSER_CHECK_NONE);
        result2 = serialized_lwgeom_from_ewkt(&gp2, "GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(3 4))))", PARSER_CHECK_NONE);
-       distance = lwgeom_mindistance2d_recursive_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
+       distance = lwgeom_mindistance2d_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
        //printf("distance #4 = %g\n",distance);
        CU_ASSERT_EQUAL(distance, 5.0);
        free(gp1.serialized_lwgeom);
@@ -109,7 +109,7 @@ void test_mindistance2d_recursive_tolerance(void)
        */
        result1 = serialized_lwgeom_from_ewkt(&gp1, "POINT(0 0)", PARSER_CHECK_NONE);
        result2 = serialized_lwgeom_from_ewkt(&gp2, "GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(MULTIPOINT(3 4))))", PARSER_CHECK_NONE);
-       distance = lwgeom_mindistance2d_recursive_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
+       distance = lwgeom_mindistance2d_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
        //printf("distance #5 = %g\n",distance);
        CU_ASSERT_EQUAL(distance, 5.0);
        free(gp1.serialized_lwgeom);
@@ -120,7 +120,7 @@ void test_mindistance2d_recursive_tolerance(void)
        */
        result1 = serialized_lwgeom_from_ewkt(&gp1, "GEOMETRYCOLLECTION(POINT(0 0))", PARSER_CHECK_NONE);
        result2 = serialized_lwgeom_from_ewkt(&gp2, "GEOMETRYCOLLECTION(POINT(3 4))", PARSER_CHECK_NONE);
-       distance = lwgeom_mindistance2d_recursive_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
+       distance = lwgeom_mindistance2d_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
        //printf("distance #6 = %g\n",distance);
        CU_ASSERT_EQUAL(distance, 5.0);
        free(gp1.serialized_lwgeom);
@@ -131,7 +131,7 @@ void test_mindistance2d_recursive_tolerance(void)
        */
        result1 = serialized_lwgeom_from_ewkt(&gp1, "GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(0 0)))", PARSER_CHECK_NONE);
        result2 = serialized_lwgeom_from_ewkt(&gp2, "GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(3 4)))", PARSER_CHECK_NONE);
-       distance = lwgeom_mindistance2d_recursive_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
+       distance = lwgeom_mindistance2d_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
        //printf("distance #7 = %g\n",distance);
        CU_ASSERT_EQUAL(distance, 5.0);
        free(gp1.serialized_lwgeom);
@@ -142,7 +142,7 @@ void test_mindistance2d_recursive_tolerance(void)
        */
        result1 = serialized_lwgeom_from_ewkt(&gp1, "GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(MULTIPOINT(0 0)))", PARSER_CHECK_NONE);
        result2 = serialized_lwgeom_from_ewkt(&gp2, "GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(MULTIPOINT(3 4)))", PARSER_CHECK_NONE);
-       distance = lwgeom_mindistance2d_recursive_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
+       distance = lwgeom_mindistance2d_tolerance(gp1.serialized_lwgeom, gp2.serialized_lwgeom, 0.0);
        //printf("distance #8 = %g\n",distance);
        CU_ASSERT_EQUAL(distance, 5.0);
        free(gp1.serialized_lwgeom);
index 3590b9a64a1be5c3f1ecc29acb8a4c6f3bf9d065..1a8b4f49e21c95b2cd5f1447a85e4145bad651bc 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "liblwgeom.h"
 #include "cu_tester.h"
+#include "measures.h"
 
 /***********************************************************************
 ** for Computational Geometry Suite
@@ -25,4 +26,4 @@
 
 
 /* Test functions */
-void test_mindistance2d_recursive_tolerance(void);
+void test_mindistance2d_tolerance(void);
index 4962699253a603d7501592960e4673de1d1eb966..20ea1add88c8e83b0035b9289a8d6f50562be718 100644 (file)
@@ -641,7 +641,6 @@ extern int ptarray_compute_box3d_p(const POINTARRAY *pa, BOX3D *out);
  */
 extern int pointArray_ptsize(const POINTARRAY *pa);
 
-
 #define        POINTTYPE       1
 #define        LINETYPE        2
 #define        POLYGONTYPE     3
@@ -1187,8 +1186,19 @@ extern float nextafterf_custom(float x, float y);
 #define LW_MIN(a,b) ((a) <= (b) ? (a) : (b))
 #define LW_ABS(a)   ((a) <     (0) ? -(a) : (a))
 
-
+/* for the measure functions*/
+#define DIST2D_MAX             -1
+#define DIST2D_MIN             1
 /* general utilities */
+extern double distance2d_pt_pt(POINT2D *p1, POINT2D *p2);
+extern double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B);
+extern LWGEOM *lw_dist2d_distancepoint(uchar *lw1, uchar *lw2,int srid,int mode);
+extern LWGEOM *lw_dist2d_distanceline(uchar *lw1, uchar *lw2,int srid,int mode);
+extern double lwgeom_mindistance2d(uchar *lw1, uchar *lw2);
+extern double lwgeom_mindistance2d_tolerance(uchar *lw1, uchar *lw2, double tolerance);
+extern double lwgeom_maxdistance2d(uchar *lw1, uchar *lw2);
+extern double lwgeom_maxdistance2d_tolerance(uchar *lw1, uchar *lw2, double tolerance);
 extern double lwgeom_polygon_area(LWPOLY *poly);
 extern double lwgeom_polygon_perimeter(LWPOLY *poly);
 extern double lwgeom_polygon_perimeter2d(LWPOLY *poly);
@@ -1198,23 +1208,9 @@ extern void lwgeom_force2d_recursive(uchar *serialized, uchar *optr, size_t *ret
 extern void lwgeom_force3dz_recursive(uchar *serialized, uchar *optr, size_t *retsize);
 extern void lwgeom_force3dm_recursive(uchar *serialized, uchar *optr, size_t *retsize);
 extern void lwgeom_force4d_recursive(uchar *serialized, uchar *optr, size_t *retsize);
-extern double distance2d_pt_pt(POINT2D *p1, POINT2D *p2);
-extern double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B);
-extern double distance2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D);
-extern double distance2d_pt_ptarray(POINT2D *p, POINTARRAY *pa);
-extern double distance2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2);
 extern int pt_in_ring_2d(POINT2D *p, POINTARRAY *ring);
 extern int pt_in_poly_2d(POINT2D *p, LWPOLY *poly);
-extern double distance2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly);
-extern double distance2d_point_point(LWPOINT *point1, LWPOINT *point2);
-extern double distance2d_point_line(LWPOINT *point, LWLINE *line);
-extern double distance2d_line_line(LWLINE *line1, LWLINE *line2);
-extern double distance2d_point_poly(LWPOINT *point, LWPOLY *poly);
-extern double distance2d_poly_poly(LWPOLY *poly1, LWPOLY *poly2);
-extern double distance2d_line_poly(LWLINE *line, LWPOLY *poly);
 extern int azimuth_pt_pt(POINT2D *p1, POINT2D *p2, double *ret);
-extern double lwgeom_mindistance2d_recursive(uchar *lw1, uchar *lw2);
-extern double lwgeom_mindistance2d_recursive_tolerance(uchar *lw1, uchar *lw2, double tolerance);
 extern int lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad);
 extern char ptarray_isccw(const POINTARRAY *pa);
 extern void lwgeom_reverse(LWGEOM *lwgeom);
index 6f8ff375b7deb0b2c6a3648e44e4bcf334b72c2d..3d5778131f1cbf5f06823e56a5a45c10b72940c3 100644 (file)
@@ -1,3 +1,4 @@
+
 /**********************************************************************
  * $Id$
  *
  *
  **********************************************************************/
 
-#include <math.h>
-#include <string.h>
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "measures.h"
+
+
+/*------------------------------------------------------------------------------------------------------------
+Initializing functions
+The functions starting the distance-calculation processses
+--------------------------------------------------------------------------------------------------------------*/
+
+/**
+Function initializing shortestline and longestline calculations.
+*/
+LWGEOM *
+lw_dist2d_distanceline(uchar *lw1, uchar *lw2,int srid,int mode)
+{
+       LWDEBUG(2, "lw_dist2d_distanceline is called");
+       double x1,x2,y1,y2;
+       LWPOINT *point1, *point2;
+       double initdistance = ( mode == DIST2D_MIN ? MAXFLOAT : -1.0);
+       DISTPTS thedl;
+       thedl.mode = mode;
+       thedl.distance = initdistance;
+       thedl.tolerance = 0.0;
+
+       LWPOINT *lwpoints[2];
+       LWGEOM *result;
+
+       if (!lw_dist2d_comp( lw1,lw2,&thedl))
+       {
+       /*should never get here. all cases ought to be error handled earlier*/
+               lwerror("Some unspecified error.");
+               result =(LWGEOM *)lwcollection_construct_empty(srid, 0, 0);
+       }
+
+       /*if thedl.distance is unchanged there where only empty geometries input*/
+       if (thedl.distance == initdistance)
+       {
+               LWDEBUG(3, "didn't find geometries to measure between, returning null");
+               result =(LWGEOM *)lwcollection_construct_empty(srid, 0, 0);
+       }
+       else
+       {
+               x1=thedl.p1.x;
+               y1=thedl.p1.y;
+               x2=thedl.p2.x;
+               y2=thedl.p2.y;
+
+               point1 = make_lwpoint2d(srid, x1, y1);
+               point2 = make_lwpoint2d(srid, x2, y2);
+
+               lwpoints[0] = make_lwpoint2d(srid, x1, y1);
+               lwpoints[1] = make_lwpoint2d(srid, x2, y2);
+
+               result = (LWGEOM *)lwline_from_lwpointarray(srid, 2, lwpoints);
+       }
+       return result;
+}
+
+/**
+Function initializing closestpoint calculations.
+*/
+LWGEOM *
+lw_dist2d_distancepoint(uchar *lw1, uchar *lw2,int srid,int mode)
+{
+       LWDEBUG(2, "lw_dist2d_distancepoint is called");
+       double x,y;
+       DISTPTS thedl;
+       double initdistance = MAXFLOAT;
+
+       thedl.mode = mode;
+       thedl.distance= initdistance;
+       thedl.tolerance = 0;
+
+       LWGEOM *result;
+
+       if (!lw_dist2d_comp( lw1,lw2,&thedl))
+       {
+       /*should never get here. all cases ought to be error handled earlier*/
+       lwerror("Some unspecified error.");
+       result =(LWGEOM *)lwcollection_construct_empty(srid, 0, 0);
+       }
+       if (thedl.distance == initdistance)
+       {
+               LWDEBUG(3, "didn't find geometries to measure between, returning null");
+               result =(LWGEOM *)lwcollection_construct_empty(srid, 0, 0);
+       }
+       else
+       {
+               x=thedl.p1.x;
+               y=thedl.p1.y;
+               result = (LWGEOM *)make_lwpoint2d(srid, x, y);
+       }
+       return result;
+}
+
+
+/**
+Function initialazing max distance calculation
+*/
+double
+lwgeom_maxdistance2d(uchar *lw1, uchar *lw2)
+{
+       LWDEBUG(2, "lwgeom_maxdistance2d is called");
+
+       return lwgeom_maxdistance2d_tolerance( lw1, lw2, 0.0 );
+}
+
+/**
+Function handling max distance calculations and dfyllywithin calculations.
+The difference is just the tolerance.
+*/
+double
+lwgeom_maxdistance2d_tolerance(uchar *lw1, uchar *lw2, double tolerance)
+{
+       LWDEBUG(2, "lwgeom_maxdistance2d_tolerance is called");
+       /*double thedist;*/
+       DISTPTS thedl;
+       thedl.mode = DIST2D_MAX;
+       thedl.distance= -1;
+       thedl.tolerance = tolerance;
+       if (lw_dist2d_comp( lw1,lw2,&thedl))
+       {
+               return thedl.distance;
+       }
+       /*should never get here. all cases ought to be error handled earlier*/
+       lwerror("Some unspecified error.");
+       return -1;
+}
+
+/**
+       Function initialazing min distance calculation
+*/
+double
+lwgeom_mindistance2d(uchar *lw1, uchar *lw2)
+{
+       LWDEBUG(2, "lwgeom_mindistance2d is called");
+       return lwgeom_mindistance2d_tolerance( lw1, lw2, 0.0 );
+}
+
+/**
+       Function handling min distance calculations and dwithin calculations.
+       The difference is just the tolerance.
+*/
+double
+lwgeom_mindistance2d_tolerance(uchar *lw1, uchar *lw2, double tolerance)
+{
+       LWDEBUG(2, "lwgeom_mindistance2d_tolerance is called");
+       DISTPTS thedl;
+       thedl.mode = DIST2D_MIN;
+       thedl.distance= MAXFLOAT;
+       thedl.tolerance = tolerance;
+       if (lw_dist2d_comp( lw1,lw2,&thedl))
+       {
+               return thedl.distance;
+       }
+       /*should never get here. all cases ought to be error handled earlier*/
+       lwerror("Some unspecified error.");
+       return MAXFLOAT;
+}
+
+
+/*------------------------------------------------------------------------------------------------------------
+End of Initializing functions
+--------------------------------------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------------------------------------
+Preprocessing functions
+Functions preparing geometries for distance-calculations
+--------------------------------------------------------------------------------------------------------------*/
+
+/**
+       This function just deserializes geometries
+       Bboxes is not checked here since it is the subgeometries
+       bboxes we will use anyway.
+*/
+int
+lw_dist2d_comp(uchar *lw1, uchar *lw2, DISTPTS *dl)
+{
+       LWDEBUG(2, "lw_dist2d_comp is called");
+
+       LWGEOM *lwg1 = lwgeom_deserialize(lw1);
+       LWGEOM *lwg2 = lwgeom_deserialize(lw2);
+
+       return lw_dist2d_recursive      ((LWCOLLECTION*) lwg1,(LWCOLLECTION*) lwg2, dl);
+}
+
+/**
+This is a recursive function delivering every possible combinatin of subgeometries
+*/
+int lw_dist2d_recursive(const LWCOLLECTION * lwg1,const LWCOLLECTION * lwg2,DISTPTS *dl)
+{
+       LWDEBUGF(2, "lw_dist2d_comp is called with type1=%d, type2=%d", TYPE_GETTYPE(lwg1->type), TYPE_GETTYPE(lwg2->type));
+       /*If empty gemetry, return. True here only means continue searching. False would have stoped the process
+       if (lwgeom_is_empty(lwg1)||lwgeom_is_empty(lwg2)) return LW_TRUE;               moved down*/
+
+       int i, j;
+       int n1=1;
+       int n2=1;;
+       LWGEOM *g1, *g2;
+
+       if (lwgeom_is_collection(TYPE_GETTYPE(lwg1->type)))
+       {
+               LWDEBUG(3, "First geometry is collection");
+               n1=lwg1->ngeoms;
+       }
+       if (lwgeom_is_collection(TYPE_GETTYPE(lwg2->type)))
+       {
+               LWDEBUG(3, "Second geometry is collection");
+               n2=lwg2->ngeoms;
+       }
+
+       for ( i = 0; i < n1; i++ )
+       {
+
+               if (lwgeom_is_collection(TYPE_GETTYPE(lwg1->type)))
+               {
+                       g1=lwg1->geoms[i];
+               }
+               else
+               {
+                       g1=(LWGEOM*)lwg1;
+               }
+
+               if (lwgeom_is_empty(g1)) return LW_TRUE;
+
+               if (lwgeom_is_collection(TYPE_GETTYPE(g1->type)))
+               {
+                       LWDEBUG(3, "Found collection inside first geometry collection, recursing");
+                       if (!lw_dist2d_recursive((LWCOLLECTION*)g1, (LWCOLLECTION*)lwg2, dl)) return LW_FALSE;
+                       continue;
+               }
+               for ( j = 0; j < n2; j++ )
+               {
+                       if (lwgeom_is_collection(TYPE_GETTYPE(lwg2->type)))
+                       {
+                               g2=lwg2->geoms[j];
+                       }
+                       else
+                       {
+                               g2=(LWGEOM*)lwg2;
+                       }
+                       if (lwgeom_is_collection(TYPE_GETTYPE(g2->type)))
+                       {
+                               LWDEBUG(3, "Found collection inside second geometry collection, recursing");
+                               if (!lw_dist2d_recursive((LWCOLLECTION*) g1, (LWCOLLECTION*)g2, dl)) return LW_FALSE;
+                               continue;
+                       }
+
+                       if ( ! g1->bbox )
+                       {
+                               g1->bbox = lwgeom_compute_box2d(g1);
+                       }
+                       if ( ! g2->bbox )
+                       {
+                               g2->bbox = lwgeom_compute_box2d(g2);
+                       }
+                       /*If one of geometries is empty, return. True here only means continue searching. False would have stoped the process*/
+                       if (lwgeom_is_empty(g1)||lwgeom_is_empty(g2)) return LW_TRUE;
+
+                       if ((dl->mode==DIST2D_MAX)||(TYPE_GETTYPE(g1->type)==POINTTYPE) ||(TYPE_GETTYPE(g2->type)==POINTTYPE)||lw_dist2d_check_overlap(g1, g2))
+                       {
+                               if (!lw_dist2d_distribute_bruteforce(g1, g2, dl)) return LW_FALSE;
+                               if (dl->distance<=dl->tolerance && dl->mode == DIST2D_MIN) return LW_TRUE; /*just a check if  the answer is already given*/
+                       }
+                       else
+                       {
+                               if (!lw_dist2d_distribute_fast(g1, g2, dl)) return LW_FALSE;
+                       }
+               }
+       }
+       return LW_TRUE;
+}
+
+
+
+/**
+
+This function distributes the "old-type" brut-force tasks depending on type
+*/
+int
+lw_dist2d_distribute_bruteforce(LWGEOM *lwg1, LWGEOM *lwg2, DISTPTS *dl)
+{
+       LWDEBUGF(2, "lw_dist2d_distribute_bruteforce is called with typ1=%d, type2=%d", TYPE_GETTYPE(lwg1->type), TYPE_GETTYPE(lwg2->type));
+
+       int     t1 = TYPE_GETTYPE(lwg1->type);
+       int     t2 = TYPE_GETTYPE(lwg2->type);
+
+
+       if  ( t1 == POINTTYPE )
+       {
+               if  ( t2 == POINTTYPE )
+               {
+                       dl->twisted=1;
+                       return lw_dist2d_point_point((LWPOINT *)lwg1, (LWPOINT *)lwg2, dl);
+               }
+               else if  ( t2 == LINETYPE )
+               {
+                       dl->twisted=1;
+                       return lw_dist2d_point_line((LWPOINT *)lwg1, (LWLINE *)lwg2, dl);
+               }
+               else if  ( t2 == POLYGONTYPE )
+               {
+                       dl->twisted=1;
+                       return lw_dist2d_point_poly((LWPOINT *)lwg1, (LWPOLY *)lwg2,dl);
+               }
+               else
+               {
+                       lwerror("Unsupported geometry type: %s", lwgeom_typename(t2));
+                       return LW_FALSE;
+               }
+       }
+       else if ( t1 == LINETYPE )
+       {
+               if ( t2 == POINTTYPE )
+               {
+                       dl->twisted=(-1);
+                       return lw_dist2d_point_line((LWPOINT *)lwg2,(LWLINE *)lwg1,dl);
+               }
+               else if ( t2 == LINETYPE )
+               {
+                       dl->twisted=1;
+                       /*lwnotice("start line");*/
+                       return lw_dist2d_line_line((LWLINE *)lwg1,(LWLINE *)lwg2,dl);
+               }
+               else if ( t2 == POLYGONTYPE )
+               {
+                       dl->twisted=1;
+                       return lw_dist2d_line_poly((LWLINE *)lwg1,(LWPOLY *)lwg2,dl);
+               }
+               else
+               {
+                       lwerror("Unsupported geometry type: %s", lwgeom_typename(t2));
+                       return LW_FALSE;
+               }
+       }
+       else if ( t1 == POLYGONTYPE )
+       {
+               if ( t2 == POLYGONTYPE )
+               {
+                       dl->twisted=(1);
+                       return lw_dist2d_poly_poly((LWPOLY *)lwg1,(LWPOLY *)lwg2,dl);
+               }
+               else if ( t2 == POINTTYPE )
+               {
+                       dl->twisted=(-1);
+                       return lw_dist2d_point_poly((LWPOINT *)lwg2,  (LWPOLY *)lwg1, dl);
+               }
+               else if ( t2 == LINETYPE )
+               {
+                       dl->twisted=(-1);
+                       return lw_dist2d_line_poly((LWLINE *)lwg2,(LWPOLY *)lwg1,dl);
+               }
+               else
+               {
+                       lwerror("Unsupported geometry type: %s", lwgeom_typename(t2));
+                       return LW_FALSE;
+               }
+       }
+       else
+       {
+               lwerror("Unsupported geometry type: %s", lwgeom_typename(t1));
+               return LW_FALSE;
+       }
+       /*You shouldn't being able to get here*/
+       lwerror("unspecified error in function lw_dist2d_distribute_bruteforce");
+       return LW_FALSE;
+}
+
+/**
+
+We have to check for overlapping bboxes
+*/
+int
+lw_dist2d_check_overlap(LWGEOM *lwg1,LWGEOM *lwg2)
+{
+       LWDEBUG(2, "lw_dist2d_check_overlap is called");
+       if ( ! lwg1->bbox )
+               lwg1->bbox = lwgeom_compute_box2d(lwg1);
+       if ( ! lwg2->bbox )
+               lwg2->bbox = lwgeom_compute_box2d(lwg2);
+
+       /*Check if the geometries intersect.
+       */
+       if ((lwg1->bbox->xmax<lwg2->bbox->xmin||lwg1->bbox->xmin>lwg2->bbox->xmax||lwg1->bbox->ymax<lwg2->bbox->ymin||lwg1->bbox->ymin>lwg2->bbox->ymax))
+       {
+               LWDEBUG(3, "geometries bboxes did not overlap");
+               return LW_FALSE;
+       }
+       LWDEBUG(3, "geometries bboxes overlap");
+       return LW_TRUE;
+}
+
+/**
+
+Here the geometries are distributed for the new faster distance-calculations
+*/
+int
+lw_dist2d_distribute_fast(LWGEOM *lwg1, LWGEOM *lwg2, DISTPTS *dl)
+{
+       LWDEBUGF(2, "lw_dist2d_distribute_fast is called with typ1=%d, type2=%d", TYPE_GETTYPE(lwg1->type), TYPE_GETTYPE(lwg2->type));
+
+       POINTARRAY *pa1, *pa2;
+       int     type1 = TYPE_GETTYPE(lwg1->type);
+       int     type2 = TYPE_GETTYPE(lwg2->type);
+
+       switch (type1)
+       {
+       case LINETYPE:
+               pa1 = ((LWLINE *)lwg1)->points;
+               break;
+       case POLYGONTYPE:
+               pa1 = ((LWPOLY *)lwg1)->rings[0];
+               break;
+       default:
+               lwerror("Unsupported geometry1 type: %s", lwgeom_typename(type1));
+               return LW_FALSE;
+       }
+       switch (type2)
+       {
+       case LINETYPE:
+               pa2 = ((LWLINE *)lwg2)->points;
+               break;
+       case POLYGONTYPE:
+               pa2 = ((LWPOLY *)lwg2)->rings[0];
+               break;
+       default:
+               lwerror("Unsupported geometry2 type: %s", lwgeom_typename(type1));
+               return LW_FALSE;
+       }
+       dl->twisted=1;
+       return lw_dist2d_fast_ptarray_ptarray(pa1, pa2, dl, lwg1->bbox, lwg2->bbox);
+}
+
+/*------------------------------------------------------------------------------------------------------------
+End of Preprocessing functions
+--------------------------------------------------------------------------------------------------------------*/
+
+
+/*------------------------------------------------------------------------------------------------------------
+Brute force functions
+The old way of calculating distances, now used for:
+1)     distances to points (because there shouldn't be anything to gain by the new way of doing it)
+2)     distances when subgeometries geometries bboxes overlaps
+--------------------------------------------------------------------------------------------------------------*/
+
+/**
+
+point to point calculation
+*/
+int
+lw_dist2d_point_point(LWPOINT *point1, LWPOINT *point2, DISTPTS *dl)
+{
+       POINT2D p1;
+       POINT2D p2;
+
+       getPoint2d_p(point1->point, 0, &p1);
+       getPoint2d_p(point2->point, 0, &p2);
+
+       return lw_dist2d_pt_pt(&p1, &p2,dl);
+}
+/**
+
+point to line calculation
+*/
+int
+lw_dist2d_point_line(LWPOINT *point, LWLINE *line, DISTPTS *dl)
+{
+       LWDEBUG(2, "lw_dist2d_point_line is called");
+       POINT2D p;
+       POINTARRAY *pa = line->points;
+       getPoint2d_p(point->point, 0, &p);
+       return lw_dist2d_pt_ptarray(&p, pa, dl);
+}
+/**
+ * 1. see if pt in outer boundary. if no, then treat the outer ring like a line
+ * 2. if in the boundary, test to see if its in a hole.
+ *    if so, then return dist to hole, else return 0 (point in polygon)
+ */
+int
+lw_dist2d_point_poly(LWPOINT *point, LWPOLY *poly, DISTPTS *dl)
+{
+       LWDEBUG(2, "lw_dist2d_point_poly called");
+
+       POINT2D p;
+       int i;
+
+       getPoint2d_p(point->point, 0, &p);
+
+
+
+
+       if (dl->mode == DIST2D_MAX)
+       {
+               LWDEBUG(3, "looking for maxdistance");
+               return lw_dist2d_pt_ptarray(&p, poly->rings[0], dl);
+       }
+       /* Return distance to outer ring if not inside it */
+       if ( ! pt_in_ring_2d(&p, poly->rings[0]) )
+       {
+               LWDEBUG(3, "first point not inside outer-ring");
+               return lw_dist2d_pt_ptarray(&p, poly->rings[0], dl);
+       }
+
+       /*
+        * Inside the outer ring.
+        * Scan though each of the inner rings looking to
+        * see if its inside.  If not, distance==0.
+        * Otherwise, distance = pt to ring distance
+        */
+       for (i=1; i<poly->nrings; i++)
+       {
+               /* Inside a hole. Distance = pt -> ring */
+               if ( pt_in_ring_2d(&p, poly->rings[i]) )
+               {
+                       LWDEBUG(3, " inside an hole");
+                       return lw_dist2d_pt_ptarray(&p, poly->rings[i], dl);
+               }
+       }
+
+       LWDEBUG(3, " inside the polygon");
+       if (dl->mode == DIST2D_MIN)
+       {
+               dl->distance=0.0;
+               dl->p1.x=p.x;
+               dl->p1.y=p.y;
+               dl->p2.x=p.x;
+               dl->p2.y=p.y;
+       }
+       return LW_TRUE; /* Is inside the polygon */
+}
+/**
+
+line to line calculation
+*/
+int
+lw_dist2d_line_line(LWLINE *line1, LWLINE *line2, DISTPTS *dl)
+{
+       LWDEBUG(2, "lw_dist2d_line_line is called");
+       POINTARRAY *pa1 = line1->points;
+       POINTARRAY *pa2 = line2->points;
+       return lw_dist2d_ptarray_ptarray(pa1, pa2, dl);
+}
+/**
+
+line to polygon calculation
+*/
+int
+lw_dist2d_line_poly(LWLINE *line, LWPOLY *poly, DISTPTS *dl)
+{
+       LWDEBUG(2, "lw_dist2d_line_poly is called");
+       return lw_dist2d_ptarray_poly(line->points, poly, dl);
+}
+
+/**
+
+Function handling polygon to polygon calculation
+1      if we are looking for maxdistance, just check the outer rings.
+2      check if poly1 has first point outside poly2 and vice versa, if so, just check outer rings
+3      check if first point of poly2 is in a hole of poly1. If so check outer ring of poly2 against that hole of poly1
+4      check if first point of poly1 is in a hole of poly2. If so check outer ring of poly1 against that hole of poly2
+5      If we have come all the way here we know that the first point of one of them is inside the other ones outer ring and not in holes so we check wich one is inside.
+ */
+int
+lw_dist2d_poly_poly(LWPOLY *poly1, LWPOLY *poly2, DISTPTS *dl)
+{
+
+       LWDEBUG(2, "lw_dist2d_poly_poly called");
+
+       POINT2D pt;
+       int i;
+
+
+       /*1     if we are looking for maxdistance, just check the outer rings.*/
+       if (dl->mode == DIST2D_MAX)
+       {
+               return lw_dist2d_ptarray_ptarray(poly1->rings[0],       poly2->rings[0],dl);
+       }
+
+
+       /* 2    check if poly1 has first point outside poly2 and vice versa, if so, just check outer rings
+       here it would be possible to handle the information about wich one is inside wich one and only search for the smaller ones in the bigger ones holes.*/
+       getPoint2d_p(poly1->rings[0], 0, &pt);
+       if ( !pt_in_ring_2d(&pt, poly2->rings[0]))
+       {
+               getPoint2d_p(poly2->rings[0], 0, &pt);
+               if (!pt_in_ring_2d(&pt, poly1->rings[0]))
+               {
+                       return lw_dist2d_ptarray_ptarray(poly1->rings[0],       poly2->rings[0],dl);
+               }
+       }
+
+       /*3     check if first point of poly2 is in a hole of poly1. If so check outer ring of poly2 against that hole of poly1*/
+       getPoint2d_p(poly2->rings[0], 0, &pt);
+       for (i=1; i<poly1->nrings; i++)
+       {
+               /* Inside a hole */
+               if ( pt_in_ring_2d(&pt, poly1->rings[i]) )
+               {
+                       return lw_dist2d_ptarray_ptarray(poly1->rings[i],       poly2->rings[0],dl);
+               }
+       }
+
+       /*4     check if first point of poly1 is in a hole of poly2. If so check outer ring of poly1 against that hole of poly2*/
+       getPoint2d_p(poly1->rings[0], 0, &pt);
+       for (i=1; i<poly2->nrings; i++)
+       {
+               /* Inside a hole */
+               if ( pt_in_ring_2d(&pt, poly2->rings[i]) )
+               {
+                       return lw_dist2d_ptarray_ptarray(poly1->rings[0],       poly2->rings[i],dl);
+               }
+       }
+
+
+       /*5     If we have come all the way here we know that the first point of one of them is inside the other ones outer ring and not in holes so we check wich one is inside.*/
+       getPoint2d_p(poly1->rings[0], 0, &pt);
+       if ( pt_in_ring_2d(&pt, poly2->rings[0]))
+       {
+               dl->distance=0.0;
+               dl->p1.x=pt.x;
+               dl->p1.y=pt.y;
+               dl->p2.x=pt.x;
+               dl->p2.y=pt.y;
+               return LW_TRUE;
+       }
+
+       getPoint2d_p(poly2->rings[0], 0, &pt);
+       if (pt_in_ring_2d(&pt, poly1->rings[0]))
+       {
+               dl->distance=0.0;
+               dl->p1.x=pt.x;
+               dl->p1.y=pt.y;
+               dl->p2.x=pt.x;
+               dl->p2.y=pt.y;
+               return LW_TRUE;
+       }
+
+
+       lwerror("Unspecified error in function lw_dist2d_poly_poly");
+       return LW_FALSE;
+}
+
+/**
+
+ * search all the segments of pointarray to see which one is closest to p1
+ * Returns minimum distance between point and pointarray
+ */
+int
+lw_dist2d_pt_ptarray(POINT2D *p, POINTARRAY *pa,DISTPTS *dl)
+{
+       LWDEBUG(2, "lw_dist2d_pt_ptarray is called");
+
+       int t;
+       POINT2D start, end;
+       int twist = dl->twisted;
+       getPoint2d_p(pa, 0, &start);
+
+       for (t=1; t<pa->npoints; t++)
+       {
+               dl->twisted=twist;
+               getPoint2d_p(pa, t, &end);
+               if (!lw_dist2d_pt_seg(p, &start, &end,dl)) return LW_FALSE;
+
+               if (dl->distance<=dl->tolerance && dl->mode == DIST2D_MIN) return LW_TRUE; /*just a check if  the answer is already given*/
+               start = end;
+       }
+
+       return LW_TRUE;
+}
+
+/**
+ * Brute force.
+ * Test line-ring distance against each ring.
+ * If there's an intersection (distance==0) then return 0 (crosses boundary).
+ * Otherwise, test to see if any point is inside outer rings of polygon,
+ * but not in inner rings.
+ * If so, return 0  (line inside polygon),
+ * otherwise return min distance to a ring (could be outside
+ * polygon or inside a hole)
+ */
+
+int
+lw_dist2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly, DISTPTS *dl)
+{
+       LWDEBUGF(2, "lw_dist2d_ptarray_poly called (%d rings)", poly->nrings);
+
+       POINT2D pt;
+       int i;
+
+
+
+       getPoint2d_p(pa, 0, &pt);
+       if ( !pt_in_ring_2d(&pt, poly->rings[0]))
+       {
+               return lw_dist2d_ptarray_ptarray(pa,poly->rings[0],dl);
+       }
+
+       for (i=1; i<poly->nrings; i++)
+       {
+               if (!lw_dist2d_ptarray_ptarray(pa, poly->rings[i], dl)) return LW_FALSE;
+
+               LWDEBUGF(3, " distance from ring %d: %f, mindist: %f",
+                        i, dist, mindist);
+               if (dl->distance<=dl->tolerance && dl->mode == DIST2D_MIN) return LW_TRUE; /*just a check if  the answer is already given*/
+       }
+
+       /*
+        * No intersection, have to check if a point is
+        * inside polygon
+        */
+       getPoint2d_p(pa, 0, &pt);
+
+       /*
+        * Outside outer ring, so min distance to a ring
+        * is the actual min distance
+
+       if ( ! pt_in_ring_2d(&pt, poly->rings[0]) )
+       {
+               return ;
+       } */
+
+       /*
+        * Its in the outer ring.
+        * Have to check if its inside a hole
+        */
+       for (i=1; i<poly->nrings; i++)
+       {
+               if ( pt_in_ring_2d(&pt, poly->rings[i]) )
+               {
+                       /*
+                        * Its inside a hole, then the actual
+                        * distance is the min ring distance
+                        */
+                       return LW_TRUE;
+               }
+       }
+       if (dl->mode == DIST2D_MIN)
+       {
+               dl->distance=0.0;
+               dl->p1.x=pt.x;
+               dl->p1.y=pt.y;
+               dl->p2.x=pt.x;
+               dl->p2.y=pt.y;
+       }
+       return LW_TRUE; /* Not in hole, so inside polygon */
+}
+
+
+
+/**
+
+test each segment of l1 against each segment of l2.
+*/
+int
+lw_dist2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2,DISTPTS *dl)
+{
+       LWDEBUG(2, "lw_dist2d_ptarray_ptarray is called");
+
+       int t,u;
+       POINT2D start, end;
+       POINT2D start2, end2;
+       int twist = dl->twisted;
+       LWDEBUGF(2, "lw_dist2d_ptarray_ptarray called (points: %d-%d)",l1->npoints, l2->npoints);
+       if (dl->mode == DIST2D_MAX)/*If we are searching for maxdistance we go straight to point-point calculation since the maxdistance have to be between two vertexes*/
+       {
+               for (t=0; t<l1->npoints; t++) /*for each segment in L1 */
+               {
+                       getPoint2d_p(l1, t, &start);
+                       for (u=0; u<l2->npoints; u++) /*for each segment in L2 */
+                       {
+                               getPoint2d_p(l2, u, &start2);
+                               lw_dist2d_pt_pt(&start,&start2,dl);
+                               LWDEBUGF(4, "maxdist_ptarray_ptarray; seg %i * seg %i, dist = %g\n",t,u,dist);
+                               LWDEBUGF(3, " seg%d-seg%d dist: %f, mindist: %f",
+                                        t, u, dl->distance, result);
+                       }
+               }
+       }
+       else
+       {
+               getPoint2d_p(l1, 0, &start);
+               for (t=1; t<l1->npoints; t++) /*for each segment in L1 */
+               {
+                       getPoint2d_p(l1, t, &end);
+                       getPoint2d_p(l2, 0, &start2);
+                       for (u=1; u<l2->npoints; u++) /*for each segment in L2 */
+                       {
+                               getPoint2d_p(l2, u, &end2);
+                               dl->twisted=twist;
+                               lw_dist2d_seg_seg(&start, &end, &start2, &end2,dl);
+                               LWDEBUGF(4, "mindist_ptarray_ptarray; seg %i * seg %i, dist = %g\n",t,u,dist);
+                               LWDEBUGF(3, " seg%d-seg%d dist: %f, mindist: %f",
+                                        t, u, dl->distance, result);
+                               if (dl->distance<=dl->tolerance && dl->mode == DIST2D_MIN) return LW_TRUE; /*just a check if  the answer is already given*/
+                               start2 = end2;
+                       }
+                       start = end;
+               }
+       }
+       return LW_TRUE;
+}
+
+/**
+
+Finds the shortest distance between two segments.
+This function is changed so it is not doing any comparasion of distance
+but just sending every possible combination further to lw_dist2d_pt_seg
+*/
+int
+lw_dist2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D, DISTPTS *dl)
+{
+       LWDEBUGF(2, "lw_dist2d_seg_seg [%g,%g]->[%g,%g] by [%g,%g]->[%g,%g]",
+                A->x,A->y,B->x,B->y, C->x,C->y, D->x, D->y);
+
+       double  s_top, s_bot,s;
+       double  r_top, r_bot,r;
+
+
+
+
+       /*A and B are the same point */
+       if (  ( A->x == B->x) && (A->y == B->y) )
+       {
+               return lw_dist2d_pt_seg(A,C,D,dl);
+       }
+       /*U and V are the same point */
+
+       if (  ( C->x == D->x) && (C->y == D->y) )
+       {
+               dl->twisted= ((dl->twisted) * (-1));
+               return lw_dist2d_pt_seg(D,A,B,dl);
+       }
+       /* AB and CD are line segments */
+       /* from comp.graphics.algo
+
+       Solving the above for r and s yields
+                               (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy)
+                  r = ----------------------------- (eqn 1)
+                               (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
+
+                       (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
+               s = ----------------------------- (eqn 2)
+                       (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
+       Let P be the position vector of the intersection point, then
+               P=A+r(B-A) or
+               Px=Ax+r(Bx-Ax)
+               Py=Ay+r(By-Ay)
+       By examining the values of r & s, you can also determine some other limiting conditions:
+               If 0<=r<=1 & 0<=s<=1, intersection exists
+               r<0 or r>1 or s<0 or s>1 line segments do not intersect
+               If the denominator in eqn 1 is zero, AB & CD are parallel
+               If the numerator in eqn 1 is also zero, AB & CD are collinear.
+
+       */
+       r_top = (A->y-C->y)*(D->x-C->x) - (A->x-C->x)*(D->y-C->y) ;
+       r_bot = (B->x-A->x)*(D->y-C->y) - (B->y-A->y)*(D->x-C->x) ;
+
+       s_top = (A->y-C->y)*(B->x-A->x) - (A->x-C->x)*(B->y-A->y);
+       s_bot = (B->x-A->x)*(D->y-C->y) - (B->y-A->y)*(D->x-C->x);
+
+       if  ( (r_bot==0) || (s_bot == 0) )
+       {
+               if ((lw_dist2d_pt_seg(A,C,D,dl)) && (lw_dist2d_pt_seg(B,C,D,dl)))
+               {
+                       dl->twisted= ((dl->twisted) * (-1));  /*here we change the order of inputted geometrys and that we  notice by changing sign on dl->twisted*/
+                       return ((lw_dist2d_pt_seg(C,A,B,dl)) && (lw_dist2d_pt_seg(D,A,B,dl))); /*if all is successful we return true*/
+               }
+               else
+               {
+                       return LW_FALSE; /* if any of the calls to lw_dist2d_pt_seg goes wrong we return false*/
+               }
+       }
+
+       s = s_top/s_bot;
+       r=  r_top/r_bot;
+
+       if (((r<0) || (r>1) || (s<0) || (s>1)) || (dl->mode == DIST2D_MAX))
+       {
+               if ((lw_dist2d_pt_seg(A,C,D,dl)) && (lw_dist2d_pt_seg(B,C,D,dl)))
+               {
+                       dl->twisted= ((dl->twisted) * (-1));  /*here we change the order of inputted geometrys and that we  notice by changing sign on dl->twisted*/
+                       return ((lw_dist2d_pt_seg(C,A,B,dl)) && (lw_dist2d_pt_seg(D,A,B,dl))); /*if all is successful we return true*/
+               }
+               else
+               {
+                       return LW_FALSE; /* if any of the calls to lw_dist2d_pt_seg goes wrong we return false*/
+               }
+       }
+       else
+       {
+               if (dl->mode == DIST2D_MIN)     /*If there is intersection we identify the intersection point and return it but only if we are looking for mindistance*/
+               {
+                       POINT2D theP;
+
+                       if (((A->x==C->x)&&(A->y==C->y))||((A->x==D->x)&&(A->y==D->y)))
+                       {
+                               theP.x = A->x;
+                               theP.y = A->y;
+                       }
+                       else if (((B->x==C->x)&&(B->y==C->y))||((B->x==D->x)&&(B->y==D->y)))
+                       {
+                               theP.x = B->x;
+                               theP.y = B->y;
+                       }
+                       else
+                       {
+                               theP.x = A->x+r*(B->x-A->x);
+                               theP.y = A->y+r*(B->y-A->y);
+                       }
+                       dl->distance=0.0;
+                       dl->p1=theP;
+                       dl->p2=theP;
+               }
+               return LW_TRUE;
+
+       }
+       lwerror("unspecified error in function lw_dist2d_seg_seg");
+       return LW_FALSE; /*If we have come here something is wrong*/
+}
+
+
+/*------------------------------------------------------------------------------------------------------------
+End of Brute force functions
+--------------------------------------------------------------------------------------------------------------*/
+
+
+/*------------------------------------------------------------------------------------------------------------
+New faster distance calculations
+--------------------------------------------------------------------------------------------------------------*/
+
+/**
+
+The new faster calculation comparing pointarray to another pointarray
+the arrays can come from both polygons and linestrings.
+The naming is not good but comes from that it compares a
+chosen selection of the points not all of them
+*/
+int
+lw_dist2d_fast_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2,DISTPTS *dl, BOX2DFLOAT4 *box1, BOX2DFLOAT4 *box2)
+{
+       LWDEBUG(2, "lw_dist2d_fast_ptarray_ptarray is called");
+       /*here we define two lists to hold our calculated "z"-values and the order number in the geometry*/
+
+       double k, thevalue;
+       float   deltaX, deltaY, c1m, c2m;
+       POINT2D theP,c1, c2;
+       float min1X, max1X, max1Y, min1Y,min2X, max2X, max2Y, min2Y;
+       int t,  n1, n2;
+       n1 = l1->npoints;
+       n2 = l2->npoints;
+
+       LISTSTRUCT list1[n1];
+       LISTSTRUCT list2[n2];
+
+       max1X = box1->xmax;
+       min1X = box1->xmin;
+       max1Y = box1->ymax;
+       min1Y = box1->ymin;
+       max2X = box2->xmax;
+       min2X = box2->xmin;
+       max2Y = box2->ymax;
+       min2Y = box2->ymin;
+       /*we want the center of the bboxes, and calculate the slope between the centerpoints*/
+       c1.x = min1X + (max1X-min1X)/2;
+       c1.y = min1Y + (max1Y-min1Y)/2;
+       c2.x = min2X + (max2X-min2X)/2;
+       c2.y = min2Y + (max2Y-min2Y)/2;
+
+       deltaX=(c2.x-c1.x);
+       deltaY=(c2.y-c1.y);
+
+
+       /*Here we calculate where the line perpendicular to the center-center line crosses the axes for each vertex
+       if the center-center line is vertical the perpendicular line will be horizontal and we find it's crossing the Y-axes with z = y-kx */
+       if ((deltaX*deltaX)<(deltaY*deltaY))        /*North or South*/
+       {
+               k = -deltaX/deltaY;
+               for (t=0; t<n1; t++) /*for each segment in L1 */
+               {
+                       getPoint2d_p(l1, t, &theP);
+                       thevalue = theP.y-(k*theP.x);
+                       list1[t].themeasure=thevalue;
+                       list1[t].pnr=t;
+
+               }
+               for (t=0; t<n2; t++) /*for each segment in L2*/
+               {
+                       getPoint2d_p(l2, t, &theP);
+                       thevalue = theP.y-(k*theP.x);
+                       list2[t].themeasure=thevalue;
+                       list2[t].pnr=t;
+
+               }
+               c1m = c1.y-(k*c1.x);
+               c2m = c2.y-(k*c2.x);
+       }
+
+
+       /*if the center-center line is horizontal the perpendicular line will be vertical. To eliminate problems with deviding by zero we are here mirroring the coordinate-system
+        and we find it's crossing the X-axes with z = x-(1/k)y */
+       else        /*West or East*/
+       {
+               k = -deltaY/deltaX;
+               for (t=0; t<n1; t++) /*for each segment in L1 */
+               {
+                       getPoint2d_p(l1, t, &theP);
+                       thevalue = theP.x-(k*theP.y);
+                       list1[t].themeasure=thevalue;
+                       list1[t].pnr=t;
+                       /*lwnotice("1pnr=%d, pnr=%d, themeasure=%f, themeasure=%f",t,list1[t].pnr,thevalue,list1[t].themeasure  );*/
+               }
+               for (t=0; t<n2; t++) /*for each segment in L2*/
+               {
+                       getPoint2d_p(l2, t, &theP);
+
+                       thevalue = theP.x-(k*theP.y);
+                       list2[t].themeasure=thevalue;
+                       list2[t].pnr=t;
+               }
+               c1m = c1.x-(k*c1.y);
+               c2m = c2.x-(k*c2.y);
+       }
+
+       /*we sort our lists by the calculated values*/
+       qsort(list1, n1, sizeof(LISTSTRUCT), struct_cmp_by_measure);
+       qsort(list2, n2, sizeof(LISTSTRUCT), struct_cmp_by_measure);
+
+       if (c1m < c2m)
+       {
+               if (!lw_dist2d_pre_seg_seg(l1,l2,list1,list2,k,dl)) return LW_FALSE;
+       }
+       else
+       {
+               dl->twisted= ((dl->twisted) * (-1));
+               if (!lw_dist2d_pre_seg_seg(l2,l1,list2,list1,k,dl)) return LW_FALSE;
+       }
+       return LW_TRUE;
+}
+
+int
+struct_cmp_by_measure(const void *a, const void *b)
+{
+       LISTSTRUCT *ia = (LISTSTRUCT*)a;
+       LISTSTRUCT *ib = (LISTSTRUCT*)b;
+       return ( ia->themeasure>ib->themeasure ) ? 1 : -1;
+}
+
+/**
+       preparation before lw_dist2d_seg_seg.
+*/
+int
+lw_dist2d_pre_seg_seg(POINTARRAY *l1, POINTARRAY *l2,LISTSTRUCT *list1, LISTSTRUCT *list2,double k, DISTPTS *dl)
+{
+       LWDEBUG(2, "lw_dist2d_pre_seg_seg is called");
+
+
+       POINT2D p1, p2, p3, p4, p01, p02;
+       int pnr1,pnr2,pnr3,pnr4, n1, n2, i, u, r, twist;
+
+       double maxmeasure;
+       n1=     l1->npoints;
+       n2 = l2->npoints;
+
+
+       getPoint2d_p(l1, list1[0].pnr, &p1);
+       getPoint2d_p(l2, list2[0].pnr, &p3);
+       lw_dist2d_pt_pt(&p1, &p3,dl);
+       maxmeasure = sqrt(dl->distance*dl->distance + (dl->distance*dl->distance*k*k));
+       twist = dl->twisted; /*to keep the incomming order between iterations*/
+       for (i =(n1-1); i>=0; --i)
+       {
+               /*we break this iteration when we have checked every
+               point closer to our perpendicular "checkline" than
+               our shortest found distance*/
+               if (((list2[0].themeasure-list1[i].themeasure)) > maxmeasure) break;
+               for (r=-1; r<=1; r +=2) /*because we are not iterating in the original pointorder we have to check the segment before and after every point*/
+               {
+                       pnr1 = list1[i].pnr;
+                       getPoint2d_p(l1, pnr1, &p1);
+                       if (pnr1+r<0)
+                       {
+                               getPoint2d_p(l1, (n1-1), &p01);
+                               if (( p1.x == p01.x) && (p1.y == p01.y)) pnr2 = (n1-1);
+                               else pnr2 = pnr1; /* if it is a line and the last and first point is not the same we avoid the edge between start and end this way*/
+                       }
+
+                       else if (pnr1+r>(n1-1))
+                       {
+                               getPoint2d_p(l1, 0, &p01);
+                               if (( p1.x == p01.x) && (p1.y == p01.y)) pnr2 = 0;
+                               else pnr2 = pnr1; /* if it is a line and the last and first point is not the same we avoid the edge between start and end this way*/
+                       }
+                       else pnr2 = pnr1+r;
+
+
+                       getPoint2d_p(l1, pnr2, &p2);
+                       for (u=0; u<n2; ++u)
+                       {
+                               if (((list2[u].themeasure-list1[i].themeasure)) >= maxmeasure) break;
+                               pnr3 = list2[u].pnr;
+                               getPoint2d_p(l2, pnr3, &p3);
+                               if (pnr3==0)
+                               {
+                                       getPoint2d_p(l2, (n2-1), &p02);
+                                       if (( p3.x == p02.x) && (p3.y == p02.y)) pnr4 = (n2-1);
+                                       else pnr4 = pnr3; /* if it is a line and the last and first point is not the same we avoid the edge between start and end this way*/
+                               }
+                               else pnr4 = pnr3-1;
+
+                               getPoint2d_p(l2, pnr4, &p4);
+                               dl->twisted=twist;
+                               if (!lw_dist2d_selected_seg_seg(&p1, &p2, &p3, &p4, dl)) return LW_FALSE;
+
+                               if (pnr3>=(n2-1))
+                               {
+                                       getPoint2d_p(l2, 0, &p02);
+                                       if (( p3.x == p02.x) && (p3.y == p02.y)) pnr4 = 0;
+                                       else pnr4 = pnr3; /* if it is a line and the last and first point is not the same we avoid the edge between start and end this way*/
+                               }
+
+                               else pnr4 = pnr3+1;
+
+                               getPoint2d_p(l2, pnr4, &p4);
+                               dl->twisted=twist; /*we reset the "twist" for each iteration*/
+                               if (!lw_dist2d_selected_seg_seg(&p1, &p2, &p3, &p4, dl)) return LW_FALSE;
+
+                               maxmeasure = sqrt(dl->distance*dl->distance + (dl->distance*dl->distance*k*k));/*here we "translate" the found mindistance so it can be compared to our "z"-values*/
+                       }
+               }
+       }
+
+       return LW_TRUE;
+}
+
+
+/**
+       This is the same function as lw_dist2d_seg_seg but
+       without any calculations to determine intersection since we
+       already know they do not intersect
+*/
+int
+lw_dist2d_selected_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D, DISTPTS *dl)
+{
+       LWDEBUGF(2, "lw_dist2d_selected_seg_seg [%g,%g]->[%g,%g] by [%g,%g]->[%g,%g]",
+                A->x,A->y,B->x,B->y, C->x,C->y, D->x, D->y);
+
+       /*A and B are the same point */
+       if (  ( A->x == B->x) && (A->y == B->y) )
+       {
+               return lw_dist2d_pt_seg(A,C,D,dl);
+       }
+       /*U and V are the same point */
+
+       if (  ( C->x == D->x) && (C->y == D->y) )
+       {
+               dl->twisted= ((dl->twisted) * (-1));
+               return lw_dist2d_pt_seg(D,A,B,dl);
+       }
+
+       if ((lw_dist2d_pt_seg(A,C,D,dl)) && (lw_dist2d_pt_seg(B,C,D,dl)))
+       {
+               dl->twisted= ((dl->twisted) * (-1));  /*here we change the order of inputted geometrys and that we  notice by changing sign on dl->twisted*/
+               return ((lw_dist2d_pt_seg(C,A,B,dl)) && (lw_dist2d_pt_seg(D,A,B,dl))); /*if all is successful we return true*/
+       }
+       else
+       {
+               return LW_FALSE; /* if any of the calls to lw_dist2d_pt_seg goes wrong we return false*/
+       }
+}
+
+/*------------------------------------------------------------------------------------------------------------
+End of New faster distance calculations
+--------------------------------------------------------------------------------------------------------------*/
 
-#include "liblwgeom.h"
 
+/*------------------------------------------------------------------------------------------------------------
+Functions in common for Brute force and new calculation
+--------------------------------------------------------------------------------------------------------------*/
 
-/*
+/**
  * pt_in_ring_2d(): crossing number test for a point in a polygon
  *      input:   p = a point,
  *               pa = vertex points of a ring V[n+1] with V[n]=V[0]
  *     Our polygons have first and last point the same,
  *
  */
-int pt_in_ring_2d(POINT2D *p, POINTARRAY *ring)
+int
+pt_in_ring_2d(POINT2D *p, POINTARRAY *ring)
 {
        int cn = 0;    /* the crossing number counter */
        int i;
@@ -40,6 +1218,7 @@ int pt_in_ring_2d(POINT2D *p, POINTARRAY *ring)
        {
                lwerror("pt_in_ring_2d: V[n] != V[0] (%g %g != %g %g)",
                        first.x, first.y, last.x, last.y);
+               return LW_FALSE;
 
        }
 #endif
@@ -81,35 +1260,31 @@ int pt_in_ring_2d(POINT2D *p, POINTARRAY *ring)
        return (cn&1);    /* 0 if even (out), and 1 if odd (in) */
 }
 
-double distance2d_pt_pt(POINT2D *p1, POINT2D *p2)
-{
-       double hside = p2->x - p1->x;
-       double vside = p2->y - p1->y;
-
-       return sqrt ( hside*hside + vside*vside );
 
-       /* the above is more readable
-          return sqrt(
-               (p2->x-p1->x) * (p2->x-p1->x) + (p2->y-p1->y) * (p2->y-p1->y)
-               );  */
-}
+/**
 
-/*distance2d from p to line A->B */
-double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B)
+lw_dist2d_comp from p to line A->B
+This one is now sending every occation to lw_dist2d_pt_pt
+Before it was handling occations where r was between 0 and 1 internally
+and just returning the distance without identifying the points.
+To get this points it was nessecary to change and it also showed to be about 10%faster.
+*/
+int
+lw_dist2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B, DISTPTS *dl)
 {
-       double  r,s;
-
+       double  r;
        /*if start==end, then use pt distance */
        if (  ( A->x == B->x) && (A->y == B->y) )
-               return distance2d_pt_pt(p,A);
-
+       {
+               return lw_dist2d_pt_pt(p,A,dl);
+       }
        /*
         * otherwise, we use comp.graphics.algorithms
         * Frequently Asked Questions method
         *
         *  (1)               AC dot AB
-               *         r = ---------
-               *               ||AB||^2
+            *         r = ---------
+            *               ||AB||^2
         *      r has the following meaning:
         *      r=0 P = A
         *      r=1 P = B
@@ -120,187 +1295,93 @@ double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B)
 
        r = ( (p->x-A->x) * (B->x-A->x) + (p->y-A->y) * (B->y-A->y) )/( (B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) );
 
-       if (r<0) return distance2d_pt_pt(p,A);
-       if (r>1) return distance2d_pt_pt(p,B);
-
-
-       /*
-        * (2)
-        *           (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
-        *      s = -----------------------------
-        *                      L^2
-        *
-        *      Then the distance from C to P = |s|*L.
-        *
-        */
-
-       s = ( (A->y-p->y)*(B->x-A->x)- (A->x-p->x)*(B->y-A->y) ) /
-           ( (B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) );
-
-       return LW_ABS(s) * sqrt(
-                  (B->x-A->x)*(B->x-A->x) + (B->y-A->y)*(B->y-A->y)
-              );
-}
-
-/* find the minimum 2d distance from AB to CD */
-double distance2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D)
-{
-
-       double  s_top, s_bot,s;
-       double  r_top, r_bot,r;
-
-       LWDEBUGF(2, "distance2d_seg_seg [%g,%g]->[%g,%g] by [%g,%g]->[%g,%g]",
-                A->x,A->y,B->x,B->y, C->x,C->y, D->x, D->y);
-
-
-       /*A and B are the same point */
-       if (  ( A->x == B->x) && (A->y == B->y) )
-               return distance2d_pt_seg(A,C,D);
-
-       /*U and V are the same point */
-
-       if (  ( C->x == D->x) && (C->y == D->y) )
-               return distance2d_pt_seg(D,A,B);
-
-       /* AB and CD are line segments */
-       /* from comp.graphics.algo
-
-       Solving the above for r and s yields
-                               (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy)
-                  r = ----------------------------- (eqn 1)
-                               (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
-
-                       (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
-               s = ----------------------------- (eqn 2)
-                       (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
-       Let P be the position vector of the intersection point, then
-               P=A+r(B-A) or
-               Px=Ax+r(Bx-Ax)
-               Py=Ay+r(By-Ay)
-       By examining the values of r & s, you can also determine some other limiting conditions:
-               If 0<=r<=1 & 0<=s<=1, intersection exists
-               r<0 or r>1 or s<0 or s>1 line segments do not intersect
-               If the denominator in eqn 1 is zero, AB & CD are parallel
-               If the numerator in eqn 1 is also zero, AB & CD are collinear.
-
-       */
-       r_top = (A->y-C->y)*(D->x-C->x) - (A->x-C->x)*(D->y-C->y) ;
-       r_bot = (B->x-A->x)*(D->y-C->y) - (B->y-A->y)*(D->x-C->x) ;
-
-       s_top = (A->y-C->y)*(B->x-A->x) - (A->x-C->x)*(B->y-A->y);
-       s_bot = (B->x-A->x)*(D->y-C->y) - (B->y-A->y)*(D->x-C->x);
-
-       if  ( (r_bot==0) || (s_bot == 0) )
-       {
-               return (
-                          LW_MIN(distance2d_pt_seg(A,C,D),
-                                 LW_MIN(distance2d_pt_seg(B,C,D),
-                                        LW_MIN(distance2d_pt_seg(C,A,B),
-                                               distance2d_pt_seg(D,A,B))
-                                       )
-                                )
-                      );
-       }
-       s = s_top/s_bot;
-       r=  r_top/r_bot;
-
-       if ((r<0) || (r>1) || (s<0) || (s>1) )
+       /*This is for finding the maxdistance.
+       the maxdistance have to be between two vertexes,
+       compared to mindistance which can be between
+       tvo vertexes vertex.*/
+       if (dl->mode == DIST2D_MAX)
        {
-               /*no intersection */
-               return (
-                          LW_MIN(distance2d_pt_seg(A,C,D),
-                                 LW_MIN(distance2d_pt_seg(B,C,D),
-                                        LW_MIN(distance2d_pt_seg(C,A,B),
-                                               distance2d_pt_seg(D,A,B))
-                                       )
-                                )
-                      );
-
+               if (r>=0.5)
+               {
+                       return lw_dist2d_pt_pt(p,A,dl);
+               }
+               if (r<0.5)
+               {
+                       return lw_dist2d_pt_pt(p,B,dl);
+               }
        }
-       else
-               return -0; /*intersection exists */
-
-}
-
-/*
- * search all the segments of pointarray to see which one is closest to p1
- * Returns minimum distance between point and pointarray
- */
-double distance2d_pt_ptarray(POINT2D *p, POINTARRAY *pa)
-{
-       double result = 0;
-       int t;
-       POINT2D start, end;
-
-       getPoint2d_p(pa, 0, &start);
 
-       for (t=1; t<pa->npoints; t++)
+       if (r<0)        /*If the first vertex A is closest to the point p*/
        {
-               double dist;
-               getPoint2d_p(pa, t, &end);
-               dist = distance2d_pt_seg(p, &start, &end);
-               if (t==1) result = dist;
-               else result = LW_MIN(result, dist);
+               return lw_dist2d_pt_pt(p,A,dl);
+       }
+       if (r>1)        /*If the second vertex B is closest to the point p*/
+       {
+               return lw_dist2d_pt_pt(p,B,dl);
+       }
 
-               if ( result == 0 ) return 0;
 
-               start = end;
-       }
+       /*else if the point p is closer to some point between a and b
+       then we find that point and send it to lw_dist2d_pt_pt*/
+       POINT2D c;
+       c.x=A->x + r * (B->x-A->x);
+       c.y=A->y + r * (B->y-A->y);
 
-       return result;
+       return lw_dist2d_pt_pt(p,&c,dl);
 }
 
-/* test each segment of l1 against each segment of l2.  Return min */
-double distance2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2)
-{
-       double  result = 99999999999.9;
-       char result_okay = 0; /*result is a valid min */
-       int t,u;
-       POINT2D start, end;
-       POINT2D start2, end2;
 
-       LWDEBUGF(2, "distance2d_ptarray_ptarray called (points: %d-%d)",
-                l1->npoints, l2->npoints);
+/**
 
-       getPoint2d_p(l1, 0, &start);
-       for (t=1; t<l1->npoints; t++) /*for each segment in L1 */
+Compares incomming points and
+stores the points closest to each other
+or most far away from each other
+depending on dl->mode (max or min)
+*/
+int
+lw_dist2d_pt_pt(POINT2D *thep1, POINT2D *thep2,DISTPTS *dl)
+{
+       double hside = thep2->x - thep1->x;
+       double vside = thep2->y - thep1->y;
+       double dist = sqrt ( hside*hside + vside*vside );
+
+       if (((dl->distance - dist)*(dl->mode))>0) /*multiplication with mode to handle mindistance (mode=1)  and maxdistance (mode = (-1)*/
        {
-               getPoint2d_p(l1, t, &end);
+               dl->distance = dist;
 
-               getPoint2d_p(l2, 0, &start2);
-               for (u=1; u<l2->npoints; u++) /*for each segment in L2 */
+               if (dl->twisted>0)      /*To get the points in right order. twisted is updated between 1 and (-1) every time the order is changed earlier in the chain*/
+               {
+                       dl->p1 = *thep1;
+                       dl->p2 = *thep2;
+               }
+               else
                {
-                       double dist;
+                       dl->p1 = *thep2;
+                       dl->p2 = *thep1;
+               }
+       }
+       return LW_TRUE;
+}
 
-                       getPoint2d_p(l2, u, &end2);
 
-                       dist = distance2d_seg_seg(&start, &end, &start2, &end2);
 
-                       LWDEBUGF(4, "line_line; seg %i * seg %i, dist = %g\n",t,u,dist);
 
-                       if (result_okay)
-                               result = LW_MIN(result,dist);
-                       else
-                       {
-                               result_okay = 1;
-                               result = dist;
-                       }
+/*------------------------------------------------------------------------------------------------------------
+End of Functions in common for Brute force and new calculation
+--------------------------------------------------------------------------------------------------------------*/
 
-                       LWDEBUGF(3, " seg%d-seg%d dist: %f, mindist: %f",
-                                t, u, dist, result);
 
-                       if (result <= 0) return 0; /*intersection */
+/*Mixed functions*/
 
-                       start2 = end2;
-               }
-               start = end;
-       }
 
-       return result;
-}
+/**
 
-/* true if point is in poly (and not in its holes) */
-int pt_in_poly_2d(POINT2D *p, LWPOLY *poly)
+ true if point is in poly (and not in its holes)
+ It's not used by postgis but since I don't know what else
+ can be affectes in the world I don't dare removing it.
+ */
+int
+pt_in_poly_2d(POINT2D *p, LWPOLY *poly)
 {
        int i;
 
@@ -317,199 +1398,89 @@ int pt_in_poly_2d(POINT2D *p, LWPOLY *poly)
        return 1; /* In outer ring, not in holes */
 }
 
-/*
- * Brute force.
- * Test line-ring distance against each ring.
- * If there's an intersection (distance==0) then return 0 (crosses boundary).
- * Otherwise, test to see if any point is inside outer rings of polygon,
- * but not in inner rings.
- * If so, return 0  (line inside polygon),
- * otherwise return min distance to a ring (could be outside
- * polygon or inside a hole)
- */
-double distance2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly)
-{
-       POINT2D pt;
-       int i;
-       double mindist = 0;
-
-       LWDEBUGF(2, "distance2d_ptarray_poly called (%d rings)", poly->nrings);
-
-       for (i=0; i<poly->nrings; i++)
-       {
-               double dist = distance2d_ptarray_ptarray(pa, poly->rings[i]);
-               if (i) mindist = LW_MIN(mindist, dist);
-               else mindist = dist;
-
-               LWDEBUGF(3, " distance from ring %d: %f, mindist: %f",
-                        i, dist, mindist);
-
-               if ( mindist <= 0 ) return 0.0; /* intersection */
-       }
-
-       /*
-        * No intersection, have to check if a point is
-        * inside polygon
-        */
-       getPoint2d_p(pa, 0, &pt);
-
-       /*
-        * Outside outer ring, so min distance to a ring
-        * is the actual min distance
-        */
-       if ( ! pt_in_ring_2d(&pt, poly->rings[0]) ) return mindist;
-
-
-       /*
-        * Its in the outer ring.
-        * Have to check if its inside a hole
-        */
-       for (i=1; i<poly->nrings; i++)
-       {
-               if ( pt_in_ring_2d(&pt, poly->rings[i]) )
-               {
-                       /*
-                        * Its inside a hole, then the actual
-                        * distance is the min ring distance
-                        */
-                       return mindist;
-               }
-       }
-
-       return 0.0; /* Not in hole, so inside polygon */
-}
 
-double distance2d_point_point(LWPOINT *point1, LWPOINT *point2)
+/**
+The old function nessecary for ptarray_segmentize2d in ptarray.c
+*/
+double
+distance2d_pt_pt(POINT2D *p1, POINT2D *p2)
 {
-       POINT2D p1;
-       POINT2D p2;
-
-       getPoint2d_p(point1->point, 0, &p1);
-       getPoint2d_p(point2->point, 0, &p2);
-
-       return distance2d_pt_pt(&p1, &p2);
-}
+       double hside = p2->x - p1->x;
+       double vside = p2->y - p1->y;
 
-double distance2d_point_line(LWPOINT *point, LWLINE *line)
-{
-       POINT2D p;
-       POINTARRAY *pa = line->points;
-       getPoint2d_p(point->point, 0, &p);
-       return distance2d_pt_ptarray(&p, pa);
-}
+       return sqrt ( hside*hside + vside*vside );
 
-double distance2d_line_line(LWLINE *line1, LWLINE *line2)
-{
-       POINTARRAY *pa1 = line1->points;
-       POINTARRAY *pa2 = line2->points;
-       return distance2d_ptarray_ptarray(pa1, pa2);
+       /* the above is more readable
+          return sqrt(
+               (p2->x-p1->x) * (p2->x-p1->x) + (p2->y-p1->y) * (p2->y-p1->y)
+               );  */
 }
 
-/*
- * 1. see if pt in outer boundary. if no, then treat the outer ring like a line
- * 2. if in the boundary, test to see if its in a hole.
- *    if so, then return dist to hole, else return 0 (point in polygon)
- */
-double distance2d_point_poly(LWPOINT *point, LWPOLY *poly)
-{
-       POINT2D p;
-       int i;
 
-       getPoint2d_p(point->point, 0, &p);
 
-       LWDEBUG(2, "distance2d_point_poly called");
+/**
 
-       /* Return distance to outer ring if not inside it */
-       if ( ! pt_in_ring_2d(&p, poly->rings[0]) )
-       {
-               LWDEBUG(3, " not inside outer-ring");
+The old function nessecary for ptarray_segmentize2d in ptarray.c
+*/
+double
+distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B)
+{
+       double  r,s;
 
-               return distance2d_pt_ptarray(&p, poly->rings[0]);
-       }
+       /*if start==end, then use pt distance */
+       if (  ( A->x == B->x) && (A->y == B->y) )
+               return distance2d_pt_pt(p,A);
 
        /*
-        * Inside the outer ring.
-        * Scan though each of the inner rings looking to
-        * see if its inside.  If not, distance==0.
-        * Otherwise, distance = pt to ring distance
+        * otherwise, we use comp.graphics.algorithms
+        * Frequently Asked Questions method
+        *
+        *  (1)               AC dot AB
+               *         r = ---------
+               *               ||AB||^2
+        *      r has the following meaning:
+        *      r=0 P = A
+        *      r=1 P = B
+        *      r<0 P is on the backward extension of AB
+        *      r>1 P is on the forward extension of AB
+        *      0<r<1 P is interior to AB
         */
-       for (i=1; i<poly->nrings; i++)
-       {
-               /* Inside a hole. Distance = pt -> ring */
-               if ( pt_in_ring_2d(&p, poly->rings[i]) )
-               {
-                       LWDEBUG(3, " inside an hole");
-
-                       return distance2d_pt_ptarray(&p, poly->rings[i]);
-               }
-       }
-
-       LWDEBUG(3, " inside the polygon");
-
-       return 0.0; /* Is inside the polygon */
-}
-
-/*
- * Brute force.
- * Test to see if any rings intersect.
- * If yes, dist=0.
- * Test to see if one inside the other and if they are inside holes.
- * Find min distance ring-to-ring.
- */
-double distance2d_poly_poly(LWPOLY *poly1, LWPOLY *poly2)
-{
-       POINT2D pt;
-       double mindist = -1;
-       int i;
 
-       LWDEBUG(2, "distance2d_poly_poly called");
-
-       /* if poly1 inside poly2 return 0 */
-       getPoint2d_p(poly1->rings[0], 0, &pt);
-       if ( pt_in_poly_2d(&pt, poly2) ) return 0.0;
+       r = ( (p->x-A->x) * (B->x-A->x) + (p->y-A->y) * (B->y-A->y) )/( (B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) );
 
-       /* if poly2 inside poly1 return 0 */
-       getPoint2d_p(poly2->rings[0], 0, &pt);
-       if ( pt_in_poly_2d(&pt, poly1) ) return 0.0;
+       if (r<0) return distance2d_pt_pt(p,A);
+       if (r>1) return distance2d_pt_pt(p,B);
 
-       LWDEBUG(3, "  polys not inside each other");
 
        /*
-        * foreach ring in Poly1
-        * foreach ring in Poly2
-        *   if intersect, return 0
+        * (2)
+        *           (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
+        *      s = -----------------------------
+        *                      L^2
+        *
+        *      Then the distance from C to P = |s|*L.
+        *
         */
-       for (i=0; i<poly1->nrings; i++)
-       {
-               int j;
-               for (j=0; j<poly2->nrings; j++)
-               {
-                       double d = distance2d_ptarray_ptarray(poly1->rings[i],
-                                                             poly2->rings[j]);
-                       if ( d <= 0 ) return 0.0;
 
-                       /* mindist is -1 when not yet set */
-                       if (mindist > -1) mindist = LW_MIN(mindist, d);
-                       else mindist = d;
+       s = ( (A->y-p->y)*(B->x-A->x)- (A->x-p->x)*(B->y-A->y) ) /
+           ( (B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) );
+
+       return LW_ABS(s) * sqrt(
+                  (B->x-A->x)*(B->x-A->x) + (B->y-A->y)*(B->y-A->y)
+              );
+}
 
-                       LWDEBUGF(3, "  ring%i-%i dist: %f, mindist: %f", i, j, d, mindist);
-               }
 
-       }
 
-       /* otherwise return closest approach of rings (no intersection) */
-       return mindist;
 
-}
 
-double distance2d_line_poly(LWLINE *line, LWPOLY *poly)
-{
-       return distance2d_ptarray_poly(line->points, poly);
-}
 
 
-/*find the 2d length of the given POINTARRAY (even if it's 3d) */
-double lwgeom_pointarray_length2d(POINTARRAY *pts)
+/**
+find the 2d length of the given POINTARRAY (even if it's 3d)
+*/
+double
+lwgeom_pointarray_length2d(POINTARRAY *pts)
 {
        double dist = 0.0;
        int i;
@@ -517,7 +1488,7 @@ double lwgeom_pointarray_length2d(POINTARRAY *pts)
        POINT2D to;
 
        if ( pts->npoints < 2 ) return 0.0;
-       for (i=0; i<pts->npoints-1;i++)
+       for (i=0; i<pts->npoints-1; i++)
        {
                getPoint2d_p(pts, i, &frm);
                getPoint2d_p(pts, i+1, &to);
@@ -527,7 +1498,7 @@ double lwgeom_pointarray_length2d(POINTARRAY *pts)
        return dist;
 }
 
-/*
+/**
  * Find the 3d/2d length of the given POINTARRAY
  * (depending on its dimensions)
  */
@@ -544,7 +1515,7 @@ lwgeom_pointarray_length(POINTARRAY *pts)
        /* compute 2d length if 3d is not available */
        if ( ! TYPE_HASZ(pts->dims) ) return lwgeom_pointarray_length2d(pts);
 
-       for (i=0; i<pts->npoints-1;i++)
+       for (i=0; i<pts->npoints-1; i++)
        {
                getPoint3dz_p(pts, i, &frm);
                getPoint3dz_p(pts, i+1, &to);
@@ -552,11 +1523,10 @@ lwgeom_pointarray_length(POINTARRAY *pts)
                              ((frm.y - to.y)*(frm.y - to.y) ) +
                              ((frm.z - to.z)*(frm.z - to.z) ) );
        }
-
        return dist;
 }
 
-/*
+/**
  * This should be rewritten to make use of the curve itself.
  */
 double
@@ -566,7 +1536,7 @@ lwgeom_curvepolygon_area(LWCURVEPOLY *curvepoly)
        return lwgeom_polygon_area(poly);
 }
 
-/*
+/**
  * Find the area of the outer ring - sum (area of inner rings).
  * Could use a more numerically stable calculator...
  */
@@ -610,11 +1580,12 @@ lwgeom_polygon_area(LWPOLY *poly)
        return poly_area;
 }
 
-/*
+/**
  * Compute the sum of polygon rings length.
  * Could use a more numerically stable calculator...
  */
-double lwgeom_polygon_perimeter(LWPOLY *poly)
+double
+lwgeom_polygon_perimeter(LWPOLY *poly)
 {
        double result=0.0;
        int i;
@@ -627,11 +1598,12 @@ double lwgeom_polygon_perimeter(LWPOLY *poly)
        return result;
 }
 
-/*
+/**
  * Compute the sum of polygon rings length (forcing 2d computation).
  * Could use a more numerically stable calculator...
  */
-double lwgeom_polygon_perimeter2d(LWPOLY *poly)
+double
+lwgeom_polygon_perimeter2d(LWPOLY *poly)
 {
        double result=0.0;
        int i;
@@ -644,165 +1616,6 @@ double lwgeom_polygon_perimeter2d(LWPOLY *poly)
        return result;
 }
 
-double
-lwgeom_mindistance2d_recursive(uchar *lw1, uchar *lw2)
-{
-       return lwgeom_mindistance2d_recursive_tolerance( lw1, lw2, 0.0 );
-}
-
-double
-lwgeom_mindistance2d_recursive_tolerance(uchar *lw1, uchar *lw2, double tolerance)
-{
-       LWGEOM_INSPECTED *in1, *in2;
-       int i, j;
-       double mindist = -1;
-
-       in1 = lwgeom_inspect(lw1);
-       in2 = lwgeom_inspect(lw2);
-
-       for (i=0; i<in1->ngeometries; i++)
-       {
-               uchar *g1 = lwgeom_getsubgeometry_inspected(in1, i);
-               int t1 = lwgeom_getType(g1[0]);
-               double dist=tolerance;
-
-               /* Argument 1 is a multitype... recurse */
-               if ( lwgeom_is_collection(t1) )
-               {
-                       dist = lwgeom_mindistance2d_recursive_tolerance(g1, lw2, tolerance);
-                       if ( dist <= tolerance ) return tolerance; /* can't be closer */
-                       if ( mindist == -1 ) mindist = dist;
-                       else mindist = LW_MIN(dist, mindist);
-                       continue;
-               }
-
-               for (j=0; j<in2->ngeometries; j++)
-               {
-                       uchar *g2 = lwgeom_getsubgeometry_inspected(in2, j);
-                       int t2 = lwgeom_getType(g2[0]);
-
-                       /* Argument 2 is a multitype... recurse */
-                       if ( lwgeom_is_collection(t2) )
-                       {
-                               dist = lwgeom_mindistance2d_recursive_tolerance(g1, g2, tolerance);
-                               if ( dist <= tolerance ) return tolerance; /* can't be closer */
-                               if ( mindist == -1 ) mindist = dist;
-                               else mindist = LW_MIN(dist, mindist);
-                               continue;
-                       }
-
-                       if  ( t1 == POINTTYPE )
-                       {
-                               if  ( t2 == POINTTYPE )
-                               {
-                                       dist = distance2d_point_point(
-                                                  lwpoint_deserialize(g1),
-                                                  lwpoint_deserialize(g2)
-                                              );
-                               }
-                               else if  ( t2 == LINETYPE )
-                               {
-                                       dist = distance2d_point_line(
-                                                  lwpoint_deserialize(g1),
-                                                  lwline_deserialize(g2)
-                                              );
-                               }
-                               else if  ( t2 == POLYGONTYPE )
-                               {
-                                       dist = distance2d_point_poly(
-                                                  lwpoint_deserialize(g1),
-                                                  lwpoly_deserialize(g2)
-                                              );
-                               }
-                               else
-                               {
-                                       lwerror("Unsupported geometry type: %s", lwgeom_typename(t2));
-                               }
-                       }
-                       else if ( t1 == LINETYPE )
-                       {
-                               if ( t2 == POINTTYPE )
-                               {
-                                       dist = distance2d_point_line(
-                                                  lwpoint_deserialize(g2),
-                                                  lwline_deserialize(g1)
-                                              );
-                               }
-                               else if ( t2 == LINETYPE )
-                               {
-                                       dist = distance2d_line_line(
-                                                  lwline_deserialize(g1),
-                                                  lwline_deserialize(g2)
-                                              );
-                               }
-                               else if ( t2 == POLYGONTYPE )
-                               {
-                                       dist = distance2d_line_poly(
-                                                  lwline_deserialize(g1),
-                                                  lwpoly_deserialize(g2)
-                                              );
-                               }
-                               else
-                               {
-                                       lwerror("Unsupported geometry type: %s", lwgeom_typename(t2));
-                               }
-                       }
-                       else if ( t1 == POLYGONTYPE )
-                       {
-                               if ( t2 == POLYGONTYPE )
-                               {
-                                       dist = distance2d_poly_poly(
-                                                  lwpoly_deserialize(g2),
-                                                  lwpoly_deserialize(g1)
-                                              );
-                               }
-                               else if ( t2 == POINTTYPE )
-                               {
-                                       dist = distance2d_point_poly(
-                                                  lwpoint_deserialize(g2),
-                                                  lwpoly_deserialize(g1)
-                                              );
-                               }
-                               else if ( t2 == LINETYPE )
-                               {
-                                       dist = distance2d_line_poly(
-                                                  lwline_deserialize(g2),
-                                                  lwpoly_deserialize(g1)
-                                              );
-                               }
-                               else
-                               {
-                                       lwerror("Unsupported geometry type: %s", lwgeom_typename(t2));
-                               }
-                       }
-//                     else if (lwgeom_is_collection(t1)) /* it's a multitype... recurse */
-//                     {
-//                             dist = lwgeom_mindistance2d_recursive_tolerance(g1, g2, tolerance);
-//                     }
-                       else
-                       {
-                               lwerror("Unsupported geometry type: %s", lwgeom_typename(t1));
-                       }
-
-                       if (mindist == -1 ) mindist = dist;
-                       else mindist = LW_MIN(dist, mindist);
-
-                       LWDEBUGF(3, "dist %d-%d: %f - mindist: %f",
-                                i, j, dist, mindist);
-
-
-                       if (mindist <= tolerance) return tolerance; /* can't be closer */
-
-               }
-
-       }
-
-       if (mindist<0) mindist = 0;
-
-       return mindist;
-}
-
-
 
 int
 lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad)
@@ -817,7 +1630,7 @@ lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad)
 
 }
 
-/*
+/**
  * Compute the azimuth of segment AB in radians.
  * Return 0 on exception (same point), 1 otherwise.
  */
@@ -870,3 +1683,4 @@ azimuth_pt_pt(POINT2D *A, POINT2D *B, double *d)
        return 1;
 }
 
+
diff --git a/liblwgeom/measures.h b/liblwgeom/measures.h
new file mode 100644 (file)
index 0000000..62c1da9
--- /dev/null
@@ -0,0 +1,74 @@
+
+/**********************************************************************
+ * $Id: measures.h 4715 2009-11-01 17:58:42Z nicklas $
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ * Copyright 2007-2008 Mark Cave-Ayland
+ * Copyright 2008 Paul Ramsey <pramsey@cleverelephant.ca>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ *
+ **********************************************************************/
+
+#include "liblwgeom.h"
+
+
+/**
+
+Structure used in distance-calculations
+*/
+typedef struct
+{
+       double distance;        /*the distance between p1 and p2*/
+       POINT2D p1;
+       POINT2D p2;
+       int mode;       /*the direction of looking, if thedir = -1 then we look for maxdistance and if it is 1 then we look for mindistance*/
+       int twisted; /*To preserve the order of incoming points to match the first and secon point in shortest and longest line*/
+       double tolerance; /*the tolerance for dwithin and dfullywithin*/
+} DISTPTS;
+
+typedef struct
+{
+       double  themeasure;     /*a value calculated to compare distances*/
+       int             pnr;    /*pointnumber. the ordernumber of the point*/
+} LISTSTRUCT;
+
+
+/*
+Preprocessing functions
+*/
+int lw_dist2d_comp(uchar *lw1, uchar *lw2, DISTPTS *dl);
+int lw_dist2d_distribute_bruteforce(LWGEOM *lwg1, LWGEOM *lwg2, DISTPTS *dl);
+int lw_dist2d_recursive(const LWCOLLECTION * lwg1,const LWCOLLECTION * lwg2, DISTPTS *dl);
+int lw_dist2d_check_overlap(LWGEOM *lwg1,LWGEOM *lwg2);
+int lw_dist2d_distribute_fast(LWGEOM *lwg1, LWGEOM *lwg2, DISTPTS *dl);
+/*
+Brute force functions
+*/
+
+int lw_dist2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D, DISTPTS *dl);
+int lw_dist2d_pt_ptarray(POINT2D *p, POINTARRAY *pa, DISTPTS *dl);
+int lw_dist2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2, DISTPTS *dl);
+int lw_dist2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly, DISTPTS *dl);
+int lw_dist2d_point_point(LWPOINT *point1, LWPOINT *point2, DISTPTS *dl);
+int lw_dist2d_point_line(LWPOINT *point, LWLINE *line, DISTPTS *dl);
+int lw_dist2d_line_line(LWLINE *line1, LWLINE *line2, DISTPTS *dl);
+int lw_dist2d_point_poly(LWPOINT *point, LWPOLY *poly, DISTPTS *dl);
+int lw_dist2d_poly_poly(LWPOLY *poly1, LWPOLY *poly2, DISTPTS *dl);
+int lw_dist2d_line_poly(LWLINE *line, LWPOLY *poly, DISTPTS *dl);
+/*
+New faster distance calculations
+*/
+
+int lw_dist2d_pre_seg_seg(POINTARRAY *l1, POINTARRAY *l2,LISTSTRUCT *list1, LISTSTRUCT *list2,double k, DISTPTS *dl);
+int lw_dist2d_selected_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D, DISTPTS *dl);
+int struct_cmp_by_measure(const void *a, const void *b);
+int lw_dist2d_fast_ptarray_ptarray(POINTARRAY *l1,POINTARRAY *l2, DISTPTS *dl, BOX2DFLOAT4 *box1, BOX2DFLOAT4 *box2);
+/*
+Functions in common for Brute force and new calculation
+*/
+int lw_dist2d_pt_pt(POINT2D *p1, POINT2D *p2, DISTPTS *dl);
+int lw_dist2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B, DISTPTS *dl);
index bb8ee4236f5c1533c293f47f695f804b119eb489..8ca3777f16f2383e8b6dd40fab187c5881cc1401 100644 (file)
@@ -33,6 +33,7 @@ Datum LWGEOM_npoints(PG_FUNCTION_ARGS);
 Datum LWGEOM_nrings(PG_FUNCTION_ARGS);
 Datum LWGEOM_area_polygon(PG_FUNCTION_ARGS);
 Datum LWGEOM_dwithin(PG_FUNCTION_ARGS);
+Datum LWGEOM_dfullywithin(PG_FUNCTION_ARGS);
 Datum postgis_uses_stats(PG_FUNCTION_ARGS);
 Datum postgis_autocache_bbox(PG_FUNCTION_ARGS);
 Datum postgis_scripts_released(PG_FUNCTION_ARGS);
@@ -44,8 +45,11 @@ Datum LWGEOM_length2d_linestring(PG_FUNCTION_ARGS);
 Datum LWGEOM_length_linestring(PG_FUNCTION_ARGS);
 Datum LWGEOM_perimeter2d_poly(PG_FUNCTION_ARGS);
 Datum LWGEOM_perimeter_poly(PG_FUNCTION_ARGS);
-Datum LWGEOM_mindistance2d(PG_FUNCTION_ARGS);
 Datum LWGEOM_maxdistance2d_linestring(PG_FUNCTION_ARGS);
+Datum LWGEOM_mindistance2d(PG_FUNCTION_ARGS);
+Datum LWGEOM_closestpoint(PG_FUNCTION_ARGS);
+Datum LWGEOM_shortestline2d(PG_FUNCTION_ARGS);
+Datum LWGEOM_longestline2d(PG_FUNCTION_ARGS);
 Datum LWGEOM_inside_circle_point(PG_FUNCTION_ARGS);
 Datum LWGEOM_collect(PG_FUNCTION_ARGS);
 Datum LWGEOM_accum(PG_FUNCTION_ARGS);
@@ -1544,7 +1548,110 @@ Datum LWGEOM_force_multi(PG_FUNCTION_ARGS)
        PG_RETURN_POINTER(result);
 }
 
-/* Minimum 2d distance between objects in geom1 and geom2. */
+/**
+Returns the point in first input geometry that is closest to the second input geometry
+*/
+
+PG_FUNCTION_INFO_V1(LWGEOM_closestpoint);
+Datum LWGEOM_closestpoint(PG_FUNCTION_ARGS)
+{
+
+
+       int srid;
+       PG_LWGEOM *geom1;
+       PG_LWGEOM *geom2;
+
+       PG_LWGEOM *result=NULL;
+       LWGEOM *point;
+
+       geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+
+       if (pglwgeom_getSRID(geom1) != pglwgeom_getSRID(geom2))
+       {
+               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
+               PG_RETURN_NULL();
+       }
+
+       srid = pglwgeom_getSRID(geom1);
+
+       point = lw_dist2d_distancepoint( SERIALIZED_FORM(geom1),SERIALIZED_FORM(geom2), srid, DIST2D_MIN);
+       if(lwgeom_is_empty(point))
+       {
+               PG_RETURN_NULL();
+       }
+       result = pglwgeom_serialize(point);
+       PG_RETURN_POINTER(result);
+}
+
+/**
+Returns the shortest line between two geometries
+*/
+PG_FUNCTION_INFO_V1(LWGEOM_shortestline2d);
+Datum LWGEOM_shortestline2d(PG_FUNCTION_ARGS)
+{
+       int srid;
+       PG_LWGEOM *geom1;
+       PG_LWGEOM *geom2;
+
+       PG_LWGEOM *result=NULL;
+       LWGEOM *theline;
+
+       geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+
+       if (pglwgeom_getSRID(geom1) != pglwgeom_getSRID(geom2))
+       {
+               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
+               PG_RETURN_NULL();
+       }
+
+       srid = pglwgeom_getSRID(geom1);
+
+       theline = lw_dist2d_distanceline( SERIALIZED_FORM(geom1),SERIALIZED_FORM(geom2), srid, DIST2D_MIN);
+       if(lwgeom_is_empty(theline))
+       {
+               PG_RETURN_NULL();
+       }
+       result = pglwgeom_serialize(theline);
+       PG_RETURN_POINTER(result);
+}
+
+/**
+Returns the longest line between two geometries
+*/
+PG_FUNCTION_INFO_V1(LWGEOM_longestline2d);
+Datum LWGEOM_longestline2d(PG_FUNCTION_ARGS)
+{
+       int srid;
+       PG_LWGEOM *geom1;
+       PG_LWGEOM *geom2;
+
+       PG_LWGEOM *result=NULL;
+       LWGEOM *theline;
+
+       geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+
+       if (pglwgeom_getSRID(geom1) != pglwgeom_getSRID(geom2))
+       {
+               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
+               PG_RETURN_NULL();
+       }
+
+       srid = pglwgeom_getSRID(geom1);
+
+       theline = lw_dist2d_distanceline( SERIALIZED_FORM(geom1),SERIALIZED_FORM(geom2), srid, DIST2D_MAX);
+       if(lwgeom_is_empty(theline))
+       {
+               PG_RETURN_NULL();
+       }
+       result = pglwgeom_serialize(theline);
+       PG_RETURN_POINTER(result);
+}
+/**
+ Minimum 2d distance between objects in geom1 and geom2. 
+ */
 PG_FUNCTION_INFO_V1(LWGEOM_mindistance2d);
 Datum LWGEOM_mindistance2d(PG_FUNCTION_ARGS)
 {
@@ -1563,7 +1670,7 @@ Datum LWGEOM_mindistance2d(PG_FUNCTION_ARGS)
                PG_RETURN_NULL();
        }
 
-       mindist = lwgeom_mindistance2d_recursive(SERIALIZED_FORM(geom1),
+       mindist = lwgeom_mindistance2d(SERIALIZED_FORM(geom1),
                  SERIALIZED_FORM(geom2));
 
        PROFSTOP(PROF_QRUN);
@@ -1571,11 +1678,19 @@ Datum LWGEOM_mindistance2d(PG_FUNCTION_ARGS)
 
        PG_FREE_IF_COPY(geom1, 0);
        PG_FREE_IF_COPY(geom2, 1);
-
-       PG_RETURN_FLOAT8(mindist);
+       /*if called with empty geometries the ingoing mindistance is untouched, and makes us return NULL*/
+       if (mindist<MAXFLOAT)
+       {
+       PG_RETURN_FLOAT8(mindist);              
+       }
+       PG_RETURN_NULL();
 }
 
-/* Minimum 2d distance between objects in geom1 and geom2. */
+/**
+Returns boolean describing if
+mininimum 2d distance between objects in 
+geom1 and geom2 is shorter than tolerance
+*/
 PG_FUNCTION_INFO_V1(LWGEOM_dwithin);
 Datum LWGEOM_dwithin(PG_FUNCTION_ARGS)
 {
@@ -1601,7 +1716,7 @@ Datum LWGEOM_dwithin(PG_FUNCTION_ARGS)
                PG_RETURN_NULL();
        }
 
-       mindist = lwgeom_mindistance2d_recursive_tolerance(
+       mindist = lwgeom_mindistance2d_tolerance(
                      SERIALIZED_FORM(geom1),
                      SERIALIZED_FORM(geom2),
                      tolerance
@@ -1612,36 +1727,72 @@ Datum LWGEOM_dwithin(PG_FUNCTION_ARGS)
 
        PG_FREE_IF_COPY(geom1, 0);
        PG_FREE_IF_COPY(geom2, 1);
-
+/*empty geometries cases should be right handled since return from underlying
+ functions should be MAXFLOAT which causes false as answer*/
        PG_RETURN_BOOL(tolerance >= mindist);
 }
 
-/*
- *  Maximum 2d distance between linestrings.
- *  Returns NULL if given geoms are not linestrings.
- *  This is very bogus (or I'm missing its meaning)
+/**
+Returns boolean describing if
+maximum 2d distance between objects in 
+geom1 and geom2 is shorter than tolerance
+*/
+PG_FUNCTION_INFO_V1(LWGEOM_dfullywithin);
+Datum LWGEOM_dfullywithin(PG_FUNCTION_ARGS)
+{
+       PG_LWGEOM *geom1;
+       PG_LWGEOM *geom2;
+       double maxdist, tolerance;
+
+       PROFSTART(PROF_QRUN);
+
+       geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+       tolerance = PG_GETARG_FLOAT8(2);
+
+       if ( tolerance < 0 )
+       {
+               elog(ERROR,"Tolerance cannot be less than zero\n");
+               PG_RETURN_NULL();
+       }
+
+       if (pglwgeom_getSRID(geom1) != pglwgeom_getSRID(geom2))
+       {
+               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
+               PG_RETURN_NULL();
+       }
+       maxdist = lwgeom_maxdistance2d_tolerance(
+                                 SERIALIZED_FORM(geom1),
+                                 SERIALIZED_FORM(geom2),
+                                 tolerance
+                         );
+       PROFSTOP(PROF_QRUN);
+       PROFREPORT("dist",geom1, geom2, NULL);
+
+       PG_FREE_IF_COPY(geom1, 0);
+       PG_FREE_IF_COPY(geom2, 1);
+       /*If function is feed with empty geometries we should return false*/
+       if (maxdist>-1)
+       {
+               PG_RETURN_BOOL(tolerance >= maxdist);
+       }
+       PG_RETURN_BOOL(LW_FALSE);       
+}
+
+/**
+ Maximum 2d distance between objects in geom1 and geom2. 
  */
 PG_FUNCTION_INFO_V1(LWGEOM_maxdistance2d_linestring);
 Datum LWGEOM_maxdistance2d_linestring(PG_FUNCTION_ARGS)
 {
-
        PG_LWGEOM *geom1;
        PG_LWGEOM *geom2;
-       LWLINE *line1;
-       LWLINE *line2;
-       double maxdist = 0;
-       int i;
+       double maxdist;
 
-       elog(ERROR, "This function is unimplemented yet");
-       PG_RETURN_NULL();
+       PROFSTART(PROF_QRUN);
 
        geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       line1 = lwline_deserialize(SERIALIZED_FORM(geom1));
-       if ( line1 == NULL ) PG_RETURN_NULL(); /* not a linestring */
-
        geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-       line2 = lwline_deserialize(SERIALIZED_FORM(geom2));
-       if ( line2 == NULL ) PG_RETURN_NULL(); /* not a linestring */
 
        if (pglwgeom_getSRID(geom1) != pglwgeom_getSRID(geom2))
        {
@@ -1649,30 +1800,24 @@ Datum LWGEOM_maxdistance2d_linestring(PG_FUNCTION_ARGS)
                PG_RETURN_NULL();
        }
 
-       for (i=0; i<line1->points->npoints; i++)
-       {
-               POINT2D p;
-               double dist;
 
-               getPoint2d_p(line1->points, i, &p);
-               dist = distance2d_pt_ptarray(&p, line2->points);
+       maxdist = lwgeom_maxdistance2d(SERIALIZED_FORM(geom1),
+                 SERIALIZED_FORM(geom2));
 
-               if (dist > maxdist) maxdist = dist;
-       }
+       PROFSTOP(PROF_QRUN);
+       PROFREPORT("maxdist",geom1, geom2, NULL);
 
        PG_FREE_IF_COPY(geom1, 0);
        PG_FREE_IF_COPY(geom2, 1);
-
-       PG_RETURN_FLOAT8(maxdist);
+       /*if called with empty geometries the ingoing mindistance is untouched, and makes us return NULL*/
+       if (maxdist>-1)
+       {
+               PG_RETURN_FLOAT8(maxdist);      
+       }
+       PG_RETURN_NULL();
 }
 
-/**
- * @brief Longitude shift:
- *     Y remains the same
- *     X is converted:
- *                     from -180..180 to 0..360
- *                     from 0..360 to -180..180
- */
+
 PG_FUNCTION_INFO_V1(LWGEOM_longitude_shift);
 Datum LWGEOM_longitude_shift(PG_FUNCTION_ARGS)
 {
index 74ef91e3f7a9f6f91711c68ca79b4bc2eb605565..0d0b1a261473d455fefb81064c4307187ad9c475 100644 (file)
@@ -1324,19 +1324,6 @@ CREATE OR REPLACE FUNCTION ST_Distance(geometry,geometry)
        LANGUAGE 'C' IMMUTABLE STRICT
        COST 100;
 
--- Maximum distance between linestrings. 2d only. Very bogus.
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION max_distance(geometry,geometry)
-       RETURNS float8
-       AS 'MODULE_PATHNAME', 'LWGEOM_maxdistance2d_linestring'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_max_distance(geometry,geometry)
-       RETURNS float8
-       AS 'MODULE_PATHNAME', 'LWGEOM_maxdistance2d_linestring'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
 -- Deprecation in 1.2.3
 CREATE OR REPLACE FUNCTION point_inside_circle(geometry,float8,float8,float8)
        RETURNS bool
@@ -5987,6 +5974,58 @@ CREATE OR REPLACE FUNCTION ST_GeomCollFromWKB(bytea)
        '
        LANGUAGE 'SQL' IMMUTABLE STRICT;
 
+--New functions
+
+-- Maximum distance between linestrings.
+
+CREATE OR REPLACE FUNCTION max_distance(geometry,geometry)
+       RETURNS float8
+       AS 'MODULE_PATHNAME', 'LWGEOM_maxdistance2d_linestring'
+       LANGUAGE 'C' IMMUTABLE STRICT; 
+
+-- Availability: 1.5.0
+CREATE OR REPLACE FUNCTION _ST_MaxDistance(geometry,geometry)
+       RETURNS float8
+       AS 'MODULE_PATHNAME', 'LWGEOM_maxdistance2d_linestring'
+       LANGUAGE 'C' IMMUTABLE STRICT; 
+       
+-- Availability: 1.5.0
+CREATE OR REPLACE FUNCTION ST_MaxDistance(geometry,geometry)
+       RETURNS float8
+       AS 'SELECT _ST_MaxDistance(ST_ConvexHull($1), ST_ConvexHull($2))'
+       LANGUAGE 'SQL' IMMUTABLE STRICT; 
+
+CREATE OR REPLACE FUNCTION ST_ClosestPoint(geometry,geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'LWGEOM_closestpoint'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION ST_ShortestLine(geometry,geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'LWGEOM_shortestline2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION _ST_LongestLine(geometry,geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'LWGEOM_longestline2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION ST_LongestLine(geometry,geometry)
+       RETURNS geometry
+       AS 'SELECT _ST_LongestLine(ST_ConvexHull($1), ST_ConvexHull($2))'
+       LANGUAGE 'SQL' IMMUTABLE STRICT; 
+
+CREATE OR REPLACE FUNCTION _ST_DFullyWithin(geometry,geometry,float8)
+       RETURNS boolean
+       AS 'MODULE_PATHNAME', 'LWGEOM_dfullywithin'
+       LANGUAGE 'C' IMMUTABLE STRICT; 
+
+CREATE OR REPLACE FUNCTION ST_DFullyWithin(geometry, geometry, float8)
+       RETURNS boolean
+       AS 'SELECT $1 && ST_Expand($2,$3) AND $2 && ST_Expand($1,$3) AND _ST_DFullyWithin(ST_ConvexHull($1), ST_ConvexHull($2), $3)'
+       LANGUAGE 'SQL' IMMUTABLE; 
+       
+       
 --
 -- SFSQL 1.1
 --
index e50ece640321342e3473311b4a4ba90bceba6daf..5a1bec99c3c4023a1ba3f3aefb0ce8313cfde752 100644 (file)
@@ -26,7 +26,9 @@ BEGIN;
 
 DROP FUNCTION ST_MinimumBoundingCircle(geometry);
 DROP FUNCTION ST_MinimumBoundingCircle(inputgeom geometry, segs_per_quarter integer);
-
+DROP FUNCTION ST_ShortestLine(geometry, geometry);
+DROP FUNCTION ST_LongestLine(geometry, geometry);
+DROP FUNCTION ST_DFullyWithin(geometry, geometry, float8);
 ---------------------------------------------------------------
 -- SQL-MM
 ---------------------------------------------------------------
index 3f0b8b648d63c4bb8cc56661ca4b6191f5af5a6b..ec6a6eaef462627930429aa09c5c7678aa569ec1 100644 (file)
@@ -47,6 +47,163 @@ select 'dist', ST_distance(a,b), ST_distance(b,a) from (
        ) as foo;
 
 
+--st_shortestline
+
+select 'st_shortestline_134', st_astext(st_shortestline('POINT(1 2)', 'POINT(1 2)'));
+select 'st_shortestline_135', st_astext(st_shortestline('POINT(5 0)', 'POINT(10 12)'));
+
+select 'st_shortestline_136', st_astext(st_shortestline('POINT(0 0)', ST_translate('POINT(0 0)', 5, 12, 0)));
+
+-- postgis-users/2006-May/012174.html
+select 'st_shortestline_dist', st_astext(st_shortestline(a,b)), st_astext(st_shortestline(b,a)) from (
+       select 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry as a,
+               'POLYGON((11 0, 12 10, 20 10, 20 0, 11 0),
+                       (15 5, 15 8, 17 8, 17 5, 15 5))'::geometry as b
+       ) as foo;
+
+
+--st_maxdistance
+
+select 'st_maxdistance_134', st_maxdistance('POINT(1 2)', 'POINT(1 2)');
+select 'st_maxdistance_135', st_maxdistance('POINT(5 0)', 'POINT(10 12)');
+
+select 'st_maxdistance_136', st_maxdistance('POINT(0 0)', ST_translate('POINT(0 0)', 5, 12, 0));
+
+-- postgis-users/2006-May/012174.html
+select 'st_maxdistance_dist', st_maxdistance(a,b), st_maxdistance(b,a) from (
+       select 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry as a,
+               'POLYGON((11 0, 11 10, 20 10, 20 0, 11 0),
+                       (15 5, 15 8, 17 8, 17 5, 15 5))'::geometry as b
+       ) as foo;
+
+
+
+--st_longestline
+
+select 'st_longestline_134', st_astext(st_longestline('POINT(1 2)', 'POINT(1 2)'));
+select 'st_longestline_135', st_astext(st_longestline('POINT(5 0)', 'POINT(10 12)'));
+
+select 'st_longestline_136', st_astext(st_longestline('POINT(0 0)', ST_translate('POINT(0 0)', 5, 12, 0)));
+
+-- postgis-users/2006-May/012174.html
+select 'st_longestline_dist', st_astext(st_longestline(a,b)), st_astext(st_longestline(b,a)) from (
+       select 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry as a,
+               'POLYGON((11 0, 11 10, 20 10, 20 0, 11 0),
+                       (15 5, 15 8, 17 8, 17 5, 15 5))'::geometry as b
+       ) as foo;
+
+       
+
+
+
+
+select 'distancetest1',                
+               st_distance(a, b),
+                       st_maxdistance(a, b),
+                               st_astext(st_shortestline(a,b)),
+                                       st_astext(st_shortestline(b,a)),
+                                               st_astext(st_longestline(a,b)),
+                                                       st_astext(st_longestline(b,a)) from (
+       select geomfromtext('MULTILINESTRING((17 16, 16 17, 17 18, 17 17, 17 16), (28 35,29 39, 30 35))') as a,
+                       geomfromtext('MULTIPOLYGON(((-1 -1, -1 25, 25 25, 25 -1, -1 -1), (14 14,14 19,19 19,19 14,14 14)),
+                       ((33 35,33 40, 35 40, 35 35, 33 35)))') as b
+       ) as foo;
+
+
+
+select  'distancetest2',
+               st_distance(a, b),
+                       st_maxdistance(a, b),
+                               st_astext(st_shortestline(a,b)),
+                                       st_astext(st_shortestline(b,a)),
+                                               st_astext(st_longestline(a,b)),
+                                                       st_astext(st_longestline(b,a)) from (
+       select geomfromtext('LINESTRING(-40 -20 , 4 2)') as a,
+               geomfromtext('LINESTRING(-10 20, 1 -2)') as b
+       ) as foo;
+
+       
+
+select 'distancepoly1',                
+               st_distance(a, b),
+                       st_maxdistance(a, b),
+                               st_astext(st_shortestline(a,b)),
+                                       st_astext(st_shortestline(b,a)),
+                                               st_astext(st_longestline(a,b)),
+                                                       st_astext(st_longestline(b,a)) from (
+       select geomfromtext('MULTIPOLYGON(((17 16, 16 17, 17 18, 17 17, 17 16)), ((28 35,29 39, 30 35, 28 35)))') as a,
+                       geomfromtext('MULTIPOLYGON(((-1 -1, -1 25, 25 25, 25 -1, -1 -1), (14 14,14 19,19 19,19 14,14 14)),
+                       ((33 35,33 40, 35 40, 35 35, 33 35)))') as b
+       ) as foo;
+
+
+
+select 'distancepoly2',                
+               st_distance(a, b),
+                       st_maxdistance(a, b),
+                               st_astext(st_shortestline(a,b)),
+                                       st_astext(st_shortestline(b,a)),
+                                               st_astext(st_longestline(a,b)),
+                                                       st_astext(st_longestline(b,a)) from (
+       select geomfromtext('POLYGON((17 14, 16 17, 17 18, 17 17, 17 14))') as a,
+                       geomfromtext('POLYGON((-1 -1, -1 25, 25 25, 25 -1, -1 -1), (14 14,14 19,19 19,19 14,14 14))') as b
+       ) as foo;
+
+
+
+select 'distancepoly3',                
+               st_distance(a, b),
+                       st_maxdistance(a, b),
+                               st_astext(st_shortestline(a,b)),
+                                       st_astext(st_shortestline(b,a)),
+                                               st_astext(st_longestline(a,b)),
+                                                       st_astext(st_longestline(b,a)) from (
+       select geomfromtext('POLYGON((17 16, 16 17, 17 19, 17 17, 17 16))') as a,
+                       geomfromtext('POLYGON((-1 -1, -1 25, 25 25, 25 -1, -1 -1), (14 14,14 19,19 19,19 14,14 14))') as b
+       ) as foo;
+
+
+select 'distancepoly4',                
+               st_distance(a, b),
+                       st_maxdistance(a, b),
+                               st_astext(st_shortestline(a,b)),
+                                       st_astext(st_shortestline(b,a)),
+                                               st_astext(st_longestline(a,b)),
+                                                       st_astext(st_longestline(b,a)) from (
+       select geomfromtext('POLYGON((17 16, 16 17, 16 20, 18 20, 18 17, 17 16))') as a,
+                       geomfromtext('POLYGON((-1 -1, -1 25, 25 25, 25 -1, -1 -1), (14 14,14 19,19 19,19 14,14 14))') as b
+       ) as foo;
+
+
+
+select 'distancepoly5',                
+               st_distance(a, b),
+                       st_maxdistance(a, b),
+                               st_astext(st_shortestline(a,b)),
+                                       st_astext(st_shortestline(b,a)),
+                                               st_astext(st_longestline(a,b)),
+                                                       st_astext(st_longestline(b,a)) from (
+       select geomfromtext('POLYGON((17 12, 16 17, 17 18, 17 17, 17 12))') as a,
+                       geomfromtext('POLYGON((-1 -1, -1 25, 25 25, 25 -1, -1 -1), (14 14,14 19,19 19,19 14,14 14))') as b
+       ) as foo;
+
+
+
+
+select 'distancepoly6',                
+               st_distance(a, b),
+                       st_maxdistance(a, b),
+                               st_astext(st_shortestline(a,b)),
+                                       st_astext(st_shortestline(b,a)),
+                                               st_astext(st_longestline(a,b)),
+                                                       st_astext(st_longestline(b,a)) from (
+       select geomfromtext('POLYGON((2 2, 2 3, 3 3, 3 2, 2 2))') as a,
+                       geomfromtext('POLYGON((-1 -1, -1 25, 25 25, 25 -1, -1 -1), (14 14,14 19,19 19,19 14,14 14))') as b
+       ) as foo;
+
+
+       
+
 -- Area of an empty polygon
 select 'emptyPolyArea', st_area('POLYGON EMPTY');
 
index 574fdc1f32646052c190edfc55c6f00005dc6782..c84e9b3c2b4038ef8c5c8f0d0c332896f1ce8799 100644 (file)
@@ -18,6 +18,26 @@ dist|1|1
 135|13
 136|13
 dist|1|1
+st_shortestline_134|LINESTRING(1 2,1 2)
+st_shortestline_135|LINESTRING(5 0,10 12)
+st_shortestline_136|LINESTRING(0 0,5 12)
+st_shortestline_dist|LINESTRING(10 0,11 0)|LINESTRING(11 0,10 0)
+st_maxdistance_134|0
+st_maxdistance_135|13
+st_maxdistance_136|13
+st_maxdistance_dist|22.3606797749979|22.3606797749979
+st_longestline_134|LINESTRING(1 2,1 2)
+st_longestline_135|LINESTRING(5 0,10 12)
+st_longestline_136|LINESTRING(0 0,5 12)
+st_longestline_dist|LINESTRING(0 0,20 10)|LINESTRING(20 10,0 0)
+distancetest1|1|50|LINESTRING(17 18,17 19)|LINESTRING(17 19,17 18)|LINESTRING(29 39,-1 -1)|LINESTRING(-1 -1,29 39)
+distancetest2|0|50|LINESTRING(0 0,0 0)|LINESTRING(0 0,0 0)|LINESTRING(-40 -20,-10 20)|LINESTRING(-10 20,-40 -20)
+distancepoly1|1|50|LINESTRING(17 18,17 19)|LINESTRING(17 19,17 18)|LINESTRING(29 39,-1 -1)|LINESTRING(-1 -1,29 39)
+distancepoly2|0|26.1725046566048|LINESTRING(17 14,17 14)|LINESTRING(17 14,17 14)|LINESTRING(17 18,-1 -1)|LINESTRING(-1 -1,17 18)
+distancepoly3|0|26.9072480941474|LINESTRING(17 19,17 19)|LINESTRING(17 19,17 19)|LINESTRING(17 19,-1 -1)|LINESTRING(-1 -1,17 19)
+distancepoly4|0|28.3196045170126|LINESTRING(16 19,16 19)|LINESTRING(16 19,16 19)|LINESTRING(18 20,-1 -1)|LINESTRING(-1 -1,18 20)
+distancepoly5|0|26.1725046566048|LINESTRING(17 12,17 12)|LINESTRING(17 12,17 12)|LINESTRING(17 18,-1 -1)|LINESTRING(-1 -1,17 18)
+distancepoly6|0|32.5269119345812|LINESTRING(2 2,2 2)|LINESTRING(2 2,2 2)|LINESTRING(2 2,25 25)|LINESTRING(25 25,2 2)
 emptyPolyArea|0
 emptyLineArea|0
 emptyPointArea|0