You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
3.2 KiB
TypeScript
89 lines
3.2 KiB
TypeScript
/*
|
|
* @Author: cbwu 504-wuchengbo@htsdfp.com
|
|
* @Date: 2024-03-22 15:42:49
|
|
* @LastEditors: cbwu
|
|
* @LastEditTime: 2024-04-01 14:05:43
|
|
* @Description: 地理计算
|
|
*/
|
|
import { Cartesian3, Math as Cesium_Math } from 'cesium'
|
|
/**
|
|
* 计算空间中一点到一条直线的最短距离的交点(在不考虑地球曲率的情况下)
|
|
* @param lineStart 直线的起点:[longitude1, latitude1, height1]
|
|
* @param lineEnd 直线的终点:[longitude2, latitude2, height2]
|
|
* @param point 空间中的点:[[longitude3, latitude3, height3]]
|
|
* @returns 最近的交点
|
|
*/
|
|
function getClosestPoint(
|
|
lineStart: Cartesian3,
|
|
lineEnd: Cartesian3,
|
|
point: Cartesian3,
|
|
): Cartesian3 {
|
|
// 计算直线方向向量
|
|
const lineDirection = new Cartesian3()
|
|
Cartesian3.subtract(lineEnd, lineStart, lineDirection)
|
|
Cartesian3.normalize(lineDirection, lineDirection)
|
|
|
|
// 计算点到直线起点的向量
|
|
const pointToStart = new Cartesian3()
|
|
Cartesian3.subtract(point, lineStart, pointToStart)
|
|
|
|
// 计算投影长度,即点到直线的向量在直线方向向量上的分量长度
|
|
const projectionLength = Cartesian3.dot(pointToStart, lineDirection)
|
|
|
|
// 使用标量乘法和向量加法确定交点
|
|
const closestPoint = new Cartesian3()
|
|
Cartesian3.multiplyByScalar(lineDirection, projectionLength, closestPoint)
|
|
Cartesian3.add(lineStart, closestPoint, closestPoint)
|
|
return closestPoint
|
|
}
|
|
|
|
/**
|
|
* 判断一个点是否在直线上(在不考虑地球曲率的情况下)
|
|
* @param lineStart 直线的起点:[longitude1, latitude1, height1]
|
|
* @param lineEnd 直线的起点:[longitude2, latitude2, height2]
|
|
* @param pointToCheck 直线的起点:[longitude3, latitude3, height3]
|
|
* @param tolerance 容差
|
|
* @returns 是否在线段上
|
|
*/
|
|
function isOnLineSegment(
|
|
lineStart: Cartesian3,
|
|
lineEnd: Cartesian3,
|
|
pointToCheck: Cartesian3,
|
|
tolerance: number = Cesium_Math.EPSILON1,
|
|
): boolean {
|
|
const dist_AP = Cartesian3.distance(lineStart, pointToCheck)
|
|
const dist_BP = Cartesian3.distance(lineEnd, pointToCheck)
|
|
const dist_AB = Cartesian3.distance(lineStart, lineEnd)
|
|
|
|
const isCollinear = Math.abs(dist_AP + dist_BP - dist_AB) < tolerance
|
|
return isCollinear
|
|
/*
|
|
const startToEnd = new Cartesian3()
|
|
const startToPoint = new Cartesian3()
|
|
const endToPoint = new Cartesian3()
|
|
|
|
// 计算向量
|
|
Cartesian3.subtract(lineEnd, lineStart, startToEnd)
|
|
Cartesian3.subtract(pointToCheck, lineStart, startToPoint)
|
|
Cartesian3.subtract(pointToCheck, lineEnd, endToPoint)
|
|
|
|
// 判断共线
|
|
const cross = Cartesian3.cross(startToEnd, startToPoint, new Cartesian3())
|
|
console.log('cross:' + Cartesian3.magnitude(cross).toString())
|
|
// Math.EPSILON6 是一个非常小的值,用来防止浮点数计算的误差
|
|
const isCollinear = Cartesian3.magnitude(cross) < tolerance
|
|
|
|
// 判断点是否在线段之间
|
|
let isBetween = false
|
|
if (isCollinear) {
|
|
const dotProduct1 = Cartesian3.dot(startToEnd, startToPoint)
|
|
const dotProduct2 = Cartesian3.dot(startToEnd, endToPoint)
|
|
isBetween = dotProduct1 >= 0 && dotProduct2 <= 0
|
|
}
|
|
return isBetween
|
|
*/
|
|
}
|
|
|
|
|
|
export { getClosestPoint, isOnLineSegment }
|