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,118 @@
1
+ /**********************************************************************
2
+ * $Id: lwcompound.c 3639 2009-02-04 00:28:37Z 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
+ LWCOMPOUND *
19
+ lwcompound_deserialize(uchar *serialized)
20
+ {
21
+ LWCOMPOUND *result;
22
+ LWGEOM_INSPECTED *insp;
23
+ int type = lwgeom_getType(serialized[0]);
24
+ int i;
25
+
26
+ if(type != COMPOUNDTYPE)
27
+ {
28
+ lwerror("lwcompound_deserialize called on non compound: %d", type);
29
+ return NULL;
30
+ }
31
+
32
+ insp = lwgeom_inspect(serialized);
33
+
34
+ result = lwalloc(sizeof(LWCOMPOUND));
35
+ result->type = insp->type;
36
+ result->SRID = insp->SRID;
37
+ result->ngeoms = insp->ngeometries;
38
+ result->geoms = lwalloc(sizeof(LWGEOM *)*insp->ngeometries);
39
+
40
+ if(lwgeom_hasBBOX(serialized[0]))
41
+ {
42
+ result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
43
+ memcpy(result->bbox, serialized + 1, sizeof(BOX2DFLOAT4));
44
+ }
45
+ else result->bbox = NULL;
46
+
47
+ for(i = 0; i < insp->ngeometries; i++)
48
+ {
49
+ if(lwgeom_getType(insp->sub_geoms[i][0]) == LINETYPE)
50
+ result->geoms[i] = (LWGEOM *)lwline_deserialize(insp->sub_geoms[i]);
51
+ else
52
+ result->geoms[i] = (LWGEOM *)lwcircstring_deserialize(insp->sub_geoms[i]);
53
+ if(TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type))
54
+ {
55
+ lwerror("Mixed dimensions (compound: %d, line/circularstring %d:%d)",
56
+ TYPE_NDIMS(result->type), i,
57
+ TYPE_NDIMS(result->geoms[i]->type)
58
+ );
59
+ lwfree(result);
60
+ return NULL;
61
+ }
62
+ }
63
+ return result;
64
+ }
65
+
66
+ /*
67
+ * Add 'what' to this string at position 'where'
68
+ * where=0 == prepend
69
+ * where=-1 == append
70
+ * Returns a COMPOUND or a GEOMETRYCOLLECTION
71
+ */
72
+ LWGEOM *
73
+ lwcompound_add(const LWCOMPOUND *to, uint32 where, const LWGEOM *what)
74
+ {
75
+ LWCOLLECTION *col;
76
+ LWGEOM **geoms;
77
+ int newtype;
78
+
79
+ LWDEBUG(2, "lwcompound_add called.");
80
+
81
+ if(where != -1 && where != 0)
82
+ {
83
+ lwerror("lwcompound_add only supports 0 or -1 as a second argument, not %d", where);
84
+ return NULL;
85
+ }
86
+
87
+ /* dimensions compatibility are checked by caller */
88
+
89
+ /* Construct geoms array */
90
+ geoms = lwalloc(sizeof(LWGEOM *)*2);
91
+ if(where == -1) /* append */
92
+ {
93
+ geoms[0] = lwgeom_clone((LWGEOM *)to);
94
+ geoms[1] = lwgeom_clone(what);
95
+ }
96
+ else /* prepend */
97
+ {
98
+ geoms[0] = lwgeom_clone(what);
99
+ geoms[1] = lwgeom_clone((LWGEOM *)to);
100
+ }
101
+
102
+ /* reset SRID and wantbbox flag from component types */
103
+ geoms[0]->SRID = geoms[1]->SRID = -1;
104
+ TYPE_SETHASSRID(geoms[0]->type, 0);
105
+ TYPE_SETHASSRID(geoms[1]->type, 0);
106
+ TYPE_SETHASBBOX(geoms[0]->type, 0);
107
+ TYPE_SETHASBBOX(geoms[1]->type, 0);
108
+
109
+ /* Find appropriate geom type */
110
+ if(TYPE_GETTYPE(what->type) == LINETYPE || TYPE_GETTYPE(what->type) == CIRCSTRINGTYPE) newtype = COMPOUNDTYPE;
111
+ else newtype = COLLECTIONTYPE;
112
+
113
+ col = lwcollection_construct(newtype,
114
+ to->SRID, NULL, 2, geoms);
115
+
116
+ return (LWGEOM *)col;
117
+ }
118
+
@@ -0,0 +1,86 @@
1
+ /**********************************************************************
2
+ * $Id: lwcurvepoly.c 3639 2009-02-04 00:28:37Z 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
+ /* basic LWCURVEPOLY manipulation */
14
+
15
+ #include <stdio.h>
16
+ #include <stdlib.h>
17
+ #include <string.h>
18
+ #include "liblwgeom.h"
19
+
20
+
21
+ LWCURVEPOLY *
22
+ lwcurvepoly_deserialize(uchar *srl)
23
+ {
24
+ LWCURVEPOLY *result;
25
+ LWGEOM_INSPECTED *insp;
26
+ int type = lwgeom_getType(srl[0]);
27
+ int i;
28
+
29
+ LWDEBUG(3, "lwcurvepoly_deserialize called.");
30
+
31
+ if(type != CURVEPOLYTYPE)
32
+ {
33
+ lwerror("lwcurvepoly_deserialize called on NON curvepoly: %d",
34
+ type);
35
+ return NULL;
36
+ }
37
+
38
+ insp = lwgeom_inspect(srl);
39
+
40
+ result = lwalloc(sizeof(LWCURVEPOLY));
41
+ result->type = insp->type;
42
+ result->SRID = insp->SRID;
43
+ result->nrings = insp->ngeometries;
44
+ result->rings = lwalloc(sizeof(LWGEOM *)*insp->ngeometries);
45
+
46
+ if(lwgeom_hasBBOX(srl[0]))
47
+ {
48
+ result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
49
+ memcpy(result->bbox, srl + 1, sizeof(BOX2DFLOAT4));
50
+ }
51
+ else result->bbox = NULL;
52
+
53
+ for(i = 0; i < insp->ngeometries; i++)
54
+ {
55
+ result->rings[i] = lwgeom_deserialize(insp->sub_geoms[i]);
56
+ if(lwgeom_getType(result->rings[i]->type) != CIRCSTRINGTYPE
57
+ && lwgeom_getType(result->rings[i]->type) != LINETYPE)
58
+ {
59
+ lwerror("Only Circularstrings and Linestrings are currently supported as rings, not %s (%d)", lwgeom_typename(result->rings[i]->type), result->rings[i]->type);
60
+ lwfree(result);
61
+ lwfree(insp);
62
+ return NULL;
63
+ }
64
+ if(TYPE_NDIMS(result->rings[i]->type) != TYPE_NDIMS(result->type))
65
+ {
66
+ lwerror("Mixed dimensions (curvepoly %d, ring %d)",
67
+ TYPE_NDIMS(result->type), i,
68
+ TYPE_NDIMS(result->rings[i]->type));
69
+ lwfree(result);
70
+ lwfree(insp);
71
+ return NULL;
72
+ }
73
+ }
74
+ return result;
75
+ }
76
+
77
+ LWGEOM *
78
+ lwcurvepoly_add(const LWCURVEPOLY *to, uint32 where, const LWGEOM *what)
79
+ {
80
+ /* TODO */
81
+ lwerror("lwcurvepoly_add not yet implemented.");
82
+ return NULL;
83
+ }
84
+
85
+
86
+
@@ -0,0 +1,886 @@
1
+ /**********************************************************************
2
+ * $Id: lwgeom.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 <stdarg.h>
16
+
17
+ #include "liblwgeom.h"
18
+ #include "wktparse.h"
19
+
20
+
21
+ LWGEOM *
22
+ lwgeom_deserialize(uchar *srl)
23
+ {
24
+ int type = lwgeom_getType(srl[0]);
25
+
26
+ LWDEBUGF(2, "lwgeom_deserialize got %d - %s", type, lwgeom_typename(type));
27
+
28
+ switch (type)
29
+ {
30
+ case POINTTYPE:
31
+ return (LWGEOM *)lwpoint_deserialize(srl);
32
+ case LINETYPE:
33
+ return (LWGEOM *)lwline_deserialize(srl);
34
+ case CIRCSTRINGTYPE:
35
+ return (LWGEOM *)lwcircstring_deserialize(srl);
36
+ case POLYGONTYPE:
37
+ return (LWGEOM *)lwpoly_deserialize(srl);
38
+ case MULTIPOINTTYPE:
39
+ return (LWGEOM *)lwmpoint_deserialize(srl);
40
+ case MULTILINETYPE:
41
+ return (LWGEOM *)lwmline_deserialize(srl);
42
+ case MULTIPOLYGONTYPE:
43
+ return (LWGEOM *)lwmpoly_deserialize(srl);
44
+ case COLLECTIONTYPE:
45
+ return (LWGEOM *)lwcollection_deserialize(srl);
46
+ case COMPOUNDTYPE:
47
+ return (LWGEOM *)lwcompound_deserialize(srl);
48
+ case CURVEPOLYTYPE:
49
+ return (LWGEOM *)lwcurvepoly_deserialize(srl);
50
+ case MULTICURVETYPE:
51
+ return (LWGEOM *)lwmcurve_deserialize(srl);
52
+ case MULTISURFACETYPE:
53
+ return (LWGEOM *)lwmsurface_deserialize(srl);
54
+ default:
55
+ lwerror("Unknown geometry type: %d", type);
56
+
57
+ return NULL;
58
+ }
59
+
60
+ }
61
+
62
+ size_t
63
+ lwgeom_serialize_size(LWGEOM *lwgeom)
64
+ {
65
+ int type = TYPE_GETTYPE(lwgeom->type);
66
+
67
+ LWDEBUGF(2, "lwgeom_serialize_size(%s) called", lwgeom_typename(type));
68
+
69
+ switch (type)
70
+ {
71
+ case POINTTYPE:
72
+ return lwpoint_serialize_size((LWPOINT *)lwgeom);
73
+ case LINETYPE:
74
+ return lwline_serialize_size((LWLINE *)lwgeom);
75
+ case POLYGONTYPE:
76
+ return lwpoly_serialize_size((LWPOLY *)lwgeom);
77
+ case CIRCSTRINGTYPE:
78
+ return lwcircstring_serialize_size((LWCIRCSTRING *)lwgeom);
79
+ case CURVEPOLYTYPE:
80
+ case COMPOUNDTYPE:
81
+ case MULTIPOINTTYPE:
82
+ case MULTILINETYPE:
83
+ case MULTICURVETYPE:
84
+ case MULTIPOLYGONTYPE:
85
+ case MULTISURFACETYPE:
86
+ case COLLECTIONTYPE:
87
+ return lwcollection_serialize_size((LWCOLLECTION *)lwgeom);
88
+ default:
89
+ lwerror("Unknown geometry type: %d", type);
90
+
91
+ return 0;
92
+ }
93
+ }
94
+
95
+ void
96
+ lwgeom_serialize_buf(LWGEOM *lwgeom, uchar *buf, size_t *retsize)
97
+ {
98
+ int type = TYPE_GETTYPE(lwgeom->type);
99
+
100
+ LWDEBUGF(2, "lwgeom_serialize_buf called with a %s",
101
+ lwgeom_typename(type));
102
+
103
+ switch (type)
104
+ {
105
+ case POINTTYPE:
106
+ lwpoint_serialize_buf((LWPOINT *)lwgeom, buf, retsize);
107
+ break;
108
+ case LINETYPE:
109
+ lwline_serialize_buf((LWLINE *)lwgeom, buf, retsize);
110
+ break;
111
+ case POLYGONTYPE:
112
+ lwpoly_serialize_buf((LWPOLY *)lwgeom, buf, retsize);
113
+ break;
114
+ case CIRCSTRINGTYPE:
115
+ lwcircstring_serialize_buf((LWCIRCSTRING *)lwgeom, buf, retsize);
116
+ break;
117
+ case CURVEPOLYTYPE:
118
+ case COMPOUNDTYPE:
119
+ case MULTIPOINTTYPE:
120
+ case MULTILINETYPE:
121
+ case MULTICURVETYPE:
122
+ case MULTIPOLYGONTYPE:
123
+ case MULTISURFACETYPE:
124
+ case COLLECTIONTYPE:
125
+ lwcollection_serialize_buf((LWCOLLECTION *)lwgeom, buf,
126
+ retsize);
127
+ break;
128
+ default:
129
+ lwerror("Unknown geometry type: %d", type);
130
+ return;
131
+ }
132
+ return;
133
+ }
134
+
135
+ uchar *
136
+ lwgeom_serialize(LWGEOM *lwgeom)
137
+ {
138
+ size_t size = lwgeom_serialize_size(lwgeom);
139
+ size_t retsize;
140
+ uchar *serialized = lwalloc(size);
141
+
142
+ lwgeom_serialize_buf(lwgeom, serialized, &retsize);
143
+
144
+ #if POSTGIS_DEBUG_LEVEL > 0
145
+ if ( retsize != size )
146
+ {
147
+ lwerror("lwgeom_serialize: computed size %d, returned size %d",
148
+ size, retsize);
149
+ }
150
+ #endif
151
+
152
+ return serialized;
153
+ }
154
+
155
+ /* Force Right-hand-rule on LWGEOM polygons */
156
+ void
157
+ lwgeom_forceRHR(LWGEOM *lwgeom)
158
+ {
159
+ LWCOLLECTION *coll;
160
+ int i;
161
+
162
+ switch (TYPE_GETTYPE(lwgeom->type))
163
+ {
164
+ case POLYGONTYPE:
165
+ lwpoly_forceRHR((LWPOLY *)lwgeom);
166
+ return;
167
+
168
+ case MULTIPOLYGONTYPE:
169
+ case COLLECTIONTYPE:
170
+ coll = (LWCOLLECTION *)lwgeom;
171
+ for (i=0; i<coll->ngeoms; i++)
172
+ lwgeom_forceRHR(coll->geoms[i]);
173
+ return;
174
+ }
175
+ }
176
+
177
+ /* Reverse vertex order of LWGEOM */
178
+ void
179
+ lwgeom_reverse(LWGEOM *lwgeom)
180
+ {
181
+ int i;
182
+ LWCOLLECTION *col;
183
+
184
+ switch (TYPE_GETTYPE(lwgeom->type))
185
+ {
186
+ case LINETYPE:
187
+ lwline_reverse((LWLINE *)lwgeom);
188
+ return;
189
+ case POLYGONTYPE:
190
+ lwpoly_reverse((LWPOLY *)lwgeom);
191
+ return;
192
+ case MULTILINETYPE:
193
+ case MULTIPOLYGONTYPE:
194
+ case COLLECTIONTYPE:
195
+ col = (LWCOLLECTION *)lwgeom;
196
+ for (i=0; i<col->ngeoms; i++)
197
+ lwgeom_reverse(col->geoms[i]);
198
+ return;
199
+ }
200
+ }
201
+
202
+ BOX3D *lwgeom_compute_box3d(const LWGEOM *lwgeom)
203
+ {
204
+ if( ! lwgeom ) return NULL;
205
+
206
+ switch(TYPE_GETTYPE(lwgeom->type))
207
+ {
208
+ case POINTTYPE:
209
+ return lwpoint_compute_box3d((LWPOINT *)lwgeom);
210
+ case LINETYPE:
211
+ return lwline_compute_box3d((LWLINE *)lwgeom);
212
+ case CIRCSTRINGTYPE:
213
+ return lwcircstring_compute_box3d((LWCIRCSTRING *)lwgeom);
214
+ case POLYGONTYPE:
215
+ return lwpoly_compute_box3d((LWPOLY *)lwgeom);
216
+ case COMPOUNDTYPE:
217
+ case CURVEPOLYTYPE:
218
+ case MULTIPOINTTYPE:
219
+ case MULTILINETYPE:
220
+ case MULTICURVETYPE:
221
+ case MULTIPOLYGONTYPE:
222
+ case MULTISURFACETYPE:
223
+ case COLLECTIONTYPE:
224
+ return lwcollection_compute_box3d((LWCOLLECTION *)lwgeom);
225
+ }
226
+ /* Never get here, please. */
227
+ return NULL;
228
+ }
229
+
230
+ int
231
+ lwgeom_compute_box2d_p(LWGEOM *lwgeom, BOX2DFLOAT4 *buf)
232
+ {
233
+ LWDEBUGF(2, "lwgeom_compute_box2d_p called of %p of type %d.", lwgeom, TYPE_GETTYPE(lwgeom->type));
234
+
235
+ switch(TYPE_GETTYPE(lwgeom->type))
236
+ {
237
+ case POINTTYPE:
238
+ return lwpoint_compute_box2d_p((LWPOINT *)lwgeom, buf);
239
+ case LINETYPE:
240
+ return lwline_compute_box2d_p((LWLINE *)lwgeom, buf);
241
+ case CIRCSTRINGTYPE:
242
+ return lwcircstring_compute_box2d_p((LWCIRCSTRING *)lwgeom, buf);
243
+ case POLYGONTYPE:
244
+ return lwpoly_compute_box2d_p((LWPOLY *)lwgeom, buf);
245
+ case COMPOUNDTYPE:
246
+ case CURVEPOLYTYPE:
247
+ case MULTIPOINTTYPE:
248
+ case MULTILINETYPE:
249
+ case MULTICURVETYPE:
250
+ case MULTIPOLYGONTYPE:
251
+ case MULTISURFACETYPE:
252
+ case COLLECTIONTYPE:
253
+ return lwcollection_compute_box2d_p((LWCOLLECTION *)lwgeom, buf);
254
+ }
255
+ return 0;
256
+ }
257
+
258
+ /*
259
+ * dont forget to lwfree() result
260
+ */
261
+ BOX2DFLOAT4 *
262
+ lwgeom_compute_box2d(LWGEOM *lwgeom)
263
+ {
264
+ BOX2DFLOAT4 *result = lwalloc(sizeof(BOX2DFLOAT4));
265
+ if ( lwgeom_compute_box2d_p(lwgeom, result) ) return result;
266
+ else {
267
+ lwfree(result);
268
+ return NULL;
269
+ }
270
+ }
271
+
272
+ LWPOINT *
273
+ lwgeom_as_lwpoint(LWGEOM *lwgeom)
274
+ {
275
+ if ( TYPE_GETTYPE(lwgeom->type) == POINTTYPE )
276
+ return (LWPOINT *)lwgeom;
277
+ else return NULL;
278
+ }
279
+
280
+ LWLINE *
281
+ lwgeom_as_lwline(LWGEOM *lwgeom)
282
+ {
283
+ if ( TYPE_GETTYPE(lwgeom->type) == LINETYPE )
284
+ return (LWLINE *)lwgeom;
285
+ else return NULL;
286
+ }
287
+
288
+ LWCIRCSTRING *
289
+ lwgeom_as_lwcircstring(LWGEOM *lwgeom)
290
+ {
291
+ if( TYPE_GETTYPE(lwgeom->type) == CIRCSTRINGTYPE )
292
+ return (LWCIRCSTRING *)lwgeom;
293
+ else return NULL;
294
+ }
295
+
296
+ LWPOLY *
297
+ lwgeom_as_lwpoly(LWGEOM *lwgeom)
298
+ {
299
+ if ( TYPE_GETTYPE(lwgeom->type) == POLYGONTYPE )
300
+ return (LWPOLY *)lwgeom;
301
+ else return NULL;
302
+ }
303
+
304
+ LWCOLLECTION *
305
+ lwgeom_as_lwcollection(LWGEOM *lwgeom)
306
+ {
307
+ if ( TYPE_GETTYPE(lwgeom->type) >= MULTIPOINTTYPE
308
+ && TYPE_GETTYPE(lwgeom->type) <= COLLECTIONTYPE)
309
+ return (LWCOLLECTION *)lwgeom;
310
+ else return NULL;
311
+ }
312
+
313
+ LWMPOINT *
314
+ lwgeom_as_lwmpoint(LWGEOM *lwgeom)
315
+ {
316
+ if ( TYPE_GETTYPE(lwgeom->type) == MULTIPOINTTYPE )
317
+ return (LWMPOINT *)lwgeom;
318
+ else return NULL;
319
+ }
320
+
321
+ LWMLINE *
322
+ lwgeom_as_lwmline(LWGEOM *lwgeom)
323
+ {
324
+ if ( TYPE_GETTYPE(lwgeom->type) == MULTILINETYPE )
325
+ return (LWMLINE *)lwgeom;
326
+ else return NULL;
327
+ }
328
+
329
+ LWMPOLY *
330
+ lwgeom_as_lwmpoly(LWGEOM *lwgeom)
331
+ {
332
+ if ( TYPE_GETTYPE(lwgeom->type) == MULTIPOLYGONTYPE )
333
+ return (LWMPOLY *)lwgeom;
334
+ else return NULL;
335
+ }
336
+
337
+ LWGEOM *lwmpoly_as_lwgeom(LWMPOLY *obj) { return (LWGEOM *)obj; }
338
+ LWGEOM *lwmline_as_lwgeom(LWMLINE *obj) { return (LWGEOM *)obj; }
339
+ LWGEOM *lwmpoint_as_lwgeom(LWMPOINT *obj) { return (LWGEOM *)obj; }
340
+ LWGEOM *lwcollection_as_lwgeom(LWCOLLECTION *obj) { return (LWGEOM *)obj; }
341
+ LWGEOM *lwpoly_as_lwgeom(LWPOLY *obj) { return (LWGEOM *)obj; }
342
+ LWGEOM *lwline_as_lwgeom(LWLINE *obj) { return (LWGEOM *)obj; }
343
+ LWGEOM *lwpoint_as_lwgeom(LWPOINT *obj) { return (LWGEOM *)obj; }
344
+
345
+ void
346
+ lwgeom_release(LWGEOM *lwgeom)
347
+ {
348
+ uint32 i;
349
+ LWCOLLECTION *col;
350
+
351
+ #ifdef INTEGRITY_CHECKS
352
+ if ( ! lwgeom )
353
+ lwerror("lwgeom_release: someone called on 0x0");
354
+ #endif
355
+
356
+ /* Drop bounding box (always a copy) */
357
+ if ( lwgeom->bbox ) {
358
+ LWDEBUG(3, "lwgeom_release: releasing bbox.");
359
+
360
+ lwfree(lwgeom->bbox);
361
+ }
362
+
363
+ /* Collection */
364
+ if ( (col=lwgeom_as_lwcollection(lwgeom)) )
365
+ {
366
+ LWDEBUG(3, "lwgeom_release: Releasing collection.");
367
+
368
+ for (i=0; i<col->ngeoms; i++)
369
+ {
370
+ lwgeom_release(col->geoms[i]);
371
+ }
372
+ lwfree(lwgeom);
373
+ }
374
+
375
+ /* Single element */
376
+ else lwfree(lwgeom);
377
+
378
+ }
379
+
380
+
381
+ /* Clone an LWGEOM object. POINTARRAY are not copied. */
382
+ LWGEOM *
383
+ lwgeom_clone(const LWGEOM *lwgeom)
384
+ {
385
+ LWDEBUGF(2, "lwgeom_clone called with %p, %d", lwgeom, TYPE_GETTYPE(lwgeom->type));
386
+
387
+ switch(TYPE_GETTYPE(lwgeom->type))
388
+ {
389
+ case POINTTYPE:
390
+ return (LWGEOM *)lwpoint_clone((LWPOINT *)lwgeom);
391
+ case LINETYPE:
392
+ return (LWGEOM *)lwline_clone((LWLINE *)lwgeom);
393
+ case CIRCSTRINGTYPE:
394
+ return (LWGEOM *)lwcircstring_clone((LWCIRCSTRING *)lwgeom);
395
+ case POLYGONTYPE:
396
+ return (LWGEOM *)lwpoly_clone((LWPOLY *)lwgeom);
397
+ case COMPOUNDTYPE:
398
+ case CURVEPOLYTYPE:
399
+ case MULTIPOINTTYPE:
400
+ case MULTILINETYPE:
401
+ case MULTICURVETYPE:
402
+ case MULTIPOLYGONTYPE:
403
+ case MULTISURFACETYPE:
404
+ case COLLECTIONTYPE:
405
+ return (LWGEOM *)lwcollection_clone((LWCOLLECTION *)lwgeom);
406
+ default:
407
+ return NULL;
408
+ }
409
+ }
410
+
411
+ /*
412
+ * Add 'what' to 'to' at position 'where'
413
+ *
414
+ * where=0 == prepend
415
+ * where=-1 == append
416
+ * Appended-to LWGEOM gets a new type based on new condition.
417
+ * Mix of dimensions is not allowed (TODO: allow it?).
418
+ */
419
+ LWGEOM *
420
+ lwgeom_add(const LWGEOM *to, uint32 where, const LWGEOM *what)
421
+ {
422
+ if ( TYPE_NDIMS(what->type) != TYPE_NDIMS(to->type) )
423
+ {
424
+ lwerror("lwgeom_add: mixed dimensions not supported");
425
+ return NULL;
426
+ }
427
+
428
+ LWDEBUGF(2, "lwgeom_add(%s, %d, %s) called",
429
+ lwgeom_typename(TYPE_GETTYPE(to->type)),
430
+ where,
431
+ lwgeom_typename(TYPE_GETTYPE(what->type)));
432
+
433
+ switch(TYPE_GETTYPE(to->type))
434
+ {
435
+ case POINTTYPE:
436
+ return (LWGEOM *)lwpoint_add((const LWPOINT *)to, where, what);
437
+ case LINETYPE:
438
+ return (LWGEOM *)lwline_add((const LWLINE *)to, where, what);
439
+
440
+ case CIRCSTRINGTYPE:
441
+ return (LWGEOM *)lwcircstring_add((const LWCIRCSTRING *)to, where, what);
442
+
443
+ case POLYGONTYPE:
444
+ return (LWGEOM *)lwpoly_add((const LWPOLY *)to, where, what);
445
+
446
+ case COMPOUNDTYPE:
447
+ return (LWGEOM *)lwcompound_add((const LWCOMPOUND *)to, where, what);
448
+
449
+ case CURVEPOLYTYPE:
450
+ return (LWGEOM *)lwcurvepoly_add((const LWCURVEPOLY *)to, where, what);
451
+
452
+ case MULTIPOINTTYPE:
453
+ return (LWGEOM *)lwmpoint_add((const LWMPOINT *)to,
454
+ where, what);
455
+
456
+ case MULTILINETYPE:
457
+ return (LWGEOM *)lwmline_add((const LWMLINE *)to,
458
+ where, what);
459
+
460
+ case MULTICURVETYPE:
461
+ return (LWGEOM *)lwmcurve_add((const LWMCURVE *)to,
462
+ where, what);
463
+
464
+ case MULTIPOLYGONTYPE:
465
+ return (LWGEOM *)lwmpoly_add((const LWMPOLY *)to,
466
+ where, what);
467
+
468
+ case MULTISURFACETYPE:
469
+ return (LWGEOM *)lwmsurface_add((const LWMSURFACE *)to,
470
+ where, what);
471
+
472
+ case COLLECTIONTYPE:
473
+ return (LWGEOM *)lwcollection_add(
474
+ (const LWCOLLECTION *)to, where, what);
475
+
476
+ default:
477
+ lwerror("lwgeom_add: unknown geometry type: %d",
478
+ TYPE_GETTYPE(to->type));
479
+ return NULL;
480
+ }
481
+ }
482
+
483
+
484
+ /*
485
+ * Return an alloced string
486
+ */
487
+ char *
488
+ lwgeom_to_ewkt(LWGEOM *lwgeom, int flags)
489
+ {
490
+ LWGEOM_UNPARSER_RESULT lwg_unparser_result;
491
+ uchar *serialized = lwgeom_serialize(lwgeom);
492
+ int result;
493
+
494
+ if ( ! serialized ) {
495
+ lwerror("Error serializing geom %p", lwgeom);
496
+ }
497
+
498
+ result = unparse_WKT(&lwg_unparser_result, serialized, lwalloc, lwfree, flags);
499
+ lwfree(serialized);
500
+
501
+ return lwg_unparser_result.wkoutput;
502
+ }
503
+
504
+ /*
505
+ * Return an alloced string
506
+ */
507
+ char *
508
+ lwgeom_to_hexwkb(LWGEOM *lwgeom, int flags, unsigned int byteorder)
509
+ {
510
+ LWGEOM_UNPARSER_RESULT lwg_unparser_result;
511
+ uchar *serialized = lwgeom_serialize(lwgeom);
512
+ int result;
513
+
514
+ result = unparse_WKB(&lwg_unparser_result, serialized, lwalloc, lwfree, flags, byteorder,1);
515
+
516
+ lwfree(serialized);
517
+ return lwg_unparser_result.wkoutput;
518
+ }
519
+
520
+ /*
521
+ * Return an alloced string
522
+ */
523
+ uchar *
524
+ lwgeom_to_ewkb(LWGEOM *lwgeom, int flags, char byteorder, size_t *outsize)
525
+ {
526
+ LWGEOM_UNPARSER_RESULT lwg_unparser_result;
527
+ uchar *serialized = lwgeom_serialize(lwgeom);
528
+ int result;
529
+
530
+ /*
531
+ * We cast return to "unsigned" char as we are
532
+ * requesting a "binary" output, not HEX
533
+ * (last argument set to 0)
534
+ */
535
+ result = unparse_WKB(&lwg_unparser_result, serialized, lwalloc, lwfree,
536
+ flags, byteorder, 0);
537
+ lwfree(serialized);
538
+ return (uchar *)lwg_unparser_result.wkoutput;
539
+ }
540
+
541
+ /*
542
+ * Make an LWGEOM object from a EWKB binary representation.
543
+ * Currently highly unoptimized as it:
544
+ * - convert EWKB to HEXEWKB
545
+ * - construct PG_LWGEOM
546
+ * - deserialize it
547
+ */
548
+ LWGEOM *
549
+ lwgeom_from_ewkb(uchar *ewkb, int flags, size_t size)
550
+ {
551
+ size_t hexewkblen = size*2;
552
+ char *hexewkb;
553
+ long int i;
554
+ int result;
555
+ LWGEOM *ret;
556
+ LWGEOM_PARSER_RESULT lwg_parser_result;
557
+
558
+ /* "HEXify" the EWKB */
559
+ hexewkb = lwalloc(hexewkblen+1);
560
+ for (i=0; i<size; ++i) deparse_hex(ewkb[i], &hexewkb[i*2]);
561
+ hexewkb[hexewkblen] = '\0';
562
+
563
+ /* Rely on grammar parser to construct a LWGEOM */
564
+ result = serialized_lwgeom_from_ewkt(&lwg_parser_result, hexewkb, flags);
565
+ if (result)
566
+ lwerror("%s", (char *)lwg_parser_result.message);
567
+
568
+ /* Free intermediate HEXified representation */
569
+ lwfree(hexewkb);
570
+
571
+ /* Deserialize */
572
+ ret = lwgeom_deserialize(lwg_parser_result.serialized_lwgeom);
573
+
574
+ return ret;
575
+ }
576
+
577
+ /*
578
+ * Make an LWGEOM object from a EWKT representation.
579
+ */
580
+ LWGEOM *
581
+ lwgeom_from_ewkt(char *ewkt, int flags)
582
+ {
583
+ int result;
584
+ LWGEOM *ret;
585
+ LWGEOM_PARSER_RESULT lwg_parser_result;
586
+
587
+ /* Rely on grammar parser to construct a LWGEOM */
588
+ result = serialized_lwgeom_from_ewkt(&lwg_parser_result, ewkt, flags);
589
+ if (result)
590
+ lwerror("%s", (char *)lwg_parser_result.message);
591
+
592
+ /* Deserialize */
593
+ ret = lwgeom_deserialize(lwg_parser_result.serialized_lwgeom);
594
+
595
+ return ret;
596
+ }
597
+
598
+ /*
599
+ * Parser functions for working with serialized LWGEOMs. Useful for cases where
600
+ * the function input is already serialized, e.g. some input and output functions
601
+ */
602
+
603
+ /*
604
+ * Make a serialzed LWGEOM object from a WKT input string
605
+ */
606
+ int
607
+ serialized_lwgeom_from_ewkt(LWGEOM_PARSER_RESULT *lwg_parser_result, char *wkt_input, int flags)
608
+ {
609
+
610
+ int result = parse_lwg(lwg_parser_result, wkt_input, flags,
611
+ lwalloc, lwerror);
612
+
613
+ LWDEBUGF(2, "serialized_lwgeom_from_ewkt with %s",wkt_input);
614
+
615
+ return result;
616
+ }
617
+
618
+ /*
619
+ * Return an alloced string
620
+ */
621
+ int
622
+ serialized_lwgeom_to_ewkt(LWGEOM_UNPARSER_RESULT *lwg_unparser_result, uchar *serialized, int flags)
623
+ {
624
+ int result;
625
+
626
+ result = unparse_WKT(lwg_unparser_result, serialized, lwalloc, lwfree, flags);
627
+
628
+ return result;
629
+ }
630
+
631
+ /*
632
+ * Return an alloced string
633
+ */
634
+ int
635
+ serialized_lwgeom_from_hexwkb(LWGEOM_PARSER_RESULT *lwg_parser_result, char *hexwkb_input, int flags)
636
+ {
637
+ /* NOTE: it is actually the same combined WKT/WKB parser that decodes HEXEWKB into LWGEOMs! */
638
+ int result = parse_lwg(lwg_parser_result, hexwkb_input, flags,
639
+ lwalloc, lwerror);
640
+
641
+ LWDEBUGF(2, "serialized_lwgeom_from_hexwkb with %s", hexwkb_input);
642
+
643
+ return result;
644
+ }
645
+
646
+ /*
647
+ * Return an alloced string
648
+ */
649
+ int
650
+ serialized_lwgeom_to_hexwkb(LWGEOM_UNPARSER_RESULT *lwg_unparser_result, uchar *serialized, int flags, unsigned int byteorder)
651
+ {
652
+ int result;
653
+
654
+ result = unparse_WKB(lwg_unparser_result, serialized, lwalloc, lwfree, flags, byteorder, 1);
655
+
656
+ return result;
657
+ }
658
+
659
+ /*
660
+ * Return an alloced string
661
+ */
662
+ int
663
+ serialized_lwgeom_to_ewkb(LWGEOM_UNPARSER_RESULT *lwg_unparser_result, uchar *serialized, int flags, unsigned int byteorder)
664
+ {
665
+ int result;
666
+
667
+ result = unparse_WKB(lwg_unparser_result, serialized, lwalloc, lwfree, flags, byteorder, 0);
668
+
669
+ return result;
670
+ }
671
+
672
+ /*
673
+ * geom1 same as geom2
674
+ * iff
675
+ * + have same type
676
+ * + have same # objects
677
+ * + have same bvol
678
+ * + each object in geom1 has a corresponding object in geom2 (see above)
679
+ */
680
+ char
681
+ lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2)
682
+ {
683
+ LWDEBUGF(2, "lwgeom_same(%s, %s) called",
684
+ lwgeom_typename(TYPE_GETTYPE(lwgeom1->type)),
685
+ lwgeom_typename(TYPE_GETTYPE(lwgeom2->type)));
686
+
687
+ if ( TYPE_GETTYPE(lwgeom1->type) != TYPE_GETTYPE(lwgeom2->type) )
688
+ {
689
+ LWDEBUG(3, " type differ");
690
+
691
+ return 0;
692
+ }
693
+
694
+ if ( TYPE_GETZM(lwgeom1->type) != TYPE_GETZM(lwgeom2->type) )
695
+ {
696
+ LWDEBUG(3, " ZM flags differ");
697
+
698
+ return 0;
699
+ }
700
+
701
+ /* Check boxes if both already computed */
702
+ if ( lwgeom1->bbox && lwgeom2->bbox )
703
+ {
704
+ /*lwnotice("bbox1:%p, bbox2:%p", lwgeom1->bbox, lwgeom2->bbox);*/
705
+ if ( ! box2d_same(lwgeom1->bbox, lwgeom2->bbox) )
706
+ {
707
+ LWDEBUG(3, " bounding boxes differ");
708
+
709
+ return 0;
710
+ }
711
+ }
712
+
713
+ /* geoms have same type, invoke type-specific function */
714
+ switch(TYPE_GETTYPE(lwgeom1->type))
715
+ {
716
+ case POINTTYPE:
717
+ return lwpoint_same((LWPOINT *)lwgeom1,
718
+ (LWPOINT *)lwgeom2);
719
+ case LINETYPE:
720
+ return lwline_same((LWLINE *)lwgeom1,
721
+ (LWLINE *)lwgeom2);
722
+ case POLYGONTYPE:
723
+ return lwpoly_same((LWPOLY *)lwgeom1,
724
+ (LWPOLY *)lwgeom2);
725
+ case MULTIPOINTTYPE:
726
+ case MULTILINETYPE:
727
+ case MULTIPOLYGONTYPE:
728
+ case COLLECTIONTYPE:
729
+ return lwcollection_same((LWCOLLECTION *)lwgeom1,
730
+ (LWCOLLECTION *)lwgeom2);
731
+ default:
732
+ lwerror("lwgeom_same: unsupported geometry type: %s",
733
+ lwgeom_typename(TYPE_GETTYPE(lwgeom1->type)));
734
+ return 0;
735
+ }
736
+
737
+ }
738
+
739
+ void
740
+ lwgeom_changed(LWGEOM *lwgeom)
741
+ {
742
+ if ( lwgeom->bbox ) lwfree(lwgeom->bbox);
743
+ lwgeom->bbox = NULL;
744
+ TYPE_SETHASBBOX(lwgeom->type, 0);
745
+ }
746
+
747
+ void
748
+ lwgeom_drop_bbox(LWGEOM *lwgeom)
749
+ {
750
+ if ( lwgeom->bbox ) lwfree(lwgeom->bbox);
751
+ lwgeom->bbox = NULL;
752
+ TYPE_SETHASBBOX(lwgeom->type, 0);
753
+ }
754
+
755
+ /*
756
+ * Ensure there's a box in the LWGEOM.
757
+ * If the box is already there just return,
758
+ * else compute it.
759
+ */
760
+ void
761
+ lwgeom_add_bbox(LWGEOM *lwgeom)
762
+ {
763
+ if ( lwgeom->bbox ) return;
764
+ lwgeom->bbox = lwgeom_compute_box2d(lwgeom);
765
+ TYPE_SETHASBBOX(lwgeom->type, 1);
766
+ }
767
+
768
+ void
769
+ lwgeom_dropSRID(LWGEOM *lwgeom)
770
+ {
771
+ TYPE_SETHASSRID(lwgeom->type, 0);
772
+ lwgeom->SRID = -1;
773
+ }
774
+
775
+ LWGEOM *
776
+ lwgeom_segmentize2d(LWGEOM *lwgeom, double dist)
777
+ {
778
+ switch(TYPE_GETTYPE(lwgeom->type))
779
+ {
780
+ case LINETYPE:
781
+ return (LWGEOM *)lwline_segmentize2d((LWLINE *)lwgeom,
782
+ dist);
783
+ case POLYGONTYPE:
784
+ return (LWGEOM *)lwpoly_segmentize2d((LWPOLY *)lwgeom,
785
+ dist);
786
+ case MULTILINETYPE:
787
+ case MULTIPOLYGONTYPE:
788
+ case COLLECTIONTYPE:
789
+ return (LWGEOM *)lwcollection_segmentize2d(
790
+ (LWCOLLECTION *)lwgeom, dist);
791
+
792
+ default:
793
+ return lwgeom_clone(lwgeom);
794
+ }
795
+ }
796
+
797
+ void
798
+ lwgeom_longitude_shift(LWGEOM *lwgeom)
799
+ {
800
+ int i;
801
+ switch(TYPE_GETTYPE(lwgeom->type))
802
+ {
803
+ LWPOINT *point;
804
+ LWLINE *line;
805
+ LWPOLY *poly;
806
+ LWCOLLECTION *coll;
807
+
808
+ case POINTTYPE:
809
+ point = (LWPOINT *)lwgeom;
810
+ ptarray_longitude_shift(point->point);
811
+ return;
812
+ case LINETYPE:
813
+ line = (LWLINE *)lwgeom;
814
+ ptarray_longitude_shift(line->points);
815
+ return;
816
+ case POLYGONTYPE:
817
+ poly = (LWPOLY *)lwgeom;
818
+ for (i=0; i<poly->nrings; i++)
819
+ ptarray_longitude_shift(poly->rings[i]);
820
+ return;
821
+ case MULTIPOINTTYPE:
822
+ case MULTILINETYPE:
823
+ case MULTIPOLYGONTYPE:
824
+ case COLLECTIONTYPE:
825
+ coll = (LWCOLLECTION *)lwgeom;
826
+ for (i=0; i<coll->ngeoms; i++)
827
+ lwgeom_longitude_shift(coll->geoms[i]);
828
+ return;
829
+ default:
830
+ lwerror("%s:%d: unsupported geom type: %s",
831
+ __FILE__, __LINE__,
832
+ lwgeom_typename(TYPE_GETTYPE(lwgeom->type)));
833
+ }
834
+ }
835
+
836
+
837
+ int
838
+ lwgeom_contains_subgeoms(int type)
839
+ {
840
+ /* Return TRUE if the geometry may contain sub-geometries, i.e. it is a MULTI* or COMPOUNDCURVE */
841
+ switch(type)
842
+ {
843
+ case MULTIPOINTTYPE:
844
+ case MULTILINETYPE:
845
+ case MULTIPOLYGONTYPE:
846
+ case COLLECTIONTYPE:
847
+ case COMPOUNDTYPE:
848
+ case MULTICURVETYPE:
849
+ case MULTISURFACETYPE:
850
+ return -1;
851
+ break;
852
+
853
+ default:
854
+ return 0;
855
+ }
856
+ }
857
+
858
+ void lwgeom_free(LWGEOM *lwgeom) {
859
+
860
+ switch(TYPE_GETTYPE(lwgeom->type))
861
+ {
862
+ case POINTTYPE:
863
+ lwpoint_free((LWPOINT *)lwgeom);
864
+ break;
865
+ case LINETYPE:
866
+ lwline_free((LWLINE *)lwgeom);
867
+ break;
868
+ case POLYGONTYPE:
869
+ lwpoly_free((LWPOLY *)lwgeom);
870
+ break;
871
+ case MULTIPOINTTYPE:
872
+ lwmpoint_free((LWMPOINT *)lwgeom);
873
+ break;
874
+ case MULTILINETYPE:
875
+ lwmline_free((LWMLINE *)lwgeom);
876
+ break;
877
+ case MULTIPOLYGONTYPE:
878
+ lwmpoly_free((LWMPOLY *)lwgeom);
879
+ break;
880
+ case COLLECTIONTYPE:
881
+ lwcollection_free((LWCOLLECTION *)lwgeom);
882
+ break;
883
+ }
884
+ return;
885
+
886
+ };