PostGIS  3.4.0dev-r@@SVN_REVISION@@
cu_out_twkb.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  * Copyright 2014 Nicklas Avén
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 "cu_tester.h"
19 
20 
21 /*
22 ** Global variable to hold hex TWKB strings
23 */
24 static char *s;
25 static char *w;
26 
27 /*
28 ** The suite initialization function.
29 ** Create any re-used objects.
30 */
31 static int init_twkb_out_suite(void)
32 {
33  s = NULL;
34  w = NULL;
35  return 0;
36 }
37 
38 /*
39 ** The suite cleanup function.
40 ** Frees any global objects.
41 */
42 static int clean_twkb_out_suite(void)
43 {
44  if (s) free(s);
45  if (w) free(w);
46  s = NULL;
47  w = NULL;
48  return 0;
49 }
50 
51 
52 /*
53 ** Creating an input TWKB from a wkt string
54 */
55 static void cu_twkb(char *wkt, int8_t prec_xy, int8_t prec_z, int8_t prec_m, uint8_t variant)
56 {
58  if ( ! g ) lwnotice("input wkt is invalid: %s", wkt);
59  lwvarlena_t *twkb = lwgeom_to_twkb(g, variant, prec_xy, prec_z, prec_m);
60  lwgeom_free(g);
61  if ( s ) free(s);
62  s = hexbytes_from_bytes((uint8_t *)twkb->data, LWSIZE_GET(twkb->size) - LWVARHDRSZ);
63  free(twkb);
64 }
65 
66 
67 /*
68 ** Creating an input TWKB from a wkt string
69 */
70 static void cu_twkb_idlist(char *wkt, int64_t *idlist, int8_t prec_xy, int8_t prec_z, int8_t prec_m, uint8_t variant)
71 {
73  LWGEOM *g_b;
74  if ( ! g ) lwnotice("input wkt is invalid: %s", wkt);
75  lwvarlena_t *twkb = lwgeom_to_twkb_with_idlist(g, idlist, variant, prec_xy, prec_z, prec_m);
76  lwgeom_free(g);
77  if ( s ) free(s);
78  if ( w ) free(w);
79  s = hexbytes_from_bytes((uint8_t *)twkb->data, LWSIZE_GET(twkb->size) - LWVARHDRSZ);
80  g_b = lwgeom_from_twkb((uint8_t *)twkb->data, LWSIZE_GET(twkb->size) - LWVARHDRSZ, LW_PARSER_CHECK_NONE);
81  w = lwgeom_to_ewkt(g_b);
82  lwgeom_free(g_b);
83  free(twkb);
84 }
85 
86 
87 
88 static void test_twkb_out_point(void)
89 {
90 
91  cu_twkb("POINT EMPTY", 0, 0, 0, 0);
92  CU_ASSERT_STRING_EQUAL(s,"0110");
93 
94  cu_twkb("POINT(0 0)", 0, 0, 0, 0);
95  CU_ASSERT_STRING_EQUAL(s,"01000000");
96 
97  cu_twkb("POINT(0 0 0 0)", 0, 0, 0, 0);
98  CU_ASSERT_STRING_EQUAL(s,"01080300000000");
99 
100  /* Point with bounding box */
101  cu_twkb("POINT(0 0)", 0, 0, 0, TWKB_BBOX);
102  CU_ASSERT_STRING_EQUAL(s,"0101000000000000");
103  // printf("TWKB: %s\n",s);
104 
105  /* Adding a size paramters to X/Y */
106  cu_twkb("POINT(0 0)", 0, 0, 0, TWKB_SIZE);
107  CU_ASSERT_STRING_EQUAL(s,"0102020000");
108 
109  /* Adding a size paramters to X/Y/M */
110  cu_twkb("POINTM(0 0 0)", 0, 0, 0, TWKB_SIZE);
111  CU_ASSERT_STRING_EQUAL(s,"010A0203000000");
112 
113  /* Adding a size paramters to X/Y/Z/M */
114  cu_twkb("POINT(0 0 0 0)", 0, 0, 0, TWKB_SIZE);
115  CU_ASSERT_STRING_EQUAL(s,"010A030400000000");
116 
117  /* Since the third dimension is Z it shall get a precision of 1 decimal (third argument) */
118  cu_twkb("POINTZ(1 1 1)", 0,1,2, 0);
119  CU_ASSERT_STRING_EQUAL(s,"010845020214");
120 
121  /* Since the third dimension is M it shall get a precision of 2 decimals (fourth argument) */
122  cu_twkb("POINTM(1 1 1)", 0,1,2, 0);
123  // printf("\n%s\n", s);
124  CU_ASSERT_STRING_EQUAL(s,"0108460202C801");
125 }
126 
127 static void test_twkb_out_linestring(void)
128 {
129 
130  cu_twkb("LINESTRING(0 0,1 1)", 0, 0, 0, 0);
131  CU_ASSERT_STRING_EQUAL(s,"02000200000202");
132  // printf("TWKB: %s\n",s);
133 
134  cu_twkb("LINESTRING(0 0 1,1 1 2,2 2 3)", 0, 0, 0, 0);
135  CU_ASSERT_STRING_EQUAL(s,"02080103000002020202020202");
136  // printf("TWKB: %s\n",s);
137 
138  /* Line with bounding box */
139  cu_twkb("LINESTRING(0 0,1 1,2 2)", 0, 0, 0, TWKB_BBOX);
140  CU_ASSERT_STRING_EQUAL(s,"02010004000403000002020202");
141  // printf("TWKB: %s\n",s);
142 
143  cu_twkb("LINESTRING EMPTY", 0, 0, 0, 0);
144  CU_ASSERT_STRING_EQUAL(s,"0210");
145  // printf("TWKB: %s\n",s);
146 }
147 
148 static void test_twkb_out_polygon(void)
149 {
150  cu_twkb("SRID=4;POLYGON((0 0 0, 0 1 0,1 1 0,1 0 0, 0 0 0))", 0, 0, 0, 0);
151  CU_ASSERT_STRING_EQUAL(s,"0308010105000000000200020000000100010000");
152  // printf("TWKB: %s\n",s);
153 
154  cu_twkb("SRID=14;POLYGON((0 0 0 1, 0 1 0 2,1 1 0 3,1 0 0 4, 0 0 0 5))", 0, 0, 0, 0);
155  CU_ASSERT_STRING_EQUAL(s,"03080301050000000200020002020000020001000201000002");
156  // printf("TWKB: %s\n",s);
157 
158  cu_twkb("POLYGON EMPTY", 0, 0, 0, 0);
159  CU_ASSERT_STRING_EQUAL(s,"0310");
160  // printf("TWKB: %s\n",s);
161 }
162 
163 static void test_twkb_out_multipoint(void)
164 {
165  cu_twkb("MULTIPOINT(0 0 0, 0 1 0,1 1 0,1 0 0, 0 0 0)", 0, 0, 0, 0);
166  CU_ASSERT_STRING_EQUAL(s,"04080105000000000200020000000100010000");
167 
168  cu_twkb("MULTIPOINT(0 0 0, 0.26794919243112270647255365849413 1 3)",7 ,7 , 0, 0);
169  //printf("WKB: %s",s);
170  CU_ASSERT_STRING_EQUAL(s,"E4081D02000000888BC70280DAC409808ECE1C");
171 // printf("TWKB: %s\n",s);
172 }
173 
174 static void test_twkb_out_multilinestring(void) {}
175 
176 static void test_twkb_out_multipolygon(void)
177 {
178  cu_twkb("MULTIPOLYGON(((0 0 0, 0 1 0,1 1 0,1 0 0, 0 0 0)),((-1 -1 0,-1 2 0,2 2 0,2 -1 0,-1 -1 0),(0 0 0, 0 1 0,1 1 0,1 0 0, 0 0 0)))", 0, 0, 0, 0);
179  CU_ASSERT_STRING_EQUAL(s,"060801020105000000000200020000000100010000020501010000060006000000050005000005020200000200020000000100010000");
180 }
181 
182 static void test_twkb_out_collection(void)
183 {
184  cu_twkb("GEOMETRYCOLLECTION(LINESTRING(1 1, 2 2), LINESTRING(3 3, 4 4), LINESTRING(5 5, 6 6))", 0, 0, 0, 0);
185  // printf("TWKB: %s\n",s);
186  CU_ASSERT_STRING_EQUAL(s,"07000302000202020202020002060602020200020A0A0202");
187 
188  cu_twkb("GEOMETRYCOLLECTION(POLYGON((0 0 0, 0 1 0,1 1 0,1 0 0, 0 0 0)),POINT(1 1 1))", 0, 0, 0, 0);
189  // printf("TWKB: %s\n",s);
190  CU_ASSERT_STRING_EQUAL(s,"070801020308010105000000000200020000000100010000010801020202");
191 
192  cu_twkb("GEOMETRYCOLLECTION EMPTY", 0, 0, 0, 0);
193  CU_ASSERT_STRING_EQUAL(s,"0710");
194 }
195 
196 static void test_twkb_out_idlist(void)
197 {
198  int64_t idlist[2];
199 
200  idlist[0] = 2;
201  idlist[1] = 4;
202  cu_twkb_idlist("MULTIPOINT(1 1, 0 0)",idlist, 0, 0, 0, 0);
203  // printf("TWKB: %s\n",s);
204  // printf("WKT: %s\n",w);
205  CU_ASSERT_STRING_EQUAL(s,"040402040802020101");
206  CU_ASSERT_STRING_EQUAL(w,"MULTIPOINT(1 1,0 0)");
207 
208  /*
209  04 06 multipoint, size/idlist
210  07 size 7 bytes
211  02 two geometries
212  0408 idlist (2, 4)
213  0202 first point @ 1,1
214  0101 second point offset -1,-1
215  */
216  idlist[0] = 2;
217  idlist[1] = 4;
218  cu_twkb_idlist("MULTIPOINT(1 1, 0 0)",idlist, 0, 0, 0, TWKB_SIZE);
219  // printf("TWKB: %s\n",s);
220  // printf("WKT: %s\n",w);
221  CU_ASSERT_STRING_EQUAL(s,"04060702040802020101");
222  CU_ASSERT_STRING_EQUAL(w,"MULTIPOINT(1 1,0 0)");
223 
224  /*
225  04 07 multipoint, bbox/size/idlist
226  0B size 11 bytes
227  00020002 bbox x(0,1), y(0,1)
228  02 two geometries
229  0408 idlist (2,4)
230  0202 first point @ 1,1
231  0101 seconds point offset -1,-1
232  */
233  idlist[0] = 2;
234  idlist[1] = 4;
235  cu_twkb_idlist("MULTIPOINT(1 1, 0 0)",idlist, 0, 0, 0, TWKB_SIZE | TWKB_BBOX);
236  // printf("TWKB: %s\n",s);
237  // printf("WKT: %s\n",w);
238  CU_ASSERT_STRING_EQUAL(s,"04070B0002000202040802020101");
239  CU_ASSERT_STRING_EQUAL(w,"MULTIPOINT(1 1,0 0)");
240 
241  /*
242  0704 geometrycollection, idlist
243  02 two geometries
244  0408 idlist (2,4)
245  01000202 first point (type, meta, x, y)
246  01000000 second point (type, meta, x, y)
247  */
248  idlist[0] = 2;
249  idlist[1] = 4;
250  cu_twkb_idlist("GEOMETRYCOLLECTION(POINT(1 1),POINT(0 0))",idlist, 0, 0, 0, 0);
251  // printf("TWKB: %s\n",s);
252  CU_ASSERT_STRING_EQUAL(s,"07040204080100020201000000");
253  CU_ASSERT_STRING_EQUAL(w,"GEOMETRYCOLLECTION(POINT(1 1),POINT(0 0))");
254 
255  /*
256  0706 geometrycollection, size/idlist
257  0D size, 13 bytes
258  02 two geometries
259  0408 idlist (2,4)
260  0102020202 first point (type, meta, size, x, y)
261  0102020000 second point (type, meta, size, x, y)
262  */
263  idlist[0] = 2;
264  idlist[1] = 4;
265  cu_twkb_idlist("GEOMETRYCOLLECTION(POINT(1 1),POINT(0 0))",idlist, 0, 0, 0, TWKB_SIZE);
266  // printf("TWKB: %s\n",s);
267  CU_ASSERT_STRING_EQUAL(s,"07060D02040801020202020102020000");
268  CU_ASSERT_STRING_EQUAL(w,"GEOMETRYCOLLECTION(POINT(1 1),POINT(0 0))");
269 
270 }
271 
272 
273 /*
274 ** Used by test harness to register the tests in this file.
275 */
276 void twkb_out_suite_setup(void);
278 {
279  CU_pSuite suite = CU_add_suite("twkb_output", init_twkb_out_suite, clean_twkb_out_suite);
288 }
static uint8_t variant
Definition: cu_in_twkb.c:26
static void cu_twkb_idlist(char *wkt, int64_t *idlist, int8_t prec_xy, int8_t prec_z, int8_t prec_m, uint8_t variant)
Definition: cu_out_twkb.c:70
static void test_twkb_out_polygon(void)
Definition: cu_out_twkb.c:148
static void cu_twkb(char *wkt, int8_t prec_xy, int8_t prec_z, int8_t prec_m, uint8_t variant)
Definition: cu_out_twkb.c:55
static int init_twkb_out_suite(void)
Definition: cu_out_twkb.c:31
static void test_twkb_out_multipolygon(void)
Definition: cu_out_twkb.c:176
static char * w
Definition: cu_out_twkb.c:25
static void test_twkb_out_multipoint(void)
Definition: cu_out_twkb.c:163
void twkb_out_suite_setup(void)
Definition: cu_out_twkb.c:277
static void test_twkb_out_point(void)
Definition: cu_out_twkb.c:88
static char * s
Definition: cu_out_twkb.c:24
static void test_twkb_out_multilinestring(void)
Definition: cu_out_twkb.c:174
static void test_twkb_out_idlist(void)
Definition: cu_out_twkb.c:196
static void test_twkb_out_linestring(void)
Definition: cu_out_twkb.c:127
static int clean_twkb_out_suite(void)
Definition: cu_out_twkb.c:42
static void test_twkb_out_collection(void)
Definition: cu_out_twkb.c:182
#define PG_ADD_TEST(suite, testfunc)
#define LWVARHDRSZ
Definition: liblwgeom.h:311
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1155
char * hexbytes_from_bytes(const uint8_t *bytes, size_t size)
Definition: lwout_wkb.c:40
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:2114
LWGEOM * lwgeom_from_twkb(const uint8_t *twkb, size_t twkb_size, char check)
WKB inputs must have a declared size, to prevent malformed WKB from reading off the end of the memory...
Definition: lwin_twkb.c:654
#define LWSIZE_GET(varsize)
Macro for reading the size from the GSERIALIZED size attribute.
Definition: liblwgeom.h:324
lwvarlena_t * lwgeom_to_twkb(const LWGEOM *geom, uint8_t variant, int8_t precision_xy, int8_t precision_z, int8_t precision_m)
Definition: lwout_twkb.c:636
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an alloced string.
Definition: lwgeom.c:565
LWGEOM * lwgeom_from_wkt(const char *wkt, const char check)
Definition: lwin_wkt.c:905
#define TWKB_SIZE
Definition: liblwgeom.h:2193
lwvarlena_t * lwgeom_to_twkb_with_idlist(const LWGEOM *geom, int64_t *idlist, uint8_t variant, int8_t precision_xy, int8_t precision_z, int8_t precision_m)
Convert LWGEOM to a char* in TWKB format.
Definition: lwout_twkb.c:589
#define TWKB_BBOX
Definition: liblwgeom.h:2192
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
void free(void *)
uint32_t size
Definition: liblwgeom.h:307
char data[]
Definition: liblwgeom.h:308