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.mzph.cn/news/808034.shtml

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

相关文章

算法练习第15天|226.翻转二叉树

226.翻转二叉树 力扣链接https://leetcode.cn/problems/invert-binary-tree/description/ 题目描述: 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 示例 1: 输入:root [4,2,7,1,3,6,9] 输出&am…

关于无人机,你必须知道的事!!(科技篇)

飞行器的五脏六腑 电机:无人机的动力单元,俗称“马达”。通过电机转动来驱动螺旋桨旋转,最终让飞机上天。 电调:无人机的动力单元,是接收油门信号并调整电机转速的控制枢纽,俗称电机的“黑屋调教师” 飞…

探索计算机的小数世界:从二进制到无限精度

前言 不知道你是否和我一样,遇到这个情况。在刚开始学习编程。计算0.3-0.20.1这个小学都知道,但是如果你在计算机执行,发现结果并不是0.1 。这个时候会疑问到底是为什么呢。 System.out.println("0.3-0.2"(0.3-0.2)); 0.3-0.20.09…

API管理平台:你用的到底是哪个?

Apifox是不开源的,在github的项目只是readme文件,私有化需要付费。当然saas版目前是免费使用的。 一、Swagger 为了让Swagger界面更加美观,有一些项目可以帮助你实现这一目标。以下是一些流行的项目,它们提供了增强的UI和额外的功…

OSCP靶场-- Sybaris

OSCP靶场–Sybaris 考点(redis MODULE LOAD命令执行) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.158.93 -sV -sC -Pn --min-rate 2500 -p- Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-11 04:24 EDT Nmap scan report for 192.168.158.93…

照片转漫画的软件有吗?分享4款热门的软件!

在数字化时代,我们总是追求新鲜、有趣、创意十足的方式来展现自我。其中,将普通照片转化为漫画风格的图像已成为许多年轻人的新宠。这种既能保留原照片中的人物特征,又能赋予其独特艺术气息的方式,让许多人趋之若鹜。那么&#xf…

PHP7垃圾回收算法

前提 本文为了梳理PHP GC工作流程,所以从引用计数、部分标记清除算法做引子,然后介绍PHP GC工作流程,最后介绍性能更高的GC算法 引用计数 概述 引用计数算法中引入了一个概念计数器。计数器代表对象被引用的次数 基本原理 为了记录一个对象有没有被…

微信公众号第三方平台-公众号扫码授权接入代运营

文章目录 接入目的效果展示技术积累如何成为服务商如何搭建第三方后端服务传统模式V云服务模式如何完成商家授权授权逻辑介绍 环境准备注册开发者平台-个人类型 传统模式后端代码接收公众号个人三方平台的票据根据票据获取三方平台访问令牌根据访问令牌获取预授权码通过预授权码…

OJ 【难度1】【Python】完美字符串 扫雷 A-B数对 赛前准备 【C】精密计时

完美字符串 题目描述 你可能见过下面这一句英文: "The quick brown fox jumps over the lazy dog." 短短的一句话就包含了所有 2626 个英文字母!因此这句话广泛地用于字体效果的展示。更短的还有: "The five boxing wizards…

网络——初识网络

在现如今,网络已经成了一种基础设施,大到国家,小到个人,网络已经充斥在我们每个人的身 边,如果一个人突然失去了网络,那么它的生活或多或少会出现一些不方便的地方,网络现在已 经伴随着我们的吃…

Solana主网使用自定义的RPC进行转账

1、引言 如果用 browser 连接主网的 RPC server 会收到 error code 403 message 為 Access forbidden, contact your app developer or supportrpcpool.com. 错误,因为主网的 RPC server 会检查 HTTP Header 如果判断出來是 browser 就会报告 403 錯誤。 要解決这…

N 皇后 - 蓝桥杯?-Lua 中文代码解题第6题

n 皇后问题 研究的是如何将 n 个皇后放置在 n n 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。 示例 1: 输入:n 4 输出:2 解释:如上图所示&…

吴恩达2022机器学习专项课程(一) 5.2 向量化(1) 5.3 向量化(2)

问题预览/关键词 什么是向量化?向量化的好处是?如何向量化多元线性回归函数的参数?如何在Python中向量化参数?计算机底层是如何计算向量化的?向量化示例 笔记 1.向量化 一种在数学和计算中广泛使用的概念&#xff…

[Mac]安装App后“XX已损坏,无法打开“

问题: “xx.app”已损坏,无法打开。你应该将它移到废纸篓。 解决: 终端输入sudo xattr -r -d com.apple.quarantine 后将Applications中对应的问题app拖入生成路径,然后执行。 $ sudo xattr -r -d com.apple.quarantine /Appli…

备战蓝桥杯(日益更新)(刷题)

备战蓝桥杯(日益更新)(刷题) 文章目录 备战蓝桥杯(日益更新)(刷题)前言:一、二分:1. acwing503 借教室:(二分 差分)2. ac…

Socks5代理IP如何使用?详细教程解析

当我们在互联网上浏览网页、下载文件或者进行在线活动时,隐私和安全问题常常被提及。在这样的环境下,一个有效的解决方案是使用Sock5IP。本教程将向您介绍Sock5IP的使用方法,帮助您保护个人隐私并提升网络安全。 一、什么是Sock5IP&#xff1…

Mybatis-Plus使用入门

Mybatis-Plus 一、Mybatis-plus的简介 官方文档的地址: MyBatis-Plus (一)什么是Mybatis-Plus Mybatis-Plus是一个Mybatis(opens new window)的增强工具,在Mybatis的基础上只做增强不做改变&#xff0c…

ChatGPT在日常生活与工作中的应用,以及Hulu AI 的探索之旅

ChatGPT在日常生活与工作中的应用,以及Hulu AI 的探索之旅 💬ChatGPT 的多面应用💬Hulu AI:一个AI工具聚合平台的探索平台优势为何选择Hulu AI?珍稀优惠 💬结束语 在数字化快速发展的当下,人工智…

冯喜运:4.11外汇黄金原油晚间行情分析及独家作家操作建议

【 黄金消息面分析】:周四(4月11日)亚市早盘,现货黄金窄幅震荡,周三金价从纪录高位下滑,盘中一度失守2320关口至2319.一线,收报2333附近,因此前强于预期的通胀数据削弱了美国提前降息的预期,美元…

Python初级第二次作业

一、 def reverse(num):anumt0b0cnumwhile a//10>0:if a%10>0:t1aa//10print(t)for i in range(t,-1,-1):if c%100:b0else:b(c%10)*(10**i)c//10print(b) if bnum:return Trueelse:return Falsedef isPalind(num):kreverse(num)if kTrue:print(f"{num}是回文&…