{"id":15563147,"url":"https://github.com/dsoprea/go-geographic-attractor","last_synced_at":"2025-09-17T20:21:44.912Z","repository":{"id":66219030,"uuid":"163670238","full_name":"dsoprea/go-geographic-attractor","owner":"dsoprea","description":"Efficiently identify the nearest major city to a given coordinate.","archived":false,"fork":false,"pushed_at":"2019-05-01T21:50:16.000Z","size":7787,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-12T12:17:35.224Z","etag":null,"topics":["geographic","go","golang","s2"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dsoprea.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2018-12-31T13:13:53.000Z","updated_at":"2021-05-07T05:24:52.000Z","dependencies_parsed_at":"2023-04-01T09:18:50.613Z","dependency_job_id":null,"html_url":"https://github.com/dsoprea/go-geographic-attractor","commit_stats":{"total_commits":33,"total_committers":2,"mean_commits":16.5,"dds":"0.12121212121212122","last_synced_commit":"ae5f9df2c7e0dd0564eb1b3c635641ad48fe0547"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dsoprea/go-geographic-attractor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsoprea%2Fgo-geographic-attractor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsoprea%2Fgo-geographic-attractor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsoprea%2Fgo-geographic-attractor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsoprea%2Fgo-geographic-attractor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dsoprea","download_url":"https://codeload.github.com/dsoprea/go-geographic-attractor/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsoprea%2Fgo-geographic-attractor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275657944,"owners_count":25504774,"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","status":"online","status_checked_at":"2025-09-17T02:00:09.119Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["geographic","go","golang","s2"],"created_at":"2024-10-02T16:19:37.715Z","updated_at":"2025-09-17T20:21:44.884Z","avatar_url":"https://github.com/dsoprea.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/dsoprea/go-geographic-attractor.svg?branch=master)](https://travis-ci.org/dsoprea/go-geographic-attractor)\n[![Coverage Status](https://coveralls.io/repos/github/dsoprea/go-geographic-attractor/badge.svg?branch=master)](https://coveralls.io/github/dsoprea/go-geographic-attractor?branch=master)\n[![GoDoc](https://godoc.org/github.com/dsoprea/go-geographic-attractor?status.svg)](https://godoc.org/github.com/dsoprea/go-geographic-attractor/index)\n\n# Overview\n\nIdentifies the nearest major city to a given coordinate.\n\n\n# Details\n\nThe purpose of this project is to provide an index that identifies the nearest urban center (\"biggest city\", \"metropolitan area\") very efficiently using Google's S2 algorithm as applied to the Earth. This basically subdivides the Earth into individual cells in a way that mitigates traditional distortion as well as optimizing how we interrelate smaller areas with larger areas.\n\nThis algorithm looks to within, approximately, thirty to forty miles of the given coordinates for a city with a population of at least 100,000. If one is found, that city is returned. If one is not found, the first city that *was* found is returned (so, not an urban center but the actual city that was searched). If no city was found, then error `geoattractorindex.ErrNoNearestCity` is returned.\n\n\n# Algorithm Notes\n\nDue to how the cells are calculated, this is only an approximation and the nearest city may sometimes be biased a little north/south/west/east of what you were expecting. However, the algorithm is very, very efficient and reduces a problem that is traditionally solved via clustering (very expensive) to a string-prefix search.\n\nIn other words, this algorithm is what you want if you can accept some minor approximation errors in exchange for instanteous searches rather than requiring a clusterized algorithm.\n\n\n# Requirements\n\n- A supported dataset. Currently, only [GeoNames](https://www.geonames.org) is supported. Browse to \"Download\" -\u003e \"[Free Gazetteer Data](http://download.geonames.org/export/dump)\". Specifically, we require \"countryInfo.txt\" and \"allCountries.zip\" files.\n\n\n# Usage\n\nFor usage examples, see the examples at [GoDoc](https://godoc.org/github.com/dsoprea/go-geographic-attractor).\n\n\n# Tool\n\nA command-line tool is also provided in order to test the index. This will load the index and then perform the search. As the index exists in memory, this is done at the top of every execution.\n\n\n## Install\n\n```\n$ go get -t github.com/dsoprea/go-geographic-attractor/command/find_nearest_city\n$ cd $GOPATH/src/github.com/dsoprea/go-geographic-attractor/command/find_nearest_city\n$ go install\n```\n\n\n## Usage Examples\n\nA simple query:\n\n```\n$ $GOPATH/bin/find_nearest_city --latitude 25.648315 --longitude -80.314120 --country-data-filepath countryInfo.txt --city-data-filepath allCountries.zip\nSource: GeoNames\nID: 7170183\nCountry: United States\nCity: City of Hialeah\nPopulation: 224669\nLatitude: 25.8696300000\nLongitude: -80.3045600000\n```\n\nNote that the tool is obviously just for testing as loading the index is [necessarily] expensive:\n\n```\n$ time $GOPATH/bin/find_nearest_city --latitude 25.648315 --longitude -80.314120 --country-data-filepath countryInfo.txt --city-data-filepath allCountries.zip\nSource: GeoNames\nID: 7170183\nCountry: United States\nCity: City of Hialeah\nPopulation: 224669\nLatitude: 25.8696300000\nLongitude: -80.3045600000\n\nreal\t0m23.927s\nuser\t0m28.365s\nsys\t0m0.346s\n```\n\nPrint with increased verbosity. Specifically, this will print the concentric cells that are checked as we move from the smallest cell (with longer S2 cell IDs representing smaller, specific cells containing the nearest city to the given coordinates) outwards to larger cells (with smaller S2 cell IDs representing larger areas):\n\n```\n$ $GOPATH/bin/find_nearest_city --latitude 25.648315 --longitude -80.314120 --country-data-filepath countryInfo.txt --city-data-filepath allCountries.zip --verbose\nVISIT( 0): 88d9c65: CityRecord\u003cID=[7172726] COUNTRY=[United States] CITY=[Village of Pinecrest] POP=(18223) LAT=(25.6650300000) LON=(-80.3042300000)\u003e\nVISIT( 1): 88d9c64: CityRecord\u003cID=[7172726] COUNTRY=[United States] CITY=[Village of Pinecrest] POP=(18223) LAT=(25.6650300000) LON=(-80.3042300000)\u003e\nVISIT( 2): 88d9c7: CityRecord\u003cID=[7172726] COUNTRY=[United States] CITY=[Village of Pinecrest] POP=(18223) LAT=(25.6650300000) LON=(-80.3042300000)\u003e\nVISIT( 3): 88d9c4: CityRecord\u003cID=[7171588] COUNTRY=[United States] CITY=[Town of Cutler Bay] POP=(40286) LAT=(25.5764800000) LON=(-80.3356600000)\u003e\nVISIT( 4): 88d9d: CityRecord\u003cID=[7317991] COUNTRY=[United States] CITY=[City of Homestead] POP=(60512) LAT=(25.4664000000) LON=(-80.4472300000)\u003e\nVISIT( 5): 88d9c: CityRecord\u003cID=[7170183] COUNTRY=[United States] CITY=[City of Hialeah] POP=(224669) LAT=(25.8696300000) LON=(-80.3045600000)\u003e\n\nSource: GeoNames\nID: 7170183\nCountry: United States\nCity: City of Hialeah\nPopulation: 224669\nLatitude: 25.8696300000\nLongitude: -80.3045600000\n```\n\n\nPrint as JSON:\n\n```\n$ $GOPATH/bin/find_nearest_city --latitude 25.648315 --longitude -80.314120 --country-data-filepath countryInfo.txt --city-data-filepath allCountries.zip --json\n{\n  \"Result\": {\n    \"id\": \"7170183\",\n    \"country\": \"United States\",\n    \"city\": \"City of Hialeah\",\n    \"population\": 224669,\n    \"latitude\": 25.86963,\n    \"longitude\": -80.30456\n  },\n  \"Stats\": {\n    \"unfiltered_records_parsed\": 11857354,\n    \"records_added_to_index\": 2061072,\n    \"records_updated_in_index\": 60040\n  }\n}\n```\n\n\nNo nearest city:\n\n```\n$ $GOPATH/bin/find_nearest_city --latitude 11.827416 --longitude -110.548982 --country-data-filepath countryInfo.txt --city-data-filepath allCountries.zip\nNo nearest city found.\n\n$ echo $?\n10\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdsoprea%2Fgo-geographic-attractor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdsoprea%2Fgo-geographic-attractor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdsoprea%2Fgo-geographic-attractor/lists"}