]> granicus.if.org Git - postgis/commitdiff
Flip ST_LocateBetween to use the same LRS code as ST_LocateBetweenElevations
authorPaul Ramsey <pramsey@cleverelephant.ca>
Thu, 12 Jan 2012 19:07:02 +0000 (19:07 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Thu, 12 Jan 2012 19:07:02 +0000 (19:07 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@8792 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/cunit/cu_algorithm.c
liblwgeom/liblwgeom.h.in
liblwgeom/liblwgeom_internal.h
liblwgeom/lwalgorithm.c
liblwgeom/lwlinearreferencing.c
postgis/lwgeom_functions_analytic.c
postgis/lwgeom_functions_basic.c
postgis/lwgeom_functions_lrs.c
postgis/postgis.sql.in.c

index 0341e02fa0c59dc165421ce83b037700ae55feed..ad03d08e64e705eb8fe637cb184d56a52d2f2c2f 100644 (file)
@@ -382,13 +382,13 @@ static void test_lwpoint_set_ordinate(void)
        p.z = 0.0;
        p.m = 0.0;
 
-       lwpoint_set_ordinate(&p, 0, 1.5);
+       lwpoint_set_ordinate(&p, 'X', 1.5);
        CU_ASSERT_EQUAL( p.x, 1.5 );
 
-       lwpoint_set_ordinate(&p, 3, 2.5);
+       lwpoint_set_ordinate(&p, 'M', 2.5);
        CU_ASSERT_EQUAL( p.m, 2.5 );
 
-       lwpoint_set_ordinate(&p, 2, 3.5);
+       lwpoint_set_ordinate(&p, 'Z', 3.5);
        CU_ASSERT_EQUAL( p.z, 3.5 );
 
 }
@@ -402,10 +402,10 @@ static void test_lwpoint_get_ordinate(void)
        p.z = 30.0;
        p.m = 40.0;
 
-       CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 0), 10.0 );
-       CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 1), 20.0 );
-       CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 2), 30.0 );
-       CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 3), 40.0 );
+       CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 'X'), 10.0 );
+       CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 'Y'), 20.0 );
+       CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 'Z'), 30.0 );
+       CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 'M'), 40.0 );
 
 }
 
@@ -424,16 +424,16 @@ static void test_lwpoint_interpolate(void)
        q.z = 40.0;
        q.m = 50.0;
 
-       rv = lwpoint_interpolate(&p, &q, &r, 4, 2, 35.0);
+       rv = lwpoint_interpolate(&p, &q, &r, 1, 1, 'Z', 35.0);
        CU_ASSERT_EQUAL( r.x, 15.0);
 
-       rv = lwpoint_interpolate(&p, &q, &r, 4, 3, 41.0);
+       rv = lwpoint_interpolate(&p, &q, &r, 1, 1, 'M', 41.0);
        CU_ASSERT_EQUAL( r.y, 21.0);
 
-       rv = lwpoint_interpolate(&p, &q, &r, 4, 3, 50.0);
+       rv = lwpoint_interpolate(&p, &q, &r, 1, 1, 'M', 50.0);
        CU_ASSERT_EQUAL( r.y, 30.0);
 
-       rv = lwpoint_interpolate(&p, &q, &r, 4, 3, 40.0);
+       rv = lwpoint_interpolate(&p, &q, &r, 1, 1, 'M', 40.0);
        CU_ASSERT_EQUAL( r.y, 20.0);
 
 }
@@ -449,7 +449,7 @@ static void test_lwline_clip(void)
        l51 = (LWLINE*)lwgeom_from_wkt("LINESTRING(0 0, 0 1, 0 2, 0 3, 0 4)", LW_PARSER_CHECK_NONE);
 
        /* Clip in the middle, mid-range. */
-       c = lwline_clip_to_ordinate_range(l51, 1, 1.5, 2.5);
+       c = lwline_clip_to_ordinate_range(l51, 'Y', 1.5, 2.5);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
@@ -457,7 +457,7 @@ static void test_lwline_clip(void)
        lwcollection_free(c);
 
        /* Clip off the top. */
-       c = lwline_clip_to_ordinate_range(l51, 1, 3.5, 5.5);
+       c = lwline_clip_to_ordinate_range(l51, 'Y', 3.5, 5.5);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 3.5,0 4))");
@@ -465,7 +465,7 @@ static void test_lwline_clip(void)
        lwcollection_free(c);
 
        /* Clip off the bottom. */
-       c = lwline_clip_to_ordinate_range(l51, 1, -1.5, 2.5);
+       c = lwline_clip_to_ordinate_range(l51, 'Y', -1.5, 2.5);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2,0 2.5))" );
@@ -473,7 +473,7 @@ static void test_lwline_clip(void)
        lwcollection_free(c);
 
        /* Range holds entire object. */
-       c = lwline_clip_to_ordinate_range(l51, 1, -1.5, 5.5);
+       c = lwline_clip_to_ordinate_range(l51, 'Y', -1.5, 5.5);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2,0 3,0 4))" );
@@ -481,7 +481,7 @@ static void test_lwline_clip(void)
        lwcollection_free(c);
 
        /* Clip on vertices. */
-       c = lwline_clip_to_ordinate_range(l51, 1, 1.0, 2.0);
+       c = lwline_clip_to_ordinate_range(l51, 'Y', 1.0, 2.0);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1,0 2))" );
@@ -489,7 +489,7 @@ static void test_lwline_clip(void)
        lwcollection_free(c);
 
        /* Clip on vertices off the bottom. */
