{"id":13463385,"url":"https://github.com/geokit/geokit","last_synced_at":"2025-05-13T20:19:48.209Z","repository":{"id":458925,"uuid":"82963","full_name":"geokit/geokit","owner":"geokit","description":"Official Geokit Gem. Geokit gem provides geocoding and distance/heading calculations. Pair with the geokit-rails plugin for full-fledged location-based app functionality.","archived":false,"fork":false,"pushed_at":"2024-07-29T00:47:05.000Z","size":13180,"stargazers_count":1634,"open_issues_count":19,"forks_count":363,"subscribers_count":38,"default_branch":"master","last_synced_at":"2025-04-28T11:52:28.171Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/geokit.png","metadata":{"files":{"readme":"README.markdown","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2008-12-01T05:49:32.000Z","updated_at":"2025-04-20T20:50:37.000Z","dependencies_parsed_at":"2024-01-08T17:13:52.838Z","dependency_job_id":"8051d926-22b1-4136-b10f-0aed03441caf","html_url":"https://github.com/geokit/geokit","commit_stats":{"total_commits":578,"total_committers":114,"mean_commits":"5.0701754385964914","dds":0.7318339100346021,"last_synced_commit":"8c921fde4446df4850f4677d5081ff4f783d7acc"},"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geokit%2Fgeokit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geokit%2Fgeokit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geokit%2Fgeokit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geokit%2Fgeokit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/geokit","download_url":"https://codeload.github.com/geokit/geokit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254020659,"owners_count":22000757,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T13:00:52.497Z","updated_at":"2025-05-13T20:19:48.177Z","avatar_url":"https://github.com/geokit.png","language":"Ruby","funding_links":[],"categories":["Time \u0026 Space","Geolocation","Ruby"],"sub_categories":["Geocoding \u0026 Maps"],"readme":"Geokit\n======\n\n[![Gem Version](https://badge.fury.io/rb/geokit.svg)](http://badge.fury.io/rb/geokit)\n[![Build Status](https://github.com/geokit/geokit/workflows/CI/badge.svg)](https://github.com/geokit/geokit/actions)\n[![Coverage Status](https://coveralls.io/repos/geokit/geokit/badge.svg)](https://coveralls.io/r/geokit/geokit)\n[![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com)\n[![Code Climate](https://codeclimate.com/github/geokit/geokit.svg)](https://codeclimate.com/github/geokit/geokit)\n\n## DESCRIPTION\n\nThe Geokit gem provides:\n\n * Distance calculations between two points on the earth. Calculate the distance in miles, kilometers, meters, or nautical miles, with all the trigonometry abstracted away by Geokit.\n * Geocoding from multiple providers. It supports Google, Yahoo, and Geocoder.ca geocoders, and others. It provides a uniform response structure from all of them.\n   It also provides a fail-over mechanism, in case your input fails to geocode in one service.\n * Rectangular bounds calculations: is a point within a given rectangular bounds?\n * Heading and midpoint calculations\n\nCombine this gem with the [geokit-rails](http://github.com/geokit/geokit-rails) to get location-based finders for your Rails app.\n\n* Repository at Github: [http://github.com/geokit/geokit](http://github.com/geokit/geokit).\n* RDoc pages: [http://rdoc.info/github/geokit/geokit/master/frames](http://rdoc.info/github/geokit/geokit/master/frames)\n\n## COMMUNICATION\n\n* If you **need help**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/geokit). (Tag 'geokit' and we'll be alerted)\n* If you **found a bug**, use GitHub issues.\n* If you **have an idea**, use GitHub issues.\n* If you'd like to **ask a general question**, use GitHub issues.\n* If you **want to contribute**, submit a pull request.\n\n## INSTALL\n\n    gem install geokit\n\n## SUPPORTED GEOCODERS\n\n### \"regular\" address geocoders\n* Yahoo BOSS - requires an API key.\n* Geocoder.ca - for Canada; may require authentication as well.\n* Geonames - a free geocoder\n* Bing\n* Yandex\n* MapQuest\n* Geocod.io\n* OpenStreetMap (Nominatim)\n* Mapbox - requires an access token\n* [OpenCage](http://geocoder.opencagedata.com) - requires an API key\n\n### address geocoders that also provide reverse geocoding\n* Google - Supports multiple results and bounding box/country code biasing.  Also supports Maps API for Business keys; see the configuration section below.\n* FCC\n* OpenStreetMap (Nominatim)\n* Mapbox\n* OpenCage\n\n### IP address geocoders\n* IP - geocodes an IP address using hostip.info's web service.\n* Geoplugin.net -- another IP address geocoder\n* RIPE\n* MaxMind\n* Ipstack\n* IP-API.com\n\n### HTTPS-supporting geocoders\n* Google\n* Yahoo\n* Bing\n* FCC\n* MapQuest\n* Mapbox\n* OpenCage\n\nOptions to control the use of HTTPS are described below in the Configuration section.\n\n## QUICK START\n\n```ruby\n    irb\u003e require 'rubygems'\n    irb\u003e require 'geokit'\n    irb\u003e a=Geokit::Geocoders::GoogleGeocoder.geocode '140 Market St, San Francisco, CA'\n    irb\u003e a.ll\n     =\u003e 37.79363,-122.396116\n    irb\u003e b=Geokit::Geocoders::GoogleGeocoder.geocode '789 Geary St, San Francisco, CA'\n    irb\u003e b.ll\n     =\u003e 37.786217,-122.41619\n    irb\u003e a.distance_to(b)\n     =\u003e 1.21120007413626\n    irb\u003e a.heading_to(b)\n    =\u003e 244.959832435678\n    irb(main):006:0\u003e c=a.midpoint_to(b)      # what's halfway from a to b?\n    irb\u003e c.ll\n    =\u003e \"37.7899239257175,-122.406153503469\"\n    irb(main):008:0\u003e d=c.endpoint(90,10)     # what's 10 miles to the east of c?\n    irb\u003e d.ll\n    =\u003e \"37.7897825005142,-122.223214776155\"\n```\n\nFYI, that `.ll` method means \"latitude longitude\".\n\nSee the RDOC more more ... there are also operations on rectangular bounds (e.g., determining if a point is within bounds, find the center, etc).\n\n## CONFIGURATION\n\nIf you're using this gem by itself, here are the configuration options:\n\n```ruby\n    # These defaults are used in Geokit::Mappable.distance_to and in acts_as_mappable\n    Geokit::default_units = :miles # others :kms, :nms, :meters\n    Geokit::default_formula = :sphere\n\n    # This is the timeout value in seconds to be used for calls to the geocoder web\n    # services.  For no timeout at all, comment out the setting.  The timeout unit\n    # is in seconds.\n    Geokit::Geocoders::request_timeout = 3\n\n    # This setting can be used if web service calls must be routed through a proxy.\n    # These setting can be nil if not needed, otherwise, a valid URI must be\n    # filled in at a minimum.  If the proxy requires authentication, the username\n    # and password can be provided as well.\n    Geokit::Geocoders::proxy = 'https://user:password@host:port'\n\n    # This setting can be used if a web service blocks requests by certain user agents.\n    # If not set Geokit uses the default useragent header set by the different net adapter libs.\n    Geokit::Geocoders::useragent = 'my agent string'\n\n    # This is your yahoo application key for the Yahoo Geocoder.\n    # See http://developer.yahoo.com/faq/index.html#appid\n    # and http://developer.yahoo.com/maps/rest/V1/geocode.html\n    Geokit::Geocoders::YahooGeocoder.key = 'REPLACE_WITH_YOUR_YAHOO_KEY'\n    Geokit::Geocoders::YahooGeocoder.secret = 'REPLACE_WITH_YOUR_YAHOO_SECRET'\n\n    # This is your Google Maps geocoder keys (all optional).\n    # See http://www.google.com/apis/maps/signup.html\n    # and http://www.google.com/apis/maps/documentation/#Geocoding_Examples\n    Geokit::Geocoders::GoogleGeocoder.client_id = ''\n    Geokit::Geocoders::GoogleGeocoder.cryptographic_key = ''\n    Geokit::Geocoders::GoogleGeocoder.channel = ''\n\n    # You can also use the free API key instead of signed requests\n    # See https://developers.google.com/maps/documentation/geocoding/#api_key\n    Geokit::Geocoders::GoogleGeocoder.api_key = ''\n\n    # You can also set multiple API KEYS for different domains that may be directed to this same application.\n    # The domain from which the current user is being directed will automatically be updated for Geokit via\n    # the GeocoderControl class, which gets it's begin filter mixed into the ActionController.\n    # You define these keys with a Hash as follows:\n    #Geokit::Geocoders::google = { 'rubyonrails.org' =\u003e 'RUBY_ON_RAILS_API_KEY', 'ruby-docs.org' =\u003e 'RUBY_DOCS_API_KEY' }\n\n    # This is your authorization key for geocoder.ca.\n    # To use the free service, the value can be set to nil or false.  For\n    # usage tied to an account, set the value to the key obtained from\n    # Geocoder.ca.\n    # See http://geocoder.ca\n    # and http://geocoder.ca/?register=1\n    Geokit::Geocoders::CaGeocoder.key = 'KEY'\n\n    # This is your username key for geonames.\n    # To use this service either free or premium, you must register a key.\n    # See http://www.geonames.org\n    Geokit::Geocoders::GeonamesGeocoder.key = 'KEY'\n\n    # This is your access key for ipstack.\n    # To use this service either free or premium, you must register a key.\n    # See https://ipstack.com\n    Geokit::Geocoders::IpstackGeocoder.api_key = 'API_KEY'\n\n    # This is your api key for ip-api.com.\n    # For the free version (with rate limits), leave api_key unset.\n    # See https://ip-api.com/\n    Geokit::Geocoders::IpApiGeocoder.key = ''\n\n    # Most other geocoders need either no setup or a key\n    Geokit::Geocoders::BingGeocoder.key = ''\n    Geokit::Geocoders::MapQuestGeocoder.key = ''\n    Geokit::Geocoders::YandexGeocoder.key = ''\n    Geokit::Geocoders::MapboxGeocoder.key = 'ACCESS_TOKEN'\n    Geokit::Geocoders::OpencageGeocoder.key = 'some_api_key'\n\n    # Geonames has a free service and a premium service, each using a different URL\n    # GeonamesGeocoder.premium = true will use http://ws.geonames.net (premium)\n    # GeonamesGeocoder.premium = false will use http://api.geonames.org (free)\n    Geokit::Geocoders::GeonamesGeocoder.premium = false\n\n    # require \"external_geocoder.rb\"\n    # Please see the section \"writing your own geocoders\" for more information.\n    # Geokit::Geocoders::external_key = 'REPLACE_WITH_YOUR_API_KEY'\n\n    # This is the order in which the geocoders are called in a failover scenario\n    # If you only want to use a single geocoder, put a single symbol in the array.\n    #\n    # Valid symbols are: :bing, :ca, :fcc, :geocodio, :geonames, :google,\n    # :map_quest, :mapbox, :maxmind, :opencage, :osm, :us, :yahoo, and :yandex.\n    #\n    # Be aware that there are Terms of Use restrictions on how you can use the\n    # various geocoders.  Make sure you read up on relevant Terms of Use for each\n    # geocoder you are going to use.\n    Geokit::Geocoders::provider_order = [:google]\n\n    # The IP provider order.\n    #\n    # Valid symbols are :ipstack, :geo_plugin, :ip, and :ripe.\n    #\n    # As before, make sure you read up on relevant Terms of Use for each.\n    # Geokit::Geocoders::ip_provider_order = [:external,:geo_plugin,:ip]\n\n\t# Disable HTTPS globally.  This option can also be set on individual\n\t# geocoder classes.\n    Geokit::Geocoders::secure = false\n\n    # Control verification of the server certificate for geocoders using HTTPS\n    Geokit::Geocoders::ssl_verify_mode = OpenSSL::SSL::VERIFY_(PEER/NONE)\n    # Setting this to VERIFY_NONE may be needed on systems that don't have\n    # a complete or up to date root certificate store. Only applies to\n    # the Net::HTTP adapter.\n```\n\n### Google Geocoder Tricks\n\nThe Google Geocoder sports a number of useful tricks that elevate it a little bit above the rest of the currently supported geocoders. For starters, it returns a `suggested_bounds` property for all your geocoded results, so you can more easily decide where and how to center a map on the places you geocode. Here's a quick example:\n\n```ruby\n    irb\u003e res = Geokit::Geocoders::GoogleGeocoder.geocode('140 Market St, San Francisco, CA')\n    irb\u003e pp res.suggested_bounds\n    #\u003cGeokit::Bounds:0x53b36c\n     @ne=#\u003cGeokit::LatLng:0x53b204 @lat=37.7968528, @lng=-122.3926933\u003e,\n     @sw=#\u003cGeokit::LatLng:0x53b2b8 @lat=37.7905576, @lng=-122.3989885\u003e\u003e\n\nIn addition, you can use viewport or country code biasing to make sure the geocoders prefers results within a specific area. Say we wanted to geocode the city of Toledo in Spain. A normal geocoding query would look like this:\n\n    irb\u003e res = Geokit::Geocoders::GoogleGeocoder.geocode('Toledo')\n    irb\u003e res.full_address\n    =\u003e \"Toledo, OH, USA\"\n```\n\nNot exactly what we were looking for. We know that Toledo is in Spain, so we can tell the Google Geocoder to prefer results from Spain first, and then wander the Toledos of the world. To do that, we have to pass Spain's ccTLD (country code top-level domain) to the `:bias` option of the `geocode` method. You can find a comprehensive list of all ccTLDs here: http://en.wikipedia.org/wiki/CcTLD.\n\n```ruby\n    irb\u003e res = Geokit::Geocoders::GoogleGeocoder.geocode('Toledo', :bias =\u003e 'es')\n    irb\u003e res.full_address\n    =\u003e \"Toledo, Toledo, Spain\"\n```\n\nAlternatively, we can specify the geocoding bias as a bounding box object. Say we wanted to geocode the Winnetka district in Los Angeles.\n\n```ruby\n    irb\u003e res = Geokit::Geocoders::GoogleGeocoder.geocode('Winnetka')\n    irb\u003e res.full_address\n    =\u003e \"Winnetka, IL, USA\"\n```\n\nNot it. What we can do is tell the geocoder to return results only from in and around LA.\n\n```ruby\n    irb\u003e la_bounds = Geokit::Geocoders::GoogleGeocoder.geocode('Los Angeles').suggested_bounds\n    irb\u003e res = Geokit::Geocoders::GoogleGeocoder.geocode('Winnetka', :bias =\u003e la_bounds)\n    irb\u003e res.full_address\n    =\u003e \"Winnetka, California, USA\"\n```\n\nAnother option is to use Component Filtering as described at https://developers.google.com/maps/documentation/geocoding/intro#ComponentFiltering. To do that supply the `:components` option to the `geocode` method. This option should be a hash with keys corresponding to desired component names.\n\nSuppose we'd like to geocode string 'Austin'. Regularly, Google would return 'Austin, TX, USA' for such a query. Not with component filtering:\n\n```ruby\n    irb\u003eres = Geokit::Geocoders::GoogleGeocoder.geocode(\"austin\", components: { administrative_area: 'IL', country: 'US' })\n    irb\u003eres.full_address\n    =\u003e \"Austin, Chicago, IL, USA\"\n```\n\n### The Multigeocoder\nMulti Geocoder - provides failover for the physical location geocoders, and also IP address geocoders. Its configured by setting Geokit::Geocoders::provider_order, and Geokit::Geocoders::ip_provider_order. You should call the Multi-Geocoder with its :geocode method, supplying one address parameter which is either a real street address, or an ip address. For example:\n\n```ruby\n    Geokit::Geocoders::MultiGeocoder.geocode(\"900 Sycamore Drive\")\n\n    Geokit::Geocoders::MultiGeocoder.geocode(\"12.12.12.12\")\n\n    Geokit::Geocoders::MultiGeocoder.geocode(\"Hamburg, Germany\", :provider_order =\u003e [:osm, :mapbox, :google])\n```\n\n## MULTIPLE RESULTS\nSome geocoding services will return multiple results if the there isn't one clear result.\nGeoloc can capture multiple results through its \"all\" method.\n\n```ruby\n    irb\u003e geo=Geokit::Geocoders::GoogleGeocoder.geocode(\"900 Sycamore Drive\")\n    irb\u003e geo.full_address\n    =\u003e \"900 Sycamore Dr, Arkadelphia, AR 71923, USA\"\n    irb\u003e geo.all.size\n    irb\u003e geo.all.each { |e| puts e.full_address }\n    900 Sycamore Dr, Arkadelphia, AR 71923, USA\n    900 Sycamore Dr, Burkburnett, TX 76354, USA\n    900 Sycamore Dr, TN 38361, USA\n    ....\n```\n\ngeo.all is just an array of additional Geolocs, so do what you want with it. If you call .all on a\ngeoloc that doesn't have any additional results, you will get  an array of one.\n\n\n## NOTES ON WHAT'S WHERE\n\nmappable.rb contains the Mappable module, which provides basic\ndistance calculation methods, i.e., calculating the distance\nbetween two points.\n\nLatLng is a simple container for latitude and longitude, but\nit's made more powerful by mixing in the above-mentioned Mappable\nmodule -- therefore, you can calculate easily the distance between two\nLatLng objects with `distance = first.distance_to(other)`\n\nGeoLoc represents an address or location which\nhas been geocoded. You can get the city, zipcode, street address, etc.\nfrom a GeoLoc object. GeoLoc extends LatLng, so you also get lat/lng\nAND the Mappable module goodness for free.\n\ngeocoders.rb contains all the geocoder implementations. All the geocoders\ninherit from a common base (class Geocoder) and implement the private method\ndo_geocode.\n\n## WRITING YOUR OWN GEOCODERS\n\nIf you would like to write your own geocoders, you can do so by requiring 'geokit' or 'geokit/geocoders.rb' in a new file and subclassing the base class (which is class \"Geocoder\").\nYou must then also require such external file back in your main geokit configuration.\n\n```ruby\n  require \"geokit\"\n\n  module Geokit\n    module Geocoders\n\n      # and use :my to specify this geocoder in your list of geocoders.\n      class MyGeocoder \u003c Geocoder\n\n        # Use via: Geokit::Geocoders::MyGeocoder.key = 'MY KEY'\n        config :key\n\n        private\n\n        def self.do_geocode(address, options = {})\n          # Main geocoding method\n        end\n\n        def self.parse_json(json)\n          # Helper method to parse http response. See geokit/geocoders.rb.\n        end\n      end\n\n    end\n  end\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeokit%2Fgeokit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeokit%2Fgeokit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeokit%2Fgeokit/lists"}