本文主要涉及的知识点是,根据经纬度算出在球面上的三维位置并通过四元数求出该点应该在球体的切面。

首先是根据经纬度和球体半径转三维位置

//计算三维位置的函数
// 引入Three.js
import * as THREE from "three";

/**
 * 经纬度坐标转球面坐标  
 * @param {地球半径} R  
 * @param {经度(角度值)} longitude 
 * @param {维度(角度值)} latitude
 */
//R代表的是球体的半径longitude,latitude代表经纬度
function lon2xyz(R,longitude,latitude) {
  var lon = longitude * Math.PI / 180;//转弧度值
  var lat = latitude * Math.PI / 180;//转弧度值
  lon = -lon;// three.js坐标系z坐标轴对应经度-90度,而不是90度
  
  // 经纬度坐标转球面坐标计算公式
  var x = R * Math.cos(lat) * Math.cos(lon);
  var y = R * Math.sin(lat);
  var z = R * Math.cos(lat) * Math.sin(lon);
  // 返回球面坐标
  return {
    x:x,
    y:y,
    z:z,
  };
}

export { lon2xyz }

导入标记点的经纬度数据

HotNewsData.forEach(function (obj) {
  var lon = obj.E;
  var lat = obj.N;
//调用函数生成光柱,这里仅仅只是生成个光柱底座什么的都没加
  var LightPillar = createLightPillar(120, lon, lat); //光柱
  scene.add(HotNews);
});

需要调用的函数

function createLightPillar(R, lon, lat) {
  var height = R * 0.3;
  var geometry = new THREE.PlaneGeometry(R * 0.05, height); //生成一个长方形几何体
  geometry.rotateX(Math.PI / 2);
  geometry.translate(0, 0, height / 2);
  var textureLoader = new THREE.TextureLoader();
  var material = new THREE.MeshBasicMaterial({
    map: textureLoader.load("/public/光柱.png"),
    color: 0x44ffaa, //光柱颜色,光柱map贴图是白色,可以通过color调节颜色
    transparent: true, //使用背景透明的png贴图,注意开启透明计算
    side: THREE.DoubleSide, //双面可见
    depthWrite: false, //是否对深度缓冲区有任何的影响
  });
  var mesh = new THREE.Mesh(geometry, material);
  var group = new THREE.Group();
  //叠加两个光柱
  group.add(mesh, mesh.clone().rotateZ(Math.PI / 2));
  //经纬度转球面坐标
  var SphereCoord = lon2xyz(R, lon, lat);
  group.position.set(SphereCoord.x, SphereCoord.y, SphereCoord.z);
  //获得球面上的法线方向,因为是从原点到SphereCoord所以需要减去原点坐标,但是原点是000,所以可以省略
  var coordVec3 = new THREE.Vector3(
    SphereCoord.x,
    SphereCoord.y,
    SphereCoord.z
  ).normalize();
  //mesh默认实在xoy平面法线方向是沿着Z轴,用四元数需要起始的法线向量和变化后的法线向量
  var meshNormal = new THREE.Vector3(0, 0, 1);
//四元数两个参数,一个是初始位置的标准向量,第二个参数是需要变动的向量直接赋值给需要改变角度的模型的quaternion就可以
  group.quaternion.setFromUnitVectors(meshNormal, coordVec3);
  return group;
}

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