-       c = lwline_clip_to_ordinate_range(l51, 1, -1.0, 2.0);
+       c = lwline_clip_to_ordinate_range(l51, 'Y', -1.0, 2.0);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2))" );
@@ -497,7 +497,7 @@ static void test_lwline_clip(void)
        lwcollection_free(c);
 
        /* Clip on top. */
-       c = lwline_clip_to_ordinate_range(l51, 1, -1.0, 0.0);
+       c = lwline_clip_to_ordinate_range(l51, 'Y', -1.0, 0.0);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(0 0))" );
@@ -506,7 +506,7 @@ static void test_lwline_clip(void)
 
        /* ST_LocateBetweenElevations(ST_GeomFromEWKT('LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)'), 1, 2)) */
        line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", LW_PARSER_CHECK_NONE);
-       c = lwline_clip_to_ordinate_range(line, 2, 1.0, 2.0);
+       c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 2.0);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2,1 1 1))" );
        lwfree(ewkt);
@@ -515,7 +515,7 @@ static void test_lwline_clip(void)
 
        /* ST_LocateBetweenElevations('LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)', 1, 2)) */
        line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", LW_PARSER_CHECK_NONE);
-       c = lwline_clip_to_ordinate_range(line, 2, 1.0, 2.0);
+       c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 2.0);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("a = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2,1 1 1))" );
@@ -525,7 +525,7 @@ static void test_lwline_clip(void)
 
        /* ST_LocateBetweenElevations('LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)', 1, 1)) */
        line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", LW_PARSER_CHECK_NONE);
-       c = lwline_clip_to_ordinate_range(line, 2, 1.0, 1.0);
+       c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 1.0);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("b = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 1 1))" );
@@ -535,7 +535,7 @@ static void test_lwline_clip(void)
 
        /* ST_LocateBetweenElevations('LINESTRING(1 1 1, 1 2 2)', 1,1) */
        line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1 1, 1 2 2)", LW_PARSER_CHECK_NONE);
-       c = lwline_clip_to_ordinate_range(line, 2, 1.0, 1.0);
+       c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 1.0);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 1 1))" );
@@ -560,7 +560,7 @@ static void test_lwmline_clip(void)
        mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
 
        /* Clip in the middle, mid-range. */
-       c = lwmline_clip_to_ordinate_range(mline, 1, 1.5, 2.5);
+       c = lwmline_clip_to_ordinate_range(mline, 'Y', 1.5, 2.5);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
@@ -575,7 +575,7 @@ static void test_lwmline_clip(void)
        mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((1 0,1 1,1 2,1 3,1 4), (0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
 
        /* Clip off the top. */
-       c = lwmline_clip_to_ordinate_range(mline, 1, 3.5, 5.5);
+       c = lwmline_clip_to_ordinate_range(mline, 'Y', 3.5, 5.5);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((1 3.5,1 4),(0 3.5,0 4))");
@@ -590,7 +590,7 @@ static void test_lwmline_clip(void)
        mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((1 0,1 -1,1 -2,1 -3,1 -4), (0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
 
        /* Clip from 0 upwards.. */
-       c = lwmline_clip_to_ordinate_range(mline, 1, 0.0, 2.5);
+       c = lwmline_clip_to_ordinate_range(mline, 'Y', 0.0, 2.5);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 0),LINESTRING(0 0,0 1,0 2,0 2.5))");
@@ -605,7 +605,7 @@ static void test_lwmline_clip(void)
        line = (LWLINE*)lwgeom_from_wkt("LINESTRING(0 0 0 0,1 1 1 1,2 2 2 2,3 3 3 3,4 4 4 4,3 3 3 5,2 2 2 6,1 1 1 7,0 0 0 8)", LW_PARSER_CHECK_NONE);
 
        /* Clip from 3 to 3.5 */
-       c = lwline_clip_to_ordinate_range(line, 2, 3.0, 3.5);
+       c = lwline_clip_to_ordinate_range(line, 'Z', 3.0, 3.5);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((3 3 3 3,3.5 3.5 3.5 3.5),(3.5 3.5 3.5 4.5,3 3 3 5))");
@@ -613,7 +613,7 @@ static void test_lwmline_clip(void)
        lwcollection_free(c);
 
        /* Clip from 2 to 3.5 */
-       c = lwline_clip_to_ordinate_range(line, 2, 2.0, 3.5);
+       c = lwline_clip_to_ordinate_range(line, 'Z', 2.0, 3.5);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2 2,3 3 3 3,3.5 3.5 3.5 3.5),(3.5 3.5 3.5 4.5,3 3 3 5,2 2 2 6))");
@@ -621,7 +621,7 @@ static void test_lwmline_clip(void)
        lwcollection_free(c);
 
        /* Clip from 3 to 4 */
-       c = lwline_clip_to_ordinate_range(line, 2, 3.0, 4.0);
+       c = lwline_clip_to_ordinate_range(line, 'Z', 3.0, 4.0);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((3 3 3 3,4 4 4 4,3 3 3 5))");
@@ -629,7 +629,7 @@ static void test_lwmline_clip(void)
        lwcollection_free(c);
 
        /* Clip from 2 to 3 */
-       c = lwline_clip_to_ordinate_range(line, 2, 2.0, 3.0);
+       c = lwline_clip_to_ordinate_range(line, 'Z', 2.0, 3.0);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2 2,3 3 3 3),(3 3 3 5,2 2 2 6))");
@@ -666,7 +666,7 @@ static void test_lwline_clip_big(void)
        p.z = 2.0;
        ptarray_set_point4d(pa, 2, &p);
 
