仓颉三方库开发实战教程(以 gcoord4cj 为例)
本文基于开源项目 gcoord4cj,总结一套从 0 到 1 的仓颉(Cangjie)三方库开发流程:工程化、API 设计、实现细节、单元测试、文档规范与发布建议。读者可直接参考本文在自己项目中落地实践。
1. 项目目标与定位 🧭
-
目标:在仓颉语言中实现地理坐标转换库,覆盖 Web/移动地图常用坐标系:
-
WGS84、GCJ02、BD09、BD09MC、EPSG3857
-
-
特性:
-
轻量、无第三方运行时依赖(仅用标准库)
-
支持坐标别名标准化(如 WGS1984/EPSG4326 → WGS84 等)
-
支持单点转换、GeoJSON 坐标数组递归转换、Geometry/Feature/FeatureCollection 顶层对象转换
-
提供 std.unittest 测试样例(HLT/LLT 分层)
-
2. 初始化与目录规范 📁
推荐目录结构(gcoord4cj 已实践):
. ├── cjpm.toml # 项目配置 ├── src # 源码 │ ├── crs_BD09.cj │ ├── crs_BD09MC.cj │ ├── crs_EPSG3857.cj │ ├── crs_GCJ02.cj │ ├── helper.cj │ ├── index.cj # 统一对外 API │ └── transform.cj # 编排与别名规范、GeoJSON 支持 ├── test # 测试目录(HLT/LLT) │ ├── HLT/transform_test.cj │ └── LLT/crs_conversion_test.cj └── doc # 文档 ├── design.md ├── feature_api.md └── cj_third_party_lib_tutorial.md # 本文
初始化工程:
cjpm init
构建与测试:
cjpm update cjpm build cjpm test

注意:默认测试扫描 src 下的 @Test/@TestCase 测试类。若测试文件放在 test 目录,可保留一个位于 src 的“测试入口”或将测试文件迁回 src(gcoord4cj 示例提供了两种使用姿势)。
3. API 设计与演进 ✨
三类核心能力建议:
-
单点转换(易用,覆盖 80% 场景)
public func transformPosition(lng: Float64, lat: Float64, from: String, to: String): (Float64, Float64)
-
坐标数组递归转换(面向 GeoJSON 的 coordinates 层)
public func transformCoordinates(coords: Any, from: String, to: String): Any
-
顶层 GeoJSON 对象转换(识别 Geometry/Feature/FeatureCollection)
public func transformGeoJSON(obj: Any, from: String, to: String): Any
配套:坐标别名标准化,确保外部传参宽松但内部实现统一:
public func normalizeCrs(name: String): String
建议将 API 汇总到
src/index.cj,便于消费端 import 一个包即可使用全部能力。
4. 实现要点 🔧
4.1 分层思想:数学实现与编排解耦
-
crs_*.cj只负责数学转换(如 BD09 ↔ BD09MC 的分带多项式、WGS84 ↔ EPSG3857 投影/反投影)。 -
transform.cj
负责:
-
normalizeCrs别名标准化 -
根据
from/to分发或链式组合(例如 WGS84→BD09 = WGS84→GCJ02→BD09) -
GeoJSON 相关:
-
transformCoordinates对任意维数组递归 -
transformGeoJSON识别并处理Geometry/Feature/FeatureCollection
-
-
4.2 统一数据模型:Any/HashMap/Array
-
为减少外部依赖,采用标准库
HashMap<String, Any>与Array<Any>表示 GeoJSON 对象/数组。 -
这样既能递归处理,又能与多种上层封装兼容(调用方可自行强类型封装)。
4.3 误差策略与边界
-
GCJ02↔WGS84 采用 1e-6 的迭代反解阈值;
-
测试断言在 1e-3/1e-4/1e-6 级别;
-
中国大陆范围外坐标不应用 GCJ02 偏移(与行业惯例一致)。
5. 单元测试与分层 🧪
-
框架:
std.unittest+ 宏注解@Test(类)@TestCase(方法)。 -
组织:
-
HLT(High Level Test):端到端功能验证(例如
transformPosition与transformCoordinates)。 -
LLT(Low Level Test):数学回环与边界精度(例如 EPSG3857/WGS84 回环、BD09MC 回环)。
-
示例(片段):
@Test
public class CRSConversionTest {
@TestCase
public func test_epsg3857_roundtrip() {
let w = (120.0, 30.0)
let m = transformPosition(w[0], w[1], "WGS84", "EPSG3857")
let w2 = transformPosition(m[0], m[1], "EPSG3857", "WGS84")
// 误差校验
if (!(abs(w2[0] - w[0]) < 1e-6 && abs(w2[1] - w[1]) < 1e-6)) {
throw Exception("assert failed")
}
}
}
命名约定:使用
*_test.cj,框架能更好地识别并展示。
6. 典型 FAQ ❓
-
Q:为什么 GeoJSON 不使用强类型?
-
A:为减少第三方依赖、兼容多种上层封装,优先使用标准库泛型容器(Any/HashMap/Array),调用方可按需包装。
-
-
Q:如何让 test 目录被测试框架识别?
-
A:可在
src新增一个带@Test的“测试入口”类,作为聚合/冒烟用例,保持 test 目录结构不变的同时确保有用例被发现与执行。
-
-
Q:如何扩展更多坐标系?
-
A:新增
crs_*.cj并在transform.cj的分发/链路中接入即可。
-
7. 小结 ✅
本文以 gcoord4cj 为例讲解了一个仓颉三方库从工程化到实现、测试与文档的完整流程。建议将“分层实现 + 别名标准化 + GeoJSON 递归 + 单元测试分层”作为通用模板,快速复制到你的业务库中,提升质量与效率。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)