一些技术路线测试,增加git,方便代码还原
f
shuishen
2025-11-21 7bab9ee5b085382ffe2344ca0c504c3aa7770d25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/**
 * 几何工具类
 * 提供法向量计算、按法线偏移、线段分割、点到线段投影、角点校正、分割线位置交错等常用几何方法
 */
export class GeometryUtils {
  /**
   * 计算四点组成平面的法向量(单位化)
   * @param {Cesium.Cartesian3[]} positions 四个顶点 [p0,p1,p2,p3]
   * @returns {Cesium.Cartesian3} 单位法向量
   */
  computeNormal (positions) {
    // 边向量:p0->p2 与 p1->p3 的叉积得到法向量
    const v13 = Cesium.Cartesian3.subtract(positions[0], positions[2], new Cesium.Cartesian3())
    const v24 = Cesium.Cartesian3.subtract(positions[1], positions[3], new Cesium.Cartesian3())
    const n = Cesium.Cartesian3.cross(v13, v24, new Cesium.Cartesian3())
    return Cesium.Cartesian3.normalize(n, new Cesium.Cartesian3())
  }
  /**
   * 按法向量将平面上的所有点整体偏移指定高度
   * @param {Cesium.Cartesian3[]} positions 原始顶点数组
   * @param {number} relativeHeight 相对高度(米),沿法线正向偏移
   * @returns {Cesium.Cartesian3[]} 偏移后的顶点数组
   */
  computeOffsetPositions (positions, relativeHeight) {
    const normal = this.computeNormal(positions)
    const offset = Cesium.Cartesian3.multiplyByScalar(normal, relativeHeight, new Cesium.Cartesian3())
    const out = new Array(positions.length)
    for (let i = 0; i < positions.length; i++) { out[i] = Cesium.Cartesian3.add(positions[i], offset, new Cesium.Cartesian3()) }
    return out
  }
  /**
   * 按指定间距分割线段,返回分割点序列
   * @param {Cesium.Cartesian3} point1 起点
   * @param {Cesium.Cartesian3} point2 终点
   * @param {number} s 目标分割间距(米)
   * @param {boolean} reverse 是否反向输出(从终点到起点)
   * @returns {Cesium.Cartesian3[]} 分割点数组(含端点)
   */
  splitSegment (point1, point2, s, reverse) {
    const distance = Cesium.Cartesian3.distance(point1, point2)
    const segments = Math.max(1, Math.ceil(distance / s))
    const points = new Array(segments + 1)
    if (reverse) {
      for (let i = segments; i >= 0; i--) { const fraction = i / segments; const pt = new Cesium.Cartesian3(); Cesium.Cartesian3.lerp(point1, point2, fraction, pt); points[segments - i] = pt }
    } else {
      for (let i = 0; i <= segments; i++) { const fraction = i / segments; const pt = new Cesium.Cartesian3(); Cesium.Cartesian3.lerp(point1, point2, fraction, pt); points[i] = pt }
    }
    return points
  }
  /**
   * 将点 A 在由 B->C 定义的方向上进行投影,返回投影点坐标(不裁剪到线段范围)
   * @param {Cesium.Cartesian3} pointA 待投影点
   * @param {Cesium.Cartesian3} pointB 基点(投影起点)
   * @param {Cesium.Cartesian3} pointC 方向参考点(形成向量 B->C)
   * @returns {Cesium.Cartesian3} 投影点(位于经过 B 且方向为 B->C 的直线上)
   */
  projectPointOnSegment (pointA, pointB, pointC) {
    const vectorBC = Cesium.Cartesian3.subtract(pointC, pointB, new Cesium.Cartesian3())
    const vectorBA = Cesium.Cartesian3.subtract(pointA, pointB, new Cesium.Cartesian3())
    const projection = new Cesium.Cartesian3()
    Cesium.Cartesian3.projectVector(vectorBA, vectorBC, projection)
    return Cesium.Cartesian3.add(pointB, projection, new Cesium.Cartesian3())
  }
  /**
   * 基于投影校正四角点位置,使得边保持相对一致与闭合
   * @param {Cesium.Cartesian3[]} positionOffset 四角点(已按法线偏移)数组 [p0,p1,p2,p3]
   * @param {number} distance01 边 p0-p1 的长度,用于阈值判断
   * @returns {{newPointList: Cesium.Cartesian3[], distanceP2:number, distanceP3:number, distanceP20:number, distanceP21:number, distanceP30:number, distanceP31:number}}
   */
  adjustCornersByProjection (positionOffset, distance01) {
    const projectionPoint2 = this.projectPointOnSegment(positionOffset[2], positionOffset[1], positionOffset[0])
    const projectionPoint3 = this.projectPointOnSegment(positionOffset[3], positionOffset[0], positionOffset[1])
    const distanceP2 = Cesium.Cartesian3.distance(projectionPoint2, positionOffset[2])
    const distanceP3 = Cesium.Cartesian3.distance(projectionPoint3, positionOffset[3])
    const distanceP30 = Cesium.Cartesian3.distance(projectionPoint3, positionOffset[0])
    const distanceP31 = Cesium.Cartesian3.distance(projectionPoint3, positionOffset[1])
    const newPoint0 = distanceP30 + distanceP31 > distance01 ? projectionPoint3 : positionOffset[0]
    const distanceP20 = Cesium.Cartesian3.distance(projectionPoint2, positionOffset[0])
    const distanceP21 = Cesium.Cartesian3.distance(projectionPoint2, positionOffset[1])
    const newPoint1 = distanceP20 + distanceP21 > distance01 ? projectionPoint2 : positionOffset[1]
    let newPoint2, newPoint3
    if (distanceP2 > distanceP3) {
      if (distanceP20 + distanceP21 > distance01) { newPoint2 = positionOffset[2] } else { const vector = Cesium.Cartesian3.subtract(positionOffset[1], projectionPoint2, new Cesium.Cartesian3()); newPoint2 = Cesium.Cartesian3.add(positionOffset[2], vector, new Cesium.Cartesian3()) }
      const vector01 = Cesium.Cartesian3.subtract(newPoint0, newPoint1, new Cesium.Cartesian3())
      newPoint3 = Cesium.Cartesian3.add(newPoint2, vector01, new Cesium.Cartesian3())
    } else {
      if (distanceP30 + distanceP31 > distance01) { newPoint3 = positionOffset[3] } else { const vector = Cesium.Cartesian3.subtract(positionOffset[0], projectionPoint3, new Cesium.Cartesian3()); newPoint3 = Cesium.Cartesian3.add(positionOffset[3], vector, new Cesium.Cartesian3()) }
      const vector01 = Cesium.Cartesian3.subtract(newPoint1, newPoint0, new Cesium.Cartesian3())
      newPoint2 = Cesium.Cartesian3.add(newPoint3, vector01, new Cesium.Cartesian3())
    }
    return { newPointList: [newPoint0, newPoint1, newPoint2, newPoint3, newPoint0], distanceP2, distanceP3, distanceP20, distanceP21, distanceP30, distanceP31 }
  }
  /**
   * 交错合并两段分割点序列,形成折线的交错点序列
   * @param {Cesium.Cartesian3[]} arr1 序列一
   * @param {Cesium.Cartesian3[]} arr2 序列二
   * @param {Cesium.Cartesian3[]} out 输出数组引用,将被填充
   */
  handleSplitLinePosition (arr1, arr2, out) {
    arr1.forEach((item, i) => { if (i % 2 === 0) { out.push(arr2[i], item) } else { out.push(item, arr2[i]) } })
  }
}