geo_coder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. data/Gemfile +12 -0
  2. data/Gemfile.lock +32 -0
  3. data/History.txt +6 -0
  4. data/Makefile +13 -0
  5. data/Manifest.txt +18 -0
  6. data/README.rdoc +197 -0
  7. data/Rakefile +53 -0
  8. data/TODO.txt +8 -0
  9. data/VERSION +1 -0
  10. data/bin/build_indexes +8 -0
  11. data/bin/rebuild_cluster +22 -0
  12. data/bin/rebuild_metaphones +23 -0
  13. data/bin/tiger_import +59 -0
  14. data/demos/demo/app/ext/geocodewrap.rb +84 -0
  15. data/demos/demo/app/views/index.builder +13 -0
  16. data/demos/demo/app/views/index.erb +71 -0
  17. data/demos/demo/config.ru +12 -0
  18. data/demos/demo/config/bootstraps.rb +130 -0
  19. data/demos/demo/config/geoenvironment.rb +25 -0
  20. data/demos/demo/geocoder_helper.rb +12 -0
  21. data/demos/demo/geocom_geocode.rb +10 -0
  22. data/demos/demo/main.rb +3 -0
  23. data/demos/demo/rakefile.rb +17 -0
  24. data/demos/demo/tmp/restart.txt +0 -0
  25. data/demos/simpledemo/views/index.builder +13 -0
  26. data/demos/simpledemo/views/index.erb +69 -0
  27. data/demos/simpledemo/ws.rb +83 -0
  28. data/doc/Makefile +7 -0
  29. data/doc/html4css1.css +279 -0
  30. data/doc/lookup.rst +193 -0
  31. data/doc/parsing.rst +125 -0
  32. data/doc/voidspace.css +147 -0
  33. data/geo_coder.gemspec +172 -0
  34. data/lib/geocoder/us.rb +21 -0
  35. data/lib/geocoder/us/address.rb +290 -0
  36. data/lib/geocoder/us/constants.rb +670 -0
  37. data/lib/geocoder/us/database.rb +745 -0
  38. data/lib/geocoder/us/import.rb +181 -0
  39. data/lib/geocoder/us/import/tiger.rb +13 -0
  40. data/lib/geocoder/us/numbers.rb +58 -0
  41. data/navteq/README +4 -0
  42. data/navteq/convert.sql +37 -0
  43. data/navteq/navteq_import +39 -0
  44. data/navteq/prepare.sql +92 -0
  45. data/sql/cluster.sql +16 -0
  46. data/sql/convert.sql +80 -0
  47. data/sql/create.sql +37 -0
  48. data/sql/index.sql +12 -0
  49. data/sql/place.csv +104944 -0
  50. data/sql/place.sql +104948 -0
  51. data/sql/setup.sql +78 -0
  52. data/src/Makefile +13 -0
  53. data/src/README +14 -0
  54. data/src/liblwgeom/Makefile +75 -0
  55. data/src/liblwgeom/box2d.c +54 -0
  56. data/src/liblwgeom/lex.yy.c +4799 -0
  57. data/src/liblwgeom/liblwgeom.h +1405 -0
  58. data/src/liblwgeom/lwalgorithm.c +946 -0
  59. data/src/liblwgeom/lwalgorithm.h +52 -0
  60. data/src/liblwgeom/lwcircstring.c +759 -0
  61. data/src/liblwgeom/lwcollection.c +541 -0
  62. data/src/liblwgeom/lwcompound.c +118 -0
  63. data/src/liblwgeom/lwcurvepoly.c +86 -0
  64. data/src/liblwgeom/lwgeom.c +886 -0
  65. data/src/liblwgeom/lwgeom_api.c +2201 -0
  66. data/src/liblwgeom/lwgparse.c +1219 -0
  67. data/src/liblwgeom/lwgunparse.c +1054 -0
  68. data/src/liblwgeom/lwline.c +525 -0
  69. data/src/liblwgeom/lwmcurve.c +125 -0
  70. data/src/liblwgeom/lwmline.c +137 -0
  71. data/src/liblwgeom/lwmpoint.c +138 -0
  72. data/src/liblwgeom/lwmpoly.c +141 -0
  73. data/src/liblwgeom/lwmsurface.c +129 -0
  74. data/src/liblwgeom/lwpoint.c +439 -0
  75. data/src/liblwgeom/lwpoly.c +579 -0
  76. data/src/liblwgeom/lwsegmentize.c +1047 -0
  77. data/src/liblwgeom/lwutil.c +369 -0
  78. data/src/liblwgeom/measures.c +861 -0
  79. data/src/liblwgeom/postgis_config.h +93 -0
  80. data/src/liblwgeom/ptarray.c +847 -0
  81. data/src/liblwgeom/vsprintf.c +179 -0
  82. data/src/liblwgeom/wktparse.h +126 -0
  83. data/src/liblwgeom/wktparse.lex +74 -0
  84. data/src/liblwgeom/wktparse.tab.c +2353 -0
  85. data/src/liblwgeom/wktparse.tab.h +145 -0
  86. data/src/liblwgeom/wktparse.y +385 -0
  87. data/src/libsqlite3_geocoder/Makefile +22 -0
  88. data/src/libsqlite3_geocoder/Makefile.nix +15 -0
  89. data/src/libsqlite3_geocoder/Makefile.redhat +15 -0
  90. data/src/libsqlite3_geocoder/extension.c +121 -0
  91. data/src/libsqlite3_geocoder/extension.h +13 -0
  92. data/src/libsqlite3_geocoder/levenshtein.c +42 -0
  93. data/src/libsqlite3_geocoder/metaphon.c +278 -0
  94. data/src/libsqlite3_geocoder/util.c +37 -0
  95. data/src/libsqlite3_geocoder/wkb_compress.c +54 -0
  96. data/src/metaphone/Makefile +7 -0
  97. data/src/metaphone/README +49 -0
  98. data/src/metaphone/extension.c +37 -0
  99. data/src/metaphone/metaphon.c +251 -0
  100. data/src/shp2sqlite/Makefile +37 -0
  101. data/src/shp2sqlite/Makefile.nix +36 -0
  102. data/src/shp2sqlite/Makefile.redhat +35 -0
  103. data/src/shp2sqlite/dbfopen.c +1595 -0
  104. data/src/shp2sqlite/getopt.c +695 -0
  105. data/src/shp2sqlite/getopt.h +127 -0
  106. data/src/shp2sqlite/shapefil.h +500 -0
  107. data/src/shp2sqlite/shp2sqlite.c +1974 -0
  108. data/src/shp2sqlite/shpopen.c +1894 -0
  109. data/tests/address.rb +236 -0
  110. data/tests/benchmark.rb +20 -0
  111. data/tests/constants.rb +57 -0
  112. data/tests/data/address-sample.csv +52 -0
  113. data/tests/data/db-test.csv +57 -0
  114. data/tests/data/locations.csv +4 -0
  115. data/tests/database.rb +137 -0
  116. data/tests/generate.rb +34 -0
  117. data/tests/numbers.rb +46 -0
  118. data/tests/run.rb +11 -0
  119. metadata +237 -0
