1 #include <math.h>
2 #include <float.h>
3 #include "wkbtest.h"
4 
5 #define WKBZOFFSET 0x80000000
6 #define WKBMOFFSET 0x40000000
7 
8 
9 //  DO NOT USE THESE decoding function (except for debugging purposes)
10 //    The code is NOT maintained and is thrown together
11 
12 
13 // unsupported debugging function.
14 // given a wkb input thats a geometrycollection, returns its size and prints out
15 // its contents
16 //
17 //  Its really messy - dont even think about using this for anything
18 //
19 // you shouldnt call this function; just call decode_wkb() and it will
20 // call this function
21 
22 //#define DEBUG 1
23 
24 
25 
26 
27 void decode_wkb_collection(char *wkb,int	*size);
28 
swap_char(char * a,char * b)29 void swap_char(char	*a,char *b)
30 {
31 	char c;
32 
33 	c = *a;
34 	*a=*b;
35 	*b=c;
36 }
37 
38 
flip_endian_double(char * d)39 void	flip_endian_double(char 	*d)
40 {
41 	swap_char(d+7, d);
42 	swap_char(d+6, d+1);
43 	swap_char(d+5, d+2);
44 	swap_char(d+4, d+3);
45 }
46 
flip_endian_int32(char * i)47 void		flip_endian_int32(char		*i)
48 {
49 	swap_char (i+3,i);
50 	swap_char (i+2,i+1);
51 }
52 
53 
decode_wkb_collection(char * wkb,int * size)54 void decode_wkb_collection(char *wkb,int	*size)
55 {
56 	int	offset =0;
57 	bool	flipbytes;
58 	int	total_size=0,sub_size;
59 	int	numb_sub,t;
60 	bool	first_one = TRUE;
61 
62 	if (wkb[0] ==0 )  //big endian
63 	{
64 		if (BYTE_ORDER == LITTLE_ENDIAN)
65 			flipbytes= 1;
66 		else
67 			flipbytes= 0;
68 	}
69 	else //little
70 	{
71 		if (BYTE_ORDER == LITTLE_ENDIAN)
72 			flipbytes= 0;
73 		else
74 			flipbytes= 1;
75 	}
76 
77 	memcpy(&numb_sub, wkb+5,4);
78 	if (flipbytes)
79 		flip_endian_int32( (char *) & numb_sub) ;
80 
81 	printf("GEOMETRYCOLLECTION(\n");
82 	offset = 9;
83 	for (t=0; t<numb_sub; t++)
84 	{
85 		if (first_one)
86 		{
87 			first_one = FALSE;
88 		}
89 		else
90 		{
91 			printf(",");
92 		}
93 
94 		printf("	");
95 		decode_wkb( wkb + offset, &sub_size);
96 		total_size += sub_size;
97 		offset += sub_size;
98 	}
99 	*size = total_size +9 ;
100 	printf(")\n");
101 	return;
102 }
103 
104 //dump wkb to screen (for debugging)
105 // assume endian is constant though out structure
decode_wkb(char * wkb,int * size)106 void decode_wkb(char *wkb, int *size)
107 {
108 
109 	bool	flipbytes;
110 	uint32	type;
111 	uint32	n1,n2,n3,t,u,v;
112 	bool	is3d;
113 	bool	first_one,first_one2,first_one3;
114 
115 	int	offset,offset1;
116 	double	x,y,z;
117 	int	total_points;
118 
119 
120 
121 #if DEBUG
122 	printf("decoding wkb\n");
123 #endif
124 
125 
126 	if (wkb[0] ==0 )  //big endian
127 	{
128 		if (BYTE_ORDER == LITTLE_ENDIAN)
129 			flipbytes= 1;
130 		else
131 			flipbytes= 0;
132 	}
133 	else //little
134 	{
135 		if (BYTE_ORDER == LITTLE_ENDIAN)
136 			flipbytes= 0;
137 		else
138 			flipbytes= 1;
139 	}
140 
141 #if DEBUG
142 	printf("	+ flipbytes = %i\n", flipbytes);
143 #endif
144 
145 #if DEBUG
146 	printf("info about wkb:\n");
147 #endif
148 	memcpy(&type, wkb+1,4);
149 	if (flipbytes)
150 		flip_endian_int32( (char *) & type) ;
151 
152 	is3d = 0;
153 
154 	if (type&WKBZOFFSET)
155 	{
156 		is3d = 1;
157 		type = type&(~WKBZOFFSET);
158 	}
159 #if DEBUG
160 	printf("	Type = %i (is3d = %i)\n", type, is3d);
161 #endif
162 	if (type == 1)  //POINT()
163 	{
164 		printf("POINT(");
165 		if (is3d)
166 		{
167 			memcpy(&x, &wkb[5], 8);
168 			memcpy(&y, &wkb[5+8], 8);
169 			memcpy(&z, &wkb[5+16], 8);
170 			if (flipbytes)
171 			{
172 				flip_endian_double( (char *) & x) ;
173 				flip_endian_double( (char *) & y) ;
174 				flip_endian_double( (char *) & z) ;
175 			}
176 			printf("%g %g %g)",x,y,z );
177 		}
178 		else
179 		{
180 			memcpy(&x, &wkb[5], 8);
181 			memcpy(&y, &wkb[5+8], 8);
182 			if (flipbytes)
183 			{
184 				flip_endian_double( (char *) & x) ;
185 				flip_endian_double( (char *) & y) ;
186 			}
187 			printf("%g %g)", x,y);
188 		}
189 		printf("\n");
190 		if (is3d)
191 			*size = 29;
192 		else
193 			*size = 21;
194 		return;
195 
196 	}
197 	if (type == 2)
198 	{
199 		printf("LINESTRING(");
200 		memcpy(&n1, &wkb[5],4);
201 		if (flipbytes)
202 			flip_endian_int32( (char *) & n1) ;
203 		//	printf("  --- has %i sub points\n",n1);
204 		first_one = TRUE;
205 		for (t=0; t<n1; t++)
206 		{
207 			if (first_one)
208 			{
209 				first_one = FALSE;
210 			}
211 			else
212 			{
213 				printf(",");
214 			}
215 			if (is3d)
216 			{
217 				memcpy(&x, &wkb[9+t*24],8);
218 				memcpy(&y, &wkb[9+t*24+8],8);
219 				memcpy(&z, &wkb[9+t*24+16],8);
220 				if (flipbytes)
221 				{
222 					flip_endian_double( (char *) & x) ;
223 					flip_endian_double( (char *) & y) ;
224 					flip_endian_double( (char *) & z) ;
225 				}
226 				printf("%g %g %g",x,y,z);
227 			}
228 			else
229 			{
230 				memcpy(&x, &wkb[9+t*16],8);
231 				memcpy(&y, &wkb[9+t*16+8],8);
232 				if (flipbytes)
233 				{
234 					flip_endian_double( (char *) & x) ;
235 					flip_endian_double( (char *) & y) ;
236 				}
237 				printf("%g %g",x,y);
238 			}
239 		}
240 
241 
242 		printf(")\n");
243 		if (is3d)
244 			*size = 9 + n1*24;
245 		else
246 			*size = 9 + n1*16;
247 		return;
248 	}
249 	if (type == 3)
250 	{
251 		*size = 9;
252 		printf("POLYGON(");
253 		memcpy(&n1, &wkb[5],4);
254 		if (flipbytes)
255 			flip_endian_int32( (char *) & n1) ;
256 		//printf("  --- has %i rings\n",n1);
257 		*size += 4*n1;
258 		offset= 9;
259 		first_one = TRUE;
260 		for (u=0; u<n1; u++)
261 		{
262 			memcpy(&n2, &wkb[offset],4);
263 			if (flipbytes)
264 				flip_endian_int32( (char *) & n2) ;
265 			//	printf(" ring %i: has %i points\n",u,n2);
266 
267 
268 			if (first_one)
269 			{
270 				first_one = FALSE;
271 			}
272 			else
273 			{
274 				printf(",");
275 			}
276 			printf("(");
277 
278 			first_one2 = TRUE;
279 			for (v=0; v< n2; v++)
280 			{
281 				if (first_one2)
282 				{
283 					first_one2 = FALSE;
284 				}
285 				else
286 				{
287 					printf(",");
288 				}
289 				if (is3d)
290 				{
291 					memcpy(&x, &wkb[offset + 4+ v*24],8);
292 					memcpy(&y, &wkb[offset + 4+ v*24 + 8],8);
293 					memcpy(&z, &wkb[offset + 4+ v*24 + 16],8);
294 					if (flipbytes)
295 					{
296 						flip_endian_double( (char *) & x) ;
297 						flip_endian_double( (char *) & y) ;
298 						flip_endian_double( (char *) & z) ;
299 					}
300 					printf("%g %g %g",x,y,z);
301 
302 				}
303 				else
304 				{
305 					memcpy(&x, &wkb[offset +4 +v*16],8);
306 					memcpy(&y, &wkb[offset +4 +v*16 + 8],8);
307 					if (flipbytes)
308 					{
309 						flip_endian_double( (char *) & x) ;
310 						flip_endian_double( (char *) & y) ;
311 					}
312 					printf("%g %g",x,y);
313 
314 				}
315 			}
316 			if (is3d)
317 			{
318 				offset +=4 +24*n2;
319 				*size += n2*24;
320 			}
321 			else
322 			{
323 				offset += 4+ 16*n2;
324 				*size += n2*16;
325 			}
326 			printf(")");
327 		}
328 
329 		printf(")\n");
330 
331 		return;
332 
333 	}
334 	if (type == 4)
335 	{
336 		printf("MULTIPOINT(");
337 		memcpy(&n1,&wkb[5],4);
338 		if (flipbytes)
339 			flip_endian_int32( (char *) & n1) ;
340 		//	printf(" -- has %i points\n",n1);
341 		if (is3d)
342 			*size = 9 + n1*29;
343 		else
344 			*size = 9 + n1*21;
345 		first_one = TRUE;
346 		for (t=0; t<n1; t++)
347 		{
348 			if (first_one)
349 			{
350 				first_one= FALSE;
351 			}
352 			else
353 			{
354 				printf(",");
355 			}
356 			if (is3d)
357 			{
358 				memcpy(&x, &wkb[9+t*29+5],8);
359 				memcpy(&y, &wkb[9+t*29+8+5],8);
360 				memcpy(&z, &wkb[9+t*29+16+5],8);
361 				if (flipbytes)
362 				{
363 					flip_endian_double( (char *) & x) ;
364 					flip_endian_double( (char *) & y) ;
365 					flip_endian_double( (char *) & z) ;
366 				}
367 				printf("%g %g %g",x,y,z);
368 			}
369 			else
370 			{
371 				memcpy(&x, &wkb[9+t*21+5],8);
372 				memcpy(&y, &wkb[9+t*21+8+5],8);
373 				if (flipbytes)
374 				{
375 					flip_endian_double( (char *) & x) ;
376 					flip_endian_double( (char *) & y) ;
377 				}
378 				printf("%g %g",x,y);
379 			}
380 		}
381 		printf (")\n");
382 		return;
383 	}
384 	if (type == 5)
385 	{
386 		*size = 9;
387 		printf("MULTILINESTRING(");
388 		memcpy(&n2,&wkb[5],4);
389 		if (flipbytes)
390 			flip_endian_int32( (char *) & n2) ;
391 		//	printf(" -- has %i sub-lines\n",n2);
392 		*size += 9 *n2;
393 		offset =9;
394 		first_one2 = TRUE;
395 		for (u=0; u<n2; u++)
396 		{
397 			if (first_one2)
398 			{
399 				first_one2= FALSE;
400 			}
401 			else
402 			{
403 				printf(",");
404 			}
405 			printf("(");
406 			memcpy(&n1, &wkb[5 +offset],4);
407 			if (flipbytes)
408 				flip_endian_int32( (char *) & n1) ;
409 			//	printf("  --- has %i sub points\n",n1);
410 			first_one = TRUE;
411 			for (t=0; t<n1; t++)
412 			{
413 				if (first_one)
414 				{
415 					first_one= FALSE;
416 				}
417 				else
418 				{
419 					printf(",");
420 				}
421 
422 				if (is3d)
423 				{
424 					memcpy(&x, &wkb[offset+9+t*24],8);
425 					memcpy(&y, &wkb[offset+9+t*24+8],8);
426 					memcpy(&z, &wkb[offset+9+t*24+16],8);
427 					if (flipbytes)
428 					{
429 						flip_endian_double( (char *) & x) ;
430 						flip_endian_double( (char *) & y) ;
431 						flip_endian_double( (char *) & z) ;
432 					}
433 					printf("%g %g %g",x,y,z);
434 				}
435 				else
436 				{
437 					memcpy(&x, &wkb[offset+9+t*16],8);
438 					memcpy(&y, &wkb[offset+9+t*16+8],8);
439 					if (flipbytes)
440 					{
441 						flip_endian_double( (char *) & x) ;
442 						flip_endian_double( (char *) & y) ;
443 					}
444 					printf("%g %g",x,y);
445 				}
446 			}
447 			printf(")");
448 			if (is3d)
449 			{
450 				*size += (24*n1);
451 				offset += 9 + (24*n1);
452 			}
453 			else
454 			{
455 				*size += (16*n1);
456 				offset += 9 + (16*n1);
457 			}
458 		}
459 		printf(")\n");
460 		return;
461 
462 	}
463 	if (type == 6)
464 	{
465 		*size = 9;
466 		printf("MULTIPOLYGON(");
467 		memcpy(&n3,&wkb[5],4);
468 		if (flipbytes)
469 			flip_endian_int32( (char *) & n3) ;
470 		//printf(" -- has %i sub-poly\n",n3);
471 		*size += 9*n3;
472 		offset1 =9;//where polygon starts
473 		first_one3= TRUE;
474 		for (t=0; t<n3; t++) //for each polygon
475 		{
476 			if (first_one3)
477 			{
478 				first_one3= FALSE;
479 			}
480 			else
481 			{
482 				printf(",");
483 			}
484 			printf("(");
485 			//printf("polygon #%i\n",t);
486 			total_points = 0;
487 			memcpy(&n1,&wkb[offset1+5],4); //# rings
488 			*size += 4*n1;
489 			if (flipbytes)
490 				flip_endian_int32( (char *) & n1) ;
491 			//printf("This polygon has %i rings\n",n1);
492 			offset = offset1+9; //where linear rings are
493 			first_one = TRUE;
494 			for (u=0; u<n1; u++) //for each ring
495 			{
496 				if (first_one)
497 				{
498 					first_one= FALSE;
499 				}
500 				else
501 				{
502 					printf(",");
503 				}
504 				printf("(");
505 				memcpy(&n2, &wkb[offset],4);
506 				if (flipbytes)
507 					flip_endian_int32( (char *) & n2) ; //pts in linear ring
508 				//	printf(" ring %i: has %i points\n",u,n2);
509 				total_points += n2;
510 				first_one2 = TRUE;
511 				for (v=0; v< n2; v++)	//for each point
512 				{
513 					if (first_one2)
514 					{
515 						first_one2= FALSE;
516 					}
517 					else
518 					{
519 						printf(",");
520 					}
521 					if (is3d)
522 					{
523 						memcpy(&x, &wkb[offset + 4+ v*24],8);
524 						memcpy(&y, &wkb[offset + 4+ v*24 + 8],8);
525 						memcpy(&z, &wkb[offset + 4+ v*24 + 16],8);
526 						if (flipbytes)
527 						{
528 							flip_endian_double( (char *) & x) ;
529 							flip_endian_double( (char *) & y) ;
530 							flip_endian_double( (char *) & z) ;
531 						}
532 						printf("%g %g %g",x,y,z);
533 					}
534 					else
535 					{
536 						memcpy(&x, &wkb[offset +4 +v*16],8);
537 						memcpy(&y, &wkb[offset +4 +v*16 + 8],8);
538 						if (flipbytes)
539 						{
540 							flip_endian_double( (char *) & x) ;
541 							flip_endian_double( (char *) & y) ;
542 						}
543 						printf("%g %g",x,y);
544 					}
545 				}
546 				if (is3d)
547 				{
548 					*size += 24*n2;
549 					offset += 4+ 24*n2;
550 				}
551 				else
552 				{
553 					*size += 16*n2;
554 					offset += 4+ 16*n2;
555 				}
556 				printf(")");
557 			}
558 			printf(")");
559 			if (is3d)
560 				offset1 +=9 +24*total_points +4*n1;
561 			else
562 				offset1 += 9+ 16*total_points +4*n1;
563 		}
564 		printf(")\n");
565 		return;
566 	}
567 	if (type == 7)
568 	{
569 		return	decode_wkb_collection(wkb, size);
570 	}
571 
572 
573 
574 
575 }
576 
577 
578