唯杰地图 logo唯杰地图
VJMAP
EN

baidu

vjmap/references/internet-map/baidu.md 5.2 KB152 行
原文

本文回答:百度地图的特殊坐标系 BD09、WMS 叠加透明色坑与 GeoJSON 叠加备用方案。

一、坐标系

百度地图使用独立的 BD09 坐标系(GCJ02 上再加一层偏移),且其瓦片投影为 百度墨卡托(非 EPSG:3857)。

因此:

  • 不能直接通过 vjmap 标准栅格源显示百度地图(投影不同)。
  • 只能在 百度 JSAPI GL 里叠加 CAD WMS。

二、在百度地图 SDK 中叠加 CAD WMS(有坐标系)

const map = new BMapGL.Map("allmap");
map.centerAndZoom(new BMapGL.Point(116.49, 39.97), 15);

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

const wmsUrl = svc.wmsTileUrl({
  mapid: mapId,
  layers: res.layer,
  srs: "EPSG:3857",        // 百度 WMS 支持 EPSG:3857
  crs: "EPSG:4548",        // CAD EPSG(sys_cad2000 = CGCS2000 3° 带 117°E;4544 是 105°E 带)
  bbox: ""                 // ⚠️ 必填:清空默认的 {bbox-epsg-3857} 占位,否则该字面量会发到服务端
  // 不用填 webMapType:默认 WGS84 的 WMS 服务就能用(百度 JSAPI 自己做了加偏)
});

const wmsLayer = BMapGL.XYZLayer({
  tileUrlTemplate: wmsUrl + "&BBOX=[b]",     // 百度 XYZLayer 的 BBOX 占位符(官方示例同款写法)
  useThumbData: false
});
map.addTileLayer(wmsLayer);

三、无坐标系 CAD:四参数校准

// 在 CAD 上取 2 个及以上控制点
const cadPoints = [
  vjmap.geoPoint([587464448.84, 3104003685.21]),
  vjmap.geoPoint([587761927.72, 3104005967.66]),
  vjmap.geoPoint([587463688.03, 3103796743.38]),
  vjmap.geoPoint([587760406.09, 3103793700.12])
];

// 对应点:在百度地图上点取(BD09 坐标)
const webPoints = [
  vjmap.geoPoint([116.497386, 39.969244]),
  vjmap.geoPoint([116.500002, 39.967539]),
  vjmap.geoPoint([116.498440, 39.966136]),
  vjmap.geoPoint([116.495814, 39.967791])
];

// BD09 → EPSG:3857
const mercPoints = webPoints.map(w =>
  vjmap.geoPoint(vjmap.transform.convert(w, vjmap.transform.CRSTypes.BD09, vjmap.transform.CRSTypes.EPSG3857))
);

// 求四参数(考虑旋转)
const p = vjmap.coordTransfromGetFourParamter(mercPoints, cadPoints, false);
const fourparam = [p.dx, p.dy, p.scale, p.rotate];

const wmsUrl = svc.wmsTileUrl({
  mapid: mapId, layers: res.layer,
  srs: "EPSG:3857",
  bbox: "",                // ⚠️ 清空默认占位,BBOX 由百度 [b] 提供
  fourParameter: fourparam,
  transparent: true
});

map.addTileLayer(BMapGL.XYZLayer({ tileUrlTemplate: wmsUrl + "&BBOX=[b]" }));

四、百度 WMS 透明色坑

现象:透明 WMS 叠到百度地图上,CAD 颜色发生变化(偏蓝 / 偏灰)。

原因:百度 JSAPI 对透明 tile 的 blend 方式与其他底图不同,暂无公开解法。

解法 A:关闭透明度,改用纯色背景。

const wmsUrl = svc.wmsTileUrl({
  ...,
  transparent: false,
  backgroundColor: "rgba(240,255,255)"        // 固定背景,颜色正常
});

代价:看不到 CAD 覆盖区域的百度地图。

解法 B:换 GeoJSON 方式展示 CAD(见下节)。

五、GeoJSON 方式叠加 CAD(替代 WMS)

// 1) 查询 CAD 所有几何
async function queryData() {
  const res = await svc.conditionQueryFeature({
    condition: "",
    fields: "",
    includegeom: true,
    realgeom: true,
    limit: 100000
  }, pt => {
    // 坐标回调:CAD → WGS84 经纬度(下面 GeoJSONLayer 的 reference 是 "WGS84",由百度自己加偏;
    // 这里若返回 BD09 会被再加偏一次)
    const cadPt = cadPrj.fromMercator(pt);
    return cadToWgs84(cadPt);   // 如 proj4(cadEpsg, "EPSG:4326", cadPt.toArray())
  });

  const features = [];
  for (const ent of res.result) {
    if (!ent.geom?.geometries) continue;
    const clr = vjmap.entColorToHtmlColor(ent.color);
    ent.geom.geometries.forEach((g, i) => {
      features.push({
        type: "Feature",
        id: ent.id,
        properties: { objectid: ent.objectid + "_" + i, color: clr },
        geometry: g
      });
    });
  }
  return { type: "FeatureCollection", features };
}

// 2) 加载到百度
const layer = new BMapGL.GeoJSONLayer("cad-child", {
  reference: "WGS84",
  dataSource: await queryData(),
  level: -10,
  polygonStyle: p => ({ fillColor: p.color }),
  polylineStyle: p => ({ strokeColor: p.color })
});
bmap.addGeoJSONLayer(layer, { maxZoom: 24 });

优点:透明度正常、可交互(hover / click)。 缺点:GeoJSON 体量大,前端渲染慢;大图不适合。

六、常见坑

  1. 直接当标准墨卡托底图加载百度瓦片 → 投影不同,图片完全错位。
  2. BD09 和 GCJ02 混淆 → 坐标计算链中 convert 参数错,常见多一次/少一次加偏,结果差 500~2000 米。
  3. useThumbData: true → 百度缓存缩略图;WMS 动态数据要关掉。
  4. WMS URL 里带 &:百度 tileUrlTemplate 要自己加 &BBOX=[b] 占位符;& 可能被 encode。