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