]> granicus.if.org Git - postgis/commitdiff
Changed locate_between_measures() to return simpler types
authorSandro Santilli <strk@keybit.net>
Wed, 23 Nov 2005 15:30:04 +0000 (15:30 +0000)
committerSandro Santilli <strk@keybit.net>
Wed, 23 Nov 2005 15:30:04 +0000 (15:30 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@2060 b70326c6-7e19-0410-871a-916f4a2858ee

lwgeom/lwgeom_functions_lrs.c
regress/regress_lrs.sql
regress/regress_lrs_expected

index ca491995ec8433165c4b563e9b8c3b9c99ef35bb..a7cba187bd3732a0524f479dd0b9f30536f2b95a 100644 (file)
@@ -17,7 +17,7 @@
 #include "math.h"
 
 #define DEBUG 0
-#define DEBUG_INERPOLATION 0
+#define DEBUG_INTERPOLATION 0
 
 Datum LWGEOM_locate_between_m(PG_FUNCTION_ARGS);
 
@@ -144,6 +144,22 @@ clip_seg_by_m_range(POINT4D *p1, POINT4D *p2, double m0, double m1)
                else ret |= 0x0010;
        }
 
+       /*
+        * if m0 and m1 have the same value
+        * avoid computation of second point to
+        * reduce rouding problems with floating
+        * numbers.
+        *
+        * The two points must be equal anyway.
+        */
+       if ( m0 == m1 )
+       {
+               memcpy(p2, p1, sizeof(POINT4D));
+               if ( swapped ) ret |= 0x0010;
+               else ret |= 0x0100;
+               return ret;
+       }
+
        /* 
         * Second point out of range, project 
         * it on the range
@@ -409,10 +425,14 @@ lwpoint_locate_between_m(LWPOINT *lwpoint, double m0, double m1)
 
 /*
  * Line is assumed to have an M value.
+ *
  * Return NULL if no parts of the line are in the given range (inclusive)
+ *
  * Return an LWCOLLECTION with LWLINES and LWPOINT being consecutive
  * and isolated points on the line falling in the range.
- * Points are interpolated.
+ *
+ * X,Y and Z (if present) ordinates are interpolated.
+ *
  */
 static LWGEOM *
 lwline_locate_between_m(LWLINE *lwline_in, double m0, double m1)
@@ -421,6 +441,10 @@ lwline_locate_between_m(LWLINE *lwline_in, double m0, double m1)
        int i;
        LWGEOM **geoms;
        int ngeoms;
+       int outtype;
+       int typeflag=0; /* see flags below */
+       const int pointflag=0x01;
+       const int lineflag=0x10;
 
 #if DEBUG
        lwnotice("lwline_locate_between called for lwline %x", lwline_in);
@@ -462,6 +486,7 @@ lwline_locate_between_m(LWLINE *lwline_in, double m0, double m1)
                        lwpoint->bbox=NULL;
                        lwpoint->point=pa;
                        geoms[i]=(LWGEOM *)lwpoint;
+                       typeflag|=pointflag;
                }
 
                /* This is a line */
@@ -478,6 +503,7 @@ lwline_locate_between_m(LWLINE *lwline_in, double m0, double m1)
                        lwline->bbox=NULL;
                        lwline->points=pa;
                        geoms[i]=(LWGEOM *)lwline;
+                       typeflag|=lineflag;
                }
 
                /* This is a bug */
@@ -488,8 +514,20 @@ lwline_locate_between_m(LWLINE *lwline_in, double m0, double m1)
 
        }
 
-       return (LWGEOM *)lwcollection_construct(COLLECTIONTYPE,
-               lwline_in->SRID, NULL, ngeoms, geoms);
+       if ( ngeoms == 1 )
+       {
+               return geoms[0];
+       }
+       else
+       {
+               /* Choose best type */
+               if ( typeflag == 1 ) outtype=MULTIPOINTTYPE;
+               else if ( typeflag == 2 ) outtype=MULTILINETYPE;
+               else outtype = COLLECTIONTYPE;
+
+               return (LWGEOM *)lwcollection_construct(outtype,
+                       lwline_in->SRID, NULL, ngeoms, geoms);
+       }
 }
 
 /*
@@ -555,6 +593,7 @@ lwgeom_locate_between_m(LWGEOM *lwin, double m0, double m1)
                /* Polygon types are not supported */
                case POLYGONTYPE:
                case MULTIPOLYGONTYPE:
