return poly;
}
+/******************************************************************************
+* rt_raster_get_envelope_geom()
+******************************************************************************/
+
+/**
+ * Get raster's envelope as a geometry
+ *
+ * @param raster : the raster to get info from
+ * @param **env : pointer to envelope
+ *
+ * @return ES_NONE if success, ES_ERROR if error
+ */
+rt_errorstate
+rt_raster_get_envelope_geom(rt_raster raster, LWGEOM **env) {
+ double gt[6] = {0.0};
+ int srid = SRID_UNKNOWN;
+
+ POINTARRAY *pts = NULL;
+ POINT4D p4d;
+
+ assert(env != NULL);
+ *env = NULL;
+
+ /* raster is NULL, envelope is NULL */
+ if (raster == NULL)
+ return ES_NONE;
+
+ /* raster metadata */
+ srid = rt_raster_get_srid(raster);
+ rt_raster_get_geotransform_matrix(raster, gt);
+
+ RASTER_DEBUGF(
+ 3,
+ "rt_raster_get_envelope: raster is %dx%d",
+ raster->width,
+ raster->height
+ );
+
+ /* return point or line since at least one of the two dimensions is 0 */
+ if ((!raster->width) || (!raster->height)) {
+ p4d.x = gt[0];
+ p4d.y = gt[3];
+
+ /* return point */
+ if (!raster->width && !raster->height) {
+ LWPOINT *point = lwpoint_make2d(srid, p4d.x, p4d.y);
+ *env = lwpoint_as_lwgeom(point);
+ }
+ /* return linestring */
+ else {
+ LWLINE *line = NULL;
+ pts = ptarray_construct_empty(0, 0, 2);
+
+ /* first point of line */
+ ptarray_append_point(pts, &p4d, LW_TRUE);
+
+ /* second point of line */
+ if (rt_raster_cell_to_geopoint(
+ raster,
+ rt_raster_get_width(raster), rt_raster_get_height(raster),
+ &p4d.x, &p4d.y,
+ gt
+ ) != ES_NONE) {
+ rterror("rt_raster_get_envelope: Could not get second point for linestring");
+ return ES_ERROR;
+ }
+ ptarray_append_point(pts, &p4d, LW_TRUE);
+ line = lwline_construct(srid, NULL, pts);
+
+ *env = lwline_as_lwgeom(line);
+ }
+
+ return ES_NONE;
+ }
+ else {
+ rt_envelope rtenv;
+ int err = ES_NONE;
+ POINTARRAY **rings = NULL;
+ LWPOLY* poly = NULL;
+
+ /* only one ring */
+ rings = (POINTARRAY **) rtalloc(sizeof (POINTARRAY*));
+ if (!rings) {
+ rterror("rt_raster_get_envelope_geom: Could not allocate memory for polygon ring");
+ return ES_ERROR;
+ }
+ rings[0] = ptarray_construct(0, 0, 5);
+ if (!rings[0]) {
+ rterror("rt_raster_get_envelope_geom: Could not construct point array");
+ return ES_ERROR;
+ }
+ pts = rings[0];
+
+ err = rt_raster_get_envelope(raster, &rtenv);
+ if (err != ES_NONE) {
+ rterror("rt_raster_get_envelope_geom: Could not get raster envelope");
+ return err;
+ }
+
+ /* build ring */
+
+ /* minx, maxy */
+ p4d.x = rtenv.MinX;
+ p4d.y = rtenv.MaxY;
+ ptarray_set_point4d(pts, 0, &p4d);
+ ptarray_set_point4d(pts, 4, &p4d);
+
+ /* maxx, maxy */
+ p4d.x = rtenv.MaxX;
+ p4d.y = rtenv.MaxY;
+ ptarray_set_point4d(pts, 1, &p4d);
+
+ /* maxx, miny */
+ p4d.x = rtenv.MaxX;
+ p4d.y = rtenv.MinY;
+ ptarray_set_point4d(pts, 2, &p4d);
+
+ /* minx, miny */
+ p4d.x = rtenv.MinX;
+ p4d.y = rtenv.MinY;
+ ptarray_set_point4d(pts, 3, &p4d);
+
+ poly = lwpoly_construct(srid, 0, 1, rings);
+ *env = lwpoly_as_lwgeom(poly);
+ }
+
+ return ES_NONE;
+}
+
/******************************************************************************
* rt_raster_get_convex_hull()
******************************************************************************/
#include "rtpostgis.h"
#include "rtpg_internal.h"
+Datum RASTER_envelope(PG_FUNCTION_ARGS);
Datum RASTER_convex_hull(PG_FUNCTION_ARGS);
Datum RASTER_dumpAsPolygons(PG_FUNCTION_ARGS);
/* rasterize a geometry */
Datum RASTER_asRaster(PG_FUNCTION_ARGS);
+/* ---------------------------------------------------------------- */
+/* Raster envelope */
+/* ---------------------------------------------------------------- */
+PG_FUNCTION_INFO_V1(RASTER_envelope);
+Datum RASTER_envelope(PG_FUNCTION_ARGS)
+{
+ rt_pgraster *pgraster;
+ rt_raster raster;
+ LWGEOM *geom = NULL;
+ GSERIALIZED* gser = NULL;
+ size_t gser_size;
+ int err = ES_NONE;
+
+ bool minhull = FALSE;
+
+ if (PG_ARGISNULL(0))
+ PG_RETURN_NULL();
+
+ pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(
+ PG_GETARG_DATUM(0),
+ 0,
+ sizeof(struct rt_raster_serialized_t)
+ );
+ raster = rt_raster_deserialize(pgraster, TRUE);
+
+ if (!raster) {
+ PG_FREE_IF_COPY(pgraster, 0);
+ elog(ERROR, "RASTER_envelope: Could not deserialize raster");
+ PG_RETURN_NULL();
+ }
+
+ err = rt_raster_get_envelope_geom(raster, &geom);
+
+ rt_raster_destroy(raster);
+ PG_FREE_IF_COPY(pgraster, 0);
+
+ if (err != ES_NONE) {
+ elog(ERROR, "RASTER_envelope: Could not get raster's envelope");
+ PG_RETURN_NULL();
+ }
+ else if (geom == NULL) {
+ elog(NOTICE, "Raster's envelope is NULL");
+ PG_RETURN_NULL();
+ }
+
+ gser = gserialized_from_lwgeom(geom, 0, &gser_size);
+ lwgeom_free(geom);
+
+ SET_VARSIZE(gser, gser_size);
+ PG_RETURN_POINTER(gser);
+}
+
/**
* Return the convex hull of this raster
*/
+/* ---------------------------------------------------------------- */
+/* Raster convex hull */
+/* ---------------------------------------------------------------- */
PG_FUNCTION_INFO_V1(RASTER_convex_hull);
Datum RASTER_convex_hull(PG_FUNCTION_ARGS)
{
#include "CUnit/Basic.h"
#include "cu_tester.h"
+static void test_raster_envelope() {
+ rt_raster raster = NULL;
+ rt_envelope rtenv;
+
+ /* width = 0, height = 0 */
+ raster = rt_raster_new(0, 0);
+ CU_ASSERT(raster != NULL);
+
+ rt_raster_set_offsets(raster, 0.5, 0.5);
+ rt_raster_set_scale(raster, 1, -1);
+
+ CU_ASSERT_EQUAL(rt_raster_get_envelope(raster, &rtenv), ES_NONE);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MinX, 0.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MaxX, 0.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MinY, 0.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MaxY, 0.5, DBL_EPSILON);
+ cu_free_raster(raster);
+
+ /* width = 0 */
+ raster = rt_raster_new(0, 5);
+ CU_ASSERT(raster != NULL);
+
+ rt_raster_set_offsets(raster, 0.5, 0.5);
+ rt_raster_set_scale(raster, 1, -1);
+
+ CU_ASSERT_EQUAL(rt_raster_get_envelope(raster, &rtenv), ES_NONE);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MinX, 0.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MaxX, 0.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MinY, -4.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MaxY, 0.5, DBL_EPSILON);
+ cu_free_raster(raster);
+
+ /* height = 0 */
+ raster = rt_raster_new(5, 0);
+ CU_ASSERT(raster != NULL);
+
+ rt_raster_set_offsets(raster, 0.5, 0.5);
+ rt_raster_set_scale(raster, 1, -1);
+
+ CU_ASSERT_EQUAL(rt_raster_get_envelope(raster, &rtenv), ES_NONE);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MinX, 0.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MaxX, 5.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MinY, 0.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MaxY, 0.5, DBL_EPSILON);
+ cu_free_raster(raster);
+
+ /* normal raster */
+ raster = rt_raster_new(5, 5);
+ CU_ASSERT(raster != NULL);
+
+ rt_raster_set_offsets(raster, 0.5, 0.5);
+ rt_raster_set_scale(raster, 1, -1);
+
+ CU_ASSERT_EQUAL(rt_raster_get_envelope(raster, &rtenv), ES_NONE);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MinX, 0.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MaxX, 5.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MinY, -4.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(rtenv.MaxY, 0.5, DBL_EPSILON);
+ cu_free_raster(raster);
+}
+
+static void test_raster_envelope_geom() {
+ rt_raster raster = NULL;
+ LWGEOM *env = NULL;
+ LWPOLY *poly = NULL;
+ POINTARRAY *ring = NULL;
+ POINT4D pt;
+
+ /* NULL raster */
+ CU_ASSERT_EQUAL(rt_raster_get_envelope_geom(NULL, &env), ES_NONE);
+ CU_ASSERT(env == NULL);
+
+ /* width = 0, height = 0 */
+ raster = rt_raster_new(0, 0);
+ CU_ASSERT(raster != NULL);
+
+ CU_ASSERT_EQUAL(rt_raster_get_envelope_geom(raster, &env), ES_NONE);
+ CU_ASSERT_EQUAL(env->type, POINTTYPE);
+ lwgeom_free(env);
+ cu_free_raster(raster);
+
+ /* width = 0 */
+ raster = rt_raster_new(0, 256);
+ CU_ASSERT(raster != NULL);
+
+ CU_ASSERT_EQUAL(rt_raster_get_envelope_geom(raster, &env), ES_NONE);
+ CU_ASSERT_EQUAL(env->type, LINETYPE);
+ lwgeom_free(env);
+ cu_free_raster(raster);
+
+ /* height = 0 */
+ raster = rt_raster_new(256, 0);
+ CU_ASSERT(raster != NULL);
+
+ CU_ASSERT_EQUAL(rt_raster_get_envelope_geom(raster, &env), ES_NONE);
+ CU_ASSERT_EQUAL(env->type, LINETYPE);
+ lwgeom_free(env);
+ cu_free_raster(raster);
+
+ /* normal raster */
+ raster = rt_raster_new(5, 5);
+ CU_ASSERT(raster != NULL);
+
+ rt_raster_set_offsets(raster, 0.5, 0.5);
+ rt_raster_set_scale(raster, 1, -1);
+
+ CU_ASSERT_EQUAL(rt_raster_get_envelope_geom(raster, &env), ES_NONE);
+ poly = lwgeom_as_lwpoly(env);
+ CU_ASSERT_EQUAL(poly->srid, rt_raster_get_srid(raster));
+ CU_ASSERT_EQUAL(poly->nrings, 1);
+
+ ring = poly->rings[0];
+ CU_ASSERT(ring != NULL);
+ CU_ASSERT_EQUAL(ring->npoints, 5);
+
+ getPoint4d_p(ring, 0, &pt);
+ CU_ASSERT_DOUBLE_EQUAL(pt.x, 0.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(pt.y, 0.5, DBL_EPSILON);
+
+ getPoint4d_p(ring, 1, &pt);
+ CU_ASSERT_DOUBLE_EQUAL(pt.x, 5.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(pt.y, 0.5, DBL_EPSILON);
+
+ getPoint4d_p(ring, 2, &pt);
+ CU_ASSERT_DOUBLE_EQUAL(pt.x, 5.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(pt.y, -4.5, DBL_EPSILON);
+
+ getPoint4d_p(ring, 3, &pt);
+ CU_ASSERT_DOUBLE_EQUAL(pt.x, 0.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(pt.y, -4.5, DBL_EPSILON);
+
+ getPoint4d_p(ring, 4, &pt);
+ CU_ASSERT_DOUBLE_EQUAL(pt.x, 0.5, DBL_EPSILON);
+ CU_ASSERT_DOUBLE_EQUAL(pt.y, 0.5, DBL_EPSILON);
+
+ lwgeom_free(env);
+ cu_free_raster(raster);
+}
+
static void test_raster_convex_hull() {
rt_raster raster = NULL;
LWGEOM *hull = NULL;
/* register tests */
CU_TestInfo raster_geometry_tests[] = {
- /* TODO: rt_raster_envelope()
PG_TEST(test_raster_envelope),
- */
+ PG_TEST(test_raster_envelope_geom),
PG_TEST(test_raster_convex_hull),
PG_TEST(test_raster_surface),
PG_TEST(test_raster_perimeter),