GeoRSS aggregator and Layar augmented reality server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

71 lines
1.6 KiB

  1. class Post < ActiveRecord::Base
  2. belongs_to :feed
  3. EARTH_RADIUS_METRES = 6378000
  4. def self.near(lat, lon, radius_metres, layer_id)
  5. # Santize inputs. Is this necessary?
  6. lat = lat.to_f
  7. lon = lon.to_f
  8. radius_metres = radius_metres.to_i
  9. layer_id = layer_id.to_i
  10. # Calculate distance using the Haversine formula
  11. self.find_by_sql(<<-ENDQUERY
  12. SELECT
  13. p.id,
  14. p.title,
  15. p.summary,
  16. p.url,
  17. p.lat,
  18. p.lon,
  19. p.published,
  20. f.title as feed_title,
  21. ( #{EARTH_RADIUS_METRES}
  22. * acos( cos( radians('#{lat}') )
  23. * cos( radians( p.lat ) )
  24. * cos( radians( p.lon )
  25. - radians('#{lon}') )
  26. + sin( radians('#{lat}') )
  27. * sin( radians( p.lat ) ) ) )
  28. As distance
  29. FROM posts p
  30. INNER JOIN feeds f
  31. ON p.feed_id = f.id
  32. WHERE
  33. p.id IN
  34. ( -- Subquery returns a list of post_ids for posts on this layer
  35. SELECT p.id
  36. FROM feeds_layers fl
  37. INNER JOIN feeds f
  38. ON fl.feed_id = f.id
  39. INNER JOIN posts p
  40. ON p.feed_id = f.id
  41. WHERE fl.layer_id = #{layer_id}
  42. )
  43. AND
  44. (
  45. #{EARTH_RADIUS_METRES}
  46. * acos( cos( radians('#{lat}') )
  47. * cos( radians( p.lat ) )
  48. * cos( radians( p.lon )
  49. - radians('#{lon}') )
  50. + sin( radians('#{lat}') )
  51. * sin( radians( p.lat ) ) )
  52. )
  53. <= #{radius_metres}
  54. ORDER BY distance
  55. ENDQUERY
  56. )
  57. end
  58. end