vue3 + potree 渲染点云数据记录

potree 官网示例
在这里插入图片描述

前置条件:

potree 无法直接加载 LAS,LCD,PLY等格式的点云文件,
需要通过 PotreeConverte 转换为 octree 数据格式,前端渲染中加载转换后的 json 格式

格式转换方向
.las ---- potreeConverter ----> .json

结合 vue3 使用

1、模板 html 引入 potree 官网示例中的所有 js 依赖

potree 示例中的 js 依赖如下:
在这里插入图片描述
确保能在 vue 项目中,window 中有 potree

2、创建渲染视图区域组件

在这里插入图片描述
组件挂载后初始化 viewer

// 全局常量
const Potree = window.Potree;
const THREE = window.THREE;
const i18next = window.i18next;
const TWEEN = window.TWEEN;const viewer: Ref = ref(null); // viewer 容器// 初始化视图容器const initViewer = () => {if (!Potree || viewer.value) return;let viewerArgs = {noDragAndDrop: true,};viewer.value = new Potree.Viewer(document.getElementById(`potree_render_area${areaIdIndex}`),viewerArgs,);// 创建原始引用const Viewer = toRaw(viewer.value)// 设置裁剪属性Viewer.setClipTask(Potree.ClipTask.SHOW_INSIDE);Viewer.loadGUI();// 禁用 edlViewer.setEDLEnabled(false);// 设置视场角Viewer.setFOV(60);// viewer最大可视点云数量固定Viewer.setPointBudget(50 * 1000 * 1000);Viewer.loadSettingsFromURL();// 设置天背景Viewer.setBackground('black');Viewer.setDescription('');Viewer.setMinNodeSize(0);Viewer.setControls(Viewer.earthControls);// 官方 自带 GUi// this.viewer.loadGUI(() => {//   this.viewer.setLanguage('zh');//   window.$('#menu_tools').next().show();//   window.$('#menu_clipping').next().show();//   this.viewer.toggleSidebar();// });// 注册 Sidebarsidebar = new Sidebar(Viewer)sidebar.init()console.log('viewer initialized');};onMounted(() => {nextTick(() => {// 挂载后初始化视图initViewer();});});
3、加载点云数据
      Potree.loadPointCloud(path).then((e: any) => {// PointCloudOctree实例// 该实例有唯一的uuid,可以保存起来方便后续对该实例进行操作let pointcloud = e.pointcloud;// console.log(pointcloud)appStore.setOriginFileUuid(fileId, pointcloud.uuid)// 材质let material = pointcloud.material;// name赋值// pointcloud.name = 'fileName';// 检查是否有彩色信息let hasRGBA =pointcloud.getAttributes().attributes.find((a: any) => a.name === 'rgba') !== undefined;if (hasRGBA) {material.activeAttributeName = 'rgba';} else {material.activeAttributeName = 'color';}// 点云点大小material.size = 1;material.minSize = 1;material.maxSize = 16;material.pointSizeType = Potree.PointSizeType.FIXED;// 设置高程渐变方案material.gradient = Potree.Gradients.TURBO;// 将点云数据添加到场景viewer.value.scene.addPointCloud(pointcloud);viewer.value.setBackground('black');// 设置相机viewer.value.zoomTo(e.pointcloud);// 设置控制器// viewer.value.setControls(viewer.value.earthControls);// 设置视场角viewer.value.setFOV(60);// 设置最小节点大小,值越小越清晰viewer.value.setMinNodeSize(0);// 打开高质量渲染viewer.value.useHQ = false;// 点云数量fetch(path).then((response) => response.json()).then((jsonData) => {// name赋值pointcloud.name = jsonData.name;// 点云数量// 根据导入的点云数据来设置对应的点云数量// viewer.value.setPointBudget(jsonData.points);// 设置点云数量pointcloud.pointBudget = jsonData.points;// 设置初始视角viewer.value.scene.view.setView(new THREE.Vector3(6.44, -6.70, 5.52), new THREE.Vector3(-0.53, 0.55, -0.63));viewer.value.scene.view.lookAt(-0.53, 0.55, -0.63);});})
4、结合官网提供的 工具栏代码,进行其他深入操作
export class Sidebar {viewer: anymeasuringTool: anyprofileTool: anyvolumeTool: anyconstructor(viewer: any) {this.viewer = viewer;this.measuringTool = viewer.measuringTool;this.profileTool = viewer.profileTool;this.volumeTool = viewer.volumeTool;}initScene() {// 监听点云追加let onPointCloudAdded = (e: any) => {let pointcloud: any = e.pointcloud;console.log('initScene--pointcloud------>')console.log(pointcloud)SceneObj.pointclouds.push(pointcloud)// let cloudIcon = `${Potree.resourcePath}/icons/cloud.svg`;// let node = createNode(pcID, pointcloud.name, cloudIcon, pointcloud);pointcloud.addEventListener("visibility_changed", () => {console.log(pointcloud.visible)if (pointcloud.visible) {// tree.jstree('check_node', node);} else {// tree.jstree('uncheck_node', node);}});};// 监听测量对象let onMeasurementAdded = (e: any) => {let measurement = e.measurement;console.log('添加测量对象')// console.log(measurement);nextTick(() => {setTimeout(() => {const meItem = {checked: true,label: measurement.name,id: measurement.uuid,}console.log(e.scene.measurements);// 追加测量对象数appStore.addMeasurementsTreeData(meItem, measurement.uuid)// let icon = Utils.getMeasurementIcon(measurement);// createNode(measurementID, measurement.name, icon, measurement);}, 0);})};// 监听体积增加let onVolumeAdded = (e: any) => {let volume = e.volume;// let icon = Utils.getMeasurementIcon(volume);// let node = createNode(measurementID, volume.name, icon, volume);volume.addEventListener("visibility_changed", () => {console.log(volume)if (volume.visible) {// tree.jstree('check_node', node);} else {// tree.jstree('uncheck_node', node);}});};// 监听高度坡面增加let onProfileAdded = (e: any) => {let profile = e.profile;// let icon = Utils.getMeasurementIcon(profile);// createNode(measurementID, profile.name, icon, profile);};// 监听标注事件let onAnnotationAdded = (e: any) => {let annotation = e.annotation;// let annotationIcon = `${Potree.resourcePath}/icons/annotation.svg`;// let parentID = this.annotationMapping.get(annotation.parent);// let annotationID = createNode(parentID, annotation.title, annotationIcon, annotation);// this.annotationMapping.set(annotation, annotationID);// annotation.addEventListener("annotation_changed", (e) => {//   let annotationsRoot = $("#jstree_scene").jstree().get_json("annotations");//   let jsonNode = annotationsRoot.children.find(child => child.data.uuid === annotation.uuid);//   $.jstree.reference(jsonNode.id).rename_node(jsonNode.id, annotation.title);// });};// 相机动作let onCameraAnimationAdded = (e: any) => {const animation = e.animation;// const animationIcon = `${Potree.resourcePath}/icons/camera_animation.svg`;// createNode(otherID, "animation", animationIcon, animation);};// 向导图let onOrientedImagesAdded = (e: any) => {const images = e.images;// const imagesIcon = `${Potree.resourcePath}/icons/picture.svg`;// const node = createNode(imagesID, "images", imagesIcon, images);images.addEventListener("visibility_changed", () => {console.log('images.visible', images.visible)if (images.visible) {// tree.jstree('check_node', node);} else {// tree.jstree('uncheck_node', node);}});};// img 360let onImages360Added = (e: any) => {const images = e.images;// const imagesIcon = `${Potree.resourcePath}/icons/picture.svg`;// const node = createNode(imagesID, "360° images", imagesIcon, images);images.addEventListener("visibility_changed", () => {console.log('360images.visible', images.visible)if (images.visible) {// tree.jstree('check_node', node);} else {// tree.jstree('uncheck_node', node);}});};// 地质const onGeopackageAdded = (e: any) => {const geopackage = e.geopackage;// const geopackageIcon = `${Potree.resourcePath}/icons/triangle.svg`;// const tree = $(`#jstree_scene`);// const parentNode = "vectors";// for (const layer of geopackage.node.children) {//   const name = layer.name;//   let shpPointsID = tree.jstree('create_node', parentNode, {//     "text": name,//     "icon": geopackageIcon,//     "object": layer,//     "data": layer,//   },//     "last", false, false);//   tree.jstree(layer.visible ? "check_node" : "uncheck_node", shpPointsID);// }};this.viewer.scene.addEventListener("pointcloud_added", onPointCloudAdded);this.viewer.scene.addEventListener("measurement_added", onMeasurementAdded);this.viewer.scene.addEventListener("profile_added", onProfileAdded);this.viewer.scene.addEventListener("volume_added", onVolumeAdded);this.viewer.scene.addEventListener("camera_animation_added", onCameraAnimationAdded);this.viewer.scene.addEventListener("oriented_images_added", onOrientedImagesAdded);this.viewer.scene.addEventListener("360_images_added", onImages360Added);this.viewer.scene.addEventListener("geopackage_added", onGeopackageAdded);this.viewer.scene.addEventListener("polygon_clip_volume_added", onVolumeAdded);this.viewer.scene.annotations.addEventListener("annotation_added", onAnnotationAdded);/*** 删除操作*/// let onMeasurementRemoved = (e) => {//   let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");//   let jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.measurement.uuid);//   tree.jstree("delete_node", jsonNode.id);// };// let onVolumeRemoved = (e) => {//   let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");//   let jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.volume.uuid);//   tree.jstree("delete_node", jsonNode.id);// };// let onPolygonClipVolumeRemoved = (e) => {//   let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");//   let jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.volume.uuid);//   tree.jstree("delete_node", jsonNode.id);// };// let onProfileRemoved = (e) => {//   let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");//   let jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.profile.uuid);//   tree.jstree("delete_node", jsonNode.id);// };// this.viewer.scene.addEventListener("measurement_removed", onMeasurementRemoved);// this.viewer.scene.addEventListener("volume_removed", onVolumeRemoved);// this.viewer.scene.addEventListener("polygon_clip_volume_removed", onPolygonClipVolumeRemoved);// this.viewer.scene.addEventListener("profile_removed", onProfileRemoved);// {//   let annotationIcon = `${Potree.resourcePath}/icons/annotation.svg`;//   this.annotationMapping = new Map();//   this.annotationMapping.set(this.viewer.scene.annotations, annotationsID);//   this.viewer.scene.annotations.traverseDescendants(annotation => {//     let parentID = this.annotationMapping.get(annotation.parent);//     let annotationID = createNode(parentID, annotation.title, annotationIcon, annotation);//     this.annotationMapping.set(annotation, annotationID);//   });// }const scene = this.viewer.scene;for (let pointcloud of scene.pointclouds) {onPointCloudAdded({ pointcloud: pointcloud });}for (let measurement of scene.measurements) {onMeasurementAdded({ measurement: measurement });}for (let volume of [...scene.volumes, ...scene.polygonClipVolumes]) {onVolumeAdded({ volume: volume });}for (let animation of scene.cameraAnimations) {onCameraAnimationAdded({ animation: animation });}for (let images of scene.orientedImages) {onOrientedImagesAdded({ images: images });}for (let images of scene.images360) {onImages360Added({ images: images });}for (const geopackage of scene.geopackages) {onGeopackageAdded({ geopackage: geopackage });}for (let profile of scene.profiles) {onProfileAdded({ profile: profile });}// {//   createNode(otherID, "Camera", null, new Camera());// }this.viewer.addEventListener("scene_changed", (e: any) => {// propertiesPanel.setScene(e.scene);e.oldScene.removeEventListener("pointcloud_added", onPointCloudAdded);e.oldScene.removeEventListener("measurement_added", onMeasurementAdded);e.oldScene.removeEventListener("profile_added", onProfileAdded);e.oldScene.removeEventListener("volume_added", onVolumeAdded);e.oldScene.removeEventListener("polygon_clip_volume_added", onVolumeAdded);// e.oldScene.removeEventListener("measurement_removed", onMeasurementRemoved);e.scene.addEventListener("pointcloud_added", onPointCloudAdded);e.scene.addEventListener("measurement_added", onMeasurementAdded);e.scene.addEventListener("profile_added", onProfileAdded);e.scene.addEventListener("volume_added", onVolumeAdded);e.scene.addEventListener("polygon_clip_volume_added", onVolumeAdded);// e.scene.addEventListener("measurement_removed", onMeasurementRemoved);});}init() {this.initScene();}
}

参考学习:potree 使用手册
鸣谢作者;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/305079.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python-常用数据结构(1)

1、从键盘输人一个正整数列表,以一1结束,分别计算列表中奇数和偶数的和。 (1)源代码: n int(input("请输入一个正整数:")) list [] while n ! -1: list.append(n) n int(input("请输入一个正整数:&…

示波器接上机器板子信号就正常工作,拿下来就机器不正常工作

系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 送给大学毕业后找不到奋斗方向的你(每周不定时更新) 【牛客网】构建从学习到职业的良性生态圈 中国计算…

算法:计数类dp

文章目录 一、举个栗子例子1:爬楼梯问题例子2:不同路径例子3:计数子序列 二、基本思路三、典型例题一、ACWing:900. 整数划分1、解法一1.1、状态转移方程1.2、参考代码 O(n) 超时 2、解法二:类似完全背包问题1.1、状态…

C语言——详解字符函数和字符串函数(二)

Hi,铁子们好呀!之前博主给大家简单地介绍了部分字符和字符串函数,那么这次,博主将会把这些字符串函数给大家依次讲完! 今天讲的具体内容如下: 文章目录 6.strcmp函数的使用及模拟实现6.1 strcmp函数介绍和基本使用6.1.1 strcmp函…

消息队列之-----------------zookeeper机制

目录 一、ZooKeeper是什么 二、ZooKeeper的工作机制 三、ZooKeeper特点 四、ZooKeeper数据结构 五、ZooKeeper应用场景 5.1统一命名服务 5.2统一配置管理 5.3统一集群管理 5.4服务器动态上下线 5.5软负载均衡 六、ZooKeeper的选举机制 6.1第一次启动选举机制 6.2非…

uniapp极光推送、java服务端集成

一、准备工作 1、进入【服务中心】-【开发者平台】 2、【创建应用】,填写应用名称和图标(填写项目名称,项目logo就行,也可填写其他的) 3、选择【消息推送】服务,点击下一步 ​ ​ Demo测试 参照文档&…

第15届蓝桥STEMA测评真题剖析-2024年3月10日Scratch编程初中级组

[导读]:超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成,后续会不定期解读蓝桥杯真题,这是Scratch蓝桥杯真题解析第180讲。 第15届蓝桥第5次STEMA测评,这是2024年3月10日举办的STEMA,比赛仍然采取线上形式。这…

达梦关键字(如:XML,EXCHANGE,DOMAIN,link等)配置忽略

背景:在使用达梦数据库时,查询SQL中涉及XML,EXCHANGE,DOMAIN,link字段,在达梦中是关键字,SQL报关键词不能使用的错误。 解决办法: 配置达梦安装文件E:\MyJava\dmdbms\data\DAMENG\dm.ini 忽略这些关键词,…

【Linux】shell 脚本基础使用

在终端中输入命令可以完成一些常用的操作,但是我们都是一条一条输入命令,比较麻烦,为了解决这个问题,就会涉及到 shell 脚本,它可以将很多条命令放到一个文件里面,然后直接运行这个文件即可。 shell 脚本类…

Jupyter Notbook如何安装配置并结合内网穿透实现无公网IP远程连接使用

文章目录 推荐1.前言2.Jupyter Notebook的安装2.1 Jupyter Notebook下载安装2.2 Jupyter Notebook的配置2.3 Cpolar下载安装 3.Cpolar端口设置3.1 Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂&am…

分类预测 | Matlab实现KPCA-IDBO-LSSVM基于核主成分分析和改进蜣螂优化算法优化最小二乘支持向量机分类预测

分类预测 | Matlab实现KPCA-IDBO-LSSVM基于核主成分分析和改进蜣螂优化算法优化最小二乘支持向量机分类预测 目录 分类预测 | Matlab实现KPCA-IDBO-LSSVM基于核主成分分析和改进蜣螂优化算法优化最小二乘支持向量机分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述…

炒股自动化:交易接口API才是重点,券商官方散户可用的接口

上一篇我们用get_full_tick取到了数据,也讲了变量和字典的基本概念,这次我们向交易所发送订单试试。前面文章的链接放在文末了,需要的可以看一下 这些内容是给新手看的,找接口的大佬们直接拉到文末即可 取市场数据的方法很多&am…

【MATLAB源码-第12期】基于matlab的4FSK(4CPFSK)的误码率BER理论值与实际值仿真。

1、算法描述 4FSK在频移键控(FSK)编码的基础上有所扩展。FSK是一种调制技术,它通过在不同频率上切换来表示不同的数字或符号。而4FSK则是FSK的一种变种,表示使用了4个不同的频率来传输信息。 在4FSK中,每个数字或符号…

ONERugged车载平板电脑厂家丨工业车载电脑优势体现丨3年质保

作为现代社会中必不可少的出行工具,汽车不仅仅是代步工具,更是我们生活中的重要一部分。而在如此多功能的汽车内,一款高可靠性、适应不同行业应用的车载平板电脑成为了当下的热门选择。ONERugged车载平板电脑以其卓越的品质和强大的功能而备受…

post请求搜索功能爬虫

<!--爬虫仅支持1.8版本的jdk--> <!-- 爬虫需要的依赖--> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.2</version> </dependency>…

git配置多SSH

目的&#xff1a; 一台电脑可以让github、gitee等账号同时存在&#xff0c;让不同账号配置不同的密钥 第一步&#xff1a;创建不同平台的SSH公钥 执行命令&#xff1a; ssh-keygen -t rsa -C "对应仓库邮箱地址" -f ~/.ssh/id_rsa.github 如果执行上面的命令&…

头歌机器学习实验 第7次实验 局部加权线性回归

任务描述 本关任务&#xff1a;编写一个利用局部加权计算回归系数的小程序。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.局部加权算法的思想&#xff1b;2.局部加权的核心算法。 局部加权算法的思想 在局部加权算法中 &#xff0c;我们给待预测点附近…

探索设计模式的魅力:MVVM模式在AI大模型领域的创新应用-打破传统,迎接智能未来

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 MVVM模式在AI大模型领域的创新应用-打破传统迎接智能未来 &#x1f680; “在人工智能的领域里&a…

08 - 镜像管理之:镜像仓库harbor介绍

本文参考&#xff1a;原文1 1 Harbor仓库介绍 Docker容器应用的开发和运行离不开可靠的镜像管理&#xff0c;虽然Docker官方也提供了公共的镜像仓库&#xff0c;但是从安全和效率等方面考虑&#xff0c;部署我们私有环境内的Registry 也是非常必要的。 之前介绍了Docker私有仓…

CSS设置文本

目录 概述&#xff1a; text-aling: text-decoration: text-transform: text-indent: line-height: letter-spacing: word-spacing: text-shadow: vertical-align: white-space: direction: 概述&#xff1a; 在CSS中我们可以设置文本的属性&#xff0c;就像Word文…