在开发一些物联网、数字孪生Web3D可视化项目的时候,比如一个工厂、化工厂、变电站、园区等场景,有时候,需要进行一些尺寸测量,比如属于鼠标点击选择模型表面上两点,然后计算两点之间尺寸距离,然后使用箭头和数字进行标注。
3D在线测量 体验地址( 先用鼠标点击按钮进入测量状态,在通过鼠标点击拾取模型任意两点,然后会自动标注 )
代码参考资料:threej中文网:http://www.webgl3d.cn/
模型表面选择两点( 用于尺寸标注计算 )
比如鼠标单击时候,通过射线从threejs模型表面Mesh上获取到两个坐标点,然后计算两点之间距离尺寸。
如果你不了解射线,更多关于射线具体内容参考threej中文网介绍
// 射线拾取选择场景模型表面任意点xyz坐标
function rayChoosePoint(event, model, camera) {
const px = event.offsetX;
const py = event.offsetY;
//屏幕坐标转标准设备坐标
const x = (px / window.innerWidth) * 2 - 1;
const y = -(py / window.innerHeight) * 2 + 1;
const raycaster = new THREE.Raycaster();
//.setFromCamera()在点击位置生成raycaster的射线ray
raycaster.setFromCamera(new THREE.Vector2(x, y), camera);
// 射线交叉计算拾取模型
const intersects = raycaster.intersectObject(model, true);
let v3 = null;
if (intersects.length > 0) {
// 获取模型上选中的一点坐标
v3 = intersects[0].point
}
return v3;
}
计算两点之间距离
通过向量可以计算两点之间距离,如果你不了解向量相关数学几何计算,参考threej中文网进阶内容
两点坐标p1、p2相减返回一个向量,计算向量长度,表示两点之间距离
// 计算模型上选中两点的距离
function length(p1, p2) {
return p1.clone().sub(p2).length()
}
线段可视化两点之间距离
你可以用一条线段,线段两端使用三角形、小球或者箭头标注下,把要标注的两个点p1、p2可视化出来。
两点之间绘制一条直线线段,把p1到p2两点之间的距离可视化表示出来。
// 两点绘制一条直线 用于标注尺寸
function createLine(p1, p2) {
const material = new THREE.LineBasicMaterial({
color: 0xffff00,
depthTest: false,//不进行深度测试,后渲染,叠加在其它模型之上(解决两个问题)
// 1.穿过模型,在内部看不到线条
// 2.线条与mesh重合时候,深度冲突不清晰
});
const geometry = new THREE.BufferGeometry(); //创建一个几何体对象
//类型数组创建顶点数据
const vertices = new Float32Array([p1.x, p1.y, p1.z, p2.x, p2.y, p2.z]);
geometry.attributes.position = new THREE.BufferAttribute(vertices, 3);
const line = new THREE.Line(geometry, material);
return line
}
//如果你想绘制有粗细的线段,可以参考threejs扩展库:Line2.js
线段两个端点位置,可以用箭头、小球、三角形平面、直线端等等任何你想要的形状可视化
比如圆锥形状箭头
function createMesh(p,dir,camera) {
const L = camera.position.clone().sub(p).length()
const h = L/20
//尺寸你可以根据需要自由设置,比如距离相机距离,比如直接根据场景渲染范围给固定尺寸
const geometry = new THREE.CylinderGeometry(0,L/200,h);
geometry.translate(0,-h/2,0)
const material = new THREE.MeshBasicMaterial({
color: 0x00ffff, //设置材质颜色
depthTest: false,
});
const mesh = new THREE.Mesh(geometry, material);
//通过四元数表示默认圆锥需要旋转的角度,才能和标注线段的方向一致
const quaternion = new