coordconver 0.1.4 → 1.1.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 +5 -5
- data/.github/workflows/ci.yml +36 -0
- data/CHANGELOG.md +59 -0
- data/README.en.md +177 -0
- data/README.md +242 -175
- data/coordconver.gemspec +33 -17
- data/docs/cc-algorithms.js +293 -0
- data/docs/index.html +283 -0
- data/exe/coordconver +241 -0
- data/lib/coordconver/coordconver.rb +268 -86
- data/lib/coordconver/degree.rb +47 -49
- data/lib/coordconver/errors.rb +23 -0
- data/lib/coordconver/formats.rb +51 -0
- data/lib/coordconver/geo/api.rb +45 -0
- data/lib/coordconver/geo/baidu.rb +67 -23
- data/lib/coordconver/geo/cache.rb +66 -0
- data/lib/coordconver/geo/client.rb +18 -5
- data/lib/coordconver/geo/configuration.rb +99 -9
- data/lib/coordconver/geo/gaode.rb +80 -25
- data/lib/coordconver/geo/key_pool.rb +78 -0
- data/lib/coordconver/geo/tencent.rb +69 -0
- data/lib/coordconver/projection.rb +129 -0
- data/lib/coordconver/utils/http.rb +71 -44
- data/lib/coordconver/utils/request.rb +9 -6
- data/lib/coordconver/version.rb +3 -1
- data/lib/coordconver.rb +20 -6
- metadata +37 -33
- data/.travis.yml +0 -8
- data/bin/coordconver +0 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 9889fff6fe699d7d248aa42661f59029249f3ca929de12bb0cb81953faa71c8b
|
|
4
|
+
data.tar.gz: 988c47e1827785c21359bb6af7c0658d8f3985a397d351ff297f378359242c1c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 24c92c16f253e8da20a14a5f26335f4782222ad8d15f78177e24b82f207033861d490dbb52613ebc0164f2f6a38d0ea769199b0534d0b46430d05210078cf3d5
|
|
7
|
+
data.tar.gz: 51db680c343e5451aaf1401345c5a6fc02b375dabcb46371449772d62cf45f5453f6c5645f4ee259e1516818009042595393e909e263b18502c061e0e028d264
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
name: Ruby ${{ matrix.ruby }}
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
ruby: ['2.7', '3.0', '3.1', '3.2', '3.3', '3.4']
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: ruby/setup-ruby@v1
|
|
19
|
+
with:
|
|
20
|
+
ruby-version: ${{ matrix.ruby }}
|
|
21
|
+
bundler-cache: true
|
|
22
|
+
- name: Run tests
|
|
23
|
+
run: bundle exec rake test
|
|
24
|
+
- name: CLI smoke test
|
|
25
|
+
run: |
|
|
26
|
+
exe/coordconver wgs2gcj 121.468738 31.247138
|
|
27
|
+
exe/coordconver wgs2gcj 121.468738 31.247138 --json
|
|
28
|
+
exe/coordconver wgs2gcj 121.468738 31.247138 --geojson
|
|
29
|
+
echo "121.468738,31.247138" | exe/coordconver gcj2wgs
|
|
30
|
+
printf "lng,lat\n121.468738,31.247138\n" | exe/coordconver wgs2gcj --csv
|
|
31
|
+
exe/coordconver dms 38.65777 104.08296
|
|
32
|
+
exe/coordconver dist 116.397428 39.90923 121.473701 31.230416
|
|
33
|
+
exe/coordconver bearing 116.397428 39.90923 121.473701 31.230416
|
|
34
|
+
exe/coordconver dest 116.397428 39.90923 153 100000
|
|
35
|
+
exe/coordconver gk 121.47 31.24 --zone3
|
|
36
|
+
exe/coordconver invgk 640045.58 3458515.34 --cm 120
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.1.0 (2026-10-25)
|
|
4
|
+
|
|
5
|
+
### 新增
|
|
6
|
+
|
|
7
|
+
- **厘米级精确逆变换**:`gcj_wgs_precise` / `bd_wgs_precise`(迭代法,误差 < 1e-7 度),原 `gcj_wgs`/`bd_wgs` 保留为近似版本(米级)。
|
|
8
|
+
- **球面几何**:`bearing`(初始方位角)、`destination_point`(沿方位角偏移点),与 `distance` 配套。
|
|
9
|
+
- **灵活的入参/出参**:所有转换方法支持 `Point` 结构 / `[lng, lat]` / `{lng:, lat:}` 单参调用,以及 `as: :hash` / `as: :point` 返回格式;新增 `Coordconver.point` 与 `Coordconver::Point`。
|
|
10
|
+
- **批量转换**:`Coordconver.transform(points, from:, to:, as:)`。
|
|
11
|
+
- **WKT / GeoJSON 支持**:`parse_wkt` / `to_wkt` / `parse_geojson` / `to_geojson`,可与坐标转换自由组合。
|
|
12
|
+
- **高斯-克吕格投影**:`gauss_kruger` / `inverse_gauss_kruger` 正反算(CGCS2000/WGS-84/北京54/西安80 椭球,往返精度优于 1cm),`zone_meridian` 3°/6° 带号与中央经线换算。
|
|
13
|
+
- **腾讯位置服务支持**:`Coordconver::Tencent` 的 `geo` / `regeo` / `ip` 及便捷方法,与百度/高德同等的多 key 轮询能力。
|
|
14
|
+
- **多 key 智能轮询**:从随机取样改为线程安全的 round-robin;识别配额超限/无效 key(百度 401/402/200/201/210,高德 10001/10003/10009/10044/20003,腾讯 110/112/120/121/199)后自动摘除并在冷却 5 分钟后恢复;全部 key 耗尽时抛出 `ApiError`。
|
|
15
|
+
- **进程内 LRU 缓存**:`config.cache = true` 开启(可配 `cache_ttl`/`cache_size`),重复的地理编码请求不再消耗配额。
|
|
16
|
+
- **高德官方坐标转换 API**:`Gaode.convert` / `convert_location`(GPS/百度 -> GCJ-02,单次最多 40 点)。
|
|
17
|
+
- **CLI 增强**:新增 `bearing` / `dest` / `gk` / `invgk` 子命令;`--csv`(表头自动跳过)、`--geojson`、`--cache`、`--tencent` 选项。
|
|
18
|
+
- **在线试用页**:`docs/` 目录新增纯前端 demo(GitHub Pages 托管),坐标转换/度分秒/距离方位角/高斯-克吕格算法的 JS 移植与 gem 数值一致,无需安装即可体验。
|
|
19
|
+
- 英文文档 `README.en.md`。
|
|
20
|
+
|
|
21
|
+
### 变更
|
|
22
|
+
|
|
23
|
+
- 百度/高德/腾讯 API 请求统一经 `Geo::Api` 调度层(缓存 + key 轮换),行为对调用方透明。
|
|
24
|
+
- `Configuration.reset!` 现在会同时重置 key 轮询状态与缓存。
|
|
25
|
+
|
|
26
|
+
## 1.0.0 (2026-10-25)
|
|
27
|
+
|
|
28
|
+
### 修复
|
|
29
|
+
|
|
30
|
+
- **`bd_wgs` 方向 bug**:0.x 版本的 `bd_wgs` 复用了 `wgs_bd` 的逻辑,返回结果方向完全错误。现已改为 `gcj_wgs(bd_gcj(...))` 并增加回归测试。
|
|
31
|
+
- `transformlng` 遗漏 return 导致结果依赖实现细节的问题。
|
|
32
|
+
|
|
33
|
+
### 变更(不兼容)
|
|
34
|
+
|
|
35
|
+
- 百度地理编码升级至 [Geocoding API v3](https://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding)(旧 v2 接口已下线),默认走 HTTPS;`regeo` 使用 Reverse Geocoding API v3。
|
|
36
|
+
- 调用百度/高德 API 前必须先配置 key(`Coordconver.configure` 或 `Coordconver::Client.new`),未配置时抛出 `Coordconver::ConfigurationError`;移除了源码中硬编码的测试 key。
|
|
37
|
+
- `Coordconver.cal_degree` 默认输出保留两位小数秒(`"38°39′27.97″"`);需要旧版整数秒输出时使用 `Coordconver.cal_degree(n, 0)`。
|
|
38
|
+
- `undegree`/`cal_undegree` 精度由 5 位小数提升至 6 位小数。
|
|
39
|
+
- 最低 Ruby 版本要求提升至 2.7。
|
|
40
|
+
- 移除 `Coordconver::Coordconver` 嵌套模块,转换方法直接定义在 `Coordconver` 单例上(原调用方式 `Coordconver.bd_gcj` 等不受影响)。
|
|
41
|
+
- 要求 RubyGems 发布启用 MFA。
|
|
42
|
+
|
|
43
|
+
### 新增
|
|
44
|
+
|
|
45
|
+
- `Coordconver.distance`:两点球面距离(Haversine,米)。
|
|
46
|
+
- `Coordconver.out_of_china?`:境外坐标判断,境外坐标 `wgs_gcj`/`gcj_wgs` 原样返回。
|
|
47
|
+
- 语义化别名:`wgs84_gcj02`、`gcj02_wgs84`、`gcj02_bd09`、`bd09_gcj02`、`wgs84_bd09`、`bd09_wgs84`。
|
|
48
|
+
- 度分秒解析支持多种写法(`38°39′27.97″` / `38d39m27.97s` / `38:39:27.97`)与负值(西经/南纬)。
|
|
49
|
+
- 命令行工具 `coordconver`:坐标系转换、度分秒互转、距离计算、stdin 批量转换、JSON 输出。
|
|
50
|
+
- 百度 SN 校验支持(`baidu_sn` 配置项)。
|
|
51
|
+
- 便捷方法:`Baidu.geo_location`、`Baidu.regeo_address`、`Gaode.geo_location`、`Gaode.regeo_address`。
|
|
52
|
+
- 统一错误体系:`Coordconver::Error` / `ConfigurationError` / `NetworkError` / `ApiError`。
|
|
53
|
+
- `Coordconver.configure` 全局配置块;`open_timeout` / `read_timeout` 可配置。
|
|
54
|
+
- HTTP 层:指数退避自动重试、非 2xx 判定、JSON 解析容错、请求头规范化。
|
|
55
|
+
- 测试全面离线化(stub 网络层),另提供 `COORDCONVER_LIVE_TEST=1` 门控的真实 API 联调测试;CI 由 Travis 迁移至 GitHub Actions(Ruby 2.7 ~ 3.4 矩阵)。
|
|
56
|
+
|
|
57
|
+
## 0.1.4
|
|
58
|
+
|
|
59
|
+
- 最后一个 0.x 版本。
|
data/README.en.md
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Coordconver
|
|
2
|
+
|
|
3
|
+
[](https://github.com/cheenwe/coordconver/actions/workflows/ci.yml)
|
|
4
|
+
[](https://badge.fury.io/rb/coordconver)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
A zero-dependency Ruby toolkit for Chinese map coordinates ([中文文档](README.md)):
|
|
8
|
+
|
|
9
|
+
1. **Offline coordinate conversion** between BD-09 (Baidu), GCJ-02 (Mars, used by Amap/Tencent/Google China) and WGS-84 (GPS), with a **centimeter-accurate iterative inverse**
|
|
10
|
+
2. **Spherical geometry**: distance, initial bearing, destination point
|
|
11
|
+
3. **Decimal degrees ⇄ DMS**, **WKT / GeoJSON** parsing and generation
|
|
12
|
+
4. **Gauss-Krüger projection** (CGCS2000 / Beijing54 / Xi'an80 / WGS-84, 3°/6° zones)
|
|
13
|
+
5. **Geocoding** via Baidu / Amap (Gaode) / Tencent Web APIs, plus Amap's official coordinate conversion API
|
|
14
|
+
6. **Production-ready**: automatic key rotation with quota failover, in-process LRU cache, unified error hierarchy, thread-safe
|
|
15
|
+
7. **CLI** for one-off and batch (CSV/GeoJSON) conversions
|
|
16
|
+
|
|
17
|
+
Requires Ruby >= 2.7. No runtime dependencies — standard library only.
|
|
18
|
+
|
|
19
|
+
> **Try it online** (no install needed): https://cheenwe.github.io/coordconver/ — a pure front-end demo with results identical to the gem.
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
Add to your Gemfile:
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
gem 'coordconver'
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
then `bundle`, or install directly:
|
|
30
|
+
|
|
31
|
+
$ gem install coordconver
|
|
32
|
+
|
|
33
|
+
## Coordinate conversion
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
require 'coordconver'
|
|
37
|
+
|
|
38
|
+
wgs = [121.468738, 31.247138]
|
|
39
|
+
Coordconver.wgs_gcj(*wgs) # => [121.47327833883615, 31.2452165865549]
|
|
40
|
+
Coordconver.wgs_bd(*wgs) # => [121.47980789007566, 31.251157822142243]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
| Conversion | Method | Alias |
|
|
44
|
+
| ----- | ----- | ----- |
|
|
45
|
+
| BD-09 -> GCJ-02 | `Coordconver.bd_gcj(lng, lat)` | `bd09_gcj02` |
|
|
46
|
+
| GCJ-02 -> BD-09 | `Coordconver.gcj_bd(lng, lat)` | `gcj02_bd09` |
|
|
47
|
+
| GCJ-02 -> WGS-84 | `Coordconver.gcj_wgs(lng, lat)` | `gcj02_wgs84` |
|
|
48
|
+
| WGS-84 -> GCJ-02 | `Coordconver.wgs_gcj(lng, lat)` | `wgs84_gcj02` |
|
|
49
|
+
| BD-09 -> WGS-84 | `Coordconver.bd_wgs(lng, lat)` | `bd09_wgs84` |
|
|
50
|
+
| WGS-84 -> BD-09 | `Coordconver.wgs_bd(lng, lat)` | `wgs84_bd09` |
|
|
51
|
+
|
|
52
|
+
Every method accepts `(lng, lat)`, a `Coordconver.point(lng, lat)` struct, `[lng, lat]` or `{lng:, lat:}`, and returns `[lng, lat]` by default — pass `as: :hash` or `as: :point` for other shapes:
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
Coordconver.wgs_gcj(121.468738, 31.247138, as: :hash)
|
|
56
|
+
# => {lng: 121.47327833883615, lat: 31.2452165865549}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Precise inverse
|
|
60
|
+
|
|
61
|
+
The standard `gcj_wgs` is an approximate inverse (meter-level error). The iterative `gcj_wgs_precise` is accurate to ~1 cm:
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
g = Coordconver.wgs_gcj(121.468738, 31.247138)
|
|
65
|
+
Coordconver.gcj_wgs_precise(*g) # => [121.468738, 31.247138]
|
|
66
|
+
Coordconver.bd_wgs_precise(*bd) # same for Baidu coordinates
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Batch conversion
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
points = [[121.468738, 31.247138], Coordconver.point(116.481499, 39.990475), { lng: 104.08, lat: 30.65 }]
|
|
73
|
+
Coordconver.transform(points, from: :wgs84, to: :gcj02, as: :hash)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Spherical geometry
|
|
77
|
+
|
|
78
|
+
```ruby
|
|
79
|
+
Coordconver.distance(116.397428, 39.90923, 121.473701, 31.230416) # => 1068194.1 (meters)
|
|
80
|
+
Coordconver.bearing(116.397428, 39.90923, 121.473701, 31.230416) # => 153.04 (degrees from north)
|
|
81
|
+
Coordconver.destination_point(116.397428, 39.90923, 153.0, 100_000)
|
|
82
|
+
Coordconver.out_of_china?(121.47, 31.25) # => false
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## DMS / WKT / GeoJSON
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
Coordconver.degree(38.65777, 104.08296) # => ["38°39′27.97″", "104°4′58.66″"]
|
|
89
|
+
Coordconver.undegree("38°39′27.97″", "104°4′58.66″")
|
|
90
|
+
Coordconver.cal_undegree("38:39:27.97") # also 38d39m27.97s, negatives supported
|
|
91
|
+
|
|
92
|
+
Coordconver.parse_wkt("POINT (121.47 31.25)") # => [121.47, 31.25]
|
|
93
|
+
Coordconver.to_wkt(121.47, 31.25) # => "POINT (121.47 31.25)"
|
|
94
|
+
Coordconver.parse_geojson(geojson_hash_or_string)
|
|
95
|
+
Coordconver.to_geojson(121.47, 31.25) # => {"type"=>"Point", "coordinates"=>[121.47, 31.25]}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Gauss-Krüger projection
|
|
99
|
+
|
|
100
|
+
Forward/inverse Gauss-Krüger (transverse Mercator) for surveying workflows:
|
|
101
|
+
|
|
102
|
+
```ruby
|
|
103
|
+
Coordconver.gauss_kruger(121.47, 31.24, zone_width: 3)
|
|
104
|
+
# => [640045.58, 3458515.34]
|
|
105
|
+
Coordconver.gauss_kruger(121.47, 31.24, central_meridian: 120, ellipsoid: :krassovsky) # Beijing54
|
|
106
|
+
Coordconver.inverse_gauss_kruger(640045.58, 3458515.34, central_meridian: 120)
|
|
107
|
+
Coordconver.zone_meridian(121.47, width: 3) # => [40, 120]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Ellipsoids: `:cgcs2000` (default), `:wgs84`, `:krassovsky` (Beijing54), `:iag75` (Xi'an80).
|
|
111
|
+
|
|
112
|
+
## Geocoding (Baidu / Amap / Tencent)
|
|
113
|
+
|
|
114
|
+
Get API keys from [Baidu](https://lbsyun.baidu.com/apiconsole/key) (server-side AK), [Amap](https://console.amap.com/dev/key/app) (Web service) or [Tencent LBS](https://lbs.qq.com/dev/console/application/mine). Pass multiple keys and the library rotates them automatically, skipping keys that hit quota limits (they recover after a 5-minute cooldown).
|
|
115
|
+
|
|
116
|
+
```ruby
|
|
117
|
+
Coordconver.configure do |config|
|
|
118
|
+
config.baidu_map_aks = ["baidu-ak-1", "baidu-ak-2"]
|
|
119
|
+
config.gaode_map_keys = ["amap-key-1"]
|
|
120
|
+
config.tencent_map_keys = ["tencent-key-1"]
|
|
121
|
+
# config.baidu_sn = "sn-secret" # only for SN-signed AKs
|
|
122
|
+
# config.cache = true # in-process LRU cache to save quota
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
Coordconver::Baidu.geo_location("百度大厦") # => [lng, lat] (BD-09)
|
|
126
|
+
Coordconver::Gaode.regeo_address(116.480881, 39.989410) # => "北京市朝阳区..." (GCJ-02 in)
|
|
127
|
+
Coordconver::Tencent.geo_location("北京市海淀区...") # => [lng, lat] (GCJ-02)
|
|
128
|
+
Coordconver::Baidu.ip("8.8.8.8")
|
|
129
|
+
|
|
130
|
+
# Official Amap conversion API (up to 40 points per call)
|
|
131
|
+
Coordconver::Gaode.convert_location([121.468738, 31.247138], from: :gps)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Raw methods (`geo`/`regeo`) return the provider's full parsed JSON. Business errors are not raised — check `status` in the response (`0` for Baidu/Tencent, `"1"` for Amap).
|
|
135
|
+
|
|
136
|
+
### Error handling
|
|
137
|
+
|
|
138
|
+
```ruby
|
|
139
|
+
begin
|
|
140
|
+
Coordconver::Gaode.regeo_address(116.48, 39.98)
|
|
141
|
+
rescue Coordconver::ConfigurationError # no key configured
|
|
142
|
+
rescue Coordconver::ApiError # all keys exhausted/invalid (e.raw has the last response)
|
|
143
|
+
rescue Coordconver::NetworkError # timeouts/HTTP failures (retried 3x internally)
|
|
144
|
+
rescue Coordconver::Error # base class
|
|
145
|
+
end
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## CLI
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
coordconver wgs2gcj 121.468738 31.247138 # => 121.473278,31.245217
|
|
152
|
+
coordconver dms 38.65777 104.08296
|
|
153
|
+
coordconver dist 116.397 39.909 121.474 31.230
|
|
154
|
+
coordconver bearing 116.397 39.909 121.474 31.230
|
|
155
|
+
coordconver dest 116.397 39.909 153 100000
|
|
156
|
+
coordconver gk 121.47 31.24 --zone3
|
|
157
|
+
cat points.txt | coordconver wgs2gcj --csv # batch, header skipped
|
|
158
|
+
coordconver wgs2gcj 121.46 31.24 --geojson
|
|
159
|
+
coordconver geo --gaode "北京方恒国际中心A座" # needs COORDCONVER_GAODE_KEY env var
|
|
160
|
+
coordconver regeo --baidu 116.322987 39.983424
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Environment variables: `COORDCONVER_BAIDU_AK`, `COORDCONVER_GAODE_KEY`, `COORDCONVER_TENCENT_KEY` (comma-separated for multiple keys).
|
|
164
|
+
|
|
165
|
+
## Development
|
|
166
|
+
|
|
167
|
+
`bin/setup` to install dependencies, `rake test` to run the offline test suite. Live API tests are gated behind `COORDCONVER_LIVE_TEST=1` plus real keys. Install locally with `bundle exec rake install`; release with `bundle exec rake release`.
|
|
168
|
+
|
|
169
|
+
The online demo is served by GitHub Pages from the `docs/` directory. To enable it once: repo Settings -> Pages -> Source `Deploy from a branch`, branch `master`, folder `/docs`.
|
|
170
|
+
|
|
171
|
+
## Contributing
|
|
172
|
+
|
|
173
|
+
Bug reports and pull requests are welcome at https://github.com/cheenwe/coordconver.
|
|
174
|
+
|
|
175
|
+
## License
|
|
176
|
+
|
|
177
|
+
MIT License.
|