地理空间锚点是一种锚点,可用于将 3D 内容放置到现实世界中。
地理空间锚点的类型
地理空间锚点有三种类型,每种类型都以不同方式处理海拔高度:
WGS84 锚点:
借助 WGS84 锚点,您可以将 3D 内容放置在任何给定纬度, 经度和海拔地形锚点:
借助地形锚点,您可以只使用纬度和 具有相对于该位置地形的高度的经度。 海拔高度是相对于已知的地面或地面而言的 由 VPS 提供支持。屋顶锚点:
借助屋顶锚点,您只需使用纬度和 该经度相对于该位置的建筑物屋顶的高度。 海拔高度是相对于已知建筑物的顶部而言的 由 Streetscape Geometry 提供。 如果未放置在建筑物上,则默认采用地形海拔高度。
WGS84 | 地形 | 屋顶 | |
---|---|---|---|
水平位置 | 纬度,经度 | 纬度,经度 | 纬度,经度 |
垂直位置 | 相对于 WGS84 海拔 | 相对于由 Google 地图确定的地面级别 | 相对于由 Google 地图确定的屋顶楼层 |
需要由服务器解决? | 否 | 是 | 是 |
前提条件
请务必先启用 Geospatial API,然后再继续操作。
放置地理空间锚点
每种锚点类型都有用于创建它们的专用 API;如需了解详情,请参阅地理空间锚点的类型。
根据点击测试创建锚点
您还可以基于命中测试结果创建地理空间锚点。
使用命中测试中的转换,并将其转换为 GARGeospatialTransform
。用它放置上述 3 种锚点类型中的任意一种。
通过 AR 转换获取地理空间转换
GARSession.geospatialTransformFromTransform:error:
通过将 AR 转换转换为 Geospatial 转换,提供了另一种确定纬度和经度的方法。
通过 Geospatial Transform 获取 AR 转换
GARSession.transformFromGeospatialCoordinate:altitude:eastUpSouthQTarget:error:
可将地球指定的水平位置、海拔高度和四元数旋转(相对于东上南坐标系)转换为相对于 GL 世界坐标的 AR 转换。
选择适合您的用例的方法
请注意,每种创建锚点的方法都有相关的权衡:
- 使用街景几何图形时, 使用点击测试将内容附加到建筑物。
- 首选地形锚点或屋顶锚点,而不是 WGS84 锚点,因为它们使用由 Google 地图确定的海拔高度值。
确定某个位置的经纬度
您可以通过以下三种方式计算位置的纬度和经度:
- 使用 Geospatial Creator 可以查看和增强 3D 内容,而无需实际前往某个地点。这样,您就可以在 Unity 编辑器中使用 Google 地图直观地放置 3D 沉浸式内容。系统会自动为您计算内容的纬度、经度、旋转角度和海拔。
- 使用Google地图
- 使用 Google 地球。请注意,与 Google 地图不同,使用 Google 地球获取这些坐标,所得到的误差范围高达几米。
- 前往实际位置
使用Google地图
要使用 Google 地图获取某个位置的经纬度,请执行以下操作:
在桌面设备上访问 Google 地图。
导航至图层 >更多。
将地图类型更改为卫星,然后取消选中屏幕左下角的地球视图复选框。
这将强制采用 2D 透视效果,并消除了可能来自 3D 角度视图的错误。
在地图上,右键点击该地点,然后选择经度/纬度即可将其复制到剪贴板。
使用 Google 地球
您可以通过在界面中点击某个位置并从地标详情中读取数据,从 Google 地球中计算该位置的纬度和经度。
要使用 Google 地球获取某个位置的经纬度,请执行以下操作:
在桌面设备上访问 Google 地球。
找到汉堡形菜单
,然后选择地图样式。
关闭 3D 建筑开关。
3D 建筑开关关闭后,点击图钉图标
在所选位置添加地标。
指定包含地标的项目,然后点击保存。
在地标的标题字段中,输入地标的名称。
点击“Project”窗格中的返回箭头
,然后选择
More Actions 菜单。
从菜单中选择导出为 KML 文件。
KLM 文件会在 <coordinates>
标记中报告地标的纬度、经度和海拔高度(以英文逗号分隔),如下所示:
<coordinates>-122.0755182435043,37.41347299422944,7.420342565583832</coordinates>
请勿使用 <LookAt>
标记中的纬度和经度,因为后者用于指定镜头位置,而非位置。
前往实际位置
您可以以物理方式前往某个地点并进行本地观察,从而计算出某个地点的海拔高度。
获取旋转四元数
GARGeospatialTransform.eastUpSouthQTarget
从地理空间转换中提取方向,并输出一个四元数,该四元数表示将矢量从目标向东上南 (EUS) 坐标系转换的旋转矩阵。X+ 指向东,Y+ 指向上,Z+ 指向南。值的写入顺序为 {x, y, z, w}
。
WGS84 锚点
WGS84 锚点是一种锚点,允许您将 3D 内容放置在任何给定的纬度、经度和高度。它依赖于转换和方向,以置于现实世界中。该位置由 WGS84 坐标系中指定的纬度、经度和海拔组成。方向包括四元数旋转。
海拔高度是以高于参考 WGS84 椭球体的米为单位报告的,因此,地平面不为零。您的应用负责为每个创建的锚点提供这些坐标。
在现实世界中放置 WGS84 锚点
确定某个位置的海拔
可通过以下几种方法确定位置以放置锚点时的海拔高度:
- 如果锚点的物理位置在用户附近,您可以使用与用户设备高度相似的海拔高度。
- 确定好经纬度后,您可以使用 Elevation API,根据 EGM96 规范获取海拔高度。您必须将 Maps API EGM96 海拔高度转换为 WGS84,才能与
GARGeospatialTransform
海拔高度进行比较。请参阅同时具有命令行和 HTML 界面的 GeoidEval。Maps API 开箱即根据 WGS84 规范报告纬度和经度。 - 您可以从 Google 地球获取某个位置的纬度、经度和海拔高度。这将为您提供高达几米的误差范围。在 KML 文件中使用
<coordinates>
标记(而不是<LookAt>
标记)中的纬度、经度和海拔高度。 - 如果现有的锚点就在附近,并且不是在陡峭的斜坡上,您也许可以使用镜头
GARGeospatialTransform
的海拔高度,而无需使用其他来源(例如 Maps API)。
创建锚点
获得纬度、经度、海拔高度和旋转四元数之后,请使用 createAnchorWithCoordinate:altitude:eastUpSouthQAnchor:error:
将内容锚定到您指定的地理坐标。
NSError *error = nil;
GARAnchor *anchor = [self.garSession createAnchorWithCoordinate:coordinate
altitude:altitude
eastUpSouthQAnchor:eastUpSouthQAnchor
error:&error];
地形锚点
地形锚点是一种锚点,您只需使用纬度和经度即可放置 AR 对象,并利用 VPS 中的信息找到地面以上的精确海拔高度。
您无需输入所需的海拔高度,只需提供地形上方的海拔高度即可。当此值为零时,锚点将与地形保持水平。
设置飞机查找模式
平面查找是可选的,并非利用锚点的必要条件。请注意,系统只会使用水平面。水平平面有助于地形锚点在地面上动态对齐。
使用 ARWorldTrackingConfiguration.PlaneDetection
选择应用检测平面的方式。
使用新的 Async API 创建地形锚点
如需创建并放置地形锚点,请调用 GARSession.createAnchorWithCoordinate:altitudeAboveTerrain:eastUpSouthQAnchor:completionHandler:error:
。
锚点无法立即准备就绪,需要解析。问题解决后,您便可以在 GARCreateAnchorOnTerrainFuture
中查看。
GARCreateAnchorOnTerrainFuture *future = [self.garSession createAnchorWithCoordinate:coordinate
altitudeAboveTerrain:altitude
eastUpSouthQAnchor:eastUpSouthQTarget
completionHandler:^(GARAnchor *anchor, GARTerrainAnchorState state) {
// handle completion
}
error:&error];
了解未来状况
Future 将有一个关联的 GARFutureState
。
州 | 说明 |
---|---|
GARFutureStatePending |
操作仍在等待处理。 |
GARFutureStateDone |
操作已完成,可提供结果。 |
GARFutureStateCancelled |
此操作已取消。 |
检查 Future 结果的地形锚点状态
GARTerrainAnchorState
属于异步操作,是最终 Future 结果的一部分。
switch (future.resultTerrainAnchorState) {
case GARTerrainAnchorStateSuccess:
// Terrain anchor finished resolving.
break;
case GARTerrainAnchorStateErrorUnsupportedLocation:
// The requested anchor is in a location that isn't supported by the Geospatial API.
break;
case GARTerrainAnchorStateErrorNotAuthorized:
// An error occurred while authorizing your app with the ARCore API. See
// https://developers.google.com/ar/reference/ios/group/GARTerrainAnchorState#garterrainanchorstateerrornotauthorized
// for troubleshooting steps.
break;
case GARTerrainAnchorStateErrorInternal:
// The Terrain anchor could not be resolved due to an internal error.
break;
default:
break;
}
屋顶锚栓
屋顶锚点是一种锚点,与上面的地形锚点非常相似。不同之处在于,您需要提供屋顶以上的海拔高度,而不是地形上方的高度。
使用新的 Async API 创建 Rooftop 锚点
锚点无法立即准备就绪,需要解析。
如需创建并放置 Rooftop 锚点,请调用 GARSession.createAnchorWithCoordinate:altitudeAboveRooftop:eastUpSouthQAnchor:completionHandler:error:
。与地形锚点类似,您也将访问 Future 的 GARFutureState
。然后,您可以查看“Future 结果”以访问 GARRooftopAnchorState
。
GARCreateAnchorOnRooftopFuture *future = [self.garSession createAnchorWithCoordinate:coordinate
altitudeAboveRooftop:altitude
eastUpSouthQAnchor:eastUpSouthQTarget
completionHandler:^(GARAnchor *anchor, GARRooftopAnchorState state) {
// handle completion
}
error:&error];
了解未来状况
Future 将具有关联的 GARFutureState
,详见上表。
检查 Future 结果的 Rooftop 锚点状态
GARRooftopAnchorState
属于异步操作,是最终 Future 结果的一部分。
switch (future.resultRooftopAnchorState) {
case GARRooftopAnchorStateSuccess:
// Rooftop anchor finished resolving.
break;
case GARRooftopAnchorStateErrorUnsupportedLocation:
// The requested anchor is in a location that isn't supported by the Geospatial API.
break;
case GARRooftopAnchorStateErrorNotAuthorized:
// An error occurred while authorizing your app with the ARCore API. See
// https://developers.google.com/ar/reference/ios/group/GARRooftopAnchorState#garrooftopanchorstateerrornotauthorized
// for troubleshooting steps.
break;
case GARRooftopAnchorStateErrorInternal:
// The Rooftop anchor could not be resolved due to an internal error.
break;
default:
break;
}
后续步骤
- 确保您了解 Geospatial API 用量配额。