PostGIS  3.0.6dev-r@@SVN_REVISION@@
cu_gserialized1.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  * Copyright 2009 Paul Ramsey <pramsey@cleverelephant.ca>
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 "gserialized1.c" /* for gserialized_peek_gbox_p */
19 #include "cu_tester.h"
20 
21 static void test_typmod_macros(void)
22 {
23  int32_t typmod = 0;
24  int32_t srid = 4326;
25  int type = 6;
26  int z = 1;
27  int rv;
28 
29  TYPMOD_SET_SRID(typmod,srid);
30  rv = TYPMOD_GET_SRID(typmod);
31  CU_ASSERT_EQUAL(rv, srid);
32 
33  srid = -5005;
34  TYPMOD_SET_SRID(typmod,srid);
35  rv = TYPMOD_GET_SRID(typmod);
36  CU_ASSERT_EQUAL(rv, srid);
37 
38  srid = 999999;
39  TYPMOD_SET_SRID(typmod,srid);
40  rv = TYPMOD_GET_SRID(typmod);
41  CU_ASSERT_EQUAL(rv, srid);
42 
43  srid = -999999;
44  TYPMOD_SET_SRID(typmod,srid);
45  rv = TYPMOD_GET_SRID(typmod);
46  CU_ASSERT_EQUAL(rv, srid);
47 
48  srid = SRID_UNKNOWN;
49  TYPMOD_SET_SRID(typmod,srid);
50  rv = TYPMOD_GET_SRID(typmod);
51  CU_ASSERT_EQUAL(rv, srid);
52 
53  srid = 0;
54  TYPMOD_SET_SRID(typmod,srid);
55  rv = TYPMOD_GET_SRID(typmod);
56  CU_ASSERT_EQUAL(rv, srid);
57 
58  srid = 1;
59  TYPMOD_SET_SRID(typmod,srid);
60  rv = TYPMOD_GET_SRID(typmod);
61  CU_ASSERT_EQUAL(rv, srid);
62 
63  TYPMOD_SET_TYPE(typmod,type);
64  rv = TYPMOD_GET_TYPE(typmod);
65  CU_ASSERT_EQUAL(rv,type);
66 
67  TYPMOD_SET_Z(typmod);
68  rv = TYPMOD_GET_Z(typmod);
69  CU_ASSERT_EQUAL(rv,z);
70 
71  rv = TYPMOD_GET_M(typmod);
72  CU_ASSERT_EQUAL(rv,0);
73 
74 }
75 
76 static void test_flags_macros(void)
77 {
78  uint8_t flags = 0;
79 
80  CU_ASSERT_EQUAL(0, G1FLAGS_GET_Z(flags));
81  G1FLAGS_SET_Z(flags, 1);
82  CU_ASSERT_EQUAL(1, G1FLAGS_GET_Z(flags));
83  G1FLAGS_SET_Z(flags, 0);
84  CU_ASSERT_EQUAL(0, G1FLAGS_GET_Z(flags));
85  CU_ASSERT_EQUAL(0, G1FLAGS_GET_BBOX(flags));
86 
87  CU_ASSERT_EQUAL(0, G1FLAGS_GET_M(flags));
88  G1FLAGS_SET_M(flags, 1);
89  CU_ASSERT_EQUAL(1, G1FLAGS_GET_M(flags));
90 
91  CU_ASSERT_EQUAL(0, G1FLAGS_GET_BBOX(flags));
92  G1FLAGS_SET_BBOX(flags, 1);
93  CU_ASSERT_EQUAL(1, G1FLAGS_GET_BBOX(flags));
94 
95  CU_ASSERT_EQUAL(0, G1FLAGS_GET_GEODETIC(flags));
96  G1FLAGS_SET_GEODETIC(flags, 1);
97  CU_ASSERT_EQUAL(1, G1FLAGS_GET_GEODETIC(flags));
98 
99  flags = g1flags(1, 0, 1); /* z=1, m=0, geodetic=1 */
100 
101  CU_ASSERT_EQUAL(1, G1FLAGS_GET_GEODETIC(flags));
102  CU_ASSERT_EQUAL(1, G1FLAGS_GET_Z(flags));
103  CU_ASSERT_EQUAL(0, G1FLAGS_GET_M(flags));
104  CU_ASSERT_EQUAL(2, G1FLAGS_GET_ZM(flags));
105 
106  flags = g1flags(1, 1, 1); /* z=1, m=1, geodetic=1 */
107 
108  CU_ASSERT_EQUAL(1, G1FLAGS_GET_GEODETIC(flags));
109  CU_ASSERT_EQUAL(1, G1FLAGS_GET_Z(flags));
110  CU_ASSERT_EQUAL(1, G1FLAGS_GET_M(flags));
111  CU_ASSERT_EQUAL(3, G1FLAGS_GET_ZM(flags));
112 
113  flags = g1flags(0, 1, 0); /* z=0, m=1, geodetic=0 */
114 
115  CU_ASSERT_EQUAL(0, G1FLAGS_GET_GEODETIC(flags));
116  CU_ASSERT_EQUAL(0, G1FLAGS_GET_Z(flags));
117  CU_ASSERT_EQUAL(1, G1FLAGS_GET_M(flags));
118  CU_ASSERT_EQUAL(1, G1FLAGS_GET_ZM(flags));
119 }
120 
121 static void test_serialized1_srid(void)
122 {
123  GSERIALIZED s;
124  int32_t srid, rv;
125 
126  srid = 4326;
127  gserialized1_set_srid(&s, srid);
128  rv = gserialized1_get_srid(&s);
129  CU_ASSERT_EQUAL(rv, srid);
130 
131  srid = -3005;
132  gserialized1_set_srid(&s, srid);
133  rv = gserialized1_get_srid(&s);
134  //printf("srid=%d rv=%d\n",srid,rv);
135  CU_ASSERT_EQUAL(rv, SRID_UNKNOWN);
136 
137  srid = SRID_UNKNOWN;
138  gserialized1_set_srid(&s, srid);
139  rv = gserialized1_get_srid(&s);
140  CU_ASSERT_EQUAL(rv, srid);
141 
142  srid = SRID_UNKNOWN;
143  gserialized1_set_srid(&s, srid);
144  rv = gserialized1_get_srid(&s);
145  CU_ASSERT_EQUAL(rv, srid);
146 
147  srid = 100000;
148  gserialized1_set_srid(&s, srid);
149  rv = gserialized1_get_srid(&s);
150  CU_ASSERT_EQUAL(rv, srid);
151 }
152 
154 {
155  LWGEOM *g;
156  size_t size = 0;
157 
158  g = lwgeom_from_wkt("POINT(0 0)", LW_PARSER_CHECK_NONE);
160  CU_ASSERT_EQUAL( size, 32 );
161  lwgeom_free(g);
162 
163  g = lwgeom_from_wkt("POINT(0 0 0)", LW_PARSER_CHECK_NONE);
165  CU_ASSERT_EQUAL( size, 40 );
166  lwgeom_free(g);
167 
168  g = lwgeom_from_wkt("MULTIPOINT(0 0 0, 1 1 1)", LW_PARSER_CHECK_NONE);
170  CU_ASSERT_EQUAL( size, 80 );
171  lwgeom_free(g);
172 
173  g = lwgeom_from_wkt("LINESTRING(0 0, 1 1)", LW_PARSER_CHECK_NONE);
175  CU_ASSERT_EQUAL( size, 48 );
176  lwgeom_free(g);
177 
178  g = lwgeom_from_wkt("MULTILINESTRING((0 0, 1 1),(0 0, 1 1))", LW_PARSER_CHECK_NONE);
180  CU_ASSERT_EQUAL( size, 96 );
181  lwgeom_free(g);
182 
183  g = lwgeom_from_wkt("POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))", LW_PARSER_CHECK_NONE);
185  CU_ASSERT_EQUAL( size, 104 );
186  lwgeom_free(g);
187 
188  g = lwgeom_from_wkt("POLYGON((-1 -1, -1 2, 2 2, 2 -1, -1 -1), (0 0, 0 1, 1 1, 1 0, 0 0))", LW_PARSER_CHECK_NONE);
190  CU_ASSERT_EQUAL( size, 184 );
191  lwgeom_free(g);
192 
193 }
194 
195 static void test_lwgeom_calculate_gbox(void)
196 {
197  LWGEOM *g;
198  GBOX b;
199 
200  g = lwgeom_from_wkt("POINT(0 0)", LW_PARSER_CHECK_NONE);
202  CU_ASSERT_DOUBLE_EQUAL(b.xmin, 0.0, 0.0000001);
203  lwgeom_free(g);
204 
205  /* Inf = 0x7FF0000000000000 */
206  /* POINT(0 0) = 00 00000001 0000000000000000 0000000000000000 */
207  /* POINT(0 Inf) = 00 00000001 0000000000000000 7FF0000000000000 */
208  g = lwgeom_from_hexwkb("000000000100000000000000007FF0000000000000", LW_PARSER_CHECK_NONE);
210  CU_ASSERT_DOUBLE_EQUAL(b.xmin, 0.0, 0.0000001);
211  CU_ASSERT(isinf(b.ymax));
212  lwgeom_free(g);
213 
214  /* LINESTRING(0 0, 0 Inf) = 00 00000002 00000002 0000000000000000 7FF0000000000000 0000000000000000 0000000000000000 */
215  /* Inf should show up in bbox */
216  g = lwgeom_from_hexwkb("00000000020000000200000000000000007FF000000000000000000000000000000000000000000000", LW_PARSER_CHECK_NONE);
218  CU_ASSERT_DOUBLE_EQUAL(b.xmin, 0.0, 0.0000001);
219  CU_ASSERT(isinf(b.ymax));
220  lwgeom_free(g);
221 
222  /* Geometry with NaN 0101000020E8640000000000000000F8FF000000000000F8FF */
223  /* NaN should show up in bbox for "SRID=4326;POINT(0 NaN)" */
224  g = lwgeom_from_hexwkb("0101000020E86400000000000000000000000000000000F8FF", LW_PARSER_CHECK_NONE);
226  CU_ASSERT(isnan(b.ymax));
227  lwgeom_free(g);
228 
229 }
230 
232 {
233  LWGEOM *geom;
234  GSERIALIZED *g;
235  char *in_ewkt;
236  char *out_ewkt;
237  size_t i = 0;
238 
239  char *ewkt[] =
240  {
241  "POINT EMPTY",
242  "POINT(0 0.2)",
243  "LINESTRING EMPTY",
244  "LINESTRING(-1 -1,-1 2.5,2 2,2 -1)",
245  "MULTIPOINT EMPTY",
246  "MULTIPOINT(0.9 0.9,0.9 0.9,0.9 0.9,0.9 0.9,0.9 0.9,0.9 0.9)",
247  "SRID=1;MULTILINESTRING EMPTY",
248  "SRID=1;MULTILINESTRING((-1 -1,-1 2.5,2 2,2 -1),(-1 -1,-1 2.5,2 2,2 -1),(-1 -1,-1 2.5,2 2,2 -1),(-1 -1,-1 2.5,2 2,2 -1))",
249  "SRID=1;MULTILINESTRING((-1 -1,-1 2.5,2 2,2 -1),(-1 -1,-1 2.5,2 2,2 -1),(-1 -1,-1 2.5,2 2,2 -1),(-1 -1,-1 2.5,2 2,2 -1))",
250  "POLYGON((-1 -1,-1 2.5,2 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0))",
251  "POLYGON EMPTY",
252  "SRID=4326;POLYGON((-1 -1,-1 2.5,2 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0))",
253  "SRID=4326;POLYGON EMPTY",
254  "SRID=4326;POLYGON((-1 -1,-1 2.5,2 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0),(-0.5 -0.5,-0.5 -0.4,-0.4 -0.4,-0.4 -0.5,-0.5 -0.5))",
255  "SRID=100000;POLYGON((-1 -1 3,-1 2.5 3,2 2 3,2 -1 3,-1 -1 3),(0 0 3,0 1 3,1 1 3,1 0 3,0 0 3),(-0.5 -0.5 3,-0.5 -0.4 3,-0.4 -0.4 3,-0.4 -0.5 3,-0.5 -0.5 3))",
256  "SRID=4326;MULTIPOLYGON(((-1 -1,-1 2.5,2 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0),(-0.5 -0.5,-0.5 -0.4,-0.4 -0.4,-0.4 -0.5,-0.5 -0.5)),((-1 -1,-1 2.5,2 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0),(-0.5 -0.5,-0.5 -0.4,-0.4 -0.4,-0.4 -0.5,-0.5 -0.5)))",
257  "SRID=4326;MULTIPOLYGON EMPTY",
258  "SRID=4326;GEOMETRYCOLLECTION(POINT(0 1),POLYGON((-1 -1,-1 2.5,2 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0)),MULTIPOLYGON(((-1 -1,-1 2.5,2 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0),(-0.5 -0.5,-0.5 -0.4,-0.4 -0.4,-0.4 -0.5,-0.5 -0.5))))",
259  "SRID=4326;GEOMETRYCOLLECTION EMPTY",
260  "SRID=4326;GEOMETRYCOLLECTION(POINT EMPTY,MULTIPOLYGON EMPTY)",
261  "MULTICURVE((5 5 1 3,3 5 2 2,3 3 3 1,0 3 1 1),CIRCULARSTRING(0 0 0 0,0.26794 1 3 -2,0.5857864 1.414213 1 2))",
262  "MULTISURFACE(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)),((7 8,10 10,6 14,4 11,7 8)))",
263  "MULTISURFACE(CURVEPOLYGON(CIRCULARSTRING EMPTY))",
264  };
265 
266  for ( i = 0; i < (sizeof ewkt/sizeof(char*)); i++ )
267  {
268  LWGEOM* geom2;
269  size_t sz1, sz2;
270 
271  in_ewkt = ewkt[i];
272  geom = lwgeom_from_wkt(in_ewkt, LW_PARSER_CHECK_NONE);
273  lwgeom_add_bbox(geom);
274  if ( geom->bbox ) gbox_float_round(geom->bbox);
275  sz1 = gserialized1_from_lwgeom_size(geom);
276  g = gserialized1_from_lwgeom(geom, &sz2);
277  CU_ASSERT_EQUAL(sz1, sz2);
278 
279  geom2 = lwgeom_from_gserialized(g);
280  out_ewkt = lwgeom_to_ewkt(geom2);
281 
282  /* printf("\n in = %s\nout = %s\n", in_ewkt, out_ewkt); */
283  CU_ASSERT_STRING_EQUAL(in_ewkt, out_ewkt);
284 
285  /* either both or none of the bboxes are null */
286  CU_ASSERT( (geom->bbox != NULL) || (geom2->bbox == NULL) );
287 
288  /* either both are null or they are the same */
289  CU_ASSERT(geom->bbox == NULL || gbox_same(geom->bbox, geom2->bbox));
290 
291  lwgeom_free(geom);
292  lwgeom_free(geom2);
293  lwfree(g);
294  lwfree(out_ewkt);
295  }
296 
297 }
298 
299 
300 static void test_gserialized1_is_empty(void)
301 {
302  int i = 0;
303  struct gserialized_empty_cases {
304  const char* wkt;
305  int isempty;
306  };
307 
308  struct gserialized_empty_cases cases[] = {
309  { "POINT EMPTY", 1 },
310  { "POINT(1 1)", 0 },
311  { "LINESTRING EMPTY", 1 },
312  { "MULTILINESTRING EMPTY", 1 },
313  { "MULTILINESTRING(EMPTY)", 1 },
314  { "MULTILINESTRING(EMPTY,EMPTY)", 1 },
315  { "MULTILINESTRING(EMPTY,(0 0,1 1))", 0 },
316  { "MULTILINESTRING((0 0,1 1),EMPTY)", 0 },
317  { "MULTILINESTRING(EMPTY,(0 0,1 1),EMPTY)", 0 },
318  { "MULTILINESTRING(EMPTY,EMPTY,EMPTY)", 1 },
319  { "GEOMETRYCOLLECTION(POINT EMPTY,MULTILINESTRING(EMPTY,EMPTY,EMPTY))", 1 },
320  { "GEOMETRYCOLLECTION(POINT EMPTY,MULTILINESTRING(EMPTY),POINT(1 1))", 0 },
321  { "GEOMETRYCOLLECTION(POINT EMPTY,MULTILINESTRING(EMPTY, (0 0)),POINT EMPTY)", 0 },
322  { "GEOMETRYCOLLECTION(POLYGON EMPTY,POINT EMPTY,MULTILINESTRING(EMPTY,EMPTY),POINT EMPTY)", 1 },
323  { "GEOMETRYCOLLECTION(POLYGON EMPTY,GEOMETRYCOLLECTION(POINT EMPTY),MULTILINESTRING(EMPTY,EMPTY),POINT EMPTY)", 1 },
324  { NULL, 0 }
325  };
326 
327  while( cases[i].wkt )
328  {
329  // i = 11;
330  LWGEOM *lw = lwgeom_from_wkt(cases[i].wkt, LW_PARSER_CHECK_NONE);
332  int ie = gserialized1_is_empty(g);
333  // printf("%s: we say %d, they say %d\n", cases[i].wkt, cases[i].isempty, ie);
334  CU_ASSERT_EQUAL(ie, cases[i].isempty);
335  lwgeom_free(lw);
336  lwfree(g);
337  i++;
338  }
339 }
340 
341 
343 {
344  int rv;
345  uint8_t type = 0;
346  int z = 0, m = 0;
347  char *str;
348 
349  str = " POINTZ";
350  rv = geometry_type_from_string(str, &type, &z, &m);
351  //printf("\n in type: %s\nout type: %d\n out z: %d\n out m: %d", str, type, z, m);
352  CU_ASSERT_EQUAL(rv, LW_SUCCESS);
353  CU_ASSERT_EQUAL(type, POINTTYPE);
354  CU_ASSERT_EQUAL(z, 1);
355  CU_ASSERT_EQUAL(m, 0);
356 
357  str = "LINESTRINGM ";
358  rv = geometry_type_from_string(str, &type, &z, &m);
359  //printf("\n in type: %s\nout type: %d\n out z: %d\n out m: %d", str, type, z, m);
360  CU_ASSERT_EQUAL(rv, LW_SUCCESS);
361  CU_ASSERT_EQUAL(type, LINETYPE);
362  CU_ASSERT_EQUAL(z, 0);
363  CU_ASSERT_EQUAL(m, 1);
364 
365  str = "MULTIPOLYGONZM";
366  rv = geometry_type_from_string(str, &type, &z, &m);
367  //printf("\n in type: %s\nout type: %d\n out z: %d\n out m: %d", str, type, z, m);
368  CU_ASSERT_EQUAL(rv, LW_SUCCESS);
369  CU_ASSERT_EQUAL(type, MULTIPOLYGONTYPE);
370  CU_ASSERT_EQUAL(z, 1);
371  CU_ASSERT_EQUAL(m, 1);
372 
373  str = " GEOMETRYCOLLECTIONZM ";
374  rv = geometry_type_from_string(str, &type, &z, &m);
375  //printf("\n in type: %s\nout type: %d\n out z: %d\n out m: %d", str, type, z, m);
376  CU_ASSERT_EQUAL(rv, LW_SUCCESS);
377  CU_ASSERT_EQUAL(type, COLLECTIONTYPE);
378  CU_ASSERT_EQUAL(z, 1);
379  CU_ASSERT_EQUAL(m, 1);
380 
381  str = " GEOMERYCOLLECTIONZM ";
382  rv = geometry_type_from_string(str, &type, &z, &m);
383  //printf("\n in type: %s\nout type: %d\n out z: %d\n out m: %d", str, type, z, m);
384  CU_ASSERT_EQUAL(rv, LW_FAILURE);
385 
386 }
387 
388 static void test_lwgeom_count_vertices(void)
389 {
390  LWGEOM *geom;
391 
392  geom = lwgeom_from_wkt("MULTIPOINT(-1 -1,-1 2.5,2 2,2 -1)", LW_PARSER_CHECK_NONE);
393  CU_ASSERT_EQUAL(lwgeom_count_vertices(geom),4);
394  lwgeom_free(geom);
395 
396  geom = lwgeom_from_wkt("SRID=1;MULTILINESTRING((-1 -131,-1 2.5,2 2,2 -1),(-1 -1,-1 2.5,2 2,2 -1),(-1 -1,-1 2.5,2 2,2 -1),(-1 -1,-1 2.5,2 2,2 -1))", LW_PARSER_CHECK_NONE);
397  CU_ASSERT_EQUAL(lwgeom_count_vertices(geom),16);
398  lwgeom_free(geom);
399 
400  geom = lwgeom_from_wkt("SRID=4326;MULTIPOLYGON(((-1 -1,-1 2.5,211 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0),(-0.5 -0.5,-0.5 -0.4,-0.4 -0.4,-0.4 -0.5,-0.5 -0.5)),((-1 -1,-1 2.5,2 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0),(-0.5 -0.5,-0.5 -0.4,-0.4 -0.4,-0.4 -0.5,-0.5 -0.5)))", LW_PARSER_CHECK_NONE);
401  CU_ASSERT_EQUAL(lwgeom_count_vertices(geom),30);
402  lwgeom_free(geom);
403 
404 }
405 
407 {
408  LWGEOM *lwgeom;
409  GSERIALIZED *g_ser1;
410  size_t ret_size;
411 
412  lwgeom = lwgeom_from_wkt("MULTIPOINT(-1 -1,-1 2.5,2 2,2 -1,1 1,2 2,4 5)", LW_PARSER_CHECK_NONE);
413  CU_ASSERT_EQUAL(lwgeom_count_vertices(lwgeom),7);
414  g_ser1 = gserialized1_from_lwgeom(lwgeom, &ret_size);
415  lwgeom_free(lwgeom);
416 
417  lwgeom = lwgeom_from_gserialized(g_ser1);
418  CU_ASSERT_EQUAL(lwgeom_count_vertices(lwgeom),7);
419  lwgeom_free(lwgeom);
420 
421  lwgeom = lwgeom_from_gserialized(g_ser1);
422 
423  CU_ASSERT_EQUAL(lwgeom_count_vertices(lwgeom),7);
424  lwgeom_free(lwgeom);
425 
426  lwfree(g_ser1);
427 
428 }
429 
430 static void test_lwcollection_extract(void)
431 {
432 
433  LWGEOM *geom;
434  LWCOLLECTION *col;
435 
436  geom = lwgeom_from_wkt("GEOMETRYCOLLECTION(POINT(0 0))", LW_PARSER_CHECK_NONE);
437 
438  col = lwcollection_extract((LWCOLLECTION*)geom, 1);
439  CU_ASSERT_EQUAL(col->type, MULTIPOINTTYPE);
440  lwcollection_free(col);
441 
442  col = lwcollection_extract((LWCOLLECTION*)geom, 2);
443  CU_ASSERT_EQUAL(col->type, MULTILINETYPE);
444  lwcollection_free(col);
445 
446  col = lwcollection_extract((LWCOLLECTION*)geom, 3);
447  CU_ASSERT_EQUAL(col->type, MULTIPOLYGONTYPE);
448  lwcollection_free(col);
449 
450  lwgeom_free(geom);
451 
452  geom = lwgeom_from_wkt("GEOMETRYCOLLECTION EMPTY", LW_PARSER_CHECK_NONE);
453 
454  col = lwcollection_extract((LWCOLLECTION*)geom, 1);
455  CU_ASSERT_EQUAL(col->type, MULTIPOINTTYPE);
456  lwcollection_free(col);
457 
458  col = lwcollection_extract((LWCOLLECTION*)geom, 2);
459  CU_ASSERT_EQUAL(col->type, MULTILINETYPE);
460  lwcollection_free(col);
461 
462  col = lwcollection_extract((LWCOLLECTION*)geom, 3);
463  CU_ASSERT_EQUAL(col->type, MULTIPOLYGONTYPE);
464  lwcollection_free(col);
465 
466  lwgeom_free(geom);
467 }
468 
469 static void test_lwgeom_free(void)
470 {
471  LWGEOM *geom;
472 
473  /* Empty geometries don't seem to free properly (#370) */
474  geom = lwgeom_from_wkt("GEOMETRYCOLLECTION EMPTY", LW_PARSER_CHECK_NONE);
475  CU_ASSERT_EQUAL(geom->type, COLLECTIONTYPE);
476  lwgeom_free(geom);
477 
478  /* Empty geometries don't seem to free properly (#370) */
479  geom = lwgeom_from_wkt("POLYGON EMPTY", LW_PARSER_CHECK_NONE);
480  CU_ASSERT_EQUAL(geom->type, POLYGONTYPE);
481  lwgeom_free(geom);
482 
483  /* Empty geometries don't seem to free properly (#370) */
484  geom = lwgeom_from_wkt("LINESTRING EMPTY", LW_PARSER_CHECK_NONE);
485  CU_ASSERT_EQUAL(geom->type, LINETYPE);
486  lwgeom_free(geom);
487 
488  /* Empty geometries don't seem to free properly (#370) */
489  geom = lwgeom_from_wkt("POINT EMPTY", LW_PARSER_CHECK_NONE);
490  CU_ASSERT_EQUAL(geom->type, POINTTYPE);
491  lwgeom_free(geom);
492 
493 }
494 
495 static void do_lwgeom_swap_ordinates(char *in, char *out)
496 {
497  LWGEOM *g;
498  char * t;
499  double xmax, ymax;
500  int testbox;
501 
503  lwgeom_add_bbox(g);
504 
505  testbox = (g->bbox != NULL);
506  if ( testbox )
507  {
508  xmax = g->bbox->xmax;
509  ymax = g->bbox->ymax;
510  }
511 
513 
514  if ( testbox )
515  {
516  CU_ASSERT_DOUBLE_EQUAL(g->bbox->xmax, ymax, 0.00001);
517  CU_ASSERT_DOUBLE_EQUAL(g->bbox->ymax, xmax, 0.00001);
518  }
519 
520  t = lwgeom_to_wkt(g, WKT_EXTENDED, 8, NULL);
521  if (t == NULL) fprintf(stderr, "In:%s", in);
522  if (strcmp(t, out))
523  fprintf(stderr, "\nIn: %s\nOut: %s\nTheo: %s\n", in, t, out);
524 
525  CU_ASSERT_STRING_EQUAL(t, out)
526 
527  lwgeom_free(g);
528  lwfree(t);
529 }
530 
531 static void test_lwgeom_swap_ordinates(void)
532 {
533  /*
534  * 2D geometries types
535  */
537  "POINT(1 2)",
538  "POINT(2 1)"
539  );
540 
542  "LINESTRING(1 2,3 4)",
543  "LINESTRING(2 1,4 3)"
544  );
545 
547  "POLYGON((1 2,3 4,5 6,1 2))",
548  "POLYGON((2 1,4 3,6 5,2 1))"
549  );
550 
552  "POLYGON((1 2,3 4,5 6,1 2),(7 8,9 10,11 12,7 8))",
553  "POLYGON((2 1,4 3,6 5,2 1),(8 7,10 9,12 11,8 7))"
554  );
555 
557  "MULTIPOINT(1 2,3 4)",
558  "MULTIPOINT(2 1,4 3)"
559  );
560 
562  "MULTILINESTRING((1 2,3 4),(5 6,7 8))",
563  "MULTILINESTRING((2 1,4 3),(6 5,8 7))"
564  );
565 
567  "MULTIPOLYGON(((1 2,3 4,5 6,7 8)),((9 10,11 12,13 14,10 9)))",
568  "MULTIPOLYGON(((2 1,4 3,6 5,8 7)),((10 9,12 11,14 13,9 10)))"
569  );
570 
572  "GEOMETRYCOLLECTION EMPTY",
573  "GEOMETRYCOLLECTION EMPTY"
574  );
575 
577  "GEOMETRYCOLLECTION(POINT(1 2),LINESTRING(3 4,5 6))",
578  "GEOMETRYCOLLECTION(POINT(2 1),LINESTRING(4 3,6 5))"
579  );
580 
582  "GEOMETRYCOLLECTION(POINT(1 2),GEOMETRYCOLLECTION(LINESTRING(3 4,5 6)))",
583  "GEOMETRYCOLLECTION(POINT(2 1),GEOMETRYCOLLECTION(LINESTRING(4 3,6 5)))"
584  );
585 
587  "CIRCULARSTRING(-2 0,0 2,2 0,0 2,2 4)",
588  "CIRCULARSTRING(0 -2,2 0,0 2,2 0,4 2)"
589  );
590 
592  "COMPOUNDCURVE(CIRCULARSTRING(0 1,1 1,1 0),(1 0,0 1))",
593  "COMPOUNDCURVE(CIRCULARSTRING(1 0,1 1,0 1),(0 1,1 0))"
594  );
595 
597  "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))",
598  "CURVEPOLYGON(CIRCULARSTRING(0 -2,-1 -1,0 0,-1 1,0 2,2 0,0 -2),(0 -1,0.5 0,0 1,1 0,0 -1))"
599  );
600 
602  "MULTICURVE((5 5,3 5,3 3,0 3),CIRCULARSTRING(0 0,2 1,2 3))",
603  "MULTICURVE((5 5,5 3,3 3,3 0),CIRCULARSTRING(0 0,1 2,3 2))"
604  );
605 
607  "MULTISURFACE(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)),((7 8,10 10,6 14,4 11,7 8)))",
608  "MULTISURFACE(CURVEPOLYGON(CIRCULARSTRING(0 -2,-1 -1,0 0,-1 1,0 2,2 0,0 -2),(0 -1,0.5 0,0 1,1 0,0 -1)),((8 7,10 10,14 6,11 4,8 7)))"
609  );
610 
611 
612  /*
613  * Ndims
614  */
615 
617  "POINT(1 2 3)",
618  "POINT(2 1 3)"
619  );
620 
622  "POINTM(1 2 3)",
623  "POINTM(2 1 3)"
624  );
625 
627  "POINT(1 2 3 4)",
628  "POINT(2 1 3 4)"
629  );
630 
631 
632  /*
633  * Srid
634  */
635 
637  "SRID=4326;POINT(1 2)",
638  "SRID=4326;POINT(2 1)"
639  );
640 
642  "SRID=0;POINT(1 2)",
643  "POINT(2 1)"
644  );
645 }
646 
647 static void test_f2d(void)
648 {
649  double d = 1000000.123456789123456789;
650  float f;
651  double e;
652 
653  f = next_float_down(d);
654  d = next_float_down(f);
655  CU_ASSERT_DOUBLE_EQUAL(f,d, 0.0000001);
656 
657  e = (double)f;
658  CU_ASSERT_DOUBLE_EQUAL(f,e, 0.0000001);
659 
660  f = next_float_down(d);
661  d = next_float_down(f);
662  CU_ASSERT_DOUBLE_EQUAL(f,d, 0.0000001);
663 
664  f = next_float_up(d);
665  d = next_float_up(f);
666  CU_ASSERT_DOUBLE_EQUAL(f,d, 0.0000001);
667 
668  f = next_float_up(d);
669  d = next_float_up(f);
670  CU_ASSERT_DOUBLE_EQUAL(f,d, 0.0000001);
671 
672  d = DBL_MAX;
673  f = next_float_up(d);
674  d = next_float_up(f);
675  CU_ASSERT_DOUBLE_EQUAL(f, d, 0.0000001);
676 
677  d = DBL_MAX;
678  f = next_float_down(d);
679  d = next_float_down(f);
680  CU_ASSERT_DOUBLE_EQUAL(f, d, 0.0000001);
681 
682  d = -DBL_MAX;
683  f = next_float_up(d);
684  d = next_float_up(f);
685  CU_ASSERT_DOUBLE_EQUAL(f, d, 0.0000001);
686 
687  d = -DBL_MAX;
688  f = next_float_down(d);
689  d = next_float_down(f);
690  CU_ASSERT_DOUBLE_EQUAL(f, d, 0.0000001);
691 }
692 
693 /*
694  * This is a test for memory leaks, can't really test
695  * w/out checking with a leak detector (ie: valgrind)
696  *
697  * See http://trac.osgeo.org/postgis/ticket/1102
698  */
699 static void test_lwgeom_clone(void)
700 {
701  size_t i;
702 
703  char *ewkt[] =
704  {
705  "POINT(0 0.2)",
706  "LINESTRING(-1 -1,-1 2.5,2 2,2 -1)",
707  "MULTIPOINT(0.9 0.9,0.9 0.9,0.9 0.9,0.9 0.9,0.9 0.9,0.9 0.9)",
708  "SRID=1;MULTILINESTRING((-1 -1,-1 2.5,2 2,2 -1),(-1 -1,-1 2.5,2 2,2 -1),(-1 -1,-1 2.5,2 2,2 -1),(-1 -1,-1 2.5,2 2,2 -1))",
709  "SRID=1;MULTILINESTRING((-1 -1,-1 2.5,2 2,2 -1),(-1 -1,-1 2.5,2 2,2 -1),(-1 -1,-1 2.5,2 2,2 -1),(-1 -1,-1 2.5,2 2,2 -1))",
710  "POLYGON((-1 -1,-1 2.5,2 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0))",
711  "SRID=4326;POLYGON((-1 -1,-1 2.5,2 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0))",
712  "SRID=4326;POLYGON((-1 -1,-1 2.5,2 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0),(-0.5 -0.5,-0.5 -0.4,-0.4 -0.4,-0.4 -0.5,-0.5 -0.5))",
713  "SRID=100000;POLYGON((-1 -1 3,-1 2.5 3,2 2 3,2 -1 3,-1 -1 3),(0 0 3,0 1 3,1 1 3,1 0 3,0 0 3),(-0.5 -0.5 3,-0.5 -0.4 3,-0.4 -0.4 3,-0.4 -0.5 3,-0.5 -0.5 3))",
714  "SRID=4326;MULTIPOLYGON(((-1 -1,-1 2.5,2 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0),(-0.5 -0.5,-0.5 -0.4,-0.4 -0.4,-0.4 -0.5,-0.5 -0.5)),((-1 -1,-1 2.5,2 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0),(-0.5 -0.5,-0.5 -0.4,-0.4 -0.4,-0.4 -0.5,-0.5 -0.5)))",
715  "SRID=4326;GEOMETRYCOLLECTION(POINT(0 1),POLYGON((-1 -1,-1 2.5,2 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0)),MULTIPOLYGON(((-1 -1,-1 2.5,2 2,2 -1,-1 -1),(0 0,0 1,1 1,1 0,0 0),(-0.5 -0.5,-0.5 -0.4,-0.4 -0.4,-0.4 -0.5,-0.5 -0.5))))",
716  "MULTICURVE((5 5 1 3,3 5 2 2,3 3 3 1,0 3 1 1),CIRCULARSTRING(0 0 0 0,0.26794 1 3 -2,0.5857864 1.414213 1 2))",
717  "MULTISURFACE(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)),((7 8,10 10,6 14,4 11,7 8)))",
718  "TIN(((0 0 0,0 0 1,0 1 0,0 0 0)),((0 0 0,0 1 0,1 0 0,0 0 0)),((0 0 0,1 0 0,0 0 1,0 0 0)),((1 0 0,0 1 0,0 0 1,1 0 0)))"
719  };
720 
721 
722  for ( i = 0; i < (sizeof ewkt/sizeof(char *)); i++ )
723  {
724  LWGEOM *geom, *cloned;
725  char *in_ewkt;
726  char *out_ewkt;
727 
728  in_ewkt = ewkt[i];
729  geom = lwgeom_from_wkt(in_ewkt, LW_PARSER_CHECK_NONE);
730  cloned = lwgeom_clone(geom);
731  out_ewkt = lwgeom_to_ewkt(cloned);
732  if (strcmp(in_ewkt, out_ewkt))
733  fprintf(stderr, "\nExp: %s\nObt: %s\n", in_ewkt, out_ewkt);
734  CU_ASSERT_STRING_EQUAL(in_ewkt, out_ewkt);
735  lwfree(out_ewkt);
736  lwgeom_free(cloned);
737  lwgeom_free(geom);
738  }
739 
740 
741 }
742 
743 /*
744  * Test lwgeom_force_clockwise
745  */
747 {
748  LWGEOM *geom;
749  LWGEOM *geom2;
750  char *in_ewkt, *out_ewkt;
751 
752  /* counterclockwise, must be reversed */
753  geom = lwgeom_from_wkt("POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))", LW_PARSER_CHECK_NONE);
754  CU_ASSERT_FALSE(lwgeom_is_clockwise(geom));
756  in_ewkt = "POLYGON((0 0,0 10,10 10,10 0,0 0))";
757  out_ewkt = lwgeom_to_ewkt(geom);
758  if (strcmp(in_ewkt, out_ewkt))
759  fprintf(stderr, "\nExp: %s\nObt: %s\n", in_ewkt, out_ewkt);
760  CU_ASSERT_STRING_EQUAL(in_ewkt, out_ewkt);
761  lwfree(out_ewkt);
762  lwgeom_free(geom);
763 
764  /* clockwise, fine as is */
765  geom = lwgeom_from_wkt("POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))", LW_PARSER_CHECK_NONE);
766  CU_ASSERT_TRUE(lwgeom_is_clockwise(geom));
768  in_ewkt = "POLYGON((0 0,0 10,10 10,10 0,0 0))";
769  out_ewkt = lwgeom_to_ewkt(geom);
770  if (strcmp(in_ewkt, out_ewkt))
771  fprintf(stderr, "\nExp: %s\nObt: %s\n", in_ewkt, out_ewkt);
772  CU_ASSERT_STRING_EQUAL(in_ewkt, out_ewkt);
773  lwfree(out_ewkt);
774  lwgeom_free(geom);
775 
776  /* counterclockwise shell (must be reversed), mixed-wise holes */
777  geom = lwgeom_from_wkt("POLYGON((0 0,10 0,10 10,0 10,0 0),(2 2,2 4,4 2,2 2),(6 2,8 2,8 4,6 2))", LW_PARSER_CHECK_NONE);
778  CU_ASSERT_FALSE(lwgeom_is_clockwise(geom));
780  in_ewkt = "POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,2 4,2 2),(6 2,8 2,8 4,6 2))";
781  out_ewkt = lwgeom_to_ewkt(geom);
782  if (strcmp(in_ewkt, out_ewkt))
783  fprintf(stderr, "\nExp: %s\nObt: %s\n", in_ewkt, out_ewkt);
784  CU_ASSERT_STRING_EQUAL(in_ewkt, out_ewkt);
785  lwfree(out_ewkt);
786  lwgeom_free(geom);
787 
788  /* clockwise shell (fine), mixed-wise holes */
789  geom = lwgeom_from_wkt("POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,2 4,2 2),(6 2,8 4,8 2,6 2))", LW_PARSER_CHECK_NONE);
790  CU_ASSERT_FALSE(lwgeom_is_clockwise(geom));
792  in_ewkt = "POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,2 4,2 2),(6 2,8 2,8 4,6 2))";
793  out_ewkt = lwgeom_to_ewkt(geom);
794  if (strcmp(in_ewkt, out_ewkt))
795  fprintf(stderr, "\nExp: %s\nObt: %s\n", in_ewkt, out_ewkt);
796  CU_ASSERT_STRING_EQUAL(in_ewkt, out_ewkt);
797  lwfree(out_ewkt);
798  lwgeom_free(geom);
799 
800  /* clockwise narrow ring, fine as-is */
801  /* NOTE: this is a narrow ring, see ticket #1302 */
802  in_ewkt = "0103000000010000000500000000917E9BA468294100917E9B8AEA2841C976BE1FA4682941C976BE9F8AEA2841B39ABE1FA46829415ACCC29F8AEA284137894120A4682941C976BE9F8AEA284100917E9BA468294100917E9B8AEA2841";
803  geom = lwgeom_from_hexwkb(in_ewkt, LW_PARSER_CHECK_NONE);
804  geom2 = lwgeom_from_hexwkb(in_ewkt, LW_PARSER_CHECK_NONE);
805  lwgeom_force_clockwise(geom2);
806 
809  CU_ASSERT( lwgeom_same(geom, geom2) );
810  lwgeom_free(geom);
811  lwgeom_free(geom2);
812 }
813 
814 /*
815  * Test lwgeom_is_empty
816  */
817 static void test_lwgeom_is_empty(void)
818 {
819  LWGEOM *geom;
820 
821  geom = lwgeom_from_wkt("POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))", LW_PARSER_CHECK_NONE);
822  CU_ASSERT( !lwgeom_is_empty(geom) );
823  lwgeom_free(geom);
824 
825  geom = lwgeom_from_wkt("POINT EMPTY", LW_PARSER_CHECK_NONE);
826  CU_ASSERT( lwgeom_is_empty(geom) );
827  lwgeom_free(geom);
828 
829  geom = lwgeom_from_wkt("LINESTRING EMPTY", LW_PARSER_CHECK_NONE);
830  CU_ASSERT( lwgeom_is_empty(geom) );
831  lwgeom_free(geom);
832 
833  geom = lwgeom_from_wkt("POLYGON EMPTY", LW_PARSER_CHECK_NONE);
834  CU_ASSERT( lwgeom_is_empty(geom) );
835  lwgeom_free(geom);
836 
837  geom = lwgeom_from_wkt("MULTIPOINT EMPTY", LW_PARSER_CHECK_NONE);
838  CU_ASSERT( lwgeom_is_empty(geom) );
839  lwgeom_free(geom);
840 
841  geom = lwgeom_from_wkt("MULTILINESTRING EMPTY", LW_PARSER_CHECK_NONE);
842  CU_ASSERT( lwgeom_is_empty(geom) );
843  lwgeom_free(geom);
844 
845  geom = lwgeom_from_wkt("MULTIPOLYGON EMPTY", LW_PARSER_CHECK_NONE);
846  CU_ASSERT( lwgeom_is_empty(geom) );
847  lwgeom_free(geom);
848 
849  geom = lwgeom_from_wkt("GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY, POINT EMPTY, LINESTRING EMPTY, POLYGON EMPTY, MULTIPOINT EMPTY, MULTILINESTRING EMPTY, MULTIPOLYGON EMPTY, GEOMETRYCOLLECTION(MULTIPOLYGON EMPTY))", LW_PARSER_CHECK_NONE);
850  CU_ASSERT( lwgeom_is_empty(geom) );
851  lwgeom_free(geom);
852 
853 }
854 
855 /*
856  * Test lwgeom_same
857  */
858 static void test_lwgeom_same(void)
859 {
860  LWGEOM *geom, *geom2;
861 
862  geom = lwgeom_from_wkt("POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))", LW_PARSER_CHECK_NONE);
863  CU_ASSERT( lwgeom_same(geom, geom) );
864  lwgeom_add_bbox(geom);
865  CU_ASSERT( lwgeom_same(geom, geom) );
866  lwgeom_free(geom);
867 
868  geom = lwgeom_from_wkt("MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0)))", LW_PARSER_CHECK_NONE);
869  CU_ASSERT( lwgeom_same(geom, geom) );
870  lwgeom_add_bbox(geom);
871  CU_ASSERT( lwgeom_same(geom, geom) );
872  lwgeom_free(geom);
873 
874  geom = lwgeom_from_wkt("LINESTRING(0 0, 2 0)", LW_PARSER_CHECK_NONE);
875  CU_ASSERT( lwgeom_same(geom, geom) );
876  lwgeom_add_bbox(geom);
877  CU_ASSERT( lwgeom_same(geom, geom) );
878  lwgeom_free(geom);
879 
880  geom = lwgeom_from_wkt("MULTILINESTRING((0 0, 2 0))", LW_PARSER_CHECK_NONE);
881  CU_ASSERT( lwgeom_same(geom, geom) );
882  lwgeom_add_bbox(geom);
883  CU_ASSERT( lwgeom_same(geom, geom) );
884  lwgeom_free(geom);
885 
886  geom = lwgeom_from_wkt("POINT(0 0)", LW_PARSER_CHECK_NONE);
887  CU_ASSERT( lwgeom_same(geom, geom) );
888  lwgeom_add_bbox(geom);
889  CU_ASSERT( lwgeom_same(geom, geom) );
890  lwgeom_free(geom);
891 
892  geom = lwgeom_from_wkt("MULTIPOINT((0 0),(4 5))", LW_PARSER_CHECK_NONE);
893  CU_ASSERT( lwgeom_same(geom, geom) );
894  lwgeom_add_bbox(geom);
895  CU_ASSERT( lwgeom_same(geom, geom) );
896  lwgeom_free(geom);
897 
898  geom = lwgeom_from_wkt("POINT EMPTY", LW_PARSER_CHECK_NONE);
899  CU_ASSERT( lwgeom_same(geom, geom) );
900  lwgeom_add_bbox(geom);
901  CU_ASSERT( lwgeom_same(geom, geom) );
902  lwgeom_free(geom);
903 
904  geom = lwgeom_from_wkt("LINESTRING EMPTY", LW_PARSER_CHECK_NONE);
905  CU_ASSERT( lwgeom_same(geom, geom) );
906  lwgeom_add_bbox(geom);
907  CU_ASSERT( lwgeom_same(geom, geom) );
908  lwgeom_free(geom);
909 
910  geom = lwgeom_from_wkt("POLYGON EMPTY", LW_PARSER_CHECK_NONE);
911  CU_ASSERT( lwgeom_same(geom, geom) );
912  lwgeom_free(geom);
913 
914  geom = lwgeom_from_wkt("MULTIPOINT EMPTY", LW_PARSER_CHECK_NONE);
915  CU_ASSERT( lwgeom_same(geom, geom) );
916  lwgeom_free(geom);
917 
918  geom = lwgeom_from_wkt("MULTILINESTRING EMPTY", LW_PARSER_CHECK_NONE);
919  CU_ASSERT( lwgeom_same(geom, geom) );
920  lwgeom_free(geom);
921 
922  geom = lwgeom_from_wkt("MULTIPOLYGON EMPTY", LW_PARSER_CHECK_NONE);
923  CU_ASSERT( lwgeom_same(geom, geom) );
924  lwgeom_free(geom);
925 
926  geom = lwgeom_from_wkt("GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY, POINT EMPTY, LINESTRING EMPTY, POLYGON EMPTY, MULTIPOINT EMPTY, MULTILINESTRING EMPTY, MULTIPOLYGON EMPTY, GEOMETRYCOLLECTION(MULTIPOLYGON EMPTY))", LW_PARSER_CHECK_NONE);
927  CU_ASSERT( lwgeom_same(geom, geom) );
928  lwgeom_free(geom);
929 
930  geom = lwgeom_from_wkt("POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))", LW_PARSER_CHECK_NONE);
931  geom2 = lwgeom_from_wkt("GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY, POINT EMPTY, LINESTRING EMPTY, POLYGON EMPTY, MULTIPOINT EMPTY, MULTILINESTRING EMPTY, MULTIPOLYGON EMPTY, GEOMETRYCOLLECTION(MULTIPOLYGON EMPTY))", LW_PARSER_CHECK_NONE);
932  CU_ASSERT( ! lwgeom_same(geom, geom2) );
933  lwgeom_free(geom);
934  lwgeom_free(geom2);
935 
936  geom = lwgeom_from_wkt("POINT(0 0)", LW_PARSER_CHECK_NONE);
937  geom2 = lwgeom_from_wkt("MULTIPOINT((0 0))", LW_PARSER_CHECK_NONE);
938  CU_ASSERT( ! lwgeom_same(geom, geom2) );
939  lwgeom_free(geom);
940  lwgeom_free(geom2);
941 
942  geom = lwgeom_from_wkt("POINT EMPTY", LW_PARSER_CHECK_NONE);
943  geom2 = lwgeom_from_wkt("POINT Z EMPTY", LW_PARSER_CHECK_NONE);
944  CU_ASSERT( ! lwgeom_same(geom, geom2) );
945  lwgeom_free(geom);
946  lwgeom_free(geom2);
947 
948 }
949 
950 /*
951  * Test lwgeom_force_curve
952  */
953 static void test_lwgeom_as_curve(void)
954 {
955  LWGEOM *geom;
956  LWGEOM *geom2;
957  char *in_ewkt, *out_ewkt;
958 
959  geom = lwgeom_from_wkt("LINESTRING(0 0, 10 0)", LW_PARSER_CHECK_NONE);
960  geom2 = lwgeom_as_curve(geom);
961  in_ewkt = "COMPOUNDCURVE((0 0,10 0))";
962  out_ewkt = lwgeom_to_ewkt(geom2);
963  if (strcmp(in_ewkt, out_ewkt))
964  fprintf(stderr, "\nExp: %s\nObt: %s\n", in_ewkt, out_ewkt);
965  CU_ASSERT_STRING_EQUAL(in_ewkt, out_ewkt);
966  lwfree(out_ewkt);
967  lwgeom_free(geom);
968  lwgeom_free(geom2);
969 
970  geom = lwgeom_from_wkt("MULTILINESTRING((0 0, 10 0))", LW_PARSER_CHECK_NONE);
971  geom2 = lwgeom_as_curve(geom);
972  in_ewkt = "MULTICURVE((0 0,10 0))";
973  out_ewkt = lwgeom_to_ewkt(geom2);
974  if (strcmp(in_ewkt, out_ewkt))
975  fprintf(stderr, "\nExp: %s\nObt: %s\n", in_ewkt, out_ewkt);
976  CU_ASSERT_STRING_EQUAL(in_ewkt, out_ewkt);
977  lwfree(out_ewkt);
978  lwgeom_free(geom);
979  lwgeom_free(geom2);
980 
981  geom = lwgeom_from_wkt("POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))", LW_PARSER_CHECK_NONE);
982  geom2 = lwgeom_as_curve(geom);
983  in_ewkt = "CURVEPOLYGON((0 0,10 0,10 10,0 10,0 0))";
984  out_ewkt = lwgeom_to_ewkt(geom2);
985  if (strcmp(in_ewkt, out_ewkt))
986  fprintf(stderr, "\nExp: %s\nObt: %s\n", in_ewkt, out_ewkt);
987  CU_ASSERT_STRING_EQUAL(in_ewkt, out_ewkt);
988  lwfree(out_ewkt);
989  lwgeom_free(geom);
990  lwgeom_free(geom2);
991 
992  geom = lwgeom_from_wkt("MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0)))", LW_PARSER_CHECK_NONE);
993  geom2 = lwgeom_as_curve(geom);
994  in_ewkt = "MULTISURFACE(((0 0,10 0,10 10,0 10,0 0)))";
995  out_ewkt = lwgeom_to_ewkt(geom2);
996  if (strcmp(in_ewkt, out_ewkt))
997  fprintf(stderr, "\nExp: %s\nObt: %s\n", in_ewkt, out_ewkt);
998  CU_ASSERT_STRING_EQUAL(in_ewkt, out_ewkt);
999  lwfree(out_ewkt);
1000  lwgeom_free(geom);
1001  lwgeom_free(geom2);
1002 
1003 }
1004 
1005 static void test_lwline_from_lwmpoint(void)
1006 {
1007  LWLINE *line;
1008  LWMPOINT *mpoint;
1009 
1010  mpoint = (LWMPOINT*)lwgeom_from_wkt("MULTIPOINT(0 0, 0 1, 1 1, 1 2, 2 2)", LW_PARSER_CHECK_NONE);
1011  line = lwline_from_lwmpoint(SRID_DEFAULT, mpoint);
1012  CU_ASSERT_EQUAL(line->points->npoints, mpoint->ngeoms);
1013  CU_ASSERT_DOUBLE_EQUAL(lwline_length_2d(line), 4.0, 0.000001);
1014 
1015  lwline_free(line);
1016  lwmpoint_free(mpoint);
1017 }
1018 
1019 /*
1020  * Test lwgeom_scale
1021  */
1022 static void test_lwgeom_scale(void)
1023 {
1024  LWGEOM *geom;
1025  POINT4D factor;
1026  char *out_ewkt;
1027  GBOX *box;
1028 
1029  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);
1030  factor.x = 2; factor.y = 3; factor.z = 4; factor.m = 5;
1031  lwgeom_scale(geom, &factor);
1032  out_ewkt = lwgeom_to_ewkt(geom);
1033  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))");
1034  lwgeom_free(geom);
1035  lwfree(out_ewkt);
1036 
1037  geom = lwgeom_from_wkt("POINT(1 1 1 1)", LW_PARSER_CHECK_NONE);
1038  lwgeom_add_bbox(geom);
1039  factor.x = 2; factor.y = 3; factor.z = 4; factor.m = 5;
1040  lwgeom_scale(geom, &factor);
1041  box = geom->bbox;
1042  ASSERT_DOUBLE_EQUAL(box->xmin, 2);
1043  ASSERT_DOUBLE_EQUAL(box->xmax, 2);
1044  ASSERT_DOUBLE_EQUAL(box->ymin, 3);
1045  ASSERT_DOUBLE_EQUAL(box->ymax, 3);
1046  ASSERT_DOUBLE_EQUAL(box->zmin, 4);
1047  ASSERT_DOUBLE_EQUAL(box->zmax, 4);
1048  ASSERT_DOUBLE_EQUAL(box->mmin, 5);
1049  ASSERT_DOUBLE_EQUAL(box->mmax, 5);
1050  lwgeom_free(geom);
1051 }
1052 
1053 static void test_gbox_same_2d(void)
1054 {
1055  LWGEOM* g1 = lwgeom_from_wkt("LINESTRING(0 0, 1 1)", LW_PARSER_CHECK_NONE);
1056  LWGEOM* g2 = lwgeom_from_wkt("LINESTRING(0 0, 0 1, 1 1)", LW_PARSER_CHECK_NONE);
1057  LWGEOM* g3 = lwgeom_from_wkt("LINESTRING(0 0, 1 1.000000000001)", LW_PARSER_CHECK_NONE);
1058 
1059  lwgeom_add_bbox(g1);
1060  lwgeom_add_bbox(g2);
1061  lwgeom_add_bbox(g3);
1062 
1063  CU_ASSERT_TRUE(gbox_same_2d(g1->bbox, g2->bbox));
1064  CU_ASSERT_FALSE(gbox_same_2d(g1->bbox, g3->bbox));
1065 
1066  /* Serializing a GBOX with precise coordinates renders the boxes not strictly equal,
1067  * but still equal according to gbox_same_2d_float.
1068  */
1069  GSERIALIZED* s3 = gserialized1_from_lwgeom(g3, NULL);
1070  GBOX s3box;
1071  gserialized1_read_gbox_p(s3, &s3box);
1072 
1073  CU_ASSERT_FALSE(gbox_same_2d(g3->bbox, &s3box));
1074  CU_ASSERT_TRUE(gbox_same_2d_float(g3->bbox, &s3box));
1075 
1076  /* The serialized box equals itself by either the exact or closest-float compares */
1077  CU_ASSERT_TRUE(gbox_same_2d(&s3box, &s3box));
1078  CU_ASSERT_TRUE(gbox_same_2d_float(&s3box, &s3box));
1079 
1080  lwgeom_free(g1);
1081  lwgeom_free(g2);
1082  lwgeom_free(g3);
1083  lwfree(s3);
1084 }
1085 
1087 {
1088  uint32_t i;
1089 
1090  char *ewkt[] =
1091  {
1092  "POINT EMPTY",
1093  "LINESTRING EMPTY",
1094  "MULTIPOINT EMPTY",
1095  "MULTIPOINT (EMPTY)",
1096  "MULTILINESTRING EMPTY",
1097  "MULTILINESTRING (EMPTY)"
1098  };
1099 
1100  for ( i = 0; i < (sizeof ewkt/sizeof(char*)); i++ )
1101  {
1102  LWGEOM* geom = lwgeom_from_wkt(ewkt[i], LW_PARSER_CHECK_NONE);
1103  GBOX box;
1104  gbox_init(&box);
1105 
1106  GSERIALIZED* gser = gserialized1_from_lwgeom(geom, NULL);
1107 
1108  CU_ASSERT_FALSE(gserialized1_has_bbox(gser));
1109 
1110  CU_ASSERT_EQUAL(LW_FAILURE, gserialized1_peek_gbox_p(gser, &box));
1111 
1112  lwgeom_free(geom);
1113  lwfree(gser);
1114  }
1115 }
1116 
1118 {
1119  uint32_t i;
1120 
1121  char *ewkt[] =
1122  {
1123  "POINT (2.2945672355 48.85822923236)",
1124  "POINTZ (2.2945672355 48.85822923236 15)",
1125  "POINTM (2.2945672355 48.85822923236 12)",
1126  "POINT ZM (2.2945672355 48.85822923236 12 2)",
1127  "MULTIPOINT ((-76.45402132523 44.225406213532))",
1128  "MULTIPOINT Z ((-76.45402132523 44.225406213532 112))",
1129  "MULTIPOINT ZM ((-76.45402132523 44.225406213532 112 44))",
1130  "LINESTRING (2.2945672355 48.85822923236, -76.45402132523 44.225406213532)",
1131  "LINESTRING Z (2.2945672355 48.85822923236 6, -76.45402132523 44.225406213532 8)",
1132  "LINESTRING ZM (2.2945672355 48.85822923236 3 2, -76.45402132523 44.225406213532 9 4)",
1133  "MULTILINESTRING ((2.2945672355 48.85822923236, -76.45402132523 44.225406213532))",
1134  "MULTILINESTRING Z ((2.2945672355 48.85822923236 4, -76.45402132523 44.225406213532 3))"
1135  };
1136 
1137  for ( i = 0; i < (sizeof ewkt/sizeof(char*)); i++ )
1138  {
1139  LWGEOM* geom = lwgeom_from_wkt(ewkt[i], LW_PARSER_CHECK_NONE);
1140  GBOX box_from_peek;
1141  GBOX box_from_lwgeom;
1142  gbox_init(&box_from_peek);
1143  gbox_init(&box_from_lwgeom);
1144 
1145  GSERIALIZED* gser = gserialized1_from_lwgeom(geom, NULL);
1146 
1147  CU_ASSERT_FALSE(gserialized1_has_bbox(gser));
1148 
1149  lwgeom_calculate_gbox(geom, &box_from_lwgeom);
1150  gserialized1_peek_gbox_p(gser, &box_from_peek);
1151 
1152  gbox_float_round(&box_from_lwgeom);
1153 
1154  CU_ASSERT_TRUE(gbox_same(&box_from_peek, &box_from_lwgeom));
1155 
1156  lwgeom_free(geom);
1157  lwfree(gser);
1158  }
1159 }
1160 
1162 {
1163  uint32_t i;
1164 
1165  char *ewkt[] =
1166  {
1167  "MULTIPOINT ((-76.45402132523 44.225406213532), (-72 33))",
1168  "LINESTRING (2.2945672355 48.85822923236, -76.45402132523 44.225406213532, -72 33)",
1169  "MULTILINESTRING ((2.2945672355 48.85822923236, -76.45402132523 44.225406213532, -72 33))",
1170  "MULTILINESTRING ((2.2945672355 48.85822923236, -76.45402132523 44.225406213532), (-72 33, -71 32))"
1171  };
1172 
1173  for ( i = 0; i < (sizeof ewkt/sizeof(char*)); i++ )
1174  {
1175  LWGEOM* geom = lwgeom_from_wkt(ewkt[i], LW_PARSER_CHECK_NONE);
1176  GBOX box;
1177  gbox_init(&box);
1178  lwgeom_drop_bbox(geom);
1179 
1180  /* Construct a GSERIALIZED* that doesn't have a box, so that we can test the
1181  * actual logic of the peek function */
1182  size_t expected_size = gserialized1_from_lwgeom_size(geom);
1183  GSERIALIZED* gser = lwalloc(expected_size);
1184  uint8_t* ptr = (uint8_t*) gser;
1185 
1186  ptr += 8; // Skip header
1187  gserialized1_from_lwgeom_any(geom, ptr);
1188  gser->gflags = lwflags_get_g1flags(geom->flags);
1189 
1190  CU_ASSERT_FALSE(gserialized1_has_bbox(gser));
1191  CU_ASSERT_EQUAL(LW_FAILURE, gserialized1_peek_gbox_p(gser, &box));
1192 
1193  lwgeom_free(geom);
1194  lwfree(gser);
1195  }
1196 }
1197 
1198 static void test_signum_macro(void)
1199 {
1200  CU_ASSERT_EQUAL(SIGNUM(-5.0),-1);
1201  CU_ASSERT_EQUAL(SIGNUM( 5.0), 1);
1202  CU_ASSERT_EQUAL(SIGNUM( 0.0), 0);
1203  CU_ASSERT_EQUAL(SIGNUM(10) * 5, 5);
1204  CU_ASSERT_EQUAL(SIGNUM(-10) * 5, -5);
1205 }
1206 
1207 static int
1208 peek1_point_helper(char *geometry, POINT4D *p)
1209 {
1211  p->x = p->y = p->z = p->m = 0;
1212  LWGEOM *geom = lwgeom_from_wkt(geometry, LW_PARSER_CHECK_NONE);
1213  CU_ASSERT(geom != NULL);
1214  GSERIALIZED *g = gserialized1_from_lwgeom(geom, NULL);
1215  CU_ASSERT(g != NULL);
1216 
1217  int ret = gserialized1_peek_first_point(g, p);
1218  lwfree(g);
1219  lwgeom_free(geom);
1220 
1221  return ret;
1222 }
1223 
1224 static void
1226 {
1227  POINT4D p = {0};
1228 
1229  CU_ASSERT(peek1_point_helper("POINT(1 2)", &p) == LW_SUCCESS);
1230  CU_ASSERT_EQUAL(p.x, 1);
1231  CU_ASSERT_EQUAL(p.y, 2);
1232 
1233  CU_ASSERT(peek1_point_helper("POINTZ(10 20 30)", &p) == LW_SUCCESS);
1234  CU_ASSERT_EQUAL(p.x, 10);
1235  CU_ASSERT_EQUAL(p.y, 20);
1236  CU_ASSERT_EQUAL(p.z, 30);
1237 
1238  CU_ASSERT(peek1_point_helper("POINTM(100 200 300)", &p) == LW_SUCCESS);
1239  CU_ASSERT_EQUAL(p.x, 100);
1240  CU_ASSERT_EQUAL(p.y, 200);
1241  CU_ASSERT_EQUAL(p.m, 300);
1242 
1243  CU_ASSERT(peek1_point_helper("POINTZM(1000 2000 3000 4000)", &p) == LW_SUCCESS);
1244  CU_ASSERT_EQUAL(p.x, 1000);
1245  CU_ASSERT_EQUAL(p.y, 2000);
1246  CU_ASSERT_EQUAL(p.z, 3000);
1247  CU_ASSERT_EQUAL(p.m, 4000);
1248 
1249  CU_ASSERT(peek1_point_helper("MULTIPOINT((0 0), (1 1))", &p) == LW_FAILURE);
1250  CU_ASSERT(peek1_point_helper("LINESTRING(0 0, 1 1)", &p) == LW_FAILURE);
1251  CU_ASSERT(peek1_point_helper("MULTILINESTRING((0 0, 1 1), (0 0, 1 1))", &p) == LW_FAILURE);
1252  CU_ASSERT(peek1_point_helper("POLYGON((0 0, 1 1, 1 0, 0 0))", &p) == LW_FAILURE);
1253 }
1254 
1255 /*
1256 ** Used by test harness to register the tests in this file.
1257 */
1258 void gserialized1_suite_setup(void);
1260 {
1261  CU_pSuite suite = CU_add_suite("serialization/deserialization v1", NULL, NULL);
1271  PG_ADD_TEST(suite, test_lwgeom_free);
1273  PG_ADD_TEST(suite, test_f2d);
1278  PG_ADD_TEST(suite, test_lwgeom_same);
1289 }
static void test_lwgeom_count_vertices(void)
static void do_lwgeom_swap_ordinates(char *in, char *out)
static void test_lwgeom_clone(void)
static void test_gserialized1_peek_first_point(void)
static void test_lwgeom_as_curve(void)
static void test_gserialized1_from_lwgeom_size(void)
static void test_lwgeom_scale(void)
static void test_gserialized1_is_empty(void)
static void test_lwgeom_free(void)
static void test_gserialized1_peek_gbox_p_no_box_when_empty(void)
static void test_lwgeom_force_clockwise(void)
static void test_f2d(void)
static void test_flags_macros(void)
static void test_on_gser_lwgeom_count_vertices(void)
static void test_lwgeom_swap_ordinates(void)
static void test_gserialized1_peek_gbox_p_gets_correct_box(void)
static void test_gserialized1_peek_gbox_p_fails_for_unsupported_cases(void)
static void test_gbox_same_2d(void)
static void test_lwgeom_calculate_gbox(void)
static void test_serialized1_srid(void)
static void test_lwline_from_lwmpoint(void)
static void test_lwgeom_same(void)
static void test_lwcollection_extract(void)
static int peek1_point_helper(char *geometry, POINT4D *p)
void gserialized1_suite_setup(void)
static void test_typmod_macros(void)
static void test_geometry_type_from_string(void)
static void test_signum_macro(void)
static void test_lwgeom_from_gserialized(void)
static void test_lwgeom_is_empty(void)
char * s
Definition: cu_in_wkt.c:23
int gbox_same(const GBOX *g1, const GBOX *g2)
Check if 2 given Gbox are the same.
Definition: gbox.c:164
int gbox_same_2d(const GBOX *g1, const GBOX *g2)
Check if 2 given GBOX are the same in x and y.
Definition: gbox.c:179
void gbox_float_round(GBOX *gbox)
Round given GBOX to float boundaries.
Definition: gbox.c:774
int lwgeom_calculate_gbox_cartesian(const LWGEOM *lwgeom, GBOX *gbox)
Calculate the 2-4D bounding box of a geometry.
Definition: gbox.c:740
void gbox_init(GBOX *gbox)
Zero out all the entries in the GBOX.
Definition: gbox.c:40
int gbox_same_2d_float(const GBOX *g1, const GBOX *g2)
Check if two given GBOX are the same in x and y, or would round to the same GBOX in x and if serializ...
Definition: gbox.c:187
static size_t gserialized1_from_lwgeom_any(const LWGEOM *geom, uint8_t *buf)
Definition: gserialized1.c:981
int gserialized1_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: gserialized1.c:203
uint8_t g1flags(int has_z, int has_m, int is_geodetic)
Definition: gserialized1.c:77
int32_t gserialized1_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: gserialized1.c:142
int gserialized1_peek_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Definition: gserialized1.c:298
int gserialized1_has_bbox(const GSERIALIZED *gser)
Check if a GSERIALIZED has a bounding box without deserializing first.
Definition: gserialized1.c:89
GSERIALIZED * gserialized1_from_lwgeom(LWGEOM *geom, size_t *size)
Allocate a new GSERIALIZED from an LWGEOM.
int gserialized1_peek_first_point(const GSERIALIZED *g, POINT4D *out_point)
Definition: gserialized1.c:491
size_t gserialized1_from_lwgeom_size(const LWGEOM *geom)
Return the memory size a GSERIALIZED will occupy for a given LWGEOM.
Definition: gserialized1.c:721
uint8_t lwflags_get_g1flags(lwflags_t lwflags)
Definition: gserialized1.c:51
void gserialized1_set_srid(GSERIALIZED *s, int32_t srid)
Write the SRID into the serialized form (it is packed into three bytes so this is a handy function).
Definition: gserialized1.c:159
static int gserialized1_read_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Definition: gserialized1.c:251
#define G1FLAGS_SET_Z(gflags, value)
Definition: gserialized1.h:23
#define G1FLAGS_GET_M(gflags)
Definition: gserialized1.h:17
#define G1FLAGS_SET_M(gflags, value)
Definition: gserialized1.h:24
#define G1FLAGS_GET_ZM(gflags)
Definition: gserialized1.h:30
#define G1FLAGS_SET_BBOX(gflags, value)
Definition: gserialized1.h:25
#define G1FLAGS_GET_BBOX(gflags)
Definition: gserialized1.h:18
#define G1FLAGS_SET_GEODETIC(gflags, value)
Definition: gserialized1.h:26
#define G1FLAGS_GET_GEODETIC(gflags)
Definition: gserialized1.h:19
#define G1FLAGS_GET_Z(gflags)
Definition: gserialized1.h:16
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Definition: gserialized.c:239
void cu_error_msg_reset()
#define ASSERT_DOUBLE_EQUAL(o, e)
#define PG_ADD_TEST(suite, testfunc)
#define ASSERT_STRING_EQUAL(o, e)
#define TYPMOD_GET_SRID(typmod)
Macros for manipulating the 'typemod' int.
Definition: liblwgeom.h:206
char lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2)
geom1 same as geom2 iff
Definition: lwgeom.c:573
@ LWORD_Y
Definition: liblwgeom.h:146
@ LWORD_X
Definition: liblwgeom.h:145
#define COLLECTIONTYPE
Definition: liblwgeom.h:122
#define TYPMOD_SET_SRID(typmod, srid)
Definition: liblwgeom.h:207
void lwmpoint_free(LWMPOINT *mpt)
Definition: lwmpoint.c:72
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition: lwin_wkb.c:849
#define LW_FAILURE
Definition: liblwgeom.h:110
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1138
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:2060
#define MULTILINETYPE
Definition: liblwgeom.h:120
#define LINETYPE
Definition: liblwgeom.h:117
#define WKT_EXTENDED
Definition: liblwgeom.h:2132
#define LW_SUCCESS
Definition: liblwgeom.h:111
#define MULTIPOINTTYPE
Definition: liblwgeom.h:119
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:116
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an alloced string.
Definition: lwgeom.c:547
void lwgeom_drop_bbox(LWGEOM *lwgeom)
Call this function to drop BBOX and SRID from LWGEOM.
Definition: lwgeom.c:664
int geometry_type_from_string(const char *str, uint8_t *type, int *z, int *m)
Utility function to get type number from string.
Definition: lwutil.c:489
void lwgeom_scale(LWGEOM *geom, const POINT4D *factors)
Definition: lwgeom.c:2029
#define TYPMOD_GET_M(typmod)
Definition: liblwgeom.h:212
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:121
uint32_t lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
Definition: lwgeom.c:1229
#define TYPMOD_SET_TYPE(typmod, type)
Definition: liblwgeom.h:209
void lwfree(void *mem)
Definition: lwutil.c:242
#define SRID_DEFAULT
Definition: liblwgeom.h:239
LWGEOM * lwgeom_as_curve(const LWGEOM *lwgeom)
Create a new LWGEOM of the appropriate CURVE* type.
Definition: lwgeom.c:402
#define POLYGONTYPE
Definition: liblwgeom.h:118
void lwgeom_swap_ordinates(LWGEOM *in, LWORD o1, LWORD o2)
Swap ordinate values in every vertex of the geometry.
Definition: lwgeom.c:1461
void lwgeom_force_clockwise(LWGEOM *lwgeom)
Force Right-hand-rule on LWGEOM polygons.
Definition: lwgeom.c:37
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:357
#define TYPMOD_GET_TYPE(typmod)
Definition: liblwgeom.h:208
LWLINE * lwline_from_lwmpoint(int32_t srid, const LWMPOINT *mpoint)
Definition: lwline.c:275
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Definition: lwout_wkt.c:676
LWGEOM * lwgeom_clone(const LWGEOM *lwgeom)
Clone LWGEOM object.
Definition: lwgeom.c:473
int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox)
Calculate bounding box of a geometry, automatically taking into account whether it is cartesian or ge...
Definition: lwgeom.c:737
LWGEOM * lwgeom_from_wkt(const char *wkt, const char check)
Definition: lwin_wkt.c:905
LWCOLLECTION * lwcollection_extract(LWCOLLECTION *col, int type)
Takes a potentially heterogeneous collection and returns a homogeneous collection consisting only of ...
Definition: lwcollection.c:387
void * lwalloc(size_t size)
Definition: lwutil.c:227
float next_float_up(double d)
Definition: lwgeom_api.c:75
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:229
#define TYPMOD_SET_Z(typmod)
Definition: liblwgeom.h:211
int lwgeom_is_clockwise(LWGEOM *lwgeom)
Ensure the outer ring is clockwise oriented and all inner rings are counter-clockwise.
Definition: lwgeom.c:65
#define TYPMOD_GET_Z(typmod)
Definition: liblwgeom.h:210
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
Definition: lwgeom.c:677
float next_float_down(double d)
Definition: lwgeom_api.c:54
void lwline_free(LWLINE *line)
Definition: lwline.c:67
double lwline_length_2d(const LWLINE *line)
Definition: lwline.c:517
#define SIGNUM(n)
Macro that returns: -1 if n < 0, 1 if n > 0, 0 if n == 0.
#define str(s)
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition: lwinline.h:193
type
Definition: ovdump.py:42
double ymax
Definition: liblwgeom.h:343
double zmax
Definition: liblwgeom.h:345
double xmax
Definition: liblwgeom.h:341
double zmin
Definition: liblwgeom.h:344
double mmax
Definition: liblwgeom.h:347
double ymin
Definition: liblwgeom.h:342
double xmin
Definition: liblwgeom.h:340
double mmin
Definition: liblwgeom.h:346
uint8_t gflags
Definition: liblwgeom.h:432
uint8_t type
Definition: liblwgeom.h:564
uint8_t type
Definition: liblwgeom.h:448
GBOX * bbox
Definition: liblwgeom.h:444
lwflags_t flags
Definition: liblwgeom.h:447
POINTARRAY * points
Definition: liblwgeom.h:469
uint32_t ngeoms
Definition: liblwgeom.h:524
double m
Definition: liblwgeom.h:400
double x
Definition: liblwgeom.h:400
double z
Definition: liblwgeom.h:400
double y
Definition: liblwgeom.h:400
uint32_t npoints
Definition: liblwgeom.h:413