jinglun-cloud
1 天以前 64819e1e2254316a090fd056b80f139ca4dbcf94
refactor(地图几何计算): 重构线段投影距离计算逻辑

将 lineSignedRemainAlong 函数从 MapCanvas 组件移至 mapTrackGeometry 工具模块
简化 calcSignedSegmentDelta 函数中的环形轨道判断逻辑
使用工具模块中的几何计算函数替代重复实现
2个文件已修改
78 ■■■■ 已修改文件
src/main/webapp/components/MapCanvas.js 47 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/basMap/mapTrackGeometry.js 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/components/MapCanvas.js
@@ -1329,37 +1329,11 @@
    calcSignedSegmentDelta(fromBarcode, toBarcode, trackInfo, totalSegmentCount) {
      const from = Number(fromBarcode);
      const to = Number(toBarcode);
      if (!isFinite(from) || !isFinite(to)) {
        return 0;
      }
      if (!isFinite(from) || !isFinite(to)) return 0;
      const raw = to - from;
      if (trackInfo.type !== 'annulus') {
        return raw;
      }
      const span = totalSegmentCount;
      if (!(span > 0)) {
        return raw;
      }
      const mod = (n, m) => ((n % m) + m) % m;
      return mod(raw, span);
    },
    lineSignedRemainAlong(path0, sx, sy, mx, my) {
      if (!path0 || path0.type !== 'line') {
        return null;
      }
      const x0 = path0.startX;
      const y0 = path0.startY;
      const vx = path0.x - x0;
      const vy = path0.y - y0;
      const segLen = Math.sqrt(vx * vx + vy * vy);
      if (!(segLen > EPSILON)) {
        return null;
      }
      const clampT = (px, py) => {
        const t = ((px - x0) * vx + (py - y0) * vy) / segLen;
        return Math.max(0, Math.min(segLen, t));
      };
      return clampT(mx, my) - clampT(sx, sy);
      if (trackInfo.type !== 'annulus' || totalSegmentCount <= 0) return raw;
      // 非负取模
      return ((raw % totalSegmentCount) + totalSegmentCount) % totalSegmentCount;
    },
    finishDeviceMotion(sprite) {
      if (!sprite || !sprite.mappingInfo) {
@@ -1521,7 +1495,7 @@
        pathList.length === 1 && pathList[0].type === 'line' && sprite.trackInfo.type !== 'annulus';
      let smoothDistance;
      if (singleLineTrack) {
        const remainAlong = this.lineSignedRemainAlong(
        const remainAlong = G.lineSignedRemainAlong(
          path,
          sprite.x,
          sprite.y,
@@ -1531,14 +1505,11 @@
        if (remainAlong != null) {
          let stepMag = Math.min(stepCap, Math.abs(remainAlong), restDistance);
          if (stepMag < EPSILON && restDistance > EPSILON) {
            const x0 = path.startX;
            const y0 = path.startY;
            const vx = path.x - x0;
            const vy = path.y - y0;
            const sl = Math.sqrt(vx * vx + vy * vy);
            const lineStart = { x: path.startX, y: path.startY };
            const lineEnd = { x: path.x, y: path.y };
            const sl = G.calcDistance(lineStart, lineEnd);
            if (sl > EPSILON) {
              const ux = vx / sl;
              const uy = vy / sl;
              const { x: ux, y: uy } = G.normalizeVector(lineStart, lineEnd);
              const wdx = sprite.mappingInfo.x - sprite.x;
              const wdy = sprite.mappingInfo.y - sprite.y;
              const hint = wdx * ux + wdy * uy;
src/main/webapp/static/js/basMap/mapTrackGeometry.js
@@ -586,6 +586,34 @@
    return count === 2;
  }
  /**
   * 计算点 (sx,sy) 和 (mx,my) 在直线段 path0 上的带符号投影距离差。
   * 返回值 >0 表示 mx,my 在 sx,sy 前方(沿路径方向)。
   * @param {{ type: string, startX: number, startY: number, x: number, y: number }} path0 直线段路径
   * @param {number} sx 起点 x
   * @param {number} sy 起点 y
   * @param {number} mx 终点 x
   * @param {number} my 终点 y
   * @returns {number|null} 带符号距离差,非线段或零长度时返回 null
   */
  function lineSignedRemainAlong(path0, sx, sy, mx, my) {
    if (!path0 || path0.type !== 'line') {
      return null;
    }
    var start = { x: path0.startX, y: path0.startY };
    var end = { x: path0.x, y: path0.y };
    var segLen = calcDistance(start, end);
    if (!(segLen > 0)) {
      return null;
    }
    var vector = normalizeVector(start, end);
    var clampT = function (px, py) {
      var t = ((px - start.x) * vector.x + (py - start.y) * vector.y) * segLen;
      return Math.max(0, Math.min(segLen, t));
    };
    return clampT(mx, my) - clampT(sx, sy);
  }
  function setRadiusInPoint(pointList, sprite) {
    sprite.halfList = [];
    var pointLength = pointList.length;
@@ -1017,6 +1045,7 @@
    startDrawSmoothedPath: startDrawSmoothedPath,
    getRotate: getRotate,
    drawCrnDeviceGraphics: drawCrnDeviceGraphics,
    drawRgvDeviceGraphics: drawRgvDeviceGraphics
    drawRgvDeviceGraphics: drawRgvDeviceGraphics,
    lineSignedRemainAlong: lineSignedRemainAlong
  };
})(typeof window !== 'undefined' ? window : this);