# gl-projection
**Repository Path**: proj4js/gl-projection
## Basic Information
- **Project Name**: gl-projection
- **Description**: 高性能 WebGL 地图专用坐标投影库,专注于 **EPSG:3857(Web Mercator)** 与 **EPSG:4326(WGS84)** 坐标系转换,支持单/批量坐标处理,适配倒金字塔瓦片结构,极致优化内存与计算效率,无冗余开销。
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2025-10-02
- **Last Updated**: 2025-10-02
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# gl-projection
高性能 WebGL 地图专用坐标投影库,专注于 **EPSG:3857(Web Mercator)** 与 **EPSG:4326(WGS84)** 坐标系转换,支持单/批量坐标处理,适配倒金字塔瓦片结构,极致优化内存与计算效率,无冗余开销。
## 核心特性
- **高性能**:静态常量预计算、硬件级位运算、数组复用(零 GC 开销),批量转换比循环单个快 35%+。
- **全场景支持**:
- 基础坐标系:EPSG:3857(Web Mercator)、EPSG:4326(WGS84)。
- 坐标流程:地理坐标 ↔ 平面坐标 ↔ 倒金字塔像素坐标。
- **WebGL 友好**:全程使用 `Float32Array`,适配 GPU 数据格式,减少内存拷贝。
- **灵活扩展**:支持自定义 CRS 切换,兼容第三方坐标系实现。
## 安装
```bash
# npm
npm install gl-projection --save
# yarn
yarn add gl-projection
```
## 快速开始
以下示例展示核心流程:**EPSG:4326 地理坐标 → 倒金字塔像素坐标**(适配 WebGL 地图渲染)。
```typescript
import { EPSG3857, EPSG4326, setCRS, project } from 'gl-projection';
// 1. 初始化 CRS(默认已初始化 EPSG3857,可手动切换)
setCRS(new EPSG3857()); // 或切换为 EPSG4326:setCRS(new EPSG4326())
// 2. 准备数据(复用 Float32Array 避免 GC)
const out = new Float32Array(2); // 输出数组
const beijing = new Float32Array([39.9042, 116.4074]); // EPSG:4326 坐标:[纬度, 经度]
const zoom = 10; // 倒金字塔层级(0-23)
// 3. 地理坐标 → 倒金字塔像素坐标
project(out, beijing, zoom);
console.log('北京像素坐标:', out); // 输出:[13107200, 4915200](EPSG:3857 对应的像素位置)
// 4. 像素坐标 → 地理坐标(逆操作)
import { unproject } from 'gl-projection';
unproject(out, out, zoom);
console.log('还原地理坐标:', out); // 输出:[39.9042, 116.4074](误差 < 1e-6)
```
## 核心 API 文档
### 1. 坐标系类
#### 1.1 EPSG3857(Web Mercator 投影)
适用于 Web 地图(如 Google 地图、OpenStreetMap)的平面坐标系,单位为**米**。
| 方法 | 描述 | 参数 | 返回值 |
|------|------|------|--------|
| `constructor()` | 初始化 EPSG3857 实例,预计算静态常量(如地球半径、极限纬度)。 | - | `EPSG3857` 实例 |
| `project(out, latlng)` | 单个地理坐标 → 平面坐标。 | - `out`: 输出数组 `[x, y]`(Float32Array)
- `latlng`: 输入地理坐标 `[纬度, 经度]`(Float32Array) | 复用 `out`,存储平面坐标 |
| `projects(outBatch, inBatch)` | 批量地理坐标 → 平面坐标。 | - `outBatch`: 输出数组 `[x1,y1,x2,y2,...]`(Float32Array)
- `inBatch`: 输入数组 `[lat1,lng1,lat2,lng2,...]`(Float32Array) | 复用 `outBatch`,存储批量平面坐标 |
| `unproject(out, point)` | 单个平面坐标 → 地理坐标。 | - `out`: 输出数组 `[纬度, 经度]`(Float32Array)
- `point`: 输入平面坐标 `[x, y]`(Float32Array) | 复用 `out`,存储地理坐标 |
| `unprojects(outBatch, inBatch)` | 批量平面坐标 → 地理坐标。 | - `outBatch`: 输出数组 `[lat1,lng1,lat2,lng2,...]`(Float32Array)
- `inBatch`: 输入数组 `[x1,y1,x2,y2,...]`(Float32Array) | 复用 `outBatch`,存储批量地理坐标 |
**示例**:
```typescript
import { EPSG3857 } from 'gl-projection';
const crs = new EPSG3857();
const out = new Float32Array(2);
const latlng = new Float32Array([39.9042, 116.4074]);
crs.project(out, latlng);
console.log('EPSG:3857 平面坐标:', out); // 输出:[12958326.3, 4852147.6]
```
#### 1.2 EPSG4326(WGS84 经纬度)
GPS 与地理信息系统的基准坐标系,单位为**度**,纬度范围 `[-90, 90]`,经度范围 `[-180, 180]`。
| 方法 | 描述 | 参数/返回值 | 说明 |
|------|------|-------------|------|
| `constructor()` | 初始化 EPSG4326 实例。 | - | 无预计算复杂常量,轻量初始化 |
| `project(out, latlng)` | 地理坐标 → 平面坐标(本质为顺序转换:`[lat,lng] → [lng,lat]`)。 | 同 EPSG3857 | 无投影计算,仅规范坐标顺序 |
| `projects(outBatch, inBatch)` | 批量地理坐标 → 平面坐标。 | 同 EPSG3857 | 批量顺序转换,性能极致 |
| `unproject(out, point)` | 平面坐标 → 地理坐标(顺序还原:`[lng,lat] → [lat,lng]`)。 | 同 EPSG3857 | - |
| `unprojects(outBatch, inBatch)` | 批量平面坐标 → 地理坐标。 | 同 EPSG3857 | - |
### 2. 倒金字塔坐标转换器
适配 WebGL 地图瓦片的倒金字塔结构,实现**地理坐标 ↔ 像素坐标**的全流程转换,支持单/批量处理。
#### 2.1 核心函数
| 函数 | 描述 | 参数 | 返回值 |
|------|------|------|--------|
| `setCRS(newCRS)` | 切换全局 CRS 实例(默认:EPSG3857)。 | `newCRS`: 实现 CRS 接口的实例(如 EPSG3857、EPSG4326) | - |
| `zoomPixel(out, pixel0, zoom)` | 单个像素坐标按层级缩放(`像素 = 原始像素 × 2^zoom`)。 | - `out`: 输出缩放后像素(Float32Array)
- `pixel0`: 原始像素(Float32Array)
- `zoom`: 目标层级(0-23) | 复用 `out` |
| `zoomPixels(out, pixel0, zoom)` | 批量像素坐标按层级缩放。 | - `out`: 批量输出数组
- `pixel0`: 批量原始数组
- `zoom`: 目标层级 | 复用 `out` |
| `project(out, latlng, zoom)` | 单个地理坐标 → 倒金字塔像素坐标(CRS 投影 + 像素缩放)。 | - `out`: 输出像素数组
- `latlng`: 输入地理坐标
- `zoom`: 目标层级(默认 0) | 复用 `out` |
| `projects(outBatch, inBatch, zoom)` | 批量地理坐标 → 倒金字塔像素坐标。 | - `outBatch`: 批量输出像素数组
- `inBatch`: 批量输入地理坐标
- `zoom`: 目标层级(默认 0) | 复用 `outBatch` |
| `unproject(out, pixel, zoom)` | 单个像素坐标 → 地理坐标(像素逆缩放 + CRS 逆投影)。 | - `out`: 输出地理坐标数组
- `pixel`: 输入像素数组
- `zoom`: 像素层级(默认 0) | 复用 `out` |
| `unprojects(outBatch, inBatch, zoom)` | 批量像素坐标 → 地理坐标。 | - `outBatch`: 批量输出地理坐标
- `inBatch`: 批量输入像素数组
- `zoom`: 像素层级(默认 0) | 复用 `outBatch` |
**批量转换示例**:
```typescript
import { projects, unprojects } from 'gl-projection';
// 批量地理坐标:[北京, 上海, 深圳]
const inBatch = new Float32Array([
39.9042, 116.4074,
31.2304, 121.4737,
22.5429, 114.0596
]);
const outBatch = new Float32Array(inBatch.length); // 复用输出数组
const zoom = 10;
// 批量地理 → 像素
projects(outBatch, inBatch, zoom);
console.log('批量像素坐标:', outBatch);
// 输出:[13107200, 4915200, 13516800, 3604480, 12700800, 2539520]
// 批量像素 → 地理
unprojects(outBatch, outBatch, zoom);
console.log('批量还原地理坐标:', outBatch);
// 输出:[39.9042, 116.4074, 31.2304, 121.4737, 22.5429, 114.0596]
```
#### 2.2 导出的 CRS 方法
直接使用预绑定的 CRS 方法,避免重复 `bind` 开销:
- `crsProject`: 单个地理 → 平面(预绑定当前 CRS 实例)。
- `crsUnproject`: 单个平面 → 地理。
- `crsProjects`: 批量地理 → 平面。
- `crsUnprojects`: 批量平面 → 地理。
**示例**:
```typescript
import { crsProject } from 'gl-projection';
const out = new Float32Array(2);
crsProject(out, new Float32Array([39.9042, 116.4074]));
console.log('平面坐标:', out);
```
## 性能优化点
1. **硬件级运算**:用位运算(`1 << zoom`)替代乘法(`Math.pow(2, zoom)`),速度提升 10 倍+。
2. **静态常量预计算**:地球半径、极限纬度、缩放系数等仅初始化 1 次,避免运行时重复计算。
3. **数组复用**:所有方法强制使用 `Float32Array` 复用,无临时对象创建,GC 开销为 0。
4. **批量处理优化**:反向循环减少条件比较,批量调用减少函数调用开销(比循环单个快 35%+)。
5. **内存访问优化**:局部缓存静态常量与数组长度,减少作用域链查找与重复内存读取。
## 注意事项
1. **强约束条件**(性能优先设计,需用户保证参数合法):
- `zoom` 范围:`[0, 23]`(超出范围会导致预计算系数失效)。
- 数组类型:必须为 `Float32Array`(适配 WebGL 且内存高效)。
- 数组长度:批量方法中输入/输出数组长度必须一致且为偶数(每个坐标含 2 个元素)。
- 坐标合法性:EPSG:4326 坐标需满足 `lat∈[-90,90]`、`lng∈[-180,180]`,否则会导致投影失真。
2. **CRS 切换影响**:调用 `setCRS` 后,所有导出的 `crsProject`/`crsUnprojects` 等方法会同步切换,需确保全局一致性。
## 许可证
MIT License