-       c = lwline_clip_to_ordinate_range(line, 2, 0.5, 1.5);
+       c = lwline_clip_to_ordinate_range(line, 'Z', 0.5, 1.5);
        ewkt = lwgeom_to_ewkt((LWGEOM*)c);
        //printf("c = %s\n", ewkt);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0.5 0.5 0.5,1 1 1,1.5 1.5 1.5))" );
index b4f340d7b7084e1f5f55e1b1072cc171e1f7f6ab..c0946375547dbfc220ce2c23db703a69eccb1bff 100644 (file)
@@ -1267,17 +1267,22 @@ enum CG_LINE_CROSS_TYPE {
 /**
 * Given two lines, characterize how (and if) they cross each other
 */
-int lwline_crossing_direction(LWLINE *l1, LWLINE *l2);
+int lwline_crossing_direction(const LWLINE *l1, const LWLINE *l2);
+
+/**
+* Given a geometry clip  based on the from/to range of one of its ordinates (x, y, z, m). Use for m- and z- clipping.
+*/
+LWCOLLECTION* lwgeom_clip_to_ordinate_range(const LWGEOM *lwin, char ordinate, double from, double to);
 
 /**
 * Clip a line based on the from/to range of one of its ordinates. Use for m- and z- clipping 
 */
-LWCOLLECTION *lwline_clip_to_ordinate_range(LWLINE *line, int ordinate, double from, double to);
+LWCOLLECTION *lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, double to);
 
 /**
 * Clip a multi-line based on the from/to range of one of its ordinates. Use for m- and z- clipping 
 */
-LWCOLLECTION *lwmline_clip_to_ordinate_range(LWMLINE *mline, int ordinate, double from, double to);
+LWCOLLECTION *lwmline_clip_to_ordinate_range(const LWMLINE *mline, char ordinate, double from, double to);
 
 /*
  * Export functions
index d050fbf1ff5e6f5c77add0d2af059a90cf8a09ef..b770459f64e276a40fca1ee33b0ef01fcce27758 100644 (file)
@@ -210,13 +210,13 @@ int lw_segment_envelope_intersects(const POINT2D *p1, const POINT2D *p2, const P
 /*
 * Get/Set an enumeratoed ordinate. (x,y,z,m)
 */
-double lwpoint_get_ordinate(const POINT4D *p, int ordinate);
-void lwpoint_set_ordinate(POINT4D *p, int ordinate, double value);
+double lwpoint_get_ordinate(const POINT4D *p, char ordinate);
+void lwpoint_set_ordinate(POINT4D *p, char ordinate, double value);
 
 /* 
 * Generate an interpolated coordinate p given an interpolation value and ordinate to apply it to
 */
-int lwpoint_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int ndims, int ordinate, double interpolation_value);
+int lwpoint_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int hasz, int hasm, char ordinate, double interpolation_value);
 
 /*
 * Geohash
index 7ee4e563fbc53fbbf63b971d697c333494fba25c..2f8b98f662089ebd355ac1100435fdc9d56d2dbd 100644 (file)
@@ -165,7 +165,7 @@ int lw_segment_intersects(const POINT2D *p1, const POINT2D *p2, const POINT2D *q
 **   LINE_MULTICROSS_END_SAME_FIRST_RIGHT = 3
 **
 */
