{"id":18418569,"url":"https://github.com/bsm/go-geohex","last_synced_at":"2025-04-07T13:31:19.616Z","repository":{"id":12322295,"uuid":"14958787","full_name":"bsm/go-geohex","owner":"bsm","description":"GeoHex implementation in Go","archived":false,"fork":false,"pushed_at":"2017-07-31T09:27:17.000Z","size":205,"stargazers_count":11,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-22T19:02:33.006Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bsm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-12-05T16:17:39.000Z","updated_at":"2020-08-25T06:56:12.000Z","dependencies_parsed_at":"2022-09-12T23:51:04.562Z","dependency_job_id":null,"html_url":"https://github.com/bsm/go-geohex","commit_stats":null,"previous_names":["bsm/geohex.go"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsm%2Fgo-geohex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsm%2Fgo-geohex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsm%2Fgo-geohex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsm%2Fgo-geohex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bsm","download_url":"https://codeload.github.com/bsm/go-geohex/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247661655,"owners_count":20975095,"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-11-06T04:14:01.158Z","updated_at":"2025-04-07T13:31:19.240Z","avatar_url":"https://github.com/bsm.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GeoHex\n\n[![Build Status](https://travis-ci.org/bsm/go-geohex.png)](https://travis-ci.org/bsm/go-geohex)\n[![GoDoc](https://godoc.org/github.com/bsm/go-geohex?status.png)](http://godoc.org/github.com/bsm/go-geohex)\n[![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n\nGeoHex implementation in Go\n\n## Quick Start\n\n```go\nimport (\n\t\"fmt\"\n\n\tgeohex \"github.com/bsm/go-geohex/v3\"\n)\n\nfunc ExampleEncode() {\n\tpos, _ := geohex.Encode(35.647401, 139.716911, 6)\n\tfmt.Println(pos.Code())\n\n\t// Output:\n\t// XM488541\n}\n\nfunc ExampleDecode() {\n\tpos, _ := geohex.Decode(\"XM488541\")\n\tll := pos.LL()\n\tfmt.Println(ll.Lat, ll.Lon)\n\n\t// Output:\n\t// 35.63992106908978 139.72565157750344\n}\n\nfunc ExampleNeighbours() {\n\tpos, _ := geohex.Decode(\"XM488541\")\n\tfor _, n := range pos.Neighbours() {\n\t\tfmt.Println(n.Code())\n\t}\n\n\t// Output:\n\t// XM488545\n\t// XM488516\n\t// XM488544\n\t// XM488517\n\t// XM488542\n\t// XM488540\n}\n```\n\n## Running tests\n\nYou need to install Ginkgo \u0026 Gomega to run tests. Please see\nhttp://onsi.github.io/ginkgo/ for more details.\n\n    $ make testdeps\n\nTo run tests, call:\n\n    $ make test\n\nTo run benchmarks, call:\n\n    $ make bench\n\n## Latest benchmarks\n\n    BenchmarkEncode-4          10000000  190 ns/op   0 B/op   0 allocs/op\n    BenchmarkDecode-4          3000000   444 ns/op   3 B/op   1 allocs/op\n    BenchmarkPosition_Code-4   5000000   326 ns/op   32 B/op  1 allocs/op\n\n## Encoding details\n\nA quick explanation of how lat/lon coordinates are encoded to hexagon positions:\n\nLat/Lon coordinates are projected to a [0,1)x[0x1) square map using\n[Mercator projection](https://en.wikipedia.org/wiki/Mercator_projection), note\nthat this means that hexagons at different latitudes cover different Earth areas.\nThe coordinates on this square are called `e`, `n` in the code (east, north).\n\nThen we transform those coordinates into `x`, `y` coordinates on the hexagons map:\nwe turn the axes 45 degrees and we stretch one of them by a factor of tan(pi/6),\nthis makes each four adjacent hexagons centers' be equidistant. Then we decide\nwhich hexagon contains the desired coordinates. This is probably the trickiest part,\nwe use this condition to decide:\n\n```go\nif yd \u003e -xd+1 \u0026\u0026 yd \u003c 2*xd \u0026\u0026 yd \u003e 0.5*xd {\n  x, y = int(x0)+1, int(y0)+1\n} else if yd \u003c= -xd+1 \u0026\u0026 yd \u003e 2*xd-1 \u0026\u0026 yd \u003c 0.5*xd+0.5 {\n  x, y = int(x0), int(y0)\n} else if yd \u003e xd {\n  x, y = int(x0), int(y0)+1\n} else {\n  x, y = int(x0)+1, int(y0)\n}\n```\n\nWhere `x0` and `y0` are the integer part of the `x`, `y` coordinates after changing\nthe base and `xd`, `yd` are the decimal part of those. If we assume that both `x0` and\n`y0` are zero, you can see how those conditions define limit lines for each of\nfour hexagons on the next drawing, while our `x`, `y` point lays somewhere inside of the square:\n\n![Hexagons on the 1x1 square](/doc/hexagons.png?raw=true)\n\nThis way, previous condtions mean:\n\n```go\nif yd \u003e -xd+1 \u0026\u0026 yd \u003c 2*xd \u0026\u0026 yd \u003e 0.5*xd {\n  // red hexagon\n  x, y = int(x0)+1, int(y0)+1\n} else if yd \u003c= -xd+1 \u0026\u0026 yd \u003e 2*xd-1 \u0026\u0026 yd \u003c 0.5*xd+0.5 {\n  // purple hexagon\n  x, y = int(x0), int(y0)\n} else if yd \u003e xd {\n  // green hexagon\n  x, y = int(x0), int(y0)+1\n} else {\n  // blue hexagon\n  x, y = int(x0)+1, int(y0)\n}\n```\n\nOnce we have our integer position of the hexagon, they are encoded into string,\napproximating in powers of 3 level+2 times: each character is a two-digit base-3\nnumber, where first digit means the relative position of previous `x` approximation,\nand the second one defines the same for `y`.\nFirst three approximations are encoded into two special characters, and after all\nof that, some fixes are applied for world-wrapping and consistency: we maintain all\nof them to make this implementation compatible with the original one from geohex.org.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbsm%2Fgo-geohex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbsm%2Fgo-geohex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbsm%2Fgo-geohex/lists"}