鸿蒙开发-实战:用AR Engine测量两点之间的距离
摘要:本文介绍了使用AR Engine实现物体测量的完整流程,包括平面检测、点击定位和距离计算三大核心步骤。通过初始化AR Session并启用平面检测功能,用户可以在手机屏幕上点击两个点,系统通过hitTest方法获取3D坐标后,运用三维空间距离公式计算出实际距离(单位:米)。文章提供了详细的代码实现,涵盖AR初始化、平面检测、命中检测和距离计算等关键环节,并展示了包含状态显示、测量结果和操作按
实战:用 AR Engine 做物体测量
你有没有想过用手机测量桌子有多宽、房间有多长?AR 技术可以做到——打开摄像头,点击两个点,手机就告诉你这两点之间的距离。
物体测量整体流程
下面是用AR Engine测量距离的完整流程:
物体测量的原理
物体测量的核心是平面检测 + 距离计算:
- 平面检测:AR Engine 检测摄像头画面中的平面(地面、桌面、墙面)
- 点击定位:用户在平面上点击两个点
- 距离计算:根据两个点的 3D 坐标,计算实际距离
第一步:初始化 AR
import { arEngine } from '@kit.ArkGraphics2D';
import { common } from '@kit.AbilityKit';
导入需要的模块。
interface Point3D {
x: number;
y: number;
z: number;
}
@Entry
@Component
struct MeasureTool {
@State status: string = '初始化中...';
@State distance: string = '';
@State points: Point3D[] = [];
private arSession: arEngine.ARSession | null = null;
private planes: arEngine.ARPlane[] = [];
定义 3D 坐标接口和状态变量。
async aboutToAppear() {
await this.initAR();
}
async initAR() {
const context: Context = this.getUIContext().getHostContext() as common.UIAbilityContext;
获取上下文。
// 检查 AR 能力
let isSupported = arEngine.isSupport(context);
if (!isSupported) {
this.status = '设备不支持 AR';
return;
}
检查设备是否支持 AR。
// 创建 AR Session,启用平面检测
let config: arEngine.ARSessionConfig = {
planeFindingMode: arEngine.PlaneFindingMode.HORIZONTAL_AND_VERTICAL
};
this.arSession = await arEngine.createSession(context, config);
创建 AR Session 时,启用平面检测。HORIZONTAL_AND_VERTICAL 表示同时检测水平面(地面、桌面)和垂直面(墙壁)。
if (this.arSession == null) {
this.status = '创建 AR Session 失败';
return;
}
// 启动 AR
this.arSession.start();
this.status = '请移动手机扫描平面';
启动 AR。
第二步:检测平面
// 持续检测平面
this.startPlaneDetection();
}
startPlaneDetection() {
setInterval(() => {
if (this.arSession == null) return;
// 获取所有检测到的平面
this.planes = this.arSession.getAllTrackables(arEngine.ARPlane);
if (this.planes.length > 0) {
this.status = `检测到 ${this.planes.length} 个平面,点击两个点测量距离`;
}
}, 500);
}
每 500ms 检测一次平面。getAllTrackables(arEngine.ARPlane) 获取所有检测到的平面。
第三步:命中检测
// 用户点击屏幕时调用
onScreenTap(x: number, y: number) {
if (this.arSession == null) return;
// 命中检测:从屏幕坐标转换到 3D 空间
let hitResult = this.arSession.hitTest(x, y);
hitTest 从屏幕坐标 (x, y) 发射一条射线,检测它和哪个平面相交。返回的是一个数组——可能命中多个平面,我们取第一个。
if (hitResult.length > 0) {
let hit = hitResult[0];
let pose = hit.getHitPose();
// 获取 3D 坐标
let point: Point3D = {
x: pose.tx(),
y: pose.ty(),
z: pose.tz()
};
getHitPose() 返回命中点的位姿(位置 + 旋转)。tx()、ty()、tz() 分别是 X、Y、Z 坐标,单位是米。
this.points.push(point);
if (this.points.length === 1) {
this.status = '已标记第一个点,请点击第二个点';
} else if (this.points.length === 2) {
// 计算距离
let dist = this.calculateDistance(this.points[0], this.points[1]);
this.distance = `${(dist * 100).toFixed(1)} 厘米`;
this.status = '测量完成,点击"重置"继续测量';
}
}
}
把点击的点保存起来。如果已经有两个点,计算距离。
第四步:计算距离
calculateDistance(p1: Point3D, p2: Point3D): number {
let dx = p2.x - p1.x;
let dy = p2.y - p1.y;
let dz = p2.z - p1.z;
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}
三维空间中两点之间的距离公式:√((x2-x1)² + (y2-y1)² + (z2-z1)²)
返回值的单位是米,所以乘以 100 转成厘米。
第五步:页面布局
reset() {
this.points = [];
this.distance = '';
this.status = '请点击第一个点';
}
build() {
Column() {
Text(this.status)
.fontSize(16)
.margin({ top: 20 })
.textAlign(TextAlign.Center)
显示状态文字。
// 测量结果显示
if (this.distance) {
Text(this.distance)
.fontSize(48)
.fontWeight(FontWeight.Bold)
.fontColor('#2196f3')
.margin({ top: 30 })
Text('两点之间的距离')
.fontSize(14)
.fontColor('#999999')
.margin({ top: 5 })
}
显示测量结果。
// AR 视图区域
// 实际项目中,这里会放一个 AR 视图组件
// 用户可以点击视图中的平面来标记点
// 操作按钮
Row() {
Button('重置')
.margin(10)
.onClick(() => this.reset())
Button('撤销')
.margin(10)
.onClick(() => {
if (this.points.length > 0) {
this.points.pop();
this.distance = '';
this.status = '已撤销,请重新标记';
}
})
}
.margin({ top: 30 })
添加重置和撤销按钮。
// 平面信息
if (this.planes.length > 0) {
Text(`已检测到 ${this.planes.length} 个平面`)
.fontSize(12)
.fontColor('#999999')
.margin({ top: 20 })
}
}
.width('100%')
.height('100%')
}
aboutToDisappear() {
if (this.arSession != null) {
this.arSession.stop();
this.arSession.release();
}
}
}
显示检测到的平面数量,页面销毁时释放资源。
命中检测流程
命中检测将屏幕坐标转换为3D空间坐标:
进阶改进
1. 多点测量
支持标记多个点,计算折线总长度:
calculateTotalDistance(): number {
let total = 0;
for (let i = 1; i < this.points.length; i++) {
total += this.calculateDistance(this.points[i - 1], this.points[i]);
}
return total;
}
2. 面积测量
标记 4 个点,计算矩形面积:
calculateArea(p1: Point3D, p2: Point3D, p3: Point3D, p4: Point3D): number {
let width = this.calculateDistance(p1, p2);
let height = this.calculateDistance(p2, p3);
return width * height;
}
3. 精度提示
AR 测量的精度受很多因素影响:
- 光线条件
- 平面纹理(纯色平面检测效果差)
- 手机移动的稳定性
你可以在 UI 上显示一个"精度指示器",告诉用户当前测量的可靠程度。
进阶改进方向
AR测量工具可以通过以下方式增强功能:
小结
物体测量的核心流程:
arEngine.createSession创建 AR Session,启用平面检测getAllTrackables(arEngine.ARPlane)获取检测到的平面hitTest(x, y)从屏幕坐标转换到 3D 坐标- 用三维距离公式计算两点之间的距离
AR Engine 提供了平面检测和命中检测能力,距离计算就是简单的数学。实际应用中,难点在于 UI 交互和精度优化。
更多推荐



所有评论(0)