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,52 @@
1
+ /**********************************************************************
2
+ * $Id: lwalgorithm.h 3688 2009-02-11 21:48:13Z pramsey $
3
+ *
4
+ * PostGIS - Spatial Types for PostgreSQL
5
+ * http://postgis.refractions.net
6
+ * Copyright 2008 Paul Ramsey
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 <math.h>
14
+ #include "liblwgeom.h"
15
+
16
+ enum CG_SEGMENT_INTERSECTION_TYPE {
17
+ SEG_ERROR = -1,
18
+ SEG_NO_INTERSECTION = 0,
19
+ SEG_COLINEAR = 1,
20
+ SEG_CROSS_LEFT = 2,
21
+ SEG_CROSS_RIGHT = 3,
22
+ SEG_TOUCH_LEFT = 4,
23
+ SEG_TOUCH_RIGHT = 5
24
+ };
25
+
26
+ double lw_segment_side(POINT2D *p1, POINT2D *p2, POINT2D *q);
27
+ int lw_segment_intersects(POINT2D *p1, POINT2D *p2, POINT2D *q1, POINT2D *q2);
28
+ int lw_segment_envelope_intersects(POINT2D p1, POINT2D p2, POINT2D q1, POINT2D q2);
29
+
30
+
31
+ enum CG_LINE_CROSS_TYPE {
32
+ LINE_NO_CROSS = 0,
33
+ LINE_CROSS_LEFT = -1,
34
+ LINE_CROSS_RIGHT = 1,
35
+ LINE_MULTICROSS_END_LEFT = -2,
36
+ LINE_MULTICROSS_END_RIGHT = 2,
37
+ LINE_MULTICROSS_END_SAME_FIRST_LEFT = -3,
38
+ LINE_MULTICROSS_END_SAME_FIRST_RIGHT = 3
39
+ };
40
+
41
+ int lwline_crossing_direction(LWLINE *l1, LWLINE *l2);
42
+
43
+ double lwpoint_get_ordinate(const POINT4D *p, int ordinate);
44
+ void lwpoint_set_ordinate(POINT4D *p, int ordinate, double value);
45
+ int lwpoint_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int ndims, int ordinate, double interpolation_value);
46
+ LWCOLLECTION *lwline_clip_to_ordinate_range(LWLINE *line, int ordinate, double from, double to);
47
+ LWCOLLECTION *lwmline_clip_to_ordinate_range(LWMLINE *mline, int ordinate, double from, double to);
48
+
49
+ int lwgeom_geohash_precision(BOX3D bbox, BOX3D *bounds);
50
+ char *lwgeom_geohash(const LWGEOM *lwgeom, int precision);
51
+ char *geohash_point(double longitude, double latitude, int precision);
52
+
@@ -0,0 +1,759 @@
1
+ /**********************************************************************
2
+ * $Id: lwcircstring.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 LWCIRCSTRING functions */
14
+
15
+ #include <stdio.h>
16
+ #include <stdlib.h>
17
+ #include <string.h>
18
+ #include <math.h>
19
+ #include "liblwgeom.h"
20
+
21
+ BOX3D *lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3);
22
+ void printLWCIRCSTRING(LWCIRCSTRING *curve);
23
+ void lwcircstring_reverse(LWCIRCSTRING *curve);
24
+ LWCIRCSTRING *lwcircstring_segmentize2d(LWCIRCSTRING *curve, double dist);
25
+ char lwcircstring_same(const LWCIRCSTRING *me, const LWCIRCSTRING *you);
26
+ LWCIRCSTRING *lwcircstring_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points);
27
+ LWCIRCSTRING *lwcircstring_from_lwmpoint(int SRID, LWMPOINT *mpoint);
28
+ LWCIRCSTRING *lwcircstring_addpoint(LWCIRCSTRING *curve, LWPOINT *point, unsigned int where);
29
+ LWCIRCSTRING *lwcircstring_removepoint(LWCIRCSTRING *curve, unsigned int index);
30
+ void lwcircstring_setPoint4d(LWCIRCSTRING *curve, unsigned int index, POINT4D *newpoint);
31
+
32
+
33
+
34
+ #ifndef MAXFLOAT
35
+ #define MAXFLOAT 3.402823466e+38F
36
+ #endif
37
+
38
+ /*
39
+ * Construct a new LWCIRCSTRING. points will *NOT* be copied
40
+ * use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
41
+ */
42
+ LWCIRCSTRING *
43
+ lwcircstring_construct(int SRID, BOX2DFLOAT4 *bbox, POINTARRAY *points)
44
+ {
45
+ LWCIRCSTRING *result;
46
+
47
+ /*
48
+ * The first arc requires three points. Each additional
49
+ * arc requires two more points. Thus the minimum point count
50
+ * is three, and the count must be odd.
51
+ */
52
+ if(points->npoints % 2 != 1 || points->npoints < 3)
53
+ {
54
+ lwerror("lwcircstring_construct: invalid point count %d", points->npoints);
55
+ return NULL;
56
+ }
57
+
58
+ result = (LWCIRCSTRING*) lwalloc(sizeof(LWCIRCSTRING));
59
+
60
+ result->type = lwgeom_makeType_full(
61
+ TYPE_HASZ(points->dims),
62
+ TYPE_HASM(points->dims),
63
+ (SRID!=-1), CIRCSTRINGTYPE, 0);
64
+ result->SRID = SRID;
65
+ result->points = points;
66
+ result->bbox = bbox;
67
+
68
+ return result;
69
+ }
70
+
71
+ /*
72
+ * given the LWGEOM serialized form (or a point into a multi* one)
73
+ * construct a proper LWCIRCSTRING.
74
+ * serialized_form should point to the 8bit type format (with type = 8)
75
+ * See serialized form doc
76
+ */
77
+ LWCIRCSTRING *
78
+ lwcircstring_deserialize(uchar *serialized_form)
79
+ {
80
+ uchar type;
81
+ LWCIRCSTRING *result;
82
+ uchar *loc=NULL;
83
+ uint32 npoints;
84
+ POINTARRAY *pa;
85
+
86
+ type = (uchar)serialized_form[0];
87
+ if(lwgeom_getType(type) != CIRCSTRINGTYPE)
88
+ {
89
+ lwerror("lwcircstring_deserialize: attempt to deserialize a circularstring which is really a %s", lwgeom_typename(type));
90
+ return NULL;
91
+ }
92
+
93
+ result = (LWCIRCSTRING*) lwalloc(sizeof(LWCIRCSTRING));
94
+ result->type = type;
95
+
96
+ loc = serialized_form + 1;
97
+
98
+ if(lwgeom_hasBBOX(type))
99
+ {
100
+ LWDEBUG(3, "lwcircstring_deserialize: input has bbox");
101
+
102
+ result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
103
+ memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4));
104
+ loc += sizeof(BOX2DFLOAT4);
105
+ }
106
+ else
107
+ {
108
+ LWDEBUG(3, "lwcircstring_deserialize: input lacks bbox");
109
+
110
+ result->bbox = NULL;
111
+ }
112
+
113
+ if(lwgeom_hasSRID(type))
114
+ {
115
+ LWDEBUG(3, "lwcircstring_deserialize: input has srid");
116
+
117
+ result->SRID = lw_get_int32(loc);
118
+ loc += 4; /* type + SRID */
119
+ }
120
+ else
121
+ {
122
+ LWDEBUG(3, "lwcircstring_deserialize: input lacks srid");
123
+
124
+ result->SRID = -1;
125
+ }
126
+
127
+ /* we've read the type (1 byte) and SRID (4 bytes, if present) */
128
+
129
+ npoints = lw_get_uint32(loc);
130
+
131
+ LWDEBUGF(3, "circstring npoints = %d", npoints);
132
+
133
+ loc += 4;
134
+ pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), npoints);
135
+ result->points = pa;
136
+ return result;
137
+ }
138
+
139
+ /*
140
+ * convert this circularstring into its serialized form
141
+ * result's first char will be the 8bit type. See serialized form doc
142
+ */
143
+ uchar *
144
+ lwcircstring_serialize(LWCIRCSTRING *curve)
145
+ {
146
+ size_t size, retsize;
147
+ uchar * result;
148
+
149
+ if(curve == NULL) {
150
+ lwerror("lwcircstring_serialize:: given null curve");
151
+ return NULL;
152
+ }
153
+
154
+ size = lwcircstring_serialize_size(curve);
155
+ result = lwalloc(size);
156
+ lwcircstring_serialize_buf(curve, result, &retsize);
157
+ if(retsize != size)
158
+ lwerror("lwcircstring_serialize_size returned %d, ..serialize_buf returned %d", size, retsize);
159
+ return result;
160
+ }
161
+
162
+ /*
163
+ * convert this circularstring into its serialized form writing it into
164
+ * the given buffer, and returning number of bytes written into
165
+ * the given int pointer.
166
+ * result's first char will be the 8bit type. See serialized form doc
167
+ */
168
+ void lwcircstring_serialize_buf(LWCIRCSTRING *curve, uchar *buf, size_t *retsize)
169
+ {
170
+ char hasSRID;
171
+ uchar *loc;
172
+ int ptsize;
173
+ size_t size;
174
+
175
+ LWDEBUGF(2, "lwcircstring_serialize_buf(%p, %p, %p) called",
176
+ curve, buf, retsize);
177
+
178
+ if(curve == NULL)
179
+ {
180
+ lwerror("lwcircstring_serialize:: given null curve");
181
+ return;
182
+ }
183
+
184
+ if(TYPE_GETZM(curve->type) != TYPE_GETZM(curve->points->dims))
185
+ {
186
+ lwerror("Dimensions mismatch in lwcircstring");
187
+ return;
188
+ }
189
+
190
+ ptsize = pointArray_ptsize(curve->points);
191
+
192
+ hasSRID = (curve->SRID != -1);
193
+
194
+ buf[0] = (uchar)lwgeom_makeType_full(
195
+ TYPE_HASZ(curve->type), TYPE_HASM(curve->type),
196
+ hasSRID, CIRCSTRINGTYPE, curve->bbox ? 1 : 0);
197
+ loc = buf+1;
198
+
199
+ LWDEBUGF(3, "lwcircstring_serialize_buf added type (%d)", curve->type);
200
+
201
+ if(curve->bbox)
202
+ {
203
+ memcpy(loc, curve->bbox, sizeof(BOX2DFLOAT4));
204
+ loc += sizeof(BOX2DFLOAT4);
205
+
206
+ LWDEBUG(3, "lwcircstring_serialize_buf added BBOX");
207
+ }
208
+
209
+ if(hasSRID)
210
+ {
211
+ memcpy(loc, &curve->SRID, sizeof(int32));
212
+ loc += sizeof(int32);
213
+
214
+ LWDEBUG(3, "lwcircstring_serialize_buf added SRID");
215
+ }
216
+
217
+ memcpy(loc, &curve->points->npoints, sizeof(uint32));
218
+ loc += sizeof(uint32);
219
+
220
+ LWDEBUGF(3, "lwcircstring_serialize_buf added npoints (%d)",
221
+ curve->points->npoints);
222
+
223
+ /* copy in points */
224
+ size = curve->points->npoints * ptsize;
225
+ memcpy(loc, getPoint_internal(curve->points, 0), size);
226
+ loc += size;
227
+
228
+ LWDEBUGF(3, "lwcircstring_serialize_buf copied serialized_pointlist (%d bytes)",
229
+ ptsize * curve->points->npoints);
230
+
231
+ if(retsize) *retsize = loc-buf;
232
+
233
+ LWDEBUGF(3, "lwcircstring_serialize_buf returning (loc: %p, size: %d)",
234
+ loc, loc-buf);
235
+ }
236
+
237
+ /* find length of this deserialized circularstring */
238
+ size_t
239
+ lwcircstring_serialize_size(LWCIRCSTRING *curve)
240
+ {
241
+ size_t size = 1; /* type */
242
+
243
+ LWDEBUG(2, "lwcircstring_serialize_size called");
244
+
245
+ if(curve->SRID != -1) size += 4; /* SRID */
246
+ if(curve->bbox) size += sizeof(BOX2DFLOAT4);
247
+
248
+ size += 4; /* npoints */
249
+ size += pointArray_ptsize(curve->points) * curve->points->npoints;
250
+
251
+ LWDEBUGF(3, "lwcircstring_serialize_size returning %d", size);
252
+
253
+ return size;
254
+ }
255
+
256
+ BOX3D *
257
+ lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3)
258
+ {
259
+ double x1, x2, y1, y2, z1, z2;
260
+ double angle, radius, sweep;
261
+ /* angles from center */
262
+ double a1, a2, a3;
263
+ /* angles from center once a1 is rotated to zero */
264
+ double r2, r3;
265
+ double xe = 0.0, ye = 0.0;
266
+ POINT4D *center;
267
+ int i;
268
+ BOX3D *box;
269
+
270
+ LWDEBUG(2, "lwcircle_compute_box3d called.");
271
+
272
+ center = lwalloc(sizeof(POINT4D));
273
+ radius = lwcircle_center(p1, p2, p3, &center);
274
+ if(radius < 0.0) return NULL;
275
+
276
+ /*
277
+ top = center->y + radius;
278
+ left = center->x - radius;
279
+
280
+ LWDEBUGF(3, "lwcircle_compute_box3d: center (%.16f, %.16f)", center->x, center->y);
281
+ */
282
+
283
+ x1 = MAXFLOAT;
284
+ x2 = -1 * MAXFLOAT;
285
+ y1 = MAXFLOAT;
286
+ y2 = -1 * MAXFLOAT;
287
+
288
+ a1 = atan2(p1->y - center->y, p1->x - center->x);
289
+ a2 = atan2(p2->y - center->y, p2->x - center->x);
290
+ a3 = atan2(p3->y - center->y, p3->x - center->x);
291
+
292
+ /* Rotate a2 and a3 such that a1 = 0 */
293
+ r2 = a2 - a1;
294
+ r3 = a3 - a1;
295
+
296
+ /*
297
+ * There are six cases here I'm interested in
298
+ * Clockwise:
299
+ * 1. a1-a2 < 180 == r2 < 0 && (r3 > 0 || r3 < r2)
300
+ * 2. a1-a2 > 180 == r2 > 0 && (r3 > 0 && r3 < r2)
301
+ * 3. a1-a2 > 180 == r2 > 0 && (r3 > r2 || r3 < 0)
302
+ * Counter-clockwise:
303
+ * 4. a1-a2 < 180 == r2 > 0 && (r3 < 0 || r3 > r2)
304
+ * 5. a1-a2 > 180 == r2 < 0 && (r3 < 0 && r3 > r2)
305
+ * 6. a1-a2 > 180 == r2 < 0 && (r3 < r2 || r3 > 0)
306
+ * 3 and 6 are invalid cases where a3 is the midpoint.
307
+ * BBOX is fundamental, so these cannot error out and will instead
308
+ * calculate the sweep using a3 as the middle point.
309
+ */
310
+
311
+ /* clockwise 1 */
312
+ if(FP_LT(r2, 0) && (FP_GT(r3, 0) || FP_LT(r3, r2)))
313
+ {
314
+ sweep = (FP_GT(r3, 0)) ? (r3 - 2 * M_PI) : r3;
315
+ }
316
+ /* clockwise 2 */
317
+ else if(FP_GT(r2, 0) && FP_GT(r3, 0) && FP_LT(r3, r2))
318
+ {
319
+ sweep = (FP_GT(r3, 0)) ? (r3 - 2 * M_PI) : r3;
320
+ }
321
+ /* counter-clockwise 4 */
322
+ else if(FP_GT(r2, 0) && (FP_LT(r3, 0) || FP_GT(r3, r2)))
323
+ {
324
+ sweep = (FP_LT(r3, 0)) ? (r3 + 2 * M_PI) : r3;
325
+ }
326
+ /* counter-clockwise 5 */
327
+ else if(FP_LT(r2, 0) && FP_LT(r3, 0) && FP_GT(r3, r2))
328
+ {
329
+ sweep = (FP_LT(r3, 0)) ? (r3 + 2 * M_PI) : r3;
330
+ }
331
+ /* clockwise invalid 3 */
332
+ else if(FP_GT(r2, 0) && (FP_GT(r3, r2) || FP_LT(r3, 0)))
333
+ {
334
+ sweep = (FP_GT(r2, 0)) ? (r2 - 2 * M_PI) : r2;
335
+ }
336
+ /* clockwise invalid 6 */
337
+ else
338
+ {
339
+ sweep = (FP_LT(r2, 0)) ? (r2 + 2 * M_PI) : r2;
340
+ }
341
+
342
+ LWDEBUGF(3, "a1 %.16f, a2 %.16f, a3 %.16f, sweep %.16f", a1, a2, a3, sweep);
343
+
344
+ angle = 0.0;
345
+ for(i=0; i < 6; i++)
346
+ {
347
+ switch(i) {
348
+ /* right extent */
349
+ case 0:
350
+ angle = 0.0;
351
+ xe = center->x + radius;
352
+ ye = center->y;
353
+ break;
354
+ /* top extent */
355
+ case 1:
356
+ angle = M_PI_2;
357
+ xe = center->x;
358
+ ye = center->y + radius;
359
+ break;
360
+ /* left extent */
361
+ case 2:
362
+ angle = M_PI;
363
+ xe = center->x - radius;
364
+ ye = center->y;
365
+ break;
366
+ /* bottom extent */
367
+ case 3:
368
+ angle = -1 * M_PI_2;
369
+ xe = center->x;
370
+ ye = center->y - radius;
371
+ break;
372
+ /* first point */
373
+ case 4:
374
+ angle = a1;
375
+ xe = p1->x;
376
+ ye = p1->y;
377
+ break;
378
+ /* last point */
379
+ case 5:
380
+ angle = a3;
381
+ xe = p3->x;
382
+ ye = p3->y;
383
+ break;
384
+ }
385
+ /* determine if the extents are outside the arc */
386
+ if(i < 4)
387
+ {
388
+ if(FP_GT(sweep, 0.0))
389
+ {
390
+ if(FP_LT(a3, a1))
391
+ {
392
+ if(FP_GT(angle, (a3 + 2 * M_PI)) || FP_LT(angle, a1)) continue;
393
+ }
394
+ else
395
+ {
396
+ if(FP_GT(angle, a3) || FP_LT(angle, a1)) continue;
397
+ }
398
+ }
399
+ else
400
+ {
401
+ if(FP_GT(a3, a1))
402
+ {
403
+ if(FP_LT(angle, (a3 - 2 * M_PI)) || FP_GT(angle, a1)) continue;
404
+ }
405
+ else
406
+ {
407
+ if(FP_LT(angle, a3) || FP_GT(angle, a1)) continue;
408
+ }
409
+ }
410
+ }
411
+
412
+ LWDEBUGF(3, "lwcircle_compute_box3d: potential extreame %d (%.16f, %.16f)", i, xe, ye);
413
+
414
+ x1 = (FP_LT(x1, xe)) ? x1 : xe;
415
+ y1 = (FP_LT(y1, ye)) ? y1 : ye;
416
+ x2 = (FP_GT(x2, xe)) ? x2 : xe;
417
+ y2 = (FP_GT(y2, ye)) ? y2 : ye;
418
+ }
419
+
420
+ LWDEBUGF(3, "lwcircle_compute_box3d: extreames found (%.16f %.16f, %.16f %.16f)", x1, y1, x2, y2);
421
+
422
+ /*
423
+ x1 = center->x + x1 * radius;
424
+ x2 = center->x + x2 * radius;
425
+ y1 = center->y + y1 * radius;
426
+ y2 = center->y + y2 * radius;
427
+ */
428
+ z1 = (FP_LT(p1->z, p2->z)) ? p1->z : p2->z;
429
+ z1 = (FP_LT(z1, p3->z)) ? z1 : p3->z;
430
+ z2 = (FP_GT(p1->z, p2->z)) ? p1->z : p2->z;
431
+ z2 = (FP_GT(z2, p3->z)) ? z2 : p3->z;
432
+
433
+ box = lwalloc(sizeof(BOX3D));
434
+ box->xmin = x1; box->xmax = x2;
435
+ box->ymin = y1; box->ymax = y2;
436
+ box->zmin = z1; box->zmax = z2;
437
+
438
+ lwfree(center);
439
+
440
+ return box;
441
+ }
442
+
443
+ /*
444
+ * Find bounding box (standard one)
445
+ * zmin=zmax=NO_Z_VALUE if 2d
446
+ * TODO: This ignores curvature, which should be taken into account.
447
+ */
448
+ BOX3D *
449
+ lwcircstring_compute_box3d(LWCIRCSTRING *curve)
450
+ {
451
+ BOX3D *box, *tmp;
452
+ int i;
453
+ POINT4D *p1 = lwalloc(sizeof(POINT4D));
454
+ POINT4D *p2 = lwalloc(sizeof(POINT4D));
455
+ POINT4D *p3 = lwalloc(sizeof(POINT4D));
456
+
457
+ LWDEBUG(2, "lwcircstring_compute_box3d called.");
458
+
459
+ /* initialize box values */
460
+ box = lwalloc(sizeof(BOX3D));
461
+ box->xmin = MAXFLOAT; box->xmax = -1 * MAXFLOAT;
462
+ box->ymin = MAXFLOAT; box->ymax = -1 * MAXFLOAT;
463
+ box->zmin = MAXFLOAT; box->zmax = -1 * MAXFLOAT;
464
+
465
+ for(i = 2; i < curve->points->npoints; i+=2)
466
+ {
467
+ getPoint4d_p(curve->points, i-2, p1);
468
+ getPoint4d_p(curve->points, i-1, p2);
469
+ getPoint4d_p(curve->points, i, p3);
470
+ tmp = lwcircle_compute_box3d(p1, p2, p3);
471
+ if(tmp == NULL) continue;
472
+ box->xmin = (box->xmin < tmp->xmin) ? box->xmin : tmp->xmin;
473
+ box->xmax = (box->xmax > tmp->xmax) ? box->xmax : tmp->xmax;
474
+ box->ymin = (box->ymin < tmp->ymin) ? box->ymin : tmp->ymin;
475
+ box->ymax = (box->ymax > tmp->ymax) ? box->ymax : tmp->ymax;
476
+ box->zmin = (box->zmin < tmp->zmin) ? box->zmin : tmp->zmin;
477
+ box->zmax = (box->zmax > tmp->zmax) ? box->zmax : tmp->zmax;
478
+
479
+ LWDEBUGF(4, "circularstring %d x=(%.16f,%.16f) y=(%.16f,%.16f) z=(%.16f,%.16f)", i/2, box->xmin, box->xmax, box->ymin, box->ymax, box->zmin, box->zmax);
480
+ }
481
+
482
+
483
+ return box;
484
+ }
485
+
486
+ int
487
+ lwcircstring_compute_box2d_p(LWCIRCSTRING *curve, BOX2DFLOAT4 *result)
488
+ {
489
+ BOX3D *box = lwcircstring_compute_box3d(curve);
490
+ LWDEBUG(2, "lwcircstring_compute_box2d_p called.");
491
+
492
+ if(box == NULL) return 0;
493
+ box3d_to_box2df_p(box, result);
494
+ return 1;
495
+ }
496
+
497
+ void lwcircstring_free(LWCIRCSTRING *curve)
498
+ {
499
+ lwfree(curve->points);
500
+ lwfree(curve);
501
+ }
502
+
503
+ /* find length of this serialized curve */
504
+ size_t
505
+ lwgeom_size_circstring(const uchar *serialized_curve)
506
+ {
507
+ int type = (uchar)serialized_curve[0];
508
+ uint32 result = 1; /* type */
509
+ const uchar *loc;
510
+ uint32 npoints;
511
+
512
+ LWDEBUG(2, "lwgeom_size_circstring called");
513
+
514
+ if(lwgeom_getType(type) != CIRCSTRINGTYPE)
515
+ lwerror("lwgeom_size_circstring::attempt to find the length of a non-circularstring");
516
+
517
+ loc = serialized_curve + 1;
518
+ if(lwgeom_hasBBOX(type))
519
+ {
520
+ loc += sizeof(BOX2DFLOAT4);
521
+ result += sizeof(BOX2DFLOAT4);
522
+ }
523
+
524
+ if(lwgeom_hasSRID(type))
525
+ {
526
+ loc += 4; /* type + SRID */
527
+ result += 4;
528
+ }
529
+
530
+ /* we've read the type (1 byte) and SRID (4 bytes, if present) */
531
+ npoints = lw_get_uint32(loc);
532
+ result += sizeof(uint32); /* npoints */
533
+
534
+ result += TYPE_NDIMS(type) * sizeof(double) * npoints;
535
+
536
+ LWDEBUGF(3, "lwgeom_size_circstring returning %d", result);
537
+
538
+ return result;
539
+ }
540
+
541
+ void printLWCIRCSTRING(LWCIRCSTRING *curve)
542
+ {
543
+ lwnotice("LWCIRCSTRING {");
544
+ lwnotice(" ndims = %i", (int)TYPE_NDIMS(curve->type));
545
+ lwnotice(" SRID = %i", (int)curve->SRID);
546
+ printPA(curve->points);
547
+ lwnotice("}");
548
+ }
549
+
550
+ /* Clone LWCIRCSTRING object. POINTARRAY is not copied. */
551
+ LWCIRCSTRING *
552
+ lwcircstring_clone(const LWCIRCSTRING *g)
553
+ {
554
+ LWCIRCSTRING *ret = lwalloc(sizeof(LWCIRCSTRING));
555
+ memcpy(ret, g, sizeof(LWCIRCSTRING));
556
+ if(g->bbox) ret->bbox = box2d_clone(g->bbox);
557
+ return ret;
558
+ }
559
+
560
+ /*
561
+ * Add 'what' to this curve at position 'where'.
562
+ * where=0 == prepend
563
+ * where=-1 == append
564
+ * Returns a MULTICURVE or a GEOMETRYCOLLECTION
565
+ */
566
+ LWGEOM *
567
+ lwcircstring_add(const LWCIRCSTRING *to, uint32 where, const LWGEOM *what)
568
+ {
569
+ LWCOLLECTION *col;
570
+ LWGEOM **geoms;
571
+ int newtype;
572
+
573
+ if(where != -1 && where != 0)
574
+ {
575
+ lwerror("lwcurve_add only supports 0 or -1 as second argument %d", where);
576
+ return NULL;
577
+ }
578
+
579
+ /* dimensions compatibility are checked by caller */
580
+
581
+ /* Construct geoms array */
582
+ geoms = lwalloc(sizeof(LWGEOM *)*2);
583
+ if(where == -1) /* append */
584
+ {
585
+ geoms[0] = lwgeom_clone((LWGEOM *)to);
586
+ geoms[1] = lwgeom_clone(what);
587
+ }
588
+ else /* prepend */
589
+ {
590
+ geoms[0] = lwgeom_clone(what);
591
+ geoms[1] = lwgeom_clone((LWGEOM *)to);
592
+ }
593
+
594
+ /* reset SRID and wantbbox flag from component types */
595
+ geoms[0]->SRID = geoms[1]->SRID = -1;
596
+ TYPE_SETHASSRID(geoms[0]->type, 0);
597
+ TYPE_SETHASSRID(geoms[1]->type, 0);
598
+ TYPE_SETHASBBOX(geoms[0]->type, 0);
599
+ TYPE_SETHASBBOX(geoms[1]->type, 0);
600
+
601
+ /* Find appropriate geom type */
602
+ if(TYPE_GETTYPE(what->type) == CIRCSTRINGTYPE || TYPE_GETTYPE(what->type) == LINETYPE) newtype = MULTICURVETYPE;
603
+ else newtype = COLLECTIONTYPE;
604
+
605
+ col = lwcollection_construct(newtype,
606
+ to->SRID, NULL,
607
+ 2, geoms);
608
+
609
+ return (LWGEOM *)col;
610
+ }
611
+
612
+ void lwcircstring_reverse(LWCIRCSTRING *curve)
613
+ {
614
+ ptarray_reverse(curve->points);
615
+ }
616
+
617
+ /*
618
+ * TODO: Invalid segmentization. This should accomodate the curvature.
619
+ */
620
+ LWCIRCSTRING *
621
+ lwcircstring_segmentize2d(LWCIRCSTRING *curve, double dist)
622
+ {
623
+ return lwcircstring_construct(curve->SRID, NULL,
624
+ ptarray_segmentize2d(curve->points, dist));
625
+ }
626
+
627
+ /* check coordinate equality */
628
+ char
629
+ lwcircstring_same(const LWCIRCSTRING *me, const LWCIRCSTRING *you)
630
+ {
631
+ return ptarray_same(me->points, you->points);
632
+ }
633
+
634
+ /*
635
+ * Construct a LWCIRCSTRING from an array of LWPOINTs
636
+ * LWCIRCSTRING dimensions are large enough to host all input dimensions.
637
+ */
638
+ LWCIRCSTRING *
639
+ lwcircstring_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points)
640
+ {
641
+ int zmflag=0;
642
+ unsigned int i;
643
+ POINTARRAY *pa;
644
+ uchar *newpoints, *ptr;
645
+ size_t ptsize, size;
646
+
647
+ /*
648
+ * Find output dimensions, check integrity
649
+ */
650
+ for(i = 0; i < npoints; i++)
651
+ {
652
+ if(TYPE_GETTYPE(points[i]->type) != POINTTYPE)
653
+ {
654
+ lwerror("lwcurve_from_lwpointarray: invalid input type: %s",
655
+ lwgeom_typename(TYPE_GETTYPE(points[i]->type)));
656
+ return NULL;
657
+ }
658
+ if(TYPE_HASZ(points[i]->type)) zmflag |= 2;
659
+ if(TYPE_HASM(points[i]->type)) zmflag |=1;
660
+ if(zmflag == 3) break;
661
+ }
662
+
663
+ if(zmflag == 0) ptsize = 2 * sizeof(double);
664
+ else if(zmflag == 3) ptsize = 4 * sizeof(double);
665
+ else ptsize = 3 * sizeof(double);
666
+
667
+ /*
668
+ * Allocate output points array
669
+ */
670
+ size = ptsize * npoints;
671
+ newpoints = lwalloc(size);
672
+ memset(newpoints, 0, size);
673
+
674
+ ptr = newpoints;
675
+ for(i = 0; i < npoints; i++)
676
+ {
677
+ size = pointArray_ptsize(points[i]->point);
678
+ memcpy(ptr, getPoint_internal(points[i]->point, 0), size);
679
+ ptr += ptsize;
680
+ }
681
+ pa = pointArray_construct(newpoints, zmflag&2, zmflag&1, npoints);
682
+
683
+ return lwcircstring_construct(SRID, NULL, pa);
684
+ }
685
+
686
+ /*
687
+ * Construct a LWCIRCSTRING from a LWMPOINT
688
+ */
689
+ LWCIRCSTRING *
690
+ lwcircstring_from_lwmpoint(int SRID, LWMPOINT *mpoint)
691
+ {
692
+ unsigned int i;
693
+ POINTARRAY *pa;
694
+ char zmflag = TYPE_GETZM(mpoint->type);
695
+ size_t ptsize, size;
696
+ uchar *newpoints, *ptr;
697
+
698
+ if(zmflag == 0) ptsize = 2 * sizeof(double);
699
+ else if(zmflag == 3) ptsize = 4 * sizeof(double);
700
+ else ptsize = 3 * sizeof(double);
701
+
702
+ /* Allocate space for output points */
703
+ size = ptsize * mpoint->ngeoms;
704
+ newpoints = lwalloc(size);
705
+ memset(newpoints, 0, size);
706
+
707
+ ptr = newpoints;
708
+ for(i = 0; i < mpoint->ngeoms; i++)
709
+ {
710
+ memcpy(ptr,
711
+ getPoint_internal(mpoint->geoms[i]->point, 0),
712
+ ptsize);
713
+ ptr += ptsize;
714
+ }
715
+
716
+ pa = pointArray_construct(newpoints, zmflag&2, zmflag&1,
717
+ mpoint->ngeoms);
718
+
719
+ LWDEBUGF(3, "lwcurve_from_lwmpoint: constructed pointarray for %d points, %d zmflag", mpoint->ngeoms, zmflag);
720
+
721
+ return lwcircstring_construct(SRID, NULL, pa);
722
+ }
723
+
724
+ LWCIRCSTRING *
725
+ lwcircstring_addpoint(LWCIRCSTRING *curve, LWPOINT *point, unsigned int where)
726
+ {
727
+ POINTARRAY *newpa;
728
+ LWCIRCSTRING *ret;
729
+
730
+ newpa = ptarray_addPoint(curve->points,
731
+ getPoint_internal(point->point, 0),
732
+ TYPE_NDIMS(point->type), where);
733
+ ret = lwcircstring_construct(curve->SRID, NULL, newpa);
734
+
735
+ return ret;
736
+ }
737
+
738
+ LWCIRCSTRING *
739
+ lwcircstring_removepoint(LWCIRCSTRING *curve, unsigned int index)
740
+ {
741
+ POINTARRAY *newpa;
742
+ LWCIRCSTRING *ret;
743
+
744
+ newpa = ptarray_removePoint(curve->points, index);
745
+ ret = lwcircstring_construct(curve->SRID, NULL, newpa);
746
+
747
+ return ret;
748
+ }
749
+
750
+ /*
751
+ * Note: input will be changed, make sure you have permissions for this.
752
+ * */
753
+ void
754
+ lwcircstring_setPoint4d(LWCIRCSTRING *curve, unsigned int index, POINT4D *newpoint)
755
+ {
756
+ setPoint4d(curve->points, index, newpoint);
757
+ }
758
+
759
+