s3m-maplibre 0.2.11 → 0.3.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.
Files changed (127) hide show
  1. package/README.md +13 -382
  2. package/dist/MapLibreGeoAdapter.d.ts +75 -0
  3. package/dist/MapLibreGeoAdapter.d.ts.map +1 -0
  4. package/dist/MapLibreGeoAdapter.js +61 -0
  5. package/dist/MapLibreGeoAdapter.js.map +1 -0
  6. package/dist/S3MLayer.d.ts +212 -0
  7. package/dist/S3MLayer.d.ts.map +1 -0
  8. package/dist/S3MLayer.js +497 -0
  9. package/dist/S3MLayer.js.map +1 -0
  10. package/dist/index.d.ts +13 -32
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +11 -23
  13. package/dist/index.js.map +1 -1
  14. package/docs/API.md +82 -470
  15. package/package.json +8 -30
  16. package/src/MapLibreGeoAdapter.ts +120 -0
  17. package/src/S3MLayer.ts +653 -0
  18. package/src/index.ts +18 -97
  19. package/dist/core/AttributeQuery.d.ts +0 -97
  20. package/dist/core/AttributeQuery.d.ts.map +0 -1
  21. package/dist/core/AttributeQuery.js +0 -221
  22. package/dist/core/AttributeQuery.js.map +0 -1
  23. package/dist/core/BinaryReader.d.ts +0 -38
  24. package/dist/core/BinaryReader.d.ts.map +0 -1
  25. package/dist/core/BinaryReader.js +0 -88
  26. package/dist/core/BinaryReader.js.map +0 -1
  27. package/dist/core/CRNDecode.d.ts +0 -13
  28. package/dist/core/CRNDecode.d.ts.map +0 -1
  29. package/dist/core/CRNDecode.js +0 -84
  30. package/dist/core/CRNDecode.js.map +0 -1
  31. package/dist/core/DXTTextureDecode.d.ts +0 -21
  32. package/dist/core/DXTTextureDecode.d.ts.map +0 -1
  33. package/dist/core/DXTTextureDecode.js +0 -236
  34. package/dist/core/DXTTextureDecode.js.map +0 -1
  35. package/dist/core/FeatureInfo.d.ts +0 -45
  36. package/dist/core/FeatureInfo.d.ts.map +0 -1
  37. package/dist/core/FeatureInfo.js +0 -125
  38. package/dist/core/FeatureInfo.js.map +0 -1
  39. package/dist/core/MeshOpt.d.ts +0 -88
  40. package/dist/core/MeshOpt.d.ts.map +0 -1
  41. package/dist/core/MeshOpt.js +0 -336
  42. package/dist/core/MeshOpt.js.map +0 -1
  43. package/dist/core/S3MBParser.d.ts +0 -27
  44. package/dist/core/S3MBParser.d.ts.map +0 -1
  45. package/dist/core/S3MBParser.js +0 -503
  46. package/dist/core/S3MBParser.js.map +0 -1
  47. package/dist/core/TextureFormat.d.ts +0 -44
  48. package/dist/core/TextureFormat.d.ts.map +0 -1
  49. package/dist/core/TextureFormat.js +0 -97
  50. package/dist/core/TextureFormat.js.map +0 -1
  51. package/dist/core/types.d.ts +0 -235
  52. package/dist/core/types.d.ts.map +0 -1
  53. package/dist/core/types.js +0 -2
  54. package/dist/core/types.js.map +0 -1
  55. package/dist/render/EdgeLines.d.ts +0 -69
  56. package/dist/render/EdgeLines.d.ts.map +0 -1
  57. package/dist/render/EdgeLines.js +0 -293
  58. package/dist/render/EdgeLines.js.map +0 -1
  59. package/dist/render/GeometryBuilder.d.ts +0 -56
  60. package/dist/render/GeometryBuilder.d.ts.map +0 -1
  61. package/dist/render/GeometryBuilder.js +0 -684
  62. package/dist/render/GeometryBuilder.js.map +0 -1
  63. package/dist/render/OrthoProjection.d.ts +0 -84
  64. package/dist/render/OrthoProjection.d.ts.map +0 -1
  65. package/dist/render/OrthoProjection.js +0 -141
  66. package/dist/render/OrthoProjection.js.map +0 -1
  67. package/dist/render/Picker.d.ts +0 -43
  68. package/dist/render/Picker.d.ts.map +0 -1
  69. package/dist/render/Picker.js +0 -266
  70. package/dist/render/Picker.js.map +0 -1
  71. package/dist/render/S3MLayer.d.ts +0 -679
  72. package/dist/render/S3MLayer.d.ts.map +0 -1
  73. package/dist/render/S3MLayer.js +0 -2353
  74. package/dist/render/S3MLayer.js.map +0 -1
  75. package/dist/render/StyleMaterial.d.ts +0 -109
  76. package/dist/render/StyleMaterial.d.ts.map +0 -1
  77. package/dist/render/StyleMaterial.js +0 -451
  78. package/dist/render/StyleMaterial.js.map +0 -1
  79. package/dist/render/TextureFactory.d.ts +0 -33
  80. package/dist/render/TextureFactory.d.ts.map +0 -1
  81. package/dist/render/TextureFactory.js +0 -117
  82. package/dist/render/TextureFactory.js.map +0 -1
  83. package/dist/tileset/S3MTileset.d.ts +0 -118
  84. package/dist/tileset/S3MTileset.d.ts.map +0 -1
  85. package/dist/tileset/S3MTileset.js +0 -371
  86. package/dist/tileset/S3MTileset.js.map +0 -1
  87. package/dist/vendor/crunch_decoder.module.js +0 -1140
  88. package/dist/vendor/meshopt_decoder.module.js +0 -118
  89. package/docs/index.html +0 -1596
  90. package/src/core/AttributeQuery.ts +0 -268
  91. package/src/core/BinaryReader.ts +0 -116
  92. package/src/core/CRNDecode.ts +0 -107
  93. package/src/core/DXTTextureDecode.ts +0 -260
  94. package/src/core/FeatureInfo.ts +0 -150
  95. package/src/core/MeshOpt.ts +0 -401
  96. package/src/core/S3MBParser.ts +0 -590
  97. package/src/core/TextureFormat.ts +0 -103
  98. package/src/core/types.ts +0 -222
  99. package/src/render/EdgeLines.ts +0 -343
  100. package/src/render/GeometryBuilder.ts +0 -825
  101. package/src/render/OrthoProjection.ts +0 -189
  102. package/src/render/Picker.ts +0 -293
  103. package/src/render/S3MLayer.ts +0 -2814
  104. package/src/render/StyleMaterial.ts +0 -514
  105. package/src/render/TextureFactory.ts +0 -134
  106. package/src/tileset/S3MTileset.ts +0 -428
  107. package/src/vendor/crunch_decoder.module.d.ts +0 -27
  108. package/src/vendor/crunch_decoder.module.js +0 -1140
  109. package/src/vendor/meshopt_decoder.module.d.ts +0 -31
  110. package/src/vendor/meshopt_decoder.module.js +0 -118
  111. package/tools/build-docs.mjs +0 -683
  112. package/tools/copy-assets.mjs +0 -28
  113. package/tools/crn-probe.mjs +0 -313
  114. package/tools/e2e.mjs +0 -78
  115. package/tools/lod-probe.mjs +0 -60
  116. package/tools/meshopt-check.mjs +0 -242
  117. package/tools/official-oracle.mjs +0 -54
  118. package/tools/parse-sample.mjs +0 -95
  119. package/tools/serve.mjs +0 -182
  120. package/tools/test-batch-texmatrix.mjs +0 -221
  121. package/tools/test-instanced.mjs +0 -207
  122. package/tools/test-new-features.mjs +0 -246
  123. package/tools/test-ortho.mjs +0 -447
  124. package/tools/test-parser.mjs +0 -203
  125. package/tools/test-regressions.mjs +0 -483
  126. package/tools/test-texture-format.mjs +0 -58
  127. package/tools/trace-one.mjs +0 -93
