# 互联网地图叠加（WebMap Overlay）

> 文档：`vjcad/doc/tile/tile-mode.md`
> 示例：`vjcad/example/tile/06webmapoverlay.js`

把 **高德 / 天地图 / 自定义瓦片源** 作为 CAD 的底图叠加显示，常用于做 GIS / BIM 的位置对照、外业核对。

## 1. 启用 / 关闭

`Engine.enableWebMap(config)` 只接收 **一个** `WebMapTileConfig` 对象——没有 `('gaode', {type})` 这样的供应商名参数：

```js
// 高德卫星图（WebMapOverlayPanel 内置预设同款配置）
Engine.enableWebMap({
    tileCrs: 'gcj02',                // 互联网地图坐标类型：高德=gcj02，天地图=wgs84
    tileUrl: [
        'https://webst0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=6&x={x}&y={y}&z={z}',
        'https://webst0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
    ],
    tileShards: '1,2,3,4',           // {s} 占位符的取值列表
    tileSize: 256,
    tileMaxZoom: 18,
    mapbounds: '0,0,100000,100000',  // TS 类型必填，但 1.0.16 不发送、不参与对齐
    srs: 'EPSG:4509',                // 自动对齐模式：CAD 图的 EPSG 码（对齐靠它）
});

// 调整透明度
Engine.setWebMapAlpha(0.6);

// 状态查询 / 关闭
Engine.isWebMapEnabled();            // → boolean
Engine.disableWebMap();
```

## 2. `WebMapTileConfig` 字段

| 字段 | 类型 | 说明 |
|---|---|---|
| `tileCrs` | `'gcj02' \| 'wgs84'` | **必填**。高德用 `gcj02`，天地图用 `wgs84` |
| `tileUrl` | `string \| string[]` | **必填**。瓦片 URL 模板，`{x}{y}{z}` 占位，`{s}` 走 `tileShards`，`{t}` 走 `tileToken` |
| `mapbounds` | `string` | TS 类型必填，`"minx,miny,maxx,maxy"`；但 1.0.16 **不发送给服务端、不参与对齐**，填图幅范围即可 |
| `srs` | `string` | 自动对齐模式：CAD 图所在 EPSG 码（如 `'EPSG:4509'`），与 `fourParameterBefore` 二选一，**两者都给时 srs 优先** |
| `fourParameterBefore` | `string` | 四参数对齐模式：`"dx,dy,scale,rotation"`（CAD → EPSG:3857，rotation 为弧度） |
| `fourParameterAfter` | `string` | `enableWebMap` 路径下 **不生效**（1.0.16 不发送） |
| `tileSize` | `number` | 瓦片像素边长，默认 256 |
| `tileMaxZoom` | `number` | 瓦片最大 zoom，默认 18 |
| `tileRetina` | `number` | `enableWebMap` 路径下 **不生效**（1.0.16 不发送） |
| `tileShards` | `string` | `{s}` 占位取值，如 `'1,2,3,4'` |
| `tileToken` | `string \| string[]` | `{t}` 占位取值（天地图 tk 等） |
| `tileFlipY` | `boolean` | 翻转 Y 轴（TMS 风格瓦片） |
| `preloadBuffer` | `number` | 预取缓冲圈数，默认 1 |
| `maxConcurrent` | `number` | 最大并发瓦片请求，默认 6 |
| `cacheSize` | `number` | LRU 纹理缓存数，默认 200 |

## 3. 常用源配置

`WebMapOverlayPanel` 内置预设（源码 `MAP_PRESETS`）照抄即可：

### 高德

```js
// 卫星 + 路网叠加（gcj02）
Engine.enableWebMap({
    tileCrs: 'gcj02',
    tileUrl: [
        'https://webst0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=6&x={x}&y={y}&z={z}',
        'https://webst0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
    ],
    tileShards: '1,2,3,4', tileSize: 256, tileMaxZoom: 18,
    mapbounds: boundsStr,
    srs: 'EPSG:4509',
});

// 路网（gcj02）
Engine.enableWebMap({
    tileCrs: 'gcj02',
    tileUrl: 'https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
    tileShards: '1,2,3,4', mapbounds: boundsStr, srs: 'EPSG:4509',
});
```

### 天地图（需 token）

