在本文中,我们将使用日本新宿站的室内地图数据,并使用 Three.js 将其进行 3D 可视化。更多精彩内容尽在数字孪生平台,关注公众号:sky的数孪技术,技术交流、源码下载请添加VX:digital_twin123
使用的数据
这次,我们将使用日本空间信息中心发布的“新宿站室内地图开放数据”的集成版本(ShapeFile)。
要素数据
网络数据
数据转换
所有这些数据都是 ShapeFile,我们可以使用 GDAL 命令将 ShapeFile 转换为 GeoJson。
mkdir geojson
for f in *.shp; do
ogr2ogr -f GeoJSON -t_srs EPSG:6677 "geojson/${f%.*}.geojson" $f
done
使用 Three.js 绘制
创建场景
创建场景并添加相机和控制器。在本文中,我将把移动操作分配给 MapControls,将缩放操作分配给 TrackballControls。
import * as THREE from 'three';
import {
MapControls } from 'three/examples/jsm/controls/MapControls.js';
import {
TrackballControls } from 'three/examples/jsm/controls/TrackballControls.js';
const sizes = {
width: window.innerWidth,
height: window.innerHeight,
};
// 创建画布
const canvas = document.createElement('canvas');
document.body.appendChild(canvas);
// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100000);
camera.position.set(-190, 280, -350);
scene.add(camera);
// 创建控制器
const mapControls = new MapControls(camera, canvas);
mapControls.enableDamping = true;
mapControls.enableZoom = false;
mapControls.maxDistance = 1000;
const zoomControls = new TrackballControls(camera, canvas);
zoomControls.noPan = true;
zoomControls.noRotate = true;
zoomControls.noZoom = false;
zoomControls.zoomSpeed = 0.5;
// 渲染器
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
alpha: true,
});
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
// 当屏幕大小调整时,画布也会调整大小
const onResize = () => {
// 获取尺寸大小
const width = window.innerWidth;
const height = window.innerHeight;
// 调整渲染器大小
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
// 修正相机纵横比
camera.aspect = width / height;
camera.updateProjectionMatrix();
};
window.addEventListener('resize', onResize);
const animate = () => {
requestAnimationFrame(animate);
const target = mapControls.target;
mapControls.update();
zoomControls.target.set(target.x, target.y, target.z);
zoomControls.update();
renderer.render(scene, camera);
};
animate();
另外,在 WebGLRenderer 选项中设置 alpha: true 以使背景透明并使用 CSS 将渐变应用于背景。
canvas {
background-image: radial-gradient(#382c6e, #000000);
}
创建 GUI 和组
在场景中绘制要素数据。这次我们按图层对要素进行分组,因此需要提前在场景中创建一个组,并将使用要素数据创建的对象添加到每个图层的组中。我们还将添加一个复选框 GUI,以便可以切换每个层次结构的显示。
import {
GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
// 创建 dat.GUI 的实例
const gui = new GUI({
width: 150 });
// 创建一个群组
const groupList = [4, 3, 2, 1, 0, -1, -2