You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何获取旋转后Ground Overlay外接南北向矩形的NW LatLng?

获取旋转后地面覆盖物的轴对齐矩形西北角(NW)经纬度

我完全懂你的痛点:当地面覆盖物是正北/正南朝向时,mOverlay.getBounds()能精准拿到你要的红色标记点,但一旦覆盖物旋转,这个方法就只返回旋转前的边界,完全无视旋转角度。你需要的是能包裹住旋转后覆盖物、边平行于经纬线的矩形的西北角经纬度对吧?

下面是具体的解决思路和可落地的实现步骤:

核心思路

要拿到这个轴对齐矩形的NW角,关键是先得到旋转后覆盖物的四个顶点,再从这些顶点里筛选出最北(纬度最高)且最西(经度最小)的点——这就是你要的目标角点。

具体实现步骤

1. 提取基础数据

先把旋转前的边界、覆盖物中心和旋转角度这几个关键数据拿出来:

// 以Google Maps API为例,其他地图API可对应调整方法名
const originalBounds = mOverlay.getBounds();
const center = originalBounds.getCenter();
const rotation = mOverlay.getRotation(); // 多数API里单位是度,顺时针为正

2. 实现经纬度点的旋转函数

因为经纬度是球面坐标,直接旋转会有误差,得先转成墨卡托平面坐标计算旋转,再转回经纬度:

// 辅助:把LatLng转成墨卡托平面坐标(单位:米)
function latLngToMercator(latLng) {
  const earthRadius = 6378137;
  const x = latLng.lng() * Math.PI * earthRadius / 180;
  const y = Math.log(Math.tan((90 + latLng.lat()) * Math.PI / 360)) * earthRadius;
  return { x, y };
}

// 辅助:把墨卡托坐标转回LatLng
function mercatorToLatLng(mercator) {
  const earthRadius = 6378137;
  const lng = (mercator.x / earthRadius) * 180 / Math.PI;
  const lat = (2 * Math.atan(Math.exp(mercator.y / earthRadius)) - Math.PI / 2) * 180 / Math.PI;
  return new google.maps.LatLng(lat, lng);
}

// 核心:将点绕中心点旋转指定角度(度)
function rotateLatLng(point, center, rotationDeg) {
  const pointMercator = latLngToMercator(point);
  const centerMercator = latLngToMercator(center);
  
  // 计算点相对于中心的偏移量
  const dx = pointMercator.x - centerMercator.x;
  const dy = pointMercator.y - centerMercator.y;
  
  // 把角度转成弧度
  const rotationRad = (rotationDeg * Math.PI) / 180;
  
  // 应用顺时针旋转矩阵(若API是逆时针旋转,调整sin的符号即可)
  const rotatedDx = dx * Math.cos(rotationRad) - dy * Math.sin(rotationRad);
  const rotatedDy = dx * Math.sin(rotationRad) + dy * Math.cos(rotationRad);
  
  // 计算旋转后的坐标并转回LatLng
  const rotatedMercator = {
    x: centerMercator.x + rotatedDx,
    y: centerMercator.y + rotatedDy
  };
  return mercatorToLatLng(rotatedMercator);
}

3. 计算旋转后的顶点并筛选目标NW角

// 获取旋转前覆盖物的四个原始顶点
const originalNW = originalBounds.getNorthWest();
const originalNE = originalBounds.getNorthEast();
const originalSW = originalBounds.getSouthWest();
const originalSE = originalBounds.getSouthEast();

// 对四个顶点分别做旋转处理
const rotatedNW = rotateLatLng(originalNW, center, rotation);
const rotatedNE = rotateLatLng(originalNE, center, rotation);
const rotatedSW = rotateLatLng(originalSW, center, rotation);
const rotatedSE = rotateLatLng(originalSE, center, rotation);

// 收集所有旋转后的顶点
const rotatedPoints = [rotatedNW, rotatedNE, rotatedSW, rotatedSE];

// 找出最北(最大纬度)和最西(最小经度)的点
let maxLat = -90;
let minLng = 180;
rotatedPoints.forEach(point => {
  if (point.lat() > maxLat) maxLat = point.lat();
  if (point.lng() < minLng) minLng = point.lng();
});

// 最终的目标NW角点
const targetNW = new google.maps.LatLng(maxLat, minLng);

注意事项

  • 不同地图API的方法名可能有差异(比如获取旋转角度的方法、LatLng构造函数),请根据你使用的API微调代码
  • 若你的API中旋转方向是逆时针为正,记得调整旋转矩阵里的sin符号
  • 超大尺寸的覆盖物可能会有微小的墨卡托投影误差,但日常场景下完全够用

内容的提问来源于stack exchange,提问作者Tommy Jackson

火山引擎 最新活动