geodetic 0.5.0 → 0.5.1
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 +39 -3
- data/README.md +86 -48
- data/docs/coordinate-systems/index.md +18 -18
- data/docs/index.md +49 -27
- data/docs/reference/arithmetic.md +1 -1
- data/docs/reference/conversions.md +3 -3
- data/docs/reference/feature.md +1 -1
- data/docs/reference/geojson.md +320 -0
- data/examples/09_geojson_export.rb +256 -0
- data/examples/README.md +14 -0
- data/lib/geodetic/areas/regular_polygon.rb +1 -21
- data/lib/geodetic/coordinate/bng.rb +26 -26
- data/lib/geodetic/coordinate/ecef.rb +12 -12
- data/lib/geodetic/coordinate/enu.rb +26 -26
- data/lib/geodetic/coordinate/lla.rb +16 -16
- data/lib/geodetic/coordinate/mgrs.rb +26 -26
- data/lib/geodetic/coordinate/ned.rb +26 -26
- data/lib/geodetic/coordinate/spatial_hash.rb +22 -22
- data/lib/geodetic/coordinate/state_plane.rb +42 -42
- data/lib/geodetic/coordinate/ups.rb +21 -21
- data/lib/geodetic/coordinate/usng.rb +25 -25
- data/lib/geodetic/coordinate/utm.rb +12 -12
- data/lib/geodetic/coordinate/web_mercator.rb +21 -21
- data/lib/geodetic/coordinate.rb +3 -2
- data/lib/geodetic/geojson.rb +214 -0
- data/lib/geodetic/path.rb +12 -15
- data/lib/geodetic/segment.rb +2 -18
- data/lib/geodetic/version.rb +1 -1
- data/lib/geodetic.rb +5 -4
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 82e74456b38ec9c888ee70e68de3e626f0333b9f791c8de7779f5aa544cbbbc7
|
|
4
|
+
data.tar.gz: a76e9a726d4a503f0e2331f321de25a3b7c155e8712a27a18c53ba8e5ab27953
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4bd3b6a3c7664f9f0b20c7bd5c9cee52d80528fe91f97d5a9d2a8a48c9f8314d34027f50ba3b091581650965721e8275b268564ac6fb203fdc896c1f7fa25fa4
|
|
7
|
+
data.tar.gz: f7d83378049a016a388e2f8b4130179e7166704e20b10525a6f5c5a88a12a8812b703fe484dbfd8c40d7af7d8e6ddda7a903052575ea52b48a169c1ebff3fd8d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
> [!CAUTION]
|
|
4
|
-
> This gem is under active development. APIs and features may change without notice.
|
|
5
|
-
|
|
6
3
|
All notable changes to this project will be documented in this file.
|
|
7
4
|
|
|
8
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
@@ -11,6 +8,45 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
11
8
|
## [Unreleased]
|
|
12
9
|
|
|
13
10
|
|
|
11
|
+
## [0.5.1] - 2026-03-10
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **`Geodetic::GeoJSON` class** — build GeoJSON FeatureCollections from any mix of Geodetic objects
|
|
16
|
+
- **Constructor**: `GeoJSON.new`, `GeoJSON.new(obj, ...)`, `GeoJSON.new([array])`
|
|
17
|
+
- **Accumulate**: `<<` accepts single objects or arrays; returns `self` for chaining
|
|
18
|
+
- **Query**: `size`/`length`, `empty?`, `each`, and all `Enumerable` methods
|
|
19
|
+
- **Remove**: `delete(obj)`, `clear`
|
|
20
|
+
- **Export**: `to_h` (Ruby Hash), `to_json`/`to_json(pretty: true)` (JSON string), `save(path, pretty: false)` (file output)
|
|
21
|
+
- Non-Feature objects auto-wrapped as GeoJSON Features with empty properties
|
|
22
|
+
- Feature objects carry `label` → `"name"` and `metadata` → `properties`
|
|
23
|
+
- **`to_geojson` instance method** on all geometry types:
|
|
24
|
+
- All 18 coordinate classes → GeoJSON Point (via LLA; altitude included when non-zero)
|
|
25
|
+
- `Segment` → GeoJSON LineString (2 positions)
|
|
26
|
+
- `Path` → GeoJSON LineString (default) or Polygon (`as: :polygon`, auto-closes ring)
|
|
27
|
+
- `Areas::Polygon` and subclasses → GeoJSON Polygon
|
|
28
|
+
- `Areas::Circle` → GeoJSON Polygon (N-gon approximation, default 32 segments, configurable via `segments:`)
|
|
29
|
+
- `Areas::BoundingBox` → GeoJSON Polygon (4 corners, right-hand rule ring order)
|
|
30
|
+
- `Feature` → GeoJSON Feature with geometry and properties
|
|
31
|
+
- ENU/NED raise `ArgumentError` (relative systems require conversion first)
|
|
32
|
+
- GeoJSON export example (`examples/09_geojson_export.rb`) — 10-section demo covering `to_geojson` on all geometry types, FeatureCollection building, delete/clear, Enumerable, and file export
|
|
33
|
+
- Documentation: `docs/reference/geojson.md` (GeoJSON Export reference)
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- Corrected stale numeric values in documentation:
|
|
38
|
+
- Seattle→Portland distance: 235393.17 → 235385.71 m (README, `docs/reference/conversions.md`)
|
|
39
|
+
- Seattle→Portland bearing: 188.2° → 186.25° (README, `docs/reference/conversions.md`, `docs/reference/arithmetic.md`)
|
|
40
|
+
- Seattle→Portland miles: 146.28 → 146.26 (README)
|
|
41
|
+
- Liberty→Empire bearing: 36.99° → 36.95° (README, `docs/reference/feature.md`)
|
|
42
|
+
- Fixed `docs/index.md` Key Features list to include all 18 coordinate systems (was missing GEOREF, GARS, H3)
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- Updated README with GeoJSON Export section, key features bullet, and example 09 in the examples table
|
|
47
|
+
- Updated `docs/index.md` with GeoJSON Export in key features and reference links
|
|
48
|
+
- Updated `examples/README.md` with example 09 description
|
|
49
|
+
|
|
14
50
|
## [0.5.0] - 2026-03-10
|
|
15
51
|
|
|
16
52
|
### Added
|
data/README.md
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
- <strong>Features</strong> - Named geometry wrapper with metadata and delegated distance/bearing<br>
|
|
25
25
|
- <strong>Vectors</strong> - Geodetic displacement (distance + bearing) with full arithmetic and Vincenty direct<br>
|
|
26
26
|
- <strong>Geodetic Arithmetic</strong> - Compose geometry with operators: P1 + P2 → Segment, + P3 → Path, + Distance → Circle, * Vector → translate<br>
|
|
27
|
+
- <strong>GeoJSON Export</strong> - Build FeatureCollections from any mix of objects and save to file<br>
|
|
27
28
|
- <strong>Validated Setters</strong> - Type coercion and range validation on all coordinate attributes<br>
|
|
28
29
|
- <strong>Serialization</strong> - to_s(precision), to_a, from_string, from_array, DMS format<br>
|
|
29
30
|
- <strong>Multiple Datums</strong> - WGS84, Clarke 1866, GRS 1980, Airy 1830, and more<br>
|
|
@@ -73,11 +74,15 @@ require "geodetic"
|
|
|
73
74
|
|
|
74
75
|
include Geodetic
|
|
75
76
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
# lng:, lon:, and long: are all accepted for longitude
|
|
78
|
+
lla = Coordinate::LLA.new(lat: 47.6205, lng: -122.3493, alt: 184.0)
|
|
79
|
+
lla = Coordinate::LLA.new(lat: 47.6205, lon: -122.3493, alt: 184.0)
|
|
80
|
+
lla = Coordinate::LLA.new(lat: 47.6205, long: -122.3493, alt: 184.0)
|
|
81
|
+
# Readers: lla.lng, lla.lon, lla.long, lla.longitude all return the same value
|
|
82
|
+
ecef = Coordinate::ECEF.new(x: -2304643.57, y: -3638650.07, z: 4688674.43)
|
|
83
|
+
utm = Coordinate::UTM.new(easting: 548894.0, northing: 5272748.0, altitude: 184.0, zone: 10, hemisphere: "N")
|
|
84
|
+
enu = Coordinate::ENU.new(e: 100.0, n: 200.0, u: 50.0)
|
|
85
|
+
ned = Coordinate::NED.new(n: 200.0, e: 100.0, d: -50.0)
|
|
81
86
|
```
|
|
82
87
|
|
|
83
88
|
### GCS Shorthand
|
|
@@ -112,19 +117,19 @@ Geodetic::Coordinate.systems.map { |c| c.name.split('::').last }
|
|
|
112
117
|
Every coordinate system can convert to and from every other system:
|
|
113
118
|
|
|
114
119
|
```ruby
|
|
115
|
-
lla =
|
|
120
|
+
lla = Coordinate::LLA.new(lat: 47.6205, lng: -122.3493, alt: 184.0)
|
|
116
121
|
|
|
117
122
|
# LLA to other systems
|
|
118
123
|
ecef = lla.to_ecef
|
|
119
124
|
utm = lla.to_utm
|
|
120
|
-
wm =
|
|
121
|
-
mgrs =
|
|
125
|
+
wm = Coordinate::WebMercator.from_lla(lla)
|
|
126
|
+
mgrs = Coordinate::MGRS.from_lla(lla)
|
|
122
127
|
|
|
123
128
|
# Convert back
|
|
124
129
|
lla_roundtrip = ecef.to_lla
|
|
125
130
|
|
|
126
131
|
# Local coordinate systems require a reference point
|
|
127
|
-
reference =
|
|
132
|
+
reference = Coordinate::LLA.new(lat: 47.62, lng: -122.35, alt: 0.0)
|
|
128
133
|
enu = lla.to_enu(reference)
|
|
129
134
|
ned = lla.to_ned(reference)
|
|
130
135
|
```
|
|
@@ -134,15 +139,15 @@ ned = lla.to_ned(reference)
|
|
|
134
139
|
All coordinate classes support `to_s`, `to_a`, `from_string`, and `from_array`. The `to_s` method accepts an optional precision parameter controlling the number of decimal places:
|
|
135
140
|
|
|
136
141
|
```ruby
|
|
137
|
-
lla =
|
|
142
|
+
lla = Coordinate::LLA.new(lat: 47.6205, lng: -122.3493, alt: 184.0)
|
|
138
143
|
|
|
139
144
|
lla.to_s # => "47.620500, -122.349300, 184.00"
|
|
140
145
|
lla.to_s(3) # => "47.620, -122.349, 184.00"
|
|
141
146
|
lla.to_s(0) # => "48, -122, 184"
|
|
142
147
|
lla.to_a # => [47.6205, -122.3493, 184.0]
|
|
143
148
|
|
|
144
|
-
|
|
145
|
-
|
|
149
|
+
Coordinate::LLA.from_string("47.6205, -122.3493, 184.0")
|
|
150
|
+
Coordinate::LLA.from_array([47.6205, -122.3493, 184.0])
|
|
146
151
|
```
|
|
147
152
|
|
|
148
153
|
Default precisions by class: LLA=6, Bearing=4, all others=2. Passing `0` returns integers.
|
|
@@ -152,24 +157,24 @@ Default precisions by class: LLA=6, Bearing=4, all others=2. Passing `0` returns
|
|
|
152
157
|
All coordinate classes provide setter methods with type coercion and validation:
|
|
153
158
|
|
|
154
159
|
```ruby
|
|
155
|
-
lla =
|
|
160
|
+
lla = Coordinate::LLA.new(lat: 47.0, lng: -122.0, alt: 100.0)
|
|
156
161
|
lla.lat = 48.0 # validates -90..90
|
|
157
162
|
lla.lng = -121.0 # validates -180..180
|
|
158
163
|
lla.alt = 200.0 # no range constraint
|
|
159
164
|
lla.lat = 91.0 # => ArgumentError
|
|
160
165
|
|
|
161
|
-
utm =
|
|
166
|
+
utm = Coordinate::UTM.new(easting: 500000.0, northing: 5000000.0, zone: 10, hemisphere: 'N')
|
|
162
167
|
utm.zone = 15 # validates 1..60
|
|
163
168
|
utm.hemisphere = 'S' # validates 'N' or 'S'
|
|
164
169
|
utm.easting = -1.0 # => ArgumentError
|
|
165
170
|
|
|
166
171
|
# UPS cross-validates hemisphere/zone combinations
|
|
167
|
-
ups =
|
|
172
|
+
ups = Coordinate::UPS.new(hemisphere: 'N', zone: 'Y')
|
|
168
173
|
ups.zone = 'Z' # valid for hemisphere 'N'
|
|
169
174
|
ups.zone = 'A' # => ArgumentError (rolls back)
|
|
170
175
|
|
|
171
176
|
# BNG auto-updates grid_ref when easting/northing change
|
|
172
|
-
bng =
|
|
177
|
+
bng = Coordinate::BNG.new(easting: 530000, northing: 180000)
|
|
173
178
|
bng.easting = 430000 # grid_ref automatically recalculated
|
|
174
179
|
```
|
|
175
180
|
|
|
@@ -178,10 +183,10 @@ ECEF, ENU, NED, and WebMercator setters coerce to float with no range constraint
|
|
|
178
183
|
### DMS (Degrees, Minutes, Seconds)
|
|
179
184
|
|
|
180
185
|
```ruby
|
|
181
|
-
lla =
|
|
186
|
+
lla = Coordinate::LLA.new(lat: 37.7749, lng: -122.4192, alt: 15.0)
|
|
182
187
|
lla.to_dms # => "37° 46' 29.64\" N, 122° 25' 9.12\" W, 15.00 m"
|
|
183
188
|
|
|
184
|
-
|
|
189
|
+
Coordinate::LLA.from_dms("37° 46' 29.64\" N, 122° 25' 9.12\" W, 15.00 m")
|
|
185
190
|
```
|
|
186
191
|
|
|
187
192
|
### String-Based Coordinate Systems
|
|
@@ -189,12 +194,12 @@ Coordinates::LLA.from_dms("37° 46' 29.64\" N, 122° 25' 9.12\" W, 15.00 m")
|
|
|
189
194
|
MGRS and USNG use string representations:
|
|
190
195
|
|
|
191
196
|
```ruby
|
|
192
|
-
mgrs =
|
|
193
|
-
mgrs =
|
|
197
|
+
mgrs = Coordinate::MGRS.new(mgrs_string: "18SUJ2337006519")
|
|
198
|
+
mgrs = Coordinate::MGRS.from_string("18SUJ2337006519")
|
|
194
199
|
mgrs.to_s # => "18SUJ2337006519"
|
|
195
200
|
|
|
196
|
-
usng =
|
|
197
|
-
usng =
|
|
201
|
+
usng = Coordinate::USNG.new(usng_string: "18T WL 12345 67890")
|
|
202
|
+
usng = Coordinate::USNG.from_string("18T WL 12345 67890")
|
|
198
203
|
usng.to_s # => "18T WL 12345 67890"
|
|
199
204
|
```
|
|
200
205
|
|
|
@@ -210,9 +215,9 @@ portland = Geodetic::Coordinate::LLA.new(lat: 45.5152, lng: -122.6784, alt: 0.0)
|
|
|
210
215
|
sf = Geodetic::Coordinate::LLA.new(lat: 37.7749, lng: -122.4194, alt: 0.0)
|
|
211
216
|
|
|
212
217
|
d = seattle.distance_to(portland) # => Distance (meters)
|
|
213
|
-
d.meters # =>
|
|
218
|
+
d.meters # => 235385.71
|
|
214
219
|
d.to_km.to_f # => 235.39
|
|
215
|
-
d.to_mi.to_f # => 146.
|
|
220
|
+
d.to_mi.to_f # => 146.26
|
|
216
221
|
|
|
217
222
|
seattle.distance_to(portland, sf) # => [Distance, Distance] (radial)
|
|
218
223
|
seattle.distance_to([portland, sf]) # => [Distance, Distance] (radial)
|
|
@@ -254,12 +259,12 @@ seattle = Geodetic::Coordinate::LLA.new(lat: 47.6205, lng: -122.3493, alt: 0.0)
|
|
|
254
259
|
portland = Geodetic::Coordinate::LLA.new(lat: 45.5152, lng: -122.6784, alt: 0.0)
|
|
255
260
|
|
|
256
261
|
b = seattle.bearing_to(portland) # => Bearing
|
|
257
|
-
b.degrees # =>
|
|
258
|
-
b.to_radians # => 3.
|
|
262
|
+
b.degrees # => 186.25
|
|
263
|
+
b.to_radians # => 3.25...
|
|
259
264
|
b.to_compass # => "S"
|
|
260
265
|
b.to_compass(points: 8) # => "S"
|
|
261
266
|
b.reverse # => Bearing (back azimuth)
|
|
262
|
-
b.to_s # => "
|
|
267
|
+
b.to_s # => "186.2539°"
|
|
263
268
|
```
|
|
264
269
|
|
|
265
270
|
**Instance method `elevation_to`** — vertical look angle:
|
|
@@ -405,7 +410,7 @@ geoid.convert_vertical_datum(47.6205, -122.3493, 184.0, "HAE", "NAVD88")
|
|
|
405
410
|
The `GeoidHeightSupport` module is mixed into LLA for convenience:
|
|
406
411
|
|
|
407
412
|
```ruby
|
|
408
|
-
lla =
|
|
413
|
+
lla = Coordinate::LLA.new(lat: 47.6205, lng: -122.3493, alt: 184.0)
|
|
409
414
|
lla.geoid_height # => geoid undulation in meters
|
|
410
415
|
lla.orthometric_height # => height above mean sea level
|
|
411
416
|
```
|
|
@@ -416,10 +421,10 @@ A spatial hashing coordinate that encodes lat/lng into a compact, URL-friendly s
|
|
|
416
421
|
|
|
417
422
|
```ruby
|
|
418
423
|
# From a geohash string
|
|
419
|
-
gh36 =
|
|
424
|
+
gh36 = Coordinate::GH36.new("bdrdC26BqH")
|
|
420
425
|
|
|
421
426
|
# From any coordinate
|
|
422
|
-
gh36 =
|
|
427
|
+
gh36 = Coordinate::GH36.new(lla)
|
|
423
428
|
gh36 = lla.to_gh36(precision: 8)
|
|
424
429
|
|
|
425
430
|
# Decode back to LLA
|
|
@@ -443,10 +448,10 @@ The standard Geohash (base-32) algorithm by Gustavo Niemeyer, widely supported b
|
|
|
443
448
|
|
|
444
449
|
```ruby
|
|
445
450
|
# From a geohash string
|
|
446
|
-
gh =
|
|
451
|
+
gh = Coordinate::GH.new("dr5ru7")
|
|
447
452
|
|
|
448
453
|
# From any coordinate
|
|
449
|
-
gh =
|
|
454
|
+
gh = Coordinate::GH.new(lla)
|
|
450
455
|
gh = lla.to_gh(precision: 8)
|
|
451
456
|
|
|
452
457
|
# Decode back to LLA
|
|
@@ -470,10 +475,10 @@ The Maidenhead Locator System used worldwide in amateur radio for grid square id
|
|
|
470
475
|
|
|
471
476
|
```ruby
|
|
472
477
|
# From a Maidenhead locator string
|
|
473
|
-
ham =
|
|
478
|
+
ham = Coordinate::HAM.new("FN31pr")
|
|
474
479
|
|
|
475
480
|
# From any coordinate
|
|
476
|
-
ham =
|
|
481
|
+
ham = Coordinate::HAM.new(lla)
|
|
477
482
|
ham = lla.to_ham(precision: 8)
|
|
478
483
|
|
|
479
484
|
# Decode back to LLA
|
|
@@ -497,10 +502,10 @@ Google's open system for encoding locations into short, URL-friendly codes:
|
|
|
497
502
|
|
|
498
503
|
```ruby
|
|
499
504
|
# From a plus code string
|
|
500
|
-
olc =
|
|
505
|
+
olc = Coordinate::OLC.new("849VCWC8+R9")
|
|
501
506
|
|
|
502
507
|
# From any coordinate
|
|
503
|
-
olc =
|
|
508
|
+
olc = Coordinate::OLC.new(lla)
|
|
504
509
|
olc = lla.to_olc(precision: 11)
|
|
505
510
|
|
|
506
511
|
# Decode back to LLA
|
|
@@ -522,22 +527,22 @@ olc.precision_in_meters # => { lat: 13.9, lng: 13.9 }
|
|
|
522
527
|
|
|
523
528
|
```ruby
|
|
524
529
|
# Circle area
|
|
525
|
-
center =
|
|
530
|
+
center = Coordinate::LLA.new(lat: 47.6205, lng: -122.3493, alt: 0.0)
|
|
526
531
|
circle = Areas::Circle.new(centroid: center, radius: 1000.0) # 1km radius
|
|
527
532
|
|
|
528
533
|
# Polygon area
|
|
529
534
|
points = [
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
535
|
+
Coordinate::LLA.new(lat: 47.60, lng: -122.35, alt: 0.0),
|
|
536
|
+
Coordinate::LLA.new(lat: 47.63, lng: -122.35, alt: 0.0),
|
|
537
|
+
Coordinate::LLA.new(lat: 47.63, lng: -122.33, alt: 0.0),
|
|
538
|
+
Coordinate::LLA.new(lat: 47.60, lng: -122.33, alt: 0.0),
|
|
534
539
|
]
|
|
535
540
|
polygon = Areas::Polygon.new(boundary: points)
|
|
536
541
|
polygon.centroid # => computed centroid as LLA
|
|
537
542
|
|
|
538
543
|
# BoundingBox area (accepts any coordinate type)
|
|
539
|
-
nw =
|
|
540
|
-
se =
|
|
544
|
+
nw = Coordinate::LLA.new(lat: 41.0, lng: -75.0)
|
|
545
|
+
se = Coordinate::LLA.new(lat: 40.0, lng: -74.0)
|
|
541
546
|
rect = Areas::BoundingBox.new(nw: nw, se: se)
|
|
542
547
|
rect.centroid # => LLA at center
|
|
543
548
|
rect.ne # => computed NE corner
|
|
@@ -628,18 +633,18 @@ route.select { |c| c.lat > 40.72 }
|
|
|
628
633
|
```ruby
|
|
629
634
|
liberty = Feature.new(
|
|
630
635
|
label: "Statue of Liberty",
|
|
631
|
-
geometry:
|
|
636
|
+
geometry: Coordinate::LLA.new(lat: 40.6892, lng: -74.0445, alt: 0),
|
|
632
637
|
metadata: { category: "monument", year: 1886 }
|
|
633
638
|
)
|
|
634
639
|
|
|
635
640
|
empire = Feature.new(
|
|
636
641
|
label: "Empire State Building",
|
|
637
|
-
geometry:
|
|
642
|
+
geometry: Coordinate::LLA.new(lat: 40.7484, lng: -73.9857, alt: 0),
|
|
638
643
|
metadata: { category: "building", floors: 102 }
|
|
639
644
|
)
|
|
640
645
|
|
|
641
646
|
liberty.distance_to(empire).to_km # => "8.24 km"
|
|
642
|
-
liberty.bearing_to(empire).degrees # => 36.
|
|
647
|
+
liberty.bearing_to(empire).degrees # => 36.95
|
|
643
648
|
|
|
644
649
|
# Area geometries use the centroid for distance/bearing
|
|
645
650
|
park = Feature.new(
|
|
@@ -723,14 +728,46 @@ corridor = route.to_corridor(width: 1000) # 1km wide polygon
|
|
|
723
728
|
corridor = route.to_corridor(width: Distance.km(1))
|
|
724
729
|
```
|
|
725
730
|
|
|
731
|
+
### GeoJSON Export
|
|
732
|
+
|
|
733
|
+
`GeoJSON` builds a GeoJSON FeatureCollection from any mix of Geodetic objects and writes it to a file.
|
|
734
|
+
|
|
735
|
+
```ruby
|
|
736
|
+
gj = Geodetic::GeoJSON.new
|
|
737
|
+
gj << seattle
|
|
738
|
+
gj << [portland, sf, la]
|
|
739
|
+
gj << Feature.new(label: "Route", geometry: route, metadata: { mode: "driving" })
|
|
740
|
+
gj << Areas::Circle.new(centroid: seattle, radius: 10_000)
|
|
741
|
+
|
|
742
|
+
gj.size # => 6
|
|
743
|
+
gj.to_h # => {"type" => "FeatureCollection", "features" => [...]}
|
|
744
|
+
gj.to_json # => compact JSON string
|
|
745
|
+
gj.save("map.geojson", pretty: true)
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
Every geometry type has a `to_geojson` method returning a GeoJSON-compatible Hash:
|
|
749
|
+
|
|
750
|
+
```ruby
|
|
751
|
+
seattle.to_geojson # => {"type" => "Point", ...}
|
|
752
|
+
Segment.new(seattle, portland).to_geojson # => {"type" => "LineString", ...}
|
|
753
|
+
route.to_geojson # => {"type" => "LineString", ...}
|
|
754
|
+
route.to_geojson(as: :polygon) # => {"type" => "Polygon", ...}
|
|
755
|
+
polygon.to_geojson # => {"type" => "Polygon", ...}
|
|
756
|
+
circle.to_geojson(segments: 64) # => {"type" => "Polygon", ...} (64-gon)
|
|
757
|
+
bbox.to_geojson # => {"type" => "Polygon", ...}
|
|
758
|
+
feature.to_geojson # => {"type" => "Feature", ...}
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
Features carry their `label` as `"name"` and `metadata` as `properties` in the GeoJSON output. Non-Feature objects added to the collection are auto-wrapped as Features with empty properties.
|
|
762
|
+
|
|
726
763
|
### Web Mercator Tile Coordinates
|
|
727
764
|
|
|
728
765
|
```ruby
|
|
729
|
-
wm =
|
|
766
|
+
wm = Coordinate::WebMercator.from_lla(lla)
|
|
730
767
|
wm.to_tile_coordinates(15) # => [x_tile, y_tile, zoom]
|
|
731
768
|
wm.to_pixel_coordinates(15) # => [x_pixel, y_pixel, zoom]
|
|
732
769
|
|
|
733
|
-
|
|
770
|
+
Coordinate::WebMercator.from_tile_coordinates(5241, 11438, 15)
|
|
734
771
|
```
|
|
735
772
|
|
|
736
773
|
## Available Datums
|
|
@@ -755,6 +792,7 @@ The [`examples/`](examples/) directory contains runnable demo scripts showing pr
|
|
|
755
792
|
| [`06_path_operations.rb`](examples/06_path_operations.rb) | Path class: construction, navigation, mutation, path arithmetic, closest approach, containment, Enumerable, equality, subpaths, split, interpolation, bounding boxes, polygon conversion, intersection, path-to-path/area closest points, and Feature integration |
|
|
756
793
|
| [`07_segments_and_shapes.rb`](examples/07_segments_and_shapes.rb) | Segment and polygon subclasses: Triangle, Rectangle, Pentagon, Hexagon, Octagon with containment, edges, and bounding boxes |
|
|
757
794
|
| [`08_geodetic_arithmetic.rb`](examples/08_geodetic_arithmetic.rb) | Geodetic arithmetic: building geometry with + (Segments, Paths, Circles), Vector class (Vincenty direct, components, arithmetic, dot/cross products), translation with * (Coordinates, Segments, Paths, Circles, Polygons), and corridors |
|
|
795
|
+
| [`09_geojson_export.rb`](examples/09_geojson_export.rb) | GeoJSON export: `to_geojson` on all geometry types, `GeoJSON` class for building FeatureCollections with `<<`, delete/clear, Enumerable, and `save` to file |
|
|
758
796
|
|
|
759
797
|
Run any example with:
|
|
760
798
|
|
|
@@ -6,54 +6,54 @@ The Geodetic gem supports 18 coordinate systems organized into six categories. A
|
|
|
6
6
|
|
|
7
7
|
| System | Class | Description |
|
|
8
8
|
|--------|-------|-------------|
|
|
9
|
-
| **LLA** | `Geodetic::Coordinate::LLA` | Latitude, Longitude, Altitude. The most common geographic coordinate system, expressing positions in decimal degrees with altitude in meters. Negative longitude is the Western hemisphere; negative latitude is the Southern hemisphere. |
|
|
10
|
-
| **ECEF** | `Geodetic::Coordinate::ECEF` | Earth-Centered, Earth-Fixed. A Cartesian coordinate system with the origin at the Earth's center of mass. Positions are expressed as X, Y, Z in meters. Commonly used in satellite navigation and aerospace applications. |
|
|
11
|
-
| **UTM** | `Geodetic::Coordinate::UTM` | Universal Transverse Mercator. Divides the Earth into 60 zones (each 6 degrees of longitude), projecting positions as easting/northing in meters within a zone and hemisphere. Covers latitudes 80S to 84N. |
|
|
9
|
+
| [**LLA**](lla.md) | `Geodetic::Coordinate::LLA` | Latitude, Longitude, Altitude. The most common geographic coordinate system, expressing positions in decimal degrees with altitude in meters. Negative longitude is the Western hemisphere; negative latitude is the Southern hemisphere. |
|
|
10
|
+
| [**ECEF**](ecef.md) | `Geodetic::Coordinate::ECEF` | Earth-Centered, Earth-Fixed. A Cartesian coordinate system with the origin at the Earth's center of mass. Positions are expressed as X, Y, Z in meters. Commonly used in satellite navigation and aerospace applications. |
|
|
11
|
+
| [**UTM**](utm.md) | `Geodetic::Coordinate::UTM` | Universal Transverse Mercator. Divides the Earth into 60 zones (each 6 degrees of longitude), projecting positions as easting/northing in meters within a zone and hemisphere. Covers latitudes 80S to 84N. |
|
|
12
12
|
|
|
13
13
|
## Local Tangent Plane Systems
|
|
14
14
|
|
|
15
15
|
| System | Class | Description |
|
|
16
16
|
|--------|-------|-------------|
|
|
17
|
-
| **ENU** | `Geodetic::Coordinate::ENU` | East, North, Up. A local tangent plane coordinate system centered on a reference point. Axes point East, North, and Up relative to the reference. Distances are in meters. Used in robotics, surveying, and local navigation. |
|
|
18
|
-
| **NED** | `Geodetic::Coordinate::NED` | North, East, Down. A local tangent plane coordinate system centered on a reference point. Axes point North, East, and Down. Used extensively in aerospace and aviation applications. Mathematically related to ENU by axis reordering and sign inversion. |
|
|
17
|
+
| [**ENU**](enu.md) | `Geodetic::Coordinate::ENU` | East, North, Up. A local tangent plane coordinate system centered on a reference point. Axes point East, North, and Up relative to the reference. Distances are in meters. Used in robotics, surveying, and local navigation. |
|
|
18
|
+
| [**NED**](ned.md) | `Geodetic::Coordinate::NED` | North, East, Down. A local tangent plane coordinate system centered on a reference point. Axes point North, East, and Down. Used extensively in aerospace and aviation applications. Mathematically related to ENU by axis reordering and sign inversion. |
|
|
19
19
|
|
|
20
20
|
## Military and Grid Systems
|
|
21
21
|
|
|
22
22
|
| System | Class | Description |
|
|
23
23
|
|--------|-------|-------------|
|
|
24
|
-
| **MGRS** | `Geodetic::Coordinate::MGRS` | Military Grid Reference System. An alphanumeric system based on UTM that identifies positions using grid zone designator, 100km square identifier, and numeric easting/northing. Variable precision from 10km down to 1m. |
|
|
25
|
-
| **USNG** | `Geodetic::Coordinate::USNG` | United States National Grid. Based on MGRS but formatted with spaces for readability. Used primarily within the United States for emergency services and land management. |
|
|
24
|
+
| [**MGRS**](mgrs.md) | `Geodetic::Coordinate::MGRS` | Military Grid Reference System. An alphanumeric system based on UTM that identifies positions using grid zone designator, 100km square identifier, and numeric easting/northing. Variable precision from 10km down to 1m. |
|
|
25
|
+
| [**USNG**](usng.md) | `Geodetic::Coordinate::USNG` | United States National Grid. Based on MGRS but formatted with spaces for readability. Used primarily within the United States for emergency services and land management. |
|
|
26
26
|
|
|
27
27
|
## Web Mapping
|
|
28
28
|
|
|
29
29
|
| System | Class | Description |
|
|
30
30
|
|--------|-------|-------------|
|
|
31
|
-
| **WebMercator** | `Geodetic::Coordinate::WebMercator` | Web Mercator (EPSG:3857). Also known as Pseudo-Mercator or Spherical Mercator. The projection used by Google Maps, OpenStreetMap, and Bing Maps. Positions are X/Y in meters. Latitude is clamped to approximately +/-85.05 degrees. Includes tile and pixel coordinate methods for web mapping applications. |
|
|
31
|
+
| [**WebMercator**](web-mercator.md) | `Geodetic::Coordinate::WebMercator` | Web Mercator (EPSG:3857). Also known as Pseudo-Mercator or Spherical Mercator. The projection used by Google Maps, OpenStreetMap, and Bing Maps. Positions are X/Y in meters. Latitude is clamped to approximately +/-85.05 degrees. Includes tile and pixel coordinate methods for web mapping applications. |
|
|
32
32
|
|
|
33
33
|
## Polar
|
|
34
34
|
|
|
35
35
|
| System | Class | Description |
|
|
36
36
|
|--------|-------|-------------|
|
|
37
|
-
| **UPS** | `Geodetic::Coordinate::UPS` | Universal Polar Stereographic. Covers the polar regions not handled by UTM (north of 84N and south of 80S). Uses a stereographic projection centered on each pole with zones Y/Z (north) and A/B (south). |
|
|
37
|
+
| [**UPS**](ups.md) | `Geodetic::Coordinate::UPS` | Universal Polar Stereographic. Covers the polar regions not handled by UTM (north of 84N and south of 80S). Uses a stereographic projection centered on each pole with zones Y/Z (north) and A/B (south). |
|
|
38
38
|
|
|
39
39
|
## Spatial Hashing
|
|
40
40
|
|
|
41
41
|
| System | Class | Description |
|
|
42
42
|
|--------|-------|-------------|
|
|
43
|
-
| **GH36** | `Geodetic::Coordinate::GH36` | Geohash-36. A hierarchical spatial hashing algorithm that encodes latitude/longitude into a compact, URL-friendly string using a case-sensitive 36-character alphabet (radix-36). Each hash represents a rectangular cell; the coordinate value is the cell midpoint. Supports neighbor lookup, area extraction via `to_area`, and configurable precision (default 10 characters for sub-meter resolution). |
|
|
44
|
-
| **GH** | `Geodetic::Coordinate::GH` | Geohash (base-32). The standard geohash algorithm by Gustavo Niemeyer using a 32-character alphabet (`0-9, b-z` excluding `a, i, l, o`). The de facto standard for spatial hashing, natively supported by Elasticsearch, Redis, PostGIS, and many geocoding services. Supports neighbor lookup, area extraction, and configurable precision (default 12 characters for sub-centimeter resolution). |
|
|
45
|
-
| **HAM** | `Geodetic::Coordinate::HAM` | Maidenhead Locator System. A hierarchical grid system used worldwide in amateur radio that encodes positions using alternating letter/digit pairs (e.g., `FN31pr`). Four levels of precision: Field (18x18), Square (10x10), Subsquare (24x24), Extended (10x10). Supports neighbor lookup, area extraction, and configurable precision (default 6 characters for ~5 km resolution). |
|
|
46
|
-
| **OLC** | `Geodetic::Coordinate::OLC` | Open Location Code (Plus Codes). Google's open system for encoding locations into short codes like `849VCWC8+R9`. Uses a 20-character alphabet with 5 paired levels of base-20 encoding plus optional grid refinement. Includes a `+` separator at position 8. Supports neighbor lookup, area extraction, and configurable precision (default 10 characters for ~14 m resolution). |
|
|
47
|
-
| **GEOREF** | `Geodetic::Coordinate::GEOREF` | World Geographic Reference System. A geocode system used in aviation and military applications that encodes positions using letter tiles (15° grid), letter degree subdivisions, and numeric minute pairs. Uses a 24-letter alphabet (A-Z excluding I and O). Supports variable precision from 15° tiles (2 chars) down to 0.01-minute resolution (12 chars). Default precision is 8 characters (1-minute resolution). |
|
|
48
|
-
| **GARS** | `Geodetic::Coordinate::GARS` | Global Area Reference System. An NGA standard that divides the world into 30-minute cells identified by a 3-digit longitude band (001-720) and 2-letter latitude band. Cells are subdivided into 15-minute quadrants (1-4) and 5-minute keypads (1-9, telephone layout). Variable precision: 5 chars (30'), 6 chars (15'), 7 chars (5'). Default precision is 7 characters. |
|
|
49
|
-
| **H3** | `Geodetic::Coordinate::H3` | H3 Hexagonal Hierarchical Index. Uber's spatial indexing system that divides the globe into hexagonal cells (and 12 pentagons) at 16 resolution levels (0-15). Each cell is a 64-bit integer displayed as a hex string. Unlike the rectangular spatial hashes, `to_area` returns an `Areas::Polygon` with 6 vertices (5 for pentagons) and `neighbors` returns an Array of 6 cells. **Requires `libh3` installed** (`brew install h3` on macOS). |
|
|
43
|
+
| [**GH36**](gh36.md) | `Geodetic::Coordinate::GH36` | Geohash-36. A hierarchical spatial hashing algorithm that encodes latitude/longitude into a compact, URL-friendly string using a case-sensitive 36-character alphabet (radix-36). Each hash represents a rectangular cell; the coordinate value is the cell midpoint. Supports neighbor lookup, area extraction via `to_area`, and configurable precision (default 10 characters for sub-meter resolution). |
|
|
44
|
+
| [**GH**](gh.md) | `Geodetic::Coordinate::GH` | Geohash (base-32). The standard geohash algorithm by Gustavo Niemeyer using a 32-character alphabet (`0-9, b-z` excluding `a, i, l, o`). The de facto standard for spatial hashing, natively supported by Elasticsearch, Redis, PostGIS, and many geocoding services. Supports neighbor lookup, area extraction, and configurable precision (default 12 characters for sub-centimeter resolution). |
|
|
45
|
+
| [**HAM**](ham.md) | `Geodetic::Coordinate::HAM` | Maidenhead Locator System. A hierarchical grid system used worldwide in amateur radio that encodes positions using alternating letter/digit pairs (e.g., `FN31pr`). Four levels of precision: Field (18x18), Square (10x10), Subsquare (24x24), Extended (10x10). Supports neighbor lookup, area extraction, and configurable precision (default 6 characters for ~5 km resolution). |
|
|
46
|
+
| [**OLC**](olc.md) | `Geodetic::Coordinate::OLC` | Open Location Code (Plus Codes). Google's open system for encoding locations into short codes like `849VCWC8+R9`. Uses a 20-character alphabet with 5 paired levels of base-20 encoding plus optional grid refinement. Includes a `+` separator at position 8. Supports neighbor lookup, area extraction, and configurable precision (default 10 characters for ~14 m resolution). |
|
|
47
|
+
| [**GEOREF**](georef.md) | `Geodetic::Coordinate::GEOREF` | World Geographic Reference System. A geocode system used in aviation and military applications that encodes positions using letter tiles (15° grid), letter degree subdivisions, and numeric minute pairs. Uses a 24-letter alphabet (A-Z excluding I and O). Supports variable precision from 15° tiles (2 chars) down to 0.01-minute resolution (12 chars). Default precision is 8 characters (1-minute resolution). |
|
|
48
|
+
| [**GARS**](gars.md) | `Geodetic::Coordinate::GARS` | Global Area Reference System. An NGA standard that divides the world into 30-minute cells identified by a 3-digit longitude band (001-720) and 2-letter latitude band. Cells are subdivided into 15-minute quadrants (1-4) and 5-minute keypads (1-9, telephone layout). Variable precision: 5 chars (30'), 6 chars (15'), 7 chars (5'). Default precision is 7 characters. |
|
|
49
|
+
| [**H3**](h3.md) | `Geodetic::Coordinate::H3` | H3 Hexagonal Hierarchical Index. Uber's spatial indexing system that divides the globe into hexagonal cells (and 12 pentagons) at 16 resolution levels (0-15). Each cell is a 64-bit integer displayed as a hex string. Unlike the rectangular spatial hashes, `to_area` returns an `Areas::Polygon` with 6 vertices (5 for pentagons) and `neighbors` returns an Array of 6 cells. **Requires `libh3` installed** (`brew install h3` on macOS). |
|
|
50
50
|
|
|
51
51
|
## Regional Systems
|
|
52
52
|
|
|
53
53
|
| System | Class | Description |
|
|
54
54
|
|--------|-------|-------------|
|
|
55
|
-
| **StatePlane** | `Geodetic::Coordinate::StatePlane` | State Plane Coordinate System. US state-based coordinate systems using Lambert Conformal Conic or Transverse Mercator projections. Each state has one or more zones with specific parameters. Coordinates are typically in US Survey Feet. |
|
|
56
|
-
| **BNG** | `Geodetic::Coordinate::BNG` | British National Grid. The official coordinate system for Great Britain, based on the OSGB36 datum with the Airy 1830 ellipsoid. Uses a Transverse Mercator projection and an alphanumeric grid reference system (e.g., "TQ 30 80"). |
|
|
55
|
+
| [**StatePlane**](state-plane.md) | `Geodetic::Coordinate::StatePlane` | State Plane Coordinate System. US state-based coordinate systems using Lambert Conformal Conic or Transverse Mercator projections. Each state has one or more zones with specific parameters. Coordinates are typically in US Survey Feet. |
|
|
56
|
+
| [**BNG**](bng.md) | `Geodetic::Coordinate::BNG` | British National Grid. The official coordinate system for Great Britain, based on the OSGB36 datum with the Airy 1830 ellipsoid. Uses a Transverse Mercator projection and an alphanumeric grid reference system (e.g., "TQ 30 80"). |
|
|
57
57
|
|
|
58
58
|
---
|
|
59
59
|
|
data/docs/index.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<td width="50%" valign="top">
|
|
10
10
|
<h2>Key Features</h2>
|
|
11
11
|
<lu>
|
|
12
|
-
<li><strong>18 Coordinate Systems</strong> - LLA, ECEF, UTM, ENU, NED, MGRS, USNG, Web Mercator, UPS, State Plane, BNG, GH36, GH, HAM, OLC<br>
|
|
12
|
+
<li><strong>18 Coordinate Systems</strong> - LLA, ECEF, UTM, ENU, NED, MGRS, USNG, Web Mercator, UPS, State Plane, BNG, GH36, GH, HAM, OLC, GEOREF, GARS, H3<br>
|
|
13
13
|
<li><strong>Full Bidirectional Conversions</strong> - Every system converts to and from every other system<br>
|
|
14
14
|
<li><strong>Distance Calculations</strong> - Vincenty great-circle and straight-line with unit tracking<br>
|
|
15
15
|
<li><strong>Bearing Calculations</strong> - Forward azimuth, back azimuth, compass directions, elevation angles<br>
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
<li><strong>Segments</strong> - Directed two-point line segments with projection, intersection, and interpolation<br>
|
|
19
19
|
<li><strong>Paths</strong> - Directed coordinate sequences with navigation, interpolation, closest approach, intersection, and area conversion<br>
|
|
20
20
|
<li><strong>Features</strong> - Named geometry wrapper with metadata and delegated distance/bearing<br>
|
|
21
|
+
<li><strong>GeoJSON Export</strong> - Build FeatureCollections from any mix of objects and save to file<br>
|
|
21
22
|
<li><strong>Validated Setters</strong> - Type coercion and range validation on all coordinate attributes<br>
|
|
22
23
|
<li><strong>Serialization</strong> - to_s(precision), to_a, from_string, from_array, DMS format<br>
|
|
23
24
|
<li><strong>Multiple Datums</strong> - WGS84, Clarke 1866, GRS 1980, Airy 1830, and more<br>
|
|
@@ -35,33 +36,33 @@ Geodetic supports full bidirectional conversion between all 18 coordinate system
|
|
|
35
36
|
|
|
36
37
|
| System | Class | Description |
|
|
37
38
|
|--------|-------|-------------|
|
|
38
|
-
| **LLA** | `Geodetic::Coordinate::LLA` | Latitude, Longitude, Altitude |
|
|
39
|
-
| **ECEF** | `Geodetic::Coordinate::ECEF` | Earth-Centered, Earth-Fixed (X, Y, Z) |
|
|
40
|
-
| **UTM** | `Geodetic::Coordinate::UTM` | Universal Transverse Mercator |
|
|
41
|
-
| **ENU** | `Geodetic::Coordinate::ENU` | East, North, Up (local tangent plane) |
|
|
42
|
-
| **NED** | `Geodetic::Coordinate::NED` | North, East, Down (local tangent plane) |
|
|
43
|
-
| **MGRS** | `Geodetic::Coordinate::MGRS` | Military Grid Reference System |
|
|
44
|
-
| **USNG** | `Geodetic::Coordinate::USNG` | United States National Grid |
|
|
45
|
-
| **WebMercator** | `Geodetic::Coordinate::WebMercator` | Web Mercator projection (EPSG:3857) |
|
|
46
|
-
| **UPS** | `Geodetic::Coordinate::UPS` | Universal Polar Stereographic |
|
|
47
|
-
| **StatePlane** | `Geodetic::Coordinate::StatePlane` | State Plane Coordinate System |
|
|
48
|
-
| **BNG** | `Geodetic::Coordinate::BNG` | British National Grid |
|
|
49
|
-
| **GH36** | `Geodetic::Coordinate::GH36` | Geohash-36 (spatial hash, URL-friendly) |
|
|
50
|
-
| **GH** | `Geodetic::Coordinate::GH` | Geohash base-32 (standard geohash, widely supported) |
|
|
51
|
-
| **HAM** | `Geodetic::Coordinate::HAM` | Maidenhead Locator System (amateur radio grid squares) |
|
|
52
|
-
| **OLC** | `Geodetic::Coordinate::OLC` | Open Location Code / Plus Codes (Google's location encoding) |
|
|
53
|
-
| **GEOREF** | `Geodetic::Coordinate::GEOREF` | World Geographic Reference System (aviation/military) |
|
|
54
|
-
| **GARS** | `Geodetic::Coordinate::GARS` | Global Area Reference System (NGA standard) |
|
|
55
|
-
| **H3** | `Geodetic::Coordinate::H3` | Uber's hexagonal hierarchical index (requires `libh3`) |
|
|
39
|
+
| [**LLA**](coordinate-systems/lla.md) | `Geodetic::Coordinate::LLA` | Latitude, Longitude, Altitude |
|
|
40
|
+
| [**ECEF**](coordinate-systems/ecef.md) | `Geodetic::Coordinate::ECEF` | Earth-Centered, Earth-Fixed (X, Y, Z) |
|
|
41
|
+
| [**UTM**](coordinate-systems/utm.md) | `Geodetic::Coordinate::UTM` | Universal Transverse Mercator |
|
|
42
|
+
| [**ENU**](coordinate-systems/enu.md) | `Geodetic::Coordinate::ENU` | East, North, Up (local tangent plane) |
|
|
43
|
+
| [**NED**](coordinate-systems/ned.md) | `Geodetic::Coordinate::NED` | North, East, Down (local tangent plane) |
|
|
44
|
+
| [**MGRS**](coordinate-systems/mgrs.md) | `Geodetic::Coordinate::MGRS` | Military Grid Reference System |
|
|
45
|
+
| [**USNG**](coordinate-systems/usng.md) | `Geodetic::Coordinate::USNG` | United States National Grid |
|
|
46
|
+
| [**WebMercator**](coordinate-systems/web-mercator.md) | `Geodetic::Coordinate::WebMercator` | Web Mercator projection (EPSG:3857) |
|
|
47
|
+
| [**UPS**](coordinate-systems/ups.md) | `Geodetic::Coordinate::UPS` | Universal Polar Stereographic |
|
|
48
|
+
| [**StatePlane**](coordinate-systems/state-plane.md) | `Geodetic::Coordinate::StatePlane` | State Plane Coordinate System |
|
|
49
|
+
| [**BNG**](coordinate-systems/bng.md) | `Geodetic::Coordinate::BNG` | British National Grid |
|
|
50
|
+
| [**GH36**](coordinate-systems/gh36.md) | `Geodetic::Coordinate::GH36` | Geohash-36 (spatial hash, URL-friendly) |
|
|
51
|
+
| [**GH**](coordinate-systems/gh.md) | `Geodetic::Coordinate::GH` | Geohash base-32 (standard geohash, widely supported) |
|
|
52
|
+
| [**HAM**](coordinate-systems/ham.md) | `Geodetic::Coordinate::HAM` | Maidenhead Locator System (amateur radio grid squares) |
|
|
53
|
+
| [**OLC**](coordinate-systems/olc.md) | `Geodetic::Coordinate::OLC` | Open Location Code / Plus Codes (Google's location encoding) |
|
|
54
|
+
| [**GEOREF**](coordinate-systems/georef.md) | `Geodetic::Coordinate::GEOREF` | World Geographic Reference System (aviation/military) |
|
|
55
|
+
| [**GARS**](coordinate-systems/gars.md) | `Geodetic::Coordinate::GARS` | Global Area Reference System (NGA standard) |
|
|
56
|
+
| [**H3**](coordinate-systems/h3.md) | `Geodetic::Coordinate::H3` | Uber's hexagonal hierarchical index (requires `libh3`) |
|
|
56
57
|
|
|
57
58
|
## Additional Features
|
|
58
59
|
|
|
59
|
-
- **16 geodetic datums** -- WGS84, GRS 1980, Clarke 1866, Airy 1830, Bessel 1841, and more. All conversion methods accept an optional datum parameter, defaulting to WGS84.
|
|
60
|
-
- **Geoid height calculations** -- Convert between ellipsoidal and orthometric heights using models such as EGM96, EGM2008, GEOID18, and GEOID12B.
|
|
61
|
-
- **Geographic areas** -- `Geodetic::Areas::Circle`, `Geodetic::Areas::Polygon`, `Geodetic::Areas::BoundingBox`, plus polygon subclasses (`Triangle`, `Rectangle`, `Pentagon`, `Hexagon`, `Octagon`) for point-in-area testing.
|
|
62
|
-
- **Segments** -- `Geodetic::Segment` is a directed two-point line segment with projection, intersection detection, interpolation, and membership testing. It is the geometric primitive underlying Path and Polygon operations.
|
|
63
|
-
- **Paths** -- `Geodetic::Path` is a directed, ordered sequence of unique coordinates supporting navigation, segment analysis, interpolation, closest approach (geometric projection), containment testing, bounding boxes, polygon conversion, and path intersection detection.
|
|
64
|
-
- **Features** -- `Geodetic::Feature` wraps any coordinate, area, or path with a label and metadata hash, delegating `distance_to` and `bearing_to` to the underlying geometry.
|
|
60
|
+
- **[16 geodetic datums](reference/datums.md)** -- WGS84, GRS 1980, Clarke 1866, Airy 1830, Bessel 1841, and more. All conversion methods accept an optional datum parameter, defaulting to WGS84.
|
|
61
|
+
- **[Geoid height calculations](reference/geoid-height.md)** -- Convert between ellipsoidal and orthometric heights using models such as EGM96, EGM2008, GEOID18, and GEOID12B.
|
|
62
|
+
- **[Geographic areas](reference/areas.md)** -- `Geodetic::Areas::Circle`, `Geodetic::Areas::Polygon`, `Geodetic::Areas::BoundingBox`, plus polygon subclasses (`Triangle`, `Rectangle`, `Pentagon`, `Hexagon`, `Octagon`) for point-in-area testing.
|
|
63
|
+
- **[Segments](reference/segment.md)** -- `Geodetic::Segment` is a directed two-point line segment with projection, intersection detection, interpolation, and membership testing. It is the geometric primitive underlying Path and Polygon operations.
|
|
64
|
+
- **[Paths](reference/path.md)** -- `Geodetic::Path` is a directed, ordered sequence of unique coordinates supporting navigation, segment analysis, interpolation, closest approach (geometric projection), containment testing, bounding boxes, polygon conversion, and path intersection detection.
|
|
65
|
+
- **[Features](reference/feature.md)** -- `Geodetic::Feature` wraps any coordinate, area, or path with a label and metadata hash, delegating `distance_to` and `bearing_to` to the underlying geometry.
|
|
65
66
|
|
|
66
67
|
## Design Principles
|
|
67
68
|
|
|
@@ -91,5 +92,26 @@ puts lla_again.to_s
|
|
|
91
92
|
|
|
92
93
|
## Documentation
|
|
93
94
|
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
### Getting Started
|
|
96
|
+
|
|
97
|
+
- [Installation](getting-started/installation.md)
|
|
98
|
+
- [Quick Start](getting-started/quick-start.md)
|
|
99
|
+
|
|
100
|
+
### Coordinate Systems
|
|
101
|
+
|
|
102
|
+
- [Coordinate Systems Overview](coordinate-systems/index.md)
|
|
103
|
+
|
|
104
|
+
### Reference
|
|
105
|
+
|
|
106
|
+
- [Conversions](reference/conversions.md)
|
|
107
|
+
- [Serialization](reference/serialization.md)
|
|
108
|
+
- [Datums](reference/datums.md)
|
|
109
|
+
- [Geoid Height](reference/geoid-height.md)
|
|
110
|
+
- [Areas](reference/areas.md)
|
|
111
|
+
- [Path](reference/path.md)
|
|
112
|
+
- [Segment](reference/segment.md)
|
|
113
|
+
- [Feature](reference/feature.md)
|
|
114
|
+
- [Vector](reference/vector.md)
|
|
115
|
+
- [Arithmetic](reference/arithmetic.md)
|
|
116
|
+
- [GeoJSON Export](reference/geojson.md)
|
|
117
|
+
- [Map Rendering](reference/map-rendering.md)
|
|
@@ -30,7 +30,7 @@ seg = seattle + portland # => Geodetic::Segment
|
|
|
30
30
|
seg.start_point # => seattle
|
|
31
31
|
seg.end_point # => portland
|
|
32
32
|
seg.length # => Distance (~235 km)
|
|
33
|
-
seg.bearing # => Bearing (~
|
|
33
|
+
seg.bearing # => Bearing (~186°)
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
Works across any coordinate system — the Segment converts both points to LLA internally:
|
|
@@ -250,7 +250,7 @@ portland = Geodetic::Coordinate::LLA.new(lat: 45.5152, lng: -122.6784, alt: 0.0)
|
|
|
250
250
|
sf = Geodetic::Coordinate::LLA.new(lat: 37.7749, lng: -122.4194, alt: 0.0)
|
|
251
251
|
|
|
252
252
|
# Radial distances from receiver
|
|
253
|
-
seattle.distance_to(portland) # => Distance (
|
|
253
|
+
seattle.distance_to(portland) # => Distance (235385.71 m)
|
|
254
254
|
seattle.distance_to(portland, sf) # => [Distance, Distance] (Array)
|
|
255
255
|
|
|
256
256
|
# Consecutive chain distances
|
|
@@ -274,7 +274,7 @@ Both `distance_to` and `straight_line_distance_to` accept any coordinate type. C
|
|
|
274
274
|
```ruby
|
|
275
275
|
utm = seattle.to_utm
|
|
276
276
|
mgrs = Geodetic::Coordinate::MGRS.from_lla(portland)
|
|
277
|
-
utm.distance_to(mgrs) # => Distance (
|
|
277
|
+
utm.distance_to(mgrs) # => Distance (235385.71 m)
|
|
278
278
|
```
|
|
279
279
|
|
|
280
280
|
### ENU and NED (Relative Systems)
|
|
@@ -308,7 +308,7 @@ sf = Geodetic::Coordinate::LLA.new(lat: 37.7749, lng: -122.4194, alt: 0.0)
|
|
|
308
308
|
|
|
309
309
|
# Forward azimuth
|
|
310
310
|
b = seattle.bearing_to(portland) # => Bearing
|
|
311
|
-
b.degrees # =>
|
|
311
|
+
b.degrees # => 186.25...
|
|
312
312
|
b.to_compass(points: 8) # => "S"
|
|
313
313
|
b.reverse # => Bearing (back azimuth)
|
|
314
314
|
|
data/docs/reference/feature.md
CHANGED
|
@@ -65,7 +65,7 @@ liberty.distance_to(LLA.new(lat: 40.7484, lng: -73.9857, alt: 0))
|
|
|
65
65
|
Returns a `Geodetic::Bearing` from this feature to another feature, coordinate, or area. Uses the same centroid resolution as `distance_to`.
|
|
66
66
|
|
|
67
67
|
```ruby
|
|
68
|
-
liberty.bearing_to(empire).degrees # => 36.
|
|
68
|
+
liberty.bearing_to(empire).degrees # => 36.95
|
|
69
69
|
liberty.bearing_to(empire).to_compass # => "NE"
|
|
70
70
|
```
|
|
71
71
|
|