h = lwgeom_homogenize(g);
tmp = lwgeom_to_ewkt(h);
if (strcmp(tmp, out))
- fprintf(stderr, "\nIn: %s\nOut: %s\nTheo: %s\n",
- in, tmp, out);
- CU_ASSERT_STRING_EQUAL(tmp, out);
- lwfree(tmp);
- lwgeom_free(g);
- /* See http://trac.osgeo.org/postgis/ticket/1104 */
- lwgeom_free(h);
-}
-
-
-static void do_coll_test(char * in, char * out)
-{
- LWGEOM *g, *h;
- char *tmp;
-
- g = lwgeom_from_wkt(in, LW_PARSER_CHECK_NONE);
- h = lwcollection_homogenize((LWCOLLECTION *) g);
- tmp = lwgeom_to_ewkt(h);
- if (strcmp(tmp, out))
- fprintf(stderr, "\nIn: %s\nOut: %s\nTheo: %s\n",
+ fprintf(stderr, "\nIn: %s\nOut: %s\nExp: %s\n",
in, tmp, out);
CU_ASSERT_STRING_EQUAL(tmp, out);
lwfree(tmp);
static void test_coll_point(void)
{
- do_coll_test("GEOMETRYCOLLECTION(POINT(1 2))",
+ do_geom_test("GEOMETRYCOLLECTION(POINT(1 2))",
"POINT(1 2)");
- do_coll_test("GEOMETRYCOLLECTION(POINT(1 2),POINT(3 4))",
+ do_geom_test("GEOMETRYCOLLECTION(POINT(1 2),POINT(3 4))",
"MULTIPOINT(1 2,3 4)");
- do_coll_test("GEOMETRYCOLLECTION(POINT(1 2),POINT(3 4),POINT(5 6))",
+ do_geom_test("GEOMETRYCOLLECTION(POINT(1 2),POINT(3 4),POINT(5 6))",
"MULTIPOINT(1 2,3 4,5 6)");
- do_coll_test("GEOMETRYCOLLECTION(MULTIPOINT(1 2,3 4),POINT(5 6))",
+ do_geom_test("GEOMETRYCOLLECTION(MULTIPOINT(1 2,3 4),POINT(5 6))",
"MULTIPOINT(1 2,3 4,5 6)");
- do_coll_test("GEOMETRYCOLLECTION(POINT(1 2),MULTIPOINT(3 4,5 6))",
+ do_geom_test("GEOMETRYCOLLECTION(POINT(1 2),MULTIPOINT(3 4,5 6))",
"MULTIPOINT(1 2,3 4,5 6)");
- do_coll_test("GEOMETRYCOLLECTION(MULTIPOINT(1 2,3 4),MULTIPOINT(5 6,7 8))",
+ do_geom_test("GEOMETRYCOLLECTION(MULTIPOINT(1 2,3 4),MULTIPOINT(5 6,7 8))",
"MULTIPOINT(1 2,3 4,5 6,7 8)");
}
static void test_coll_line(void)
{
- do_coll_test("GEOMETRYCOLLECTION(LINESTRING(1 2,3 4))",
+ do_geom_test("GEOMETRYCOLLECTION(LINESTRING(1 2,3 4))",
"LINESTRING(1 2,3 4)");
- do_coll_test("GEOMETRYCOLLECTION(LINESTRING(1 2,3 4),LINESTRING(5 6,7 8))",
+ do_geom_test("GEOMETRYCOLLECTION(LINESTRING(1 2,3 4),LINESTRING(5 6,7 8))",
"MULTILINESTRING((1 2,3 4),(5 6,7 8))");
- do_coll_test("GEOMETRYCOLLECTION(LINESTRING(1 2,3 4),LINESTRING(5 6,7 8),LINESTRING(9 10,11 12))",
+ do_geom_test("GEOMETRYCOLLECTION(LINESTRING(1 2,3 4),LINESTRING(5 6,7 8),LINESTRING(9 10,11 12))",
"MULTILINESTRING((1 2,3 4),(5 6,7 8),(9 10,11 12))");
- do_coll_test("GEOMETRYCOLLECTION(MULTILINESTRING((1 2,3 4),(5 6,7 8)),LINESTRING(9 10,11 12))",
+ do_geom_test("GEOMETRYCOLLECTION(MULTILINESTRING((1 2,3 4),(5 6,7 8)),LINESTRING(9 10,11 12))",
"MULTILINESTRING((1 2,3 4),(5 6,7 8),(9 10,11 12))");
- do_coll_test("GEOMETRYCOLLECTION(LINESTRING(1 2,3 4),MULTILINESTRING((5 6,7 8),(9 10,11 12)))",
+ do_geom_test("GEOMETRYCOLLECTION(LINESTRING(1 2,3 4),MULTILINESTRING((5 6,7 8),(9 10,11 12)))",
"MULTILINESTRING((1 2,3 4),(5 6,7 8),(9 10,11 12))");
- do_coll_test("GEOMETRYCOLLECTION(MULTILINESTRING((1 2,3 4),(5 6,7 8)),MULTILINESTRING((9 10,11 12),(13 14,15 16)))",
+ do_geom_test("GEOMETRYCOLLECTION(MULTILINESTRING((1 2,3 4),(5 6,7 8)),MULTILINESTRING((9 10,11 12),(13 14,15 16)))",
"MULTILINESTRING((1 2,3 4),(5 6,7 8),(9 10,11 12),(13 14,15 16))");
}
static void test_coll_poly(void)
{
- do_coll_test("GEOMETRYCOLLECTION(POLYGON((1 2,3 4,5 6,1 2)))",
+ do_geom_test("GEOMETRYCOLLECTION(POLYGON((1 2,3 4,5 6,1 2)))",
"POLYGON((1 2,3 4,5 6,1 2))");
- do_coll_test("GEOMETRYCOLLECTION(POLYGON((1 2,3 4,5 6,1 2)),POLYGON((7 8,9 10,11 12,7 8)))",
+ do_geom_test("GEOMETRYCOLLECTION(POLYGON((1 2,3 4,5 6,1 2)),POLYGON((7 8,9 10,11 12,7 8)))",
"MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,9 10,11 12,7 8)))");
- do_coll_test("GEOMETRYCOLLECTION(POLYGON((1 2,3 4,5 6,1 2)),POLYGON((7 8,9 10,11 12,7 8)),POLYGON((13 14,15 16,17 18,13 14)))",
+ do_geom_test("GEOMETRYCOLLECTION(POLYGON((1 2,3 4,5 6,1 2)),POLYGON((7 8,9 10,11 12,7 8)),POLYGON((13 14,15 16,17 18,13 14)))",
"MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,9 10,11 12,7 8)),((13 14,15 16,17 18,13 14)))");
- do_coll_test("GEOMETRYCOLLECTION(MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,9 10,11 12,7 8))),POLYGON((13 14,15 16,17 18,13 14)))",
+ do_geom_test("GEOMETRYCOLLECTION(MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,9 10,11 12,7 8))),POLYGON((13 14,15 16,17 18,13 14)))",
"MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,9 10,11 12,7 8)),((13 14,15 16,17 18,13 14)))");
- do_coll_test("GEOMETRYCOLLECTION(POLYGON((1 2,3 4,5 6,1 2)),MULTIPOLYGON(((7 8,9 10,11 12,7 8)),((13 14,15 16,17 18,13 14))))",
+ do_geom_test("GEOMETRYCOLLECTION(POLYGON((1 2,3 4,5 6,1 2)),MULTIPOLYGON(((7 8,9 10,11 12,7 8)),((13 14,15 16,17 18,13 14))))",
"MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,9 10,11 12,7 8)),((13 14,15 16,17 18,13 14)))");
- do_coll_test("GEOMETRYCOLLECTION(MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,9 10,11 12,7 8))),MULTIPOLYGON(((13 14,15 16,17 18,13 14)),((19 20,21 22,23 24,19 20))))",
+ do_geom_test("GEOMETRYCOLLECTION(MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,9 10,11 12,7 8))),MULTIPOLYGON(((13 14,15 16,17 18,13 14)),((19 20,21 22,23 24,19 20))))",
"MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,9 10,11 12,7 8)),((13 14,15 16,17 18,13 14)),((19 20,21 22,23 24,19 20)))");
}
static void test_coll_coll(void)
{
/* Two different types together must produce a Collection as output */
- do_coll_test("GEOMETRYCOLLECTION(POINT(1 2),LINESTRING(3 4,5 6))",
+ do_geom_test("GEOMETRYCOLLECTION(POINT(1 2),LINESTRING(3 4,5 6))",
"GEOMETRYCOLLECTION(POINT(1 2),LINESTRING(3 4,5 6))");
- do_coll_test("GEOMETRYCOLLECTION(LINESTRING(1 2,3 4),POLYGON((5 6,7 8,9 10,5 6)))",
+ do_geom_test("GEOMETRYCOLLECTION(LINESTRING(1 2,3 4),POLYGON((5 6,7 8,9 10,5 6)))",
"GEOMETRYCOLLECTION(LINESTRING(1 2,3 4),POLYGON((5 6,7 8,9 10,5 6)))");
/* Ability to produce a single MULTI with same type */
- do_coll_test("GEOMETRYCOLLECTION(POINT(1 2),LINESTRING(3 4,5 6),POINT(7 8))",
+ do_geom_test("GEOMETRYCOLLECTION(POINT(1 2),LINESTRING(3 4,5 6),POINT(7 8))",
"GEOMETRYCOLLECTION(MULTIPOINT(1 2,7 8),LINESTRING(3 4,5 6))");
- do_coll_test("GEOMETRYCOLLECTION(POINT(1 2),LINESTRING(3 4,5 6),MULTIPOINT(7 8,9 10))",
+ do_geom_test("GEOMETRYCOLLECTION(POINT(1 2),LINESTRING(3 4,5 6),MULTIPOINT(7 8,9 10))",
"GEOMETRYCOLLECTION(MULTIPOINT(1 2,7 8,9 10),LINESTRING(3 4,5 6))");
/* Recursive Collection handle */
- do_coll_test("GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(1 2))))",
+ do_geom_test("GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(1 2))))",
"POINT(1 2)");
- do_coll_test("GEOMETRYCOLLECTION(POINT(1 2),GEOMETRYCOLLECTION(LINESTRING(3 4,5 6)))",
+ do_geom_test("GEOMETRYCOLLECTION(POINT(1 2),GEOMETRYCOLLECTION(LINESTRING(3 4,5 6)))",
"GEOMETRYCOLLECTION(POINT(1 2),LINESTRING(3 4,5 6))");
/* EMPTY Collection */
- do_coll_test("GEOMETRYCOLLECTION EMPTY",
+ do_geom_test("GEOMETRYCOLLECTION EMPTY",
"GEOMETRYCOLLECTION EMPTY");
/* Recursive EMPTY Collection */
- do_coll_test("GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY)",
+ do_geom_test("GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY)",
"GEOMETRYCOLLECTION EMPTY");
- do_coll_test("GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY))",
+ do_geom_test("GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY))",
"GEOMETRYCOLLECTION EMPTY");
}
+static void test_coll_curve(void)
+{
+ /* Two different types together must produce a Collection as output */
+ do_geom_test("GEOMETRYCOLLECTION(CIRCULARSTRING(0 0,1 1,2 2))",
+ "CIRCULARSTRING(0 0,1 1,2 2)");
+
+ do_geom_test("GEOMETRYCOLLECTION(CIRCULARSTRING(0 0,1 1,2 2),CIRCULARSTRING(0 0,1 1,2 2))",
+ "MULTICURVE(CIRCULARSTRING(0 0,1 1,2 2),CIRCULARSTRING(0 0,1 1,2 2))");
+}
static void test_geom(void)
{
PG_TEST(test_coll_poly),
PG_TEST(test_coll_coll),
PG_TEST(test_geom),
+ PG_TEST(test_coll_curve),
CU_TEST_INFO_NULL
};
CU_SuiteInfo homogenize_suite = {"Homogenize Suite", NULL, NULL, homogenize_tests};
#include <stdlib.h>
#include "liblwgeom_internal.h"
#include "lwgeom_log.h"
-#include "lwhomogenize.h"
-/*
-** Known limitation: not (yet ?) support SQL/MM Curves.
-*/
+typedef struct {
+ int cnt[NUMTYPES];
+ LWCOLLECTION* buf[NUMTYPES];
+} HomogenizeBuffer;
-
-/*
-** 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)
+static void
+init_homogenizebuffer(HomogenizeBuffer *buffer)
{
- LWGEOM *hgeom;
-
- /* EMPTY Geometry */
- if (lwgeom_is_empty(geom)) return lwgeom_clone(geom);
-
- /* Already a simple Geometry */
- switch (geom->type)
+ int i;
+ for ( i = 0; i < NUMTYPES; i++ )
{
- case POINTTYPE:
- case LINETYPE:
- case POLYGONTYPE:
- return lwgeom_clone(geom);
+ buffer->cnt[i] = 0;
+ buffer->buf[i] = NULL;
}
+}
- /* A MULTI */
- switch (geom->type)
+static void
+free_homogenizebuffer(HomogenizeBuffer *buffer)
+{
+ int i;
+ for ( i = 0; i < NUMTYPES; i++ )
{
- case MULTIPOINTTYPE:
- case MULTILINETYPE:
- case MULTIPOLYGONTYPE:
-
- /* A MULTI with a single geometry inside */
- if (((LWCOLLECTION *) geom)->ngeoms == 1)
+ if ( buffer->buf[i] )
{
-
- hgeom = lwgeom_clone((LWGEOM *)
- ((LWCOLLECTION *)geom)->geoms[0]);
-
- hgeom->srid = geom->srid;
- if (geom->bbox)
- hgeom->bbox = gbox_copy(geom->bbox);
-
- return hgeom;
+ lwcollection_free(buffer->buf[i]);
}
-
- /* A 'real' MULTI */
- return lwgeom_clone(geom);
}
-
- if (geom->type == COLLECTIONTYPE)
- return lwcollection_homogenize((LWCOLLECTION *) geom);
-
- lwerror("lwgeom_homogenize: Geometry Type not supported (%i)",
- lwtype_name(geom->type));
-
- return NULL; /*Never reach */
}
-
/*
** Given a generic collection, return the "simplest" form.
**
** Otherwise, return a generic collection, with the subtypes in minimal
** typed collections.
*/
-LWGEOM *
-lwcollection_homogenize(const LWCOLLECTION *col)
+static void
+lwcollection_build_buffer(const LWCOLLECTION *col, HomogenizeBuffer *buffer)
{
- uint32_t i, srid;
- uint8_t hasz, hasm;
- LWGEOM *res = NULL;
- LWCOLLECTION *coll;
- LWGEOM_HOMOGENIZE *geoms;
-
- if (!col) lwerror("lwcollection_homogenize: Null input geometry.");
-
- /* EMPTY Geometry case */
- if (col->ngeoms == 0)
- return (LWGEOM *) lwcollection_construct_empty(COLLECTIONTYPE, col->srid, 0, 0);
-
- hasz = FLAGS_GET_Z(col->flags);
- hasm = FLAGS_GET_M(col->flags);
- srid = col->srid;
-
- /* LWGEOM_HOMOGENIZE struct setup */
- geoms = lwalloc(sizeof(LWGEOM_HOMOGENIZE));
- geoms->points = lwmpoint_construct_empty(SRID_UNKNOWN, hasz, hasm);
- geoms->lines = lwmline_construct_empty(SRID_UNKNOWN, hasz, hasm);
- geoms->polys = lwmpoly_construct_empty(SRID_UNKNOWN, hasz, hasm);
-
- LWDEBUGF(4, "geoms->points %p", geoms->points);
-
- /* Parse each sub geom and update LWGEOM_HOMOGENIZE struct */
- for (i=0 ; i < col->ngeoms ; i++)
- geoms = lwcollection_homogenize_subgeom(geoms, col->geoms[i]);
-
- /* Check if struct is mixed typed, and need a COLLECTION as output */
- if ((geoms->points->ngeoms && geoms->lines->ngeoms) ||
- (geoms->points->ngeoms && geoms->polys->ngeoms) ||
- (geoms->lines->ngeoms && geoms->polys->ngeoms))
+ int i;
+
+ if ( ! col ) return;
+ if ( lwgeom_is_empty(lwcollection_as_lwgeom(col)) ) return;
+ for ( i = 0; i < col->ngeoms; i++ )
{
- LWDEBUGF(4,"geoms->points->ngeoms %d geoms->lines->ngeoms %d geoms->polys->ngeoms %d", geoms->points->ngeoms, geoms->lines->ngeoms, geoms->polys->ngeoms);
- coll = lwcollection_construct_empty(COLLECTIONTYPE, srid, hasz, hasm);
-
- LWDEBUGF(4,"coll->ngeoms %d", coll->ngeoms);
-
- if (col->bbox) coll->bbox = gbox_copy(col->bbox);
-
- if (geoms->points->ngeoms == 1)
- coll = lwcollection_add_lwgeom(coll, lwgeom_clone((LWGEOM*) geoms->points->geoms[0]));
- else if (geoms->points->ngeoms)
- coll = lwcollection_add_lwgeom(coll, lwgeom_clone((LWGEOM*) geoms->points));
-
- LWDEBUGF(4,"coll->ngeoms %d", coll->ngeoms);
-
- if (geoms->lines->ngeoms == 1)
- coll = lwcollection_add_lwgeom(coll, lwgeom_clone((LWGEOM*) geoms->lines->geoms[0]));
- else if (geoms->lines->ngeoms)
- coll = lwcollection_add_lwgeom(coll, lwgeom_clone((LWGEOM*) geoms->lines));
-
- LWDEBUGF(4,"coll->ngeoms %d", coll->ngeoms);
-
- if (geoms->polys->ngeoms == 1)
- coll = lwcollection_add_lwgeom(coll, lwgeom_clone((LWGEOM*) geoms->polys->geoms[0]));
- else if (geoms->polys->ngeoms)
- coll = lwcollection_add_lwgeom(coll, lwgeom_clone((LWGEOM*) geoms->polys));
-
- LWDEBUGF(4,"coll->ngeoms %d", coll->ngeoms);
-
- /* We could now free the struct */
- lwmpoint_free(geoms->points);
- lwmline_free(geoms->lines);
- lwmpoly_free(geoms->polys);
- lwfree(geoms);
-
- for ( i = 0; i < coll->ngeoms; i++ )
- LWDEBUGF(2,"coll->geoms[%d]->type %d", i, coll->geoms[i]->type);
-
-
- return (LWGEOM *) coll;
+ 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);
+ }
+ }
}
-
- /* Check if we have to return simple type (i.e not a MULTI) */
- if (geoms->points->ngeoms == 1)
- res = lwgeom_clone((LWGEOM *) geoms->points->geoms[0]);
- if (geoms->lines->ngeoms == 1)
- res = lwgeom_clone((LWGEOM *) geoms->lines->geoms[0]);
- if (geoms->polys->ngeoms == 1)
- res = lwgeom_clone((LWGEOM *) geoms->polys->geoms[0]);
-
- /* We have to return a single MULTI */
- if (geoms->points->ngeoms > 1)
- res = lwgeom_clone((LWGEOM *) geoms->points);
- if (geoms->lines->ngeoms > 1)
- res = lwgeom_clone((LWGEOM *) geoms->lines);
- if (geoms->polys->ngeoms > 1)
- res = lwgeom_clone((LWGEOM *) geoms->polys);
-
- /* We could now free the struct */
- lwmpoint_free(geoms->points);
- lwmline_free(geoms->lines);
- lwmpoly_free(geoms->polys);
- lwfree(geoms);
-
- /* Empty (and recursive) Geometry case */
- if (!res) return (LWGEOM *) lwcollection_construct_empty(COLLECTIONTYPE, col->srid, 0, 0);
-
- /* Handle srid and Bbox */
- res->srid = srid;
- if (col->bbox) res->bbox = gbox_copy(col->bbox);
-
- return res;
+ return;
}
-static LWGEOM_HOMOGENIZE*
-lwcollection_homogenize_subgeom(LWGEOM_HOMOGENIZE *hgeoms, LWGEOM *geom)
+static LWGEOM*
+lwcollection_homogenize(const LWCOLLECTION *col)
{
- uint32_t i;
-
- if (!geom) lwerror("lwcollection_homogenize: Sub geometry is Null");
-
- /* We manage the srid in lwcollection_homogenize */
- geom->srid = SRID_UNKNOWN;
-
- if (geom->type == POINTTYPE)
+ int i;
+ int ntypes = 0;
+ int type = 0;
+ LWGEOM *outgeom = NULL;
+
+ HomogenizeBuffer buffer;
+
+ /* Sort all the parts into a buffer */
+ init_homogenizebuffer(&buffer);
+ lwcollection_build_buffer(col, &buffer);
+
+ /* Check for homogeneity */
+ for ( i = 0; i < NUMTYPES; i++ )
{
- hgeoms->points = lwmpoint_add_lwpoint(hgeoms->points, (LWPOINT*)lwgeom_clone(geom));
+ if ( buffer.cnt[i] > 0 )
+ {
+ ntypes++;
+ type = i;
+ }
}
- else if (geom->type == LINETYPE)
+
+ /* No types? Huh. Return empty. */
+ if ( ntypes == 0 )
{
- hgeoms->lines = lwmline_add_lwline(hgeoms->lines, (LWLINE*)lwgeom_clone(geom));
+ LWCOLLECTION *outcol;
+ outcol = lwcollection_construct_empty(COLLECTIONTYPE, col->srid, FLAGS_GET_Z(col->flags), FLAGS_GET_M(col->flags));
+ outgeom = lwcollection_as_lwgeom(outcol);
}
- else if (geom->type == POLYGONTYPE)
+ /* One type, return homogeneous collection */
+ else if ( ntypes == 1 )
{
- hgeoms->polys = lwmpoly_add_lwpoly(hgeoms->polys, (LWPOLY*)lwgeom_clone(geom));
+ LWCOLLECTION *outcol;
+ outcol = buffer.buf[type];
+ if ( outcol->ngeoms == 1 )
+ {
+ outgeom = outcol->geoms[0];
+ lwfree(outcol);
+ }
+ else
+ {
+ outgeom = lwcollection_as_lwgeom(outcol);
+ }
}
- else if ( lwtype_is_collection(geom->type) )
+ /* Bah, more than out type, return anonymous collection */
+ else if ( ntypes > 1 )
{
- LWCOLLECTION *obj = (LWCOLLECTION*)geom;
- for (i=0; i < obj->ngeoms ; i++)
- hgeoms = lwcollection_homogenize_subgeom(hgeoms, obj->geoms[i]);
+ int j;
+ LWCOLLECTION *outcol;
+ outcol = lwcollection_construct_empty(COLLECTIONTYPE, col->srid, FLAGS_GET_Z(col->flags), FLAGS_GET_M(col->flags));
+ for ( j = 0; j < NUMTYPES; j++ )
+ {
+ if ( buffer.buf[j] )
+ {
+ LWCOLLECTION *bcol = buffer.buf[j];
+ if ( bcol->ngeoms == 1 )
+ {
+ lwcollection_add_lwgeom(outcol, bcol->geoms[0]);
+ lwfree(bcol);
+ }
+ else
+ {
+ lwcollection_add_lwgeom(outcol, lwcollection_as_lwgeom(bcol));
+ }
+ }
+ }
+ outgeom = lwcollection_as_lwgeom(outcol);
}
- else
+
+ return outgeom;
+}
+
+
+
+
+
+/*
+** 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))
{
- lwerror("lwcollection_homogenize: Unsupported geometry type");
+ 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);
}
- return hgeoms;
+ 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! */
}