-int lwline_crossing_direction(LWLINE *l1, LWLINE *l2)
+int lwline_crossing_direction(const LWLINE *l1, const LWLINE *l2)
 {
        int i = 0, j = 0, rv = 0;
        POINT2D p1, p2, q1, q2;
index 093fafbb1086090d3282f748d91ef06d8c3aa2a1..6391856dd3942e58f9cc37108cb82458d70aac5f 100644 (file)
@@ -222,7 +222,7 @@ lwgeom_locate_along(const LWGEOM *lwin, double m, double offset)
 * @param ordinate number (1=x, 2=y, 3=z, 4=m)
 * @return d value at that ordinate
 */
-double lwpoint_get_ordinate(const POINT4D *p, int ordinate)
+double lwpoint_get_ordinate(const POINT4D *p, char ordinate)
 {
        if ( ! p )
        {
@@ -230,19 +230,22 @@ double lwpoint_get_ordinate(const POINT4D *p, int ordinate)
                return 0.0;
        }
 
-       if ( ordinate > 3 || ordinate < 0 )
+       if ( ! ( ordinate == 'X' || ordinate == 'Y' || ordinate == 'Z' || ordinate == 'M' ) )
        {
-               lwerror("Cannot extract ordinate %d.", ordinate);
+               lwerror("Cannot extract %c ordinate.", ordinate);
                return 0.0;
        }
 
-       if ( ordinate == 3 )
-               return p->m;
-       if ( ordinate == 2 )
-               return p->z;
-       if ( ordinate == 1 )
+       if ( ordinate == 'X' )
+               return p->x;
+       if ( ordinate == 'Y' )
                return p->y;
+       if ( ordinate == 'Z' )
+               return p->z;
+       if ( ordinate == 'M' )
+               return p->m;
 
+       /* X */
        return p->x;
 
 }
@@ -251,7 +254,7 @@ double lwpoint_get_ordinate(const POINT4D *p, int ordinate)
 * Given a point, ordinate number and value, set that ordinate on the
 * point.
 */
-void lwpoint_set_ordinate(POINT4D *p, int ordinate, double value)
+void lwpoint_set_ordinate(POINT4D *p, char ordinate, double value)
 {
        if ( ! p )
        {
@@ -259,27 +262,27 @@ void lwpoint_set_ordinate(POINT4D *p, int ordinate, double value)
                return;
        }
 
-       if ( ordinate > 3 || ordinate < 0 )
+       if ( ! ( ordinate == 'X' || ordinate == 'Y' || ordinate == 'Z' || ordinate == 'M' ) )
        {
-               lwerror("Cannot extract ordinate %d.", ordinate);
+               lwerror("Cannot set %c ordinate.", ordinate);
                return;
        }
 
-       LWDEBUGF(4, "    setting ordinate %d to %g", ordinate, value);
+       LWDEBUGF(4, "    setting ordinate %c to %g", ordinate, value);
 
        switch ( ordinate )
        {
-       case 3:
-               p->m = value;
-               return;
-       case 2:
-               p->z = value;
+       case 'X':
+               p->x = value;
                return;
-       case 1:
+       case 'Y':
                p->y = value;
                return;
-       case 0:
-               p->x = value;
+       case 'Z':
+               p->z = value;
+               return;
+       case 'M':
+               p->m = value;
                return;
        }
 }
@@ -289,21 +292,22 @@ void lwpoint_set_ordinate(POINT4D *p, int ordinate, double value)
 * generate a new point that is proportionally between the input points,
 * using the values in the provided dimension as the scaling factors.
 */
-int lwpoint_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int ndims, int ordinate, double interpolation_value)
+int lwpoint_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int hasz, int hasm, char ordinate, double interpolation_value)
 {
+       static char* dims = "XYZM";
        double p1_value = lwpoint_get_ordinate(p1, ordinate);
        double p2_value = lwpoint_get_ordinate(p2, ordinate);
        double proportion;
        int i = 0;
 
-       if ( ordinate < 0 || ordinate >= ndims )
+       if ( ! ( ordinate == 'X' || ordinate == 'Y' || ordinate == 'Z' || ordinate == 'M' ) )
        {
-               lwerror("Ordinate (%d) is not within ndims (%d).", ordinate, ndims);
+               lwerror("Cannot set %c ordinate.", ordinate);
                return 0;
        }
 
        if ( FP_MIN(p1_value, p2_value) > interpolation_value ||
-               FP_MAX(p1_value, p2_value) < interpolation_value )
+            FP_MAX(p1_value, p2_value) < interpolation_value )
        {
                lwerror("Cannot interpolate to a value (%g) not between the input points (%g, %g).", interpolation_value, p1_value, p2_value);
                return 0;
@@ -311,14 +315,16 @@ int lwpoint_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int nd
 
        proportion = fabs((interpolation_value - p1_value) / (p2_value - p1_value));
 
-       for ( i = 0; i < ndims; i++ )
+       for ( i = 0; i < 4; i++ )
        {
                double newordinate = 0.0;
-               p1_value = lwpoint_get_ordinate(p1, i);
-               p2_value = lwpoint_get_ordinate(p2, i);
+               if ( dims[i] == 'Z' && ! hasz ) continue;
+               if ( dims[i] == 'M' && ! hasm ) continue;
+               p1_value = lwpoint_get_ordinate(p1, dims[i]);
+               p2_value = lwpoint_get_ordinate(p2, dims[i]);
                newordinate = p1_value + proportion * (p2_value - p1_value);
-               lwpoint_set_ordinate(p, i, newordinate);
-               LWDEBUGF(4, "   clip ordinate(%d) p1_value(%g) p2_value(%g) proportion(%g) newordinate(%g) ", i, p1_value, p2_value, proportion, newordinate );
+               lwpoint_set_ordinate(p, dims[i], newordinate);
+               LWDEBUGF(4, "   clip ordinate(%c) p1_value(%g) p2_value(%g) proportion(%g) newordinate(%g) ", dims[i], p1_value, p2_value, proportion, newordinate );
        }
 
        return 1;
@@ -327,7 +333,8 @@ int lwpoint_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int nd
 /**
 * Clip an input MULTILINESTRING between two values, on any ordinate input.
 */
-LWCOLLECTION *lwmline_clip_to_ordinate_range(LWMLINE *mline, int ordinate, double from, double to)
+LWCOLLECTION*
+lwmline_clip_to_ordinate_range(const LWMLINE *mline, char ordinate, double from, double to)
 {
        LWCOLLECTION *lwgeom_out = NULL;
 
@@ -344,8 +351,8 @@ LWCOLLECTION *lwmline_clip_to_ordinate_range(LWMLINE *mline, int ordinate, doubl
        else
        {
                LWCOLLECTION *col;
-               char hasz = FLAGS_GET_Z(mline->flags);
-               char hasm = FLAGS_GET_M(mline->flags);
+               char hasz = lwgeom_has_z(lwmline_as_lwgeom(mline));
+               char hasm = lwgeom_has_m(lwmline_as_lwgeom(mline));
                int i, j;
                char homogeneous = 1;
                size_t geoms_size = 0;
@@ -407,7 +414,8 @@ LWCOLLECTION *lwmline_clip_to_ordinate_range(LWMLINE *mline, int ordinate, doubl
 * Take in a LINESTRING and return a MULTILINESTRING of those portions of the
 * LINESTRING between the from/to range for the specified ordinate (XYZM)
 */
-LWCOLLECTION *lwline_clip_to_ordinate_range(LWLINE *line, int ordinate, double from, double to)
+LWCOLLECTION*
+lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, double to)
 {
 
        POINTARRAY *pa_in = NULL;
@@ -417,8 +425,8 @@ LWCOLLECTION *lwline_clip_to_ordinate_range(LWLINE *line, int ordinate, double f
        int added_last_point = 0;
        POINT4D *p = NULL, *q = NULL, *r = NULL;
        double ordinate_value_p = 0.0, ordinate_value_q = 0.0;
-       char hasz = FLAGS_GET_Z(line->flags);
-       char hasm = FLAGS_GET_M(line->flags);
+       char hasz = lwgeom_has_z(lwline_as_lwgeom(line));
+       char hasm = lwgeom_has_m(lwline_as_lwgeom(line));
        char dims = FLAGS_NDIMS(line->flags);
 
        /* Null input, nothing we can do. */
@@ -436,11 +444,11 @@ LWCOLLECTION *lwline_clip_to_ordinate_range(LWLINE *line, int ordinate, double f
                to = t;
        }
 
-       LWDEBUGF(4, "from = %g, to = %g, ordinate = %d", from, to, ordinate);
+       LWDEBUGF(4, "from = %g, to = %g, ordinate = %c", from, to, ordinate);
        LWDEBUGF(4, "%s", lwgeom_to_ewkt((LWGEOM*)line));
 
        /* Asking for an ordinate we don't have. Error. */
-       if ( ordinate >= dims )
+       if ( (ordinate == 'Z' && ! hasz) || (ordinate == 'M' && ! hasm) )
        {
                lwerror("Cannot clip on ordinate %d in a %d-d geometry.", ordinate, dims);
                return NULL;
@@ -494,7 +502,7 @@ LWCOLLECTION *lwline_clip_to_ordinate_range(LWLINE *line, int ordinate, double f
                                {
                                        double interpolation_value;
                                        (ordinate_value_q > to) ? (interpolation_value = to) : (interpolation_value = from);
-                                       rv = lwpoint_interpolate(q, p, r, dims, ordinate, interpolation_value);
+                                       rv = lwpoint_interpolate(q, p, r, hasz, hasm, ordinate, interpolation_value);
                                        rv = ptarray_append_point(dp, r, LW_FALSE);
                                        LWDEBUGF(4, "[0] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
                                }
@@ -520,7 +528,7 @@ LWCOLLECTION *lwline_clip_to_ordinate_range(LWLINE *line, int ordinate, double f
                                *  to the point array at the range boundary. */
                                double interpolation_value;
                                (ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
-                               rv = lwpoint_interpolate(q, p, r, dims, ordinate, interpolation_value);
+                               rv = lwpoint_interpolate(q, p, r, hasz, hasm, ordinate, interpolation_value);
                                rv = ptarray_append_point(dp, r, LW_FALSE);
                                LWDEBUGF(4, " [1] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
                        }
@@ -535,7 +543,7 @@ LWCOLLECTION *lwline_clip_to_ordinate_range(LWLINE *line, int ordinate, double f
                                {
                                        double interpolation_value;
                                        (ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
-                                       rv = lwpoint_interpolate(q, p, r, dims, ordinate, interpolation_value);
+                                       rv = lwpoint_interpolate(q, p, r, hasz, hasm, ordinate, interpolation_value);
                                        rv = ptarray_append_point(dp, r, LW_FALSE);
                                        LWDEBUGF(4, " [2] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
                                }
@@ -546,10 +554,10 @@ LWCOLLECTION *lwline_clip_to_ordinate_range(LWLINE *line, int ordinate, double f
                                *  so we need to add *two* interpolated points! */
                                dp = ptarray_construct(hasz, hasm, 2);
                                /* Interpolate lower point. */
-                               rv = lwpoint_interpolate(p, q, r, dims, ordinate, from);
+                               rv = lwpoint_interpolate(p, q, r, hasz, hasm, ordinate, from);
                                ptarray_set_point4d(dp, 0, r);
                                /* Interpolate upper point. */
-                               rv = lwpoint_interpolate(p, q, r, dims, ordinate, to);
+                               rv = lwpoint_interpolate(p, q, r, hasz, hasm, ordinate, to);
                                ptarray_set_point4d(dp, 1, r);
                        }
                        else if ( i && ordinate_value_q > to && ordinate_value_p < from )
@@ -558,10 +566,10 @@ LWCOLLECTION *lwline_clip_to_ordinate_range(LWLINE *line, int ordinate, double f
                                *  so we need to add *two* interpolated points! */
                                dp = ptarray_construct(hasz, hasm, 2);
                                /* Interpolate upper point. */
-                               rv = lwpoint_interpolate(p, q, r, dims, ordinate, to);
+                               rv = lwpoint_interpolate(p, q, r, hasz, hasm, ordinate, to);
                                ptarray_set_point4d(dp, 0, r);
                                /* Interpolate lower point. */
-                               rv = lwpoint_interpolate(p, q, r, dims, ordinate, from);
+                               rv = lwpoint_interpolate(p, q, r, hasz, hasm, ordinate, from);
                                ptarray_set_point4d(dp, 1, r);
                        }
                        /* We have an extant point-array, save it out to a multi-line. */
@@ -628,4 +636,23 @@ LWCOLLECTION *lwline_clip_to_ordinate_range(LWLINE *line, int ordinate, double f
 
        return NULL;
 
-}
\ No newline at end of file
+}
+
+LWCOLLECTION*
+lwgeom_clip_to_ordinate_range(const LWGEOM *lwin, char ordinate, double from, double to)
+{
+       if ( ! lwin )
+               lwerror("lwgeom_clip_to_ordinate_range: null input geometry!");
+               
+       switch ( lwin->type )
+       {
+               case LINETYPE:
+                       return lwline_clip_to_ordinate_range((LWLINE*)lwin, ordinate, from, to);
+               case MULTILINETYPE:
+                       return lwmline_clip_to_ordinate_range((LWMLINE*)lwin, ordinate, from, to);
+               default:
+                       lwerror("This function only accepts LINESTRING or MULTILINESTRING as arguments.");
+       }
+
+       return NULL;
+}
index 45682795b61f85ca2fcacb121b62a28fb6ee7703..98da739df5921db4eab09a6df6fd6c43fa6ddfc9 100644 (file)
@@ -32,7 +32,6 @@
 /* Prototypes */
 Datum LWGEOM_simplify2d(PG_FUNCTION_ARGS);
 Datum ST_LineCrossingDirection(PG_FUNCTION_ARGS);
-Datum ST_LocateBetweenElevations(PG_FUNCTION_ARGS);
 
 double determineSide(POINT2D *seg1, POINT2D *seg2, POINT2D *point);
 int isOnSegment(POINT2D *seg1, POINT2D *seg2, POINT2D *point);
@@ -667,50 +666,7 @@ Datum ST_LineCrossingDirection(PG_FUNCTION_ARGS)
 
 }
 
-PG_FUNCTION_INFO_V1(ST_LocateBetweenElevations);
-Datum ST_LocateBetweenElevations(PG_FUNCTION_ARGS)
-{
-       GSERIALIZED *geom_in = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       double from = PG_GETARG_FLOAT8(1);
-       double to = PG_GETARG_FLOAT8(2);
-       LWCOLLECTION *geom_out = NULL;
-       LWGEOM *line_in = NULL;
-       char geomtype = gserialized_get_type(geom_in);
-       static int ordinate = 2; /* Z */
-
-       if ( ! ( geomtype == LINETYPE || geomtype == MULTILINETYPE ) )
-       {
-               elog(ERROR,"This function only accepts LINESTRING or MULTILINESTRING as arguments.");
-               PG_RETURN_NULL();
-       }
-
-       line_in = lwgeom_from_gserialized(geom_in);
-
-       if ( ! FLAGS_GET_Z(line_in->flags) )
-       {
-               elog(ERROR,"This function only accepts LINESTRING or MULTILINESTRING with Z values as arguments.");
-               PG_RETURN_NULL();
-       }
-
-       if ( geomtype == LINETYPE )
-       {
-               geom_out = lwline_clip_to_ordinate_range((LWLINE*)line_in, ordinate, from, to);
-       }
-       else if ( geomtype == MULTILINETYPE )
-       {
-               geom_out = lwmline_clip_to_ordinate_range((LWMLINE*)line_in, ordinate, from, to);
-       }
-       lwgeom_free(line_in);
 
-       if ( ! geom_out )
-       {
-               elog(ERROR,"The lwline_clip_to_ordinate_range returned null.");
-               PG_RETURN_NULL();
-       }
-
-       PG_FREE_IF_COPY(geom_in, 0);
-       PG_RETURN_POINTER(geometry_serialize((LWGEOM*)geom_out));
-}
 
 /***********************************************************************
  * --strk@keybit.net
index f526391b1461344c1c360c999a0cc14bcbc96352..a3680763fcf99651bfae729a8eee8578c7da8827 100644 (file)
@@ -1033,7 +1033,7 @@ Datum LWGEOM_inside_circle_point(PG_FUNCTION_ARGS)
 PG_FUNCTION_INFO_V1(LWGEOM_collect);
 Datum LWGEOM_collect(PG_FUNCTION_ARGS)
 {
-       GSERIALIZED *pglwgeom1, *pglwgeom2, *result;
+       GSERIALIZED *gser1, *gser2, *result;
        LWGEOM *lwgeoms[2], *outlwg;
     uint32 type1, type2;
     uint8_t outtype;
@@ -1053,22 +1053,22 @@ Datum LWGEOM_collect(PG_FUNCTION_ARGS)
        if (PG_ARGISNULL(1))
                PG_RETURN_DATUM(PG_GETARG_DATUM(0));
 
-       pglwgeom1 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       pglwgeom2 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+       gser1 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       gser2 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
 
-       POSTGIS_DEBUGF(3, "LWGEOM_collect(%s, %s): call", lwtype_name(gserialized_get_type(pglwgeom1)), lwtype_name(gserialized_get_type(pglwgeom2)));
+       POSTGIS_DEBUGF(3, "LWGEOM_collect(%s, %s): call", lwtype_name(gserialized_get_type(gser1)), lwtype_name(gserialized_get_type(gser2)));
 
-       if ( FLAGS_GET_ZM(pglwgeom1->flags) != FLAGS_GET_ZM(pglwgeom2->flags) )
+       if ( FLAGS_GET_ZM(gser1->flags) != FLAGS_GET_ZM(gser2->flags) )
        {
                elog(ERROR,"Cannot ST_Collect geometries with differing dimensionality.");
                PG_RETURN_NULL();
        }
 
-       srid = gserialized_get_srid(pglwgeom1);
-       error_if_srid_mismatch(srid, gserialized_get_srid(pglwgeom2));
+       srid = gserialized_get_srid(gser1);
+       error_if_srid_mismatch(srid, gserialized_get_srid(gser2));
 
-       lwgeoms[0] = lwgeom_from_gserialized(pglwgeom1);
-       lwgeoms[1] = lwgeom_from_gserialized(pglwgeom2);
+       lwgeoms[0] = lwgeom_from_gserialized(gser1);
+       lwgeoms[1] = lwgeom_from_gserialized(gser2);
 
        type1 = lwgeoms[0]->type;
        type2 = lwgeoms[1]->type;
@@ -1092,8 +1092,8 @@ Datum LWGEOM_collect(PG_FUNCTION_ARGS)
        lwgeom_free(lwgeoms[0]);
        lwgeom_free(lwgeoms[1]);
 
-       PG_FREE_IF_COPY(pglwgeom1, 0);
-       PG_FREE_IF_COPY(pglwgeom2, 1);
+       PG_FREE_IF_COPY(gser1, 0);
+       PG_FREE_IF_COPY(gser2, 1);
 
        PG_RETURN_POINTER(result);
 }
@@ -1575,7 +1575,7 @@ Datum LWGEOM_expand(PG_FUNCTION_ARGS)
 
        gbox_expand(&gbox, d);
 
-       pa = ptarray_construct_empty(FLAGS_GET_Z(lwgeom->flags), FLAGS_GET_M(lwgeom->flags), 5);
+       pa = ptarray_construct_empty(lwgeom_has_z(lwgeom), lwgeom_has_m(lwgeom), 5);
        
        /* Assign coordinates to POINT2D array */
        pt.x = gbox.xmin;
index 137b47633c5e933415930e526a8ec1fcb5d34e54..8e55c3f442c81651b62d24b219f8c4479a36a3ba 100644 (file)
@@ -587,3 +587,72 @@ Datum ST_LocateAlong(PG_FUNCTION_ARGS)
        PG_RETURN_POINTER(gout);
 }
 
+
+/*
+* Locate the portion of a line between the specified measures
+*/
+Datum ST_LocateBetween(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(ST_LocateBetween);
+Datum ST_LocateBetween(PG_FUNCTION_ARGS)
+{
+       GSERIALIZED *geom_in = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       double from = PG_GETARG_FLOAT8(1);
+       double to = PG_GETARG_FLOAT8(2);
+       double offset = PG_GETARG_FLOAT8(3);
+       LWCOLLECTION *geom_out = NULL;
+       LWGEOM *line_in = NULL;
+       static char ordinate = 'M'; /* M */
+
+       if ( ! gserialized_has_m(geom_in) )
+       {
+               elog(ERROR,"This function only accepts geometries that have an M dimension.");
+               PG_RETURN_NULL();
+       }
+
+       line_in = lwgeom_from_gserialized(geom_in);
+       geom_out = lwgeom_clip_to_ordinate_range(line_in,  ordinate, from, to); 
+       lwgeom_free(line_in);
+       PG_FREE_IF_COPY(geom_in, 0);
+
+       if ( ! geom_out )
+       {
+               elog(ERROR,"lwline_clip_to_ordinate_range returned null");
+               PG_RETURN_NULL();
+       }
+
+       PG_RETURN_POINTER(geometry_serialize((LWGEOM*)geom_out));
+}
+
+/*
+* Locate the portion of a line between the specified elevations
+*/
+Datum ST_LocateBetweenElevations(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(ST_LocateBetweenElevations);
+Datum ST_LocateBetweenElevations(PG_FUNCTION_ARGS)
+{
+       GSERIALIZED *geom_in = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       double from = PG_GETARG_FLOAT8(1);
+       double to = PG_GETARG_FLOAT8(2);
+       LWCOLLECTION *geom_out = NULL;
+       LWGEOM *line_in = NULL;
+       static char ordinate = 'Z'; /* Z */
+
+       if ( ! gserialized_has_z(geom_in) )
+       {
+               elog(ERROR,"This function only accepts LINESTRING or MULTILINESTRING with Z dimensions.");
+               PG_RETURN_NULL();
+       }
+
+       line_in = lwgeom_from_gserialized(geom_in);
+       geom_out = lwgeom_clip_to_ordinate_range(line_in,  ordinate, from, to); 
+       lwgeom_free(line_in);
+       PG_FREE_IF_COPY(geom_in, 0);
+
+       if ( ! geom_out )
+       {
+               elog(ERROR,"lwline_clip_to_ordinate_range returned null");
+               PG_RETURN_NULL();
+       }
+
+       PG_RETURN_POINTER(geometry_serialize((LWGEOM*)geom_out));
+}
\ No newline at end of file
index f2fdc4b5947cb77b18863dc36fefc67ca7c76df0..68f50b67f4aaddc3731483bbdfeba739fc3139ec 100644 (file)
@@ -2592,14 +2592,6 @@ CREATE OR REPLACE FUNCTION ST_LineCrossingDirection(geom1 geometry, geom2 geomet
        $$ SELECT CASE WHEN NOT $1 && $2 THEN 0 ELSE _ST_LineCrossingDirection($1,$2) END $$\r
        LANGUAGE 'sql' IMMUTABLE;\r
 \r
-\r
--- Only accepts LINESTRING as parameters.\r
--- Availability: 1.4.0\r
-CREATE OR REPLACE FUNCTION ST_LocateBetweenElevations(geometry, float8, float8)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME', 'ST_LocateBetweenElevations'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
 -- Requires GEOS >= 3.0.0\r
 -- Availability: 1.3.3\r
 CREATE OR REPLACE FUNCTION ST_SimplifyPreserveTopology(geometry, float8)\r
@@ -4444,7 +4436,7 @@ CREATE OR REPLACE FUNCTION ST_3DIntersects(geom1 geometry, geom2 geometry)
 -- SQL-MM\r
 ---------------------------------------------------------------\r
 -- PostGIS equivalent function: ST_ndims(geometry)\r
-CREATE OR REPLACE FUNCTION ST_CoordDim(geometry)\r
+CREATE OR REPLACE FUNCTION ST_CoordDim(Geometry geometry)\r
        RETURNS smallint\r
        AS 'MODULE_PATHNAME', 'LWGEOM_ndims'\r
        LANGUAGE 'C' IMMUTABLE STRICT; \r
@@ -4472,25 +4464,25 @@ CREATE OR REPLACE FUNCTION ST_CurveToLine(geometry)
        RETURNS geometry AS 'SELECT ST_CurveToLine($1, 32)'\r
        LANGUAGE 'SQL' IMMUTABLE STRICT;\r
 \r
-CREATE OR REPLACE FUNCTION ST_HasArc(geometry)\r
+CREATE OR REPLACE FUNCTION ST_HasArc(Geometry geometry)\r
        RETURNS boolean\r
        AS 'MODULE_PATHNAME', 'LWGEOM_has_arc'\r
        LANGUAGE 'C' IMMUTABLE STRICT;\r
 \r
-CREATE OR REPLACE FUNCTION ST_LineToCurve(geometry)\r
+CREATE OR REPLACE FUNCTION ST_LineToCurve(Geometry geometry)\r
        RETURNS geometry\r
        AS 'MODULE_PATHNAME', 'LWGEOM_line_desegmentize'\r
        LANGUAGE 'C' IMMUTABLE STRICT;\r
        \r
 -- Availability: 1.5.0\r
-CREATE OR REPLACE FUNCTION _ST_OrderingEquals(geometry, geometry)\r
+CREATE OR REPLACE FUNCTION _ST_OrderingEquals(GeometryA geometry, GeometryB geometry)\r
        RETURNS boolean\r
        AS 'MODULE_PATHNAME', 'LWGEOM_same'\r
        LANGUAGE 'C' IMMUTABLE STRICT\r
        COST 100;\r
 \r
 -- Availability: 1.3.0\r
-CREATE OR REPLACE FUNCTION ST_OrderingEquals(geometry, geometry)\r
+CREATE OR REPLACE FUNCTION ST_OrderingEquals(GeometryA geometry, GeometryB geometry)\r
        RETURNS boolean\r
        AS $$ \r
        SELECT $1 ~= $2 AND _ST_OrderingEquals($1, $2)\r
@@ -4501,13 +4493,13 @@ CREATE OR REPLACE FUNCTION ST_OrderingEquals(geometry, geometry)
 -- SQL/MM - SQL Functions on type ST_Point\r
 -------------------------------------------------------------------------------\r
 \r
--- PostGIS equivalent function: ST_MakePoint(float8,float8)\r
+-- PostGIS equivalent function: ST_MakePoint(XCoordinate float8,YCoordinate float8)\r
 CREATE OR REPLACE FUNCTION ST_Point(float8, float8)\r
        RETURNS geometry\r
        AS 'MODULE_PATHNAME', 'LWGEOM_makepoint'\r
        LANGUAGE 'C' IMMUTABLE STRICT; \r
        \r
--- PostGIS equivalent function: ST_MakePolygon(geometry)\r
+-- PostGIS equivalent function: ST_MakePolygon(Geometry geometry)\r
 CREATE OR REPLACE FUNCTION ST_Polygon(geometry, int)\r
        RETURNS geometry\r
        AS $$ \r
@@ -4515,10 +4507,9 @@ CREATE OR REPLACE FUNCTION ST_Polygon(geometry, int)
        $$      \r
        LANGUAGE 'SQL' IMMUTABLE STRICT; \r
        \r
--- PostGIS equivalent function: GeomFromWKB(bytea))\r
+-- PostGIS equivalent function: GeomFromWKB(WKB bytea))\r
 -- Note: Defaults to an SRID=-1, not 0 as per SQL/MM specs.\r
-\r
-CREATE OR REPLACE FUNCTION ST_WKBToSQL(bytea)\r
+CREATE OR REPLACE FUNCTION ST_WKBToSQL(WKB bytea)\r
        RETURNS geometry\r
        AS 'MODULE_PATHNAME','LWGEOM_from_WKB'\r
        LANGUAGE 'C' IMMUTABLE STRICT; \r
@@ -4526,16 +4517,26 @@ CREATE OR REPLACE FUNCTION ST_WKBToSQL(bytea)
 ---\r
 -- Linear referencing functions\r
 ---\r
-CREATE OR REPLACE FUNCTION ST_LocateBetween(Geometry geometry, Measure1 float8, Measure2 float8, Offsets float8 default 0.0)\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_LocateBetween(Geometry geometry, FromMeasure float8, ToMeasure float8, LeftRightOffset float8 default 0.0)\r
        RETURNS geometry\r
-       AS 'MODULE_PATHNAME', 'LWGEOM_locate_between_m'\r
+       AS 'MODULE_PATHNAME', 'ST_LocateBetween'\r
        LANGUAGE 'C' IMMUTABLE STRICT;\r
        \r
-CREATE OR REPLACE FUNCTION ST_LocateAlong(Geometry geometry, Measure float8, Offsets float8 default 0.0)\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_LocateAlong(Geometry geometry, Measure float8, LeftRightOffset float8 default 0.0)\r
        RETURNS geometry\r
        AS 'MODULE_PATHNAME', 'ST_LocateAlong'\r
        LANGUAGE 'C' IMMUTABLE STRICT;\r
 \r
+-- Only accepts LINESTRING as parameters.\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION ST_LocateBetweenElevations(Geometry geometry, FromElevation float8, ToElevation float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'ST_LocateBetweenElevations'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+\r
        \r
 ---------------------------------------------------------------\r
 -- END\r