首页 > 其他分享 >在Cesium中从模型上采样点集数据

在Cesium中从模型上采样点集数据

时间:2024-12-22 13:03:35浏览次数:7  
标签:采样 const 模型 点集 let Cesium height

在 Cesium 中从实景模型(如倾斜摄影模型或 3D Tiles 模型)中采样点,通常是指获取模型表面的坐标、法线或其他属性。这可以通过以下步骤实现:

方法一:使用 sampleHeight 函数

Cesium 提供了 sampleHeight 方法,可以从支持高度查询的地形或 3D Tiles 数据中获取指定位置的高度。

示例代码:
viewer.scene.sampleHeight({
    positions: [Cesium.Cartographic.fromDegrees(longitude, latitude)],
    objectsToExclude: [], // 可选,排除某些模型或对象
}).then(function(samples) {
    let height = samples[0].height; // 获取第一个位置的高度
    console.log("Sampled height: " + height);
});
要点:
  • 需要提供一个或多个 Cartographic 位置。
  • 结果包含对应的高度值。
  • 此方法适用于模型具有支持采样的功能(如地形或某些 3D Tiles)。

方法二:使用 scene.pick 和射线投射

通过 scene.pickscene.pickPosition,可以通过屏幕上的点击或射线投射与模型交互,获取相应的三维坐标。

示例代码:
// 创建一个射线
let ray = viewer.camera.getPickRay(screenPosition);

// 获取模型表面点
let pickedPosition = viewer.scene.pickPosition(ray);

if (pickedPosition) {
    console.log("Picked position: " + pickedPosition);
} else {
    console.log("No position picked.");
}
要点:
  • screenPosition 是屏幕上的像素坐标(例如鼠标点击位置)。
  • pickPosition 返回世界坐标系(Cartesian3)中的点。
  • 需要模型启用了深度缓冲,否则可能无法拾取。

方法三:直接访问 3D Tiles 数据

如果需要更高精度或更多信息,可以直接操作 3D Tiles 的数据结构,例如 TileContentTileFeatures

示例代码:
let tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
    url: "URL_TO_YOUR_3DTILES"
}));

tileset.readyPromise.then(function(tileset) {
    let boundingVolume = tileset.boundingVolume.boundingVolume;
    console.log("Bounding Volume: ", boundingVolume);

    // 访问单个 tile 的内容
    tileset.tileVisible.addEventListener(function(tile) {
        let content = tile.content;
        console.log("Tile content: ", content);
    });
});
要点:
  • 需要熟悉 3D Tiles 数据结构。
  • 可以获取更详细的模型元数据,但解析较复杂。

方法四:结合地形和模型

如果模型覆盖了地形,可能需要从地形和模型中分别采样高度,并进行对比。

示例代码:
// 地形采样
Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, [
    Cesium.Cartographic.fromDegrees(longitude, latitude)
]).then(function(samples) {
    let terrainHeight = samples[0].height;
    console.log("Terrain height: " + terrainHeight);
});

// 实景模型采样(结合 pickPosition)
let ray = viewer.camera.getPickRay(screenPosition);
let modelPosition = viewer.scene.pickPosition(ray);
if (modelPosition) {
    console.log("Model surface height: ", Cesium.Cartesian3.fromElements(modelPosition));
}

注意事项

  1. 深度缓冲区:要确保 viewer.scene.globe.depthTestAgainstTerraintrue,以提高采样精度。
  2. 数据支持:只有部分类型的 3D Tiles 数据支持直接采样。
  3. 性能:大规模采样可能需要批量处理,以避免性能瓶颈。

选择具体方法取决于您的实际应用需求和数据类型。
如果仅有三维实景模型(例如倾斜摄影生成的 3D Tiles 模型),需要通过 Cesium 提供的功能从模型表面采样所有区域的点。这种需求通常用于重建表面网格、分析地形等。以下是可能的实现步骤:


方法概述

  1. 确定采样区域和分辨率
    确定需要采样的地理范围(如经纬度范围)以及采样的分辨率(步长)。

  2. 生成采样网格
    在地理范围内生成规则的经纬度网格点。

  3. 使用 sampleHeightMostDetailedpickPosition 获取模型表面点
    将经纬度网格点逐一映射到模型表面,得到三维坐标点。

  4. 处理和存储采样数据
    存储采样结果,例如输出为 CSV、GeoJSON,或直接用于进一步处理。


