lib/geokit/geocoders.rb in andre-geokit-1.2.0 vs lib/geokit/geocoders.rb in andre-geokit-1.2.1

- old
+ new

@@ -93,18 +93,33 @@ def self.geocode(address) res = do_geocode(address) return res.success ? res : GeoLoc.new end + # Main method which calls the do_reverse_geocode template method which subclasses + # are responsible for implementing. Returns a populated GeoLoc or an + # empty one with a failed success code. + def self.reverse_geocode(latlng) + res = do_reverse_geocode(latlng) + return res.success ? res : GeoLoc.new + end + # Call the geocoder service using the timeout if configured. def self.call_geocoder_service(url) timeout(Geokit::Geocoders::timeout) { return self.do_get(url) } if Geokit::Geocoders::timeout return self.do_get(url) rescue TimeoutError return nil end + # Not all geocoders can do reverse geocoding. So, unless the subclass explicitly overrides this method, + # a call to reverse_geocode will return an empty GeoLoc. If you happen to be using MultiGeocoder, + # this will cause it to failover to the next geocoder, which will hopefully be one which supports reverse geocoding. + def self.do_reverse_geocode(latlng) + return GeoLoc.new + end + protected def self.logger() Geokit::Geocoders::logger end @@ -191,28 +206,42 @@ # Google geocoder implementation. Requires the Geokit::Geocoders::GOOGLE variable to # contain a Google API key. Conforms to the interface set by the Geocoder class. class GoogleGeocoder < Geocoder private + + # Template method which does the reverse-geocode lookup. + def self.do_reverse_geocode(latlng) + res = self.call_geocoder_service("http://maps.google.com/maps/geo?ll=#{Geokit::Inflector::url_escape(latlng)}&output=xml&key=#{Geokit::Geocoders::google}&oe=utf-8") + # res = Net::HTTP.get_response(URI.parse("http://maps.google.com/maps/geo?ll=#{Geokit::Inflector::url_escape(address_str)}&output=xml&key=#{Geokit::Geocoders::google}&oe=utf-8")) + return GeoLoc.new if !res.is_a?(Net::HTTPSuccess) + xml = res.body + logger.debug "Google reverse-geocoding. LL: #{latlng}. Result: #{xml}" + return self.xml2GeoLoc(xml) + end # Template method which does the geocode lookup. def self.do_geocode(address) address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address res = self.call_geocoder_service("http://maps.google.com/maps/geo?q=#{Geokit::Inflector::url_escape(address_str)}&output=xml&key=#{Geokit::Geocoders::google}&oe=utf-8") # res = Net::HTTP.get_response(URI.parse("http://maps.google.com/maps/geo?q=#{Geokit::Inflector::url_escape(address_str)}&output=xml&key=#{Geokit::Geocoders::google}&oe=utf-8")) return GeoLoc.new if !res.is_a?(Net::HTTPSuccess) - xml=res.body + xml = res.body logger.debug "Google geocoding. Address: #{address}. Result: #{xml}" + return self.xml2GeoLoc(xml) + end + + def self.xml2GeoLoc(xml) doc=REXML::Document.new(xml) if doc.elements['//kml/Response/Status/code'].text == '200' res = GeoLoc.new coordinates=doc.elements['//coordinates'].text.to_s.split(',') #basics res.lat=coordinates[1] res.lng=coordinates[0] - res.country_code=doc.elements['//CountryNameCode'].text + res.country_code=doc.elements['//CountryNameCode'].text if doc.elements['//CountryNameCode'] res.provider='google' #extended -- false if not not available res.city = doc.elements['//LocalityName'].text if doc.elements['//LocalityName'] res.state = doc.elements['//AdministrativeAreaName'].text if doc.elements['//AdministrativeAreaName'] \ No newline at end of file