activerecord-postgres-earthdistance 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/.document +5 -0
  2. data/Gemfile +11 -0
  3. data/Gemfile.lock +84 -0
  4. data/LICENSE +20 -0
  5. data/README.rdoc +17 -0
  6. data/Rakefile +55 -0
  7. data/VERSION +1 -0
  8. data/activerecord-postgres-earthdistance.gemspec +124 -0
  9. data/lib/activerecord-postgres-earthdistance.rb +48 -0
  10. data/lib/activerecord-postgres-earthdistance/activerecord.rb +17 -0
  11. data/lib/templates/cube.sql +326 -0
  12. data/lib/templates/earthdistance.sql +93 -0
  13. data/lib/templates/setup_earthdistance.rb +434 -0
  14. data/test/app/.gitignore +4 -0
  15. data/test/app/Gemfile +5 -0
  16. data/test/app/Gemfile.lock +83 -0
  17. data/test/app/README +256 -0
  18. data/test/app/Rakefile +7 -0
  19. data/test/app/app/controllers/application_controller.rb +3 -0
  20. data/test/app/app/helpers/application_helper.rb +2 -0
  21. data/test/app/app/models/place.rb +3 -0
  22. data/test/app/app/views/layouts/application.html.erb +14 -0
  23. data/test/app/config.ru +4 -0
  24. data/test/app/config/application.rb +42 -0
  25. data/test/app/config/boot.rb +13 -0
  26. data/test/app/config/database.yml +25 -0
  27. data/test/app/config/environment.rb +5 -0
  28. data/test/app/config/environments/development.rb +26 -0
  29. data/test/app/config/environments/production.rb +49 -0
  30. data/test/app/config/environments/test.rb +35 -0
  31. data/test/app/config/initializers/backtrace_silencers.rb +7 -0
  32. data/test/app/config/initializers/inflections.rb +10 -0
  33. data/test/app/config/initializers/mime_types.rb +5 -0
  34. data/test/app/config/initializers/secret_token.rb +7 -0
  35. data/test/app/config/initializers/session_store.rb +8 -0
  36. data/test/app/config/initializers/use_sql_schema.rb +3 -0
  37. data/test/app/config/locales/en.yml +5 -0
  38. data/test/app/config/routes.rb +58 -0
  39. data/test/app/db/development_structure.sql +807 -0
  40. data/test/app/db/migrate/20110225205046_setup_earthdistance.rb +434 -0
  41. data/test/app/db/migrate/20110225205131_create_places.rb +15 -0
  42. data/test/app/db/schema.rb +24 -0
  43. data/test/app/db/seeds.rb +7 -0
  44. data/test/app/doc/README_FOR_APP +2 -0
  45. data/test/app/lib/tasks/.gitkeep +0 -0
  46. data/test/app/public/404.html +26 -0
  47. data/test/app/public/422.html +26 -0
  48. data/test/app/public/500.html +26 -0
  49. data/test/app/public/favicon.ico +0 -0
  50. data/test/app/public/images/rails.png +0 -0
  51. data/test/app/public/index.html +239 -0
  52. data/test/app/public/javascripts/application.js +2 -0
  53. data/test/app/public/javascripts/controls.js +965 -0
  54. data/test/app/public/javascripts/dragdrop.js +974 -0
  55. data/test/app/public/javascripts/effects.js +1123 -0
  56. data/test/app/public/javascripts/prototype.js +6001 -0
  57. data/test/app/public/javascripts/rails.js +175 -0
  58. data/test/app/public/robots.txt +5 -0
  59. data/test/app/public/stylesheets/.gitkeep +0 -0
  60. data/test/app/script/rails +6 -0
  61. data/test/app/test/performance/browsing_test.rb +9 -0
  62. data/test/app/test/test_helper.rb +13 -0
  63. data/test/app/test/unit/place_test.rb +27 -0
  64. data/test/app/vendor/plugins/.gitkeep +0 -0
  65. metadata +205 -0
