{"id":13850605,"url":"https://github.com/zverok/geo_coord","last_synced_at":"2025-04-06T06:13:08.565Z","repository":{"id":54494991,"uuid":"58394435","full_name":"zverok/geo_coord","owner":"zverok","description":"Simple yet useful Geo Coordinates class for Ruby","archived":false,"fork":false,"pushed_at":"2021-02-15T16:39:36.000Z","size":61,"stargazers_count":124,"open_issues_count":2,"forks_count":10,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-30T05:08:03.772Z","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/zverok.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-05-09T17:16:32.000Z","updated_at":"2024-11-01T22:10:39.000Z","dependencies_parsed_at":"2022-08-13T17:40:54.912Z","dependency_job_id":null,"html_url":"https://github.com/zverok/geo_coord","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zverok%2Fgeo_coord","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zverok%2Fgeo_coord/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zverok%2Fgeo_coord/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zverok%2Fgeo_coord/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zverok","download_url":"https://codeload.github.com/zverok/geo_coord/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247441059,"owners_count":20939239,"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-08-04T20:01:20.162Z","updated_at":"2025-04-06T06:13:08.536Z","avatar_url":"https://github.com/zverok.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# Geo::Coord—simple geo coordinates class for Ruby\n\n[![Gem Version](https://badge.fury.io/rb/geo_coord.svg)](http://badge.fury.io/rb/geo_coord)\n![Build Status](https://github.com/zverok/geo_coord/workflows/CI/badge.svg?branch=master)\n[![Coverage Status](https://coveralls.io/repos/zverok/geo_coord/badge.svg?branch=master)](https://coveralls.io/r/zverok/geo_coord?branch=master)\n\n`Geo::Coord` is a basic class representing `[latitude, longitude]` pair\nand incapsulating related concepts and calculations.\n\n## Features\n\n* Simple storage for geographical latitude \u0026 longitude pair;\n* Easily converted from/to many different representations (arrays, hashes,\n  degrees/minutes/seconds, radians, strings with different formatting);\n* Geodesy math (distances, directions, endpoints) via precise Vincenty\n  formula.\n\n## Reasons\n\nGeo coordinates are, in fact, one of basic types in XXI century programming.\n\nThis gem is a (desperate) attempt to provide such a \"basic\" type ready\nto be dropped into any of Ruby code, to unify all different `LatLng` or\n`Point` or `Location` classes in existing geography and geo-aware gems\nfor easy data exchange and natural usage.\n\nAs an independent gem, this attempt is doomed by design, but why not\nto try?..\n\nInitially, I've done this work as a proposal for inclusion in Ruby's\nstandard library, but it was not met very well.\nSo, now I'm releasing it as a gem to be available at least for my own\nother projects.\n\nYou can read my initial proposal [here](https://github.com/zverok/geo_coord/blob/master/StdlibProposal.md)\nand discussion in Ruby tracker [there](https://bugs.ruby-lang.org/issues/12361).\n\n~~I still have a small hope it would be part of stdlib once, that's why I\npreserve the style of specs (outdated rspec, but compatible with mspec used\nfor standard library) and docs (yard in RDoc-compatibility mode).~~\n\n## Installation\n\nAs usual: `gem install geo_coord` or add\n`gem \"geo_coord\", require: \"geo/coord\"` to your Gemfile.\n\n## Usage\n\n### Creation\n\n```ruby\nrequire 'geo/coord'\n\n# From lat/lng pair:\ng = Geo::Coord.new(50.004444, 36.231389)\n# =\u003e #\u003cGeo::Coord 50°0'16\"N 36°13'53\"E\u003e\n\n# Or using keyword arguments form:\ng = Geo::Coord.new(lat: 50.004444, lng: 36.231389)\n# =\u003e #\u003cGeo::Coord 50°0'16\"N 36°13'53\"E\u003e\n\n# Keyword arguments also allow creation of Coord from components:\ng = Geo::Coord.new(latd: 50, latm: 0, lats: 16, lath: 'N', lngd: 36, lngm: 13, lngs: 53, lngh: 'E')\n# =\u003e #\u003cGeo::Coord 50°0'16\"N 36°13'53\"E\u003e\n```\n\nFor parsing API responses you'd like to use `from_h`,\nwhich accepts String and Symbol keys, any letter case,\nand knows synonyms (lng/lon/longitude):\n\n```ruby\ng = Geo::Coord.from_h('LAT' =\u003e 50.004444, 'LON' =\u003e 36.231389)\n# =\u003e #\u003cGeo::Coord 50°0'16\"N 36°13'53\"E\u003e\n```\n\nFor math, you'd probably like to be able to initialize\nCoord with radians rather than degrees:\n\n```ruby\ng = Geo::Coord.from_rad(0.8727421884291233, 0.6323570306208558)\n# =\u003e #\u003cGeo::Coord 50°0'16\"N 36°13'53\"E\u003e\n```\n\nThere's also family of string parsing methods, with different\napplicability:\n\n```ruby\n# Tries to parse (lat, lng) pair:\ng = Geo::Coord.parse_ll('50.004444, 36.231389')\n# =\u003e #\u003cGeo::Coord 50°0'16\"N 36°13'53\"E\u003e\n\n# Tries to parse degrees/minutes/seconds:\ng = Geo::Coord.parse_dms('50° 0′ 16″ N, 36° 13′ 53″ E')\n# =\u003e #\u003cGeo::Coord 50°0'16\"N 36°13'53\"E\u003e\n\n# Tries to do best guess:\ng = Geo::Coord.parse('50.004444, 36.231389')\n# =\u003e #\u003cGeo::Coord 50°0'16\"N 36°13'53\"E\u003e\ng = Geo::Coord.parse('50° 0′ 16″ N, 36° 13′ 53″ E')\n# =\u003e #\u003cGeo::Coord 50°0'16\"N 36°13'53\"E\u003e\n\n# Allows user to provide pattern:\ng = Geo::Coord.strpcoord('50.004444, 36.231389', '%lat, %lng')\n# =\u003e #\u003cGeo::Coord 50°0'16\"N 36°13'53\"E\u003e\n```\n\n[Pattern language description](http://www.rubydoc.info/gems/geo_coord/Geo/Coord#strpcoord-class_method)\n\n### Examining the object\n\nHaving Coord object, you can get its properties:\n\n```ruby\ng = Geo::Coord.new(50.004444, 36.231389)\ng.lat # =\u003e 50.004444\ng.latd # =\u003e 50 -- latitude degrees\ng.lath # =\u003e N -- latitude hemisphere\ng.lngh # =\u003e E -- longitude hemishpere\ng.phi  # =\u003e 0.8727421884291233 -- longitude in radians\ng.latdms # =\u003e [50, 0, 15.998400000011316, \"N\"]\n# ...and so on\n```\n\n### Formatting and converting\n\n```ruby\ng.to_s              # =\u003e \"50°0'16\\\"N 36°13'53\\\"E\"\ng.to_s(dms: false)  # =\u003e \"50.004444,36.231389\"\ng.strfcoord('%latd°%latm′%lats″%lath %lngd°%lngm′%lngs″%lngh')\n# =\u003e \"50°0′16″N 36°13′53″E\"\n\ng.to_h(lat: 'LAT', lng: 'LON') # =\u003e {'LAT'=\u003e50.004444, 'LON'=\u003e36.231389}\n```\n\n### Geodesy math\n\n```ruby\nkharkiv = Geo::Coord.new(50.004444, 36.231389)\nkyiv = Geo::Coord.new(50.45, 30.523333)\n\nkharkiv.distance(kyiv) # =\u003e 410211.22377421556\nkharkiv.azimuth(kyiv) # =\u003e 279.12614358262067\nkharkiv.endpoint(410_211, 280) # =\u003e #\u003cGeo::Coord 50°30'22\"N 30°31'53\"E\u003e\n```\n\n[Full API Docs](http://www.rubydoc.info/gems/geo_coord)\n\n## Design decisions\n\nWhile designing `Geo` library, my reference point was standard `Time`\nclass (and, to lesser extent, `Date`/`DateTime`). It has these\nresponsibilities:\n\n* stores data in simple internal form;\n* helps to parse and format data to and from strings;\n* provides easy access to logical components of data;\n* allows most simple and unambiguous calculations.\n\n**Namespace name**: The gem takes pretty short and generic top-level\nnamespace name `Geo`, but creates only one class inside it: `Geo::Coord`.\n\n**Main type name**: as far as I can see, there's no good singular name\nfor `(lat, lng)` pair concept. In different libraries, there can be seen\nnames like `LatLng`, or `Location`, or `Point`; and in natural language\njust \"coordinates\" used frequently. I propose the name `Coord`, which\nis pretty short, easy to remember, demonstrates intentions (and looks\nlike singular, so you can have \"one coord object\" and \"array of coords\",\nwhich is not 100% linguistically correct, yet convenient). Alternative\n`Point` name seems to be too ambiguous, being used in many contexts.\n\n`Geo::Coord` object is **immutable**, there's no semantical sense in\n`location.latitude = ...` or something like this.\n\n**Units**: `Geo` calculations (just like `Time` calculations) provide\nno units options, just returning numbers measured in \"default\" units:\nmetres for distances (as they are SI unit) and degrees for azimuth.\nLatitude and longitude are stored in degrees, but radians values accessors\nare provided (being widely used in geodesy math).\n\n**Internal storage**: Since ver 0.1.0, latitude and longitude stored\ninternally as an instances of `BigDecimal`. While having some memory\nand performance downsides, this datatype provides _correctness_ of\nconversions between floating point \u0026 deg-min-sec representations:\n\n```ruby\n# 33.3 should be 33°18'00\"\n# Float:\n33.3 * 60 % 60 # =\u003e 17.999999999999773 minutes\n# BigDecimal\nBigDecimal(33.3, 10) * 60 % 60 # =\u003e 0.18e2\n```\n\nAll coordinates and calculations are thought to be in\n[WGS 84](https://en.wikipedia.org/wiki/World_Geodetic_System#A_new_World_Geodetic_System:_WGS_84)\ncoordinates reference system, being current standard for maps and GPS.\n\nThere's introduced **a concept of globe** used internally for calculations.\nOnly generic (sphere) and Earth globes are implemented, but for 2010th I\nfeel like the current design of basic types should take in consideration\npossibility of writing Ruby scripts for Mars maps analysis. Only one\ngeodesy formula is implemented (Vincenty, generally considered one of\nthe most precise), as for standard library class it considered\nunnecessary to provide a user with geodesy formulae options.\n\nNo **map projection** math was added into the current gem, but it\nmay be a good direction for further work. No **elevation** data considered\neither.\n\n## Author\n\n[Victor Shepelev](https://zverok.github.io)\n\n## License\n\n[MIT](https://github.com/zverok/geo_coord/blob/master/LICENSE.txt).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzverok%2Fgeo_coord","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzverok%2Fgeo_coord","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzverok%2Fgeo_coord/lists"}