xushiting 2 年之前
父節點
當前提交
8f24f1f86e
共有 3 個文件被更改,包括 201 次插入108 次删除
  1. 42 38
      src/graphic/ListenLayer.js
  2. 15 0
      src/graphic/Service/RoadService.js
  3. 144 70
      src/graphic/Util/MathUtil.js

+ 42 - 38
src/graphic/ListenLayer.js

@@ -288,7 +288,7 @@ export default class ListenLayer {
         continue;
       }
       const curveRoad = dataService.getCurveRoad(curveRoadId);
-      console.log("currentRoad", curveRoad.curves)
+      console.log("currentRoad", curveRoad.curves);
       let joinInfo = this.distanceForBezier(position, curveRoad.curves);
       if (joinInfo.distance < Constant.minAdsorbPix) {
         curveRoadInfo = {
@@ -455,44 +455,48 @@ export default class ListenLayer {
     // return flag1 && flag2 && flag3 && flag4;
   }
 
+  // distanceForBezier(position, curves) {
+  //   let joinInfo = {
+  //     position: null,
+  //     distance: null,
+  //   };
+  //   for (let i = 0; i < curves.length; ++i) {
+  //     const curve = curves[i];
+  //     let bezierData = [];
+  //     bezierData.push(curve.start.x);
+  //     bezierData.push(curve.start.y);
+  //     bezierData.push(curve.control.x);
+  //     bezierData.push(curve.control.y);
+  //     bezierData.push(curve.end.x);
+  //     bezierData.push(curve.end.y);
+  //     const { isHit, getInfo } = bezierUtil.measureBezier(...bezierData);
+  //     const { point } = getInfo(position);
+  //     const distance = mathUtil.getDistance(position, {
+  //       x: point[0],
+  //       y: point[1],
+  //     });
+  //     if (joinInfo.distance == null || distance < joinInfo.distance) {
+  //       joinInfo.distance = mathUtil.getDistance(position, {
+  //         x: point[0],
+  //         y: point[1],
+  //       });
+  //       joinInfo.position = {
+  //         x: point[0],
+  //         y: point[1],
+  //       };
+  //     }
+  //   }
+  //   if (joinInfo.distance != null) {
+  //     console.log("离曲线距离:" + joinInfo.distance);
+  //     //position到joinInfo.position的线段
+  //     //draw.clear();
+  //     draw.drawTestLine(position, joinInfo.position);
+  //   }
+  //   return joinInfo;
+  // }
+
   distanceForBezier(position, curves) {
-    let joinInfo = {
-      position: null,
-      distance: null,
-    };
-    for (let i = 0; i < curves.length; ++i) {
-      const curve = curves[i];
-      let bezierData = [];
-      bezierData.push(curve.start.x);
-      bezierData.push(curve.start.y);
-      bezierData.push(curve.control.x);
-      bezierData.push(curve.control.y);
-      bezierData.push(curve.end.x);
-      bezierData.push(curve.end.y);
-      const { isHit, getInfo } = bezierUtil.measureBezier(...bezierData);
-      const { point } = getInfo(position);
-      const distance = mathUtil.getDistance(position, {
-        x: point[0],
-        y: point[1],
-      });
-      if (joinInfo.distance == null || distance < joinInfo.distance) {
-        joinInfo.distance = mathUtil.getDistance(position, {
-          x: point[0],
-          y: point[1],
-        });
-        joinInfo.position = {
-          x: point[0],
-          y: point[1],
-        };
-      }
-    }
-    if (joinInfo.distance != null) {
-      console.log("离曲线距离:" + joinInfo.distance);
-      //position到joinInfo.position的线段
-      //draw.clear();
-      draw.drawTestLine(position, joinInfo.position);
-    }
-    return joinInfo;
+    return mathUtil.getHitInfoForCurves(position, curves);
   }
 
   equalAndClone(info1, info2) {

+ 15 - 0
src/graphic/Service/RoadService.js

@@ -844,6 +844,11 @@ export default class RoadService {
     const startJoin2 = mathUtil.getJoinLinePoint(rightEdge.start, line);
     const distance1 = mathUtil.getDistance(startJoin1, mid);
     const distance2 = mathUtil.getDistance(startJoin2, mid);
+
+    if (road.midDivide == null) {
+      road.midDivide = {};
+    }
+
     if (!dir || dir == "start") {
       if (distance1 > distance2) {
         road.midDivide.start = {
@@ -875,6 +880,7 @@ export default class RoadService {
         };
       }
     }
+    this.setMidDivideDisplay(roadId);
   }
 
   setMidDivideForPointId(pointId) {
@@ -884,6 +890,15 @@ export default class RoadService {
     }
   }
 
+  setMidDivideDisplay(roadId) {
+    const road = dataService.getRoad(roadId);
+    if (road.leftDrivewayCount == 0 || road.rightDrivewayCount == 0) {
+      road.midDivide.display = false;
+    } else {
+      road.midDivide.display = true;
+    }
+  }
+
   //设置车道
   setLanes(roadId, dir) {
     let road = dataService.getRoad(roadId);

+ 144 - 70
src/graphic/Util/MathUtil.js

@@ -1,4 +1,5 @@
 import Constant from "../Constant";
+import bezierUtil from "./bezierUtil.js";
 
 export default class MathUtil {
   constructor() {}
@@ -1043,22 +1044,22 @@ export default class MathUtil {
   pointMinus(v1, v2) {
     return {
       x: v1.x - v2.x,
-      y: v1.y - v2.y
-    }
+      y: v1.y - v2.y,
+    };
   }
   // 两点相加
   pointPlus(v1, v2) {
     return {
       x: v1.x + v2.x,
-      y: v1.y + v2.y
-    }
+      y: v1.y + v2.y,
+    };
   }
   // 点放大
   pointScale(v, a) {
     return {
       x: v.x * a,
-      y: v.y * a
-    }
+      y: v.y * a,
+    };
   }
 
   clamp(value, min, max) {
@@ -1069,7 +1070,6 @@ export default class MathUtil {
     return v.x * v.x + v.y * v.y;
   }
 
-
   // 当前点 下一个点 下下个点
   getCurvesControls(p1, pt, p2, scale = 0.3) {
     const vec1T = mathUtil.pointMinus(p1, pt);
@@ -1082,12 +1082,18 @@ export default class MathUtil {
     if (v > 1) {
       delta = mathUtil.pointMinus(
         p1,
-        mathUtil.pointPlus(pt, mathUtil.pointScale(mathUtil.pointMinus(p2, pt), (1 / v))),
+        mathUtil.pointPlus(
+          pt,
+          mathUtil.pointScale(mathUtil.pointMinus(p2, pt), 1 / v)
+        )
       );
     } else {
       delta = mathUtil.pointMinus(
-        mathUtil.pointPlus(pt, mathUtil.pointScale(mathUtil.pointMinus(p1, pt), v)),
-        p2,
+        mathUtil.pointPlus(
+          pt,
+          mathUtil.pointScale(mathUtil.pointMinus(p1, pt), v)
+        ),
+        p2
       );
     }
     delta = mathUtil.pointScale(delta, scale);
@@ -1100,44 +1106,42 @@ export default class MathUtil {
       x: mathUtil.pointMinus(pt, delta).x,
       y: mathUtil.pointMinus(pt, delta).y,
     };
-    return {control1, control2}
+    return { control1, control2 };
   }
 
   getCurvesByPoints(points, scale = 0.2) {
     const curves = [];
-    let preControl1, preControl2
+    let preControl1, preControl2;
     for (let i = 0; i < points.length - 2; i++) {
-      const {control1, control2} = mathUtil.getCurvesControls(
+      const { control1, control2 } = mathUtil.getCurvesControls(
         points[i],
         points[i + 1],
         points[i + 2],
         scale
-      )
+      );
       curves.push({
         start: points[i],
         end: points[i + 1],
-        controls: i === 0 ? [control1] :  [preControl2, control1]
-      })
+        controls: i === 0 ? [control1] : [preControl2, control1],
+      });
       if (i + 2 === points.length - 1) {
         curves.push({
           start: points[i + 1],
           controls: [control2],
           end: points[i + 2],
-        })
+        });
       }
-      preControl1 = control1
-      preControl2 = control2
+      preControl1 = control1;
+      preControl2 = control2;
     }
     curves.push({
       start: points[points.length - 2],
       controls: [preControl2],
       end: points[points.length - 1],
-    })
-    return curves
+    });
+    return curves;
   }
 
