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