1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > Threejs实现绘制地球 地理位置标注 经纬度转换世界坐标threejs坐标

Threejs实现绘制地球 地理位置标注 经纬度转换世界坐标threejs坐标

时间:2020-04-11 01:03:07

相关推荐

Threejs实现绘制地球 地理位置标注 经纬度转换世界坐标threejs坐标

1,介绍

该示例使用的是 r95版本Three.js库。

主要实现功能:绘制地球和地理位置进行标注

效果图如下:

2,主要说明

准备一张地图,创建一个球体并进行贴图,把地理位置经纬度转换成threejs的世界坐标,并进行标注。

创建地球,部分代码如下:

// 创建地球 半径100function createEarth() {var earthGeo = new THREE.SphereGeometry(radius, 50, 50);var earthMater = new THREE.MeshPhongMaterial({map: new THREE.TextureLoader().load('assets/earth/earth3.jpg'),transparent: true,depthWrite: false,side: THREE.DoubleSide,blending: THREE.AdditiveBlending,opacity: 0.8,color: 0x03d98e});var earthMesh = new THREE.Mesh(earthGeo, earthMater);scene.add(earthMesh)}

经纬度转换成threejs坐标(也叫右手坐标系)

phi是方位面(水平面)内的角度,范围0~360度,theta是俯仰面(竖直面)内的角度,范围0~180度、就是空间极坐标系中的两个参数,和类比直角坐标系里的xyz

threejs实现转换,代码如下:

// 坐标转换,function createPosition(lnglat) {let spherical = new THREE.Sphericalspherical.radius = radius;const lng = lnglat[0]const lat = lnglat[1]const theta = (lng + 90) * (Math.PI / 180)const phi = (90 - lat) * (Math.PI / 180)spherical.phi = phi; // phi是方位面(水平面)内的角度,范围0~360度spherical.theta = theta; // theta是俯仰面(竖直面)内的角度,范围0~180度let position = new THREE.Vector3()position.setFromSpherical(spherical)return position}

3,源码

