You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用D3.js将椭球面上的3D坐标投影至2D并保持相对位置

解决椭球3D点到2D平面的D3.js自定义投影方案

首先,你需要先把椭球上的笛卡尔坐标转换成球面经纬度,再基于经纬度实现自定义投影来保持相对位置。以下是分步骤的公式和代码示例:

1. 椭球坐标转球面经纬度

假设你的椭球是三轴椭球,三个半轴分别为a(X轴半径)、b(Y轴半径)、c(Z轴半径),先将原始3D坐标归一化到单位球面:

  • 归一化坐标:
    const xPrime = point.X / a;
    const yPrime = point.Y / b;
    const zPrime = parseFloat(point.Z) / c; // 注意你的Z是字符串格式,先转数字
    
  • 计算经纬度(弧度制):
    const longitude = Math.atan2(yPrime, xPrime); // 经度,范围[-π, π]
    const latitude = Math.asin(zPrime); // 纬度,范围[-π/2, π/2]
    

如果是旋转椭球(X/Y轴半径相同,即a=b),上述公式依然适用,无需调整。

2. 自定义D3投影保持相对位置

要保证点的相对位置关系不混乱,推荐用等距圆柱投影(Equirectangular),它能维持点之间的相对比例与位置逻辑,仅存在均匀的轴向拉伸,公式和实现如下:

投影函数实现

// 定义画布尺寸
const width = 800;
const height = 600;

// 自定义等距圆柱投影
const customProjection = (lon, lat) => {
  // 弧度转角度
  const lonDeg = lon * 180 / Math.PI;
  const latDeg = lat * 180 / Math.PI;
  
  // 等距圆柱投影核心公式
  const x = (lonDeg + 180) * (width / 360);
  const y = (90 - latDeg) * (height / 180);
  
  return [x, y];
};

完整流程示例

// 原始点数据
const points = [{X: 339.34474945068354, Y: 505.363540649415, Z: '187.425979614258'},{X: 333.741912841797, Y: 445.61164855957054, Z: '185.462127685547'}];

// 替换为你实际的椭球半轴参数
const a = 500; // X轴半径
const b = 500; // Y轴半径
const c = 200; // Z轴半径

// 转换所有点到经纬度格式
const geoPoints = points.map(point => {
  const xPrime = point.X / a;
  const yPrime = point.Y / b;
  const zPrime = parseFloat(point.Z) / c;
  const lon = Math.atan2(yPrime, xPrime);
  const lat = Math.asin(zPrime);
  return [lon, lat];
});

// 用自定义投影转换到2D坐标
const projectedPoints = geoPoints.map(([lon, lat]) => customProjection(lon, lat));

// 在D3中绘制点
const svg = d3.select("svg")
  .attr("width", width)
  .attr("height", height);

svg.selectAll("circle")
  .data(projectedPoints)
  .enter()
  .append("circle")
  .attr("cx", d => d[0])
  .attr("cy", d => d[1])
  .attr("r", 3)
  .attr("fill", "red");

其他可选投影

如果需要不同的视觉效果但仍保持相对位置:

  • 正射投影(Orthographic):模拟太空视角看椭球的效果,适合展示局部区域,D3内置d3.geoOrthographic(),也可自行自定义实现。
  • 墨卡托投影:保持角度不变,但高纬度区域会拉伸,D3内置d3.geoMercator(),适合需要方向准确性的场景。

注意:必须根据你实际椭球的半轴参数a、b、c调整代码,这些参数是坐标转换准确性的关键。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 07:07:33