From: Sandro Santilli Date: Wed, 10 Jun 2015 17:19:57 +0000 (+0000) Subject: Add lwgeom_scale and ptarray_scale with support of all dimensions (#3062) X-Git-Tag: 2.2.0rc1~378 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f3d14ec8b364fd65d90762871d4198524f260778;p=postgis Add lwgeom_scale and ptarray_scale with support of all dimensions (#3062) Includes unit test. git-svn-id: http://svn.osgeo.org/postgis/trunk@13643 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/liblwgeom/cunit/cu_libgeom.c b/liblwgeom/cunit/cu_libgeom.c index f22943dcc..9e22f8b72 100644 --- a/liblwgeom/cunit/cu_libgeom.c +++ b/liblwgeom/cunit/cu_libgeom.c @@ -962,6 +962,26 @@ static void test_lwline_from_lwmpoint(void) lwmpoint_free(mpoint); } +/* + * Test lwgeom_scale + */ +static void test_lwgeom_scale(void) +{ + LWGEOM *geom; + POINT4D factor; + char *out_ewkt; + + geom = lwgeom_from_wkt("SRID=4326;GEOMETRYCOLLECTION(POINT(0 1 2 3),POLYGON((-1 -1 0 1,-1 2.5 0 1,2 2 0 1,2 -1 0 1,-1 -1 0 1),(0 0 1 2,0 1 1 2,1 1 1 2,1 0 2 3,0 0 1 2)),LINESTRING(0 0 0 0, 1 2 3 4))", LW_PARSER_CHECK_NONE); + factor.x = 2; factor.y = 3; factor.z = 4; factor.m = 5; + lwgeom_scale(geom, &factor); + out_ewkt = lwgeom_to_ewkt(geom); + ASSERT_STRING_EQUAL(out_ewkt, "SRID=4326;GEOMETRYCOLLECTION(POINT(0 3 8 15),POLYGON((-2 -3 0 5,-2 7.5 0 5,4 6 0 5,4 -3 0 5,-2 -3 0 5),(0 0 4 10,0 3 4 10,2 3 4 10,2 0 8 15,0 0 4 10)),LINESTRING(0 0 0 0,2 6 12 20))"); + + lwgeom_free(geom); + lwfree(out_ewkt); + +} + /* ** Used by test harness to register the tests in this file. */ @@ -989,4 +1009,5 @@ void libgeom_suite_setup(void) PG_ADD_TEST(suite, test_lwgeom_same); PG_ADD_TEST(suite, test_lwline_from_lwmpoint); PG_ADD_TEST(suite, test_lwgeom_as_curve); + PG_ADD_TEST(suite, test_lwgeom_scale); } diff --git a/liblwgeom/cunit/cu_ptarray.c b/liblwgeom/cunit/cu_ptarray.c index 6dbc15135..a8106a978 100644 --- a/liblwgeom/cunit/cu_ptarray.c +++ b/liblwgeom/cunit/cu_ptarray.c @@ -687,6 +687,45 @@ static void test_ptarrayarc_contains_point() lwline_free(lwline); } +static void test_ptarray_scale() +{ + LWLINE *line; + POINTARRAY *pa; + POINT4D factor; + const char *wkt; + char *wktout; + + wkt = "LINESTRING ZM (0 1 2 3,1 2 3 0,-2 -3 0 -1,-3 0 -1 -2)"; + line = lwgeom_as_lwline(lwgeom_from_text(wkt)); + pa = line->points; + factor.x = factor.y = factor.z = factor.m = 1; + ptarray_scale(pa, &factor); + wktout = lwgeom_to_text(lwline_as_lwgeom(line)); + ASSERT_STRING_EQUAL(wktout, wkt); + factor.x = 2; + wkt = "LINESTRING ZM (0 1 2 3,2 2 3 0,-4 -3 0 -1,-6 0 -1 -2)"; + ptarray_scale(pa, &factor); + wktout = lwgeom_to_text(lwline_as_lwgeom(line)); + ASSERT_STRING_EQUAL(wktout, wkt); + factor.x = 1; factor.y = 3; + wkt = "LINESTRING ZM (0 3 2 3,2 6 3 0,-4 -9 0 -1,-6 0 -1 -2)"; + ptarray_scale(pa, &factor); + wktout = lwgeom_to_text(lwline_as_lwgeom(line)); + ASSERT_STRING_EQUAL(wktout, wkt); + factor.x = 1; factor.y = 1; factor.z = -2; + wkt = "LINESTRING ZM (0 3 -4 3,2 6 -6 0,-4 -9 -0 -1,-6 0 2 -2)"; + ptarray_scale(pa, &factor); + wktout = lwgeom_to_text(lwline_as_lwgeom(line)); + ASSERT_STRING_EQUAL(wktout, wkt); + factor.x = 1; factor.y = 1; factor.z = 1; factor.m = 2; + wkt = "LINESTRING ZM (0 3 -4 6,2 6 -6 0,-4 -9 -0 -2,-6 0 2 -4)"; + ptarray_scale(pa, &factor); + wktout = lwgeom_to_text(lwline_as_lwgeom(line)); + ASSERT_STRING_EQUAL(wktout, wkt); + + lwline_free(line); +} + /* ** Used by the test harness to register the tests in this file. @@ -704,4 +743,5 @@ void ptarray_suite_setup(void) PG_ADD_TEST(suite, test_ptarray_insert_point); PG_ADD_TEST(suite, test_ptarray_contains_point); PG_ADD_TEST(suite, test_ptarrayarc_contains_point); + PG_ADD_TEST(suite, test_ptarray_scale); } diff --git a/liblwgeom/cunit/cu_tester.h b/liblwgeom/cunit/cu_tester.h index 0bf87e4db..b41de4014 100644 --- a/liblwgeom/cunit/cu_tester.h +++ b/liblwgeom/cunit/cu_tester.h @@ -35,4 +35,9 @@ typedef void (*PG_SuiteSetup)(void); CU_ASSERT_EQUAL(o,e); \ } while (0); +#define ASSERT_STRING_EQUAL(o,e) do { \ + if ( strcmp(o,e) != 0 ) \ + fprintf(stderr, "[%s:%d]\n Expected: %s\n Obtained: %s\n", __FILE__, __LINE__, (e), (o)); \ + CU_ASSERT_STRING_EQUAL(o,e); \ +} while (0); diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in index 0bd42cb9d..e2abe8b5d 100644 --- a/liblwgeom/liblwgeom.h.in +++ b/liblwgeom/liblwgeom.h.in @@ -1184,6 +1184,7 @@ extern double lwgeom_length_2d(const LWGEOM *geom); extern double lwgeom_perimeter(const LWGEOM *geom); extern double lwgeom_perimeter_2d(const LWGEOM *geom); extern void lwgeom_affine(LWGEOM *geom, const AFFINE *affine); +extern void lwgeom_scale(LWGEOM *geom, const POINT4D *factors); extern int lwgeom_dimension(const LWGEOM *geom); extern LWPOINT* lwline_get_lwpoint(LWLINE *line, int where); diff --git a/liblwgeom/liblwgeom_internal.h b/liblwgeom/liblwgeom_internal.h index 2a5bd5fc1..ed91bbe04 100644 --- a/liblwgeom/liblwgeom_internal.h +++ b/liblwgeom/liblwgeom_internal.h @@ -299,6 +299,11 @@ LWPOLY *lwcurvepoly_segmentize(const LWCURVEPOLY *curvepoly, uint32_t perQuad); */ void ptarray_affine(POINTARRAY *pa, const AFFINE *affine); +/* +* Scale +*/ +void ptarray_scale(POINTARRAY *pa, const POINT4D *factor); + /* * PointArray */ diff --git a/liblwgeom/lwgeom.c b/liblwgeom/lwgeom.c index 4bbffdfcb..c031a4786 100644 --- a/liblwgeom/lwgeom.c +++ b/liblwgeom/lwgeom.c @@ -1732,6 +1732,56 @@ lwgeom_affine(LWGEOM *geom, const AFFINE *affine) } +void +lwgeom_scale(LWGEOM *geom, const POINT4D *factor) +{ + int type = geom->type; + int i; + + switch(type) + { + /* Take advantage of fact tht pt/ln/circ/tri have same memory structure */ + case POINTTYPE: + case LINETYPE: + case CIRCSTRINGTYPE: + case TRIANGLETYPE: + { + LWLINE *l = (LWLINE*)geom; + ptarray_scale(l->points, factor); + break; + } + case POLYGONTYPE: + { + LWPOLY *p = (LWPOLY*)geom; + for( i = 0; i < p->nrings; i++ ) + ptarray_scale(p->rings[i], factor); + break; + } + case CURVEPOLYTYPE: + { + LWCURVEPOLY *c = (LWCURVEPOLY*)geom; + for( i = 0; i < c->nrings; i++ ) + lwgeom_scale(c->rings[i], factor); + break; + } + default: + { + if( lwgeom_is_collection(geom) ) + { + LWCOLLECTION *c = (LWCOLLECTION*)geom; + for( i = 0; i < c->ngeoms; i++ ) + { + lwgeom_scale(c->geoms[i], factor); + } + } + else + { + lwerror("lwgeom_scale: unable to handle type '%s'", lwtype_name(type)); + } + } + } +} + LWGEOM* lwgeom_construct_empty(uint8_t type, int srid, char hasz, char hasm) { diff --git a/liblwgeom/ptarray.c b/liblwgeom/ptarray.c index 6e7a6c2b5..3a21ac442 100644 --- a/liblwgeom/ptarray.c +++ b/liblwgeom/ptarray.c @@ -1763,6 +1763,31 @@ ptarray_affine(POINTARRAY *pa, const AFFINE *a) } +/** + * Scale a pointarray. + */ +void +ptarray_scale(POINTARRAY *pa, const POINT4D *fact) +{ + int i; + POINT4D p4d; + + LWDEBUG(3, "ptarray_scale start"); + + for (i=0; inpoints; ++i) + { + getPoint4d_p(pa, i, &p4d); + p4d.x *= fact->x; + p4d.y *= fact->y; + p4d.z *= fact->z; + p4d.m *= fact->m; + ptarray_set_point4d(pa, i, &p4d); + } + + LWDEBUG(3, "ptarray_scale end"); + +} + int ptarray_startpoint(const POINTARRAY* pa, POINT4D* pt) {