将点云数据添加到threeJS的场景中

如何让将你的点云数据文件渲染到threeJS的场景中

1.解析文件

这里我的文件是csv文件。关于我为什么要选择csv文件存储而不是excel文件存储。

原因一

一般使用PapaParse可以直接读取和解析csv文件,使用SheetJ读取和解析excel文件。当然PapaParse也可以用来解析excel文件,但是需要先将excel文件转换为CSV使用。

原因二

考虑到这两个方法的特点和局限性
PapaParse
1.主要用途:PapaParse是一个快速、强大的CSV文件(以及类似文本文件)解析库,专注于大文件和性能
2.优点:
对大型CSV文件有优化,可以处理巨大的文件而不会冻结或崩溃浏览器支持流式解析,可以逐行解析数据,这有助于处理非常大的文件。
易于使用,有清晰的文档。
3.限制:主要用于解析CSV文件,对于Excel的.x1sx.x1s格式不是直接支持需要先将Excel文件转换为CSV格式。
SheetJS
1.主要用途:SheetJs(xlsx.js)是一个复杂的库,专门用于处理Excel文件(包括’.x1s·等格式)以及其他电子表格格式。xlsx`、
2.优点:
直接支持多种电子表格格式,包括Excel的.x1sx·和.x1s`格式,无需转换即可直接读取。提供了读取和写入电子表格的丰富功能,能够处理单元格格式、公式、日期等复杂数据。支持将电子表格转换成多种格式,包括JSON。
3.限制:
由于功能丰富,其体积相对较大,可能会影响到页面加载时间。处理非常大的Excel文件时,性能可能不如专门处理文本文件的PapaParse。
所以我选择使用PapaParse来解析csv文件。

2.创建点云材料和几何体

在Three.js中,可以使用PointsMaterial和BufferGeometry来创建点云。PointsMaterial允许定义点的颜色和大小,而BufferGeometry则用于存储点的位置信息。

将点云数据添加到场景中,点云渲染

有了几何体和材料,就可以通过将它们传递给THREE.Points来创建点云,并将该点云添加到场景中。
思路分析完毕现在开始上代码!

在HTML文件中添加这一行代码

    <script src="https://cdnjs.cloudflare.com/ajax/libs/papaparse/5.3.0/papaparse.min.js"></script>
    <input type="file" id="upload" accept=".csv" />
    <div id="3dScene"></div>

这个HTML文件包括一个文件输入,用于上传CSV文件。我会将JavaScript代码放在一个单独的文件中我这里是index.js。

在index.js中添加用于解析文件,创建模型和场景的代码

// 文件上传和解析
document.getElementById('upload').addEventListener('change', function(event) {
    const file = event.target.files[0];
    if (!file) {
        return;
    }

    const reader = new FileReader();
    reader.onload = function(e) {
        const text = e.target.result;
        const data = parseCSV(text);
        addPointCloud(data); // 调用添加点云函数
    };
    reader.readAsText(file);
});
// CSV解析函数(简单实现,仅适用于此特定格式)
function parseCSV(csvText) {
    const lines = csvText.split('\n').map(line => line.trim()).filter(line => line);
    // 跳过标题行,解析每行
    // return lines.slice(1).map(line => {
    //     const parts = line.split(',').map(part => parseFloat(part));
    //     return { x: parts[0], y: parts[1], z: parts[2], value: parts[3] };
    // });
    const data = lines.slice(1).map(line => {
        const parts = line.split(',').map(part => parseFloat(part));
        return { x: parts[0], y: parts[1], z: parts[2], value: parts[3] };
    });
    console.log(data); // 打印解析出的数据查看
    return data;
}
// 添加点云到场景的函数
function addPointCloud(data) {
    const geometry = new THREE.BufferGeometry();
    const positions = [];
    const colors = [];
    const color = new THREE.Color();

    data.forEach(point => {
        positions.push(point.x, point.y, point.z);
        // 使用value决定颜色,简单映射
        color.setHSL(point.value, 1.0, 0.5);
        colors.push(color.r, color.g, color.b);
    });

    geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
    geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));

    const material = new THREE.PointsMaterial({ size: 0.05, vertexColors: true });
    const points = new THREE.Points(geometry, material);
    console.log(`添加了${positions.length / 3}个点到场景中。`);
    scene.add(points);
}

