Ejemplo n.º 1
0
/* May return LWPOINT or LWMPOINT */
static LWGEOM*
lwgeom_extract_unique_endpoints(const LWGEOM* lwg)
{
	LWGEOM* ret;
	GEOSGeometry *gepu;
	LWMPOINT *epall = lwgeom_extract_endpoints(lwg);
	GEOSGeometry *gepall = LWGEOM2GEOS((LWGEOM*)epall, 1);
	lwmpoint_free(epall);
	if ( ! gepall ) {
		lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	/* UnaryUnion to remove duplicates */
	/* TODO: do it all within pgis using indices */
	gepu = GEOSUnaryUnion(gepall);
	if ( ! gepu ) {
		GEOSGeom_destroy(gepall);
		lwerror("GEOSUnaryUnion: %s", lwgeom_geos_errmsg);
		return NULL;
	}
	GEOSGeom_destroy(gepall);

	ret = GEOS2LWGEOM(gepu, FLAGS_GET_Z(lwg->flags));
	GEOSGeom_destroy(gepu);
	if ( ! ret ) {
		lwerror("Error during GEOS2LWGEOM");
		return NULL;
	}

	return ret;
}
Ejemplo n.º 2
0
    void object::test<2>()
    {
        geom1_ = GEOSGeomFromWKT("POINT (6 3)");
        ensure( 0 != geom1_ );

        geom2_ = GEOSUnaryUnion(geom1_);
        ensure( 0 != geom2_ );

        ensure_equals(toWKT(geom2_), std::string("POINT (6 3)"));
    }
Ejemplo n.º 3
0
    void object::test<1>()
    {
        geom1_ = GEOSGeomFromWKT("POINT EMPTY");
        ensure( 0 != geom1_ );

        geom2_ = GEOSUnaryUnion(geom1_);
        ensure( 0 != geom2_ );

        ensure_equals(toWKT(geom2_), std::string("GEOMETRYCOLLECTION EMPTY"));
    }
Ejemplo n.º 4
0
    void object::test<5>()
    {
        geom1_ = GEOSGeomFromWKT("GEOMETRYCOLLECTION (POINT(4 5), MULTIPOINT(6 7, 6 5, 6 7), LINESTRING(0 5, 10 5), LINESTRING(4 -10, 4 10))");
        ensure( 0 != geom1_ );

        geom2_ = GEOSUnaryUnion(geom1_);
        ensure( 0 != geom2_ );

        ensure_equals(toWKT(geom2_), std::string("GEOMETRYCOLLECTION (POINT (6 7), LINESTRING (4 -10, 4 5), LINESTRING (4 5, 4 10), LINESTRING (0 5, 4 5), LINESTRING (4 5, 10 5))"));
    }
Ejemplo n.º 5
0
    void object::test<4>()
    {
        geom1_ = GEOSGeomFromWKT("MULTIPOINT (4 5, 6 7, 4 5, 6 5, 6 7)");
        ensure( 0 != geom1_ );

        geom2_ = GEOSUnaryUnion(geom1_);
        ensure( 0 != geom2_ );

        ensure_equals(toWKT(geom2_), std::string("MULTIPOINT (4 5, 6 5, 6 7)"));
    }
Ejemplo n.º 6
0
    void object::test<8>()
    {
        geom1_ = GEOSGeomFromWKT("GEOMETRYCOLLECTION (MULTILINESTRING((5 7, 12 7), (4 5, 6 5), (5.5 7.5, 6.5 7.5)), POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(5 6, 7 6, 7 8, 5 8, 5 6)), MULTIPOINT(6 6.5, 6 1, 12 2, 6 1))");
        ensure( 0 != geom1_ );

        geom2_ = GEOSUnaryUnion(geom1_);
        ensure( 0 != geom2_ );

        ensure_equals(toWKT(geom2_), std::string(
"GEOMETRYCOLLECTION (POINT (6 6.5), POINT (12 2), LINESTRING (5 7, 7 7), LINESTRING (10 7, 12 7), LINESTRING (5.5 7.5, 6.5 7.5), POLYGON ((10 7, 10 0, 0 0, 0 10, 10 10, 10 7), (5 6, 7 6, 7 7, 7 8, 5 8, 5 7, 5 6)))"
));
    }
Ejemplo n.º 7
0
    void object::test<6>()
    {
        geom1_ = GEOSGeomFromWKT("GEOMETRYCOLLECTION (POINT(4 5), MULTIPOINT(6 7, 6 5, 6 7), POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(5 6, 7 6, 7 8, 5 8, 5 6)))");
        ensure( 0 != geom1_ );

        geom2_ = GEOSUnaryUnion(geom1_);
        ensure( 0 != geom2_ );

        ensure_equals(toWKT(geom2_), std::string(
"GEOMETRYCOLLECTION (POINT (6 7), POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (5 6, 7 6, 7 8, 5 8, 5 6)))"
));
    }
Ejemplo n.º 8
0
/* May return LWPOINT or LWMPOINT */
static LWGEOM*
lwgeom_extract_unique_endpoints(const LWGEOM* lwg)
{
#if POSTGIS_GEOS_VERSION < 33
	lwerror("The GEOS version this postgis binary "
	        "was compiled against (%d) doesn't support "
	        "'GEOSUnaryUnion' function (3.3.0+ required)",
	        POSTGIS_GEOS_VERSION);
	return NULL;
#else /* POSTGIS_GEOS_VERSION >= 33 */
	LWGEOM* ret;
	GEOSGeometry *gepu;
	LWMPOINT *epall = lwgeom_extract_endpoints(lwg);
	GEOSGeometry *gepall = LWGEOM2GEOS((LWGEOM*)epall);
	lwmpoint_free(epall);
	if ( ! gepall ) {
		lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	/* UnaryUnion to remove duplicates */
	/* TODO: do it all within pgis using indices */
	gepu = GEOSUnaryUnion(gepall);
	if ( ! gepu ) {
		GEOSGeom_destroy(gepall);
		lwerror("GEOSUnaryUnion: %s", lwgeom_geos_errmsg);
		return NULL;
	}
	GEOSGeom_destroy(gepall);

	ret = GEOS2LWGEOM(gepu, FLAGS_GET_Z(lwg->flags));
	GEOSGeom_destroy(gepu);
	if ( ! ret ) {
		lwerror("Error during GEOS2LWGEOM");
		return NULL;
	}

	return ret;
#endif /* POSTGIS_GEOS_VERSION >= 33 */
}
Ejemplo n.º 9
0
LWGEOM*
lwgeom_node(const LWGEOM* lwgeom_in)
{
#if POSTGIS_GEOS_VERSION < 33
	lwerror("The GEOS version this postgis binary "
	        "was compiled against (%d) doesn't support "
	        "'GEOSUnaryUnion' function (3.3.0+ required)",
	        POSTGIS_GEOS_VERSION);
	return NULL;
#else /* POSTGIS_GEOS_VERSION >= 33 */
	GEOSGeometry *g1, *gu, *gm;
	LWGEOM *ep, *lines;
	LWCOLLECTION *col, *tc;
	int pn, ln, np, nl;

	if ( lwgeom_dimension(lwgeom_in) != 1 ) {
		lwerror("Noding geometries of dimension != 1 is unsupported");
		return NULL;
	}

	initGEOS(lwgeom_geos_error, lwgeom_geos_error);
	g1 = LWGEOM2GEOS(lwgeom_in);
	if ( ! g1 ) {
		lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	ep = lwgeom_extract_unique_endpoints(lwgeom_in);
	if ( ! ep ) {
		GEOSGeom_destroy(g1);
		lwerror("Error extracting unique endpoints from input");
		return NULL;
	}

	/* Unary union input to fully node */
	gu = GEOSUnaryUnion(g1);
	GEOSGeom_destroy(g1);
	if ( ! gu ) {
		lwgeom_free(ep);
		lwerror("GEOSUnaryUnion: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	/* Linemerge (in case of overlaps) */
	gm = GEOSLineMerge(gu);
	GEOSGeom_destroy(gu);
	if ( ! gm ) {
		lwgeom_free(ep);
		lwerror("GEOSLineMerge: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	lines = GEOS2LWGEOM(gm, FLAGS_GET_Z(lwgeom_in->flags));
	GEOSGeom_destroy(gm);
	if ( ! lines ) {
		lwgeom_free(ep);
		lwerror("Error during GEOS2LWGEOM");
		return NULL;
	}

	/*
	 * Reintroduce endpoints from input, using split-line-by-point.
	 * Note that by now we can be sure that each point splits at 
	 * most _one_ segment as any point shared by multiple segments
	 * would already be a node. Also we can be sure that any of
	 * the segments endpoints won't split any other segment.
	 * We can use the above 2 assertions to early exit the loop.
	 */

	col = lwcollection_construct_empty(MULTILINETYPE, lwgeom_in->srid,
	                              FLAGS_GET_Z(lwgeom_in->flags),
	                              FLAGS_GET_M(lwgeom_in->flags));

	np = lwgeom_ngeoms(ep);
	for (pn=0; pn<np; ++pn) { /* for each point */

		const LWPOINT* p = (LWPOINT*)lwgeom_subgeom(ep, pn);

		nl = lwgeom_ngeoms(lines);
		for (ln=0; ln<nl; ++ln) { /* for each line */

			const LWLINE* l = (LWLINE*)lwgeom_subgeom(lines, ln);

			int s = lwline_split_by_point_to(l, p, (LWMLINE*)col);

			if ( ! s ) continue; /* not on this line */

			if ( s == 1 ) {
				/* found on this line, but not splitting it */
				break;
			}

			/* splits this line */

			/* replace this line with the two splits */
			if ( lwgeom_is_collection(lines) ) {
				tc = (LWCOLLECTION*)lines;
				lwcollection_reserve(tc, nl + 1);
				while (nl > ln+1) {
					tc->geoms[nl] = tc->geoms[nl-1];
					--nl;
				}
				lwgeom_free(tc->geoms[ln]);
				tc->geoms[ln]   = col->geoms[0];
				tc->geoms[ln+1] = col->geoms[1];
				tc->ngeoms++;
			} else {
				lwgeom_free(lines);
				/* transfer ownership rather than cloning */
				lines = (LWGEOM*)lwcollection_clone_deep(col);
				assert(col->ngeoms == 2);
				lwgeom_free(col->geoms[0]);
				lwgeom_free(col->geoms[1]);
			}

			/* reset the vector */
			assert(col->ngeoms == 2);
			col->ngeoms = 0;

			break;
		}

	}

	lwgeom_free(ep);
	lwcollection_free(col);

	lines->srid = lwgeom_in->srid;
	return (LWGEOM*)lines;
#endif /* POSTGIS_GEOS_VERSION >= 33 */
}