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,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
+ };