geo_coder 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ ******************************************************************/