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 char *s;
25 char *w;
26
27 /*
28 ** The suite initialization function.
29 ** Create any re-used objects.
30 */
init_twkb_out_suite(void)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 */
clean_twkb_out_suite(void)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 */
cu_twkb(char * wkt,int8_t prec_xy,int8_t prec_z,int8_t prec_m,uint8_t variant)55 static void cu_twkb(char *wkt, int8_t prec_xy, int8_t prec_z, int8_t prec_m, uint8_t variant)
56 {
57 LWGEOM *g = lwgeom_from_wkt(wkt, LW_PARSER_CHECK_NONE);
58 size_t twkb_size;
59 uint8_t *twkb;
60 if ( ! g ) lwnotice("input wkt is invalid: %s", wkt);
61 twkb = lwgeom_to_twkb(g, variant, prec_xy, prec_z, prec_m, &twkb_size);
62 lwgeom_free(g);
63 if ( s ) free(s);
64 s = hexbytes_from_bytes(twkb, twkb_size);
65 free(twkb);
66 }
67
68
69 /*
70 ** Creating an input TWKB from a wkt string
71 */
cu_twkb_idlist(char * wkt,int64_t * idlist,int8_t prec_xy,int8_t prec_z,int8_t prec_m,uint8_t variant)72 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)
73 {
74 LWGEOM *g = lwgeom_from_wkt(wkt, LW_PARSER_CHECK_NONE);
75 LWGEOM *g_b;
76 size_t twkb_size;
77 uint8_t *twkb;
78 if ( ! g ) lwnotice("input wkt is invalid: %s", wkt);
79 twkb = lwgeom_to_twkb_with_idlist(g, idlist, variant, prec_xy, prec_z, prec_m, &twkb_size);
80 lwgeom_free(g);
81 if ( s ) free(s);
82 if ( w ) free(w);
83 s = hexbytes_from_bytes(twkb, twkb_size);
84 g_b = lwgeom_from_twkb(twkb, twkb_size, LW_PARSER_CHECK_NONE);
85 w = lwgeom_to_ewkt(g_b);
86 lwgeom_free(g_b);
87 free(twkb);
88 }
89
90
91
test_twkb_out_point(void)92 static void test_twkb_out_point(void)
93 {
94
95 cu_twkb("POINT EMPTY", 0, 0, 0, 0);
96 CU_ASSERT_STRING_EQUAL(s,"0110");
97
98 cu_twkb("POINT(0 0)", 0, 0, 0, 0);
99 CU_ASSERT_STRING_EQUAL(s,"01000000");
100
101 cu_twkb("POINT(0 0 0 0)", 0, 0, 0, 0);
102 CU_ASSERT_STRING_EQUAL(s,"01080300000000");
103
104 /* Point with bounding box */
105 cu_twkb("POINT(0 0)", 0, 0, 0, TWKB_BBOX);
106 CU_ASSERT_STRING_EQUAL(s,"0101000000000000");
107 // printf("TWKB: %s\n",s);
108
109 /* Adding a size paramters to X/Y */
110 cu_twkb("POINT(0 0)", 0, 0, 0, TWKB_SIZE);
111 CU_ASSERT_STRING_EQUAL(s,"0102020000");
112
113 /* Adding a size paramters to X/Y/M */
114 cu_twkb("POINTM(0 0 0)", 0, 0, 0, TWKB_SIZE);
115 CU_ASSERT_STRING_EQUAL(s,"010A0203000000");
116
117 /* Adding a size paramters to X/Y/Z/M */
118 cu_twkb("POINT(0 0 0 0)", 0, 0, 0, TWKB_SIZE);
119 CU_ASSERT_STRING_EQUAL(s,"010A030400000000");
120
121 /* Since the third dimension is Z it shall get a precision of 1 decimal (third argument) */
122 cu_twkb("POINTZ(1 1 1)", 0,1,2, 0);
123 CU_ASSERT_STRING_EQUAL(s,"010845020214");
124
125 /* Since the third dimension is M it shall get a precision of 2 decimals (fourth argument) */
126 cu_twkb("POINTM(1 1 1)", 0,1,2, 0);
127 // printf("\n%s\n", s);
128 CU_ASSERT_STRING_EQUAL(s,"0108460202C801");
129 }
130
test_twkb_out_linestring(void)131 static void test_twkb_out_linestring(void)
132 {
133
134 cu_twkb("LINESTRING(0 0,1 1)", 0, 0, 0, 0);
135 CU_ASSERT_STRING_EQUAL(s,"02000200000202");
136 // printf("TWKB: %s\n",s);
137
138 cu_twkb("LINESTRING(0 0 1,1 1 2,2 2 3)", 0, 0, 0, 0);
139 CU_ASSERT_STRING_EQUAL(s,"02080103000002020202020202");
140 // printf("TWKB: %s\n",s);
141
142 /* Line with bounding box */
143 cu_twkb("LINESTRING(0 0,1 1,2 2)", 0, 0, 0, TWKB_BBOX);
144 CU_ASSERT_STRING_EQUAL(s,"02010004000403000002020202");
145 // printf("TWKB: %s\n",s);
146
147 cu_twkb("LINESTRING EMPTY", 0, 0, 0, 0);
148 CU_ASSERT_STRING_EQUAL(s,"0210");
149 // printf("TWKB: %s\n",s);
150 }
151
test_twkb_out_polygon(void)152 static void test_twkb_out_polygon(void)
153 {
154 cu_twkb("SRID=4;POLYGON((0 0 0, 0 1 0,1 1 0,1 0 0, 0 0 0))", 0, 0, 0, 0);
155 CU_ASSERT_STRING_EQUAL(s,"0308010105000000000200020000000100010000");
156 // printf("TWKB: %s\n",s);
157
158 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);
159 CU_ASSERT_STRING_EQUAL(s,"03080301050000000200020002020000020001000201000002");
160 // printf("TWKB: %s\n",s);
161
162 cu_twkb("POLYGON EMPTY", 0, 0, 0, 0);
163 CU_ASSERT_STRING_EQUAL(s,"0310");
164 // printf("TWKB: %s\n",s);
165 }
166
test_twkb_out_multipoint(void)167 static void test_twkb_out_multipoint(void)
168 {
169 cu_twkb("MULTIPOINT(0 0 0, 0 1 0,1 1 0,1 0 0, 0 0 0)", 0, 0, 0, 0);
170 CU_ASSERT_STRING_EQUAL(s,"04080105000000000200020000000100010000");
171
172 cu_twkb("MULTIPOINT(0 0 0, 0.26794919243112270647255365849413 1 3)",7 ,7 , 0, 0);
173 //printf("WKB: %s",s);
174 CU_ASSERT_STRING_EQUAL(s,"E4081D02000000888BC70280DAC409808ECE1C");
175 // printf("TWKB: %s\n",s);
176 }
177
test_twkb_out_multilinestring(void)178 static void test_twkb_out_multilinestring(void) {}
179
test_twkb_out_multipolygon(void)180 static void test_twkb_out_multipolygon(void)
181 {
182 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);
183 CU_ASSERT_STRING_EQUAL(s,"060801020105000000000200020000000100010000020501010000060006000000050005000005020200000200020000000100010000");
184 }
185
test_twkb_out_collection(void)186 static void test_twkb_out_collection(void)
187 {
188 cu_twkb("GEOMETRYCOLLECTION(LINESTRING(1 1, 2 2), LINESTRING(3 3, 4 4), LINESTRING(5 5, 6 6))", 0, 0, 0, 0);
189 // printf("TWKB: %s\n",s);
190 CU_ASSERT_STRING_EQUAL(s,"07000302000202020202020002060602020200020A0A0202");
191
192 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);
193 // printf("TWKB: %s\n",s);
194 CU_ASSERT_STRING_EQUAL(s,"070801020308010105000000000200020000000100010000010801020202");
195
196 cu_twkb("GEOMETRYCOLLECTION EMPTY", 0, 0, 0, 0);
197 CU_ASSERT_STRING_EQUAL(s,"0710");
198 }
199
test_twkb_out_idlist(void)200 static void test_twkb_out_idlist(void)
201 {
202 int64_t idlist[2];
203
204 idlist[0] = 2;
205 idlist[1] = 4;
206 cu_twkb_idlist("MULTIPOINT(1 1, 0 0)",idlist, 0, 0, 0, 0);
207 // printf("TWKB: %s\n",s);
208 // printf("WKT: %s\n",w);
209 CU_ASSERT_STRING_EQUAL(s,"040402040802020101");
210 CU_ASSERT_STRING_EQUAL(w,"MULTIPOINT(1 1,0 0)");
211
212 /*
213 04 06 multipoint, size/idlist
214 07 size 7 bytes
215 02 two geometries
216 0408 idlist (2, 4)
217 0202 first point @ 1,1
218 0101 second point offset -1,-1
219 */
220 idlist[0] = 2;
221 idlist[1] = 4;
222 cu_twkb_idlist("MULTIPOINT(1 1, 0 0)",idlist, 0, 0, 0, TWKB_SIZE);
223 // printf("TWKB: %s\n",s);
224 // printf("WKT: %s\n",w);
225 CU_ASSERT_STRING_EQUAL(s,"04060702040802020101");
226 CU_ASSERT_STRING_EQUAL(w,"MULTIPOINT(1 1,0 0)");
227
228 /*
229 04 07 multipoint, bbox/size/idlist
230 0B size 11 bytes
231 00020002 bbox x(0,1), y(0,1)
232 02 two geometries
233 0408 idlist (2,4)
234 0202 first point @ 1,1
235 0101 seconds point offset -1,-1
236 */
237 idlist[0] = 2;
238 idlist[1] = 4;
239 cu_twkb_idlist("MULTIPOINT(1 1, 0 0)",idlist, 0, 0, 0, TWKB_SIZE | TWKB_BBOX);
240 // printf("TWKB: %s\n",s);
241 // printf("WKT: %s\n",w);
242 CU_ASSERT_STRING_EQUAL(s,"04070B0002000202040802020101");
243 CU_ASSERT_STRING_EQUAL(w,"MULTIPOINT(1 1,0 0)");
244
245 /*
246 0704 geometrycollection, idlist
247 02 two geometries
248 0408 idlist (2,4)
249 01000202 first point (type, meta, x, y)
250 01000000 second point (type, meta, x, y)
251 */
252 idlist[0] = 2;
253 idlist[1] = 4;
254 cu_twkb_idlist("GEOMETRYCOLLECTION(POINT(1 1),POINT(0 0))",idlist, 0, 0, 0, 0);
255 // printf("TWKB: %s\n",s);
256 CU_ASSERT_STRING_EQUAL(s,"07040204080100020201000000");
257 CU_ASSERT_STRING_EQUAL(w,"GEOMETRYCOLLECTION(POINT(1 1),POINT(0 0))");
258
259 /*
260 0706 geometrycollection, size/idlist
261 0D size, 13 bytes
262 02 two geometries
263 0408 idlist (2,4)
264 0102020202 first point (type, meta, size, x, y)
265 0102020000 second point (type, meta, size, x, y)
266 */
267 idlist[0] = 2;
268 idlist[1] = 4;
269 cu_twkb_idlist("GEOMETRYCOLLECTION(POINT(1 1),POINT(0 0))",idlist, 0, 0, 0, TWKB_SIZE);
270 // printf("TWKB: %s\n",s);
271 CU_ASSERT_STRING_EQUAL(s,"07060D02040801020202020102020000");
272 CU_ASSERT_STRING_EQUAL(w,"GEOMETRYCOLLECTION(POINT(1 1),POINT(0 0))");
273
274 }
275
276
277 /*
278 ** Used by test harness to register the tests in this file.
279 */
280 void twkb_out_suite_setup(void);
twkb_out_suite_setup(void)281 void twkb_out_suite_setup(void)
282 {
283 CU_pSuite suite = CU_add_suite("twkb_output", init_twkb_out_suite, clean_twkb_out_suite);
284 PG_ADD_TEST(suite, test_twkb_out_point);
285 PG_ADD_TEST(suite, test_twkb_out_linestring);
286 PG_ADD_TEST(suite, test_twkb_out_polygon);
287 PG_ADD_TEST(suite, test_twkb_out_multipoint);
288 PG_ADD_TEST(suite, test_twkb_out_multilinestring);
289 PG_ADD_TEST(suite, test_twkb_out_multipolygon);
290 PG_ADD_TEST(suite, test_twkb_out_collection);
291 PG_ADD_TEST(suite, test_twkb_out_idlist);
292 }
293