BIM模型+GIS信息的融合加载(纯Threejs方案)
把地图信息(天地图)整合到threejs中,并在此基础上解决BIM模型+GIS信息的加载。前几年一直没完成的作品,今天随手完成了。感慨一下,AI真是强大。
以前还是使用threejs+Cesium叠加来完成的,在控制上是以Cesium为主,Cesium非常笨重,想做好相机的控制,对不熟悉它的人来说真难,而且在渲染效果上也有不小的差距。
而现在,如果只是一个项目的周边环境分析,利用threejs简单载入一下天地图的切片,效果也完全没有问题,而它从根本上还是一个BIM模型浏览器,只是多了载入地图的能力。
看下效果:
核心代码示例:
function lonLatToTile(lon, lat, zoom) {
const n = Math.pow(2, zoom);
const x = Math.floor((lon + 180) / 360 * n);
const latRad = lat * (Math.PI / 180);
const y = Math.floor((1 - Math.log(Math.tan(latRad) + (1 / Math.cos(latRad))) / Math.PI) / 2 * n);
return { x, y };
}
function getTileRange(minLon, minLat, maxLon, maxLat, zoom) {
const minTile = lonLatToTile(minLon, minLat, zoom);
const maxTile = lonLatToTile(maxLon, maxLat, zoom);
return {
minX: Math.min(minTile.x, maxTile.x),
maxX: Math.max(minTile.x, maxTile.x),
minY: Math.min(minTile.y, maxTile.y),
maxY: Math.max(minTile.y, maxTile.y)
};
}
import * as THREE from 'three';
// 初始化Three.js场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 天地图瓦片服务地址模板
const tileUrlTemplate = 'http://t{0-7}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=your_token';
const zoom = 10;
const minLon = 116.0;
const minLat = 39.0;
const maxLon = 117.0;
const maxLat = 40.0;
const tileRange = getTileRange(minLon, minLat, maxLon, maxLat, zoom);
for (let x = tileRange.minX; x <= tileRange.maxX; x++) {
for (let y = tileRange.minY; y <= tileRange.maxY; y++) {
const tileUrl = tileUrlTemplate.replace('{z}', zoom).replace('{x}', x).replace('{y}', y).replace('{0-7}', Math.floor(Math.random() * 8));
const textureLoader = new THREE.TextureLoader();
textureLoader.load(tileUrl, (texture) => {
const geometry = new THREE.PlaneGeometry(1, 1);
const material = new THREE.MeshBasicMaterial({ map: texture });
const mesh = new THREE.Mesh(geometry, material);
mesh.position.set(x - tileRange.minX, -(y - tileRange.minY), 0);
scene.add(mesh);
});
}
}