Parent

Geokit::Geocoders::GoogleGeocoder

Google geocoder implementation. Requires the Geokit::Geocoders::GOOGLE variable to contain a Google API key. Conforms to the interface set by the Geocoder class.

Private Class Methods

construct_bias_string_from_options(bias) click to toggle source

(Not documented)

     # File /Users/andre/projects/rails/geokit/lib/geokit/geocoders.rb, line 442
442:       def self.construct_bias_string_from_options(bias)
443:         if bias.is_a?(String) or bias.is_a?(Symbol)
444:           # country code biasing
445:           "&gl=#{bias.to_s.downcase}"
446:         elsif bias.is_a?(Bounds)
447:           # viewport biasing
448:           "&ll=#{bias.center.ll}&spn=#{bias.to_span.ll}"
449:         end
450:       end
do_geocode(address, options = {}) click to toggle source

Template method which does the geocode lookup.

Supports viewport/country code biasing

OPTIONS

  • :bias - This option makes the Google Geocoder return results biased to a particular
            country or viewport. Country code biasing is achieved by passing the ccTLD
            ('uk' for .co.uk, for example) as a :bias value. For a list of ccTLD's,
            look here: http://en.wikipedia.org/wiki/CcTLD. By default, the geocoder
            will be biased to results within the US (ccTLD .com).
    
            If you'd like the Google Geocoder to prefer results within a given viewport,
            you can pass a Geokit::Bounds object as the :bias value.
    

EXAMPLES

# By default, the geocoder will return Syracuse, NY Geokit::Geocoders::GoogleGeocoder.geocode(‘Syracuse’).country_code # => ‘US’ # With country code biasing, it returns Syracuse in Sicily, Italy Geokit::Geocoders::GoogleGeocoder.geocode(‘Syracuse’, :bias => :it).country_code # => ‘IT’

# By default, the geocoder will return Winnetka, IL Geokit::Geocoders::GoogleGeocoder.geocode(‘Winnetka’).state # => ‘IL’ # When biased to an bounding box around California, it will now return the Winnetka neighbourhood, CA bounds = Geokit::Bounds.normalize([34.074081, -118.694401], [34.321129, -118.399487]) Geokit::Geocoders::GoogleGeocoder.geocode(‘Winnetka’, :bias => bounds).state # => ‘CA’

     # File /Users/andre/projects/rails/geokit/lib/geokit/geocoders.rb, line 432
432:       def self.do_geocode(address, options = {})
433:         bias_str = options[:bias] ? construct_bias_string_from_options(options[:bias]) : ''
434:         address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
435:         res = self.call_geocoder_service("http://maps.google.com/maps/geo?q=#{Geokit::Inflector::url_escape(address_str)}&output=xml#{bias_str}&key=#{Geokit::Geocoders::google}&oe=utf-8")
436:         return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
437:         xml = res.body
438:         logger.debug "Google geocoding. Address: #{address}. Result: #{xml}"
439:         return self.xml2GeoLoc(xml, address)        
440:       end
do_reverse_geocode(latlng) click to toggle source

Template method which does the reverse-geocode lookup.

     # File /Users/andre/projects/rails/geokit/lib/geokit/geocoders.rb, line 397
397:       def self.do_reverse_geocode(latlng) 
398:         latlng=LatLng.normalize(latlng)
399:         res = self.call_geocoder_service("http://maps.google.com/maps/geo?ll=#{Geokit::Inflector::url_escape(latlng.ll)}&output=xml&key=#{Geokit::Geocoders::google}&oe=utf-8")
400:         #        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"))
401:         return GeoLoc.new unless (res.is_a?(Net::HTTPSuccess) || res.is_a?(Net::HTTPOK))
402:         xml = res.body
403:         logger.debug "Google reverse-geocoding. LL: #{latlng}. Result: #{xml}"
404:         return self.xml2GeoLoc(xml)        
405:       end
extract_placemark(doc) click to toggle source

extracts a single geoloc from a //placemark element in the google results xml

     # File /Users/andre/projects/rails/geokit/lib/geokit/geocoders.rb, line 487