```js
// 天地图矢量 + 注记（wgs84），{t} 占位符由 tileToken 填充
Engine.enableWebMap({
    tileCrs: 'wgs84',
    tileUrl: [
        'https://t{s}.tianditu.gov.cn/DataServer?T=vec_w&X={x}&Y={y}&L={z}&tk={t}',
        'https://t{s}.tianditu.gov.cn/DataServer?T=cva_w&X={x}&Y={y}&L={z}&tk={t}',
    ],
    tileShards: '1,2,3,4,5,6',
    tileToken: ['TOKEN_A', 'TOKEN_B'],   // token 池（不是每层一个）：服务端用当前 token 填 {t}，遇 429 换下一个
    mapbounds: boundsStr,
    srs: 'EPSG:4509',                    // 填 CAD 图自身的 EPSG，与底图是天地图还是高德无关
});
// 卫星图把 T=vec_w/cva_w 换成 T=img_w/cia_w
```

### 自定义 XYZ 瓦片

```js
Engine.enableWebMap({
    tileCrs: 'gcj02',
    tileUrl: 'https://tile.example.com/{z}/{x}/{y}.png',
    tileMaxZoom: 18,
    mapbounds: boundsStr,
    fourParameterBefore: '0,0,1,0',      // 无 EPSG 时用四参数对齐（CAD→EPSG:3857；此值表示 CAD 坐标本身就是 3857 米）
});
```

## 4. 坐标对齐

对齐完全由服务端 `/map/tile/webmap` 完成：前端每块瓦片只发送自己的 CAD WCS bbox，服务端把 bbox 两角点换算成 WGS84，再按 `tileCrs` 抓取并拼接互联网瓦片。CAD 坐标 → 经纬度的换算二选一：

- **`srs`（推荐）**：图是标准投影坐标，给出 EPSG 码，服务端 proj4 转 WGS84（两者都给时 srs 优先）
- **`fourParameterBefore`**：图是任意本地坐标，用四参数（平移 dx,dy + 缩放 + 旋转弧度）把 CAD 坐标直接换到 EPSG:3857，再反算经纬度

两者都不给，服务端一律返回空白瓦片；`mapbounds` 不发送、不参与对齐。

## 5. 透明度联动

```js
// 给互联网地图加 50% 透明
Engine.setWebMapAlpha(0.5);
```

`setWebMapAlpha` 与 `setWmsTileAlpha` / `setReadOnlyAlpha` 是 **三个独立通道**。常见组合：

| 场景 | 推荐 |
|---|---|
| 矢量为主，地图当背景 | webmap 0.5、瓦片 1.0、遮罩 1.0 |
| 瓦片图纸 + 地图核对 | webmap 0.6、瓦片 0.4 |
| 调试 mask | 瓦片 1.0、遮罩 0 |

## 6. 与瓦片模式叠加示意

```mermaid
flowchart TB
    W[互联网地图] --> C[Canvas 底层]
    T[CAD 瓦片] --> C
    M[编辑区遮罩] --> C
    V[矢量层] --> C
    C --> Out[最终画面]
```

每一层都有自己的透明度。`enableWebMap` 不会进入只读，纯粹是显示层。

## 红旗

- 天地图 token 需要后端代理，否则会暴露在前端代码
- 互联网地图按公司或项目可能有合规要求，部署前确认是否被允许
- `tileUrl` 的 `{z}`/`{x}`/`{y}`/`{s}`/`{t}` 占位符可出现在 URL 任意位置（如天地图 `?X={x}&Y={y}&L={z}`）；瓦片由 vjmap 服务端代为抓取，浏览器不直连瓦片源
- `enableWebMap` 之后必须保证 `pcanvas` 仍然存在（页面 destroy 时记得 `disableWebMap`）
- `srs`/`fourParameterBefore` 配错 = 地图叠到错误位置，都不给 = 空白；先小范围验证再铺开
- 内置 UI 面板 `WebMapOverlayPanel` 走的也是同一套 `enableWebMapTileLayer`——手动开启后再用面板操作会互相覆盖

## 参考（官方文档 MCP）

- 文档：`vjcad/doc/tile/tile-mode.md`
- 示例：`vjcad/example/tile/06webmapoverlay.js`