-
-
   /**
    * 已知四个控制点,及曲线中的某一个点的 x/y,反推求 t
    * @param {number} x1 起点 x/y
@@ -1148,63 +1152,75 @@ export default class MathUtil {
    * @returns {number[]} t[]
    */
   getThreeBezierT(x1, x2, x3, x4, X) {
-    const a = -x1 + 3 * x2 - 3 * x3 + x4
-    const b = 3 * x1 - 6 * x2 + 3 * x3
-    const c = -3 * x1 + 3 * x2
-    const d = x1 - X
+    const a = -x1 + 3 * x2 - 3 * x3 + x4;
+    const b = 3 * x1 - 6 * x2 + 3 * x3;
+    const c = -3 * x1 + 3 * x2;
+    const d = x1 - X;
 
     // 盛金公式, 预先需满足, a !== 0
     // 判别式
-    const A = Math.pow(b, 2) - 3 * a * c
-    const B = b * c - 9 * a * d
-    const C = Math.pow(c, 2) - 3 * b * d
-    const delta = Math.pow(B, 2) - 4 * A * C
+    const A = Math.pow(b, 2) - 3 * a * c;
+    const B = b * c - 9 * a * d;
+    const C = Math.pow(c, 2) - 3 * b * d;
+    const delta = Math.pow(B, 2) - 4 * A * C;
 
-    let t1 = -100, t2 = -100, t3 = -100
+    let t1 = -100,
+      t2 = -100,
+      t3 = -100;
 
     // 3个相同实数根
     if (A === B && A === 0) {
-      t1 = -b / (3 * a)
-      t2 = -c / b
-      t3 = -3 * d / c
-      return [t1, t2, t3]
+      t1 = -b / (3 * a);
+      t2 = -c / b;
+      t3 = (-3 * d) / c;
+      return [t1, t2, t3];
     }
 
     // 1个实数根和1对共轭复数根
     if (delta > 0) {
-      const v = Math.pow(B, 2) - 4 * A * C
-      const xsv = v < 0 ? -1 : 1
+      const v = Math.pow(B, 2) - 4 * A * C;
+      const xsv = v < 0 ? -1 : 1;
 
-      const m1 = A * b + 3 * a * (-B + (v * xsv) ** (1 / 2) * xsv) / 2
-      const m2 = A * b + 3 * a * (-B - (v * xsv) ** (1 / 2) * xsv) / 2
+      const m1 = A * b + (3 * a * (-B + (v * xsv) ** (1 / 2) * xsv)) / 2;
+      const m2 = A * b + (3 * a * (-B - (v * xsv) ** (1 / 2) * xsv)) / 2;
 
-      const xs1 = m1 < 0 ? -1 : 1
-      const xs2 = m2 < 0 ? -1 : 1
+      const xs1 = m1 < 0 ? -1 : 1;
+      const xs2 = m2 < 0 ? -1 : 1;
 
-      t1 = (-b - (m1 * xs1) ** (1 / 3) * xs1 - (m2 * xs2) ** (1 / 3) * xs2) / (3 * a)
+      t1 =
+        (-b - (m1 * xs1) ** (1 / 3) * xs1 - (m2 * xs2) ** (1 / 3) * xs2) /
+        (3 * a);
       // 涉及虚数,可不考虑。i ** 2 = -1
     }
 
     // 3个实数根
     if (delta === 0) {
-      const K = B / A
-      t1 = -b / a + K
-      t2 = t3 = -K / 2
+      const K = B / A;
+      t1 = -b / a + K;
+      t2 = t3 = -K / 2;
     }
 
     // 3个不相等实数根
     if (delta < 0) {
-      const xsA = A < 0 ? -1 : 1
-      const T = (2 * A * b - 3 * a * B) / (2 * (A * xsA) ** (3 / 2) * xsA)
-      const theta = Math.acos(T)
+      const xsA = A < 0 ? -1 : 1;
+      const T = (2 * A * b - 3 * a * B) / (2 * (A * xsA) ** (3 / 2) * xsA);
+      const theta = Math.acos(T);
 
       if (A > 0 && T < 1 && T > -1) {
-        t1 = (-b - 2 * A ** (1 / 2) * Math.cos(theta / 3)) / (3 * a)
-        t2 = (-b + A ** (1 / 2) * (Math.cos(theta / 3) + 3 ** (1 / 2) * Math.sin(theta / 3))) / (3 * a)
-        t3 = (-b + A ** (1 / 2) * (Math.cos(theta / 3) - 3 ** (1 / 2) * Math.sin(theta / 3))) / (3 * a)
+        t1 = (-b - 2 * A ** (1 / 2) * Math.cos(theta / 3)) / (3 * a);
+        t2 =
+          (-b +
+            A ** (1 / 2) *
+              (Math.cos(theta / 3) + 3 ** (1 / 2) * Math.sin(theta / 3))) /
+          (3 * a);
+        t3 =
+          (-b +
+            A ** (1 / 2) *
+              (Math.cos(theta / 3) - 3 ** (1 / 2) * Math.sin(theta / 3))) /
+          (3 * a);
       }
     }
-    return [t1, t2, t3]
+    return [t1, t2, t3];
   }
 
   /**
@@ -1217,55 +1233,113 @@ export default class MathUtil {
    * @param {Array} cp2 控制点2
    */
   getThreeBezierPoint(t, p1, cp1, cp2, p2) {
-    const {x: x1, y: y1} = p1
-    const {x: x2, y: y2} = p2
-    const {x: cx1, y: cy1} = cp1
-    const {x: cx2, y: cy2} = cp2
+    const { x: x1, y: y1 } = p1;
+    const { x: x2, y: y2 } = p2;
+    const { x: cx1, y: cy1 } = cp1;
+    const { x: cx2, y: cy2 } = cp2;
 
     const x =
       x1 * (1 - t) * (1 - t) * (1 - t) +
       3 * cx1 * t * (1 - t) * (1 - t) +
       3 * cx2 * t * t * (1 - t) +
-      x2 * t * t * t
+      x2 * t * t * t;
     const y =
       y1 * (1 - t) * (1 - t) * (1 - t) +
       3 * cy1 * t * (1 - t) * (1 - t) +
       3 * cy2 * t * t * (1 - t) +
-      y2 * t * t * t
-    return {x, y}
+      y2 * t * t * t;
+    return { x, y };
   }
 
