Cesium 点击获取/拾取(PICK)的不同用法

本文详细介绍了Cesium中的几种拾取方法,包括viewer.scene.pick用于获取最顶部的对象,viewer.scene.pickPosition获取世界坐标,viewer.scene.drillPick进行穿透拾取,viewer.scene.globe.pick定位地球表面交点,以及viewer.scene.camera.pickEllipsoid选取椭球面位置。每种方法都有其特定的使用场景和注意事项,如深度检测的开启和关闭,以及在处理重叠对象和地形时的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Cesium 拾取有多个方法,下面就分别说明一下几种常用方法都是做什么用的,在什么场景下使用。

1. viewer.scene.pick

通过坐标位置,拾取 EntityPrimitive3D-TilesCesium3DTileFeature)对象。

例如获取 Entity ,通过position(坐标位置)获取到 pick 对象,通过pick.id即可拾取当前的entity对象。

var pick = viewer.scene.pick(position);

注意: scene.pick 只能获取一个对象,并且获取的是最顶部的对象。如果拾取点没有对象,则为undefined

使用场景: viewer.scene.pick 主要是用来拾取 EntityPrimitive、3D-Tiles。拾取后,可以用于改变对象的属性参数。

示例代码: 点击获取图标,修改图标的图片

var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
// 设置左键点击事件
handler.setInputAction(function (event) {
  // 获取 pick 拾取对象
  var pick = viewer.scene.pick(event.position);
  // 判断是否获取到了 pick 
  if (Cesium.defined(pick)) {
    // 修改拾取到的entity的样式
    pick.id.billboard.image = "xxx.png"
  }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

2. viewer.scene.pickPosition

主要是用于拾取对应位置的世界坐标,例如:拾取点击模型表面的坐标。

注意: 一定要开启深度检测(viewer.scene.globe.depthTestAgainstTerrain = true;),否则在没有3dTile模型的情况下,会出现空间坐标不准的问题,如果不开启深度检测,只能在3dTile模型上获取准确的空间坐标。

使用场景: 适用于模型表面位置的选取,拾取三维物体的坐标等。

示例

var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (event) {
     var position = viewer.scene.pickPosition(event.position);
     console.log("获取到的坐标:", positionposition);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

3. viewer.scene.drillPick

可以理解为穿透拾取,是从当前拾取位置获取所有对象的对象列表(entity的集合),列表按其在场景中的视觉顺序(从前到后)排序(通过for循环可以获取当前坐标下的所有entity)。

注意: drillPickPick 不同,Pick 只能拾取一个对象,而 drillPick 可以拾取多个对象,并且 drillPick 可以设置 limit 参数,limit 参数可以控制获取几个对象,超出的就不获取了。

使用场景: 适用于多个对象重叠在一个位置,并且要获取到多个对象的情况。

示例

var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (event) {
	var pickedObjects = scene.drillPick(event.position);
	// pickedObjects 使用for循环 可以拿到所有entity
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

4. viewer.scene.globe.pick

找到射线与渲染的地球表面之间的交点(射线必须以世界坐标给出),返回的是世界坐标。一般用来获取加载地形后的经纬度和高程。

注意: 一定要开启深度检测(viewer.scene.globe.depthTestAgainstTerrain = true;

使用场景: 一般用于获取点击处地球表面的世界坐标(有地形),注意:不包括模型、倾斜摄影表面。

示例

var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (event) {
     var ray = viewer.camera.getPickRay(event.position);
     var position = viewer.scene.globe.pick(ray, viewer.scene);
     console.log("获取到的坐标:", position);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

5. viewer.scene.camera.pickEllipsoid

通过一个必选的屏幕坐标,获取椭圆球体表面的一个Cartesian3坐标。适用于裸球表面的选取,是基于数学模型的椭圆球体。

注意: pickEllipsoid在加载地形的情况下有误差,地形凹凸程度越大,误差越大,所以不要用来获取有地形的坐标。

使用场景: 主要用于获取椭球面的位置。

示例

var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (event) {
     var position = viewer.scene.camera.pickEllipsoid(event.position, viewer.scene.globe.ellipsoid);
     console.log("获取到的坐标:", position);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

本文在后续遇到详细场景的时候会继续补充

<think>首先,用户的问题是关于Cesium不同拾取方法的适用场景对比。用户说:“我想比较Cesium不同的拾取方法的适用场景 请问Cesium 不同拾取方法 使用场景 对比”。所以,我需要提供关于Cesium中拾取方法的详细比较。 Cesium是一个用于3D地球和2D地图可视化的JavaScript库。拾取(Picking)是指从场景中选择对象的过程,比如点击一个点来获取其信息。 回想Cesium中的拾取方法: 1. **scene.pick**:用于拾取单个对象,通常在点击事件中使用。 2. **scene.drillPick**:用于拾取多个对象,在同一个位置下的所有对象。 3. **scene.pickPosition**:用于拾取场景中的确切位置(世界坐标)。 4. **globe.pick**:用于拾取地球表面的点。 5. **Cesium.Cartesian3.fromDegrees**:用于将经纬度转换为笛卡尔坐标,但这不是拾取方法;它是坐标转换。 用户引用了两个引用: - 引用[1]:关于将经纬度转换为笛卡尔坐标。 - 引用[2]:关于Cesium工具应用,包括一些参考资料。 用户说:“上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。” 但在这个对话中,没有之前的消息,所以这是第一次交互。我需要基于当前问题回答。 系统级指令: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 用户可见层: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 结构回答: 1. **介绍拾取方法**:简要解释什么是拾取。 2. **列出主要拾取方法**:描述每个方法。 3. **适用场景对比**:比较每个方法的优缺点和适用场景。 4. **示例代码**:提供简单的代码片段来演示。 5. **生成相关问题**:在最后添加相关问题。 确保使用中文。 关键拾取方法: - `scene.pick(ray)`:拾取射线击中的第一个对象。 - `scene.drillPick(ray)`:拾取射线击中的所有对象。 - `scene.pickPosition(position)`:拾取屏幕位置对应的世界坐标。 - `globe.pick(ray, scene)`:拾取地球表面的点。 - 其他:如`Camera.pickEllipsoid`等。 适用场景: - `scene.pick`:适用于点击选择单个实体,如模型或点。 - `scene.drillPick`:当有重叠对象时,选择所有对象。 - `scene.pickPosition`:用于获取精确位置,如放置标记。 - `globe.pick`:用于地球表面的交互,如地形分析。 引用:用户提供了引用,但它们是关于坐标转换的,不是直接相关。我应该在回答中引用这些作为背景,但焦点是拾取方法。 参考引用[1]:它提到`Cesium.Cartesian3.fromDegrees`,用于经纬度转笛卡尔坐标,这在拾取中可能用到,但不是拾取本身。 在回答中,自然地添加引用标识。 最后,生成相关问题。 大纲回答: 1. 介绍Cesium拾取。 2. 详细描述每个方法。 3. 对比表格或列表。 4. 示例代码。 5. 相关问题。</think>### Cesium不同拾取方法的适用场景对比 在Cesium中,拾取(Picking)是指从3D场景中获取用户交互(如点击或悬停)的对象或位置信息的过程。这对于实现对象选择、信息查询、空间分析等功能至关重要。Cesium提供了多种拾取方法,每种方法适用于不同的场景。下面我将逐步解释主要拾取方法的原理、优缺点,并进行适用场景对比。所有方法均基于Cesium的API设计,确保回答真实可靠。 #### 1. **主要拾取方法及其原理** - **`scene.pick(ray)`** 此方法通过射线(ray)拾取场景中第一个被击中的对象(如实体、模型或图元)。它返回一个`PickResult`对象,包含选中实体的详细信息。 - **优点**:效率高,适合快速响应点击事件。 - **缺点**:只能返回单个对象,如果多个对象重叠,只拾取最上层的一个。 - **示例代码**: ```javascript viewer.screenSpaceEventHandler.setInputAction((movement) => { const ray = viewer.camera.getPickRay(movement.position); const pickedObject = viewer.scene.pick(ray); if (pickedObject && Cesium.defined(pickedObject.id)) { console.log("拾取到的实体:", pickedObject.id.name); } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); ``` - **`scene.drillPick(ray)`** 此方法通过射线拾取场景中所有被击中的对象(即使它们重叠)。它返回一个`PickResult`数组,包含所有命中对象的列表。 - **优点**:能处理多个重叠对象,适合复杂场景。 - **缺点**:性能开销较大,可能降低渲染帧率。 - **示例代码**: ```javascript viewer.screenSpaceEventHandler.setInputAction((movement) => { const ray = viewer.camera.getPickRay(movement.position); const pickedObjects = viewer.scene.drillPick(ray); pickedObjects.forEach((result) => { if (Cesium.defined(result.id)) { console.log("拾取到的实体:", result.id.name); } }); }, Cesium.ScreenSpaceEventType.LEFT_CLICK); ``` - **`scene.pickPosition(position)`** 此方法拾取屏幕坐标(position)对应的世界坐标(笛卡尔坐标)。它返回一个`Cartesian3`对象,表示3D空间中的精确位置。 - **优点**:提供高精度位置信息,适合空间定位。 - **缺点**:依赖地形数据,如果地形未加载可能返回`undefined`。 - **示例代码**: ```javascript viewer.screenSpaceEventHandler.setInputAction((movement) => { const position = movement.position; const worldPosition = viewer.scene.pickPosition(position); if (Cesium.defined(worldPosition)) { const cartographic = Cesium.Cartographic.fromCartesian(worldPosition); const lon = Cesium.Math.toDegrees(cartographic.longitude); const lat = Cesium.Math.toDegrees(cartographic.latitude); console.log("拾取位置经度:", lon, "纬度:", lat); } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); ``` - **`globe.pick(ray, scene)`** 此方法专用于拾取地球表面的点(基于地形或椭球体)。它返回一个`Cartesian3`对象,表示地表位置。 - **优点**:针对地球表面优化,支持地形高程。 - **缺点**:不适用于非地表对象(如空中模型)。 - **示例代码**: ```javascript viewer.screenSpaceEventHandler.setInputAction((movement) => { const ray = viewer.camera.getPickRay(movement.position); const surfacePosition = viewer.scene.globe.pick(ray, viewer.scene); if (Cesium.defined(surfacePosition)) { console.log("地球表面位置:", surfacePosition); } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); ``` - **`Cesium.Cartesian3.fromDegrees(lon, lat, height)`** 此方法将经纬度转换为世界坐标(笛卡尔坐标),常用于坐标转换而非直接拾取。但它在拾取前后用于数据处理[^1]。 - **优点**:简单高效,适合批量坐标转换。 - **缺点**:不处理交互拾取,仅用于静态数据。 - **示例代码**: ```javascript const cartesian = Cesium.Cartesian3.fromDegrees(114.0, 29.0, 1000); // 武汉坐标 console.log("笛卡尔坐标:", cartesian); ``` #### 2. **适用场景对比** 下表总结了不同拾取方法的适用场景、优缺点和推荐用例: | 方法 | 适用场景 | 优点 | 缺点 | 推荐用例 | |------|----------|------|------|----------| | `scene.pick(ray)` | 选择单个实体(如模型、点) | 高效、低延迟 | 无法处理重叠对象 | 实体信息查询、点击选择模型[^2] | | `scene.drillPick(ray)` | 选择多个重叠对象 | 返回所有命中对象 | 性能开销大 | 复杂场景分析(如多层建筑)[^2] | | `scene.pickPosition(position)` | 获取精确世界坐标 | 高精度位置 | 依赖地形数据 | 空间定位、放置标记(如测量工具) | | `globe.pick(ray, scene)` | 地球表面交互 | 支持地形高程 | 不适用于空中对象 | 地形分析、地表点击事件[^2] | | `Cesium.Cartesian3.fromDegrees` | 坐标转换(非交互) | 简单快速 | 非拾取方法 | 数据预处理、坐标批量转换[^1] | **关键对比点**: - **效率**:`scene.pick` 最适合实时交互(如游戏或导航),而 `scene.drillPick` 在对象密集时可能引起卡顿。 - **精度**:`scene.pickPosition` 和 `globe.pick` 提供高精度的空间位置,常用于GIS分析。 - **场景复杂性**:简单场景用 `scene.pick`,复杂场景(如城市模型)用 `scene.drillPick`。 - **地球表面**:优先使用 `globe.pick` 处理地形相关操作,避免 `scene.pickPosition` 在无地形时的错误。 #### 3. **最佳实践建议** - **性能优化**:在大型场景中,避免频繁调用 `scene.drillPick`;使用节流(throttling)减少事件触发频率。 - **错误处理**:检查返回值是否为 `defined`,避免未定义错误。 - **结合使用**:例如,先用 `scene.pick` 选择实体,再用 `scene.pickPosition` 获取位置,实现高效交互。 - **引用工具**:Cesium工具如缓冲区分析或剖面分析常依赖这些方法[^2]。 通过以上对比,您可以根据具体需求选择最合适的拾取方法。如果您有特定场景(如地形分析或模型交互),我可以提供更针对性的代码示例。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值