487:       def self.extract_placemark(doc)
488:         res = GeoLoc.new
489:         coordinates=doc.elements['.//coordinates'].text.to_s.split(',')
490: 
491:         #basics
492:         res.lat=coordinates[1]
493:         res.lng=coordinates[0]
494:         res.country_code=doc.elements['.//CountryNameCode'].text if doc.elements['.//CountryNameCode']
495:         res.provider='google'
496: 
497:         #extended -- false if not not available
498:         res.city = doc.elements['.//LocalityName'].text if doc.elements['.//LocalityName']
499:         res.state = doc.elements['.//AdministrativeAreaName'].text if doc.elements['.//AdministrativeAreaName']
500:         res.province = doc.elements['.//SubAdministrativeAreaName'].text if doc.elements['.//SubAdministrativeAreaName']
501:         res.full_address = doc.elements['.//address'].text if doc.elements['.//address'] # google provides it
502:         res.zip = doc.elements['.//PostalCodeNumber'].text if doc.elements['.//PostalCodeNumber']
503:         res.street_address = doc.elements['.//ThoroughfareName'].text if doc.elements['.//ThoroughfareName']
504:         res.country = doc.elements['.//CountryName'].text if doc.elements['.//CountryName']
505:         res.district = doc.elements['.//DependentLocalityName'].text if doc.elements['.//DependentLocalityName']
506:         # Translate accuracy into Yahoo-style token address, street, zip, zip+4, city, state, country
507:         # For Google, 1=low accuracy, 8=high accuracy
508:         address_details=doc.elements['.//*[local-name() = "AddressDetails"]']
509:         res.accuracy = address_details ? address_details.attributes['Accuracy'].to_i : 0
510:         res.precision=%w{unknown country state state city zip zip+4 street address building}[res.accuracy]
511:         
512:         # google returns a set of suggested boundaries for the geocoded result
513:         if suggested_bounds = doc.elements['//LatLonBox']  
514:           res.suggested_bounds = Bounds.normalize(
515:                                   [suggested_bounds.attributes['south'], suggested_bounds.attributes['west']], 
516:                                   [suggested_bounds.attributes['north'], suggested_bounds.attributes['east']])
517:         end
518:         
519:         res.success=true
520: 
521:         return res
522:       end
xml2GeoLoc(xml, address="") click to toggle source

(Not documented)

     # File /Users/andre/projects/rails/geokit/lib/geokit/geocoders.rb, line 452
452:       def self.xml2GeoLoc(xml, address="")
453:         doc=REXML::Document.new(xml)
454: 
455:         if doc.elements['//kml/Response/Status/code'].text == '200'
456:           geoloc = nil
457:           # Google can return multiple results as //Placemark elements. 
458:           # iterate through each and extract each placemark as a geoloc
459:           doc.each_element('//Placemark') do |e|
460:             extracted_geoloc = extract_placemark(e) # g is now an instance of GeoLoc
461:             if geoloc.nil? 
462:               # first time through, geoloc is still nil, so we make it the geoloc we just extracted
463:               geoloc = extracted_geoloc 
464:             else
465:               # second (and subsequent) iterations, we push additional 
466:               # geolocs onto "geoloc.all" 
467:               geoloc.all.push(extracted_geoloc) 
468:             end  
469:           end
470:           return geoloc
471:         elsif doc.elements['//kml/Response/Status/code'].text == '620'
472:            raise Geokit::TooManyQueriesError
473:         else
474:           logger.info "Google was unable to geocode address: "+address
475:           return GeoLoc.new
476:         end
477: 
478:       rescue Geokit::TooManyQueriesError
479:         # re-raise because of other rescue
480:         raise Geokit::TooManyQueriesError, "Google returned a 620 status, too many queries. The given key has gone over the requests limit in the 24 hour period or has submitted too many requests in too short a period of time. If you're sending multiple requests in parallel or in a tight loop, use a timer or pause in your code to make sure you don't send the requests too quickly."
481:       rescue
482:         logger.error "Caught an error during Google geocoding call: "+$!
483:         return GeoLoc.new
484:       end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.