Harmonyos应用实例214:空间角与距离计算器
·
6. 空间角与距离计算器
功能简介:利用空间向量计算异面直线所成角、直线与平面所成角、二面角,以及点到平面的距离。通过输入向量坐标,实时计算并展示结果,帮助学生掌握空间角与距离的向量计算方法。
ArkTS代码:
@Entry
@Component
struct SpaceVectorCalculator {
@State private calculationType: string = 'skewLines' // skewLines, linePlane, dihedral, pointPlane
// 异面直线相关向量
@State private line1Point1: number[] = [0, 0, 0]
@State private line1Vector: number[] = [1, 0, 0]
@State private line2Point1: number[] = [0, 1, 0]
@State private line2Vector: number[] = [0, 0, 1]
// 直线与平面相关向量
@State private linePoint: number[] = [0, 0, 0]
@State private lineDir: number[] = [1, 0, 0]
@State private planePoint: number[] = [0, 0, 0]
@State private planeNormal: number[] = [0, 1, 0]
// 二面角相关向量
@State private plane1Point: number[] = [0, 0, 0]
@State private plane1Normal: number[] = [1, 0, 0]
@State private plane2Point: number[] = [0, 0, 0]
@State private plane2Normal: number[] = [0, 1, 0]
// 点到平面相关向量
@State private pointCoords: number[] = [1, 1, 1]
@State private planePointDistance: number[] = [0, 0, 0]
@State private planeNormalDistance: number[] = [0, 1, 0]
@State private result: string = ''
build() {
Column() {
Text('� 空间向量计算工具')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
// 计算类型选择
Row() {
Button('异面直线角')
.fontSize(12)
.onClick(() => this.calculationType = 'skewLines')
Button('直线平面角')
.fontSize(12)
.onClick(() => this.calculationType = 'linePlane')
Button('二面角')
.fontSize(12)
.onClick(() => this.calculationType = 'dihedral')
Button('点到平面距离')
.fontSize(12)
.onClick(() => this.calculationType = 'pointPlane')
}
.margin({ bottom: 20 })
// 输入区域
this.renderInputSection()
// 计算按钮
Button('计算')
.fontSize(16)
.onClick(() => this.calculate())
.margin({ top: 20, bottom: 20 })
// 结果显示
Column() {
Text('计算结果:')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Text(this.result)
.fontSize(14)
.fontColor('#2196F3')
.padding(15)
.backgroundColor('#f9f9f9')
.borderRadius(8)
.width('100%')
}
.margin({ top: 20 })
}
.padding(20)
.width('100%')
.height('100%')
}
@Builder
renderInputSection() {
Column() {
if (this.calculationType === 'skewLines') {
this.renderSkewLinesInput()
} else if (this.calculationType === 'linePlane') {
this.renderLinePlaneInput()
} else if (this.calculationType === 'dihedral') {
this.renderDihedralInput()
} else if (this.calculationType === 'pointPlane') {
this.renderPointPlaneInput()
}
}
}
@Builder
renderSkewLinesInput() {
Column() {
Text('异面直线所成角计算')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
// 直线1
Column() {
Text('直线1:')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
this.renderVectorInput('点1坐标:', this.line1Point1)
this.renderVectorInput('方向向量:', this.line1Vector)
}
.margin({ bottom: 20 })
// 直线2
Column() {
Text('直线2:')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
this.renderVectorInput('点1坐标:', this.line2Point1)
this.renderVectorInput('方向向量:', this.line2Vector)
}
}
}
@Builder
renderLinePlaneInput() {
Column() {
Text('直线与平面所成角计算')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
// 直线
Column() {
Text('直线:')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
this.renderVectorInput('直线上一点:', this.linePoint)
this.renderVectorInput('直线方向向量:', this.lineDir)
}
.margin({ bottom: 20 })
// 平面
Column() {
Text('平面:')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
this.renderVectorInput('平面上一点:', this.planePoint)
this.renderVectorInput('平面法向量:', this.planeNormal)
}
}
}
@Builder
renderDihedralInput() {
Column() {
Text('二面角计算')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
// 平面1
Column() {
Text('平面1:')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
this.renderVectorInput('平面上一点:', this.plane1Point)
this.renderVectorInput('平面法向量:', this.plane1Normal)
}
.margin({ bottom: 20 })
// 平面2
Column() {
Text('平面2:')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
this.renderVectorInput('平面上一点:', this.plane2Point)
this.renderVectorInput('平面法向量:', this.plane2Normal)
}
}
}
@Builder
renderPointPlaneInput() {
Column() {
Text('点到平面距离计算')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
// 点
this.renderVectorInput('点坐标:', this.pointCoords)
// 平面
Column() {
Text('平面:')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 10 })
this.renderVectorInput('平面上一点:', this.planePointDistance)
this.renderVectorInput('平面法向量:', this.planeNormalDistance)
}
}
}
@Builder
renderVectorInput(label: string, vector: number[]) {
Row() {
Text(label)
.width(100)
ForEach([0, 1, 2], (index: number) => {
TextInput({
text: vector[index].toString()
})
.type(InputType.Number)
.width(60)
.onChange((value: string) => {
const num = parseFloat(value) || 0
vector[index] = num
})
})
}
.margin({ bottom: 10 })
}
private calculate() {
switch (this.calculationType) {
case 'skewLines':
this.calculateSkewLinesAngle()
break
case 'linePlane':
this.calculateLinePlaneAngle()
break
case 'dihedral':
this.calculateDihedralAngle()
break
case 'pointPlane':
this.calculatePointPlaneDistance()
break
}
}
private calculateSkewLinesAngle() {
// 计算异面直线所成角
const v1 = this.line1Vector
const v2 = this.line2Vector
// 计算向量点积
const dotProduct = v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]
// 计算向量模长
const v1Magnitude = Math.sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2])
const v2Magnitude = Math.sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2])
if (v1Magnitude === 0 || v2Magnitude === 0) {
this.result = '方向向量不能为零向量'
return
}
// 计算夹角余弦值
const cosTheta = Math.abs(dotProduct) / (v1Magnitude * v2Magnitude)
// 计算角度(弧度转角度)
const theta = Math.acos(cosTheta) * 180 / Math.PI
this.result = `异面直线所成角: ${theta.toFixed(2)}°`
}
private calculateLinePlaneAngle() {
// 计算直线与平面所成角
const lineDir = this.lineDir
const planeNormal = this.planeNormal
// 计算向量点积
const dotProduct = lineDir[0] * planeNormal[0] + lineDir[1] * planeNormal[1] + lineDir[2] * planeNormal[2]
// 计算向量模长
const lineMagnitude = Math.sqrt(lineDir[0] * lineDir[0] + lineDir[1] * lineDir[1] + lineDir[2] * lineDir[2])
const normalMagnitude = Math.sqrt(planeNormal[0] * planeNormal[0] + planeNormal[1] * planeNormal[1] + planeNormal[2] * planeNormal[2])
if (lineMagnitude === 0 || normalMagnitude === 0) {
this.result = '方向向量或法向量不能为零向量'
return
}
// 计算直线与法向量的夹角余弦值
const cosPhi = Math.abs(dotProduct) / (lineMagnitude * normalMagnitude)
// 计算直线与平面的夹角(90度减去直线与法向量的夹角)
const phi = Math.acos(cosPhi) * 180 / Math.PI
const theta = 90 - phi
this.result = `直线与平面所成角: ${theta.toFixed(2)}°`
}
private calculateDihedralAngle() {
// 计算二面角
const n1 = this.plane1Normal
const n2 = this.plane2Normal
// 计算向量点积
const dotProduct = n1[0] * n2[0] + n1[1] * n2[1] + n1[2] * n2[2]
// 计算向量模长
const n1Magnitude = Math.sqrt(n1[0] * n1[0] + n1[1] * n1[1] + n1[2] * n1[2])
const n2Magnitude = Math.sqrt(n2[0] * n2[0] + n2[1] * n2[1] + n2[2] * n2[2])
if (n1Magnitude === 0 || n2Magnitude === 0) {
this.result = '法向量不能为零向量'
return
}
// 计算二面角余弦值
const cosTheta = dotProduct / (n1Magnitude * n2Magnitude)
// 计算角度(弧度转角度)
const theta = Math.acos(cosTheta) * 180 / Math.PI
// 二面角范围是[0, 180],但通常取锐角或直角
const finalAngle = theta <= 90 ? theta : 180 - theta
this.result = `二面角: ${finalAngle.toFixed(2)}°`
}
private calculatePointPlaneDistance() {
// 计算点到平面的距离
const point = this.pointCoords
const planePoint = this.planePointDistance
const planeNormal = this.planeNormalDistance
// 计算向量 PA
const PA = [planePoint[0] - point[0], planePoint[1] - point[1], planePoint[2] - point[2]]
// 计算向量点积
const dotProduct = PA[0] * planeNormal[0] + PA[1] * planeNormal[1] + PA[2] * planeNormal[2]
// 计算法向量模长
const normalMagnitude = Math.sqrt(planeNormal[0] * planeNormal[0] + planeNormal[1] * planeNormal[1] + planeNormal[2] * planeNormal[2])
if (normalMagnitude === 0) {
this.result = '法向量不能为零向量'
return
}
// 计算距离
const distance = Math.abs(dotProduct) / normalMagnitude
this.result = `点到平面的距离: ${distance.toFixed(3)}`
}
}
更多推荐


所有评论(0)