PostGIS  3.7.0dev-r@@SVN_REVISION@@
liblwgeom/cunit/cu_misc.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  * Copyright 2008 Paul Ramsey
6  *
7  * This is free software; you can redistribute and/or modify it under
8  * the terms of the GNU General Public Licence. See the COPYING file.
9  *
10  **********************************************************************/
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include "CUnit/Basic.h"
16 
17 #include "liblwgeom_internal.h"
18 #include "optionlist.h"
19 #include "stringlist.h"
20 #include "cu_tester.h"
21 
22 
23 static void test_misc_simplify(void)
24 {
25  LWGEOM *geom;
26  LWGEOM *geom2d;
27  char *wkt_out;
28 
29  geom = lwgeom_from_wkt("LINESTRING(0 0,0 10,0 51,50 20,30 20,7 32)", LW_PARSER_CHECK_NONE);
30  geom2d = lwgeom_simplify(geom, 2, LW_FALSE);
31  wkt_out = lwgeom_to_ewkt(geom2d);
32  ASSERT_STRING_EQUAL("LINESTRING(0 0,0 51,50 20,30 20,7 32)",wkt_out);
33  lwgeom_free(geom);
34  lwgeom_free(geom2d);
35  lwfree(wkt_out);
36 
37  geom = lwgeom_from_wkt("MULTILINESTRING((0 0,0 10,0 51,50 20,30 20,7 32))", LW_PARSER_CHECK_NONE);
38  geom2d = lwgeom_simplify(geom, 2, LW_FALSE);
39  wkt_out = lwgeom_to_ewkt(geom2d);
40  ASSERT_STRING_EQUAL("MULTILINESTRING((0 0,0 51,50 20,30 20,7 32))",wkt_out);
41  lwgeom_free(geom);
42  lwgeom_free(geom2d);
43  lwfree(wkt_out);
44 
45  geom = lwgeom_from_wkt("POLYGON((0 0,1 1,1 3,0 4,-2 3,-1 1,0 0))", LW_PARSER_CHECK_NONE);
46  geom2d = lwgeom_simplify(geom, 1, LW_FALSE);
47  wkt_out = lwgeom_to_ewkt(geom2d);
48  ASSERT_STRING_EQUAL("POLYGON((0 0,0 4,-2 3,0 0))", wkt_out);
49  lwgeom_free(geom);
50  lwgeom_free(geom2d);
51  lwfree(wkt_out);
52 }
53 
54 static void test_misc_startpoint(void)
55 {
56  LWGEOM *geom;
57  POINT4D p = {0};
58 
59  geom = lwgeom_from_wkt("POINT(1 2)", LW_PARSER_CHECK_NONE);
60  CU_ASSERT(lwgeom_startpoint(geom, &p) == LW_SUCCESS);
61  CU_ASSERT_EQUAL(p.x, 1);
62  CU_ASSERT_EQUAL(p.y, 2);
63  lwgeom_free(geom);
64 
65  geom = lwgeom_from_wkt("LINESTRING(10 20, 30 40)", LW_PARSER_CHECK_NONE);
66  CU_ASSERT(lwgeom_startpoint(geom, &p) == LW_SUCCESS);
67  CU_ASSERT_EQUAL(p.x, 10);
68  CU_ASSERT_EQUAL(p.y, 20);
69  lwgeom_free(geom);
70 
71  geom = lwgeom_from_wkt("POLYGON((1 2, 3 4, 5 6, 1 2))", LW_PARSER_CHECK_NONE);
72  CU_ASSERT(lwgeom_startpoint(geom, &p) == LW_SUCCESS);
73  CU_ASSERT_EQUAL(p.x, 1);
74  CU_ASSERT_EQUAL(p.y, 2);
75  lwgeom_free(geom);
76 
77  geom = lwgeom_from_wkt("GEOMETRYCOLLECTION(LINESTRING(100 200, 300 400), POINT(10 20))", LW_PARSER_CHECK_NONE);
78  CU_ASSERT(lwgeom_startpoint(geom, &p) == LW_SUCCESS);
79  CU_ASSERT_EQUAL(p.x, 100);
80  CU_ASSERT_EQUAL(p.y, 200);
81  lwgeom_free(geom);
82 }
83 
84 static void test_misc_count_vertices(void)
85 {
86  LWGEOM *geom;
87  int count;
88 
89  geom = lwgeom_from_wkt("GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,1 1),POLYGON((0 0,0 1,1 0,0 0)),CIRCULARSTRING(0 0,0 1,1 1),CURVEPOLYGON(CIRCULARSTRING(0 0,0 1,1 1)))", LW_PARSER_CHECK_NONE);
91  CU_ASSERT_EQUAL(count,13);
92  lwgeom_free(geom);
93 
94  geom = lwgeom_from_wkt("GEOMETRYCOLLECTION(CIRCULARSTRING(0 0,0 1,1 1),POINT(0 0),CURVEPOLYGON(CIRCULARSTRING(0 0,0 1,1 1,1 0,0 0)))", LW_PARSER_CHECK_NONE);
96  CU_ASSERT_EQUAL(count,9);
97  lwgeom_free(geom);
98 
99  geom = lwgeom_from_wkt("CURVEPOLYGON((0 0,1 0,0 1,0 0),CIRCULARSTRING(0 0,1 0,1 1,1 0,0 0))", LW_PARSER_CHECK_NONE);
101  CU_ASSERT_EQUAL(count,9);
102  lwgeom_free(geom);
103 
104 
105  geom = lwgeom_from_wkt("POLYGON((0 0,1 0,0 1,0 0))", LW_PARSER_CHECK_NONE);
107  CU_ASSERT_EQUAL(count,4);
108  lwgeom_free(geom);
109 
110  geom = lwgeom_from_wkt("CURVEPOLYGON((0 0,1 0,0 1,0 0),CIRCULARSTRING(0 0,1 0,1 1,1 0,0 0))", LW_PARSER_CHECK_NONE);
112  CU_ASSERT_EQUAL(count,9);
113  lwgeom_free(geom);
114 }
115 
116 static void test_misc_area(void)
117 {
118  LWGEOM *geom;
119  double area;
120 
121  geom = lwgeom_from_wkt("LINESTRING EMPTY", LW_PARSER_CHECK_ALL);
122  area = lwgeom_area(geom);
123  CU_ASSERT_DOUBLE_EQUAL(area, 0.0, 0.0001);
124  lwgeom_free(geom);
125 }
126 
127 static void test_misc_wkb(void)
128 {
129  static char *wkb = "010A0000000200000001080000000700000000000000000000C00000000000000000000000000000F0BF000000000000F0BF00000000000000000000000000000000000000000000F03F000000000000F0BF000000000000004000000000000000000000000000000000000000000000004000000000000000C00000000000000000010200000005000000000000000000F0BF00000000000000000000000000000000000000000000E03F000000000000F03F00000000000000000000000000000000000000000000F03F000000000000F0BF0000000000000000";
131  char *str = lwgeom_to_wkt(geom, WKB_ISO, 8, 0);
132  ASSERT_STRING_EQUAL(str, "CURVEPOLYGON(CIRCULARSTRING(-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0 0.5,1 0,0 1,-1 0))");
133  lwfree(str);
134  lwgeom_free(geom);
135 
136 }
137 
138 
139 static void test_grid(void)
140 {
141  gridspec grid;
142  static char *wkt = "MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0)))";
144  LWGEOM *geomgrid;
145  char *str;
146 
147  grid.ipx = grid.ipy = 0;
148  grid.xsize = grid.ysize = 20;
149 
150  geomgrid = lwgeom_grid(geom, &grid);
151  str = lwgeom_to_ewkt(geomgrid);
152  ASSERT_STRING_EQUAL(str, "MULTIPOLYGON EMPTY");
153  lwfree(str);
154  lwgeom_free(geom);
155  lwgeom_free(geomgrid);
156 }
157 
158 static void do_grid_test(const char *wkt_in, const char *wkt_out, double size)
159 {
160  char *wkt_result, *wkt_norm;
161  gridspec grid;
164  wkt_norm = lwgeom_to_ewkt(go);
165  memset(&grid, 0, sizeof(gridspec));
166  grid.xsize = grid.ysize = grid.zsize = grid.msize = size;
167  lwgeom_grid_in_place(g, &grid);
168  wkt_result = lwgeom_to_ewkt(g);
169  // printf("%s ==%ld==> %s == %s\n", wkt_in, lround(size), wkt_result, wkt_out);
170  ASSERT_STRING_EQUAL(wkt_result, wkt_norm);
171  lwfree(wkt_result);
172  lwfree(wkt_norm);
173  lwgeom_free(g);
174  lwgeom_free(go);
175 }
176 
177 static void test_grid_in_place(void)
178 {
179  do_grid_test(
180  "LINESTRING(0 0,1 1,1 1,1 1)",
181  "LINESTRING(0 0,1 1)",
182  0.001
183  );
184  do_grid_test(
185  "POINT ZM (5.1423999999 5.1423999999 5.1423999999 5.1423999999)",
186  "POINT(5.1424 5.1424 5.1424 5.1424)",
187  0.0001
188  );
189  do_grid_test(
190  "MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)))",
191  "MULTIPOLYGON EMPTY",
192  20
193  );
194  do_grid_test(
195  "MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)))",
196  "MULTIPOLYGON(((0 0,10 0,10 10, 0 10,0 0)))",
197  1
198  );
199  do_grid_test(
200  "LINESTRING(0 0,1 1, 2 2, 3 3, 4 4, 5 5)",
201  "LINESTRING(0 0,2 2,4 4)",
202  2
203  );
204  do_grid_test(
205  "MULTIPOINT(0 0,1 1, 2 2, 3 3, 4 4, 5 5)",
206  /* This preserves current behaviour, but is probably not right */
207  "MULTIPOINT(0 0,0 0,2 2,4 4,4 4,4 4)",
208  2
209  );
210  do_grid_test(
211  "MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(4 4, 4 5, 5 5, 5 4, 4 4)))",
212  "MULTIPOLYGON(((0 0,10 0,10 10, 0 10,0 0)))",
213  2
214  );
215  do_grid_test(
216  "MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(4 4, 4 5, 5 5, 5 4, 4 4)))",
217  "MULTIPOLYGON EMPTY",
218  20
219  );
220  do_grid_test(
221  "POINT Z (5 5 5)",
222  "POINT(0 0 0)",
223  20
224  );
225 }
226 
227 static void test_clone(void)
228 {
229  static char *wkt = "GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0))),POINT(1 1),LINESTRING(2 3,4 5))";
231  LWGEOM *geom2;
232 
233  /* Free in "backwards" order */
234  geom2 = lwgeom_clone(geom1);
235  lwgeom_free(geom1);
236  lwgeom_free(geom2);
237 
238  /* Free in "forwards" order */
239  geom1 = lwgeom_from_wkt(wkt, LW_PARSER_CHECK_ALL);
240  geom2 = lwgeom_clone(geom1);
241  lwgeom_free(geom2);
242  lwgeom_free(geom1);
243 }
244 
245 static void test_lwmpoint_from_lwgeom(void)
246 {
247  /* This cast is so ugly, we only want to do it once. And not even that. */
248  LWGEOM* (*to_points)(LWGEOM*) = (LWGEOM* (*)(LWGEOM*)) &lwmpoint_from_lwgeom;
249 
250  do_fn_test(to_points, "MULTIPOLYGON (EMPTY)", "MULTIPOINT EMPTY");
251  do_fn_test(to_points, "POINT (30 10)", "MULTIPOINT ((30 10))");
252  do_fn_test(to_points, "LINESTRING Z (30 10 4,10 30 5,40 40 6)", "MULTIPOINT Z (30 10 4,10 30 5, 40 40 6)");
253  do_fn_test(to_points, "POLYGON((35 10,45 45,15 40,10 20,35 10),(20 30,35 35,30 20,20 30))", "MULTIPOINT(35 10,45 45,15 40,10 20,35 10,20 30,35 35,30 20,20 30)");
254  do_fn_test(to_points, "MULTIPOINT M (10 40 1,40 30 2,20 20 3,30 10 4)", "MULTIPOINT M (10 40 1,40 30 2,20 20 3,30 10 4)");
255  do_fn_test(to_points, "COMPOUNDCURVE(CIRCULARSTRING(0 0,2 0, 2 1, 2 3, 4 3),(4 3, 4 5, 1 4, 0 0))", "MULTIPOINT(0 0, 2 0, 2 1, 2 3, 4 3, 4 3, 4 5, 1 4, 0 0)");
256  do_fn_test(to_points, "TIN(((80 130,50 160,80 70,80 130)),((50 160,10 190,10 70,50 160)))", "MULTIPOINT (80 130, 50 160, 80 70, 80 130, 50 160, 10 190, 10 70, 50 160)");
257 }
258 
259 static void test_gbox_serialized_size(void)
260 {
261  lwflags_t flags = lwflags(0, 0, 0);
262  CU_ASSERT_EQUAL(gbox_serialized_size(flags),16);
263  FLAGS_SET_BBOX(flags, 1);
264  CU_ASSERT_EQUAL(gbox_serialized_size(flags),16);
265  FLAGS_SET_Z(flags, 1);
266  CU_ASSERT_EQUAL(gbox_serialized_size(flags),24);
267  FLAGS_SET_M(flags, 1);
268  CU_ASSERT_EQUAL(gbox_serialized_size(flags),32);
269  FLAGS_SET_GEODETIC(flags, 1);
270  CU_ASSERT_EQUAL(gbox_serialized_size(flags),24);
271 }
272 
273 static void test_optionlist(void)
274 {
275  size_t sz;
276  const char* value;
277  // zero out all the pointers so our list ends up null-terminated
278  char *olist[OPTION_LIST_SIZE];
279  char input[128];
280  memset(olist, 0, sizeof(olist));
281  // input string needs to be writeable because we are inserting nulls
282  strcpy(input, "key1=value1 key2=value2 ");
283  option_list_parse(input, olist);
284 
285  value = option_list_search(olist, "key1");
286  // printf("value: %s\n", value);
287  ASSERT_STRING_EQUAL("value1", value);
288  value = option_list_search(olist, "key2");
289  ASSERT_STRING_EQUAL("value2", value);
290  value = option_list_search(olist, "key3");
291  CU_ASSERT_EQUAL(NULL, value);
292 
293  sz = option_list_length(olist);
294  CU_ASSERT_EQUAL(4, sz);
295 
296  memset(olist, 0, sizeof(olist));
297  strcpy(input, " ");
298  option_list_parse(input, olist);
299  value = option_list_search(olist, "key1");
300  CU_ASSERT_EQUAL(NULL, value);
301 
302  memset(olist, 0, sizeof(olist));
303  strcpy(input, " key3= ");
304  option_list_parse(input, olist);
305  sz = option_list_length(olist);
306  CU_ASSERT_EQUAL(2, sz);
307 
308  strcpy(input, " key1=value1 key2='value2 value3' ");
309  memset(olist, 0, sizeof(olist));
310  option_list_gdal_parse(input, olist);
311  sz = option_list_length(olist);
312  CU_ASSERT_EQUAL(2, sz);
313  ASSERT_STRING_EQUAL("key1=value1", olist[0]);
314  ASSERT_STRING_EQUAL("key2='value2 value3'", olist[1]);
315 }
316 
317 
318 static void test_stringlist(void)
319 {
320  stringlist_t s;
321  stringlist_init(&s);
322 
323  CU_ASSERT_EQUAL(stringlist_length(&s), 0);
324  stringlist_add_string_nosort(&s, "first string");
325  stringlist_add_string_nosort(&s, "second string");
326  stringlist_add_string_nosort(&s, "third string");
327  CU_ASSERT_EQUAL(stringlist_length(&s), 3);
328  ASSERT_STRING_EQUAL(stringlist_get(&s, 0), "first string");
329  stringlist_add_string_nosort(&s, "an initial string");
330  stringlist_sort(&s);
331  ASSERT_STRING_EQUAL(stringlist_get(&s, 0), "an initial string");
332  ASSERT_STRING_EQUAL(stringlist_find(&s, "third string"), "third string");
333  CU_ASSERT_EQUAL(stringlist_find(&s, "nothing_matches"), NULL);
334  stringlist_add_string_nosort(&s, "fourth string");
335  stringlist_add_string_nosort(&s, "fifth string");
336  stringlist_add_string_nosort(&s, "sixth string");
337  stringlist_add_string_nosort(&s, "seventh string");
338  stringlist_add_string_nosort(&s, "eighth string");
339  stringlist_sort(&s);
340  ASSERT_STRING_EQUAL(stringlist_find(&s, "fifth string"), "fifth string");
342 }
343 
344 
345 /*
346 ** Used by the test harness to register the tests in this file.
347 */
348 void misc_suite_setup(void);
350 {
351  CU_pSuite suite = CU_add_suite("miscellaneous", NULL, NULL);
355  PG_ADD_TEST(suite, test_misc_area);
356  PG_ADD_TEST(suite, test_misc_wkb);
357  PG_ADD_TEST(suite, test_grid);
359  PG_ADD_TEST(suite, test_clone);
364 }
char * s
Definition: cu_in_wkt.c:23
size_t gbox_serialized_size(lwflags_t flags)
Return the number of bytes necessary to hold a GBOX of this dimension in serialized form.
Definition: gbox.c:452
static void test_lwmpoint_from_lwgeom(void)
static void test_clone(void)
static void test_misc_area(void)
void misc_suite_setup(void)
static void do_grid_test(const char *wkt_in, const char *wkt_out, double size)
static void test_misc_simplify(void)
static void test_grid_in_place(void)
static void test_misc_wkb(void)
static void test_stringlist(void)
static void test_misc_startpoint(void)
static void test_optionlist(void)
static void test_gbox_serialized_size(void)
static void test_misc_count_vertices(void)
static void test_grid(void)
void do_fn_test(LWGEOM *(*transfn)(LWGEOM *), char *input_wkt, char *expected_wkt)
#define PG_ADD_TEST(suite, testfunc)
#define ASSERT_STRING_EQUAL(o, e)
#define LW_PARSER_CHECK_ALL
Definition: liblwgeom.h:2147
LWGEOM * lwgeom_grid(const LWGEOM *lwgeom, gridspec *grid)
Definition: lwgeom.c:2393
LWGEOM * lwgeom_simplify(const LWGEOM *igeom, double dist, int preserve_collapsed)
Simplification.
Definition: lwgeom.c:1956
#define LW_FALSE
Definition: liblwgeom.h:94
int lwgeom_startpoint(const LWGEOM *lwgeom, POINT4D *pt)
Definition: lwgeom.c:2221
#define WKB_ISO
Definition: liblwgeom.h:2207
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition: lwin_wkb.c:866
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1218
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:2146
#define LW_SUCCESS
Definition: liblwgeom.h:97
uint16_t lwflags_t
Definition: liblwgeom.h:299
#define FLAGS_SET_BBOX(flags, value)
Definition: liblwgeom.h:174
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an allocated string.
Definition: lwgeom.c:565
double lwgeom_area(const LWGEOM *geom)
Definition: lwgeom.c:1971
uint32_t lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
Definition: lwgeom.c:1309
void lwfree(void *mem)
Definition: lwutil.c:248
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Definition: lwout_wkt.c:708
LWGEOM * lwgeom_clone(const LWGEOM *lwgeom)
Clone LWGEOM object.
Definition: lwgeom.c:491
LWGEOM * lwgeom_from_wkt(const char *wkt, const char check)
Definition: lwin_wkt.c:940
LWMPOINT * lwmpoint_from_lwgeom(const LWGEOM *g)
Definition: lwmpoint.c:93
#define FLAGS_SET_GEODETIC(flags, value)
Definition: liblwgeom.h:175
void lwgeom_grid_in_place(LWGEOM *lwgeom, gridspec *grid)
Definition: lwgeom.c:2289
lwflags_t lwflags(int hasz, int hasm, int geodetic)
Construct a new flags bitmask.
Definition: lwutil.c:477
#define FLAGS_SET_M(flags, value)
Definition: liblwgeom.h:173
#define FLAGS_SET_Z(flags, value)
Definition: liblwgeom.h:172
#define str(s)
int value
Definition: genraster.py:62
int count
Definition: genraster.py:57
void option_list_gdal_parse(char *input, char **olist)
Definition: optionlist.c:121
size_t option_list_length(char **olist)
Returns the total number of keys and values in the list.
Definition: optionlist.c:73
const char * option_list_search(char **olist, const char *key)
Returns null if the key cannot be found.
Definition: optionlist.c:54
void option_list_parse(char *input, char **olist)
option_list is a null-terminated list of strings, where every odd string is a key and every even stri...
Definition: optionlist.c:86
#define OPTION_LIST_SIZE
Definition: optionlist.h:31
void stringlist_init(stringlist_t *s)
Definition: stringlist.c:44
size_t stringlist_length(stringlist_t *s)
Definition: stringlist.c:137
void stringlist_release(stringlist_t *s)
Definition: stringlist.c:50
const char * stringlist_find(stringlist_t *s, const char *key)
Definition: stringlist.c:129
void stringlist_add_string_nosort(stringlist_t *s, const char *string)
Definition: stringlist.c:117
const char * stringlist_get(stringlist_t *s, size_t i)
Definition: stringlist.c:143
void stringlist_sort(stringlist_t *s)
Definition: stringlist.c:123
double x
Definition: liblwgeom.h:414
double y
Definition: liblwgeom.h:414
double zsize
Definition: liblwgeom.h:1405
double ysize
Definition: liblwgeom.h:1404
double xsize
Definition: liblwgeom.h:1403
double ipx
Definition: liblwgeom.h:1399
double msize
Definition: liblwgeom.h:1406
double ipy
Definition: liblwgeom.h:1400
Snap-to-grid.
Definition: liblwgeom.h:1398