Ignore:
Timestamp:
Feb 18, 2010 1:02:49 PM (6 years ago)
Author:
pramsey
Message:

Add multilinestring support to st_line_substring (#419)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/postgis/lwgeom_functions_analytic.c

    r5181 r5261  
    10561056        double from = PG_GETARG_FLOAT8(1);
    10571057        double to = PG_GETARG_FLOAT8(2);
    1058         LWLINE *iline;
    10591058        LWGEOM *olwgeom;
    10601059        POINTARRAY *ipa, *opa;
    10611060        PG_LWGEOM *ret;
     1061        uchar type = geom->type;
    10621062
    10631063        if ( from < 0 || from > 1 )
     
    10791079        }
    10801080
    1081         if ( lwgeom_getType(geom->type) != LINETYPE )
     1081        if ( TYPE_GETTYPE(type) == LINETYPE )
     1082        {
     1083                LWLINE *iline;
     1084
     1085                iline = lwline_deserialize(SERIALIZED_FORM(geom));
     1086
     1087                if( lwgeom_is_empty((LWGEOM*)iline) )
     1088                {
     1089                        /* TODO return empty line */
     1090                        lwline_release(iline);
     1091                        PG_FREE_IF_COPY(geom, 0);
     1092                        PG_RETURN_NULL();
     1093                }
     1094
     1095                ipa = iline->points;
     1096
     1097                opa = ptarray_substring(ipa, from, to);
     1098
     1099                if ( opa->npoints == 1 ) /* Point returned */
     1100                        olwgeom = (LWGEOM *)lwpoint_construct(iline->SRID, NULL, opa);
     1101                else
     1102                        olwgeom = (LWGEOM *)lwline_construct(iline->SRID, NULL, opa);
     1103
     1104        }
     1105        else if ( TYPE_GETTYPE(type) == MULTILINETYPE )
     1106        {
     1107                LWMLINE *iline;
     1108                int i = 0, g = 0;
     1109                int homogeneous = LW_TRUE;
     1110                LWGEOM **geoms = NULL;
     1111                double length = 0.0, sublength = 0.0, minprop = 0.0, maxprop = 0.0;
     1112               
     1113                iline = lwmline_deserialize(SERIALIZED_FORM(geom));
     1114               
     1115                if( lwgeom_is_empty((LWGEOM*)iline) )
     1116                {
     1117                        /* TODO return empty collection */
     1118                        lwmline_release(iline);
     1119                        PG_FREE_IF_COPY(geom, 0);
     1120                        PG_RETURN_NULL();
     1121                }
     1122
     1123                /* Calculate the total length of the mline */
     1124                for ( i = 0; i < iline->ngeoms; i++ )
     1125                {
     1126                        LWLINE *subline = (LWLINE*)iline->geoms[i];
     1127                        if ( subline->points && subline->points->npoints > 1 )
     1128                                length += lwgeom_pointarray_length2d(subline->points);
     1129                }
     1130                       
     1131                geoms = lwalloc(sizeof(LWGEOM*) * iline->ngeoms);
     1132                       
     1133                /* Slice each sub-geometry of the multiline */
     1134                for( i = 0; i < iline->ngeoms; i++ )
     1135                {
     1136                        LWLINE *subline = (LWLINE*)iline->geoms[i];
     1137                        double subfrom = 0.0, subto = 0.0;
     1138                       
     1139                        if ( subline->points && subline->points->npoints > 1 )
     1140                                sublength += lwgeom_pointarray_length2d(subline->points);
     1141                       
     1142                        /* Calculate proportions for this subline */
     1143                        minprop = maxprop;
     1144                        maxprop = sublength / length;
     1145                       
     1146                        /* This subline doesn't reach the lowest proportion requested
     1147                           or is beyond the highest proporton */
     1148                        if( from > maxprop || to < minprop )
     1149                                continue;
     1150                       
     1151                        if( from <= minprop )
     1152                                subfrom = 0.0;
     1153                        if( to >= maxprop )
     1154                                subto = 1.0;
     1155                               
     1156                        if( from > minprop && from <= maxprop )
     1157                                subfrom = (from - minprop) / (maxprop - minprop);
     1158
     1159                        if( to < maxprop && to >= minprop )
     1160                                subto = (to - minprop) / (maxprop - minprop);
     1161                               
     1162                       
     1163                        opa = ptarray_substring(subline->points, subfrom, subto);
     1164                        if( opa && opa->npoints > 0 )
     1165                        {
     1166                                if ( opa->npoints == 1 ) /* Point returned */
     1167                                {
     1168                                        geoms[g] = (LWGEOM *)lwpoint_construct(iline->SRID, NULL, opa);
     1169                                        homogeneous = LW_FALSE;
     1170                                }
     1171                                else
     1172                                {
     1173                                        geoms[g] = (LWGEOM *)lwline_construct(iline->SRID, NULL, opa);
     1174                                }
     1175                                g++;
     1176                        }
     1177                       
     1178                       
     1179                       
     1180                }
     1181                /* If we got any points, we need to return a GEOMETRYCOLLECTION */
     1182                if( ! homogeneous )
     1183                        TYPE_SETTYPE(type,COLLECTIONTYPE);
     1184                       
     1185                olwgeom = (LWGEOM*)lwcollection_construct(type, iline->SRID, NULL, g, geoms);
     1186        }
     1187        else
    10821188        {
    10831189                elog(ERROR,"line_interpolate_point: 1st arg isnt a line");
    10841190                PG_RETURN_NULL();
    10851191        }
    1086 
    1087         iline = lwline_deserialize(SERIALIZED_FORM(geom));
    1088         ipa = iline->points;
    1089 
    1090         opa = ptarray_substring(ipa, from, to);
    1091 
    1092         if ( opa->npoints == 1 ) /* Point returned */
    1093                 olwgeom = (LWGEOM *)lwpoint_construct(iline->SRID, NULL, opa);
    1094         else
    1095                 olwgeom = (LWGEOM *)lwline_construct(iline->SRID, NULL, opa);
    10961192
    10971193        ret = pglwgeom_serialize(olwgeom);
     
    10991195        lwgeom_release(olwgeom);
    11001196        PG_RETURN_POINTER(ret);
     1197
    11011198}
    11021199
Note: See TracChangeset for help on using the changeset viewer.