/* * @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 }