+                       lwerror("Areal geometries are not supported by locate_between_measures");
                        return NULL;
        }
 
@@ -568,6 +607,7 @@ lwgeom_locate_between_m(LWGEOM *lwin, double m0, double m1)
  *
  * Implements SQL/MM ST_LocateBetween(measure, measure) method.
  * See ISO/IEC CD 13249-3:200x(E)
+ *
  */
 PG_FUNCTION_INFO_V1(LWGEOM_locate_between_m);
 Datum LWGEOM_locate_between_m(PG_FUNCTION_ARGS)
@@ -594,11 +634,13 @@ Datum LWGEOM_locate_between_m(PG_FUNCTION_ARGS)
        }
 
        /*
-        * Return NULL if input is a polygon, a multipolygon or a collection
+        * Raise an error if input is a polygon, a multipolygon
+        * or a collection
         */
        type=lwgeom_getType(gin->type);
        if ( type == POLYGONTYPE || type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE )
        {
+               lwerror("Areal or Collection types are not supported");
                PG_RETURN_NULL();
        }
 
index 3857dcaeeda05e10a7a89f563e22da0cfd7b588b..7d19f68404a27931c20d3fac4804b5b4dc2dd68f 100644 (file)
@@ -22,4 +22,4 @@ select 'LINEZM_2', asewkt(locate_between_measures('LINESTRING(0 10 0 0, 0 0 100
 select 'LINEZM_3', asewkt(locate_between_measures('LINESTRING(0 10 100 0, 0 0 0 10, 10 0 0 0)', 2, 18));
 select 'LINEZM_4', asewkt(locate_between_measures('LINESTRING(0 10 100 0, 0 0 0 20, 10 0 0 0)', 2, 18));
 select 'LINEZM_5', asewkt(locate_between_measures('LINESTRING(0 10 100 0, 0 0 0 20, 0 10 10 40, 10 0 0 0)', 2, 18));
-
+select 'LINEZM_6', asewkt(locate_between_measures('LINESTRING(0 10 10 40, 10 0 0 0)', 2, 2));
index 59c341eff4a4bd2d206950832c2d0e76dda739b0..fa73b41f890ded347aeb01cc535e1602b07e608a 100644 (file)
@@ -9,8 +9,9 @@ MPNT_1|GEOMETRYCOLLECTIONM(POINT(1 2 2))
 MPNT_2|GEOMETRYCOLLECTIONM(POINT(2 2 5))
 MPNT_3|GEOMETRYCOLLECTIONM EMPTY
 MPNT_4|GEOMETRYCOLLECTIONM(POINT(1 2 8),POINT(2 2 5))
-LINEZM_1|GEOMETRYCOLLECTION(LINESTRING(0 8 80 2,0 0 0 10))
-LINEZM_2|GEOMETRYCOLLECTION(LINESTRING(0 8 20 2,0 0 100 10))
-LINEZM_3|GEOMETRYCOLLECTION(LINESTRING(0 8 80 2,0 0 0 10,8 0 0 2))
+LINEZM_1|LINESTRING(0 8 80 2,0 0 0 10)
+LINEZM_2|LINESTRING(0 8 20 2,0 0 100 10)
+LINEZM_3|LINESTRING(0 8 80 2,0 0 0 10,8 0 0 2)
 LINEZM_4|GEOMETRYCOLLECTION(LINESTRING(0 9 90 2,0 1 10 18),LINESTRING(1 0 0 18,9 0 0 2))
 LINEZM_5|GEOMETRYCOLLECTION(LINESTRING(0 9 90 2,0 1 10 18),LINESTRING(5.5 4.5 4.5 18,9.5 0.5 0.5 2))
+LINEZM_6|POINT(9.5 0.5 0.5 2)