| | 560 | |
| | 561 | /** |
| | 562 | * Takes a potentially heterogeneous collection and returns a homogeneous |
| | 563 | * collection consisting only of the specified type. |
| | 564 | */ |
| | 565 | LWCOLLECTION* 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 | |