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,129 @@
1
+ /**********************************************************************
2
+ * $Id: lwmsurface.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
+
19
+ LWMSURFACE *
20
+ lwmsurface_deserialize(uchar *srl)
21
+ {
22
+ LWMSURFACE *result;
23
+ LWGEOM_INSPECTED *insp;
24
+ int stype;
25
+ int type = lwgeom_getType(srl[0]);
26
+ int i;
27
+
28
+ LWDEBUG(2, "lwmsurface_deserialize called");
29
+
30
+ if(type != MULTISURFACETYPE)
31
+ {
32
+ lwerror("lwmsurface_deserialize called on a non-multisurface: %d", type);
33
+ return NULL;
34
+ }
35
+
36
+ insp = lwgeom_inspect(srl);
37
+
38
+ result = lwalloc(sizeof(LWMSURFACE));
39
+ result->type = insp->type;
40
+ result->SRID = insp->SRID;
41
+ result->ngeoms = insp->ngeometries;
42
+ result->geoms = lwalloc(sizeof(LWPOLY *)*insp->ngeometries);
43
+
44
+ if(lwgeom_hasBBOX(srl[0]))
45
+ {
46
+ result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
47
+ memcpy(result->bbox, srl + 1, sizeof(BOX2DFLOAT4));
48
+ }
49
+ else result->bbox = NULL;
50
+
51
+ for(i = 0; i < insp->ngeometries; i++)
52
+ {
53
+ stype = lwgeom_getType(insp->sub_geoms[i][0]);
54
+ if(stype == POLYGONTYPE)
55
+ {
56
+ result->geoms[i] = (LWGEOM *)lwpoly_deserialize(insp->sub_geoms[i]);
57
+ }
58
+ else if(stype == CURVEPOLYTYPE)
59
+ {
60
+ result->geoms[i] = (LWGEOM *)lwcurvepoly_deserialize(insp->sub_geoms[i]);
61
+ }
62
+ else
63
+ {
64
+ lwerror("Only Polygons and Curved Polygons are supported in a MultiSurface.");
65
+ lwfree(result);
66
+ lwfree(insp);
67
+ return NULL;
68
+ }
69
+
70
+ if(TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type))
71
+ {
72
+ lwerror("Mixed dimensions (multisurface: %d, surface %d:%d",
73
+ TYPE_NDIMS(result->type), i,
74
+ TYPE_NDIMS(result->geoms[i]->type));
75
+ lwfree(result);
76
+ lwfree(insp);
77
+ return NULL;
78
+ }
79
+ }
80
+ return result;
81
+ }
82
+
83
+ /*
84
+ * Add 'what' to this multisurface at position 'where'
85
+ * where=0 == prepend
86
+ * where=-1 == append
87
+ * Returns a MULTISURFACE or a COLLECTION
88
+ */
89
+ LWGEOM *
90
+ lwmsurface_add(const LWMSURFACE *to, uint32 where, const LWGEOM *what)
91
+ {
92
+ LWCOLLECTION *col;
93
+ LWGEOM **geoms;
94
+ int newtype;
95
+ uint32 i;
96
+
97
+ if(where == -1) where = to->ngeoms;
98
+ else if(where < -1 || where > to->ngeoms)
99
+ {
100
+ lwerror("lwmsurface_add: add position out of range %d..%d",
101
+ -1, to->ngeoms);
102
+ return NULL;
103
+ }
104
+
105
+ /* dimensions compatibility are checked by caller */
106
+
107
+ /* Construct geoms array */
108
+ geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
109
+ for(i = 0; i < where; i++)
110
+ {
111
+ geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]);
112
+ }
113
+ geoms[where] = lwgeom_clone(what);
114
+ for(i = where; i < to->ngeoms; i++)
115
+ {
116
+ geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]);
117
+ }
118
+
119
+ if(TYPE_GETTYPE(what->type) == POLYGONTYPE
120
+ || TYPE_GETTYPE(what->type) == CURVEPOLYTYPE)
121
+ newtype = MULTISURFACETYPE;
122
+ else newtype = COLLECTIONTYPE;
123
+
124
+ col = lwcollection_construct(newtype,
125
+ to->SRID, NULL, to->ngeoms + 1, geoms);
126
+
127
+ return (LWGEOM *)col;
128
+ }
129
+
@@ -0,0 +1,439 @@
1
+ /**********************************************************************
2
+ * $Id: lwpoint.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
+ /*
20
+ * Convert this point into its serialize form
21
+ * result's first char will be the 8bit type. See serialized form doc
22
+ */
23
+ uchar *
24
+ lwpoint_serialize(LWPOINT *point)
25
+ {
26
+ size_t size, retsize;
27
+ uchar *result;
28
+
29
+ size = lwpoint_serialize_size(point);
30
+ result = lwalloc(size);
31
+ lwpoint_serialize_buf(point, result, &retsize);
32
+
33
+ if ( retsize != size )
34
+ {
35
+ lwerror("lwpoint_serialize_size returned %d, ..serialize_buf returned %d", size, retsize);
36
+ }
37
+
38
+ return result;
39
+ }
40
+
41
+ /*
42
+ * Convert this point into its serialize form writing it into
43
+ * the given buffer, and returning number of bytes written into
44
+ * the given int pointer.
45
+ * result's first char will be the 8bit type. See serialized form doc
46
+ */
47
+ void
48
+ lwpoint_serialize_buf(LWPOINT *point, uchar *buf, size_t *retsize)
49
+ {
50
+ int size=1;
51
+ char hasSRID;
52
+ uchar *loc;
53
+ int ptsize = pointArray_ptsize(point->point);
54
+
55
+ if ( TYPE_GETZM(point->type) != TYPE_GETZM(point->point->dims) )
56
+ lwerror("Dimensions mismatch in lwpoint");
57
+
58
+ LWDEBUGF(2, "lwpoint_serialize_buf(%p, %p) called", point, buf);
59
+ /*printLWPOINT(point); */
60
+
61
+ hasSRID = (point->SRID != -1);
62
+
63
+ if (hasSRID) size +=4; /*4 byte SRID */
64
+ if (point->bbox) size += sizeof(BOX2DFLOAT4); /* bvol */
65
+
66
+ size += sizeof(double)*TYPE_NDIMS(point->type);
67
+
68
+ buf[0] = (uchar) lwgeom_makeType_full(
69
+ TYPE_HASZ(point->type), TYPE_HASM(point->type),
70
+ hasSRID, POINTTYPE, point->bbox?1:0);
71
+ loc = buf+1;
72
+
73
+ if (point->bbox)
74
+ {
75
+ memcpy(loc, point->bbox, sizeof(BOX2DFLOAT4));
76
+ loc += sizeof(BOX2DFLOAT4);
77
+ }
78
+
79
+ if (hasSRID)
80
+ {
81
+ memcpy(loc, &point->SRID, sizeof(int32));
82
+ loc += 4;
83
+ }
84
+
85
+ /* copy in points */
86
+ memcpy(loc, getPoint_internal(point->point, 0), ptsize);
87
+
88
+ if (retsize) *retsize = size;
89
+ }
90
+
91
+ /*
92
+ * Find bounding box (standard one)
93
+ * zmin=zmax=NO_Z_VALUE if 2d
94
+ */
95
+ BOX3D *
96
+ lwpoint_compute_box3d(LWPOINT *point)
97
+ {
98
+ LWDEBUGF(2, "lwpoint_compute_box3d called with point %p", point);
99
+
100
+ if (point == NULL)
101
+ {
102
+ LWDEBUG(3, "lwpoint_compute_box3d returning NULL");
103
+
104
+ return NULL;
105
+ }
106
+
107
+ LWDEBUG(3, "lwpoint_compute_box3d returning ptarray_compute_box3d return");
108
+
109
+ return ptarray_compute_box3d(point->point);
110
+ }
111
+
112
+ /*
113
+ * Convenience functions to hide the POINTARRAY
114
+ * TODO: obsolete this
115
+ */
116
+ int
117
+ lwpoint_getPoint2d_p(const LWPOINT *point, POINT2D *out)
118
+ {
119
+ return getPoint2d_p(point->point, 0, out);
120
+ }
121
+
122
+ /* convenience functions to hide the POINTARRAY */
123
+ int
124
+ lwpoint_getPoint3dz_p(const LWPOINT *point, POINT3DZ *out)
125
+ {
126
+ return getPoint3dz_p(point->point,0,out);
127
+ }
128
+ int
129
+ lwpoint_getPoint3dm_p(const LWPOINT *point, POINT3DM *out)
130
+ {
131
+ return getPoint3dm_p(point->point,0,out);
132
+ }
133
+ int
134
+ lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out)
135
+ {
136
+ return getPoint4d_p(point->point,0,out);
137
+ }
138
+
139
+ /* find length of this deserialized point */
140
+ size_t
141
+ lwpoint_serialize_size(LWPOINT *point)
142
+ {
143
+ size_t size = 1; /* type */
144
+
145
+ LWDEBUG(2, "lwpoint_serialize_size called");
146
+
147
+ if ( point->SRID != -1 ) size += 4; /* SRID */
148
+ if ( point->bbox ) size += sizeof(BOX2DFLOAT4);
149
+
150
+ size += TYPE_NDIMS(point->type) * sizeof(double); /* point */
151
+
152
+ LWDEBUGF(3, "lwpoint_serialize_size returning %d", size);
153
+
154
+ return size;
155
+ }
156
+
157
+ /*
158
+ * Construct a new point. point will not be copied
159
+ * use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
160
+ */
161
+ LWPOINT *
162
+ lwpoint_construct(int SRID, BOX2DFLOAT4 *bbox, POINTARRAY *point)
163
+ {
164
+ LWPOINT *result ;
165
+
166
+ if (point == NULL)
167
+ return NULL; /* error */
168
+
169
+ result = lwalloc(sizeof(LWPOINT));
170
+ result->type = lwgeom_makeType_full(TYPE_HASZ(point->dims), TYPE_HASM(point->dims), (SRID!=-1), POINTTYPE, 0);
171
+ result->SRID = SRID;
172
+ result->point = point;
173
+ result->bbox = bbox;
174
+
175
+ return result;
176
+ }
177
+
178
+ LWPOINT *
179
+ make_lwpoint2d(int SRID, double x, double y)
180
+ {
181
+ POINT2D p;
182
+ POINTARRAY *pa = ptarray_construct(0, 0, 1);
183
+
184
+ p.x = x;
185
+ p.y = y;
186
+
187
+ memcpy(getPoint_internal(pa, 0), &p, sizeof(POINT2D));
188
+
189
+ return lwpoint_construct(SRID, NULL, pa);
190
+ }
191
+
192
+ LWPOINT *
193
+ make_lwpoint3dz(int SRID, double x, double y, double z)
194
+ {
195
+ POINT3DZ p;
196
+ POINTARRAY *pa = ptarray_construct(1, 0, 1);
197
+
198
+ p.x = x;
199
+ p.y = y;
200
+ p.z = z;
201
+
202
+ memcpy(getPoint_internal(pa, 0), &p, sizeof(POINT3DZ));
203
+
204
+ return lwpoint_construct(SRID, NULL, pa);
205
+ }
206
+
207
+ LWPOINT *
208
+ make_lwpoint3dm(int SRID, double x, double y, double m)
209
+ {
210
+ POINTARRAY *pa = ptarray_construct(0, 1, 1);
211
+ POINT3DM p;
212
+
213
+ p.x = x;
214
+ p.y = y;
215
+ p.m = m;
216
+
217
+ memcpy(getPoint_internal(pa, 0), &p, sizeof(POINT3DM));
218
+
219
+ return lwpoint_construct(SRID, NULL, pa);
220
+ }
221
+
222
+ LWPOINT *
223
+ make_lwpoint4d(int SRID, double x, double y, double z, double m)
224
+ {
225
+ POINTARRAY *pa = ptarray_construct(1, 1, 1);
226
+ POINT4D p;
227
+
228
+ p.x = x;
229
+ p.y = y;
230
+ p.z = z;
231
+ p.m = m;
232
+
233
+ memcpy(getPoint_internal(pa, 0), &p, sizeof(POINT4D));
234
+
235
+ return lwpoint_construct(SRID, NULL, pa);
236
+ }
237
+
238
+ /*
239
+ * Given the LWPOINT serialized form (or a pointer into a muli* one)
240
+ * construct a proper LWPOINT.
241
+ * serialized_form should point to the 8bit type format (with type = 1)
242
+ * See serialized form doc
243
+ */
244
+ LWPOINT *
245
+ lwpoint_deserialize(uchar *serialized_form)
246
+ {
247
+ uchar type;
248
+ int geom_type;
249
+ LWPOINT *result;
250
+ uchar *loc = NULL;
251
+ POINTARRAY *pa;
252
+
253
+ LWDEBUG(2, "lwpoint_deserialize called");
254
+
255
+ result = (LWPOINT*) lwalloc(sizeof(LWPOINT)) ;
256
+
257
+ type = serialized_form[0];
258
+ geom_type = lwgeom_getType(type);
259
+
260
+ if ( geom_type != POINTTYPE)
261
+ {
262
+ lwerror("lwpoint_deserialize: attempt to deserialize a point which is really a %s", lwgeom_typename(geom_type));
263
+ return NULL;
264
+ }
265
+ result->type = type;
266
+
267
+ loc = serialized_form+1;
268
+
269
+ if (lwgeom_hasBBOX(type))
270
+ {
271
+ LWDEBUG(3, "lwpoint_deserialize: input has bbox");
272
+
273
+ result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
274
+ memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4));
275
+ loc += sizeof(BOX2DFLOAT4);
276
+ }
277
+ else
278
+ {
279
+ result->bbox = NULL;
280
+ }
281
+
282
+ if ( lwgeom_hasSRID(type))
283
+ {
284
+ LWDEBUG(3, "lwpoint_deserialize: input has SRID");
285
+
286
+ result->SRID = lw_get_int32(loc);
287
+ loc += 4; /* type + SRID */
288
+ }
289
+ else
290
+ {
291
+ result->SRID = -1;
292
+ }
293
+
294
+ /* we've read the type (1 byte) and SRID (4 bytes, if present) */
295
+
296
+ pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), 1);
297
+
298
+ result->point = pa;
299
+
300
+ return result;
301
+ }
302
+
303
+ void lwpoint_free(LWPOINT *pt)
304
+ {
305
+ if(pt->point)
306
+ ptarray_free(pt->point);
307
+ lwfree(pt);
308
+ }
309
+
310
+ void printLWPOINT(LWPOINT *point)
311
+ {
312
+ lwnotice("LWPOINT {");
313
+ lwnotice(" ndims = %i", (int)TYPE_NDIMS(point->type));
314
+ lwnotice(" BBOX = %i", TYPE_HASBBOX(point->type) ? 1 : 0 );
315
+ lwnotice(" SRID = %i", (int)point->SRID);
316
+ printPA(point->point);
317
+ lwnotice("}");
318
+ }
319
+
320
+ int
321
+ lwpoint_compute_box2d_p(LWPOINT *point, BOX2DFLOAT4 *box)
322
+ {
323
+ return ptarray_compute_box2d_p(point->point, box);
324
+ }
325
+
326
+ /* Clone LWPOINT object. POINTARRAY is not copied. */
327
+ LWPOINT *
328
+ lwpoint_clone(const LWPOINT *g)
329
+ {
330
+ LWPOINT *ret = lwalloc(sizeof(LWPOINT));
331
+
332
+ LWDEBUG(2, "lwpoint_clone called");
333
+
334
+ memcpy(ret, g, sizeof(LWPOINT));
335
+ if ( g->bbox ) ret->bbox = box2d_clone(g->bbox);
336
+ return ret;
337
+ }
338
+
339
+ /*
340
+ * Add 'what' to this point at position 'where'.
341
+ * where=0 == prepend
342
+ * where=-1 == append
343
+ * Returns a MULTIPOINT or a GEOMETRYCOLLECTION
344
+ */
345
+ LWGEOM *
346
+ lwpoint_add(const LWPOINT *to, uint32 where, const LWGEOM *what)
347
+ {
348
+ LWCOLLECTION *col;
349
+ LWGEOM **geoms;
350
+ int newtype;
351
+
352
+ if ( where != -1 && where != 0 )
353
+ {
354
+ lwerror("lwpoint_add only supports 0 or -1 as second argument, got %d", where);
355
+ return NULL;
356
+ }
357
+
358
+ /* dimensions compatibility are checked by caller */
359
+
360
+
361
+ /* Construct geoms array */
362
+ geoms = lwalloc(sizeof(LWGEOM *)*2);
363
+ if ( where == -1 ) /* append */
364
+ {
365
+ geoms[0] = lwgeom_clone((LWGEOM *)to);
366
+ geoms[1] = lwgeom_clone(what);
367
+ }
368
+ else /* prepend */
369
+ {
370
+ geoms[0] = lwgeom_clone(what);
371
+ geoms[1] = lwgeom_clone((LWGEOM *)to);
372
+ }
373
+ /* reset SRID and wantbbox flag from component types */
374
+ lwgeom_dropSRID(geoms[0]);
375
+ lwgeom_drop_bbox(geoms[0]);
376
+ lwgeom_dropSRID(geoms[1]);
377
+ lwgeom_drop_bbox(geoms[1]);
378
+
379
+ /* Find appropriate geom type */
380
+ if ( TYPE_GETTYPE(what->type) == POINTTYPE ) newtype = MULTIPOINTTYPE;
381
+ else newtype = COLLECTIONTYPE;
382
+
383
+ col = lwcollection_construct(newtype,
384
+ to->SRID, NULL,
385
+ 2, geoms);
386
+
387
+ return (LWGEOM *)col;
388
+ }
389
+
390
+ /* Find length of this serialized point */
391
+ size_t
392
+ lwgeom_size_point(const uchar *serialized_point)
393
+ {
394
+ uint32 result = 1;
395
+ uchar type;
396
+ const uchar *loc;
397
+
398
+ type = serialized_point[0];
399
+
400
+ if ( lwgeom_getType(type) != POINTTYPE) return 0;
401
+
402
+ LWDEBUGF(2, "lwgeom_size_point called (%d)", result);
403
+
404
+ loc = serialized_point+1;
405
+
406
+ if (lwgeom_hasBBOX(type))
407
+ {
408
+ loc += sizeof(BOX2DFLOAT4);
409
+ result +=sizeof(BOX2DFLOAT4);
410
+
411
+ LWDEBUGF(3, "lwgeom_size_point: has bbox (%d)", result);
412
+ }
413
+
414
+ if ( lwgeom_hasSRID(type))
415
+ {
416
+ LWDEBUGF(3, "lwgeom_size_point: has srid (%d)", result);
417
+
418
+ loc +=4; /* type + SRID */
419
+ result +=4;
420
+ }
421
+
422
+ result += lwgeom_ndims(type)*sizeof(double);
423
+
424
+ return result;
425
+ }
426
+
427
+ void
428
+ lwpoint_release(LWPOINT *lwpoint)
429
+ {
430
+ lwgeom_release(lwpoint_as_lwgeom(lwpoint));
431
+ }
432
+
433
+
434
+ /* check coordinate equality */
435
+ char
436
+ lwpoint_same(const LWPOINT *p1, const LWPOINT *p2)
437
+ {
438
+ return ptarray_same(p1->point, p2->point);
439
+ }