欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > 使用three.js 实现测量

使用three.js 实现测量

2024/10/25 10:29:07 来源:https://blog.csdn.net/guang2586/article/details/142638350  浏览:    关键词:使用three.js 实现测量

使用three.js 实现测量
在这里插入图片描述

在线预览https://threehub.cn/#/codeMirror?navigation=ThreeJS&classify=application&id=lineMeasure

在 https://threehub.cn 中还有很多案例

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script type="importmap">
{"imports": {"three": "https://threejs.org/build/three.module.min.js","three/addons/": "https://threejs.org/examples/jsm/","three/examples/jsm/": "https://threejs.org/examples/jsm/","gsap": "https://file.threehub.cn/js/gsap/index.js","postprocessing": "https://threehub.cn/js/postprocessing.js","cannon-es": "https://threehub.cn/js/cannon-es.js","dat.gui": "https://threehub.cn/js/dat.gui.module.js","@tweenjs/tween.js": "https://threehub.cn/js/tween.esm.js"}
}
</script>
<style>body {margin: 0;padding: 1px;box-sizing: border-box;background-color: #1f1f1f;display: flex;flex-direction: column;width: 100vw;height: 100vh;overflow: hidden;}#box {width: 100%;height: 100%;}
</style>
</head>
<body>
<div id="box"></div>
<script type="module">
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { TransformControls } from "three/addons/controls/TransformControls.js";const worldToScreenPosition = (pos, camera) => {// 三维坐标转换成屏幕坐标const worldVector = new THREE.Vector3(pos.x, pos.y, pos.z);const standardVector = worldVector.project(camera);const widthHalf = window.innerWidth / 2;const heightHalf = window.innerHeight / 2;return {x: Math.round(standardVector.x * widthHalf + widthHalf),y: Math.round(-standardVector.y * heightHalf + heightHalf),z: 1,};
}let renderer, scene, camera, orbitControls, transformControls;let plane;
let raycaster = new THREE.Raycaster();
let intersects;
let mouse = new THREE.Vector2();
let markersGroup = new THREE.Group();
let markers = [];
let points = [];
let vec2Array = [];
let dashLine;
let line;
let canDrawLine = true;
let mesh;
let index = 0;
let distanceArray = [];
let distance = 0;
let totalDistance = 0;
let geometry = null;
let distanceDom = null;
let nextPoint = null;init();
animate();function init() {renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setPixelRatio(window.devicePixelRatio);renderer.setSize(window.innerWidth, window.innerHeight);renderer.outputEncoding = THREE.sRGBEncoding;document.body.appendChild(renderer.domElement);scene = new THREE.Scene();scene.background = new THREE.Color(0xbfe3dd);scene.add(markersGroup);camera = new THREE.PerspectiveCamera(40,window.innerWidth / window.innerHeight,1,100);camera.position.set(10, 10, 10);//planelet planeGeo = new THREE.PlaneGeometry(40, 40, 40);let planeMat = new THREE.MeshBasicMaterial({ color: 0x6666666 });plane = new THREE.Mesh(planeGeo, planeMat);plane.rotation.x = -Math.PI / 2;scene.add(plane);// orbitorbitControls = new OrbitControls(camera, renderer.domElement);orbitControls.target.set(0, 0.5, 0);orbitControls.update();orbitControls.enableDamping = true;// transformtransformControls = new TransformControls(camera, renderer.domElement);transformControls.addEventListener("dragging-changed", onDragChanged);transformControls.addEventListener("mouseUp", onDragend);transformControls.addEventListener("change", onDragChanging);scene.add(transformControls);function onDragChanged(event) {orbitControls.enabled = !event.value;}document.body.addEventListener("mousedown", onMousedown, false);document.body.addEventListener("mousemove", onMousemove, false);window.onresize = function () {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);};
}
function animate() {requestAnimationFrame(animate);orbitControls.update();renderer.render(scene, camera);
}
function onDragChanging(event) {if (points.length < 2) return;let point = mesh.position;let _idx = mesh._idx;updatePoints(points, _idx, point);totalDistance = updateDistanceArray(points, distanceArray);distanceDom.innerHTML = totalDistance.toFixed(2) + "m";const positions ="array" in line.geometry.attributes.position &&line.geometry.attributes.position.array;if (_idx === 0) {positions[0] = point.x;positions[1] = point.y;positions[2] = point.z;} else {let i = (2 * _idx - 1) * 3;positions[i] = point.x;positions[i + 1] = point.y;positions[i + 2] = point.z;positions[i + 3] = point.x;positions[i + 4] = point.y;positions[i + 5] = point.z;}line.geometry.attributes.position.needsUpdate = true;
}
function onDragend() {console.log(111);transformControls.detach();
}
function onMousedown(event) {raycaster.setFromCamera(mouse, camera);if (canDrawLine) {// 右键点击之后停止测距if (event.button === 2) {canDrawLine = false;}if (points.length > 0) {distanceArray.push(distance);totalDistance += distance;distance = 0}intersects = raycaster.intersectObject(plane);if (intersects.length === 0) return;let point = intersects[0].point;let newPoint = new THREE.Vector3(point.x, point.y, point.z);// 判断是否绘制完成if (points.length > 0 && canDrawLine === true) {points.push(newPoint, newPoint);} else {points.push(newPoint);}// 添加节点let marker = new THREE.Mesh(new THREE.SphereGeometry(0.1, 30, 30),new THREE.MeshBasicMaterial({ color: 0xff5fff }));marker._idx = index;marker.position.set(newPoint.x, newPoint.y, newPoint.z);markersGroup.add(marker);markers.push(marker);// 记录场景中点位的数量index++;if (!distanceDom) {distanceDom = document.createElement("span");distanceDom.style.position = "absolute";distanceDom.style.top = "0";distanceDom.style.color = "red";distanceDom.style.pointerEvents = "none";document.body.appendChild(distanceDom);}if (points.length > 1) {createLine(scene, points);}if (!canDrawLine) {scene.remove(dashLine);return;}// 如果存在虚线,更新虚线位置if (dashLine) {const positions ="array" in dashLine.geometry.attributes.position &&dashLine.geometry.attributes.position.array;positions[0] = positions[3];positions[1] = positions[4];positions[2] = positions[5];positions[3] = newPoint.x;positions[4] = newPoint.y;positions[5] = newPoint.z;dashLine.geometry.attributes.position.needsUpdate = true;} else {geometry = new THREE.BufferGeometry().setFromPoints([newPoint,newPoint,]);dashLine = new THREE.LineSegments(geometry,new THREE.LineDashedMaterial({color: 0xff5555,transparent: true,depthTest: false,dashSize: 0.1,gapSize: 1,}));dashLine.frustumCulled = false;dashLine.name = "dashLine";scene.add(dashLine);}} else {intersects = raycaster.intersectObject(markersGroup);if (intersects.length === 0) return;mesh = intersects[0].object;transformControls.attach(mesh);}
}
function updateLinePoints(line, point, arrayIndex) {const positions ="array" in line.geometry.attributes.position &&line.geometry.attributes.position.array;positions[arrayIndex] = point.x;positions[arrayIndex + 1] = point.y;positions[arrayIndex + 2] = point.z;line.geometry.attributes.position.needsUpdate = true;
}
function onMousemove(event) {event.preventDefault();mouse.x = (event.clientX / renderer.domElement.offsetWidth) * 2 - 1;mouse.y = -(event.clientY / renderer.domElement.offsetHeight) * 2 + 1;if (!canDrawLine) return;raycaster.setFromCamera(mouse, camera);intersects = raycaster.intersectObject(plane);if (!intersects.length) return;nextPoint = intersects[0].point;if (points.length > 0) {const pre = points[points.length - 1];const v0 = new THREE.Vector3(pre.x, pre.y, pre.z);const v1 = new THREE.Vector3(nextPoint.x, nextPoint.y, nextPoint.z);distance = v0.distanceTo(v1);}if (!dashLine) return;updateLinePoints(dashLine, nextPoint, 3);
}
function createLine(scene, points) {if (line) scene.remove(line);geometry = new THREE.BufferGeometry().setFromPoints([...points]);line = new THREE.LineSegments(geometry,new THREE.LineBasicMaterial({color: 0xfff000,transparent: true,depthTest: false,}));line.renderOrder = 10;line.name = "line";line.onBeforeRender = () => {if (distanceDom) {let v = worldToScreenPosition(nextPoint, camera);distanceDom.style.left = v.x + 15 + "px";distanceDom.style.top = v.y - 15 + "px";distanceDom.innerHTML = (distance + totalDistance).toFixed(2) + "m";}};scene.add(line);
}
function updatePoints(points, index, point) {if (index === 0) {points[index] = point;} else if (index === points.length / 2) {points[points.length - 1] = point;nextPoint = points[points.length - 1];} else {points[2 * index - 1] = point;points[2 * index] = point;}
}
function updateDistanceArray(points, array) {let distance = 0;for (let i = 0; i < array.length; i++) {array[i] = points[2 * i].distanceTo(points[2 * i + 1]);distance += array[i];}return distance;
}
function dispose() {scene.traverse((e) => {if (e instanceof THREE.Mesh) {e.geometry.dispose();e.material.dispose();}});scene.clear();renderer.dispose();renderer.forceContextLoss();
}
</script>
</body>
</html>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com