<!DOCTYPE html><html><head><title>Threejs实现绘制地球,地理位置标注-经纬度转换世界坐标</title><script type="text/javascript" src="libs/three.js"></script><script type="text/javascript" src="libs/OrbitControls.js"></script><style>body {margin: 0;overflow: hidden;}</style></head><body><div id="dom"></div><script type="text/javascript">var camera;var renderer;var radius = 100; // 地球半径var areas = [{name: "中国",position: [116.20, 39.55]}, {name: "中非共和国",position: [18.35, 4.23]}, {name: "智利",position: [-70.40, -33.24]}, {name: "乍得",position: [14.59, 12.10]}, {name: "赞比亚",position: [28.16, -15.28]}, {name: "越南",position: [105.55, 21.05]}, {name: "约旦",position: [35.52, 31.57]}, {name: "英属维尔京群岛",position: [-64.37, 18.27]}, {name: "英国",position: [-0.05, 51.36]}];function init() {// 创建一个场景,它将包含我们所有的元素,如物体,相机和灯光。var scene = new THREE.Scene();var urls = ['assets/textures/cubemap/flowers/posx.jpg','assets/textures/cubemap/flowers/negx.jpg','assets/textures/cubemap/flowers/posy.jpg','assets/textures/cubemap/flowers/negy.jpg','assets/textures/cubemap/flowers/posz.jpg','assets/textures/cubemap/flowers/negz.jpg'];var cubeLoader = new THREE.CubeTextureLoader();// scene.background = cubeLoader.load(urls);// 创建一个摄像机,它定义了我们正在看的地方camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);// 将摄像机对准场景的中心camera.position.z = 500;camera.lookAt(scene.position);var orbit = new THREE.OrbitControls(camera);// 创建一个渲染器并设置大小,WebGLRenderer将会使用电脑显卡来渲染场景renderer = new THREE.WebGLRenderer({antialias: true,logarithmicDepthBuffer: true,});renderer.setSize(window.innerWidth, window.innerHeight);// scene.add(new THREE.AmbientLight(0x666666));var ambientLight = new THREE.AmbientLight("#ffffff", 1);scene.add(ambientLight);// 在屏幕上显示坐标轴var axes = new THREE.AxisHelper(radius);scene.add(axes);// 将平面添加到场景中var plane = createPlaneGeometryBasicMaterial();// scene.add(plane);// initSphere(10, 0, 10);createEarth();createAreaPoint();var rs = coordinateWorldTurnScreen(10, 0, 10);var div = document.createElement('div');div.innerHTML = '立';div.style.padding = '5px';div.style.position = 'absolute';div.style.backgroundColor = 'rgba(155,0,155,0.8)';document.body.appendChild(div);div.style.left = rs.x + "px";div.style.top = rs.y + "px";console.log(rs)// 将呈现器的输出添加到HTML元素document.getElementById("dom").appendChild(renderer.domElement);// 启动动画renderScene();/*** 创建地面并添加材质* wrapS属性定义的是纹理沿x轴方向的行为,而warpT属性定义的是纹理沿y轴方向的行为。* Three.js为这些属性提供了如下两个选项:* ·THREE.RepeatWrapping允许纹理重复自己。* ·THREE.ClampToEdgeWrapping是属性的默认值。* 属性值为THREE.ClampToEdgeWrapping时,那么纹理的整体不会重复,只会重复纹理边缘的像素来填满剩下的空间。*/function createPlaneGeometryBasicMaterial() {var textureLoader = new THREE.TextureLoader();var cubeMaterial = new THREE.MeshStandardMaterial({map: textureLoader.load("assets/textures/stone/cd.jpg"),});cubeMaterial.map.wrapS = THREE.RepeatWrapping;cubeMaterial.map.wrapT = THREE.RepeatWrapping;cubeMaterial.map.repeat.set(8, 8)// 创建地平面并设置大小var planeGeometry = new THREE.PlaneGeometry(100, 100);var plane = new THREE.Mesh(planeGeometry, cubeMaterial);// 设置平面位置并旋转plane.rotation.x = -0.5 * Math.PI;plane.position.x = 0;plane.position.z = 0;return plane;}// 世界坐标转屏幕坐标function coordinateWorldTurnScreen(x, y, z) {let world_vector = new THREE.Vector3(x, y, z);let vector = world_vector.project(camera);let halfWidth = window.innerWidth / 2,halfHeight = window.innerHeight / 2;return {x: Math.round(vector.x * halfWidth + halfWidth),y: Math.round(-vector.y * halfHeight + halfHeight)}}// 创建地球 半径100function createEarth() {var earthGeo = new THREE.SphereGeometry(radius, 50, 50);var earthMater = new THREE.MeshPhongMaterial({map: new THREE.TextureLoader().load('assets/earth/earth3.jpg'),transparent: true,depthWrite: false,side: THREE.DoubleSide,blending: THREE.AdditiveBlending,opacity: 0.8,color: 0x03d98e});var earthMesh = new THREE.Mesh(earthGeo, earthMater);scene.add(earthMesh)}function createAreaPoint() {// 球面let sphereGeom = new THREE.SphereGeometry(1, 20, 20),sphereMat = new THREE.MeshBasicMaterial({color: 0x03d98e,wireframe: true})let sphere = new THREE.Mesh(sphereGeom, sphereMat)scene.add(sphere)// 地标及光锥for (let i = 0, length = areas.length; i < length; i++) {const position = createPosition(this.areas[i].position)createHexagon(position); // 地标}}// 坐标转换,function createPosition(lnglat) {let spherical = new THREE.Sphericalspherical.radius = radius;const lng = lnglat[0]const lat = lnglat[1]const theta = (lng + 90) * (Math.PI / 180)const phi = (90 - lat) * (Math.PI / 180)spherical.phi = phi; // phi是方位面(水平面)内的角度,范围0~360度spherical.theta = theta; // theta是俯仰面(竖直面)内的角度,范围0~180度let position = new THREE.Vector3()position.setFromSpherical(spherical)return position}// 创建地标标记function createHexagon(position) {var hexagon = new THREE.Object3D()let hexagonLine = new THREE.CircleGeometry(4, 6)let hexagonPlane = new THREE.CircleGeometry(3, 6)let vertices = hexagonLine.verticesvertices.shift() // 第一个节点是中心点let material = new THREE.MeshBasicMaterial({color: 0xffff00,side: THREE.DoubleSide,opacity: 0.5})let circleLine = new THREE.LineLoop(hexagonLine, material)let circlePlane = new THREE.Mesh(hexagonPlane, material)circleLine.position.copy(position)circlePlane.position.copy(position)circlePlane.lookAt(new THREE.Vector3(0, 0, 0))circleLine.lookAt(new THREE.Vector3(0, 0, 0))hexagon.add(circleLine)hexagon.add(circlePlane)scene.add(hexagon);}// 初始球体function initSphere(x, y, z) {var geometry = new THREE.SphereGeometry(1, 100, 100); //球体几何var material = new THREE.MeshBasicMaterial({color: 0xffff00}); //网格基础材料var sphere = new THREE.Mesh(geometry, material);sphere.position.x = x;sphere.position.y = y;sphere.position.z = z;scene.add(sphere);}function renderScene() {orbit.update();// 使用requestAnimationFrame函数进行渲染requestAnimationFrame(renderScene);renderer.render(scene, camera);}// 渲染的场景renderer.render(scene, camera);}window.onload = init;// 随着窗体的变化修改场景function onResize() {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);}// 监听窗体调整大小事件window.addEventListener('resize', onResize, false);</script></body></html>

在线预览:左本的博客 (zuoben.top)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。