]> granicus.if.org Git - postgis/commitdiff
Add lwgeom_scale and ptarray_scale with support of all dimensions (#3062)
authorSandro Santilli <strk@keybit.net>
Wed, 10 Jun 2015 17:19:57 +0000 (17:19 +0000)
committerSandro Santilli <strk@keybit.net>
Wed, 10 Jun 2015 17:19:57 +0000 (17:19 +0000)
Includes unit test.

git-svn-id: http://svn.osgeo.org/postgis/trunk@13643 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/cunit/cu_libgeom.c
liblwgeom/cunit/cu_ptarray.c
liblwgeom/cunit/cu_tester.h
liblwgeom/liblwgeom.h.in
liblwgeom/liblwgeom_internal.h
liblwgeom/lwgeom.c
liblwgeom/ptarray.c

index f22943dcc2ca4444f95d49464870b80988090483..9e22f8b7257f9611ca12a3ad34181399b10ed4de 100644 (file)
@@ -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);
 }
index 6dbc15135ff274b7d22d1bc81c189f98bae2b30c..a8106a97858d4e851998b98cad2549e8b75fe512 100644 (file)
@@ -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);
 }
index 0bf87e4db53b7751f1c3abe0a261bad992df77da..b41de40143532362d9f7ce85b17f9b0324749637 100644 (file)
@@ -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);
 
index 0bd42cb9d8e980bac2e0ace9c1cb373fa0b4f328..e2abe8b5d3bedafbead14b52568018e28d20a0d8 100644 (file)
@@ -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);
index 2a5bd5fc128e5095ca3df74fe139e906c2f06f62..ed91bbe04885f5f558d675ec5ca82dc8b4ca97c3 100644 (file)
@@ -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
 */
index 4bbffdfcba953179910ddc868ea0f2ce3afc83f3..c031a4786a97fdcb3bdcff9585df3a2082582080 100644 (file)
@@ -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)
 {
index 6e7a6c2b505664f10967af0805425b26c524f296..3a21ac44203cef9c14f33fba6a1cd529aa8b1964 100644 (file)
@@ -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; i<pa->npoints; ++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)
 {