-  isAboveThreeBezier(offsetX, offsetY, curve, rang = 3) {
+  getHitInfoForThreeBezier(offsetX, offsetY, curve, rang = 3) {
     // 用 x 求出对应的 t,用 t 求相应位置的 y,再比较得出的 y 与 offsetY 之间的差值
-    const tsx = mathUtil.getThreeBezierT(curve.start.x, curve.controls[0].x, curve.controls[1].x, curve.end.x, offsetX)
+    const tsx = mathUtil.getThreeBezierT(
+      curve.start.x,
+      curve.controls[0].x,
+      curve.controls[1].x,
+      curve.end.x,
+      offsetX
+    );
     for (let x = 0; x < 3; x++) {
       if (tsx[x] <= 1 && tsx[x] >= 0) {
-        const point = mathUtil.getThreeBezierPoint(tsx[x], curve.start, curve.controls[0], curve.controls[1], curve.end)
+        const point = mathUtil.getThreeBezierPoint(
+          tsx[x],
+          curve.start,
+          curve.controls[0],
+          curve.controls[1],
+          curve.end
+        );
         if (Math.abs(point.y - offsetY) < rang) {
-          return point
+          return point;
         }
       }
     }
     // 如果上述没有结果,则用 y 求出对应的 t,再用 t 求出对应的 x,与 offsetX 进行匹配
-    const tsy = mathUtil.getThreeBezierT(curve.start.y, curve.controls[0].y, curve.controls[1].y, curve.end.y, offsetY)
+    const tsy = mathUtil.getThreeBezierT(
+      curve.start.y,
+      curve.controls[0].y,
+      curve.controls[1].y,
+      curve.end.y,
+      offsetY
+    );
     for (let y = 0; y < 3; y++) {
       if (tsy[y] <= 1 && tsy[y] >= 0) {
-        const point = mathUtil.getThreeBezierPoint(tsy[y], curve.start, curve.controls[0], curve.controls[1], curve.end)
+        const point = mathUtil.getThreeBezierPoint(
+          tsy[y],
+          curve.start,
+          curve.controls[0],
+          curve.controls[1],
+          curve.end
+        );
         if (Math.abs(point.x - offsetX) < rang) {
-          return point
+          return point;
         }
       }
     }
   }
 
-  isAboveCurves(pos, curves) {
+  // 二次曲线
+  getHitInfoForTwoBezier(position, curves) {
+    let joinInfo = {
+      position: null,
+      distance: null,
+    };
+    for (let i = 0; i < curves.length; ++i) {
+      const curve = curves[i];
+      let bezierData = [];
+      bezierData.push(curve.start.x);
+      bezierData.push(curve.start.y);
+      bezierData.push(curve.control.x);
+      bezierData.push(curve.control.y);
+      bezierData.push(curve.end.x);
+      bezierData.push(curve.end.y);
+      const { isHit, getInfo } = bezierUtil.measureBezier(...bezierData);
+      const { point } = getInfo(position);
+      const distance = mathUtil.getDistance(position, {
+        x: point[0],
+        y: point[1],
+      });
+      if (joinInfo.distance == null || distance < joinInfo.distance) {
+        joinInfo.distance = mathUtil.getDistance(position, {
+          x: point[0],
+          y: point[1],
+        });
+        joinInfo.position = {
+          x: point[0],
+          y: point[1],
+        };
+      }
+    }
+    return joinInfo;
+  }
+
+  getHitInfoForCurves(pos, curves) {
     for (const curve of curves) {
       if (curve.controls.length === 2) {
-        if (mathUtil.isAboveThreeBezier(pos.x, pos.y, curve)) {
+        if (mathUtil.getHitInfoForThreeBezier(pos.x, pos.y, curve)) {
           return true;
         }
       } else {
-        // 二次曲线
       }
     }
   }