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,541 @@
1
+ /**********************************************************************
2
+ * $Id: lwcollection.c 3812 2009-03-09 14:36:15Z pramsey $
3
+ *
4
+ * PostGIS - Spatial Types for PostgreSQL
5
+ * http://postgis.refractions.net
6
+ * Copyright 2001-2006 Refractions Research Inc.
7
+ *
8
+ * This is free software; you can redistribute and/or modify it under
9
+ * the terms of the GNU General Public Licence. See the COPYING file.
10
+ *
11
+ **********************************************************************/
12
+
13
+ #include <stdio.h>
14
+ #include <stdlib.h>
15
+ #include <string.h>
16
+ #include "liblwgeom.h"
17
+
18
+
19
+ #define CHECK_LWGEOM_ZM 1
20
+
21
+ void
22
+ lwcollection_release(LWCOLLECTION *lwcollection)
23
+ {
24
+ lwgeom_release(lwcollection_as_lwgeom(lwcollection));
25
+ }
26
+
27
+
28
+ LWCOLLECTION *
29
+ lwcollection_construct(unsigned int type, int SRID, BOX2DFLOAT4 *bbox,
30
+ unsigned int ngeoms, LWGEOM **geoms)
31
+ {
32
+ LWCOLLECTION *ret;
33
+ int hasz, hasm;
34
+ #ifdef CHECK_LWGEOM_ZM
35
+ char zm;
36
+ unsigned int i;
37
+ #endif
38
+
39
+ LWDEBUGF(2, "lwcollection_construct called with %d, %d, %p, %d, %p.", type, SRID, bbox, ngeoms, geoms);
40
+
41
+ hasz = 0;
42
+ hasm = 0;
43
+ if ( ngeoms > 0 )
44
+ {
45
+ hasz = TYPE_HASZ(geoms[0]->type);
46
+ hasm = TYPE_HASM(geoms[0]->type);
47
+ #ifdef CHECK_LWGEOM_ZM
48
+ zm = TYPE_GETZM(geoms[0]->type);
49
+
50
+ LWDEBUGF(3, "lwcollection_construct type[0]=%d", geoms[0]->type);
51
+
52
+ for (i=1; i<ngeoms; i++)
53
+ {
54
+ LWDEBUGF(3, "lwcollection_construct type=[%d]=%d", i, geoms[i]->type);
55
+
56
+ if ( zm != TYPE_GETZM(geoms[i]->type) )
57
+ lwerror("lwcollection_construct: mixed dimension geometries: %d/%d", zm, TYPE_GETZM(geoms[i]->type));
58
+ }
59
+ #endif
60
+ }
61
+
62
+
63
+ ret = lwalloc(sizeof(LWCOLLECTION));
64
+ ret->type = lwgeom_makeType_full(hasz, hasm, (SRID!=-1),
65
+ type, 0);
66
+ ret->SRID = SRID;
67
+ ret->ngeoms = ngeoms;
68
+ ret->geoms = geoms;
69
+ ret->bbox = bbox;
70
+
71
+ return ret;
72
+ }
73
+
74
+ LWCOLLECTION *
75
+ lwcollection_construct_empty(int SRID, char hasz, char hasm)
76
+ {
77
+ LWCOLLECTION *ret;
78
+
79
+ ret = lwalloc(sizeof(LWCOLLECTION));
80
+ ret->type = lwgeom_makeType_full(hasz, hasm, (SRID!=-1),
81
+ COLLECTIONTYPE, 0);
82
+ ret->SRID = SRID;
83
+ ret->ngeoms = 0;
84
+ ret->geoms = NULL;
85
+ ret->bbox = NULL;
86
+
87
+ return ret;
88
+ }
89
+
90
+
91
+ LWCOLLECTION *
92
+ lwcollection_deserialize(uchar *srl)
93
+ {
94
+ LWCOLLECTION *result;
95
+ LWGEOM_INSPECTED *insp;
96
+ char typefl = srl[0];
97
+ int type = lwgeom_getType(typefl);
98
+ int i;
99
+
100
+ if ( type != COLLECTIONTYPE )
101
+ {
102
+ lwerror("lwcollection_deserialize called on NON geometrycollection: %d", type);
103
+ return NULL;
104
+ }
105
+
106
+ insp = lwgeom_inspect(srl);
107
+
108
+ result = lwalloc(sizeof(LWCOLLECTION));
109
+ result->type = typefl;
110
+ result->SRID = insp->SRID;
111
+ result->ngeoms = insp->ngeometries;
112
+
113
+ if (lwgeom_hasBBOX(srl[0]))
114
+ {
115
+ result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
116
+ memcpy(result->bbox, srl+1, sizeof(BOX2DFLOAT4));
117
+ }
118
+ else result->bbox = NULL;
119
+
120
+
121
+ if ( insp->ngeometries )
122
+ {
123
+ result->geoms = lwalloc(sizeof(LWGEOM *)*insp->ngeometries);
124
+ for (i=0; i<insp->ngeometries; i++)
125
+ {
126
+ result->geoms[i] =
127
+ lwgeom_deserialize(insp->sub_geoms[i]);
128
+ }
129
+ }
130
+
131
+ return result;
132
+ }
133
+
134
+ LWGEOM *
135
+ lwcollection_getsubgeom(LWCOLLECTION *col, int gnum)
136
+ {
137
+ return (LWGEOM *)col->geoms[gnum];
138
+ }
139
+
140
+ /* find serialized size of this collection */
141
+ size_t
142
+ lwcollection_serialize_size(LWCOLLECTION *col)
143
+ {
144
+ size_t size = 5; /* type + nsubgeoms */
145
+ int i;
146
+
147
+ if ( col->SRID != -1 ) size += 4; /* SRID */
148
+ if ( col->bbox ) size += sizeof(BOX2DFLOAT4);
149
+
150
+ LWDEBUGF(2, "lwcollection_serialize_size[%p]: start size: %d", col, size);
151
+
152
+
153
+ for (i=0; i<col->ngeoms; i++)
154
+ {
155
+ size += lwgeom_serialize_size(col->geoms[i]);
156
+
157
+ LWDEBUGF(3, "lwcollection_serialize_size[%p]: with geom%d: %d", col, i, size);
158
+ }
159
+
160
+ LWDEBUGF(3, "lwcollection_serialize_size[%p]: returning %d", col, size);
161
+
162
+ return size;
163
+ }
164
+
165
+ /*
166
+ * convert this collectoin into its serialize form writing it into
167
+ * the given buffer, and returning number of bytes written into
168
+ * the given int pointer.
169
+ */
170
+ void
171
+ lwcollection_serialize_buf(LWCOLLECTION *coll, uchar *buf, size_t *retsize)
172
+ {
173
+ size_t size=1; /* type */
174
+ size_t subsize=0;
175
+ char hasSRID;
176
+ uchar *loc;
177
+ int i;
178
+
179
+ LWDEBUGF(2, "lwcollection_serialize_buf called (%s with %d elems)",
180
+ lwgeom_typename(TYPE_GETTYPE(coll->type)), coll->ngeoms);
181
+
182
+ hasSRID = (coll->SRID != -1);
183
+
184
+ buf[0] = lwgeom_makeType_full(
185
+ TYPE_HASZ(coll->type), TYPE_HASM(coll->type),
186
+ hasSRID, TYPE_GETTYPE(coll->type), coll->bbox ? 1 : 0);
187
+ loc = buf+1;
188
+
189
+ /* Add BBOX if requested */
190
+ if ( coll->bbox )
191
+ {
192
+ memcpy(loc, coll->bbox, sizeof(BOX2DFLOAT4));
193
+ size += sizeof(BOX2DFLOAT4);
194
+ loc += sizeof(BOX2DFLOAT4);
195
+ }
196
+
197
+ /* Add SRID if requested */
198
+ if (hasSRID)
199
+ {
200
+ memcpy(loc, &coll->SRID, 4);
201
+ size += 4;
202
+ loc += 4;
203
+ }
204
+
205
+ /* Write number of subgeoms */
206
+ memcpy(loc, &coll->ngeoms, 4);
207
+ size += 4;
208
+ loc += 4;
209
+
210
+ /* Serialize subgeoms */
211
+ for (i=0; i<coll->ngeoms; i++)
212
+ {
213
+ lwgeom_serialize_buf(coll->geoms[i], loc, &subsize);
214
+ size += subsize;
215
+ loc += subsize;
216
+ }
217
+
218
+ if (retsize) *retsize = size;
219
+
220
+ LWDEBUG(3, "lwcollection_serialize_buf returning");
221
+ }
222
+
223
+ int
224
+ lwcollection_compute_box2d_p(LWCOLLECTION *col, BOX2DFLOAT4 *box)
225
+ {
226
+ BOX2DFLOAT4 boxbuf;
227
+ uint32 i;
228
+
229
+ if ( ! col->ngeoms ) return 0;
230
+ if ( ! lwgeom_compute_box2d_p(col->geoms[0], box) ) return 0;
231
+ for (i=1; i<col->ngeoms; i++)
232
+ {
233
+ if ( ! lwgeom_compute_box2d_p(col->geoms[i], &boxbuf) )
234
+ return 0;
235
+ if ( ! box2d_union_p(box, &boxbuf, box) ) return 0;
236
+ }
237
+ return 1;
238
+ }
239
+
240
+ /*
241
+ * Clone LWCOLLECTION object. POINTARRAY are not copied.
242
+ * Bbox is cloned if present in input.
243
+ */
244
+ LWCOLLECTION *
245
+ lwcollection_clone(const LWCOLLECTION *g)
246
+ {
247
+ uint32 i;
248
+ LWCOLLECTION *ret = lwalloc(sizeof(LWCOLLECTION));
249
+ memcpy(ret, g, sizeof(LWCOLLECTION));
250
+ if ( g->ngeoms > 0 )
251
+ {
252
+ ret->geoms = lwalloc(sizeof(LWGEOM *)*g->ngeoms);
253
+ for (i=0; i<g->ngeoms; i++)
254
+ {
255
+ ret->geoms[i] = lwgeom_clone(g->geoms[i]);
256
+ }
257
+ if ( g->bbox ) ret->bbox = box2d_clone(g->bbox);
258
+ }
259
+ else
260
+ {
261
+ ret->bbox = NULL; /* empty collection */
262
+ ret->geoms = NULL;
263
+ }
264
+ return ret;
265
+ }
266
+
267
+ /*
268
+ * Add 'what' to this collection at position 'where'.
269
+ * where=0 == prepend
270
+ * where=-1 == append
271
+ * Returns a GEOMETRYCOLLECTION
272
+ */
273
+ LWGEOM *
274
+ lwcollection_add(const LWCOLLECTION *to, uint32 where, const LWGEOM *what)
275
+ {
276
+ LWCOLLECTION *col;
277
+ LWGEOM **geoms;
278
+ uint32 i;
279
+
280
+ if ( where == -1 ) where = to->ngeoms;
281
+ else if ( where < -1 || where > to->ngeoms )
282
+ {
283
+ lwerror("lwcollection_add: add position out of range %d..%d",
284
+ -1, to->ngeoms);
285
+ return NULL;
286
+ }
287
+
288
+ /* dimensions compatibility are checked by caller */
289
+
290
+ /* Construct geoms array */
291
+ geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
292
+ for (i=0; i<where; i++)
293
+ {
294
+ geoms[i] = lwgeom_clone(to->geoms[i]);
295
+ lwgeom_dropSRID(geoms[i]);
296
+ lwgeom_drop_bbox(geoms[i]);
297
+ }
298
+ geoms[where] = lwgeom_clone(what);
299
+ lwgeom_dropSRID(geoms[where]);
300
+ lwgeom_drop_bbox(geoms[where]);
301
+ for (i=where; i<to->ngeoms; i++)
302
+ {
303
+ geoms[i+1] = lwgeom_clone(to->geoms[i]);
304
+ lwgeom_dropSRID(geoms[i+1]);
305
+ lwgeom_drop_bbox(geoms[i+1]);
306
+ }
307
+
308
+ col = lwcollection_construct(COLLECTIONTYPE,
309
+ to->SRID, NULL,
310
+ to->ngeoms+1, geoms);
311
+
312
+ return (LWGEOM *)col;
313
+
314
+ }
315
+
316
+ LWCOLLECTION *
317
+ lwcollection_segmentize2d(LWCOLLECTION *col, double dist)
318
+ {
319
+ unsigned int i;
320
+ LWGEOM **newgeoms;
321
+
322
+ if ( ! col->ngeoms ) return col;
323
+
324
+ newgeoms = lwalloc(sizeof(LWGEOM *)*col->ngeoms);
325
+ for (i=0; i<col->ngeoms; i++)
326
+ newgeoms[i] = lwgeom_segmentize2d(col->geoms[i], dist);
327
+
328
+ return lwcollection_construct(col->type, col->SRID, NULL,
329
+ col->ngeoms, newgeoms);
330
+ }
331
+
332
+ /* check for same geometry composition */
333
+ char
334
+ lwcollection_same(const LWCOLLECTION *c1, const LWCOLLECTION *c2)
335
+ {
336
+ unsigned int i, j;
337
+ unsigned int *hit;
338
+
339
+ LWDEBUG(2, "lwcollection_same called");
340
+
341
+ if ( TYPE_GETTYPE(c1->type) != TYPE_GETTYPE(c2->type) ) return 0;
342
+ if ( c1->ngeoms != c2->ngeoms ) return 0;
343
+
344
+ hit = lwalloc(sizeof(unsigned int)*c1->ngeoms);
345
+ memset(hit, 0, sizeof(unsigned int)*c1->ngeoms);
346
+
347
+ for (i=0; i<c1->ngeoms; i++)
348
+ {
349
+ char found=0;
350
+ for (j=0; j<c2->ngeoms; j++)
351
+ {
352
+ if ( hit[j] ) continue;
353
+ if ( lwgeom_same(c1->geoms[i], c2->geoms[j]) )
354
+ {
355
+ hit[j] = 1;
356
+ found=1;
357
+ break;
358
+ }
359
+ }
360
+ if ( ! found ) return 0;
361
+ }
362
+ return 1;
363
+ }
364
+
365
+ int lwcollection_ngeoms(const LWCOLLECTION *col)
366
+ {
367
+ int i;
368
+ int ngeoms = 0;
369
+
370
+ if( ! col ) {
371
+ lwerror("Null input geometry.");
372
+ return 0;
373
+ }
374
+
375
+ for( i = 0; i < col->ngeoms; i++ )
376
+ {
377
+ if( col->geoms[i]) {
378
+ switch(TYPE_GETTYPE(col->geoms[i]->type)) {
379
+ case POINTTYPE:
380
+ case LINETYPE:
381
+ case CIRCSTRINGTYPE:
382
+ case POLYGONTYPE:
383
+ ngeoms += 1;
384
+ break;
385
+ case MULTIPOINTTYPE:
386
+ case MULTILINETYPE:
387
+ case MULTICURVETYPE:
388
+ case MULTIPOLYGONTYPE:
389
+ ngeoms += col->ngeoms;
390
+ break;
391
+ case COLLECTIONTYPE:
392
+ ngeoms += lwcollection_ngeoms((LWCOLLECTION*)col->geoms[i]);
393
+ break;
394
+ }
395
+ }
396
+ }
397
+ return ngeoms;
398
+ }
399
+
400
+ /*
401
+ ** Given a generic collection, return the "simplest" form.
402
+ ** eg: GEOMETRYCOLLECTION(MULTILINESTRING()) => MULTELINESTRING()
403
+ ** GEOMETRYCOLLECTION(MULTILINESTRING(), MULTILINESTRING(), POINT()) => GEOMETRYCOLLECTION(MULTILINESTRING(), MULTIPOINT())
404
+ **
405
+ ** In general, if the subcomponents are homogeneous, return a properly typed collection.
406
+ ** Otherwise, return a generic collection, with the subtypes in minimal typed collections.
407
+ LWCOLLECTION *lwcollection_homogenize(const LWCOLLECTION *c1)
408
+ {
409
+ TODO: pramsey
410
+ }
411
+ */
412
+
413
+ /*
414
+ ** Given a generic collection, extract and return just the desired types.
415
+ LWGEOM *lwcollection_extract(const LWCOLLECTION *col, char type)
416
+ {
417
+ LWGEOM **extracted_geoms;
418
+ extracted_geoms = lwalloc(sizeof(void*)*col->ngeoms);
419
+ extracted_curgeom = 0;
420
+ char reqtype = TYPE_GETTYPE(type);
421
+ for ( i = 0; i < col->ngeoms; i++ )
422
+ {
423
+ if( col->geoms[i] )
424
+ char geomtype = TYPE_GETTYPE(col->geoms[i]->type);
425
+ if ( geomtype == reqtype ) {
426
+ extracted_geoms[extracted_curgeom] = col->geoms[i];
427
+ extracted_curgeom++;
428
+ continue;
429
+ }
430
+ else {
431
+ if ( geomtype == COLLECTIONTYPE ) {
432
+ LWGEOM *colgeom;
433
+ colgeom = lwcollection_extract(col->geoms[i], type);
434
+ extracted_geoms[extracted_curgeom] = colgeom->geoms;
435
+ extracted_curgeom++;
436
+ if( colgeom->bbox ) lwfree(colgeom->bbox);
437
+ lwfree(colgeom);
438
+ continue;
439
+ }
440
+ }
441
+ TODO: pramsey
442
+ }
443
+ */
444
+
445
+
446
+
447
+ void lwcollection_free(LWCOLLECTION *col)
448
+ {
449
+ int i;
450
+ if( col->bbox )
451
+ {
452
+ lwfree(col->bbox);
453
+ }
454
+ for ( i = 0; i < col->ngeoms; i++ )
455
+ {
456
+ if( col->geoms[i] ) {
457
+ switch( TYPE_GETTYPE(col->geoms[i]->type) )
458
+ {
459
+ case POINTTYPE:
460
+ lwpoint_free((LWPOINT*)col->geoms[i]);
461
+ break;
462
+ case LINETYPE:
463
+ lwline_free((LWLINE*)col->geoms[i]);
464
+ break;
465
+ case POLYGONTYPE:
466
+ lwpoly_free((LWPOLY*)col->geoms[i]);
467
+ break;
468
+ case MULTIPOINTTYPE:
469
+ lwmpoint_free((LWMPOINT*)col->geoms[i]);
470
+ break;
471
+ case MULTILINETYPE:
472
+ lwmline_free((LWMLINE*)col->geoms[i]);
473
+ break;
474
+ case MULTIPOLYGONTYPE:
475
+ lwmpoly_free((LWMPOLY*)col->geoms[i]);
476
+ break;
477
+ case COLLECTIONTYPE:
478
+ lwcollection_free((LWCOLLECTION*)col->geoms[i]);
479
+ break;
480
+ }
481
+ }
482
+ }
483
+ if( col->geoms )
484
+ {
485
+ lwfree(col->geoms);
486
+ }
487
+ lwfree(col);
488
+
489
+ };
490
+
491
+ BOX3D *lwcollection_compute_box3d(LWCOLLECTION *col)
492
+ {
493
+ int i;
494
+ BOX3D *boxfinal = NULL;
495
+ BOX3D *boxtmp1 = NULL;
496
+ BOX3D *boxtmp2 = NULL;
497
+ for ( i = 0; i < col->ngeoms; i++ )
498
+ {
499
+ if( col->geoms[i] ) {
500
+ switch( TYPE_GETTYPE(col->geoms[i]->type) )
501
+ {
502
+ case POINTTYPE:
503
+ boxtmp1 = lwpoint_compute_box3d((LWPOINT*)(col->geoms[i]));
504
+ break;
505
+ case LINETYPE:
506
+ boxtmp1 = lwline_compute_box3d((LWLINE*)(col->geoms[i]));
507
+ break;
508
+ case POLYGONTYPE:
509
+ boxtmp1 = lwpoly_compute_box3d((LWPOLY*)(col->geoms[i]));
510
+ break;
511
+ case CIRCSTRINGTYPE:
512
+ boxtmp1 = lwcircstring_compute_box3d((LWCIRCSTRING *)(col->geoms[i]));
513
+ break;
514
+ case COMPOUNDTYPE:
515
+ case CURVEPOLYTYPE:
516
+ case MULTIPOINTTYPE:
517
+ case MULTILINETYPE:
518
+ case MULTIPOLYGONTYPE:
519
+ case MULTICURVETYPE:
520
+ case MULTISURFACETYPE:
521
+ case COLLECTIONTYPE:
522
+ boxtmp1 = lwcollection_compute_box3d((LWCOLLECTION*)(col->geoms[i]));
523
+ boxfinal = box3d_union(boxtmp1, boxtmp2);
524
+ break;
525
+ }
526
+ boxtmp2 = boxfinal;
527
+ boxfinal = box3d_union(boxtmp1, boxtmp2);
528
+ if( boxtmp1 && boxtmp1 != boxfinal )
529
+ {
530
+ lwfree(boxtmp1);
531
+ boxtmp1 = NULL;
532
+ }
533
+ if( boxtmp2 && boxtmp2 != boxfinal )
534
+ {
535
+ lwfree(boxtmp2);
536
+ boxtmp2 = NULL;
537
+ }
538
+ }
539
+ }
540
+ return boxfinal;
541
+ }