{"id":13508227,"url":"https://github.com/yltsrc/geocalc","last_synced_at":"2025-10-21T18:59:34.218Z","repository":{"id":51523965,"uuid":"43765833","full_name":"yltsrc/geocalc","owner":"yltsrc","description":"Geographic calculations for Elixir","archived":false,"fork":false,"pushed_at":"2022-10-14T12:57:57.000Z","size":229,"stargazers_count":149,"open_issues_count":1,"forks_count":21,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-11-01T07:33:30.278Z","etag":null,"topics":["hacktoberfest"],"latest_commit_sha":null,"homepage":"","language":"Elixir","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/yltsrc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-10-06T17:17:45.000Z","updated_at":"2024-10-28T15:17:42.000Z","dependencies_parsed_at":"2022-08-03T04:30:54.046Z","dependency_job_id":null,"html_url":"https://github.com/yltsrc/geocalc","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yltsrc%2Fgeocalc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yltsrc%2Fgeocalc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yltsrc%2Fgeocalc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yltsrc%2Fgeocalc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yltsrc","download_url":"https://codeload.github.com/yltsrc/geocalc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246307578,"owners_count":20756473,"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":["hacktoberfest"],"created_at":"2024-08-01T02:00:50.074Z","updated_at":"2025-10-21T18:59:29.160Z","avatar_url":"https://github.com/yltsrc.png","language":"Elixir","funding_links":[],"categories":["Geolocation"],"sub_categories":[],"readme":"# Geocalc\n\n[![Build Status](https://github.com/yltsrc/geocalc/actions/workflows/elixir.yml/badge.svg?branch=master)](https://github.com/yltsrc/geocalc/actions/workflows/elixir.yml?query=branch%3Amaster)\n[![Module Version](https://img.shields.io/hexpm/v/geocalc.svg)](https://hex.pm/packages/geocalc)\n[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/geocalc/)\n[![Total Download](https://img.shields.io/hexpm/dt/geocalc.svg)](https://hex.pm/packages/geocalc)\n[![License](https://img.shields.io/hexpm/l/geocalc.svg)](https://github.com/yltsrc/geocalc/blob/master/LICENSE.md)\n[![Last Updated](https://img.shields.io/github/last-commit/yltsrc/geocalc.svg)](https://github.com/yltsrc/geocalc/commits/master)\n\nCalculate distance, bearing and more between latitude/longitude points.\n\nAll the formulas are adapted from\n[http://www.movable-type.co.uk/scripts/latlong.html](http://www.movable-type.co.uk/scripts/latlong.html).\n\nArea calculations are implemented from\n[ETSI EN 302 931 v1.1.1](https://www.etsi.org/deliver/etsi_en/302900_302999/302931/01.01.01_60/en_302931v010101p.pdf) standard.\n\n## Installation\n\nFirst, add `:geocalc` to your `mix.exs` dependencies:\n\n```elixir\ndef deps do\n  [\n    {:geocalc, \"~\u003e 0.8\"}\n  ]\nend\n```\n\nAnd then fetch your dependencies:\n\n```bash\n$ mix deps.get\n```\n\n\n## Usage\n\n### Calculate distance (in meters) between 2 points\n\n```elixir\nGeocalc.distance_between([50.0663889, -5.7147222], [58.6438889, -3.07])\n# =\u003e 968853.5464535094\n```\n\n### Calculate if point is inside a circle given by a center point and a radius (in meters)\n\n```elixir\nsan_juan = [18.4655, 66.1057]\npuerto_rico = [18.2208, 66.5901]\nGeocalc.within?(170_000, san_juan, puerto_rico)\n# =\u003e true\n```\n\n### Get destination point given distance (meters) from start and end point\n\n```elixir\nGeocalc.destination_point([50.0663889, -5.7147222], [58.6438889, -3.07], 100_000)\n# =\u003e {:ok, [50.95412546615634, -5.488452905258299]}\n```\n\n### Get destination point given distance (meters) and bearing from start point\n\n```elixir\nGeocalc.destination_point([50.0663889, -5.7147222], 2.123, 100_000)\n# =\u003e {:ok, [49.58859917965055, -4.533613856982982]}\n```\n\n### Calculate bearing from start and end points\n\n```elixir\nGeocalc.bearing([50.0663889, -5.7147222], [58.6438889, -3.07])\n# =\u003e 0.1591708517503001\n```\n\n### Get intersection point given start points and bearings\n\n```elixir\nGeocalc.intersection_point([50.0663889, -5.7147222], 2.123, [55.0663889, -15.7147222], 2.123)\n# =\u003e {:ok, [48.04228582473962, -1.0347033632388496]}\n\nGeocalc.intersection_point([50.0663889, -5.7147222], 2.123, [50.0663889, -5.7147222], 2.123)\n# =\u003e {:error, \"No intersection point found\"}\n```\n\n### Get bounding box from a point and radius\n\n```elixir\nberlin = [52.5075419, 13.4251364]\nradius = 10_000\nGeocalc.bounding_box(berlin, radius)\n# =\u003e [[52.417520954378574, 13.277235453275123], [52.59756284562143, 13.573037346724874]]\n```\n\n### Get bounding box from a list of points\n\n```elixir\nberlin = [52.5075419, 13.4251364]\nrome = [41.9102415, 12.3959161]\nminsk = [53.8838884, 27.5949741]\nGeocalc.bounding_box_for_points([berlin, rome, minsk])\n# =\u003e [[41.9102415, 12.3959161], [53.8838884, 27.5949741]]\n```\n\n### Get geographical center point\n\n```elixir\nberlin = [52.5075419, 13.4251364]\nlondon = [51.5286416, -0.1015987]\nrome = [41.9102415, 12.3959161]\nGeocalc.geographic_center([berlin, london, rome])\n# =\u003e [48.810406537400254, 8.785092188535195]\n```\n\n### Get maximum latitude reached when travelling on a great circle on given bearing from the point\n\n```elixir\nberlin = [52.5075419, 13.4251364]\nparis = [48.8588589, 2.3475569]\nbearing = Geocalc.bearing(berlin, paris)\nGeocalc.max_latitude(berlin, bearing)\n# =\u003e 55.953467429882835\n```\n\n### Get distance from the point to great circle defined by start-point and end-point\n\n```elixir\nberlin = [52.5075419, 13.4251364]\nlondon = [51.5286416, -0.1015987]\nparis = [48.8588589, 2.3475569]\nGeocalc.cross_track_distance_to(berlin, london, paris)\n# =\u003e -877680.2992295175\n```\n\n### Calculate how far the point is along a path from from start-point, heading towards end-point\n\n```elixir\nberlin = [52.5075419, 13.4251364]\nlondon = [51.5286416, -0.1015987]\nparis = [48.8588589, 2.3475569]\nGeocalc.along_track_distance_to(berlin, london, paris)\n# =\u003e 310412.6031976226\n```\n\n### Get the pair of meridians at which a great circle defined by two points crosses the given latitude\n\n```elixir\nberlin = [52.5075419, 13.4251364]\nparis = [48.8588589, 2.3475569]\nGeocalc.crossing_parallels(berlin, paris, 12.3456)\n# =\u003e {:ok, 123.179463369946, -39.81144878508576}\n```\n\n### Convert degrees to radians\n\n```elixir\nGeocalc.degrees_to_radians(245)\n# =\u003e -2.007128639793479\n```\n\n### Convert radians to degrees\n\n```elixir\nGeocalc.radians_to_degrees(1.234)\n# =\u003e 70.70299191914359\n```\n\n## Geocalc.Shape\n\nContains geometrical shapes designed for geofencing calculations, ie: determine if one point is inside or outside a geographical area.\nThree area shapes are defined:\n* Circle\n* Rectangle\n* Ellipse\n\n### Check if a point is inside an area\n```elixir\narea = %Geocalc.Shape.Circle{latitude: 48.856614, longitude: 2.3522219, radius: 1000}\npoint = %{lat: 48.856612, lng: 2.3522217}\nGeocalc.in_area?(area, point)\n# =\u003e true\n```\n\n### Check if a point is outside an area\n```elixir\narea = %Geocalc.Shape.Circle{latitude: 48.856614, longitude: 2.3522219, radius: 10}\npoint = %{lat: 48.856418, lng: 2.365871}\nGeocalc.outside_area?(area, point)\n# =\u003e true\n```\n\n### Check if a point is at the border of an area\n```elixir\narea = %Geocalc.Shape.Circle{latitude: 48.856614, longitude: 2.3522219, radius: 1000}\npoint = %{lat: 48.856418, lng: 2.365871}\nGeocalc.at_area_border?(area, point)\n# =\u003e true\n```\n\n### Check if a point at the center point of an area\n```elixir\narea = %Geocalc.Shape.Circle{latitude: 48.856614, longitude: 2.3522219, radius: 100}\npoint = %{lat: 48.856614, lng: 2.3522219}\nGeocalc.at_center_point?(area, point)\n# =\u003e true\n```\n\n## Geocalc.Point protocol\n\nEverything which implements `Geocalc.Point` protocol can be passed as a point\nargument for any function in this library.\nWe already have implementations for `List`, `Tuple` and `Map`.\nYou can define your own implementations if you need, everything we need to know\nto do calculations are `latitude` and `longitude`.\n\n## Geocalc.DMS\n\n`Geocalc.DMS` is a struct which contains degrees, minutes and seconds, which also can be used in `Geocalc.Point`.\n\n### Additionally now there is an options to convert `Geocalc.DMS` to decimal degrees.\n\n```elixir\ndms = %Geocalc.DMS{hours: 13, minutes: 31, seconds: 59.998, direction: \"N\"}\nGeocalc.DMS.to_degrees(dms)\n# =\u003e 13.533332777777778\n```\n\n## Benchmark\n\nRun this command to generate the benchmark result:\n\n```bash\n$ MIX_ENV=bench mix bench\n\nSettings:\n  duration:      1.0 s\n\n## GeocalcBench\n[03:00:36] 1/10: bearing\n[03:00:37] 2/10: bounding box\n[03:00:39] 3/10: bounding box for points\n[03:00:53] 3/10: degrees to radians\n[03:01:03] 5/10: destination point\n[03:01:06] 6/10: distance between\n[03:01:08] 7/10: intersection point\n[03:01:11] 8/10: radians to degrees\n[03:01:13] 9/10: within?/2\n[03:01:15] 10/10: within?/3\n\nFinished in 31.32 seconds\n\n## GeocalcBench\nbenchmark name           iterations   average time\ndegrees to radians        100000000   0.09 µs/op\nradians to degrees         10000000   0.17 µs/op\nbounding box                1000000   1.51 µs/op\nbearing                     1000000   1.65 µs/op\ndestination point           1000000   1.89 µs/op\nwithin?/3                   1000000   2.10 µs/op\ndistance between            1000000   2.33 µs/op\nintersection point           500000   4.96 µs/op\nbounding box for points      500000   7.26 µs/op\nwithin?/2                    100000   12.17 µs/op\n```\n\n## Copyright and License\n\nCopyright (c) 2015 Yura Tolstik\n\nReleased under the MIT License, which can be found in the repository in [LICENSE.md](./LICENSE.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyltsrc%2Fgeocalc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyltsrc%2Fgeocalc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyltsrc%2Fgeocalc/lists"}