@@ -0,0 +1,1054 @@
1
+ /*
2
+ * Written by Ralph Mason ralph.mason<at>telogis.com
3
+ *
4
+ * Copyright Telogis 2004
5
+ * www.telogis.com
6
+ *
7
+ * $Id: lwgunparse.c 3639 2009-02-04 00:28:37Z pramsey $
8
+ */
9
+
10
+
11
+ #include <string.h>
12
+ #include <math.h>
13
+ #include <stdio.h>
14
+ /* TO get byte order */
15
+ #include <sys/types.h>
16
+ #include <sys/param.h>
17
+ /* Solaris9 does not provide stdint.h */
18
+ /* #include <stdint.h> */
19
+ #include <inttypes.h>
20
+
21
+ #include "liblwgeom.h"
22
+ #include "wktparse.h"
23
+
24
+
25
+ /*-- Typedefs ---------------------------------------------- */
26
+
27
+ typedef uint32_t int4;
28
+ typedef uchar* (*outfunc)(uchar*,int);
29
+ typedef uchar* (*outwkbfunc)(uchar*);
30
+
31
+ /*-- Prototypes -------------------------------------------- */
32
+
33
+ void ensure(int chars);
34
+ void to_end(void);
35
+ void write_str(const char* str);
36
+ void write_double(double val);
37
+ void write_int(int i);
38
+ int4 read_int(uchar** geom);
39
+ double read_double(uchar** geom);
40
+ uchar* output_point(uchar* geom,int supress);
41
+ uchar* output_single(uchar* geom,int supress);
42
+ uchar* output_collection(uchar* geom,outfunc func,int supress);
43
+ uchar* output_line_collection(uchar* geom,outfunc func,int supress);
44
+ uchar* output_polygon_collection(uchar* geom,int suppress);
45
+ uchar* output_polygon_ring_collection(uchar* geom,outfunc func,int supress);
46
+ uchar* output_circstring_collection(uchar* geom,outfunc func,int supress);
47
+ uchar* output_multipoint(uchar* geom,int suppress);
48
+ uchar* output_compound(uchar* geom, int suppress);
49
+ uchar* output_multisurface(uchar* geom, int suppress);
50
+
51
+ void write_wkb_hex_bytes(uchar* ptr, unsigned int cnt, size_t size);
52
+ void write_wkb_bin_bytes(uchar* ptr, unsigned int cnt, size_t size);
53
+ void write_wkb_bin_flip_bytes(uchar* ptr, unsigned int cnt, size_t size);
54
+ void write_wkb_hex_flip_bytes(uchar* ptr, unsigned int cnt, size_t size);
55
+
56
+ void write_wkb_int(int i);
57
+ uchar* output_wkb_collection(uchar* geom,outwkbfunc func);
58
+ uchar* output_wkb_polygon_collection(uchar* geom);
59
+ uchar* output_wkb_polygon_ring_collection(uchar* geom,outwkbfunc func);
60
+ uchar* output_wkb_line_collection(uchar* geom,outwkbfunc func);
61
+ uchar* output_wkb_circstring_collection(uchar* geom,outwkbfunc func);
62
+ uchar* output_wkb_point(uchar* geom);
63
+ uchar* output_wkb(uchar* geom);
64
+
65
+ /*-- Globals ----------------------------------------------- */
66
+
67
+ static int unparser_ferror_occured;
68
+ static int dims;
69
+ static allocator local_malloc;
70
+ static freeor local_free;
71
+ static char* out_start;
72
+ static char* out_pos;
73
+ static int len;
74
+ static int lwgi;
75
+ static uchar endianbyte;
76
+ void (*write_wkb_bytes)(uchar* ptr,unsigned int cnt,size_t size);
77
+
78
+ /*
79
+ * Unparser current instance check flags - a bitmap of flags that determine which checks are enabled during the current unparse
80
+ * (see liblwgeom.h for the related PARSER_CHECK constants)
81
+ */
82
+ int current_unparser_check_flags;
83
+
84
+ /*
85
+ * Unparser current instance result structure - the result structure being used for the current unparse
86
+ */
87
+ LWGEOM_UNPARSER_RESULT *current_lwg_unparser_result;
88
+
89
+ /*
90
+ * Unparser error messages
91
+ *
92
+ * IMPORTANT: Make sure the order of these messages matches the UNPARSER_ERROR constants in liblwgeom.h!
93
+ * The 0th element should always be empty since it is unused (error constants start from -1)
94
+ */
95
+
96
+ const char *unparser_error_messages[] = {
97
+ "",
98
+ "geometry requires more points",
99
+ "geometry must have an odd number of points",
100
+ "geometry contains non-closed rings"
101
+ };
102
+
103
+ /* Macro to return the error message and the current position within WKT */
104
+ #define LWGEOM_WKT_UNPARSER_ERROR(errcode) \
105
+ do { \
106
+ if (!unparser_ferror_occured) { \
107
+ unparser_ferror_occured = -1 * errcode; \
108
+ current_lwg_unparser_result->message = unparser_error_messages[errcode]; \
109
+ current_lwg_unparser_result->errlocation = (out_pos - out_start); \
110
+ } \
111
+ } while (0);
112
+
113
+ /* Macro to return the error message and the current position within WKB */
114
+ #define LWGEOM_WKB_UNPARSER_ERROR(errcode) \
115
+ do { \
116
+ if (!unparser_ferror_occured) { \
117
+ unparser_ferror_occured = -1 * errcode; \
118
+ current_lwg_unparser_result->message = unparser_error_messages[errcode]; \
119
+ current_lwg_unparser_result->errlocation = (out_pos - out_start); \
120
+ } \
121
+ } while (0);
122
+
123
+ /*---------------------------------------------------------- */
124
+
125
+
126
+
127
+
128
+
129
+
130
+ /*
131
+ * Ensure there is enough space for chars bytes.
132
+ * Reallocate memory is this is not the case.
133
+ */
134
+ void
135
+ ensure(int chars){
136
+
137
+ int pos = out_pos - out_start;
138
+
139
+ if ( (pos + chars) >= len ){
140
+ char* newp =(char*)local_malloc(len*2);
141
+ memcpy(newp,out_start,len);
142
+ local_free(out_start);
143
+ out_start = newp;
144
+ out_pos = newp + pos;
145
+ len *=2;
146
+ }
147
+ }
148
+
149
+ void
150
+ to_end(void)
151
+ {
152
+ while(*out_pos){
153
+ out_pos++;
154
+ }
155
+ }
156
+
157
+ void
158
+ write_str(const char* str)
159
+ {
160
+ ensure(32);
161
+ strcpy(out_pos,str);
162
+ to_end();
163
+ }
164
+
165
+ void
166
+ write_double(double val){
167
+ ensure(32);
168
+ if (lwgi)
169
+ sprintf(out_pos,"%.8g",val);
170
+ else
171
+ sprintf(out_pos,"%.15g",val);
172
+ to_end();
173
+ }
174
+
175
+ void
176
+ write_int(int i){
177
+ ensure(32);
178
+ sprintf(out_pos,"%i",i);
179
+ to_end();
180
+ }
181
+
182
+ int4
183
+ read_int(uchar** geom)
184
+ {
185
+ int4 ret;
186
+ #ifdef SHRINK_INTS
187
+ if ( getMachineEndian() == NDR ){
188
+ if( (**geom)& 0x01){
189
+ ret = **geom >>1;
190
+ (*geom)++;
191
+ return ret;
192
+ }
193
+ }
194
+ else{
195
+ if( (**geom)& 0x80){
196
+ ret = **geom & ~0x80;
197
+ (*geom)++;
198
+ return ret;
199
+ }
200
+ }
201
+ #endif
202
+ memcpy(&ret,*geom,4);
203
+
204
+ #ifdef SHRINK_INTS
205
+ if ( getMachineEndian() == NDR ){
206
+ ret >>= 1;
207
+ }
208
+ #endif
209
+
210
+ (*geom)+=4;
211
+ return ret;
212
+ }
213
+
214
+ double round(double);
215
+
216
+ double read_double(uchar** geom){
217
+ if (lwgi){
218
+ double ret = *((int4*)*geom);
219
+ ret /= 0xb60b60;
220
+ (*geom)+=4;
221
+ return ret-180.0;
222
+ }
223
+ else{
224
+ double ret;
225
+ memcpy(&ret, *geom, 8);
226
+ (*geom)+=8;
227
+ return ret;
228
+ }
229
+ }
230
+
231
+ uchar *
232
+ output_point(uchar* geom,int supress)
233
+ {
234
+ int i;
235
+
236
+ for( i = 0 ; i < dims ; i++ ){
237
+ write_double(read_double(&geom));
238
+ if (i +1 < dims )
239
+ write_str(" ");
240
+ }
241
+ return geom;
242
+ }
243
+
244
+ uchar *
245
+ output_single(uchar* geom,int supress)
246
+ {
247
+ write_str("(");
248
+ geom=output_point(geom,supress);
249
+ write_str(")");
250
+ return geom;
251
+ }
252
+
253
+ /* Output a standard collection */
254
+ uchar *
255
+ output_collection(uchar* geom,outfunc func,int supress)
256
+ {
257
+ int cnt = read_int(&geom);
258
+ if ( cnt == 0 ){
259
+ write_str(" EMPTY");
260
+ }
261
+ else{
262
+ write_str("(");
263
+ while(cnt--){
264
+ geom=func(geom,supress);
265
+ if ( cnt ){
266
+ write_str(",");
267
+ }
268
+ }
269
+ write_str(")");
270
+ }
271
+ return geom;
272
+ }
273
+
274
+ /* Output a set of LINESTRING points */
275
+ uchar *
276
+ output_line_collection(uchar* geom,outfunc func,int supress)
277
+ {
278
+ int cnt = read_int(&geom);
279
+ int orig_cnt = cnt;
280
+
281
+ if ( cnt == 0 ){
282
+ write_str(" EMPTY");
283
+ }
284
+ else{
285
+ write_str("(");
286
+ while(cnt--){
287
+ geom=func(geom,supress);
288
+ if ( cnt ){
289
+ write_str(",");
290
+ }
291
+ }
292
+ write_str(")");
293
+ }
294
+
295
+ /* Ensure that LINESTRING has a minimum of 2 points */
296
+ if ((current_unparser_check_flags & PARSER_CHECK_MINPOINTS) && orig_cnt < 2)
297
+ LWGEOM_WKT_UNPARSER_ERROR(UNPARSER_ERROR_MOREPOINTS);
298
+
299
+ return geom;
300
+ }
301
+
302
+ /* Output an individual ring from a POLYGON */
303
+ uchar *
304
+ output_polygon_ring_collection(uchar* geom,outfunc func,int supress)
305
+ {
306
+ uchar *temp;
307
+ int dimcount;
308
+ double first_point[dims];
309
+ double last_point[dims];
310
+
311
+ int cnt = read_int(&geom);
312
+ int orig_cnt = cnt;
313
+ if ( cnt == 0 ){
314
+ write_str(" EMPTY");
315
+ }
316
+ else{
317
+ write_str("(");
318
+
319
+ /* Store the first point of the ring (use a temp var since read_double alters
320
+ the pointer after use) */
321
+ temp = geom;
322
+ dimcount = 0;
323
+ while (dimcount < dims)
324
+ {
325
+ first_point[dimcount] = read_double(&temp);
326
+ dimcount++;
327
+ }
328
+
329
+ while(cnt--){
330
+ geom=func(geom,supress);
331
+ if ( cnt ){
332
+ write_str(",");
333
+ }
334
+ }
335
+ write_str(")");
336
+
337
+ /* Store the last point of the ring (note: we will have moved past it, so we
338
+ need to count backwards) */
339
+ temp = geom - sizeof(double) * dims;
340
+ dimcount = 0;
341
+ while (dimcount < dims)
342
+ {
343
+ last_point[dimcount] = read_double(&temp);
344
+ dimcount++;
345
+ }
346
+
347
+ /* Check if they are the same... */
348
+ if (memcmp(&first_point, &last_point, sizeof(double) * dims) &&
349
+ (current_unparser_check_flags & PARSER_CHECK_CLOSURE))
350
+ LWGEOM_WKT_UNPARSER_ERROR(UNPARSER_ERROR_UNCLOSED);
351
+
352
+ /* Ensure that POLYGON has a minimum of 4 points */
353
+ if ((current_unparser_check_flags & PARSER_CHECK_MINPOINTS) && orig_cnt < 4)
354
+ LWGEOM_WKT_UNPARSER_ERROR(UNPARSER_ERROR_MOREPOINTS);
355
+ }
356
+ return geom;
357
+ }
358
+
359
+ /* Ouput the points from a CIRCULARSTRING */
360
+ uchar *
361
+ output_circstring_collection(uchar* geom,outfunc func,int supress)
362
+ {
363
+ int cnt = read_int(&geom);
364
+ int orig_cnt = cnt;
365
+
366
+ if ( cnt == 0 ){
367
+ write_str(" EMPTY");
368
+ }
369
+ else{
370
+ write_str("(");
371
+ while(cnt--){
372
+ geom=func(geom,supress);
373
+ if ( cnt ){
374
+ write_str(",");
375
+ }
376
+ }
377
+ write_str(")");
378
+ }
379
+
380
+ /* Ensure that a CIRCULARSTRING has a minimum of 3 points */
381
+ if ((current_unparser_check_flags & PARSER_CHECK_MINPOINTS) && orig_cnt < 3) {
382
+ LWGEOM_WKT_UNPARSER_ERROR(UNPARSER_ERROR_MOREPOINTS);
383
+ }
384
+
385
+ /* Ensure that a CIRCULARSTRING has an odd number of points */
386
+ if ((current_unparser_check_flags & PARSER_CHECK_ODD) && orig_cnt % 2 != 1) {
387
+ LWGEOM_WKT_UNPARSER_ERROR(UNPARSER_ERROR_ODDPOINTS);
388
+ }
389
+
390
+ return geom;
391
+ }
392
+
393
+ /* Output a POLYGON consisting of a number of rings */
394
+ uchar *
395
+ output_polygon_collection(uchar* geom,int suppress)
396
+ {
397
+ return output_polygon_ring_collection(geom,output_point,suppress);
398
+ }
399
+
400
+ uchar *output_wkt(uchar* geom, int supress);
401
+
402
+ /* special case for multipoint to supress extra brackets */
403
+ uchar *output_multipoint(uchar* geom,int suppress){
404
+ unsigned char type = *geom & 0x0f;
405
+
406
+ if ( type == POINTTYPE )
407
+ return output_point(++geom,suppress);
408
+ else if ( type == POINTTYPEI ){
409
+ lwgi++;
410
+ geom=output_point(++geom,0);
411
+ lwgi--;
412
+ return geom;
413
+ }
414
+
415
+ return output_wkt(geom,suppress);
416
+ }
417
+
418
+ /* Special case for compound curves: suppress the LINESTRING prefix from a curve if it appears as
419
+ a component of a COMPOUNDCURVE, but not CIRCULARSTRING */
420
+ uchar *output_compound(uchar* geom, int suppress) {
421
+ unsigned char type;
422
+
423
+ LWDEBUG(2, "output_compound called.");
424
+
425
+ type=*geom;
426
+ switch(TYPE_GETTYPE(type))
427
+ {
428
+ case LINETYPE:
429
+ geom = output_wkt(geom,2);
430
+ break;
431
+ case CIRCSTRINGTYPE:
432
+ geom = output_wkt(geom,1);
433
+ break;
434
+ }
435
+ return geom;
436
+ }
437
+
438
+ /* Special case for multisurfaces: suppress the POLYGON prefix from a surface if it appears as
439
+ a component of a MULTISURFACE, but not CURVEPOLYGON */
440
+ uchar *output_multisurface(uchar* geom, int suppress) {
441
+ unsigned char type;
442
+
443
+ LWDEBUG(2, "output_multisurface called.");
444
+
445
+ type=*geom;
446
+ switch(TYPE_GETTYPE(type))
447
+ {
448
+ case POLYGONTYPE:
449
+ geom = output_wkt(geom,2);
450
+ break;
451
+ case CURVEPOLYTYPE:
452
+ geom = output_wkt(geom,1);
453
+ break;
454
+ }
455
+ return geom;
456
+ }
457
+
458
+ /*
459
+ * Suppress=0 -- write TYPE, M, coords
460
+ * Suppress=1 -- write TYPE, coords
461
+ * Suppress=2 -- write only coords
462
+ */
463
+ uchar *
464
+ output_wkt(uchar* geom, int supress)
465
+ {
466
+
467
+ unsigned char type=*geom++;
468
+ char writeM=0;
469
+ dims = TYPE_NDIMS(type); /* ((type & 0x30) >> 4)+2; */
470
+
471
+ LWDEBUG(2, "output_wkt called.");
472
+
473
+ if ( ! supress && !TYPE_HASZ(type) && TYPE_HASM(type) ) writeM=1;
474
+
475
+
476
+ /* Skip the bounding box if there is one */
477
+ if ( TYPE_HASBBOX(type) )
478
+ {
479
+ geom+=16;
480
+ }
481
+
482
+ if ( TYPE_HASSRID(type) ) {
483
+ write_str("SRID=");write_int(read_int(&geom));write_str(";");
484
+ }
485
+
486
+ switch(TYPE_GETTYPE(type)) {
487
+ case POINTTYPE:
488
+ if ( supress < 2 )
489
+ {
490
+ if (writeM) write_str("POINTM");
491
+ else write_str("POINT");
492
+ }
493
+ geom=output_single(geom,0);
494
+ break;
495
+ case LINETYPE:
496
+ if ( supress < 2 )
497
+ {
498
+ if (writeM) write_str("LINESTRINGM");
499
+ else write_str("LINESTRING");
500
+ }
501
+ geom = output_line_collection(geom,output_point,0);
502
+ break;
503
+ case CIRCSTRINGTYPE:
504
+ if ( supress < 2 )
505
+ {
506
+ if(writeM) write_str("CIRCULARSTRINGM");
507
+ else write_str("CIRCULARSTRING");
508
+ }
509
+ geom = output_circstring_collection(geom,output_point,0);
510
+ break;
511
+ case POLYGONTYPE:
512
+ if ( supress < 2 )
513
+ {
514
+ if (writeM) write_str("POLYGONM");
515
+ else write_str("POLYGON");
516
+ }
517
+ geom = output_collection(geom,output_polygon_collection,0);
518
+ break;
519
+ case COMPOUNDTYPE:
520
+ if ( supress < 2 )
521
+ {
522
+ if (writeM) write_str("COMPOUNDCURVEM");
523
+ else write_str("COMPOUNDCURVE");
524
+ }
525
+ geom = output_collection(geom, output_compound,1);
526
+ break;
527
+ case CURVEPOLYTYPE:
528
+ if (supress < 2)
529
+ {
530
+ if(writeM) write_str("CURVEPOLYGONM");
531
+ else write_str("CURVEPOLYGON");
532
+ }
533
+ geom = output_collection(geom, output_compound,0);
534
+ break;
535
+ case MULTIPOINTTYPE:
536
+ if ( supress < 2 )
537
+ {
538
+ if (writeM) write_str("MULTIPOINTM");
539
+ else write_str("MULTIPOINT");
540
+ }
541
+ geom = output_collection(geom,output_multipoint,2);
542
+ break;
543
+ case MULTILINETYPE:
544
+ if ( supress < 2 )
545
+ {
546
+ if (writeM) write_str("MULTILINESTRINGM");
547
+ else write_str("MULTILINESTRING");
548
+ }
549
+ geom = output_collection(geom,output_wkt,2);
550
+ break;
551
+ case MULTICURVETYPE:
552
+ if ( supress < 2 )
553
+ {
554
+ if (writeM) write_str("MULTICURVEM");
555
+ else write_str("MULTICURVE");
556
+ }
557
+ geom = output_collection(geom,output_compound,2);
558
+ break;
559
+ case MULTIPOLYGONTYPE:
560
+ if ( supress < 2 )
561
+ {
562
+ if (writeM) write_str("MULTIPOLYGONM");
563
+ else write_str("MULTIPOLYGON");
564
+ }
565
+ geom = output_collection(geom,output_wkt,2);
566
+ break;
567
+ case MULTISURFACETYPE:
568
+ if ( supress < 2)
569
+ {
570
+ if (writeM) write_str("MULTISURFACEM");
571
+ else write_str("MULTISURFACE");
572
+ }
573
+ geom = output_collection(geom,output_multisurface,2);
574
+ break;
575
+ case COLLECTIONTYPE:
576
+ if ( supress < 2 )
577
+ {
578
+ if (writeM) write_str("GEOMETRYCOLLECTIONM");
579
+ else write_str("GEOMETRYCOLLECTION");
580
+ }
581
+ geom = output_collection(geom,output_wkt,1);
582
+ break;
583
+
584
+ case POINTTYPEI:
585
+ if ( supress < 2 )
586
+ {
587
+ if (writeM) write_str("POINTM");
588
+ else write_str("POINT");
589
+ }
590
+ lwgi++;
591
+ geom=output_single(geom,0);
592
+ lwgi--;
593
+ break;
594
+ case LINETYPEI:
595
+ if ( supress < 2 )
596
+ {
597
+ if (writeM) write_str("LINESTRINGM");
598
+ else write_str("LINESTRING");
599
+ }
600
+ lwgi++;
601
+ geom = output_collection(geom,output_point,0);
602
+ lwgi--;
603
+ break;
604
+ case POLYGONTYPEI:
605
+ if ( supress < 2 )
606
+ {
607
+ if (writeM) write_str("POLYGONM");
608
+ else write_str("POLYGON");
609
+ }
610
+ lwgi++;
611
+ geom = output_collection(geom,output_polygon_collection,0);
612
+ lwgi--;
613
+ break;
614
+ }
615
+ return geom;
616
+ }
617
+
618
+ int
619
+ unparse_WKT(LWGEOM_UNPARSER_RESULT *lwg_unparser_result, uchar* serialized, allocator alloc, freeor free, int flags)
620
+ {
621
+
622
+ LWDEBUGF(2, "unparse_WKT called with parser flags %d.", flags);
623
+
624
+ if (serialized==NULL)
625
+ return 0;
626
+
627
+ /* Setup the inital parser flags and empty the return struct */
628
+ current_lwg_unparser_result = lwg_unparser_result;
629
+ current_unparser_check_flags = flags;
630
+ lwg_unparser_result->wkoutput = NULL;
631
+ lwg_unparser_result->size = 0;
632
+ lwg_unparser_result->serialized_lwgeom = serialized;
633
+
634
+ unparser_ferror_occured = 0;
635
+ local_malloc=alloc;
636
+ local_free=free;
637
+ len = 128;
638
+ out_start = out_pos = alloc(len);
639
+ lwgi=0;
640
+
641
+ output_wkt(serialized, 0);
642
+
643
+ /* Store the result in the struct */
644
+ lwg_unparser_result->wkoutput = out_start;
645
+ lwg_unparser_result->size = strlen(out_start);
646
+
647
+ return unparser_ferror_occured;
648
+ }
649
+
650
+ static char outchr[]={"0123456789ABCDEF" };
651
+
652
+ /* Write HEX bytes flipping */
653
+ void
654
+ write_wkb_hex_flip_bytes(uchar* ptr, unsigned int cnt, size_t size)
655
+ {
656
+ unsigned int bc; /* byte count */
657
+
658
+ ensure(cnt*2*size);
659
+
660
+ while(cnt--){
661
+ for(bc=size; bc; bc--)
662
+ {
663
+ *out_pos++ = outchr[ptr[bc-1]>>4];
664
+ *out_pos++ = outchr[ptr[bc-1]&0x0F];
665
+ }
666
+ ptr+=size;
667
+ }
668
+ }
669
+
670
+ /* Write HEX bytes w/out flipping */
671
+ void
672
+ write_wkb_hex_bytes(uchar* ptr, unsigned int cnt, size_t size)
673
+ {
674
+ unsigned int bc; /* byte count */
675
+
676
+ ensure(cnt*2*size);
677
+
678
+ while(cnt--){
679
+ for(bc=0; bc<size; bc++)
680
+ {
681
+ *out_pos++ = outchr[ptr[bc]>>4];
682
+ *out_pos++ = outchr[ptr[bc]&0x0F];
683
+ }
684
+ ptr+=size;
685
+ }
686
+ }
687
+
688
+ /* Write BIN bytes flipping */
689
+ void
690
+ write_wkb_bin_flip_bytes(uchar* ptr, unsigned int cnt, size_t size)
691
+ {
692
+ unsigned int bc; /* byte count */
693
+
694
+ ensure(cnt*size);
695
+
696
+ while(cnt--)
697
+ {
698
+ for(bc=size; bc; bc--)
699
+ *out_pos++ = ptr[bc-1];
700
+ ptr+=size;
701
+ }
702
+ }
703
+
704
+
705
+ /* Write BIN bytes w/out flipping */
706
+ void
707
+ write_wkb_bin_bytes(uchar* ptr, unsigned int cnt, size_t size)
708
+ {
709
+ unsigned int bc; /* byte count */
710
+
711
+ ensure(cnt*size);
712
+
713
+ /* Could just use a memcpy here ... */
714
+ while(cnt--)
715
+ {
716
+ for(bc=0; bc<size; bc++)
717
+ *out_pos++ = ptr[bc];
718
+ ptr+=size;
719
+ }
720
+ }
721
+
722
+ uchar *
723
+ output_wkb_point(uchar* geom)
724
+ {
725
+ if ( lwgi ){
726
+ write_wkb_bytes(geom,dims,4);
727
+ return geom + (4*dims);
728
+ }
729
+ else{
730
+ write_wkb_bytes(geom,dims,8);
731
+ return geom + (8*dims);
732
+ }
733
+ }
734
+
735
+ void
736
+ write_wkb_int(int i){
737
+ write_wkb_bytes((uchar*)&i,1,4);
738
+ }
739
+
740
+ /* Output a standard collection */
741
+ uchar *
742
+ output_wkb_collection(uchar* geom,outwkbfunc func)
743
+ {
744
+ int cnt = read_int(&geom);
745
+
746
+ LWDEBUGF(2, "output_wkb_collection: %d iterations loop", cnt);
747
+
748
+ write_wkb_int(cnt);
749
+ while(cnt--) geom=func(geom);
750
+ return geom;
751
+ }
752
+
753
+ /* Output a set of LINESTRING points */
754
+ uchar *
755
+ output_wkb_line_collection(uchar* geom,outwkbfunc func)
756
+ {
757
+ int cnt = read_int(&geom);
758
+ int orig_cnt = cnt;
759
+
760
+ LWDEBUGF(2, "output_wkb_line_collection: %d iterations loop", cnt);
761
+
762
+ write_wkb_int(cnt);
763
+ while(cnt--) geom=func(geom);
764
+
765
+ /* Ensure that LINESTRING has a minimum of 2 points */
766
+ if ((current_unparser_check_flags & PARSER_CHECK_MINPOINTS) && orig_cnt < 2) {
767
+ LWGEOM_WKB_UNPARSER_ERROR(UNPARSER_ERROR_MOREPOINTS);
768
+ }
769
+
770
+ return geom;
771
+ }
772
+
773
+ /* Output an individual ring from a POLYGON */
774
+ uchar *
775
+ output_wkb_polygon_ring_collection(uchar* geom,outwkbfunc func)
776
+ {
777
+ uchar *temp;
778
+ int dimcount;
779
+ double first_point[dims];
780
+ double last_point[dims];
781
+
782
+ int cnt = read_int(&geom);
783
+ int orig_cnt = cnt;
784
+
785
+ LWDEBUGF(2, "output_wkb_polygon_ring_collection: %d iterations loop", cnt);
786
+
787
+ write_wkb_int(cnt);
788
+
789
+ /* Store the first point of the ring (use a temp var since read_double alters
790
+ the pointer after use) */
791
+ temp = geom;
792
+ dimcount = 0;
793
+ while (dimcount < dims)
794
+ {
795
+ first_point[dimcount] = read_double(&temp);
796
+ dimcount++;
797
+ }
798
+
799
+ while(cnt--) geom=func(geom);
800
+
801
+ /* Store the last point of the ring (note: we will have moved past it, so we
802
+ need to count backwards) */
803
+ temp = geom - sizeof(double) * dims;
804
+ dimcount = 0;
805
+ while (dimcount < dims)
806
+ {
807
+ last_point[dimcount] = read_double(&temp);
808
+ dimcount++;
809
+ }
810
+
811
+ /* Check if they are the same... */
812
+ if (memcmp(&first_point, &last_point, sizeof(double) * dims) &&
813
+ (current_unparser_check_flags & PARSER_CHECK_CLOSURE)) {
814
+ LWGEOM_WKB_UNPARSER_ERROR(UNPARSER_ERROR_UNCLOSED);
815
+ }
816
+
817
+ /* Ensure that POLYGON has a minimum of 4 points */
818
+ if ((current_unparser_check_flags & PARSER_CHECK_MINPOINTS) && orig_cnt < 4)
819
+ LWGEOM_WKT_UNPARSER_ERROR(UNPARSER_ERROR_MOREPOINTS);
820
+
821
+ return geom;
822
+ }
823
+
824
+ /* Output a POLYGON consisting of a number of rings */
825
+ uchar *
826
+ output_wkb_polygon_collection(uchar* geom)
827
+ {
828
+ LWDEBUG(2, "output_wkb_polygon_collection");
829
+
830
+ return output_wkb_polygon_ring_collection(geom,output_wkb_point);
831
+ }
832
+
833
+ /* Ouput the points from a CIRCULARSTRING */
834
+ uchar *
835
+ output_wkb_circstring_collection(uchar* geom,outwkbfunc func)
836
+ {
837
+ int cnt = read_int(&geom);
838
+ int orig_cnt = cnt;
839
+
840
+ LWDEBUGF(2, "output_wkb_curve_collection: %d iterations loop", cnt);
841
+
842
+ write_wkb_int(cnt);
843
+ while(cnt--) geom=func(geom);
844
+
845
+ /* Ensure that a CIRCULARSTRING has a minimum of 3 points */
846
+ if ((current_unparser_check_flags & PARSER_CHECK_MINPOINTS) && orig_cnt < 3) {
847
+ LWGEOM_WKB_UNPARSER_ERROR(UNPARSER_ERROR_MOREPOINTS);
848
+ }
849
+
850
+ /* Ensure that a CIRCULARSTRING has an odd number of points */
851
+ if ((current_unparser_check_flags & PARSER_CHECK_ODD) && orig_cnt % 2 != 1) {
852
+ LWGEOM_WKB_UNPARSER_ERROR(UNPARSER_ERROR_ODDPOINTS);
853
+ }
854
+
855
+ return geom;
856
+ }
857
+
858
+ uchar *
859
+ output_wkb(uchar* geom)
860
+ {
861
+ unsigned char type=*geom++;
862
+ int4 wkbtype;
863
+
864
+ dims = TYPE_NDIMS(type);
865
+
866
+ LWDEBUGF(2, "output_wkb: dims set to %d", dims);
867
+
868
+ /* Skip the bounding box */
869
+ if ( TYPE_HASBBOX(type) ) {
870
+ geom+=16;
871
+ }
872
+
873
+ wkbtype = TYPE_GETTYPE(type);
874
+
875
+ if ( TYPE_HASZ(type) )
876
+ wkbtype |= WKBZOFFSET;
877
+ if ( TYPE_HASM(type) )
878
+ wkbtype |= WKBMOFFSET;
879
+ if ( TYPE_HASSRID(type) ) {
880
+ wkbtype |= WKBSRIDFLAG;
881
+ }
882
+
883
+
884
+ /* Write byteorder (as from WKB specs...) */
885
+ write_wkb_bytes(&endianbyte,1,1);
886
+
887
+ write_wkb_int(wkbtype);
888
+
889
+ if ( TYPE_HASSRID(type) ) {
890
+ write_wkb_int(read_int(&geom));
891
+ }
892
+
893
+ switch(TYPE_GETTYPE(type)){
894
+ case POINTTYPE:
895
+ geom=output_wkb_point(geom);
896
+ break;
897
+ case LINETYPE:
898
+ geom=output_wkb_line_collection(geom,output_wkb_point);
899
+ break;
900
+ case CIRCSTRINGTYPE:
901
+ geom=output_wkb_circstring_collection(geom,output_wkb_point);
902
+ break;
903
+ case POLYGONTYPE:
904
+ geom=output_wkb_collection(geom,output_wkb_polygon_collection);
905
+ break;
906
+ case COMPOUNDTYPE:
907
+ geom=output_wkb_collection(geom,output_wkb);
908
+ break;
909
+ case CURVEPOLYTYPE:
910
+ geom=output_wkb_collection(geom,output_wkb);
911
+ break;
912
+ case MULTICURVETYPE:
913
+ case MULTISURFACETYPE:
914
+ case MULTIPOINTTYPE:
915
+ case MULTILINETYPE:
916
+ case MULTIPOLYGONTYPE:
917
+ case COLLECTIONTYPE:
918
+ geom = output_wkb_collection(geom,output_wkb);
919
+ break;
920
+
921
+ /*
922
+ These don't output standard wkb at the moment
923
+ the output and integer version.
924
+
925
+ however you could run it through the wkt parser
926
+ for a lwg and then output that. There should
927
+ also be a force_to_real_(lwgi)
928
+ */
929
+ case POINTTYPEI:
930
+ lwgi++;
931
+ geom=output_wkb_point(geom);
932
+ lwgi--;
933
+ break;
934
+ case LINETYPEI:
935
+ lwgi++;
936
+ geom = output_wkb_collection(geom,output_wkb_point);
937
+ lwgi--;
938
+ break;
939
+ case POLYGONTYPEI:
940
+ lwgi++;
941
+ geom = output_wkb_collection(geom,output_wkb_polygon_collection);
942
+ lwgi--;
943
+ break;
944
+ }
945
+ return geom;
946
+ }
947
+
948
+ int
949
+ unparse_WKB(LWGEOM_UNPARSER_RESULT *lwg_unparser_result, uchar* serialized, allocator alloc, freeor free, int flags, char endian, uchar hex)
950
+ {
951
+ LWDEBUGF(2, "unparse_WKB(%p,...) called with parser flags %d", serialized, flags);
952
+
953
+ if (serialized==0)
954
+ return 0;
955
+
956
+ /* Setup the inital parser flags and empty the return struct */
957
+ current_lwg_unparser_result = lwg_unparser_result;
958
+ current_unparser_check_flags = flags;
959
+ lwg_unparser_result->wkoutput = NULL;
960
+ lwg_unparser_result->size = 0;
961
+ lwg_unparser_result->serialized_lwgeom = serialized;
962
+
963
+ unparser_ferror_occured = 0;
964
+ local_malloc=alloc;
965
+ local_free=free;
966
+ len = 128;
967
+ out_start = out_pos = alloc(len);
968
+ lwgi=0;
969
+
970
+ if ( endian == (char)-1 )
971
+ {
972
+ endianbyte = getMachineEndian();
973
+ if ( hex ) write_wkb_bytes = write_wkb_hex_bytes;
974
+ else write_wkb_bytes = write_wkb_bin_bytes;
975
+ }
976
+ else
977
+ {
978
+ endianbyte = endian;
979
+ if ( endianbyte != getMachineEndian() )
980
+ {
981
+ if ( hex ) write_wkb_bytes = write_wkb_hex_flip_bytes;
982
+ else write_wkb_bytes = write_wkb_bin_flip_bytes;
983
+ }
984
+ else
985
+ {
986
+ if ( hex ) write_wkb_bytes = write_wkb_hex_bytes;
987
+ else write_wkb_bytes = write_wkb_bin_bytes;
988
+ }
989
+ }
990
+
991
+ output_wkb(serialized);
992
+
993
+ if ( hex ) {
994
+ ensure(1);
995
+ *out_pos=0;
996
+ }
997
+
998
+ /* Store the result in the struct */
999
+ lwg_unparser_result->wkoutput = out_start;
1000
+ lwg_unparser_result->size = (out_pos-out_start);
1001
+
1002
+ return unparser_ferror_occured;
1003
+ }
1004
+
1005
+
1006
+ /******************************************************************
1007
+ * $Log$
1008
+ * Revision 1.23 2006/02/06 11:12:22 strk
1009
+ * uint32_t typedef moved back from wktparse.h to lwgparse.c and wktunparse.c
1010
+ *
1011
+ * Revision 1.22 2006/02/03 20:53:37 strk
1012
+ * Swapped stdint.h (unavailable on Solaris9) with inttypes.h
1013
+ *
1014
+ * Revision 1.21 2006/02/03 09:52:14 strk
1015
+ * Changed int4 typedefs to use POSIX uint32_t
1016
+ *
1017
+ * Revision 1.20 2006/01/09 15:12:02 strk
1018
+ * ISO C90 comments
1019
+ *
1020
+ * Revision 1.19 2005/03/10 18:19:16 strk
1021
+ * Made void args explicit to make newer compilers happy
1022
+ *
1023
+ * Revision 1.18 2005/02/21 16:16:14 strk
1024
+ * Changed byte to uchar to avoid clashes with win32 headers.
1025
+ *
1026
+ * Revision 1.17 2005/02/07 13:21:10 strk
1027
+ * Replaced DEBUG* macros with PGIS_DEBUG*, to avoid clashes with postgresql DEBUG
1028
+ *
1029
+ * Revision 1.16 2005/01/18 09:32:03 strk
1030
+ * Changed unparse_WKB interface to take an output size pointer and an HEXFORM
1031
+ * specifier. Reworked code in wktunparse to use function pointers.
1032
+ *
1033
+ * Revision 1.15 2004/12/21 15:19:01 strk
1034
+ * Canonical binary reverted back to EWKB, now supporting SRID inclusion.
1035
+ *
1036
+ * Revision 1.14 2004/12/17 11:08:53 strk
1037
+ * Moved getMachineEndian from parser to liblwgeom.{h,c}.
1038
+ * Added XDR and NDR defines.
1039
+ * Fixed all usage of them.
1040
+ *
1041
+ * Revision 1.13 2004/10/25 12:27:33 strk
1042
+ * Removed useless network type includes,
1043
+ * Added param.h include for BYTE_ORDER defines under win32.
1044
+ *
1045
+ * Revision 1.12 2004/10/21 19:48:34 strk
1046
+ * Stricter syntax fixes. Reported by S�bastien NICAISE <snicaise@iciatechnologies.com>
1047
+ *
1048
+ * Revision 1.11 2004/10/15 07:35:41 strk
1049
+ * Fixed a bug introduced by me (byteorder skipped for inner geoms in WKB)
1050
+ *
1051
+ * Revision 1.10 2004/10/11 14:03:33 strk
1052
+ * Added endiannes specification to unparse_WKB, AsBinary, lwgeom_to_wkb.
1053
+ *
1054
+ ******************************************************************/