]> granicus.if.org Git - postgis/commitdiff
Make ST_AddMeasure handle multilinestrings as well as linestrings.
authorPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 26 Jan 2010 18:56:22 +0000 (18:56 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 26 Jan 2010 18:56:22 +0000 (18:56 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@5168 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/cunit/cu_geodetic.c
liblwgeom/liblwgeom.h
liblwgeom/lwline.c
liblwgeom/lwmline.c
postgis/lwgeom_functions_lrs.c

index f0dbd7cc9014f8ebc2c38bfe9c88280c46a8a0a1..e4ecc7414642d8d623345598d1b5e43bd7016fc2 100644 (file)
@@ -30,7 +30,7 @@ CU_pSuite register_geodetic_suite(void)
        if (
            (NULL == CU_add_test(pSuite, "test_signum()", test_signum))  ||
            (NULL == CU_add_test(pSuite, "test_gbox_from_spherical_coordinates()", test_gbox_from_spherical_coordinates))  ||
-/*         (NULL == CU_add_test(pSuite, "test_gserialized_get_gbox_geocentric()", test_gserialized_get_gbox_geocentric))  || */
+           (NULL == CU_add_test(pSuite, "test_gserialized_get_gbox_geocentric()", test_gserialized_get_gbox_geocentric))  || 
            (NULL == CU_add_test(pSuite, "test_clairaut()", test_clairaut))  || 
            (NULL == CU_add_test(pSuite, "test_edge_intersection()", test_edge_intersection))  ||
            (NULL == CU_add_test(pSuite, "test_edge_distance_to_point()", test_edge_distance_to_point)) ||
index f3ce1ef35742ba5e7d5b5e9211844a54449cf013..8d33e49547a53b05da2cc9e7a56aa5bbd8a5b4a1 100644 (file)
@@ -1380,6 +1380,7 @@ extern POINTARRAY *ptarray_substring(POINTARRAY *, double, double);
 extern double ptarray_locate_point(POINTARRAY *, POINT2D *);
 extern void closest_point_on_segment(POINT2D *p, POINT2D *A, POINT2D *B, POINT2D *ret);
 extern LWLINE *lwline_measured_from_lwline(const LWLINE *lwline, double m_start, double m_end);
+extern LWMLINE* lwmline_measured_from_lwmline(const LWMLINE *lwmline, double m_start, double m_end);
 
 /*
  * Ensure every segment is at most 'dist' long.
index 614496cdbcb1b1a19bf1c02b01f23d7956f6c742..d9adfb483aa33b2f1c50e188ea74cbc483c53df3 100644 (file)
@@ -544,7 +544,7 @@ lwline_measured_from_lwline(const LWLINE *lwline, double m_start, double m_end)
        
        if( TYPE_GETTYPE(lwline->type) != LINETYPE )
        {
-               lwerror("lwmline_construct_from_lwline: only line types supported");
+               lwerror("lwline_construct_from_lwline: only line types supported");
                return NULL;
        }
        
index f3e82b18969f761282475fad4004c660fab2afad..969d76f1eb7b0258586122d88964fad1b408047d 100644 (file)
@@ -123,6 +123,67 @@ lwmline_add(const LWMLINE *to, uint32 where, const LWGEOM *what)
 
 }
 
+/**
+* Re-write the measure ordinate (or add one, if it isn't already there) interpolating
+* the measure between the supplied start and end values. 
+*/
+LWMLINE* 
+lwmline_measured_from_lwmline(const LWMLINE *lwmline, double m_start, double m_end)
+{
+       int i = 0;
+       int hasm = 0, hasz = 0;
+       double length = 0.0, length_so_far = 0.0;
+       double m_range = m_end - m_start;
+       LWGEOM **geoms = NULL;
+       
+       if( TYPE_GETTYPE(lwmline->type) != MULTILINETYPE )
+       {
+               lwerror("lwmline_measured_from_lmwline: only multiline types supported");
+               return NULL;
+       }
+       
+       hasz = TYPE_HASZ(lwmline->type);
+       hasm = 1;
+       
+       /* Calculate the total length of the mline */
+       for( i = 0; i < lwmline->ngeoms; i++ )
+       {
+               LWLINE *lwline = (LWLINE*)lwmline->geoms[i];
+               if( lwline->points && lwline->points->npoints > 1 )
+               {
+                       length += lwgeom_pointarray_length2d(lwline->points);
+               }
+       }
+               
+       if( lwgeom_is_empty((LWGEOM*)lwmline) )
+       {
+               return (LWMLINE*)lwcollection_construct_empty(lwmline->SRID, hasz, hasm);
+       }
+       
+       geoms = lwalloc(sizeof(LWGEOM*) * lwmline->ngeoms);
+       
+       for( i = 0; i < lwmline->ngeoms; i++ )
+       {               
+               double sub_m_start, sub_m_end;
+               double sub_length = 0.0;
+               LWLINE *lwline = (LWLINE*)lwmline->geoms[i];
+               
+               if( lwline->points && lwline->points->npoints > 1 )
+               {
+                       sub_length = lwgeom_pointarray_length2d(lwline->points);
+               }
+               
+               sub_m_start = (m_start + m_range * length_so_far / length);
+               sub_m_end = (m_start + m_range * (length_so_far + sub_length) / length);
+               
+               geoms[i] = (LWGEOM*)lwline_measured_from_lwline(lwline, sub_m_start, sub_m_end);
+               
+               length_so_far += sub_length;
+       }
+
+       return (LWMLINE*)lwcollection_construct(lwmline->type, lwmline->SRID, NULL, lwmline->ngeoms, geoms);
+}
+
 void lwmline_free(LWMLINE *mline)
 {
        int i;
index c9ba726abded435a070e57b39118383396b2bdbd..22d46e7b56c8da9a3e0737875a2c778c7d98d132 100644 (file)
@@ -551,16 +551,21 @@ Datum ST_AddMeasure(PG_FUNCTION_ARGS)
        double start_measure = PG_GETARG_FLOAT8(1);
        double end_measure = PG_GETARG_FLOAT8(2);
        LWGEOM *lwin, *lwout;
+       int type = TYPE_GETTYPE(gin->type);
 
-       /* Raise an error if input is not a linestring */
-       if ( TYPE_GETTYPE(gin->type) != LINETYPE )
+       /* Raise an error if input is not a linestring or multilinestring */
+       if ( type != LINETYPE && type != MULTILINETYPE )
        {
-               lwerror("Only LINESTRING is supported");
+               lwerror("Only LINESTRING and MULTILINESTRING are supported");
                PG_RETURN_NULL();
        }
 
        lwin = pglwgeom_deserialize(gin);
-       lwout = (LWGEOM*)lwline_measured_from_lwline((LWLINE*)lwin, start_measure, end_measure);
+       if( type == LINETYPE )
+               lwout = (LWGEOM*)lwline_measured_from_lwline((LWLINE*)lwin, start_measure, end_measure);
+       else
+               lwout = (LWGEOM*)lwmline_measured_from_lwmline((LWMLINE*)lwin, start_measure, end_measure);
+
        lwgeom_release(lwin);
 
        if ( lwout == NULL )