实现步骤

1. 确定采样区域和分辨率

定义感兴趣区域的经纬度范围和步长。例如:

const west = -123.1; // 最西经度
const east = -122.9; // 最东经度
const south = 37.7;  // 最南纬度
const north = 37.9;  // 最北纬度
const step = 0.001;  // 经纬度步长
2. 生成采样网格

根据区域范围和步长,生成一组经纬度点。

function generateGrid(west, east, south, north, step) {
    const points = [];
    for (let lat = south; lat <= north; lat += step) {
        for (let lon = west; lon <= east; lon += step) {
            points.push(Cesium.Cartographic.fromDegrees(lon, lat));
        }
    }
    return points;
}

const gridPoints = generateGrid(west, east, south, north, step);
3. 采样表面高度

利用 scene.sampleHeightMostDetailedpickPosition 对每个网格点进行采样。

使用 sampleHeightMostDetailed

sampleHeightMostDetailed 可以批量采样 3D Tiles 表面点高度。

viewer.scene.sampleHeightMostDetailed(gridPoints).then((samples) => {
    const results = samples.map(sample => ({
        longitude: Cesium.Math.toDegrees(sample.cartographic.longitude),
        latitude: Cesium.Math.toDegrees(sample.cartographic.latitude),
        height: sample.height
    }));
    console.log(results);
    // 处理或保存结果
});
使用射线 pickPosition

如果 sampleHeightMostDetailed 不适用,可以通过 pickPosition 获取模型表面坐标。

const sampledPositions = [];

gridPoints.forEach(cartographic => {
    const cartesian = Cesium.Cartographic.toCartesian(cartographic, viewer.scene.globe.ellipsoid);
    const ray = new Cesium.Ray(cartesian, Cesium.Cartesian3.UNIT_Z); // 朝向模型的射线
    const position = viewer.scene.pickPosition(ray);

    if (position) {
        const cartographicPosition = Cesium.Cartographic.fromCartesian(position);
        sampledPositions.push({
            longitude: Cesium.Math.toDegrees(cartographicPosition.longitude),
            latitude: Cesium.Math.toDegrees(cartographicPosition.latitude),
            height: cartographicPosition.height
        });
    }
});

console.log(sampledPositions);
4. 存储采样结果

可以将结果保存为 GeoJSON、CSV 或其他格式:

