唯杰地图 logo唯杰地图
VJMAP
EN

openlayers

vjmap/references/overlay/openlayers.md 4.4 KB124 行
原文

本文回答:在 OpenLayers 项目里叠加 vjmap CAD。

一、OL 上叠 CAD WMS

import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import TileLayer from "ol/layer/Tile";
import TileImage from "ol/source/TileImage";
import TileWMS from "ol/source/TileWMS";

const svc = new vjmap.Service(URL, TOKEN);
await svc.openMap({ mapid: "sys_cad2000", mapopenway: vjmap.MapOpenWay.GeomRender });

const wmsUrl = svc.wmsTileUrl({
  mapid: "sys_cad2000",
  layers: "默认图层名",
  bbox: "",                // ⚠️ 必传空串:默认 "{bbox-epsg-3857}" 只有 vjmap 引擎会填,OL 不认
  srs: "EPSG:3857",
  crs: "EPSG:4548"          // sys_cad2000 是 CGCS2000 3° 带 117°E(无带号)
});

// 用 TileWMS(由它追加 BBOX);TileImage 会把 {bbox-epsg-3857} 原样发给后端
const cadLayer = new TileLayer({
  source: new TileWMS({ url: wmsUrl, params: { TILED: true } })
});

const olMap = new Map({
  target: "map",
  layers: [cadLayer],
  view: new View({ center: [13000000, 3100000], zoom: 16 })
});

二、以 CAD 为底图,加互联网瓦片

webMapUrl 返回的瓦片按 vjmap 的 CAD 瓦片网格切,OL 的 View 必须用以 CAD 范围为 extent 的自定义投影 + 匹配的 resolutions(官方示例 12olwebCad.js),CAD 本身用 svc.rasterTileUrl() 作底图;在默认 EPSG:3857 的 View 上叠不齐:

import Projection from "ol/proj/Projection";
import { addProjection } from "ol/proj";

const mapBounds = vjmap.GeoBounds.fromString(res.bounds);
const cadProjection = new Projection({ code: "cad", extent: mapBounds.toArray(), units: "m" });
addProjection(cadProjection);
const resolutions = [];
for (let i = 0; i < 25; i++) resolutions.push(mapBounds.width() / (512 * Math.pow(2, i - 1)));
const olMap = new Map({
  target: "map",
  layers: [new TileLayer({ source: new TileImage({ url: svc.rasterTileUrl() }) })],   // CAD 底图
  view: new View({ projection: cadProjection, resolutions, center: mapBounds.center().toArray(), zoom: 9 })
});

再叠互联网瓦片:

const tileUrl = svc.webMapUrl({
  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}"],
  tileSize: 256,
  tileShards: "1,2,3,4",
  mapbounds: res.bounds,
  srs: "EPSG:4527",
  fourParameterBefore: "39000000,0,1,0"
});

const gdLayer = new TileLayer({
  source: new TileImage({ url: tileUrl }),
  zIndex: -1
});
olMap.addLayer(gdLayer);

三、坐标系配置

OL 默认 EPSG:3857。如果 CAD 是 WMS-based 叠加,已经由 WMS 服务做坐标转换,不需动 OL 投影。

如果想让 OL 直接用 CAD 坐标系(EPSG:4544 等):

import proj4 from "proj4";
import { register } from "ol/proj/proj4";
import { get as getProjection } from "ol/proj";

proj4.defs("EPSG:4544", "+proj=tmerc +lat_0=0 +lon_0=105 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs");   // 4544 = CGCS2000 3° 带 105°E;117°E 是 EPSG:4548
register(proj4);

const view = new View({
  projection: getProjection("EPSG:4544"),
  center: [100000, 3000000],
  zoom: 14
});

四、点击查询

olMap.on("click", async (evt) => {
  const [lng, lat] = evt.coordinate;     // EPSG:3857 坐标(默认)
  // 转 CAD
  // 目标 EPSG 必须与 WMS 的 crs 一致(sys_cad2000 → EPSG:4548)
  const r = await svc.cmdTransform("EPSG:3857", "EPSG:4548", vjmap.geoPoint([lng, lat])); // 必须 geoPoint 包装,裸数组会序列化成 undefined,undefined
  const [x, y] = r[0];
  // 查询附近实体:zoom 参数按 vjmap 的缩放级别换算像素容差,OL 的 zoom 不是同一套——改传每像素地理长度
  const q = await svc.pointQueryFeature({
    x, y, pixelsize: 5,
    pixelToGeoLength: olMap.getView().getResolution()   // 3857 米/像素,近似 CAD 米(纬度 φ 处偏大 1/cosφ),作拾取容差够用
  });
  console.log(q);
});

五、常见坑

  1. OL 默认 tileSize 256 → 没问题;vjmap WMS 动态生成瓦片会按请求 size 渲染。

  2. 图像旋转:WMS useImageRotate 默认自动;若底图与 CAD 有夹角会自动旋转。

  3. OL 不支持 {s} subdomain → 用 tileUrls 数组自己做负载均衡:

    source: new TileImage({ urls: [url1, url2, url3] })