* New Features *
+ - #2430, ST_ForceCurve
+
* Enhancements *
- Added missing variants of ST_TPI(), ST_TRI() and ST_Roughness()
}
+/*
+ * Test lwgeom_force_curve
+ */
+static void test_lwgeom_as_curve(void)
+{
+ LWGEOM *geom;
+ LWGEOM *geom2;
+ char *in_ewkt, *out_ewkt;
+
+ geom = lwgeom_from_wkt("LINESTRING(0 0, 10 0)", LW_PARSER_CHECK_NONE);
+ geom2 = lwgeom_as_curve(geom);
+ in_ewkt = "COMPOUNDCURVE((0 0,10 0))";
+ out_ewkt = lwgeom_to_ewkt(geom2);
+ if (strcmp(in_ewkt, out_ewkt))
+ fprintf(stderr, "\nExp: %s\nObt: %s\n", in_ewkt, out_ewkt);
+ CU_ASSERT_STRING_EQUAL(in_ewkt, out_ewkt);
+ lwfree(out_ewkt);
+ lwgeom_free(geom);
+ lwgeom_free(geom2);
+
+ geom = lwgeom_from_wkt("MULTILINESTRING((0 0, 10 0))", LW_PARSER_CHECK_NONE);
+ geom2 = lwgeom_as_curve(geom);
+ in_ewkt = "MULTICURVE((0 0,10 0))";
+ out_ewkt = lwgeom_to_ewkt(geom2);
+ if (strcmp(in_ewkt, out_ewkt))
+ fprintf(stderr, "\nExp: %s\nObt: %s\n", in_ewkt, out_ewkt);
+ CU_ASSERT_STRING_EQUAL(in_ewkt, out_ewkt);
+ lwfree(out_ewkt);
+ lwgeom_free(geom);
+ lwgeom_free(geom2);
+
+ geom = lwgeom_from_wkt("POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))", LW_PARSER_CHECK_NONE);
+ geom2 = lwgeom_as_curve(geom);
+ in_ewkt = "CURVEPOLYGON((0 0,10 0,10 10,0 10,0 0))";
+ out_ewkt = lwgeom_to_ewkt(geom2);
+ if (strcmp(in_ewkt, out_ewkt))
+ fprintf(stderr, "\nExp: %s\nObt: %s\n", in_ewkt, out_ewkt);
+ CU_ASSERT_STRING_EQUAL(in_ewkt, out_ewkt);
+ lwfree(out_ewkt);
+ lwgeom_free(geom);
+ lwgeom_free(geom2);
+
+ geom = lwgeom_from_wkt("MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0)))", LW_PARSER_CHECK_NONE);
+ geom2 = lwgeom_as_curve(geom);
+ in_ewkt = "MULTISURFACE(((0 0,10 0,10 10,0 10,0 0)))";
+ out_ewkt = lwgeom_to_ewkt(geom2);
+ if (strcmp(in_ewkt, out_ewkt))
+ fprintf(stderr, "\nExp: %s\nObt: %s\n", in_ewkt, out_ewkt);
+ CU_ASSERT_STRING_EQUAL(in_ewkt, out_ewkt);
+ lwfree(out_ewkt);
+ lwgeom_free(geom);
+ lwgeom_free(geom2);
+
+}
+
/*
** Used by test harness to register the tests in this file.
*/
PG_TEST(test_lwgeom_calculate_gbox),
PG_TEST(test_lwgeom_is_empty),
PG_TEST(test_lwgeom_same),
+ PG_TEST(test_lwgeom_as_curve),
CU_TEST_INFO_NULL
};
CU_SuiteInfo libgeom_suite = {"libgeom", NULL, NULL, libgeom_tests};
extern LWTRIANGLE *lwgeom_as_lwtriangle(const LWGEOM *lwgeom);
extern LWTIN *lwgeom_as_lwtin(const LWGEOM *lwgeom);
extern LWGEOM *lwgeom_as_multi(const LWGEOM *lwgeom);
+extern LWGEOM *lwgeom_as_curve(const LWGEOM *lwgeom);
/* Casts LW*->LWGEOM (always cast) */
extern LWGEOM *lwtin_as_lwgeom(const LWTIN *obj);
*/
extern int lwcompound_add_lwgeom(LWCOMPOUND *comp, LWGEOM *geom);
+/**
+* Construct an equivalent compound curve from a linestring.
+* Compound curves can have linear components, so this works fine
+*/
+extern LWCOMPOUND* lwcompound_construct_from_lwline(const LWLINE *lwpoly);
+
/**
* Construct an equivalent curve polygon from a polygon. Curve polygons
* can have linear rings as their rings, so this works fine (in theory?)
/* Inside */
return LW_INSIDE;
}
+
+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;
+}
/**
** Look-up for the correct MULTI* type promotion for singleton types.
*/
-static uint8_t MULTITYPE[17] =
+static uint8_t MULTITYPE[NUMTYPES] =
{
0,
MULTIPOINTTYPE, /* 1 */
POLYHEDRALSURFACETYPE, /* 11 */
0, 0,
TINTYPE, /* 14 */
- 0,0
+ 0
};
/**
return ogeom;
}
+/**
+* Create a new LWGEOM of the appropriate CURVE* type.
+*/
+LWGEOM *
+lwgeom_as_curve(const LWGEOM *lwgeom)
+{
+ LWGEOM *ogeom;
+ int type = lwgeom->type;
+/*
+ int hasz = FLAGS_GET_Z(lwgeom->flags);
+ int hasm = FLAGS_GET_M(lwgeom->flags);
+ int srid = lwgeom->srid;
+*/
+
+ switch(type)
+ {
+ case LINETYPE:
+ /* turn to COMPOUNDCURVE */
+ ogeom = (LWGEOM*)lwcompound_construct_from_lwline((LWLINE*)lwgeom);
+ break;
+ case POLYGONTYPE:
+ ogeom = (LWGEOM*)lwcurvepoly_construct_from_lwpoly(lwgeom_as_lwpoly(lwgeom));
+ break;
+ case MULTILINETYPE:
+ /* turn to MULTICURVE */
+ ogeom = lwgeom_clone(lwgeom);
+ ogeom->type = MULTICURVETYPE;
+ break;
+ case MULTIPOLYGONTYPE:
+ /* turn to MULTISURFACE */
+ ogeom = lwgeom_clone(lwgeom);
+ ogeom->type = MULTISURFACETYPE;
+ break;
+ case COLLECTIONTYPE:
+ default:
+ ogeom = lwgeom_clone(lwgeom);
+ break;
+ }
+
+ /* TODO: copy bbox from input geom ? */
+
+ return ogeom;
+}
+
/**
* Free the containing LWGEOM and the associated BOX. Leave the underlying
Datum LWGEOM_force_4d(PG_FUNCTION_ARGS);
Datum LWGEOM_force_collection(PG_FUNCTION_ARGS);
Datum LWGEOM_force_multi(PG_FUNCTION_ARGS);
+Datum LWGEOM_force_curve(PG_FUNCTION_ARGS);
Datum LWGEOMFromWKB(PG_FUNCTION_ARGS);
Datum WKBFromLWGEOM(PG_FUNCTION_ARGS);
PG_RETURN_POINTER(result);
}
+/** transform input geometry to a curved type */
+PG_FUNCTION_INFO_V1(LWGEOM_force_curve);
+Datum LWGEOM_force_curve(PG_FUNCTION_ARGS)
+{
+ GSERIALIZED *geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+ GSERIALIZED *result;
+ LWGEOM *lwgeom;
+ LWGEOM *ogeom;
+
+ POSTGIS_DEBUG(2, "LWGEOM_force_curve called");
+
+ /* TODO: early out if input is already a curve */
+
+ lwgeom = lwgeom_from_gserialized(geom);
+ ogeom = lwgeom_as_curve(lwgeom);
+
+ result = geometry_serialize(ogeom);
+
+ PG_FREE_IF_COPY(geom, 0);
+
+ PG_RETURN_POINTER(result);
+}
+
/** transform input geometry to a SFS 1.1 geometry type compliant */
PG_FUNCTION_INFO_V1(LWGEOM_force_sfs);
Datum LWGEOM_force_sfs(PG_FUNCTION_ARGS)
AS 'MODULE_PATHNAME', 'LWGEOM_force_multi'
LANGUAGE 'c' IMMUTABLE STRICT;
+-- Availability: 2.2.0
+CREATE OR REPLACE FUNCTION ST_ForceCurve(geometry)
+ RETURNS geometry
+ AS 'MODULE_PATHNAME', 'LWGEOM_force_curve'
+ LANGUAGE 'c' IMMUTABLE STRICT;
+
-- Availability: 2.1.0
CREATE OR REPLACE FUNCTION ST_ForceSFS(geometry)
RETURNS geometry
summary \
affine \
empty \
+ forcecurve \
measures \
legacy \
long_xact \
--- /dev/null
+SELECT '1', ST_AsText(ST_ForceCurve('POINT(0 0)'));
+SELECT '2', ST_AsText(ST_ForceCurve('MULTIPOINT((0 0))'));
+SELECT '3', ST_AsText(ST_ForceCurve('LINESTRING(0 0, 10 0)'));
+SELECT '4', ST_AsText(ST_ForceCurve('MULTILINESTRING((0 0, 10 0),(30 0, 30 2))'));
+SELECT '5', ST_AsText(ST_ForceCurve('POLYGON((0 0,10 0,10 10,0 10,0 0))'));
+SELECT '6', ST_AsText(ST_ForceCurve('MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)))'));
+SELECT '7', ST_AsText(ST_ForceCurve('GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0))))'));
+SELECT '8', ST_AsText(ST_ForceCurve('CIRCULARSTRING(0 0,10 1,20 0)'));
+SELECT '9', ST_AsText(ST_ForceCurve('COMPOUNDCURVE(CIRCULARSTRING(0 0,10 1,20 0))'));
+SELECT '10', ST_AsText(ST_ForceCurve('MULTICURVE(COMPOUNDCURVE(CIRCULARSTRING(0 0,10 1,20 0)))'));
+SELECT '11', ST_AsText(ST_ForceCurve('CURVEPOLYGON(COMPOUNDCURVE(CIRCULARSTRING(0 0,10 1,20 0),(20 0,0 0)))'));
+SELECT '12', ST_AsText(ST_ForceCurve('MULTISURFACE(CURVEPOLYGON(COMPOUNDCURVE(CIRCULARSTRING(0 0,10 1,20 0),(20 0,0 0))))'));
--- /dev/null
+1|POINT(0 0)
+2|MULTIPOINT(0 0)
+3|COMPOUNDCURVE((0 0,10 0))
+4|MULTICURVE((0 0,10 0),(30 0,30 2))
+5|CURVEPOLYGON((0 0,10 0,10 10,0 10,0 0))
+6|MULTISURFACE(((0 0,10 0,10 10,0 10,0 0)))
+7|GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0))))
+8|CIRCULARSTRING(0 0,10 1,20 0)
+9|COMPOUNDCURVE(CIRCULARSTRING(0 0,10 1,20 0))
+10|MULTICURVE(COMPOUNDCURVE(CIRCULARSTRING(0 0,10 1,20 0)))
+11|CURVEPOLYGON(COMPOUNDCURVE(CIRCULARSTRING(0 0,10 1,20 0),(20 0,0 0)))
+12|MULTISURFACE(CURVEPOLYGON(COMPOUNDCURVE(CIRCULARSTRING(0 0,10 1,20 0),(20 0,0 0))))