接下来让我们分析一下这段代码

文件上传和解析

1.获取上传的文件:这段代码首先通过document.getElementById(‘upload’)获取页面上的文件上传元素(一个元素),然后为它添加一个change事件监听器。这意味着每当用户选择了一个文件,就会触发这个事件。

2.读取文件内容:一旦文件被选择,创建一个FileReader对象来异步读取文件内容。当读取操作完成后,触发onload事件,并执行一个函数来处理读取到的内容。

解析CSV内容:reader.onload函数中,e.target.result包含了文件的文本内容。这个内容被传递给parseCSV函数,该函数负责将CSV文本解析为JavaScript对象的数组。

CSV解析函数

function parseCSV(csvText) {
    const lines = csvText.split('\n').map(line => line.trim()).filter(line => line);
    const data = lines.slice(1).map(line => {
        const parts = line.split(',').map(part => parseFloat(part));
        return { x: parts[0], y: parts[1], z: parts[2], value: parts[3] };
    });
    console.log(data); // 打印解析出的数据查看
    return data;
}

1.拆分和清理数据:首先,csvText.split(‘\n’)按行拆分CSV文件的内容,.map(line => line.trim())移除每行前后的空白字符,.filter(line => line)过滤掉空行。

2.跳过标题行,解析数据行:lines.slice(1)跳过第一行(通常是标题行)。对于剩余的每一行,用逗号分隔并将每个部分转换为浮点数,创建一个包含x, y, z, value属性的对象。

3.打印和返回数据:通过console.log(data)打印解析后的数据,以便调试和查看,然后返回这个数据数组供后续使用。

添加点云到场景的函数

// 添加点云到场景的函数
function addPointCloud(data) {
    const geometry = new THREE.BufferGeometry();
    const positions = [];
    const colors = [];
    const color = new THREE.Color();

    data.forEach(point => {
        positions.push(point.x, point.y, point.z);
        // 使用value决定颜色,简单映射
        color.setHSL(point.value, 1.0, 0.5);
        colors.push(color.r, color.g, color.b);
    });

    geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
    geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));

    const material = new THREE.PointsMaterial({ size: 0.05, vertexColors: true });
    const points = new THREE.Points(geometry, material);
    console.log(`添加了${positions.length / 3}个点到场景中。`);
    scene.add(points);
}

1.准备点云数据:创建一个BufferGeometry对象来存储点云。对于每个点,将其x, y, z坐标添加到positions数组中,并根据点的value计算颜色值,添加到colors数组中。

2.设置几何属性:将positions和colors数组设置为几何体的属性,这样每个点的位置和颜色都被正确地定义了。

3.创建和添加点云:使用PointsMaterial和上一步定义的几何体创建一个Points对象(即点云)。这个对象随后被添加到场景中,以便渲染。

4.打印点的数量:最后,打印添加到场景中的点的数量,帮助调试和确认数据被正确处理。

这整个过程将CSV文件中的数据转换为Three.js场景中的点云,其中点的位置由CSV文件决定,颜色基于每个点的value值动态计算。

注意点1:

threeJS原点(0,0,0)默认位于场景的中心。
如果我们希望模型的一个角而不是中心对齐于原点(0,0,0),我们就需要调整模型的位置。我们需要将模型沿x轴和z轴正方向移动其一半的宽度和长度。

这是因为Three.js中的物体是根据它们的中心点进行定位的。当我们说一个物体位于(x,y,z)时,我们实际上是指物体的中心点位于(x,y,z)。因此,要使物体的一个角而不是中心与原点对齐,我们需要将它沿各个轴移动其半个尺寸的距离。

注意点2:

在Three.js中,单位是抽象的,1单位可以代表任何长度。选择厘米作为单位是为了方便与现实世界的数据对接。在3D场景中,无论是选择米、厘米还是其他任何单位,最重要的是保持一致性,并确保场景内的所有元素都是按照相同的比例尺建造的。

  • 9
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值