geodetic 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +54 -0
- data/README.md +118 -22
- data/docs/assets/images/geodetic.jpg +0 -0
- data/docs/coordinate-systems/bng.md +5 -5
- data/docs/coordinate-systems/ecef.md +23 -23
- data/docs/coordinate-systems/enu.md +3 -3
- data/docs/coordinate-systems/gars.md +246 -0
- data/docs/coordinate-systems/georef.md +221 -0
- data/docs/coordinate-systems/gh.md +282 -0
- data/docs/coordinate-systems/gh36.md +6 -6
- data/docs/coordinate-systems/ham.md +207 -0
- data/docs/coordinate-systems/index.md +39 -29
- data/docs/coordinate-systems/lla.md +26 -26
- data/docs/coordinate-systems/mgrs.md +3 -3
- data/docs/coordinate-systems/ned.md +3 -3
- data/docs/coordinate-systems/olc.md +221 -0
- data/docs/coordinate-systems/state-plane.md +2 -2
- data/docs/coordinate-systems/ups.md +4 -4
- data/docs/coordinate-systems/usng.md +2 -2
- data/docs/coordinate-systems/utm.md +23 -23
- data/docs/coordinate-systems/web-mercator.md +7 -7
- data/docs/getting-started/installation.md +18 -14
- data/docs/getting-started/quick-start.md +11 -11
- data/docs/index.md +44 -15
- data/docs/reference/areas.md +15 -15
- data/docs/reference/conversions.md +38 -32
- data/docs/reference/datums.md +10 -17
- data/docs/reference/geoid-height.md +5 -5
- data/docs/reference/serialization.md +55 -47
- data/examples/01_basic_conversions.rb +10 -10
- data/examples/02_all_coordinate_systems.rb +24 -24
- data/lib/geodetic/areas/circle.rb +1 -1
- data/lib/geodetic/areas/polygon.rb +2 -2
- data/lib/geodetic/areas/rectangle.rb +6 -6
- data/lib/geodetic/{coordinates → coordinate}/bng.rb +3 -10
- data/lib/geodetic/{coordinates → coordinate}/ecef.rb +3 -9
- data/lib/geodetic/{coordinates → coordinate}/enu.rb +48 -1
- data/lib/geodetic/coordinate/gars.rb +233 -0
- data/lib/geodetic/coordinate/georef.rb +204 -0
- data/lib/geodetic/coordinate/gh.rb +161 -0
- data/lib/geodetic/{coordinates → coordinate}/gh36.rb +28 -163
- data/lib/geodetic/coordinate/ham.rb +226 -0
- data/lib/geodetic/{coordinates → coordinate}/lla.rb +58 -3
- data/lib/geodetic/{coordinates → coordinate}/mgrs.rb +3 -9
- data/lib/geodetic/{coordinates → coordinate}/ned.rb +48 -1
- data/lib/geodetic/coordinate/olc.rb +273 -0
- data/lib/geodetic/coordinate/spatial_hash.rb +342 -0
- data/lib/geodetic/{coordinates → coordinate}/state_plane.rb +48 -1
- data/lib/geodetic/{coordinates → coordinate}/ups.rb +3 -10
- data/lib/geodetic/{coordinates → coordinate}/usng.rb +3 -9
- data/lib/geodetic/{coordinates → coordinate}/utm.rb +3 -9
- data/lib/geodetic/{coordinates → coordinate}/web_mercator.rb +3 -9
- data/lib/geodetic/{coordinates.rb → coordinate.rb} +61 -39
- data/lib/geodetic/version.rb +1 -1
- data/lib/geodetic.rb +1 -1
- data/spatial_hash_idea.md +241 -0
- metadata +32 -18
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 782ba82d99727dfa9a075fcdfb9dea89f631ebc78e0e105293745c64f77f9dae
|
|
4
|
+
data.tar.gz: 59e9c844470d77026a9929c8b9ffd01a5d065fd491d8efb67106b0903267c681
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 38543deb9e8d62aa20b4a90c9602b0e97806d7d2f55dd9d308a138b9aea2b033e6f51656a9d247ce750d5abcd5298f170825a3f0e4f013a63198bc467e1f3d8c
|
|
7
|
+
data.tar.gz: fcb62fac876d350bd784d08bb17d45b7c14218a31ff6cfcce4be7e384e3f9a6a2c711ae3731b4a4241e5b34c062a8ddcdc2fb8ce6786ac114ff35d872ad8a7f3
|
data/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,60 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
|
|
14
|
+
## [0.2.0] - 2026-03-08
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **2 new coordinate systems** bringing the total from 15 to 17:
|
|
19
|
+
- `Geodetic::Coordinate::GEOREF` — World Geographic Reference System (aviation/military geocode with variable precision from 15-degree tiles to 0.001-minute resolution)
|
|
20
|
+
- `Geodetic::Coordinate::GARS` — Global Area Reference System (NGA standard with 30-minute cells, 15-minute quadrants, and 5-minute keypads)
|
|
21
|
+
- Full cross-system conversions for GEOREF and GARS — all 17 coordinate systems convert to/from every other system (289 conversion paths)
|
|
22
|
+
- Spatial hash features for GEOREF and GARS: `neighbors`, `to_area`, `precision_in_meters`, `to_slug`, configurable precision
|
|
23
|
+
- Documentation pages: `docs/coordinate-systems/georef.md` and `docs/coordinate-systems/gars.md`
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- **Namespace renamed**: `Geodetic::Coordinates` is now `Geodetic::Coordinate` (singular)
|
|
28
|
+
- **SpatialHash base class** (`lib/geodetic/coordinate/spatial_hash.rb`) — GH36, GH, HAM, OLC, GEOREF, and GARS now inherit from a shared base class that provides common behavior (neighbors, to_area, precision_in_meters, serialization, encoding/decoding contract)
|
|
29
|
+
- **Auto-generated hash conversions** — `SpatialHash.generate_hash_conversions_for` replaces 232 lines of hand-written boilerplate `to_gh`/`from_gh`/`to_ham`/`from_ham`/etc. methods across 7 coordinate classes
|
|
30
|
+
- **Self-registration** — each coordinate class calls `Coordinate.register_class(self)` at load time; `ALL_COORD_CLASSES` is populated from the registry instead of a manual list
|
|
31
|
+
|
|
32
|
+
## [0.1.0] - 2026-03-08
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
|
|
36
|
+
- **4 new coordinate systems** bringing the total from 11 to 15:
|
|
37
|
+
- `Geodetic::Coordinate::GH36` — Geohash-36 (radix-36 spatial hash, URL-friendly)
|
|
38
|
+
- `Geodetic::Coordinate::GH` — Geohash base-32 (standard geohash, supported by Elasticsearch, Redis, PostGIS)
|
|
39
|
+
- `Geodetic::Coordinate::HAM` — Maidenhead Locator System (amateur radio grid squares)
|
|
40
|
+
- `Geodetic::Coordinate::OLC` — Open Location Code / Plus Codes (Google's location encoding)
|
|
41
|
+
- **Full cross-system conversions** — all 15 coordinate systems convert to/from every other system (225 conversion paths)
|
|
42
|
+
- **Spatial hash features** for GH36, GH, HAM, and OLC:
|
|
43
|
+
- `neighbors` — returns all 8 adjacent grid cells
|
|
44
|
+
- `to_area` — returns the cell as a `Geodetic::Areas::Rectangle`
|
|
45
|
+
- `precision_in_meters` — cell size in meters as `{ lat:, lng: }`
|
|
46
|
+
- `to_slug` — URL-friendly string representation
|
|
47
|
+
- Configurable precision on construction
|
|
48
|
+
- **Geographic areas** — `Geodetic::Areas::Circle`, `Geodetic::Areas::Polygon`, and `Geodetic::Areas::Rectangle` for point-in-area testing
|
|
49
|
+
- **Bearing calculations** — universal `bearing_to` and `elevation_to` methods on all coordinate classes via `BearingMethods` mixin
|
|
50
|
+
- **`Geodetic::Bearing` class** — immutable value type with compass directions, reciprocal, radians, arithmetic, and `Comparable`
|
|
51
|
+
- **Validated setters** with type coercion and range validation on all mutable coordinate classes
|
|
52
|
+
- **`to_s(precision)`** on all coordinate classes, `Distance`, and `Bearing` with class-specific defaults
|
|
53
|
+
- **ENU and NED local methods** — `local_bearing_to` and `local_elevation_angle_to` for tangent-plane operations; NED adds `horizontal_distance_to`
|
|
54
|
+
- **GitHub Pages documentation** site with MkDocs
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
|
|
58
|
+
- Coordinate classes use `attr_reader` with validated setter methods instead of `attr_accessor`
|
|
59
|
+
- ENU/NED bearing methods renamed: `bearing_to` → `local_bearing_to`, `elevation_angle_to` → `local_elevation_angle_to` (universal `bearing_to`/`elevation_to` now come from the mixin)
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
|
|
63
|
+
- ENU/NED argument mismatch in 8 coordinate classes — `to_enu`/`to_ned` passed extra `datum` arg that `LLA#to_enu`/`LLA#to_ned` does not accept
|
|
64
|
+
- StatePlane `lambert_conformal_conic_to_lla` double `DEG_PER_RAD` conversion producing incorrect results
|
|
65
|
+
- OLC floating-point encoding error — pre-computed `PAIR_RESOLUTIONS` with epsilon correction prevents truncation (e.g., Google HQ encoding "849VCWC8+R9")
|
|
66
|
+
|
|
13
67
|
## [0.0.1] - 2026-03-07
|
|
14
68
|
|
|
15
69
|
Initial update from an old archived project.
|
data/README.md
CHANGED
|
@@ -1,23 +1,33 @@
|
|
|
1
1
|
# Geodetic
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
3
|
+
> [!INFO]
|
|
4
|
+
> See the [CHANGELOG](CHANGELOG.md) for the latest changes. The [examples directory has runnable demo apps](examples/) that show-off the various capabilities of the Geodetic library.
|
|
5
|
+
|
|
6
|
+
<br>
|
|
7
|
+
<table>
|
|
8
|
+
<tr>
|
|
9
|
+
<td width="50%" align="center" valign="top">
|
|
10
|
+
<img src="docs/assets/images/geodetic.jpg" alt="Geodetic"><br>
|
|
11
|
+
<em>"Convert coordinates. Map the world."</em>
|
|
12
|
+
</td>
|
|
13
|
+
<td width="50%" valign="top">
|
|
14
|
+
<strong>Key Features</strong><br>
|
|
15
|
+
|
|
16
|
+
- <strong>17 Coordinate Systems</strong> - LLA, ECEF, UTM, ENU, NED, MGRS, USNG, Web Mercator, UPS, State Plane, BNG, GH36, GH, HAM, OLC, GEOREF, GARS<br>
|
|
17
|
+
- <strong>Full Bidirectional Conversions</strong> - Every system converts to and from every other system<br>
|
|
18
|
+
- <strong>Distance Calculations</strong> - Vincenty great-circle and straight-line with unit tracking<br>
|
|
19
|
+
- <strong>Bearing Calculations</strong> - Forward azimuth, back azimuth, compass directions, elevation angles<br>
|
|
20
|
+
- <strong>Geoid Height Support</strong> - EGM96, EGM2008, GEOID18, GEOID12B models<br>
|
|
21
|
+
- <strong>Geographic Areas</strong> - Circle, Polygon, and Rectangle with point-in-area tests<br>
|
|
22
|
+
- <strong>Validated Setters</strong> - Type coercion and range validation on all coordinate attributes<br>
|
|
23
|
+
- <strong>Serialization</strong> - to_s(precision), to_a, from_string, from_array, DMS format<br>
|
|
24
|
+
- <strong>Multiple Datums</strong> - WGS84, Clarke 1866, GRS 1980, Airy 1830, and more<br>
|
|
25
|
+
- <strong>Immutable Value Types</strong> - Distance and Bearing with arithmetic and comparison
|
|
26
|
+
</td>
|
|
27
|
+
</tr>
|
|
28
|
+
</table>
|
|
29
|
+
|
|
30
|
+
<p>Geodetic enables precise conversion between geodetic coordinate systems in Ruby. All 17 coordinate systems support complete bidirectional conversions with high precision. Review the <a href="https://madbomber.github.io/geodetic/">full documentation website</a> and explore the <a href="examples/">runnable examples</a>.</p>
|
|
21
31
|
|
|
22
32
|
## Installation
|
|
23
33
|
|
|
@@ -53,12 +63,12 @@ ned = Coordinates::NED.new(n: 200.0, e: 100.0, d: -50.0)
|
|
|
53
63
|
|
|
54
64
|
### GCS Shorthand
|
|
55
65
|
|
|
56
|
-
`GCS` is a top-level alias for `Geodetic::
|
|
66
|
+
`GCS` is a top-level alias for `Geodetic::Coordinate`, providing a concise way to create and work with coordinates:
|
|
57
67
|
|
|
58
68
|
```ruby
|
|
59
69
|
require "geodetic"
|
|
60
70
|
|
|
61
|
-
# Use GCS as a shorthand for Geodetic::
|
|
71
|
+
# Use GCS as a shorthand for Geodetic::Coordinate
|
|
62
72
|
seattle = GCS::LLA.new(lat: 47.6205, lng: -122.3493, alt: 184.0)
|
|
63
73
|
ecef = GCS::ECEF.new(x: -2304643.57, y: -3638650.07, z: 4688674.43)
|
|
64
74
|
```
|
|
@@ -129,7 +139,7 @@ bng = Coordinates::BNG.new(easting: 530000, northing: 180000)
|
|
|
129
139
|
bng.easting = 430000 # grid_ref automatically recalculated
|
|
130
140
|
```
|
|
131
141
|
|
|
132
|
-
ECEF, ENU, NED, and WebMercator setters coerce to float with no range constraints. MGRS, USNG, GH36, Distance, and Bearing are immutable.
|
|
142
|
+
ECEF, ENU, NED, and WebMercator setters coerce to float with no range constraints. MGRS, USNG, GH36, GH, HAM, OLC, Distance, and Bearing are immutable.
|
|
133
143
|
|
|
134
144
|
### DMS (Degrees, Minutes, Seconds)
|
|
135
145
|
|
|
@@ -396,6 +406,90 @@ gh36.precision # => 10
|
|
|
396
406
|
gh36.precision_in_meters # => { lat: 0.31, lng: 0.62 }
|
|
397
407
|
```
|
|
398
408
|
|
|
409
|
+
### Geohash (GH)
|
|
410
|
+
|
|
411
|
+
The standard Geohash (base-32) algorithm by Gustavo Niemeyer, widely supported by Elasticsearch, Redis, PostGIS, and geocoding services:
|
|
412
|
+
|
|
413
|
+
```ruby
|
|
414
|
+
# From a geohash string
|
|
415
|
+
gh = Coordinates::GH.new("dr5ru7")
|
|
416
|
+
|
|
417
|
+
# From any coordinate
|
|
418
|
+
gh = Coordinates::GH.new(lla)
|
|
419
|
+
gh = lla.to_gh(precision: 8)
|
|
420
|
+
|
|
421
|
+
# Decode back to LLA
|
|
422
|
+
lla = gh.to_lla
|
|
423
|
+
|
|
424
|
+
# URL slug (the hash itself is URL-safe)
|
|
425
|
+
gh.to_slug # => "dr5ru7"
|
|
426
|
+
|
|
427
|
+
# Neighbor cells
|
|
428
|
+
gh.neighbors # => { N: GH, S: GH, E: GH, W: GH, NE: ..., NW: ..., SE: ..., SW: ... }
|
|
429
|
+
|
|
430
|
+
# Bounding rectangle of the geohash cell
|
|
431
|
+
area = gh.to_area # => Areas::Rectangle
|
|
432
|
+
area.includes?(gh.to_lla) # => true
|
|
433
|
+
|
|
434
|
+
# Precision info
|
|
435
|
+
gh.precision # => 6
|
|
436
|
+
gh.precision_in_meters # => { lat: 610.98, lng: 1221.97 }
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### Maidenhead Locator (HAM)
|
|
440
|
+
|
|
441
|
+
The Maidenhead Locator System used worldwide in amateur radio for grid square identification:
|
|
442
|
+
|
|
443
|
+
```ruby
|
|
444
|
+
# From a Maidenhead locator string
|
|
445
|
+
ham = Coordinates::HAM.new("FN31pr")
|
|
446
|
+
|
|
447
|
+
# From any coordinate
|
|
448
|
+
ham = Coordinates::HAM.new(lla)
|
|
449
|
+
ham = lla.to_ham(precision: 8)
|
|
450
|
+
|
|
451
|
+
# Decode back to LLA
|
|
452
|
+
lla = ham.to_lla
|
|
453
|
+
|
|
454
|
+
# Neighbor cells
|
|
455
|
+
ham.neighbors # => { N: HAM, S: HAM, E: HAM, W: HAM, NE: ..., NW: ..., SE: ..., SW: ... }
|
|
456
|
+
|
|
457
|
+
# Bounding rectangle of the grid square
|
|
458
|
+
area = ham.to_area # => Areas::Rectangle
|
|
459
|
+
area.includes?(ham.to_lla) # => true
|
|
460
|
+
|
|
461
|
+
# Precision info
|
|
462
|
+
ham.precision # => 6
|
|
463
|
+
ham.precision_in_meters # => { lat: 4631.0, lng: 9260.0 }
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
### Open Location Code / Plus Codes (OLC)
|
|
467
|
+
|
|
468
|
+
Google's open system for encoding locations into short, URL-friendly codes:
|
|
469
|
+
|
|
470
|
+
```ruby
|
|
471
|
+
# From a plus code string
|
|
472
|
+
olc = Coordinates::OLC.new("849VCWC8+R9")
|
|
473
|
+
|
|
474
|
+
# From any coordinate
|
|
475
|
+
olc = Coordinates::OLC.new(lla)
|
|
476
|
+
olc = lla.to_olc(precision: 11)
|
|
477
|
+
|
|
478
|
+
# Decode back to LLA
|
|
479
|
+
lla = olc.to_lla
|
|
480
|
+
|
|
481
|
+
# Neighbor cells
|
|
482
|
+
olc.neighbors # => { N: OLC, S: OLC, E: OLC, W: OLC, NE: ..., NW: ..., SE: ..., SW: ... }
|
|
483
|
+
|
|
484
|
+
# Bounding rectangle of the plus code cell
|
|
485
|
+
area = olc.to_area # => Areas::Rectangle
|
|
486
|
+
area.includes?(olc.to_lla) # => true
|
|
487
|
+
|
|
488
|
+
# Precision info
|
|
489
|
+
olc.precision # => 10
|
|
490
|
+
olc.precision_in_meters # => { lat: 13.9, lng: 13.9 }
|
|
491
|
+
```
|
|
492
|
+
|
|
399
493
|
### Geographic Areas
|
|
400
494
|
|
|
401
495
|
```ruby
|
|
@@ -448,7 +542,7 @@ The [`examples/`](examples/) directory contains runnable demo scripts showing pr
|
|
|
448
542
|
| Script | Description |
|
|
449
543
|
|--------|-------------|
|
|
450
544
|
| [`01_basic_conversions.rb`](examples/01_basic_conversions.rb) | LLA, ECEF, UTM, ENU, NED conversions and roundtrips |
|
|
451
|
-
| [`02_all_coordinate_systems.rb`](examples/02_all_coordinate_systems.rb) | All
|
|
545
|
+
| [`02_all_coordinate_systems.rb`](examples/02_all_coordinate_systems.rb) | All 17 coordinate systems, cross-system chains, and areas |
|
|
452
546
|
| [`03_distance_calculations.rb`](examples/03_distance_calculations.rb) | Distance class features, unit conversions, and arithmetic |
|
|
453
547
|
| [`04_bearing_calculations.rb`](examples/04_bearing_calculations.rb) | Bearing class, compass directions, elevation angles, and chain bearings |
|
|
454
548
|
|
|
@@ -460,6 +554,8 @@ ruby -Ilib examples/01_basic_conversions.rb
|
|
|
460
554
|
|
|
461
555
|
## Development
|
|
462
556
|
|
|
557
|
+
For comprehensive guides and API documentation, visit **[https://madbomber.github.io/geodetic](https://madbomber.github.io/geodetic)**
|
|
558
|
+
|
|
463
559
|
```bash
|
|
464
560
|
bin/setup # Install dependencies
|
|
465
561
|
rake test # Run tests
|
|
Binary file
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Geodetic::
|
|
1
|
+
# Geodetic::Coordinate::BNG
|
|
2
2
|
|
|
3
3
|
## British National Grid
|
|
4
4
|
|
|
@@ -9,13 +9,13 @@ The British National Grid (BNG) is the official coordinate system for Great Brit
|
|
|
9
9
|
Create a BNG coordinate from numeric easting/northing values:
|
|
10
10
|
|
|
11
11
|
```ruby
|
|
12
|
-
point = Geodetic::
|
|
12
|
+
point = Geodetic::Coordinate::BNG.new(easting: 530000.0, northing: 180000.0)
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Alternatively, create from an alphanumeric grid reference string:
|
|
16
16
|
|
|
17
17
|
```ruby
|
|
18
|
-
point = Geodetic::
|
|
18
|
+
point = Geodetic::Coordinate::BNG.new(grid_ref: "TQ 300000 800000")
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## Grid References
|
|
@@ -52,8 +52,8 @@ point.valid? # => true if within Great Britain bounds
|
|
|
52
52
|
The universal `distance_to` method computes the Vincenty great-circle distance to any other coordinate type, returning a `Distance` object. The `straight_line_distance_to` method computes the Euclidean distance in ECEF space. The universal `bearing_to` method computes the great-circle forward azimuth, returning a `Bearing` object. All accept single or multiple targets.
|
|
53
53
|
|
|
54
54
|
```ruby
|
|
55
|
-
bng_a = Geodetic::
|
|
56
|
-
bng_b = Geodetic::
|
|
55
|
+
bng_a = Geodetic::Coordinate::BNG.new(easting: 530000.0, northing: 180000.0)
|
|
56
|
+
bng_b = Geodetic::Coordinate::BNG.new(easting: 540000.0, northing: 190000.0)
|
|
57
57
|
bng_a.distance_to(bng_b) # => Distance (great-circle)
|
|
58
58
|
bng_a.straight_line_distance_to(bng_b) # => Distance (Euclidean)
|
|
59
59
|
bng_a.bearing_to(bng_b) # => Bearing (great-circle forward azimuth)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Geodetic::
|
|
1
|
+
# Geodetic::Coordinate::ECEF
|
|
2
2
|
|
|
3
3
|
Earth-Centered, Earth-Fixed -- a Cartesian coordinate system with its origin at the center of mass of the Earth. The X axis points toward the intersection of the Prime Meridian and the Equator, the Y axis points toward 90 degrees East longitude on the Equator, and the Z axis points toward the North Pole. All values are in meters.
|
|
4
4
|
|
|
@@ -7,7 +7,7 @@ ECEF is useful for satellite positioning, radar tracking, and any application re
|
|
|
7
7
|
## Constructor
|
|
8
8
|
|
|
9
9
|
```ruby
|
|
10
|
-
Geodetic::
|
|
10
|
+
Geodetic::Coordinate::ECEF.new(x: 0.0, y: 0.0, z: 0.0)
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
| Parameter | Type | Default | Description |
|
|
@@ -35,9 +35,9 @@ All conversion methods accept an optional `datum` parameter (defaults to `Geodet
|
|
|
35
35
|
Converts to geodetic Latitude, Longitude, Altitude coordinates using an iterative algorithm. The iteration converges when both latitude and altitude changes are below `1e-12`, with a maximum of 100 iterations.
|
|
36
36
|
|
|
37
37
|
```ruby
|
|
38
|
-
ecef = Geodetic::
|
|
38
|
+
ecef = Geodetic::Coordinate::ECEF.new(x: 1130730.0, y: -4828583.0, z: 3991570.0)
|
|
39
39
|
lla = ecef.to_lla
|
|
40
|
-
# => Geodetic::
|
|
40
|
+
# => Geodetic::Coordinate::LLA
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
### ECEF.from_lla(lla, datum = WGS84)
|
|
@@ -45,7 +45,7 @@ lla = ecef.to_lla
|
|
|
45
45
|
Creates an ECEF from an LLA instance. Raises `ArgumentError` if the argument is not an `LLA`.
|
|
46
46
|
|
|
47
47
|
```ruby
|
|
48
|
-
ecef = Geodetic::
|
|
48
|
+
ecef = Geodetic::Coordinate::ECEF.from_lla(lla)
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
### to_utm(datum = WGS84)
|
|
@@ -54,7 +54,7 @@ Converts to Universal Transverse Mercator coordinates. Internally converts to LL
|
|
|
54
54
|
|
|
55
55
|
```ruby
|
|
56
56
|
utm = ecef.to_utm
|
|
57
|
-
# => Geodetic::
|
|
57
|
+
# => Geodetic::Coordinate::UTM
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
### ECEF.from_utm(utm, datum = WGS84)
|
|
@@ -66,10 +66,10 @@ Creates an ECEF from a UTM instance. Raises `ArgumentError` if the argument is n
|
|
|
66
66
|
Converts to East-North-Up local tangent plane coordinates relative to a reference ECEF position. If `reference_lla` is not provided, it is computed from `reference_ecef` via `to_lla`.
|
|
67
67
|
|
|
68
68
|
```ruby
|
|
69
|
-
ref_ecef = Geodetic::
|
|
70
|
-
point_ecef = Geodetic::
|
|
69
|
+
ref_ecef = Geodetic::Coordinate::ECEF.new(x: 1130730.0, y: -4828583.0, z: 3991570.0)
|
|
70
|
+
point_ecef = Geodetic::Coordinate::ECEF.new(x: 1130740.0, y: -4828573.0, z: 3991580.0)
|
|
71
71
|
enu = point_ecef.to_enu(ref_ecef)
|
|
72
|
-
# => Geodetic::
|
|
72
|
+
# => Geodetic::Coordinate::ENU
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
Raises `ArgumentError` if `reference_ecef` is not an `ECEF`.
|
|
@@ -84,7 +84,7 @@ Converts to North-East-Down local tangent plane coordinates. Internally converts
|
|
|
84
84
|
|
|
85
85
|
```ruby
|
|
86
86
|
ned = point_ecef.to_ned(ref_ecef)
|
|
87
|
-
# => Geodetic::
|
|
87
|
+
# => Geodetic::Coordinate::NED
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
### ECEF.from_ned(ned, reference_ecef, reference_lla = nil)
|
|
@@ -98,7 +98,7 @@ Creates an ECEF from a NED instance and a reference ECEF origin. Raises `Argumen
|
|
|
98
98
|
Returns a comma-separated string of `x, y, z`.
|
|
99
99
|
|
|
100
100
|
```ruby
|
|
101
|
-
ecef = Geodetic::
|
|
101
|
+
ecef = Geodetic::Coordinate::ECEF.new(x: 1130730.0, y: -4828583.0, z: 3991570.0)
|
|
102
102
|
ecef.to_s
|
|
103
103
|
# => "1130730.0, -4828583.0, 3991570.0"
|
|
104
104
|
```
|
|
@@ -117,7 +117,7 @@ ecef.to_a
|
|
|
117
117
|
Parses a comma-separated string into an ECEF.
|
|
118
118
|
|
|
119
119
|
```ruby
|
|
120
|
-
ecef = Geodetic::
|
|
120
|
+
ecef = Geodetic::Coordinate::ECEF.from_string("1130730.0, -4828583.0, 3991570.0")
|
|
121
121
|
```
|
|
122
122
|
|
|
123
123
|
### ECEF.from_array(array)
|
|
@@ -125,7 +125,7 @@ ecef = Geodetic::Coordinates::ECEF.from_string("1130730.0, -4828583.0, 3991570.0
|
|
|
125
125
|
Creates an ECEF from a three-element array `[x, y, z]`.
|
|
126
126
|
|
|
127
127
|
```ruby
|
|
128
|
-
ecef = Geodetic::
|
|
128
|
+
ecef = Geodetic::Coordinate::ECEF.from_array([1130730.0, -4828583.0, 3991570.0])
|
|
129
129
|
```
|
|
130
130
|
|
|
131
131
|
## Additional Methods
|
|
@@ -135,8 +135,8 @@ ecef = Geodetic::Coordinates::ECEF.from_array([1130730.0, -4828583.0, 3991570.0]
|
|
|
135
135
|
Compares two ECEF instances for approximate equality. Returns `true` if the absolute difference for each of `x`, `y`, and `z` is `<= 1e-6` meters. Returns `false` if `other` is not an `ECEF`.
|
|
136
136
|
|
|
137
137
|
```ruby
|
|
138
|
-
a = Geodetic::
|
|
139
|
-
b = Geodetic::
|
|
138
|
+
a = Geodetic::Coordinate::ECEF.new(x: 1130730.0, y: -4828583.0, z: 3991570.0)
|
|
139
|
+
b = Geodetic::Coordinate::ECEF.new(x: 1130730.0, y: -4828583.0, z: 3991570.0)
|
|
140
140
|
a == b
|
|
141
141
|
# => true
|
|
142
142
|
```
|
|
@@ -146,8 +146,8 @@ a == b
|
|
|
146
146
|
Computes the Vincenty great-circle distance to one or more other coordinates. Accepts any coordinate type (coordinates are converted to LLA internally). Returns a `Distance` for a single target or an Array of `Distance` objects for multiple targets (radial distances from the receiver).
|
|
147
147
|
|
|
148
148
|
```ruby
|
|
149
|
-
a = Geodetic::
|
|
150
|
-
b = Geodetic::
|
|
149
|
+
a = Geodetic::Coordinate::ECEF.new(x: 1130730.0, y: -4828583.0, z: 3991570.0)
|
|
150
|
+
b = Geodetic::Coordinate::ECEF.new(x: 1130740.0, y: -4828573.0, z: 3991580.0)
|
|
151
151
|
a.distance_to(b)
|
|
152
152
|
# => Distance (meters, great-circle distance)
|
|
153
153
|
```
|
|
@@ -169,7 +169,7 @@ a.straight_line_distance_to(b)
|
|
|
169
169
|
require 'geodetic'
|
|
170
170
|
|
|
171
171
|
# Create an ECEF coordinate
|
|
172
|
-
ecef = Geodetic::
|
|
172
|
+
ecef = Geodetic::Coordinate::ECEF.new(x: 1130730.0, y: -4828583.0, z: 3991570.0)
|
|
173
173
|
|
|
174
174
|
# Convert to LLA and back
|
|
175
175
|
lla = ecef.to_lla
|
|
@@ -181,8 +181,8 @@ ecef == ecef_roundtrip
|
|
|
181
181
|
### Distance between two points
|
|
182
182
|
|
|
183
183
|
```ruby
|
|
184
|
-
station_a = Geodetic::
|
|
185
|
-
station_b = Geodetic::
|
|
184
|
+
station_a = Geodetic::Coordinate::ECEF.new(x: 1130730.0, y: -4828583.0, z: 3991570.0)
|
|
185
|
+
station_b = Geodetic::Coordinate::ECEF.new(x: 1131000.0, y: -4828300.0, z: 3991800.0)
|
|
186
186
|
|
|
187
187
|
# Great-circle distance (Vincenty)
|
|
188
188
|
distance = station_a.distance_to(station_b)
|
|
@@ -196,8 +196,8 @@ puts "Straight-line distance: #{straight.meters} meters"
|
|
|
196
196
|
### Local tangent plane from ECEF
|
|
197
197
|
|
|
198
198
|
```ruby
|
|
199
|
-
origin = Geodetic::
|
|
200
|
-
target = Geodetic::
|
|
199
|
+
origin = Geodetic::Coordinate::ECEF.new(x: 1130730.0, y: -4828583.0, z: 3991570.0)
|
|
200
|
+
target = Geodetic::Coordinate::ECEF.new(x: 1130740.0, y: -4828573.0, z: 3991580.0)
|
|
201
201
|
|
|
202
202
|
# Provide reference LLA to avoid recomputing it
|
|
203
203
|
ref_lla = origin.to_lla
|
|
@@ -210,6 +210,6 @@ ned = target.to_ned(origin, ref_lla)
|
|
|
210
210
|
|
|
211
211
|
```ruby
|
|
212
212
|
clarke66 = Geodetic::Datum.new(name: 'CLARKE_1866')
|
|
213
|
-
ecef = Geodetic::
|
|
213
|
+
ecef = Geodetic::Coordinate::ECEF.new(x: 1130730.0, y: -4828583.0, z: 3991570.0)
|
|
214
214
|
lla = ecef.to_lla(clarke66)
|
|
215
215
|
```
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Geodetic::
|
|
1
|
+
# Geodetic::Coordinate::ENU - East, North, Up
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
@@ -52,7 +52,7 @@ The one exception is the conversion between ENU and NED, which does not require
|
|
|
52
52
|
ENU is a relative coordinate system. The universal `distance_to`, `straight_line_distance_to`, `bearing_to`, and `elevation_to` methods raise `ArgumentError` because ENU cannot be converted to an absolute system without a reference point. Convert to an absolute system first:
|
|
53
53
|
|
|
54
54
|
```ruby
|
|
55
|
-
ref = Geodetic::
|
|
55
|
+
ref = Geodetic::Coordinate::LLA.new(lat: 47.62, lng: -122.35, alt: 0.0)
|
|
56
56
|
lla = enu.to_lla(ref)
|
|
57
57
|
lla.distance_to(other_lla) # Vincenty great-circle distance
|
|
58
58
|
lla.bearing_to(other_lla) # Great-circle forward azimuth (Bearing object)
|
|
@@ -65,7 +65,7 @@ Bearing is measured in **degrees from north**, clockwise, in the range **0-360**
|
|
|
65
65
|
## Example
|
|
66
66
|
|
|
67
67
|
```ruby
|
|
68
|
-
point = Geodetic::
|
|
68
|
+
point = Geodetic::Coordinate::ENU.new(e: 100.0, n: 200.0, u: 50.0)
|
|
69
69
|
|
|
70
70
|
point.east # => 100.0
|
|
71
71
|
point.north # => 200.0
|