PostGIS  2.5.7dev-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  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 */
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 {
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 
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 
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 
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 
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 
178 static void test_twkb_out_multilinestring(void) {}
179 
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 
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 
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);
282 {
283  CU_pSuite suite = CU_add_suite("twkb_output", init_twkb_out_suite, clean_twkb_out_suite);
292 }
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:72
static void test_twkb_out_polygon(void)
Definition: cu_out_twkb.c:152
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:180
static char * w
Definition: cu_out_twkb.c:25
static void test_twkb_out_multipoint(void)
Definition: cu_out_twkb.c:167
void twkb_out_suite_setup(void)
Definition: cu_out_twkb.c:281
static void test_twkb_out_point(void)
Definition: cu_out_twkb.c:92
static char * s
Definition: cu_out_twkb.c:24
static void test_twkb_out_multilinestring(void)
Definition: cu_out_twkb.c:178
static void test_twkb_out_idlist(void)
Definition: cu_out_twkb.c:200
static void test_twkb_out_linestring(void)
Definition: cu_out_twkb.c:131
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:186
#define PG_ADD_TEST(suite, testfunc)
uint8_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, size_t *twkb_size)
Convert LWGEOM to a char* in TWKB format.
Definition: lwout_twkb.c:571
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1144
char * hexbytes_from_bytes(const uint8_t *bytes, size_t size)
Definition: lwout_wkb.c:39
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:2005
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:656
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an alloced string.
Definition: lwgeom.c:556
LWGEOM * lwgeom_from_wkt(const char *wkt, const char check)
Definition: lwin_wkt.c:904
#define TWKB_SIZE
Definition: liblwgeom.h:2084
#define TWKB_BBOX
Definition: liblwgeom.h:2083
uint8_t * lwgeom_to_twkb(const LWGEOM *geom, uint8_t variant, int8_t precision_xy, int8_t precision_z, int8_t precision_m, size_t *twkb_size)
Definition: lwout_twkb.c:618
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
void free(void *)
unsigned char uint8_t
Definition: uthash.h:79