package/README.md CHANGED
@@ -1,69 +1,8 @@
1
1
  # s3m-maplibre
2
2
 
3
- **在 MapLibre GL JS 里原生渲染 SuperMap S3M 三维模型** —— 浏览器直接解析 `.s3mb` 瓦片,不需要预先转成 3D Tiles,也不需要 SuperMap 的 WebGL 客户端。
3
+ SuperMap S3M 三维模型格式的 **MapLibre / Mapbox 原生渲染图层**。
4
4
 
5
- [![npm](https://img.shields.io/npm/v/s3m-maplibre?color=blue&label=npm)](https://www.npmjs.com/package/s3m-maplibre)
6
- [![docs](https://img.shields.io/badge/docs-online-38bdf8)](https://joo1es.github.io/s3m-maplibre/docs/index.html)
7
- [![demo](https://img.shields.io/badge/demo-online-2ea44f)](https://joo1es.github.io/s3m-maplibre/demo/index.html)
8
- [![license](https://img.shields.io/badge/license-Apache--2.0-green)](./LICENSE)
9
- [![types](https://img.shields.io/badge/types-included-blue)](./src/index.ts)
10
-
11
- ---
12
-
13
- ## 为什么需要它
14
-
15
- SuperMap 的 S3M(Spatial 3D Model)是国内 GIS 项目里非常常见的三维格式,iServer 的 `realspace` 服务默认就发布成 S3M。但它和 MapLibre / Mapbox 生态是断开的:
16
-
17
- - 官方只有 Cesium 系的 WebGL 客户端;
18
- - 转 3D Tiles 是离线批处理,数据一更新就得重跑,做不到实时;
19
- - 转出来的 3D Tiles 还要再丢一次精度。
20
-
21
- 这个库走的是**第二条路**:在浏览器里直接解析 S3MB 二进制,用 three.js 画在 MapLibre 的自定义图层上。数据更新即时可见,不需要任何预处理。
22
-
23
- ```
24
- iServer / 本地目录 → .scp 配置 + .s3mb 瓦片
25
- ↓ fetch + 解压 + 二进制解析
26
- three.js 几何 + 材质
27
- ↓ ENU → Web Mercator
28
- MapLibre custom layer (3d)
29
- ```
30
-
31
- ---
32
-
33
- ## 能力
34
-
35
- | 能力 | 状态 | 说明 |
36
- |---|---|---|
37
- | S3MB 解析 | ✅ | v1.0 / v2.0 / v3.0,9 个官方样例字节级对齐 |
38
- | MeshOpt 几何压缩 | ✅ | v3 默认压缩方式,浏览器内 wasm 解码,按需加载 |
39
- | LOD 渐进加载 | ✅ | 支持 `Distance_From_EyePoint` / `Pixel_Size_OnScreen` |
40
- | 多数据集叠加 | ✅ | 各数据集独立锚点,自动对齐到统一场景原点 |
41
- | 白膜 / 单色 | ✅ | |
42
- | 按高度 / 按楼层着色 | ✅ | 高度范围自动统计 |
43
- | 按单体着色 | ✅ | 基于 S3M 单体化信息 |
44
- | 按业务字段着色 | ✅ | 走 iServer 数据服务查 SMID 属性,分类 / 色带 / 分级,见 [docs/API.md](./docs/API.md#按业务字段着色) |
45
- | 按业务字段过滤 / 抬高 | ✅ | 区间 / 取值 / 谓词过滤,字段值映射成抬高米数,同样只改一张一维纹理 |
46
- | 动态扫描 | ✅ | 扫描线沿高度循环 |
47
- | 透明度 | ✅ | 实时,不重编译着色器 |
48
- | 选中高亮 + 描边 | ✅ | 单体级 |
49
- | 全局棱线 | ✅ | 优先用数据自带棱线包,没有才 CPU 现算 |
50
- | 单体级点选 + 属性 | ✅ | GPU 拾取,代价与面数无关;支持 `pickPosition()` 返回精确表面交点与世界坐标 |
51
- | 穿透拾取 drillPick | ✅ | 沿视线方向穿透拾取多个单体并按深度排序返回 |
52
- | 单体包围盒与飞向 | ✅ | `getFeatureBounds(smid)` 与 `flyToFeature(smid)` 聚焦单体 |
53
- | 单体三维平移 | ✅ | 状态纹理 2 行存储,支持任意 `[dx, dy, dz]` 平移与着色器/拾取/描边全链路同步 |
54
- | LOD 细化倍率 | ✅ | `lodRangeScale` 运行时动态调节粗细模判定阈值 |
55
- | 实例化几何 | ✅ | `instanceMode` 16 / 17 |
56
- | 正交投影 | ✅ | 可选开关(`projection: 'orthographic'`),默认透视;需 MapLibre ≥ 5,正交时底图 / 地形 / marker 需 App 退出,见[正交投影](#正交投影) |
57
- | 瓦片同材质合批 | ✅ | 倾斜摄影大瓦片自动合批,大幅降低 DrawCall |
58
- | 纹理变换与寻址 | ✅ | 支持 `texmodmatrix` 仿射变换与 `addressmode` |
59
- | DXT / WebP 纹理 | ✅ | |
60
- | 骨骼动画 | ❌ | 未实现:LODPackage 上的 animations JSON 直接跳过不解析,官方 JS SDK 同样只读偏移不驱动 |
61
- | 地形遮挡 | ❌ | |
62
- | Draco 压缩几何 | ❌ | 能识别、不能解码,遇到抛明确错误;接法见[未支持的格式](#未支持的格式draco--crn--ktx2) |
63
- | CRN 纹理(`compressType` 26 / 27 / 38001 / 50000) | ✅ | 内联 crunch wasm 转 DXT 后走同一套解码,只在遇到时懒加载;已在 SuperMap Online 公有服务实测 |
64
- | KTX2 纹理 | — | S3M 官方 `pixelFormat` 枚举里没有这个值,属于「不会遇到」而不是「不支持」 |
65
-
66
- ---
5
+ 在 MapLibre GL JS 里直接解析 `.s3mb` 瓦片并渲染,不需要预先转成 3D Tiles,也不需要 SuperMap 的 WebGL 客户端。渲染能力来自 [`s3m-three`](https://www.npmjs.com/package/s3m-three)(安装本包会自动带上)。
67
6
 
68
7
  ## 安装
69
8
 
@@ -71,335 +10,27 @@ iServer / 本地目录 → .scp 配置 + .s3mb 瓦片
71
10
  npm install s3m-maplibre three
72
11
  ```
73
12
 
74
- 包在 npm 上是 [s3m-maplibre](https://www.npmjs.com/package/s3m-maplibre),当前 `0.2.8`。
75
-
76
- `three` 是 peer 依赖(`>=0.168.0`)。`maplibre-gl` 不是依赖——图层只是一个符合 `CustomLayerInterface` 的普通对象,MapLibre / Mapbox 都能挂;不用地图时也能只用解析和瓦片层(见「纯 three.js 使用」)。
77
-
78
- 类型随包发布(`dist/index.d.ts`,由源码直接生成)。three `>=0.168` 自带类型,更老的版本需要自己装 `@types/three`。
79
-
80
- ---
13
+ `three` 是 peer 依赖(`>=0.168.0`)。`maplibre-gl` 不是依赖——图层只是一个符合 `CustomLayerInterface` 的普通对象,MapLibre GL JS v4/v5 与 Mapbox GL JS v2/v3 都能挂。
81
14
 
82
- ## 快速开始
15
+ ## 30 秒上手
83
16
 
84
17
  ```js
85
- import maplibregl from 'maplibre-gl';
86
- import { S3MLayer, STYLE } from 's3m-maplibre';
87
-
88
- const map = new maplibregl.Map({
89
- container: 'map',
90
- style: 'https://demotiles.maplibre.org/style.json',
91
- center: [121.4739, 31.244],
92
- zoom: 16.5,
93
- pitch: 60,
94
- antialias: true, // 建筑边缘需要抗锯齿
95
- });
18
+ import { S3MLayer } from 's3m-maplibre';
96
19
 
97
20
  const layer = new S3MLayer({
98
- datasets: [
99
- {
100
- id: 'jingmo',
101
- name: '精模',
102
- configUrl: 'https://host/iserver/services/svc/rest/realspace/datas/jingmo/data/path/jingmo.scp',
103
- },
104
- ],
105
- style: { mode: STYLE.WHITE, opacity: 0.92 },
106
- onPick: (f) => console.log(f?.smid, f?.height, f?.floors),
107
- });
108
-
109
- map.on('load', () => map.addLayer(layer));
110
- ```
111
-
112
- ### 叠加多个数据集 + 换着色
113
-
114
- ```js
115
- const layer = new S3MLayer({
116
- datasets: [
117
- { id: 'zhoubian', name: '周边底模', configUrl: '.../zhoubian.scp' },
118
- { id: 'jingmo', name: '精模', configUrl: '.../jingmo.scp' },
119
- ],
120
- maxTiles: 48,
121
- });
122
-
123
- await layer.addDataset({ id: 'cheng', name: 'cheng', configUrl: '.../cheng.scp' });
124
-
125
- layer.setStyle({ mode: STYLE.HEIGHT, colorA: '#e2e8f0', colorB: '#1d4ed8' });
126
- layer.setDatasetVisible('zhoubian', false);
127
- layer.setEdges(true);
128
- ```
129
-
130
- ### 点选
131
-
132
- ```js
133
- map.on('click', (e) => {
134
- const f = layer.pickFromEvent(e);
135
- if (!f) return layer.select(null);
136
- layer.select(f);
137
- console.log(`${f.datasetName} · SMID ${f.smid} · ${f.height}m · ${f.floors}层`);
138
- });
139
- ```
140
-
141
- 完整接口见 **[开发指南与 API 文档(在线网页)](https://joo1es.github.io/s3m-maplibre/docs/index.html)** 或本地 **[docs/API.md](./docs/API.md)**。
142
-
143
- ---
144
-
145
- ## 演示与在线文档
146
-
147
- 在线体验与文档(GitHub Pages,数据随仓库一起发布):
148
-
149
- - **📚 完整开发指南 & API 文档** — <https://joo1es.github.io/s3m-maplibre/docs/index.html>
150
- - **🗺️ MapLibre 版演示** — <https://joo1es.github.io/s3m-maplibre/demo/index.html>
151
- - **🧊 纯 three.js 版演示** — <https://joo1es.github.io/s3m-maplibre/demo/three.html>
152
- - **🏠 Pages 导航入口** — <https://joo1es.github.io/s3m-maplibre/>
153
-
154
- 本地跑:
155
-
156
- ```bash
157
- npm run dev # 开发模式:tsc -w + 静态服务,保存源码后浏览器自动刷新
158
- npm run demo # 一次性编译后起静态服务(不做监听)
159
- ```
160
-
161
- 两个命令都指向 http://localhost:8123/s3m-maplibre/demo/index.html ,`demo/three.html` 是同一台服务器上的纯 three 版。
162
-
163
- 演示自带两份本地样例数据(北京 CBD 的 CCTV、comModel,离线可用),另有一个在线预设「地铁站 (CRN 纹理)」——SuperMap Online 公有服务,纹理全是 CRN,用来肉眼验证 CRN 转码链路;也可以在地址栏输入框里填任意 iServer `realspace` 服务根地址、`datas` 集合或具体的 `.scp`,自动列出数据集并默认勾选第一个。
164
-
165
- 演示包含:数据集叠加开关、着色模式、透明度、平面/平滑着色、选中描边(棱线 / 外扩两种画法,粗细可调)、全局棱线、点击属性卡;右侧面板还能填 iServer 数据服务地址,按业务字段(KEYID / SmMaxZ…)上色出图例、按区间过滤、按字段值抬高。
166
-
167
- 「投影」分组里的**正交投影**勾选框(或 `?ortho=1`)会把 S3M 层切成正交相机——pan / zoom / pitch / 拾取 / 选中全部照常,勾选时自动隐藏底图(正交层和透视底图对不齐,见[正交投影](#正交投影))。演示内置的是 MapLibre GL JS v5.0.0(`demo/vendor/`),正交需要的独立投影矩阵从 v5 开始才有。
168
-
169
- ---
170
-
171
- ## 纯 three.js 使用(不用 MapLibre)
172
-
173
- 可以。图层本身只是把三层粘到地图上,这三层都是宿主无关的:
174
-
175
- | 层 | 需要什么 | 与地图的关系 |
176
- |---|---|---|
177
- | `core/` 解析 | 一个 `ArrayBuffer` | 完全无关,Node 里也能跑 |
178
- | `tileset/` 瓦片树 | `fetch` + 一个 `three.Group` 当容器 | 只要喂相机位置算 LOD |
179
- | `render/` 几何 | WebGL 上下文 | 只产出 `THREE.Group` / `Mesh` |
180
-
181
- ```js
182
- import * as THREE from 'three';
183
- import { S3MTileset, createSharedUniforms, STYLE } from 's3m-maplibre';
184
-
185
- const uniforms = createSharedUniforms(); // 材质 uniform 全局共享
186
- uniforms.uMode.value = STYLE.TEXTURE; // 改这一行就是切样式
187
-
188
- const root = new THREE.Group();
189
- root.rotation.x = -Math.PI / 2; // S3M 顶点是 ENU(z 朝上),three 是 y 朝上
190
- scene.add(root);
191
-
192
- const tileset = new S3MTileset({
193
- configUrl: '.../jingmo.scp',
194
- uniforms,
195
- onTile: (node) => root.add(node.group), // node.group 就是这片瓦片拼好的 Group(米制局部坐标)
21
+ configUrl: 'https://host/.../3D-local3DCache-xxx/rest/realspace/datas/Xxx/config',
22
+ style: { mode: 'texture' },
23
+ onPick: (r) => console.log(r?.smid, r?.lngLat),
196
24
  });
197
- await tileset.init(); // 返回时首棵瓦片已就绪
198
-
199
- // 每帧:把相机位置换算回 ENU 喂给 LOD 调度,父子瓦片自己按需细分
200
- function tick() {
201
- const p = camera.position;
202
- tileset.update([p.x, -p.z, p.y], THREE.MathUtils.degToRad(camera.fov), renderer.domElement.height);
203
- renderer.render(scene, camera);
204
- requestAnimationFrame(tick);
205
- }
206
- ```
207
-
208
- 完整可运行版本见 [`demo/three.js`](./demo/three.js)(一个文件,含轨道控制、切片统计、样式切换)。
209
-
210
- 自己搭宿主时需要补的几件事,`S3MLayer` 不会代劳:
211
-
212
- - **光照**:`MeshStandardMaterial` 的标准光照,自己加 `HemisphereLight` + `DirectionalLight`;
213
- - **多数据集对齐**:每份数据有各自的锚点,`S3MLayer` 会按墨卡托算锚点差、写进数据集 `Group.position`(米),纯 three 里需要自己算一次;
214
- - **贴地 / 经纬度**:不接地图就没有「贴在地球上」这一步,只有局部米制坐标;
215
- - **拾取 / 选中描边 / 样式切换 UI**:`Picker`、等宽棱线、`setStyle` 都是 `S3MLayer` 上的,纯 three 用法需要直接操作 `uniforms` 与 Mesh。
216
-
217
- ---
218
-
219
- ## 未支持的格式:Draco / KTX2
220
-
221
- 这三个常被问到,结论分别不同:
222
-
223
- **Draco 压缩几何 —— 能解决,缺的是样本。**
224
- 官方 SDK 里有 `S3MParser/S3MDracoDecode.js` + `draco_decode.module.js`(对 `DecodeBufferToPointCloud` 的封装,POSITION / NORMAL / TEX_COORD 三个属性,再按 `compressOptions` 分支处理)。接法与本项目的 MeshOpt 完全一致:内联 wasm 解码器、只在遇到 `VertexTag.DRACO` 时动态 `import`、解码后走同一套 attribute 组装 + 量化还原。真正的成本不在写代码,而在**标定容器**——MeshOpt 当时就是靠 60 个真实瓦片逐字节对齐才做对的,Draco 的 attribute 映射、`compressOptions` 与实际数据是否一致也必须拿样例验。仓库里没有 Draco 瓦片,所以现在是「识别到就抛明确错误」。
225
-
226
- **CRN 纹理 —— 已支持,并在真实服务上验过。**
227
- `src/vendor/crunch_decoder.module.js`(crunch 的 emscripten 胶水,wasm 内联成 base64,只在真的遇到 CRN 时动态 import)把 CRN 转回 DXT 块,再走现成的 DXT1/3/4/5 解码;具体是 DXT1 还是 DXT5 由 CRN 头部给出。判定逻辑收敛在 `src/core/TextureFormat.ts`,单测钉死 25 条断言。
228
-
229
- **关键点:「是不是 CRN」看 `compressType`,不能看 `pixelFormat`。** 实测到的三组组合(SuperMap Online 公有服务):
230
-
231
- | 数据版本 | compressType | pixelFormat | 实际内容 |
232
- |:---|:---|:---|:---|
233
- | v3.00 | `26`(CRN_DXT5) | `13`(ABGR,无意义) | CRN,数据以 `Hx` 开头 |
234
- | v3.00 | `14`(噪声) | `21` | DXT5 裸块 |
235
- | v3.01(行标) | `50000`(TC_CRN_DXT5) | `32856`(GL_RGBA8) | CRN,数据以 `Hx` 开头 |
236
-
237
- 早期版本按 `pixelFormat === 26 / 27` 判断,真实服务里的 CRN 纹理会被当成未知格式整包丢掉——表现就是**模型能出来,但全是灰模**。现在先看 `compressType`(`26 / 27 / 38001 / 50000`),认不出来才退回 `pixelFormat`;另外 `transcodeCRN` 会先验 `Hx` 魔数,避免把误标的 DXT 数据喂进 crunch 解出一个「尺寸看着合理」的垃圾块。
238
-
239
- 验证方式:
240
-
241
- ```bash
242
- npm run probe:crn -- --crn https://host/iserver/services/svc/rest/realspace/datas/<数据集>/config --limit 3
243
- # 也可以先摸底:--service <realspace 根地址> 列出每个数据集的 s3m:TextureCompressionType
244
- ```
245
-
246
- 探针会对每张 CRN 纹理报告「尺寸是否与纹理头一致 / 解出的色数 / 邻域粗糙度」,并打一张 ASCII 灰度预览,用来判断熵解码是否真的解对了(解错会是一屏噪声)。已跑过的数据:`3D-BianDianZhan3`(512²,v3.00)、`3D-BIMTreeModel` / `3D-local3DCache-SubwayStationCombined`(32² / 64²,v3.01)、`3D-scyx`(1024²),除「数据本身标错」外全部尺寸吻合、预览有真实结构。
247
-
248
- **KTX2 —— 不是「不支持」,是 S3M 里基本不会出现。**
249
- 官方 `S3MPixelFormat` 枚举(`1/2/3/4/5/6/7/10/11/12/13/14/17…21/25/26/27/28`)里没有 KTX2 / Basis 的条目,iServer 也不会发。真要支持,得自己引入 `basis_transcoder.wasm` 并把 KTX2 容器转成 RGBA32 或 DXT,但那是给「别人转成 KTX2 再塞进 S3M」的场景准备的,没有数据样本可测。
250
-
251
- 共同前提:**要有样例数据**。手头有 Draco 压缩的瓦片,把 `.s3mb` 给我,就能按 MeshOpt 那套方式标定 + 实现 + 回归(CRN 的代码已经接好,只差真样本验一遍熵解码)。
252
-
253
- ---
254
-
255
- ## 工作原理
256
-
257
- ### 解析
258
-
259
- S3MB 是「文件头 + 压缩段」结构:`float version` → (v3) `uint32 compressedType` → (v2+) `uint32 uncompressedSize` → `uint32 compressedSize` → 压缩载荷。解压后是严格的顺序流:
260
-
261
- ```
262
- fileOptions
263
- GroupNode → PageLOD[] → Geode[](matrix4d + skeletonNames)
264
- Skeleton[] → VertexDataPackage + IndexPackage[]
265
- Textures / Materials
266
- PickInfo(单体化:SMID → batchId + 顶点区间)
267
- Extensions(v3)
268
- ```
269
-
270
- 解析器是纯 TS,**不依赖 three 和 WebGL**,可以在 Node 里跑,用 `bytesRead === bytesTotal` 自检偏移是否正确。
271
-
272
- ### MeshOpt 压缩几何
273
-
274
- iServer 现在默认用 MeshOpt 压几何(`VertexTag = 2`),瓦片里的顶点流是 meshoptimizer 编码过的量化数据。处理方式:
275
-
276
- - **解码器**直接内联 [meshoptimizer](https://github.com/zeux/meshoptimizer) 0.17 的 wasm 解码器(MIT,约 22KB),只有真的遇到 MeshOpt 瓦片才动态 `import`;
277
- - **容器结构**按真实数据逐字节标定(规范里的 `CompressedDataPackage` 已经落后于 v3.01 的实际数据),量化公式用瓦片自带的 OBB 反推验证:
278
- ```
279
- position = minVerticesValue + uint16 * vertCompressConstant
280
- texcoord = minTexCoordValue[i] + uint16 * texCoordCompressConstant[i]
281
- normal = octDecode(int16 / 32767)
282
- ```
283
- - 官方 `ParseMeshOpt.js` **不能直接搬运**:它被混淆过,而且在描述字符串之后多推进 4 字节,遇到现在 iServer 发的 v3.01 数据必然崩在索引包上。
284
-
285
- ### 索引包类型
286
-
287
- 一个骨架可以带多个索引包,`primitiveType` 决定怎么画:
288
-
289
- | primitiveType | 含义 | 画法 |
290
- |---|---|---|
291
- | 4 | 独立三角形 | `Mesh` |
292
- | 13 | **数据自带的棱线包**(规范里没写,实测就是建筑轮廓线) | `LineSegments` |
293
- | 其他 | 点 / 线 / 条带 | 跳过 |
294
-
295
- 把 13 当三角形画,每条棱线都会被连成一根几十上百米的尖刺 —— 这是踩过的坑,写在这里省下一个人一天。
296
-
297
- ### 坐标
298
-
25
+ map.addLayer(layer);
299
26
  ```
300
- S3M 顶点(数据集局部 ENU,米)
301
- → 数据集 Group 偏移(各锚点对齐到场景锚点)
302
- → L 矩阵:ENU → Web Mercator 归一化
303
- → MapLibre 传入的 mercator→clip
304
- ```
305
-
306
- 场景原点固定在第一个数据集的锚点,顶点只保留「相对锚点的米」——等价于 3D Tiles 的 `RTC_CENTER`,避免 float32 在大坐标下抖动。
307
-
308
- ### 着色
309
-
310
- 所有模式都在同一个 `MeshStandardMaterial` 的片元着色器里用 `uMode` 分支实现,uniform 全局共享。切换样式不重建几何、不重建材质、不重编译着色器。
311
-
312
- ### 拾取
313
-
314
- 「物体编号 + batchId」编码成 RGBA 渲到离屏目标,点击时读那一个像素。代价与三角面数无关,深度测试由 GPU 完成,天然只命中最前面的可见面。
315
-
316
- 离屏目标只有 1×1:viewport 仍是整块画布、原点平移到点击点,整幅画面照常光栅化,只有那一格落在目标上——所以每点一次不是渲染一整屏。
317
-
318
- ### 正交投影
319
-
320
- 可选开关(`projection: 'orthographic'`,默认透视)。MapLibre 没有正交相机,custom layer 每帧拿到的是透视 MVP;但 MapLibre ≥5 会把 `projectionMatrix`(view→clip)和 `modelViewProjectionMatrix`(world→clip)**分开**给,于是视图矩阵可以精确解出来:
321
-
322
- ```
323
- V = P⁻¹ × MVP (反推视图矩阵,不猜、不自建相机)
324
- 正交 MVP = P_ortho · V ,P_ortho 半高 = 相机距 × tan(fov/2)
325
- ```
326
-
327
- 半高取「目标深度处透视视锥的半高」,于是正交与透视在目标平面上逐点重合,zoom 改相机距离 → 距离减半 = 半高减半 = 放大一倍,pan / pitch / rotate 手感与透视完全一致。拾取、选中描边、状态纹理都读同一个相机,自动跟随。MapLibre v4 只给一个合并矩阵,解不出 V,会明确告警并保持透视。
328
27
 
329
- 实现上有个坑:视场角必须用 render() 入参里的 `fov`(弧度)——MapLibre v5 起 `transform.fov` 改成了「度」,当弧度用会让 `tan(fov/2)` 差出 20% 以上(LOD 屏幕误差和正交半高都会错)。
28
+ 多数据集叠加、白膜 / 按高度 / 按单体 / 动态扫描着色、单体级 GPU 拾取与属性查询、选中描边、正交投影等能力的完整文档见 <https://github.com/joo1es/s3m-maplibre>。
330
29
 
331
- **边界(产品决策,不是技术限制)**:正交只覆盖本层。底图瓦片、地形、DOM Marker / 弹窗仍走 MapLibre 自己的透视投影,和正交层差 ≈ 楼高 / 相机距——城市尺度(楼高 100m、相机距 1km)俯视时屋顶线就能差出 ~90px(1080p),带俯仰角时连地面一起撕开(近端可差上千像素)。要用正交,App 需要自行把这些层退出;demo 里的勾选框就是这么干的(勾选即隐藏 `bg` / `osm` 两层)。
332
-
333
- ---
334
-
335
- ## 验证情况
336
-
337
- - **解析正确性**:9 个官方样例(v1 / v2 / v3)全部 `bytesRead === bytesTotal`;并用官方 `S3ModelParser.js` 在 Node 里做逐段偏移对照。
338
- - **MeshOpt 解码**:`npm run test:meshopt` 跑 60 个真实瓦片(5 个数据集 × 根瓦片 + 一级子瓦片),逐项校验偏移对齐、索引不越界、三角形索引数是 3 的倍数、法线归一化、顶点包围盒与 OBB 尺寸一致 —— 60/60 通过。
339
- - **真实服务**:上海某区 iServer `realspace` 服务,S3M 3.01、`epsg:4326`、DXT 纹理压缩、5 个数据集叠加,20 个瓦片 / 45 万三角面稳定 85~90 fps。
340
- - **拾取正确性**:以射线求交为真值,对 135 个像素采样,有效像素 96/96 一致(其余 39 个是两个数据集几何完全重合的平局)。
341
-
342
- ---
343
-
344
- ## 性能
345
-
346
- | 项 | 数值 |
347
- |---|---|
348
- | 45 万三角面 / 20 瓦片 / 1440×900 | 85~90 fps |
349
- | 拾取单次 | < 1 ms(与面数无关) |
350
- | 棱线构建 | 8ms 一帧切片,20 网格约 1.9s 总计,不阻塞交互 |
351
-
352
- 调优建议见 [docs/API.md#性能调优](./docs/API.md#性能调优)。
353
-
354
- ---
355
-
356
- ## 已知限制
357
-
358
- - **Draco 压缩几何**未实现(可解,缺样例数据),见[未支持的格式](#未支持的格式draco--ktx2)。
359
- - **纹理分包(`s3m:TextureSharing`)未支持**:这类数据集的 `tiles` 全是 `.s3mblock`(纹理块文件),不是 `.s3mb` 瓦片,加载会直接失败,例如 SuperMap Online 的 `3D-CBD/Xiaopin@CBD`。目前会如实报错,不做静默降级。
360
- - **多块 MeshOpt 骨架尚未对齐**:`3D-WorkSpace_pbr1/pbrmodel` 里有根瓦片是 `blockCount=2`,第二块的头按现有布局读会错位。单个属性流尺寸会先拦一道、给出可定位的报错,不会抛「Invalid typed array length」。
361
- - **地形遮挡**未实现:MapLibre 的地形深度没进 custom layer 的深度缓冲,建筑不会被地形裁掉。
362
- - 跨城市量级的数据集叠加会重新引入 float32 精度问题。
363
- - 卸载只做了「超上限淘汰」:`maxTiles` 满了会淘汰最久没用的瓦片,但没有做预算式(按显存占用)的主动回收。
364
- - **切线(TANGENT)顶点流不参与渲染**:没有法线贴图通道,所以这条流只跳过不解码;但带它的数据(PBR 一类)不会因此失败。
365
- - **正交投影不覆盖 MapLibre 自己画的内容**:正交模式下底图瓦片、地形、DOM Marker / 弹窗仍是透视投影,和正交层差 ≈ 楼高 / 相机距(城市尺度几十到上百像素),App 需要自行把这些层退出,见[正交投影](#正交投影)。另外正交需要 MapLibre ≥ 5(要拿到独立的投影矩阵),v4 上会告警并保持透视。
366
-
367
- ---
368
-
369
- ## 目录结构
370
-
371
- ```
372
- src/
373
- core/ 解析层(无 three 依赖,Node 可用)
374
- BinaryReader.ts 小端二进制读取
375
- S3MBParser.ts S3MB 结构解析
376
- MeshOpt.ts MeshOpt 几何压缩解码(量化还原 + 八面体法线)
377
- FeatureInfo.ts 单体属性反推
378
- DXTTextureDecode.ts DXT 解码(来自 SuperMap/s3m-spec)
379
- TextureFormat.ts 纹理格式判定(compressType / pixelFormat → 解码路径)
380
- CRNDecode.ts CRN → DXT 转码(crunch wasm,按需加载)
381
- tileset/ 瓦片树 + LOD + 加载调度
382
- render/ three 渲染
383
- S3MLayer.ts 图层主体(多数据集 / 样式 / 拾取)
384
- GeometryBuilder.ts 几何与材质组装
385
- StyleMaterial.ts 着色器注入的着色系统
386
- EdgeLines.ts 屏幕空间等宽棱线(选中描边 / 全局棱线)
387
- OrthoProjection.ts 正交投影:反推视图矩阵 + 正交视锥(纯数学,可单测)
388
- Picker.ts GPU 拾取
389
- TextureFactory.ts 纹理解码
390
- vendor/ meshoptimizer 解码器(wasm 内联,原样保留)
391
- demo/
392
- index.html / main.js MapLibre 完整示例(控制面板 + 属性卡)
393
- three.html / three.js 纯 three.js 示例(无地图)
394
- tools/ 自检脚本(解析校验、MeshOpt 回归、纹理/CRN 探针、带热更新的静态服务)
395
- ```
30
+ 完整 API 见 **[docs/API.md](./docs/API.md)**;样式系统、字段着色、底层解析等内核能力见 [`s3m-three` 的 API 文档](../s3m-three/docs/API.md)。
396
31
 
397
- ---
32
+ 不接地图、只要 three 场景?直接用 `s3m-three` 的 `S3MViewer`。
398
33
 
399
34
  ## 许可
400
35
 
401
- - 本项目 [Apache-2.0](./LICENSE)。
402
- - `src/core/DXTTextureDecode.ts` 来自 [SuperMap/s3m-spec](https://github.com/supermap/s3m-spec)(Apache-2.0)。
403
- - `src/vendor/crunch_decoder.module.js` 是 [crunch](https://github.com/BinomialLLC/crunch) 的 emscripten 构建(经 SuperMap SDK 转发,Apache-2.0);只改了两处:wasm 改为内联字节、Node ESM 下 `__dirname` 兜底。
404
- - `src/vendor/meshopt_decoder.module.js` 是 [meshoptimizer](https://github.com/zeux/meshoptimizer) 官方解码器(MIT,© Arseny Kapoulkine),未做修改。
405
- - S3M 规范文本遵循 CC BY-ND 4.0,不得修改规范文本后再发布。
36
+ Apache-2.0
@@ -0,0 +1,75 @@
1
+ /**
2
+ * MapLibre / Mapbox 宿主适配
3
+ *
4
+ * 把宿主地图的「世界坐标」能力包装成 s3m-three 的 `GeoAdapter` 接口:
5
+ * 1. 从 map.transform / painter / getProjection 里提取 WorldCoordinateHelper
6
+ * (自动适配 MapLibre v5+ CRS 体系与自定义投影、平面直角坐标系);
7
+ * 2. 提不到就回退到标准 Web 墨卡托(MapLibre v4 / Mapbox 的世界坐标就是墨卡托)。
8
+ *
9
+ * 这里只放 MapLibre 相关的东西:鸭子类型的 MapLike、鼠标事件、helper 提取。
10
+ * 纯 three 宿主不需要这个文件 —— 直接用 GeoAdapter 的墨卡托兜底,
11
+ * 或自己实现一个 GeoAdapter 即可。
12
+ */
13
+ import type { GeoAdapter } from 's3m-three';
14
+ /** MapLibre 默认垂直视场角(弧度) */
15
+ export declare const DEFAULT_FOV = 0.6435011087932844;
16
+ /** 宿主地图 WorldCoordinateHelper 用到的子集(MapLibre v5+ / Mapbox) */
17
+ export interface WorldCoordinateHelperLike {
18
+ name?: string;
19
+ worldFromLngLat(lng: number, lat: number, altitude?: number): {
20
+ x: number;
21
+ y: number;
22
+ z?: number;
23
+ };
24
+ lngLatFromWorld(x: number, y: number): {
25
+ lng: number;
26
+ lat: number;
27
+ } | [number, number];
28
+ metersPerWorldUnit?(x: number, y: number): number;
29
+ }
30
+ /** 宿主地图上我们真正用到的能力,MapLibre / Mapbox 的交集 */
31
+ export interface MapLike {
32
+ getCanvas(): HTMLCanvasElement;
33
+ triggerRepaint(): void;
34
+ on(type: string, listener: (e: MapMouseEventLike) => void): unknown;
35
+ off(type: string, listener: (e: MapMouseEventLike) => void): unknown;
36
+ getBearing?(): number;
37
+ getFreeCameraOptions?(): {
38
+ position?: {
39
+ x: number;
40
+ y: number;
41
+ z: number;
42
+ } | null;
43
+ } | null;
44
+ /** 注意 fov 在 MapLibre v5 起是「度」,v4 / Mapbox 是「弧度」;弧度用 fovInRadians */
45
+ transform?: {
46
+ fov?: number;
47
+ fovInRadians?: number;
48
+ cameraToCenterDistance?: number;
49
+ worldCoordinateHelper?: unknown;
50
+ projection?: {
51
+ worldCoordinateHelper?: unknown;
52
+ };
53
+ };
54
+ getProjection?(): unknown;
55
+ }
56
+ export interface MapMouseEventLike {
57
+ originalEvent?: {
58
+ clientX: number;
59
+ clientY: number;
60
+ };
61
+ point?: {
62
+ x: number;
63
+ y: number;
64
+ };
65
+ }
66
+ /**
67
+ * 从宿主地图中提取 WorldCoordinateHelper(自动适配 MapLibre v5+ CRS 体系与自定义投影)
68
+ */
69
+ export declare function extractWorldCoordinateHelper(map: unknown): WorldCoordinateHelperLike | null;
70
+ /**
71
+ * 把宿主地图包装成 s3m-three 的 GeoAdapter。
72
+ * 拿不到 WorldCoordinateHelper 时返回 null,由渲染层回退到标准 Web 墨卡托。
73
+ */
74
+ export declare function createMapLibreGeoAdapter(map: MapLike | null): GeoAdapter | null;
75
+ //# sourceMappingURL=MapLibreGeoAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MapLibreGeoAdapter.d.ts","sourceRoot":"","sources":["../src/MapLibreGeoAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,2BAA2B;AAC3B,eAAO,MAAM,WAAW,qBAAqB,CAAC;AAE9C,8DAA8D;AAC9D,MAAM,WAAW,yBAAyB;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnG,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvF,kBAAkB,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACnD;AAED,2CAA2C;AAC3C,MAAM,WAAW,OAAO;IACtB,SAAS,IAAI,iBAAiB,CAAC;IAC/B,cAAc,IAAI,IAAI,CAAC;IACvB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC;IACpE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC;IACrE,UAAU,CAAC,IAAI,MAAM,CAAC;IACtB,oBAAoB,CAAC,IAAI;QAAE,QAAQ,CAAC,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1F,oEAAoE;IACpE,SAAS,CAAC,EAAE;QACV,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,sBAAsB,CAAC,EAAE,MAAM,CAAC;QAChC,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAChC,UAAU,CAAC,EAAE;YAAE,qBAAqB,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC;KAClD,CAAC;IACF,aAAa,CAAC,IAAI,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,KAAK,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAClC;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,OAAO,GAAG,yBAAyB,GAAG,IAAI,CA0B3F;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,GAAG,UAAU,GAAG,IAAI,CAmC/E"}
@@ -0,0 +1,61 @@
1
+ /** MapLibre 默认垂直视场角(弧度) */
2
+ export const DEFAULT_FOV = 0.6435011087932844;
3
+ /**
4
+ * 从宿主地图中提取 WorldCoordinateHelper(自动适配 MapLibre v5+ CRS 体系与自定义投影)
5
+ */
6
+ export function extractWorldCoordinateHelper(map) {
7
+ const m = map;
8
+ const helper = (m?.transform?.worldCoordinateHelper ??
9
+ m?.transform?.projection?.worldCoordinateHelper ??
10
+ m?.painter?.transform?.worldCoordinateHelper ??
11
+ (typeof m?.getProjection === 'function' ? m.getProjection()?.worldCoordinateHelper : null) ??
12
+ null);
13
+ if (helper && typeof helper.worldFromLngLat === 'function' && typeof helper.lngLatFromWorld === 'function') {
14
+ return helper;
15
+ }
16
+ return null;
17
+ }
18
+ /**
19
+ * 把宿主地图包装成 s3m-three 的 GeoAdapter。
20
+ * 拿不到 WorldCoordinateHelper 时返回 null,由渲染层回退到标准 Web 墨卡托。
21
+ */
22
+ export function createMapLibreGeoAdapter(map) {
23
+ const helper = extractWorldCoordinateHelper(map);
24
+ if (!helper)
25
+ return null;
26
+ return {
27
+ worldFromLngLat(lng, lat, altitude = 0) {
28
+ const coord = helper.worldFromLngLat(lng, lat, altitude);
29
+ let s = 0;
30
+ if (typeof helper.metersPerWorldUnit === 'function') {
31
+ const mpw = helper.metersPerWorldUnit(coord.x, coord.y);
32
+ if (Number.isFinite(mpw) && mpw > 0)
33
+ s = 1 / mpw;
34
+ }
35
+ if (s === 0) {
36
+ // 用 +1 米的差分反推尺度;z 不动(某些 CRS 的 z 不是米)就退回墨卡托近似
37
+ const c1 = helper.worldFromLngLat(lng, lat, altitude + 1);
38
+ const dz = Math.abs((c1.z ?? 0) - (coord.z ?? 0));
39
+ const sinLat = Math.sin((lat * Math.PI) / 180);
40
+ s = dz > 0 ? dz : 1 / (2 * Math.PI * 6378137) / Math.cos((lat * Math.PI) / 180);
41
+ }
42
+ return {
43
+ x: coord.x,
44
+ y: coord.y,
45
+ z: coord.z ?? altitude * s,
46
+ meterInMercator: s,
47
+ altitude,
48
+ };
49
+ },
50
+ lngLatFromWorld(x, y) {
51
+ const res = helper.lngLatFromWorld(x, y);
52
+ if (Array.isArray(res))
53
+ return [res[0], res[1]];
54
+ if (res && typeof res.lng === 'number' && typeof res.lat === 'number') {
55
+ return [res.lng, res.lat];
56
+ }
57
+ return [0, 0];
58
+ },
59
+ };
60
+ }
61
+ //# sourceMappingURL=MapLibreGeoAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MapLibreGeoAdapter.js","sourceRoot":"","sources":["../src/MapLibreGeoAdapter.ts"],"names":[],"mappings":"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"}