@@ -0,0 +1,93 @@
1
+ /* $PostgreSQL: pgsql/contrib/earthdistance/earthdistance.sql.in,v 1.11 2007/11/13 04:24:27 momjian Exp $ */
2
+
3
+ -- Adjust this setting to control where the objects get created.
4
+ SET search_path = public;
5
+
6
+ -- The earth functions rely on contrib/cube having been installed and loaded.
7
+
8
+ -- earth() returns the radius of the earth in meters. This is the only
9
+ -- place you need to change things for the cube base distance functions
10
+ -- in order to use different units (or a better value for the Earth's radius).
11
+
12
+ CREATE OR REPLACE FUNCTION earth() RETURNS float8
13
+ LANGUAGE SQL IMMUTABLE
14
+ AS 'SELECT ''6378168''::float8';
15
+
16
+ -- Astromers may want to change the earth function so that distances will be
17
+ -- returned in degrees. To do this comment out the above definition and
18
+ -- uncomment the one below. Note that doing this will break the regression
19
+ -- tests.
20
+ --
21
+ -- CREATE OR REPLACE FUNCTION earth() RETURNS float8
22
+ -- LANGUAGE SQL IMMUTABLE
23
+ -- AS 'SELECT 180/pi()';
24
+
25
+ -- Define domain for locations on the surface of the earth using a cube
26
+ -- datatype with constraints. cube provides 3D indexing.
27
+ -- The cube is restricted to be a point, no more than 3 dimensions
28
+ -- (for less than 3 dimensions 0 is assumed for the missing coordinates)
29
+ -- and that the point must be very near the surface of the sphere
30
+ -- centered about the origin with the radius of the earth.
31
+
32
+ CREATE DOMAIN earth AS cube
33
+ CONSTRAINT not_point check(cube_is_point(value))
34
+ CONSTRAINT not_3d check(cube_dim(value) <= 3)
35
+ CONSTRAINT on_surface check(abs(cube_distance(value, '(0)'::cube) /
36
+ earth() - 1) < '10e-7'::float8);
37
+
38
+ CREATE OR REPLACE FUNCTION sec_to_gc(float8)
39
+ RETURNS float8
40
+ LANGUAGE SQL
41
+ IMMUTABLE STRICT
42
+ AS 'SELECT CASE WHEN $1 < 0 THEN 0::float8 WHEN $1/(2*earth()) > 1 THEN pi()*earth() ELSE 2*earth()*asin($1/(2*earth())) END';
43
+
44
+ CREATE OR REPLACE FUNCTION gc_to_sec(float8)
45
+ RETURNS float8
46
+ LANGUAGE SQL
47
+ IMMUTABLE STRICT
48
+ AS 'SELECT CASE WHEN $1 < 0 THEN 0::float8 WHEN $1/earth() > pi() THEN 2*earth() ELSE 2*earth()*sin($1/(2*earth())) END';
49
+
50
+ CREATE OR REPLACE FUNCTION ll_to_earth(float8, float8)
51
+ RETURNS earth
52
+ LANGUAGE SQL
53
+ IMMUTABLE STRICT
54
+ AS 'SELECT cube(cube(cube(earth()*cos(radians($1))*cos(radians($2))),earth()*cos(radians($1))*sin(radians($2))),earth()*sin(radians($1)))::earth';
55
+
56
+ CREATE OR REPLACE FUNCTION latitude(earth)
57
+ RETURNS float8
58
+ LANGUAGE SQL
59
+ IMMUTABLE STRICT
60
+ AS 'SELECT CASE WHEN cube_ll_coord($1, 3)/earth() < -1 THEN -90::float8 WHEN cube_ll_coord($1, 3)/earth() > 1 THEN 90::float8 ELSE degrees(asin(cube_ll_coord($1, 3)/earth())) END';
61
+
62
+ CREATE OR REPLACE FUNCTION longitude(earth)
63
+ RETURNS float8
64
+ LANGUAGE SQL
65
+ IMMUTABLE STRICT
66
+ AS 'SELECT degrees(atan2(cube_ll_coord($1, 2), cube_ll_coord($1, 1)))';
67
+
68
+ CREATE OR REPLACE FUNCTION earth_distance(earth, earth)
69
+ RETURNS float8
70
+ LANGUAGE SQL
71
+ IMMUTABLE STRICT
72
+ AS 'SELECT sec_to_gc(cube_distance($1, $2))';
73
+
74
+ CREATE OR REPLACE FUNCTION earth_box(earth, float8)
75
+ RETURNS cube
76
+ LANGUAGE SQL
77
+ IMMUTABLE STRICT
78
+ AS 'SELECT cube_enlarge($1, gc_to_sec($2), 3)';
79
+
80
+ --------------- geo_distance
81
+
82
+ CREATE OR REPLACE FUNCTION geo_distance (point, point)
83
+ RETURNS float8
84
+ LANGUAGE C IMMUTABLE STRICT AS '$libdir/earthdistance';
85
+
86
+ --------------- geo_distance as operator <@>
87
+
88
+ CREATE OPERATOR <@> (
89
+ LEFTARG = point,
90
+ RIGHTARG = point,
91
+ PROCEDURE = geo_distance,
92
+ COMMUTATOR = <@>
93
+ );
@@ -0,0 +1,434 @@
1
+ class SetupEarthdistance < ActiveRecord::Migration
2
+ def self.up
3
+ sql = <<-EARTHDISTANCE_SQL
4
+ /* $PostgreSQL: pgsql/contrib/cube/cube.sql.in,v 1.25 2009/06/11 18:30:03 tgl Exp $ */
5
+
6
+ -- Adjust this setting to control where the objects get created.
7
+ SET search_path = public;
8
+
9
+ -- Create the user-defined type for N-dimensional boxes
10
+ --
11
+
12
+ CREATE OR REPLACE FUNCTION cube_in(cstring)
13
+ RETURNS cube
14
+ AS '$libdir/cube'
15
+ LANGUAGE C IMMUTABLE STRICT;
16
+
17
+ CREATE OR REPLACE FUNCTION cube(float8[], float8[]) RETURNS cube
18
+ AS '$libdir/cube', 'cube_a_f8_f8'
19
+ LANGUAGE C IMMUTABLE STRICT;
20
+
21
+ CREATE OR REPLACE FUNCTION cube(float8[]) RETURNS cube
22
+ AS '$libdir/cube', 'cube_a_f8'
23
+ LANGUAGE C IMMUTABLE STRICT;
24
+
25
+ CREATE OR REPLACE FUNCTION cube_out(cube)
26
+ RETURNS cstring
27
+ AS '$libdir/cube'
28
+ LANGUAGE C IMMUTABLE STRICT;
29
+
30
+ CREATE TYPE cube (
31
+ INTERNALLENGTH = variable,
32
+ INPUT = cube_in,
33
+ OUTPUT = cube_out,
34
+ ALIGNMENT = double
35
+ );
36
+
37
+ COMMENT ON TYPE cube IS 'multi-dimensional cube ''(FLOAT-1, FLOAT-2, ..., FLOAT-N), (FLOAT-1, FLOAT-2, ..., FLOAT-N)''';
38
+
39
+ --
40
+ -- External C-functions for R-tree methods
41
+ --
42
+
43
+ -- Comparison methods
44
+
45
+ CREATE OR REPLACE FUNCTION cube_eq(cube, cube)
46
+ RETURNS bool
47
+ AS '$libdir/cube'
48
+ LANGUAGE C IMMUTABLE STRICT;
49
+
50
+ COMMENT ON FUNCTION cube_eq(cube, cube) IS 'same as';
51
+
52
+ CREATE OR REPLACE FUNCTION cube_ne(cube, cube)
53
+ RETURNS bool
54
+ AS '$libdir/cube'
55
+ LANGUAGE C IMMUTABLE STRICT;
56
+
57
+ COMMENT ON FUNCTION cube_ne(cube, cube) IS 'different';
58
+
59
+ CREATE OR REPLACE FUNCTION cube_lt(cube, cube)
60
+ RETURNS bool
61
+ AS '$libdir/cube'
62
+ LANGUAGE C IMMUTABLE STRICT;
63
+
64
+ COMMENT ON FUNCTION cube_lt(cube, cube) IS 'lower than';
65
+
66
+ CREATE OR REPLACE FUNCTION cube_gt(cube, cube)
67
+ RETURNS bool
68
+ AS '$libdir/cube'
69
+ LANGUAGE C IMMUTABLE STRICT;
70
+
71
+ COMMENT ON FUNCTION cube_gt(cube, cube) IS 'greater than';
72
+
73
+ CREATE OR REPLACE FUNCTION cube_le(cube, cube)
74
+ RETURNS bool
75
+ AS '$libdir/cube'
76
+ LANGUAGE C IMMUTABLE STRICT;
77
+
78
+ COMMENT ON FUNCTION cube_le(cube, cube) IS 'lower than or equal to';
79
+
80
+ CREATE OR REPLACE FUNCTION cube_ge(cube, cube)
81
+ RETURNS bool
82
+ AS '$libdir/cube'
83
+ LANGUAGE C IMMUTABLE STRICT;
84
+
85
+ COMMENT ON FUNCTION cube_ge(cube, cube) IS 'greater than or equal to';
86
+
87
+ CREATE OR REPLACE FUNCTION cube_cmp(cube, cube)
88
+ RETURNS int4
89
+ AS '$libdir/cube'
90
+ LANGUAGE C IMMUTABLE STRICT;
91
+
92
+ COMMENT ON FUNCTION cube_cmp(cube, cube) IS 'btree comparison function';
93
+
94
+ CREATE OR REPLACE FUNCTION cube_contains(cube, cube)
95
+ RETURNS bool
96
+ AS '$libdir/cube'
97
+ LANGUAGE C IMMUTABLE STRICT;
98
+
99
+ COMMENT ON FUNCTION cube_contains(cube, cube) IS 'contains';
100
+
101
+ CREATE OR REPLACE FUNCTION cube_contained(cube, cube)
102
+ RETURNS bool
103
+ AS '$libdir/cube'
104
+ LANGUAGE C IMMUTABLE STRICT;
105
+
106
+ COMMENT ON FUNCTION cube_contained(cube, cube) IS 'contained in';
107
+
108
+ CREATE OR REPLACE FUNCTION cube_overlap(cube, cube)
109
+ RETURNS bool
110
+ AS '$libdir/cube'
111
+ LANGUAGE C IMMUTABLE STRICT;
112
+
113
+ COMMENT ON FUNCTION cube_overlap(cube, cube) IS 'overlaps';
114
+
115
+ -- support routines for indexing
116
+
117
+ CREATE OR REPLACE FUNCTION cube_union(cube, cube)
118
+ RETURNS cube
119
+ AS '$libdir/cube'
120
+ LANGUAGE C IMMUTABLE STRICT;
121
+
122
+ CREATE OR REPLACE FUNCTION cube_inter(cube, cube)
123
+ RETURNS cube
124
+ AS '$libdir/cube'
125
+ LANGUAGE C IMMUTABLE STRICT;
126
+
127
+ CREATE OR REPLACE FUNCTION cube_size(cube)
128
+ RETURNS float8
129
+ AS '$libdir/cube'
130
+ LANGUAGE C IMMUTABLE STRICT;
131
+
132
+
133
+ -- Misc N-dimensional functions
134
+
135
+ CREATE OR REPLACE FUNCTION cube_subset(cube, int4[])
136
+ RETURNS cube
137
+ AS '$libdir/cube'
138
+ LANGUAGE C IMMUTABLE STRICT;
139
+
140
+ -- proximity routines
141
+
142
+ CREATE OR REPLACE FUNCTION cube_distance(cube, cube)
143
+ RETURNS float8
144
+ AS '$libdir/cube'
145
+ LANGUAGE C IMMUTABLE STRICT;
146
+
147
+ -- Extracting elements functions
148
+
149
+ CREATE OR REPLACE FUNCTION cube_dim(cube)
150
+ RETURNS int4
151
+ AS '$libdir/cube'
152
+ LANGUAGE C IMMUTABLE STRICT;
153
+
154
+ CREATE OR REPLACE FUNCTION cube_ll_coord(cube, int4)
155
+ RETURNS float8
156
+ AS '$libdir/cube'
157
+ LANGUAGE C IMMUTABLE STRICT;
158
+
159
+ CREATE OR REPLACE FUNCTION cube_ur_coord(cube, int4)
160
+ RETURNS float8
161
+ AS '$libdir/cube'
162
+ LANGUAGE C IMMUTABLE STRICT;
163
+
164
+ CREATE OR REPLACE FUNCTION cube(float8) RETURNS cube
165
+ AS '$libdir/cube', 'cube_f8'
166
+ LANGUAGE C IMMUTABLE STRICT;
167
+
168
+ CREATE OR REPLACE FUNCTION cube(float8, float8) RETURNS cube
169
+ AS '$libdir/cube', 'cube_f8_f8'
170
+ LANGUAGE C IMMUTABLE STRICT;
171
+
172
+ CREATE OR REPLACE FUNCTION cube(cube, float8) RETURNS cube
173
+ AS '$libdir/cube', 'cube_c_f8'
174
+ LANGUAGE C IMMUTABLE STRICT;
175
+
176
+ CREATE OR REPLACE FUNCTION cube(cube, float8, float8) RETURNS cube
177
+ AS '$libdir/cube', 'cube_c_f8_f8'
178
+ LANGUAGE C IMMUTABLE STRICT;
179
+
180
+ -- Test if cube is also a point
181
+
182
+ CREATE OR REPLACE FUNCTION cube_is_point(cube)
183
+ RETURNS bool
184
+ AS '$libdir/cube'
185
+ LANGUAGE C IMMUTABLE STRICT;
186
+
187
+ -- Increasing the size of a cube by a radius in at least n dimensions
188
+
189
+ CREATE OR REPLACE FUNCTION cube_enlarge(cube, float8, int4)
190
+ RETURNS cube
191
+ AS '$libdir/cube'
192
+ LANGUAGE C IMMUTABLE STRICT;
193
+
194
+ --
195
+ -- OPERATORS
196
+ --
197
+
198
+ CREATE OPERATOR < (
199
+ LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_lt,
200
+ COMMUTATOR = '>', NEGATOR = '>=',
201
+ RESTRICT = scalarltsel, JOIN = scalarltjoinsel
202
+ );
203
+
204
+ CREATE OPERATOR > (
205
+ LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_gt,
206
+ COMMUTATOR = '<', NEGATOR = '<=',
207
+ RESTRICT = scalargtsel, JOIN = scalargtjoinsel
208
+ );
209
+
210
+ CREATE OPERATOR <= (
211
+ LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_le,
212
+ COMMUTATOR = '>=', NEGATOR = '>',
213
+ RESTRICT = scalarltsel, JOIN = scalarltjoinsel
214
+ );
215
+
216
+ CREATE OPERATOR >= (
217
+ LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_ge,
218
+ COMMUTATOR = '<=', NEGATOR = '<',
219
+ RESTRICT = scalargtsel, JOIN = scalargtjoinsel
220
+ );
221
+
222
+ CREATE OPERATOR && (
223
+ LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_overlap,
224
+ COMMUTATOR = '&&',
225
+ RESTRICT = areasel, JOIN = areajoinsel
226
+ );
227
+
228
+ CREATE OPERATOR = (
229
+ LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_eq,
230
+ COMMUTATOR = '=', NEGATOR = '<>',
231
+ RESTRICT = eqsel, JOIN = eqjoinsel,
232
+ MERGES
233
+ );
234
+
235
+ CREATE OPERATOR <> (
236
+ LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_ne,
237
+ COMMUTATOR = '<>', NEGATOR = '=',
238
+ RESTRICT = neqsel, JOIN = neqjoinsel
239
+ );
240
+
241
+ CREATE OPERATOR @> (
242
+ LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_contains,
243
+ COMMUTATOR = '<@',
244
+ RESTRICT = contsel, JOIN = contjoinsel
245
+ );
246
+
247
+ CREATE OPERATOR <@ (
248
+ LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_contained,
249
+ COMMUTATOR = '@>',
250
+ RESTRICT = contsel, JOIN = contjoinsel
251
+ );
252
+
253
+ -- these are obsolete/deprecated:
254
+ CREATE OPERATOR @ (
255
+ LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_contains,
256
+ COMMUTATOR = '~',
257
+ RESTRICT = contsel, JOIN = contjoinsel
258
+ );
259
+
260
+ CREATE OPERATOR ~ (
261
+ LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_contained,
262
+ COMMUTATOR = '@',
263
+ RESTRICT = contsel, JOIN = contjoinsel
264
+ );
265
+
266
+
267
+ -- define the GiST support methods
268
+ CREATE OR REPLACE FUNCTION g_cube_consistent(internal,cube,int,oid,internal)
269
+ RETURNS bool
270
+ AS '$libdir/cube'
271
+ LANGUAGE C IMMUTABLE STRICT;
272
+
273
+ CREATE OR REPLACE FUNCTION g_cube_compress(internal)
274
+ RETURNS internal
275
+ AS '$libdir/cube'
276
+ LANGUAGE C IMMUTABLE STRICT;
277
+
278
+ CREATE OR REPLACE FUNCTION g_cube_decompress(internal)
279
+ RETURNS internal
280
+ AS '$libdir/cube'
281
+ LANGUAGE C IMMUTABLE STRICT;
282
+
283
+ CREATE OR REPLACE FUNCTION g_cube_penalty(internal,internal,internal)
284
+ RETURNS internal
285
+ AS '$libdir/cube'
286
+ LANGUAGE C IMMUTABLE STRICT;
287
+
288
+ CREATE OR REPLACE FUNCTION g_cube_picksplit(internal, internal)
289
+ RETURNS internal
290
+ AS '$libdir/cube'
291
+ LANGUAGE C IMMUTABLE STRICT;
292
+
293
+ CREATE OR REPLACE FUNCTION g_cube_union(internal, internal)
294
+ RETURNS cube
295
+ AS '$libdir/cube'
296
+ LANGUAGE C IMMUTABLE STRICT;
297
+
298
+ CREATE OR REPLACE FUNCTION g_cube_same(cube, cube, internal)
299
+ RETURNS internal
300
+ AS '$libdir/cube'
301
+ LANGUAGE C IMMUTABLE STRICT;
302
+
303
+
304
+ -- Create the operator classes for indexing
305
+
306
+ CREATE OPERATOR CLASS cube_ops
307
+ DEFAULT FOR TYPE cube USING btree AS
308
+ OPERATOR 1 < ,
309
+ OPERATOR 2 <= ,
310
+ OPERATOR 3 = ,
311
+ OPERATOR 4 >= ,
312
+ OPERATOR 5 > ,
313
+ FUNCTION 1 cube_cmp(cube, cube);
314
+
315
+ CREATE OPERATOR CLASS gist_cube_ops
316
+ DEFAULT FOR TYPE cube USING gist AS
317
+ OPERATOR 3 && ,
318
+ OPERATOR 6 = ,
319
+ OPERATOR 7 @> ,
320
+ OPERATOR 8 <@ ,
321
+ OPERATOR 13 @ ,
322
+ OPERATOR 14 ~ ,
323
+ FUNCTION 1 g_cube_consistent (internal, cube, int, oid, internal),
324
+ FUNCTION 2 g_cube_union (internal, internal),
325
+ FUNCTION 3 g_cube_compress (internal),
326
+ FUNCTION 4 g_cube_decompress (internal),
327
+ FUNCTION 5 g_cube_penalty (internal, internal, internal),
328
+ FUNCTION 6 g_cube_picksplit (internal, internal),
329
+ FUNCTION 7 g_cube_same (cube, cube, internal);
330
+
331
+
332
+
333
+ /* $PostgreSQL: pgsql/contrib/earthdistance/earthdistance.sql.in,v 1.11 2007/11/13 04:24:27 momjian Exp $ */
334
+
335
+ -- Adjust this setting to control where the objects get created.
336
+ SET search_path = public;
337
+
338
+ -- The earth functions rely on contrib/cube having been installed and loaded.
339
+
340
+ -- earth() returns the radius of the earth in meters. This is the only
341
+ -- place you need to change things for the cube base distance functions
342
+ -- in order to use different units (or a better value for the Earth's radius).
343
+
344
+ CREATE OR REPLACE FUNCTION earth() RETURNS float8
345
+ LANGUAGE SQL IMMUTABLE
346
+ AS 'SELECT ''6378168''::float8';
347
+
348
+ -- Astromers may want to change the earth function so that distances will be
349
+ -- returned in degrees. To do this comment out the above definition and
350
+ -- uncomment the one below. Note that doing this will break the regression
351
+ -- tests.
352
+ --
353
+ -- CREATE OR REPLACE FUNCTION earth() RETURNS float8
354
+ -- LANGUAGE SQL IMMUTABLE
355
+ -- AS 'SELECT 180/pi()';
356
+
357
+ -- Define domain for locations on the surface of the earth using a cube
358
+ -- datatype with constraints. cube provides 3D indexing.
359
+ -- The cube is restricted to be a point, no more than 3 dimensions
360
+ -- (for less than 3 dimensions 0 is assumed for the missing coordinates)
361
+ -- and that the point must be very near the surface of the sphere
362
+ -- centered about the origin with the radius of the earth.
363
+
364
+ CREATE DOMAIN earth AS cube
365
+ CONSTRAINT not_point check(cube_is_point(value))
366
+ CONSTRAINT not_3d check(cube_dim(value) <= 3)
367
+ CONSTRAINT on_surface check(abs(cube_distance(value, '(0)'::cube) /
368
+ earth() - 1) < '10e-7'::float8);
369
+
370
+ CREATE OR REPLACE FUNCTION sec_to_gc(float8)
371
+ RETURNS float8
372
+ LANGUAGE SQL
373
+ IMMUTABLE STRICT
374
+ AS 'SELECT CASE WHEN $1 < 0 THEN 0::float8 WHEN $1/(2*earth()) > 1 THEN pi()*earth() ELSE 2*earth()*asin($1/(2*earth())) END';
375
+
376
+ CREATE OR REPLACE FUNCTION gc_to_sec(float8)
377
+ RETURNS float8
378
+ LANGUAGE SQL
379
+ IMMUTABLE STRICT
380
+ AS 'SELECT CASE WHEN $1 < 0 THEN 0::float8 WHEN $1/earth() > pi() THEN 2*earth() ELSE 2*earth()*sin($1/(2*earth())) END';
381
+
382
+ CREATE OR REPLACE FUNCTION ll_to_earth(float8, float8)
383
+ RETURNS earth
384
+ LANGUAGE SQL
385
+ IMMUTABLE STRICT
386
+ AS 'SELECT cube(cube(cube(earth()*cos(radians($1))*cos(radians($2))),earth()*cos(radians($1))*sin(radians($2))),earth()*sin(radians($1)))::earth';
387
+
388
+ CREATE OR REPLACE FUNCTION latitude(earth)
389
+ RETURNS float8
390
+ LANGUAGE SQL
391
+ IMMUTABLE STRICT
392
+ AS 'SELECT CASE WHEN cube_ll_coord($1, 3)/earth() < -1 THEN -90::float8 WHEN cube_ll_coord($1, 3)/earth() > 1 THEN 90::float8 ELSE degrees(asin(cube_ll_coord($1, 3)/earth())) END';
393
+
394
+ CREATE OR REPLACE FUNCTION longitude(earth)
395
+ RETURNS float8
396
+ LANGUAGE SQL
397
+ IMMUTABLE STRICT
398
+ AS 'SELECT degrees(atan2(cube_ll_coord($1, 2), cube_ll_coord($1, 1)))';
399
+
400
+ CREATE OR REPLACE FUNCTION earth_distance(earth, earth)
401
+ RETURNS float8
402
+ LANGUAGE SQL
403
+ IMMUTABLE STRICT
404
+ AS 'SELECT sec_to_gc(cube_distance($1, $2))';
405
+
406
+ CREATE OR REPLACE FUNCTION earth_box(earth, float8)
407
+ RETURNS cube
408
+ LANGUAGE SQL
409
+ IMMUTABLE STRICT
410
+ AS 'SELECT cube_enlarge($1, gc_to_sec($2), 3)';
411
+
412
+ --------------- geo_distance
413
+
414
+ CREATE OR REPLACE FUNCTION geo_distance (point, point)
415
+ RETURNS float8
416
+ LANGUAGE C IMMUTABLE STRICT AS '$libdir/earthdistance';
417
+
418
+ --------------- geo_distance as operator <@>
419
+
420
+ CREATE OPERATOR <@> (
421
+ LEFTARG = point,
422
+ RIGHTARG = point,
423
+ PROCEDURE = geo_distance,
424
+ COMMUTATOR = <@>
425
+ );
426
+
427
+ EARTHDISTANCE_SQL
428
+ execute sql
429
+ end
430
+
431
+ def self.down
432
+ # Kinda... hard.
433
+ end
434
+ end