保存为 CSV
function saveAsCSV(data) {
    const csvContent = "longitude,latitude,height\n" +
        data.map(row => `${row.longitude},${row.latitude},${row.height}`).join("\n");
    const blob = new Blob([csvContent], { type: "text/csv" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "sampled_points.csv";
    a.click();
}

saveAsCSV(sampledPositions);

注意事项

  1. 精度与性能权衡

    • 小步长会增加采样点数量,但可能导致性能下降。
    • 如果范围较大,可分区域并行处理。
  2. 数据要求

    • sampleHeightMostDetailedpickPosition 依赖模型提供表面高度数据。
    • 模型需要加载到内存中,确保分块可见。
  3. 深度缓冲区
    在使用 pickPosition 时,确保启用深度缓冲区:

    viewer.scene.globe.depthTestAgainstTerrain = true;
    
  4. 大规模采样
    对大范围区域,可以使用分布式方法(如 Web Workers)加速采样。

通过上述方法,可以从 3D Tiles 实景模型中采样出所有区域的点并进行进一步处理。
如果采样范围过大且时间过慢,可以通过优化采样方法和利用 GPU 加速来提高效率。以下是改进建议和具体方法:


1. 优化采样方法

1.1 自适应采样

根据模型的复杂度动态调整采样分辨率:

  • 在地形平坦区域使用较大的步长。
  • 在复杂区域(如建筑物密集处)使用较小的步长。
示例代码:
function adaptiveSampling(west, east, south, north, coarseStep, fineStep, complexityThreshold) {
    const points = [];
    for (let lat = south; lat <= north; lat += coarseStep) {
        for (let lon = west; lon <= east; lon += coarseStep) {
            const complexity = Math.random(); // 模拟复杂度分析
            const step = complexity > complexityThreshold ? fineStep : coarseStep;

            points.push(Cesium.Cartographic.fromDegrees(lon, lat));
        }
    }
    return points;
}

const gridPoints = adaptiveSampling(-123.1, -122.9, 37.7, 37.9, 0.01, 0.001, 0.5);

实现复杂度分析:可通过分块的法向变化、梯度计算或其他属性来判断地形复杂度。


1.2 按块加载采样

将大范围划分为小块,逐块加载模型并采样,降低内存消耗和计算开销。

示例代码:
function splitRegion(west, east, south, north, step) {
    const regions = [];
    for (let lat = south; lat < north; lat += step) {
        for (let lon = west; lon < east; lon += step) {
            regions.push({ west: lon, east: lon + step, south: lat, north: lat + step });
        }
    }
    return regions;
}

const regions = splitRegion(-123.1, -122.9, 37.7, 37.9, 0.1);

regions.forEach(region => {
    const gridPoints = generateGrid(region.west, region.east, region.south, region.north, 0.001);
    viewer.scene.sampleHeightMostDetailed(gridPoints).then(samples => {
        console.log("Sampled points: ", samples);
    });
});

1.3 视野裁剪

只对屏幕范围内可见区域进行采样,减少不必要的计算。

示例代码:
const boundingRectangle = viewer.camera.computeViewRectangle();
const gridPoints = generateGrid(
    Cesium.Math.toDegrees(boundingRectangle.west),
    Cesium.Math.toDegrees(boundingRectangle.east),
    Cesium.Math.toDegrees(boundingRectangle.south),
    Cesium.Math.toDegrees(boundingRectangle.north),
    0.001
);

2. 利用 GPU 加速

Cesium 本身在大部分操作中已经利用了 GPU,但可以通过以下方式进一步优化:

2.1 WebGL 批量计算

利用 pickPosition 的同时通过 WebGL 批量处理大量点。例如:

  • 批量生成射线,直接渲染采样区域。
  • 通过着色器进行复杂度检测。
示例框架:Cesium + custom WebGL
  1. 创建自定义着色器
    使用 Cesium 的 customShader 功能来处理采样逻辑。

  2. 示例代码

const customShader = new Cesium.CustomShader({
    vertexShaderText: `
        void main() {
            gl_Position = ...; // 自定义顶点处理
        }
    `,
    fragmentShaderText: `
        void main() {
            float height = ...; // 根据输入点计算高度
            gl_FragColor = vec4(height, 0.0, 0.0, 1.0);
        }
    `,
});
tileset.customShader = customShader;
  1. 收集结果
    通过帧缓冲或 pickPosition 获取数据。

2.2 GPU 计算框架

借助 GPU 计算框架(如 WebGPU 或三方库)对采样点进行并行计算:

  • 使用 deck.glregl
  • 批量处理数千个点的投射和采样。

3. 分布式采样

3.1 多线程 (Web Workers)

将采样任务分配给多个 Web Worker 并行处理,减少主线程负担。

示例代码:
const worker = new Worker('samplingWorker.js');

// 发送任务
worker.postMessage({ points: gridPoints });

// 接收结果
worker.onmessage = (event) => {
    console.log("Sampled results: ", event.data.samples);
};

4. 选择合适的数据结构和存储方式

采样过程中,数据存储会影响性能:

  • 空间索引优化:对采样点建立空间索引(如四叉树、R树)以加速检索。
  • 流式处理:将采样结果流式写入文件(如 CSV)或直接传输至后端。

5. 总结

在范围过大或时间过慢时:

  1. 优化采样分辨率,按复杂度动态调整。
  2. 分块处理,逐块加载和采样。
  3. 利用 GPU 并行计算,加速大量点的处理。
  4. 分布式任务处理,充分利用多核 CPU 和 Web Workers。
  5. 结合视野裁剪与空间索引,减少不必要的计算。

根据具体需求和硬件条件,灵活组合这些方法可以显著提高效率。

标签:采样,const,模型,点集,let,Cesium,height
From: https://blog.csdn.net/m0_55049655/article/details/144605603

相关文章

  • 大模型--采样技术 TopK TopP 惩罚系数--37
    目录1.参考2.概述重复惩罚(RepetitionPenalty)1.参考https://mp.weixin.qq.com/s/mBZA6PaMotJw7WeVdA359g2.概述大型语言模型(LLMs)通过“根据上下文预测下一个token的概率分布”来生成文本。最简单的采样方法是贪心采样(GreedySampling),它在每一步选择概率最高的token。......
  • [vLLM vs TensorRT-LLM]:采样方法对两者性能的影响
    来源:oldpan来自:https://medium.com/squeezebits-team-blog/vllm-vs-tensorrt-llm-3-understanding-sampling-methods-and-their-performance-impact-a8ffa5ee0245我们都知道,大型语言模型(LLMs)通过“根据上下文预测下一个token的概率分布”来生成文本。最简单的采样方法是贪......
  • Cesium-(Primitive)-(CorridorGeometry)
    CorridorGeometry效果:以下是CorridorGeometry类的构造函数属性,以表格形式展示:属性名类型默认值描述positionsArray.定义走廊中心的坐标点数组。widthnumber走廊边缘之间的距离,单位为米。ellipsoidEllipsoidEllipsoid.default用作参考的椭......
  • 在IIS部署cesium用的倾斜摄影3dtiles服务注意事项(备忘)
    1、将地形或倾斜摄影切片拷贝到IIS服务上,需要添加相应文件的MIME类型(如果缺少自己模型服务的数据类型,直接按扩展名添加,一般都使用application/octet-stream) .json   application/json .terrain  application/octet-stream.b3dm->application/octet-stream.pnts->->a......
  • cesium常见的四种坐标系,互相转换方法
    Cesium支持多种坐标系,主要用于地理空间数据的表示和转换。以下是Cesium中常见的几种坐标系:世界坐标系(WorldCoordinateSystem,WGS84)这是地球上的一个标准地理坐标系统,使用经纬度(经度、纬度、高度)来定义位置。在Cesium中,WGS84坐标通常用Cartographic类......
  • 在UE5 Cesium中点击地图生成Spline线
    本文中介绍在UE5Cesium中点击地图生成Spline线步骤包含了:1、鼠标点击时获得屏幕坐标2、将屏幕坐标转成世界坐标3、射线检测找到屏幕坐标在Cesium中的坐标4、生成Spline步骤1、2、3:https://blog.csdn.net/m0_48562356/article/details/144358371步骤4:新建一个Actor,......
  • RT-DETR融合[ICCV2023]DySample中的上采样模块
    RT-DETR使用教程: RT-DETR使用教程RT-DETR改进汇总贴:RT-DETR更新汇总贴《DySample:LearningtoUpsamplebyLearningtoSample》一、模块介绍    论文链接: https://arxiv.org/abs/2308.15085    代码链接:https://github.com/tiny-smart/dysam......
  • 24-bit 音频 与 16-bit 音频 的对比,主要通过表格形式展示它们的不同:24 bit 是指音频文
    在音频领域,16-bit、24-bit、32-bit和64-bit已经是常见的位深,这些位深代表了音频的动态范围和精度。但如果我们进一步探讨是否存在更高的位深或是否有更高的标准,可以从几个方面来回答。1. 64-bit及更高的位深在理论上,音频位深是没有固定上限的,您可以定义更高的位深,比如128-b......
  • cesium拾取管网属性功能
    最近在做移动端地下管网可视化系统时,做到一个属性查询功能。就是拾取一根管道,读取该管道属性并显示。实现效果如下图。核心代码如下://开始拾取consthandlePick=()=>{if(!cesiumStore.viewer){Notify.create({type:"negative",message:"Cesi......
  • Cesium高级开发教程之四:鹰眼地图#OpenLayers
    教程示例网站:https://thomaz529.github.io一、效果图二、代码init2DDiv(){this.mapDiv=document.createElement('div');this.mapDiv.setAttribute('id',this.mapId)constviewerContainer=this.viewer.cesiumWidget.container.pa......