Show
Ignore:
Timestamp:
11/17/09 12:03:50 (3 years ago)
Author:
pramsey
Message:

Implement ST_CollectionExtract() to pull specific homogeneous collections out of heterogeneous collections. Regressions and documentation included. (#218)

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/liblwgeom/lwcollection.c

    r4789 r4847  
    558558        return boxfinal; 
    559559} 
     560 
     561/** 
     562* Takes a potentially heterogeneous collection and returns a homogeneous 
     563* collection consisting only of the specified type. 
     564*/ 
     565LWCOLLECTION* lwcollection_extract(LWCOLLECTION *col, int type) 
     566{ 
     567        int i = 0; 
     568        LWGEOM **geomlist; 
     569        BOX3D *b3d; 
     570        LWCOLLECTION *outcol; 
     571        int geomlistsize = 16; 
     572        int geomlistlen = 0; 
     573        uchar outtype; 
     574 
     575        if( ! col ) return NULL; 
     576 
     577        switch (type) 
     578        { 
     579                case POINTTYPE: 
     580                        outtype = MULTIPOINTTYPE; 
     581                        break; 
     582                case LINETYPE: 
     583                        outtype = MULTILINETYPE; 
     584                        break; 
     585                case POLYGONTYPE: 
     586                        outtype = MULTIPOLYGONTYPE; 
     587                        break; 
     588                default: 
     589                        lwerror("Only POLYGON, LINESTRING and POINT are supported by lwcollection_extract. %s requested.", lwgeom_typename(type)); 
     590                        return NULL; 
     591        } 
     592         
     593        geomlist = lwalloc(sizeof(LWGEOM*) * geomlistsize); 
     594 
     595        /* Process each sub-geometry */ 
     596        for( i = 0; i < col->ngeoms; i++ ) 
     597        { 
     598                int subtype = TYPE_GETTYPE(col->geoms[i]->type); 
     599                /* Copy our sub-types into the output list */ 
     600                if( subtype == type ) 
     601                { 
     602                        /* We've over-run our buffer, double the memory segment */ 
     603                        if( geomlistlen == geomlistsize ) 
     604                        { 
     605                                geomlistsize *= 2; 
     606                                geomlist = lwrealloc(geomlist, sizeof(LWGEOM*) * geomlistsize); 
     607                        } 
     608                        geomlist[geomlistlen] = col->geoms[i]; 
     609                        geomlistlen++; 
     610                } 
     611                if( lwgeom_is_collection( subtype ) ) 
     612                { 
     613                        int j = 0; 
     614                        LWCOLLECTION *tmpcol = lwcollection_extract((LWCOLLECTION*)col->geoms[i], type); 
     615                        for( j = 0; j < tmpcol->ngeoms; j++ ) 
     616                        { 
     617                                /* We've over-run our buffer, double the memory segment */ 
     618                                if( geomlistlen == geomlistsize ) 
     619                                { 
     620                                        geomlistsize *= 2; 
     621                                        geomlist = lwrealloc(geomlist, sizeof(LWGEOM*) * geomlistsize); 
     622                                } 
     623                                geomlist[geomlistlen] = tmpcol->geoms[j]; 
     624                                geomlistlen++; 
     625                        } 
     626                        lwfree(tmpcol); 
     627                } 
     628        } 
     629         
     630        if( geomlistlen > 0 ) 
     631        { 
     632                outcol = lwcollection_construct(outtype, col->SRID, NULL, geomlistlen, geomlist);        
     633                b3d = lwcollection_compute_box3d(outcol); 
     634                outcol->bbox = box3d_to_box2df(b3d); 
     635        } 
     636        else 
     637        { 
     638                outcol = lwcollection_construct_empty(col->SRID, TYPE_HASZ(col->type), TYPE_HASM(col->type)); 
     639        } 
     640         
     641        return outcol; 
     642} 
     643