GeoRSS aggregator and Layar augmented reality server
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 

74 lignes
1.8 KiB

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