LWGEOM * lwmpolygon_desegmentize(LWMPOLY *mpoly) { LWGEOM **geoms; int i, hascurve = 0; LWDEBUG(2, "lwmpoly_desegmentize called."); geoms = lwalloc(sizeof(LWGEOM *)*mpoly->ngeoms); for (i=0; i<mpoly->ngeoms; i++) { geoms[i] = lwpolygon_desegmentize((LWPOLY *)mpoly->geoms[i]); if (geoms[i]->type == CURVEPOLYTYPE) { hascurve = 1; } } if (hascurve == 0) { for (i=0; i<mpoly->ngeoms; i++) { lwfree(geoms[i]); } return lwgeom_clone((LWGEOM *)mpoly); } return (LWGEOM *)lwcollection_construct(MULTISURFACETYPE, mpoly->srid, NULL, mpoly->ngeoms, geoms); }
LWGEOM * lwcurve_linearize(const LWGEOM *geom, double tol, LW_LINEARIZE_TOLERANCE_TYPE type, int flags) { LWGEOM * ogeom = NULL; switch (geom->type) { case CIRCSTRINGTYPE: ogeom = (LWGEOM *)lwcircstring_linearize((LWCIRCSTRING *)geom, tol, type, flags); break; case COMPOUNDTYPE: ogeom = (LWGEOM *)lwcompound_linearize((LWCOMPOUND *)geom, tol, type, flags); break; case CURVEPOLYTYPE: ogeom = (LWGEOM *)lwcurvepoly_linearize((LWCURVEPOLY *)geom, tol, type, flags); break; case MULTICURVETYPE: ogeom = (LWGEOM *)lwmcurve_linearize((LWMCURVE *)geom, tol, type, flags); break; case MULTISURFACETYPE: ogeom = (LWGEOM *)lwmsurface_linearize((LWMSURFACE *)geom, tol, type, flags); break; case COLLECTIONTYPE: ogeom = (LWGEOM *)lwcollection_linearize((LWCOLLECTION *)geom, tol, type, flags); break; default: ogeom = lwgeom_clone(geom); } return ogeom; }
LWGEOM * lwpolygon_desegmentize(LWPOLY *poly) { LWGEOM **geoms; int i, hascurve = 0; LWDEBUG(2, "lwpolygon_desegmentize called."); geoms = lwalloc(sizeof(LWGEOM *)*poly->nrings); for (i=0; i<poly->nrings; i++) { geoms[i] = pta_desegmentize(poly->rings[i], poly->flags, poly->srid); if (geoms[i]->type == CIRCSTRINGTYPE || geoms[i]->type == COMPOUNDTYPE) { hascurve = 1; } } if (hascurve == 0) { for (i=0; i<poly->nrings; i++) { lwfree(geoms[i]); } return lwgeom_clone((LWGEOM *)poly); } return (LWGEOM *)lwcollection_construct(CURVEPOLYTYPE, poly->srid, NULL, poly->nrings, geoms); }
LWGEOM * lwmline_desegmentize(LWMLINE *mline) { LWGEOM **geoms; int i, hascurve = 0; LWDEBUG(2, "lwmline_desegmentize called."); geoms = lwalloc(sizeof(LWGEOM *)*mline->ngeoms); for (i=0; i<mline->ngeoms; i++) { geoms[i] = lwline_desegmentize((LWLINE *)mline->geoms[i]); if (geoms[i]->type == CIRCSTRINGTYPE || geoms[i]->type == COMPOUNDTYPE) { hascurve = 1; } } if (hascurve == 0) { for (i=0; i<mline->ngeoms; i++) { lwfree(geoms[i]); } return lwgeom_clone((LWGEOM *)mline); } return (LWGEOM *)lwcollection_construct(MULTICURVETYPE, mline->srid, NULL, mline->ngeoms, geoms); }
LWGEOM * lwgeom_segmentize(LWGEOM *geom, uint32_t perQuad) { LWGEOM * ogeom = NULL; switch (geom->type) { case CIRCSTRINGTYPE: ogeom = (LWGEOM *)lwcircstring_segmentize((LWCIRCSTRING *)geom, perQuad); break; case COMPOUNDTYPE: ogeom = (LWGEOM *)lwcompound_segmentize((LWCOMPOUND *)geom, perQuad); break; case CURVEPOLYTYPE: ogeom = (LWGEOM *)lwcurvepoly_segmentize((LWCURVEPOLY *)geom, perQuad); break; case MULTICURVETYPE: ogeom = (LWGEOM *)lwmcurve_segmentize((LWMCURVE *)geom, perQuad); break; case MULTISURFACETYPE: ogeom = (LWGEOM *)lwmsurface_segmentize((LWMSURFACE *)geom, perQuad); break; case COLLECTIONTYPE: ogeom = (LWGEOM *)lwcollection_segmentize((LWCOLLECTION *)geom, perQuad); break; default: ogeom = lwgeom_clone(geom); } return ogeom; }
LWCOMPOUND * lwcompound_construct_from_lwline(const LWLINE *lwline) { LWCOMPOUND* ogeom = lwcompound_construct_empty(lwline->srid, FLAGS_GET_Z(lwline->flags), FLAGS_GET_M(lwline->flags)); lwcompound_add_lwgeom(ogeom, lwgeom_clone((LWGEOM*)lwline)); /* ogeom->bbox = lwline->bbox; */ return ogeom; }
/* * Add 'what' to this string at position 'where' * where=0 == prepend * where=-1 == append * Returns a COMPOUND or a GEOMETRYCOLLECTION */ LWGEOM * lwcompound_add(const LWCOMPOUND *to, uint32 where, const LWGEOM *what) { LWCOLLECTION *col; LWGEOM **geoms; int newtype; LWDEBUG(2, "lwcompound_add called."); if(where != -1 && where != 0) { lwerror("lwcompound_add only supports 0 or -1 as a second argument, not %d", where); return NULL; } /* dimensions compatibility are checked by caller */ /* Construct geoms array */ geoms = lwalloc(sizeof(LWGEOM *)*2); if(where == -1) /* append */ { geoms[0] = lwgeom_clone((LWGEOM *)to); geoms[1] = lwgeom_clone(what); } else /* prepend */ { geoms[0] = lwgeom_clone(what); geoms[1] = lwgeom_clone((LWGEOM *)to); } /* reset SRID and wantbbox flag from component types */ geoms[0]->SRID = geoms[1]->SRID = -1; TYPE_SETHASSRID(geoms[0]->type, 0); TYPE_SETHASSRID(geoms[1]->type, 0); TYPE_SETHASBBOX(geoms[0]->type, 0); TYPE_SETHASBBOX(geoms[1]->type, 0); /* Find appropriate geom type */ if(TYPE_GETTYPE(what->type) == LINETYPE || TYPE_GETTYPE(what->type) == CIRCSTRINGTYPE) newtype = COMPOUNDTYPE; else newtype = COLLECTIONTYPE; col = lwcollection_construct(newtype, to->SRID, NULL, 2, geoms); return (LWGEOM *)col; }
static void test_clone(void) { static char *wkt = "GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0))),POINT(1 1),LINESTRING(2 3,4 5))"; LWGEOM *geom1 = lwgeom_from_wkt(wkt, LW_PARSER_CHECK_ALL); LWGEOM *geom2; /* Free in "backwards" order */ geom2 = lwgeom_clone(geom1); lwgeom_free(geom1); lwgeom_free(geom2); /* Free in "forewards" order */ geom1 = lwgeom_from_wkt(wkt, LW_PARSER_CHECK_ALL); geom2 = lwgeom_clone(geom1); lwgeom_free(geom2); lwgeom_free(geom1); }
/** * Create a new LWGEOM of the appropriate MULTI* type. */ LWGEOM * lwgeom_as_multi(const LWGEOM *lwgeom) { LWGEOM **ogeoms; LWGEOM *ogeom = NULL; GBOX *box = NULL; int type; /* ** This funx is a no-op only if a bbox cache is already present ** in input. */ if ( lwgeom_is_collection(lwgeom) ) { return lwgeom_clone(lwgeom); } type = lwgeom->type; if ( ! MULTITYPE[type] ) return lwgeom_clone(lwgeom); if( lwgeom_is_empty(lwgeom) ) { ogeom = (LWGEOM *)lwcollection_construct_empty( MULTITYPE[type], lwgeom->srid, FLAGS_GET_Z(lwgeom->flags), FLAGS_GET_M(lwgeom->flags) ); } else { ogeoms = lwalloc(sizeof(LWGEOM*)); ogeoms[0] = lwgeom_clone(lwgeom); /* Sub-geometries are not allowed to have bboxes or SRIDs, move the bbox to the collection */ box = ogeoms[0]->bbox; ogeoms[0]->bbox = NULL; ogeoms[0]->srid = SRID_UNKNOWN; ogeom = (LWGEOM *)lwcollection_construct(MULTITYPE[type], lwgeom->srid, box, 1, ogeoms); } return ogeom; }
/* * Add 'what' to this point at position 'where'. * where=0 == prepend * where=-1 == append * Returns a MULTIPOINT or a GEOMETRYCOLLECTION */ LWGEOM * lwpoint_add(const LWPOINT *to, uint32 where, const LWGEOM *what) { LWCOLLECTION *col; LWGEOM **geoms; int newtype; if ( where != -1 && where != 0 ) { lwerror("lwpoint_add only supports 0 or -1 as second argument, got %d", where); return NULL; } /* dimensions compatibility are checked by caller */ /* Construct geoms array */ geoms = lwalloc(sizeof(LWGEOM *)*2); if ( where == -1 ) /* append */ { geoms[0] = lwgeom_clone((LWGEOM *)to); geoms[1] = lwgeom_clone(what); } else /* prepend */ { geoms[0] = lwgeom_clone(what); geoms[1] = lwgeom_clone((LWGEOM *)to); } /* reset SRID and wantbbox flag from component types */ lwgeom_dropSRID(geoms[0]); lwgeom_drop_bbox(geoms[0]); lwgeom_dropSRID(geoms[1]); lwgeom_drop_bbox(geoms[1]); /* Find appropriate geom type */ if ( TYPE_GETTYPE(what->type) == POINTTYPE ) newtype = MULTIPOINTTYPE; else newtype = COLLECTIONTYPE; col = lwcollection_construct(newtype, to->SRID, NULL, 2, geoms); return (LWGEOM *)col; }
/* * Add 'what' to this multisurface at position 'where' * where=0 == prepend * where=-1 == append * Returns a MULTISURFACE or a COLLECTION */ LWGEOM * lwmsurface_add(const LWMSURFACE *to, uint32 where, const LWGEOM *what) { LWCOLLECTION *col; LWGEOM **geoms; int newtype; uint32 i; if (where == -1) where = to->ngeoms; else if (where < -1 || where > to->ngeoms) { lwerror("lwmsurface_add: add position out of range %d..%d", -1, to->ngeoms); return NULL; } /* dimensions compatibility are checked by caller */ /* Construct geoms array */ geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1)); for (i = 0; i < where; i++) { geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]); } geoms[where] = lwgeom_clone(what); for (i = where; i < to->ngeoms; i++) { geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]); } if (TYPE_GETTYPE(what->type) == POLYGONTYPE || TYPE_GETTYPE(what->type) == CURVEPOLYTYPE) newtype = MULTISURFACETYPE; else newtype = COLLECTIONTYPE; col = lwcollection_construct(newtype, to->SRID, NULL, to->ngeoms + 1, geoms); return (LWGEOM *)col; }
LWGEOM * lwgeom_desegmentize(LWGEOM *geom) { LWDEBUG(2, "lwgeom_desegmentize called."); switch (geom->type) { case LINETYPE: return lwline_desegmentize((LWLINE *)geom); case POLYGONTYPE: return lwpolygon_desegmentize((LWPOLY *)geom); case MULTILINETYPE: return lwmline_desegmentize((LWMLINE *)geom); case MULTIPOLYGONTYPE: return lwmpolygon_desegmentize((LWMPOLY *)geom); default: return lwgeom_clone(geom); } }
LWGEOM* lwgeom_simplify(const LWGEOM *igeom, double dist) { switch (igeom->type) { case POINTTYPE: case MULTIPOINTTYPE: return lwgeom_clone(igeom); case LINETYPE: return (LWGEOM*)lwline_simplify((LWLINE*)igeom, dist); case POLYGONTYPE: return (LWGEOM*)lwpoly_simplify((LWPOLY*)igeom, dist); case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: return (LWGEOM*)lwcollection_simplify((LWCOLLECTION *)igeom, dist); default: lwerror("lwgeom_simplify: unsupported geometry type: %s",lwtype_name(igeom->type)); } return NULL; }
/** * @param collection input geometry collection * @param tol tolerance, semantic driven by tolerance_type * @param tolerance_type see LW_LINEARIZE_TOLERANCE_TYPE * @param flags see flags in lwarc_linearize * * @return a newly allocated LWCOLLECTION */ static LWCOLLECTION * lwcollection_linearize(const LWCOLLECTION *collection, double tol, LW_LINEARIZE_TOLERANCE_TYPE type, int flags) { LWCOLLECTION *ocol; LWGEOM *tmp; LWGEOM **geoms; int i; LWDEBUG(2, "lwcollection_linearize called."); geoms = lwalloc(sizeof(LWGEOM *)*collection->ngeoms); for (i=0; i<collection->ngeoms; i++) { tmp = collection->geoms[i]; switch (tmp->type) { case CIRCSTRINGTYPE: geoms[i] = (LWGEOM *)lwcircstring_linearize((LWCIRCSTRING *)tmp, tol, type, flags); break; case COMPOUNDTYPE: geoms[i] = (LWGEOM *)lwcompound_linearize((LWCOMPOUND *)tmp, tol, type, flags); break; case CURVEPOLYTYPE: geoms[i] = (LWGEOM *)lwcurvepoly_linearize((LWCURVEPOLY *)tmp, tol, type, flags); break; case MULTICURVETYPE: case MULTISURFACETYPE: case COLLECTIONTYPE: geoms[i] = (LWGEOM *)lwcollection_linearize((LWCOLLECTION *)tmp, tol, type, flags); break; default: geoms[i] = lwgeom_clone(tmp); break; } } ocol = lwcollection_construct(COLLECTIONTYPE, collection->srid, NULL, collection->ngeoms, geoms); return ocol; }
LWGEOM * lwgeom_segmentize2d(LWGEOM *lwgeom, double dist) { switch (lwgeom->type) { case LINETYPE: return (LWGEOM *)lwline_segmentize2d((LWLINE *)lwgeom, dist); case POLYGONTYPE: return (LWGEOM *)lwpoly_segmentize2d((LWPOLY *)lwgeom, dist); case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: return (LWGEOM *)lwcollection_segmentize2d( (LWCOLLECTION *)lwgeom, dist); default: return lwgeom_clone(lwgeom); } }
LWGEOM* lwgeom_set_effective_area(const LWGEOM *igeom,int set_area, double trshld) { LWDEBUG(2, "Entered lwgeom_set_effective_area"); switch (igeom->type) { case POINTTYPE: case MULTIPOINTTYPE: return lwgeom_clone(igeom); case LINETYPE: return (LWGEOM*)lwline_set_effective_area((LWLINE*)igeom,set_area, trshld); case POLYGONTYPE: return (LWGEOM*)lwpoly_set_effective_area((LWPOLY*)igeom,set_area, trshld); case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: return (LWGEOM*)lwcollection_set_effective_area((LWCOLLECTION *)igeom,set_area, trshld); default: lwerror("lwgeom_simplify: unsupported geometry type: %s",lwtype_name(igeom->type)); } return NULL; }
/* ** Given a generic collection, return the "simplest" form. ** ** eg: GEOMETRYCOLLECTION(MULTILINESTRING()) => MULTILINESTRING() ** ** GEOMETRYCOLLECTION(MULTILINESTRING(), MULTILINESTRING(), POINT()) ** => GEOMETRYCOLLECTION(MULTILINESTRING(), POINT()) ** ** In general, if the subcomponents are homogeneous, return a properly ** typed collection. ** Otherwise, return a generic collection, with the subtypes in minimal ** typed collections. */ static void lwcollection_build_buffer(const LWCOLLECTION *col, HomogenizeBuffer *buffer) { int i; if ( ! col ) return; if ( lwgeom_is_empty(lwcollection_as_lwgeom(col)) ) return; for ( i = 0; i < col->ngeoms; i++ ) { LWGEOM *geom = col->geoms[i]; switch(geom->type) { case POINTTYPE: case LINETYPE: case CIRCSTRINGTYPE: case COMPOUNDTYPE: case TRIANGLETYPE: case CURVEPOLYTYPE: case POLYGONTYPE: { /* Init if necessary */ if ( ! buffer->buf[geom->type] ) { LWCOLLECTION *bufcol = lwcollection_construct_empty(COLLECTIONTYPE, col->srid, FLAGS_GET_Z(col->flags), FLAGS_GET_M(col->flags)); bufcol->type = lwtype_get_collectiontype(geom->type); buffer->buf[geom->type] = bufcol; } /* Add sub-geom to buffer */ lwcollection_add_lwgeom(buffer->buf[geom->type], lwgeom_clone(geom)); /* Increment count for this singleton type */ buffer->cnt[geom->type] = buffer->cnt[geom->type] + 1; } default: { lwcollection_build_buffer(lwgeom_as_lwcollection(geom), buffer); } } } return; }
/** * @brief Clone #LWCOLLECTION object. #POINTARRAY are not copied. * Bbox is cloned if present in input. */ LWCOLLECTION * lwcollection_clone(const LWCOLLECTION *g) { uint32_t i; LWCOLLECTION *ret = lwalloc(sizeof(LWCOLLECTION)); memcpy(ret, g, sizeof(LWCOLLECTION)); if ( g->ngeoms > 0 ) { ret->geoms = lwalloc(sizeof(LWGEOM *)*g->ngeoms); for (i=0; i<g->ngeoms; i++) { ret->geoms[i] = lwgeom_clone(g->geoms[i]); } if ( g->bbox ) ret->bbox = gbox_copy(g->bbox); } else { ret->bbox = NULL; /* empty collection */ ret->geoms = NULL; } return ret; }
LWCOLLECTION * lwcollection_segmentize(LWCOLLECTION *collection, uint32_t perQuad) { LWCOLLECTION *ocol; LWGEOM *tmp; LWGEOM **geoms; int i; LWDEBUG(2, "lwcollection_segmentize called."); geoms = lwalloc(sizeof(LWGEOM *)*collection->ngeoms); for (i=0; i<collection->ngeoms; i++) { tmp = collection->geoms[i]; switch (tmp->type) { case CIRCSTRINGTYPE: geoms[i] = (LWGEOM *)lwcircstring_segmentize((LWCIRCSTRING *)tmp, perQuad); break; case COMPOUNDTYPE: geoms[i] = (LWGEOM *)lwcompound_segmentize((LWCOMPOUND *)tmp, perQuad); break; case CURVEPOLYTYPE: geoms[i] = (LWGEOM *)lwcurvepoly_segmentize((LWCURVEPOLY *)tmp, perQuad); break; case COLLECTIONTYPE: geoms[i] = (LWGEOM *)lwcollection_segmentize((LWCOLLECTION *)tmp, perQuad); break; default: geoms[i] = lwgeom_clone(tmp); break; } } ocol = lwcollection_construct(COLLECTIONTYPE, collection->srid, NULL, collection->ngeoms, geoms); return ocol; }
LWGEOM * lwgeom_intersection(const LWGEOM *geom1, const LWGEOM *geom2) { LWGEOM *result ; GEOSGeometry *g1, *g2, *g3 ; int is3d ; int srid ; /* A.Intersection(Empty) == Empty */ if ( lwgeom_is_empty(geom2) ) return lwgeom_clone(geom2); /* Empty.Intersection(A) == Empty */ if ( lwgeom_is_empty(geom1) ) return lwgeom_clone(geom1); /* ensure srids are identical */ srid = (int)(geom1->srid); error_if_srid_mismatch(srid, (int)(geom2->srid)); is3d = (FLAGS_GET_Z(geom1->flags) || FLAGS_GET_Z(geom2->flags)) ; initGEOS(lwnotice, lwgeom_geos_error); LWDEBUG(3, "intersection() START"); g1 = LWGEOM2GEOS(geom1); if ( 0 == g1 ) /* exception thrown at construction */ { lwerror("First argument geometry could not be converted to GEOS."); return NULL ; } g2 = LWGEOM2GEOS(geom2); if ( 0 == g2 ) /* exception thrown at construction */ { lwerror("Second argument geometry could not be converted to GEOS."); GEOSGeom_destroy(g1); return NULL ; } LWDEBUG(3, " constructed geometrys - calling geos"); LWDEBUGF(3, " g1 = %s", GEOSGeomToWKT(g1)); LWDEBUGF(3, " g2 = %s", GEOSGeomToWKT(g2)); /*LWDEBUGF(3, "g2 is valid = %i",GEOSisvalid(g2)); */ /*LWDEBUGF(3, "g1 is valid = %i",GEOSisvalid(g1)); */ g3 = GEOSIntersection(g1,g2); LWDEBUG(3, " intersection finished"); if (g3 == NULL) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); lwerror("Error performing intersection: %s", lwgeom_geos_errmsg); return NULL; /* never get here */ } LWDEBUGF(3, "result: %s", GEOSGeomToWKT(g3) ) ; GEOSSetSRID(g3, srid); result = GEOS2LWGEOM(g3, is3d); if (result == NULL) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g3); lwerror("Error performing intersection: GEOS2LWGEOM: %s", lwgeom_geos_errmsg); return NULL ; /* never get here */ } GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g3); return result ; }
/* ** Given a generic geometry, return the "simplest" form. ** ** eg: ** LINESTRING() => LINESTRING() ** ** MULTILINESTRING(with a single line) => LINESTRING() ** ** GEOMETRYCOLLECTION(MULTILINESTRING()) => MULTILINESTRING() ** ** GEOMETRYCOLLECTION(MULTILINESTRING(), MULTILINESTRING(), POINT()) ** => GEOMETRYCOLLECTION(MULTILINESTRING(), POINT()) */ LWGEOM * lwgeom_homogenize(const LWGEOM *geom) { LWGEOM *hgeom; /* EMPTY Geometry */ if (lwgeom_is_empty(geom)) { if( lwgeom_is_collection(geom) ) { return lwcollection_as_lwgeom(lwcollection_construct_empty(geom->type, geom->srid, lwgeom_has_z(geom), lwgeom_has_m(geom))); } return lwgeom_clone(geom); } switch (geom->type) { /* Return simple geometries untouched */ case POINTTYPE: case LINETYPE: case CIRCSTRINGTYPE: case COMPOUNDTYPE: case TRIANGLETYPE: case CURVEPOLYTYPE: case POLYGONTYPE: return lwgeom_clone(geom); /* Process homogeneous geometries lightly */ case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case MULTICURVETYPE: case MULTISURFACETYPE: case POLYHEDRALSURFACETYPE: case TINTYPE: { LWCOLLECTION *col = (LWCOLLECTION*)geom; /* Strip single-entry multi-geometries down to singletons */ if ( col->ngeoms == 1 ) { hgeom = lwgeom_clone((LWGEOM*)(col->geoms[0])); hgeom->srid = geom->srid; if (geom->bbox) hgeom->bbox = gbox_copy(geom->bbox); return hgeom; } /* Return proper multigeometry untouched */ return lwgeom_clone(geom); } /* Work on anonymous collections separately */ case COLLECTIONTYPE: return lwcollection_homogenize((LWCOLLECTION *) geom); } /* Unknown type */ lwerror("lwgeom_homogenize: Geometry Type not supported (%i)", lwtype_name(geom->type)); return NULL; /* Never get here! */ }
LWGEOM* lwgeom_union(const LWGEOM *geom1, const LWGEOM *geom2) { int is3d; int srid; GEOSGeometry *g1, *g2, *g3; LWGEOM *result; LWDEBUG(2, "in geomunion"); /* A.Union(empty) == A */ if ( lwgeom_is_empty(geom1) ) return lwgeom_clone(geom2); /* B.Union(empty) == B */ if ( lwgeom_is_empty(geom2) ) return lwgeom_clone(geom1); /* ensure srids are identical */ srid = (int)(geom1->srid); error_if_srid_mismatch(srid, (int)(geom2->srid)); is3d = (FLAGS_GET_Z(geom1->flags) || FLAGS_GET_Z(geom2->flags)) ; initGEOS(lwnotice, lwgeom_geos_error); g1 = LWGEOM2GEOS(geom1); if ( 0 == g1 ) /* exception thrown at construction */ { lwerror("First argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg); return NULL; } g2 = LWGEOM2GEOS(geom2); if ( 0 == g2 ) /* exception thrown at construction */ { GEOSGeom_destroy(g1); lwerror("Second argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg); return NULL; } LWDEBUGF(3, "g1=%s", GEOSGeomToWKT(g1)); LWDEBUGF(3, "g2=%s", GEOSGeomToWKT(g2)); g3 = GEOSUnion(g1,g2); LWDEBUGF(3, "g3=%s", GEOSGeomToWKT(g3)); GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); if (g3 == NULL) { lwerror("GEOSUnion: %s", lwgeom_geos_errmsg); return NULL; /* never get here */ } GEOSSetSRID(g3, srid); result = GEOS2LWGEOM(g3, is3d); GEOSGeom_destroy(g3); if (result == NULL) { lwerror("Error performing union: GEOS2LWGEOM: %s", lwgeom_geos_errmsg); return NULL; /*never get here */ } return result; }
/** * Takes a potentially heterogeneous collection and returns a homogeneous * collection consisting only of the specified type. */ LWCOLLECTION* lwcollection_extract(LWCOLLECTION *col, int type) { int i = 0; LWGEOM **geomlist; LWCOLLECTION *outcol; int geomlistsize = 16; int geomlistlen = 0; uint8_t outtype; if ( ! col ) return NULL; switch (type) { case POINTTYPE: outtype = MULTIPOINTTYPE; break; case LINETYPE: outtype = MULTILINETYPE; break; case POLYGONTYPE: outtype = MULTIPOLYGONTYPE; break; default: lwerror("Only POLYGON, LINESTRING and POINT are supported by lwcollection_extract. %s requested.", lwtype_name(type)); return NULL; } geomlist = lwalloc(sizeof(LWGEOM*) * geomlistsize); /* Process each sub-geometry */ for ( i = 0; i < col->ngeoms; i++ ) { int subtype = col->geoms[i]->type; /* Don't bother adding empty sub-geometries */ if ( lwgeom_is_empty(col->geoms[i]) ) { continue; } /* Copy our sub-types into the output list */ if ( subtype == type ) { /* We've over-run our buffer, double the memory segment */ if ( geomlistlen == geomlistsize ) { geomlistsize *= 2; geomlist = lwrealloc(geomlist, sizeof(LWGEOM*) * geomlistsize); } geomlist[geomlistlen] = lwgeom_clone(col->geoms[i]); geomlistlen++; } /* Recurse into sub-collections */ if ( lwtype_is_collection( subtype ) ) { int j = 0; LWCOLLECTION *tmpcol = lwcollection_extract((LWCOLLECTION*)col->geoms[i], type); for ( j = 0; j < tmpcol->ngeoms; j++ ) { /* We've over-run our buffer, double the memory segment */ if ( geomlistlen == geomlistsize ) { geomlistsize *= 2; geomlist = lwrealloc(geomlist, sizeof(LWGEOM*) * geomlistsize); } geomlist[geomlistlen] = tmpcol->geoms[j]; geomlistlen++; } lwfree(tmpcol); } } if ( geomlistlen > 0 ) { GBOX gbox; outcol = lwcollection_construct(outtype, col->srid, NULL, geomlistlen, geomlist); lwgeom_calculate_gbox((LWGEOM *) outcol, &gbox); outcol->bbox = gbox_copy(&gbox); } else { lwfree(geomlist); outcol = lwcollection_construct_empty(outtype, col->srid, FLAGS_GET_Z(col->flags), FLAGS_GET_M(col->flags)); } return outcol; }
LWGEOM * lwgeom_symdifference(const LWGEOM* geom1, const LWGEOM* geom2) { GEOSGeometry *g1, *g2, *g3; LWGEOM *result; int is3d; int srid; /* A.SymDifference(Empty) == A */ if ( lwgeom_is_empty(geom2) ) return lwgeom_clone(geom1); /* Empty.DymDifference(B) == Empty */ if ( lwgeom_is_empty(geom1) ) return lwgeom_clone(geom1); /* ensure srids are identical */ srid = (int)(geom1->srid); error_if_srid_mismatch(srid, (int)(geom2->srid)); is3d = (FLAGS_GET_Z(geom1->flags) || FLAGS_GET_Z(geom2->flags)) ; initGEOS(lwnotice, lwgeom_geos_error); g1 = LWGEOM2GEOS(geom1); if ( 0 == g1 ) /* exception thrown at construction */ { lwerror("First argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg); return NULL; } g2 = LWGEOM2GEOS(geom2); if ( 0 == g2 ) /* exception thrown at construction */ { lwerror("Second argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg); GEOSGeom_destroy(g1); return NULL; } g3 = GEOSSymDifference(g1,g2); if (g3 == NULL) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); lwerror("GEOSSymDifference: %s", lwgeom_geos_errmsg); return NULL; /*never get here */ } LWDEBUGF(3, "result: %s", GEOSGeomToWKT(g3)); GEOSSetSRID(g3, srid); result = GEOS2LWGEOM(g3, is3d); if (result == NULL) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g3); lwerror("GEOS symdifference() threw an error (result postgis geometry formation)!"); return NULL ; /*never get here */ } GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g3); return result; }