Browse Source

Merge branch 'dev' of http://192.168.0.115:3000/bill/traffic-laser into dev

xzw 4 tháng trước cách đây
mục cha
commit
be09bcc5a5

+ 10 - 11
src/dbo/main.ts

@@ -1,16 +1,15 @@
-import axios from 'axios'
-import {params} from "@/hook";
+import axios from "axios";
+import { params } from "@/hook";
 
-const instance = axios.create()
+const instance = axios.create();
 
-console.log(import.meta.env)
-export const baseURL =
-  import.meta.env.VITE_API_BASE_URL
-    ? `/${import.meta.env.VITE_API_BASE_URL}/${params.m}`
-    : `/${params.m}`;
+console.log(import.meta.env);
+export const baseURL = import.meta.env.VITE_API_BASE_URL
+  ? `/${import.meta.env.VITE_API_BASE_URL}/${params.m}`
+  : `/${params.m}`;
 
-instance.defaults.baseURL = baseURL
+instance.defaults.baseURL = baseURL;
 
-export const getStaticFile = (url: string) => baseURL + url
+export const getStaticFile = (url: string) => baseURL + url;
 
-export default instance
+export default instance;

+ 75 - 10
src/graphic/Controls/MoveSVG.js

@@ -1,3 +1,4 @@
+import Constant from "../Constant";
 import { dataService } from "../Service/DataService";
 import { mathUtil } from "../Util/MathUtil";
 
@@ -21,6 +22,8 @@ export default class MoveSVG {
 
     svg.points[3].x += dx;
     svg.points[3].y += dy;
+
+    svg.setControlAnglePoint();
   }
 
   // movePoint(position, svgId, pointIndex) {
@@ -31,23 +34,85 @@ export default class MoveSVG {
   //     Math.pow((rec.width / 2) * scale, 2) +
   //       Math.pow((rec.length / 2) * scale, 2)
   //   );
+
+  //   svg.setBoundingVertexs2(position, pointIndex);
   //   const side2 = mathUtil.getDistance(position, svg.center);
   //   svg.scale = (side2 / side1) * scale;
-  //   svg.setBoundingVertexs();
   // }
 
-  movePoint(position, svgId, pointIndex) {
+  moveRotateSVG(position, svgId) {
     let svg = dataService.getSVG(svgId);
-    const rec = svg.getLengthWidth();
-    const scale = svg.getScale();
-    const side1 = Math.sqrt(
-      Math.pow((rec.width / 2) * scale, 2) +
-        Math.pow((rec.length / 2) * scale, 2)
+    svg.angle = mathUtil.vectorAngle(
+      svg.center,
+      svg.controlAnglePoint,
+      position
+    );
+    for (let i = 0; i < svg.points.length; ++i) {
+      svg.points[i] = svg.rotatePoint(svg.points[i], svg.center, svg.angle);
+    }
+
+    //svg.setControlAnglePoint();
+    // svg.controlAnglePoint = svg.rotatePoint(
+    //   svg.controlAnglePoint,
+    //   svg.center,
+    //   svg.angle
+    // );
+
+    let controlAnglePoint = svg.rotatePoint(
+      svg.controlAnglePoint,
+      svg.center,
+      svg.angle
     );
 
-    svg.setBoundingVertexs2(position, pointIndex);
-    const side2 = mathUtil.getDistance(position, svg.center);
-    svg.scale = (side2 / side1) * scale;
+    svg.controlAnglePoint = JSON.parse(JSON.stringify(controlAnglePoint));
+  }
+
+  movePoint(newPos, svgId, pointIndex) {
+    let svg = dataService.getSVG(svgId);
+    const preIndex = svg.getPreIndex(pointIndex);
+    const nextIndex = svg.getNextIndex(pointIndex);
+    const nextIndex2 = svg.getNextIndex(nextIndex);
+
+    const line1 = mathUtil.createLine1(
+      svg.points[nextIndex2],
+      svg.points[nextIndex]
+    );
+    const nextPoint = mathUtil.getJoinLinePoint(newPos, line1);
+
+    const line2 = mathUtil.createLine1(
+      svg.points[nextIndex2],
+      svg.points[preIndex]
+    );
+    const prePoint = mathUtil.getJoinLinePoint(newPos, line2);
+
+    if (
+      nextPoint != null &&
+      prePoint != null &&
+      mathUtil.getDistance(newPos, nextPoint) > Constant.minAdsorbPix &&
+      mathUtil.getDistance(newPos, prePoint) > Constant.minAdsorbPix &&
+      mathUtil.getDistance(newPos, svg.points[nextIndex2]) >
+        Constant.minAdsorbPix
+    ) {
+      svg.points[pointIndex] = newPos;
+
+      if (!mathUtil.isClockwise(svg.points)) {
+        svg.points[nextIndex] = nextPoint;
+        svg.points[preIndex] = prePoint;
+      } else {
+        svg.points[nextIndex] = prePoint;
+        svg.points[preIndex] = nextPoint;
+
+        svg.resetPointsIndex();
+        --pointIndex;
+        if (pointIndex < 0) {
+          pointIndex += 4;
+        }
+        return pointIndex;
+      }
+    }
+    svg.setCenter();
+    svg.setControlAnglePoint();
+    return pointIndex;
   }
 }
 

+ 6 - 7
src/graphic/Geometry/Geometry.js

@@ -1,5 +1,5 @@
-import { dataService } from '../Service/DataService';
-import { mathUtil } from '../Util/MathUtil';
+import { dataService } from "../Service/DataService";
+import { mathUtil } from "../Util/MathUtil";
 
 export default class Geometry {
   constructor() {
@@ -7,7 +7,7 @@ export default class Geometry {
   }
 
   setId(vectorId) {
-    if (vectorId == null || typeof vectorId === 'undefined') {
+    if (vectorId == null || typeof vectorId === "undefined") {
       vectorId = dataService.getCurrentId();
       dataService.updateCurrentId();
       this.vectorId = this.geoType + vectorId;
@@ -108,7 +108,6 @@ export default class Geometry {
     this.weight = weight;
   }
 
-
   getWeight() {
     return this.weight;
   }
@@ -165,13 +164,13 @@ export default class Geometry {
     var b = ptRotationCenter.y;
     var x0 = ptSrc.x;
     var y0 = ptSrc.y;
-    var rx = a + (x0 - a) * Math.cos((angle * Math.PI) / 180) - (y0 - b) * Math.sin((angle * Math.PI) / 180);
-    var ry = b + (x0 - a) * Math.sin((angle * Math.PI) / 180) + (y0 - b) * Math.cos((angle * Math.PI) / 180);
+    var rx = a + (x0 - a) * Math.cos(angle) - (y0 - b) * Math.sin(angle);
+    var ry = b + (x0 - a) * Math.sin(angle) + (y0 - b) * Math.cos(angle);
     var json = { x: rx, y: ry };
     return json;
   }
+
   setRoadWidthTipsPos(roadWidthTipsPos) {
     this.roadWidthTipsPos = roadWidthTipsPos;
   }
-  
 }

+ 97 - 22
src/graphic/Geometry/SVG.js

@@ -7,20 +7,23 @@ import VectorCategory from "../enum/VectorCategory";
 import RoadStructure from "../enum/RoadStructure";
 import SVGType from "../enum/SVGType";
 
-//const sideWidth = 10;
+const controlPointDistance = 100;
 export default class SVG extends Geometry {
   constructor(center, type, vectorId) {
     super();
     this.category = null;
     this.center = center;
-    this.points = null; //包裹的矩形的四个顶点
+    this.points = null; //包裹的矩形的四个顶点,顺时针。0-1是width,1-3是height
     this.angle = 0; //逆时针为负,顺时针为正。单位是:°
     this.type = type;
     this.geoType = VectorType.SVG;
-    this.scale = this.getScale(); //缩放比例
+    this.scaleLength = this.getScale();
+    this.scaleWidth = this.getScale();
     this.setBoundingVertexs();
+    this.controlAnglePoint = null;
+    this.setControlAnglePoint();
     this.setId(vectorId);
-    this.checkCategory(type)
+    this.checkCategory(type);
   }
 
   // createDefaultPoints() {
@@ -42,15 +45,15 @@ export default class SVG extends Geometry {
   //     y: this.center.y - sideWidth / 2,
   //   };
   // }
-  checkCategory(type){
+  checkCategory(type) {
     // this.setCategory()
-    let category = ''
-    if(RoadStructure[type]){
-      category = VectorCategory.SVG['RoadStructure']
-    }else if(SVGType[type]){
-      category = VectorCategory.SVG['SVG']
+    let category = "";
+    if (RoadStructure[type]) {
+      category = VectorCategory.SVG["RoadStructure"];
+    } else if (SVGType[type]) {
+      category = VectorCategory.SVG["SVG"];
     }
-    this.setCategory(category)
+    this.setCategory(category);
   }
   setCategory(value) {
     this.category = value;
@@ -58,8 +61,8 @@ export default class SVG extends Geometry {
   setBoundingVertexs() {
     this.points = [];
     const rec = this.getLengthWidth();
-    const length = this.scale * rec.length;
-    const width = this.scale * rec.width;
+    const length = this.scaleLength * rec.length;
+    const width = this.scaleWidth * rec.width;
 
     const minX = this.center.x - length / 2;
     const minY = this.center.y - width / 2;
@@ -107,13 +110,69 @@ export default class SVG extends Geometry {
     this.points.push(point3);
     this.points.push(point4);
   }
-  setPoints(points){
-    this.points = points
+
+  setPoints(points) {
+    this.points = points;
+  }
+
+  setCenter() {
+    this.center.x =
+      (this.points[0].x +
+        this.points[1].x +
+        this.points[2].x +
+        this.points[3].x) /
+      4;
+    this.center.y =
+      (this.points[0].y +
+        this.points[1].y +
+        this.points[2].y +
+        this.points[3].y) /
+      4;
   }
-  setScale(scale) {
-    this.scale = scale
+
+  setControlAnglePoint() {
+    // const len =
+    //   mathUtil.getDistance(this.points[0], this.points[2]) / 2 +
+    //   20 * coordinate.ratio;
+    // const v = {
+    //   x: Math.sin(this.angle),
+    //   y: Math.cos(this.angle),
+    // };
+    // console.log("svg角度:" + this.angle);
+    // this.controlAnglePoint = {
+    //   x: this.center.x + v.x * len,
+    //   y: this.center.y + v.y * len,
+    // };
+    const distance = controlPointDistance * coordinate.ratio;
+    const line = mathUtil.createLine1(this.points[0], this.points[1]);
+    const lines = mathUtil.getParallelLineForDistance(line, distance);
+    const dis1 = mathUtil.getDisForPoinLine(this.center, lines.line1);
+    const dis2 = mathUtil.getDisForPoinLine(this.center, lines.line2);
+    if (dis1 > dis2) {
+      this.controlAnglePoint = mathUtil.getJoinLinePoint(
+        this.center,
+        lines.line1
+      );
+    } else {
+      this.controlAnglePoint = mathUtil.getJoinLinePoint(
+        this.center,
+        lines.line2
+      );
+    }
   }
 
+  // setLengthScale(scale1) {
+  //   this.scaleLength = scale1;
+  // }
+
+  // setWidthScale(scale2) {
+  //   this.scaleWidth = scale2;
+  // }
+
+  //不同图例,缩放比不一样
+  getScale() {
+    return 1;
+  }
 
   setBoundingVertexs2(position, pointIndex) {
     if (mathUtil.getDistance(position, this.center) < Constant.minAdsorbPix) {
@@ -129,6 +188,14 @@ export default class SVG extends Geometry {
     this.points[nextIndex] = this.rotatePoint(position, this.center, 270);
   }
 
+  getPreIndex(index) {
+    let preIndex = index - 1;
+    if (preIndex < 0) {
+      preIndex = preIndex + 4;
+    }
+    return preIndex;
+  }
+
   getNextIndex(index) {
     let nextIndex = index + 1;
     if (nextIndex > 3) {
@@ -137,15 +204,23 @@ export default class SVG extends Geometry {
     return nextIndex;
   }
 
-  //不同图例,缩放比不一样
-  getScale() {
-    return 1;
-  }
-
   getLengthWidth() {
     return {
       length: 100,
       width: 100,
     };
   }
+
+  //变更顺序
+  resetPointsIndex() {
+    const point0 = JSON.parse(JSON.stringify(this.points[1]));
+    const point1 = JSON.parse(JSON.stringify(this.points[2]));
+    const point2 = JSON.parse(JSON.stringify(this.points[3]));
+    const point3 = JSON.parse(JSON.stringify(this.points[0]));
+
+    this.points[0] = point0;
+    this.points[1] = point1;
+    this.points[2] = point2;
+    this.points[3] = point3;
+  }
 }

+ 3 - 1
src/graphic/Layer.js

@@ -1047,8 +1047,10 @@ export default class Layer {
         if (draggingItem != null) {
           if (draggingItem.state == -1) {
             moveSVG.moveFullSVG(position, draggingItem.vectorId);
+          } else if (draggingItem.state == 100) {
+            moveSVG.moveRotateSVG(position, draggingItem.vectorId);
           } else {
-            moveSVG.movePoint(
+            draggingItem.state = moveSVG.movePoint(
               position,
               draggingItem.vectorId,
               draggingItem.state

+ 421 - 149
src/graphic/ListenLayer.js

@@ -64,18 +64,37 @@ export default class ListenLayer {
     }
     this.clear();
     if (!vType || vType == VectorType.CurveRoad) {
-      selectInfo.curveRoadEdgeInfo = this.isSelectCurveRoad(position, exceptVectorIds.exceptCurveRoadId); //包括edge
-      selectInfo.curveRoadPointInfo = this.isSelectCurveRoadPoint(position, exceptVectorIds.exceptCurveRoadPointId);
+      selectInfo.curveRoadEdgeInfo = this.isSelectCurveRoad(
+        position,
+        exceptVectorIds.exceptCurveRoadId
+      ); //包括edge
+      selectInfo.curveRoadPointInfo = this.isSelectCurveRoadPoint(
+        position,
+        exceptVectorIds.exceptCurveRoadPointId
+      );
     }
 
     if (!vType || vType == VectorType.Road) {
-      selectInfo.roadEdgeInfo = this.isSelectRoad(position, exceptVectorIds.exceptRoadIds); //包括edge
-      selectInfo.roadPointInfo = this.isSelectRoadPoint(position, exceptVectorIds.exceptRoadPointId);
+      selectInfo.roadEdgeInfo = this.isSelectRoad(
+        position,
+        exceptVectorIds.exceptRoadIds
+      ); //包括edge
+      selectInfo.roadPointInfo = this.isSelectRoadPoint(
+        position,
+        exceptVectorIds.exceptRoadPointId
+      );
     }
 
     if (!vType || vType == VectorType.Line) {
-      selectInfo.lineInfo = this.isSelectLine(position, exceptVectorIds.exceptLineIds);
-      selectInfo.pointInfo = this.isSelectPoint(position, exceptVectorIds.exceptPointId, exceptVectorIds.exceptLineIds);
+      selectInfo.lineInfo = this.isSelectLine(
+        position,
+        exceptVectorIds.exceptLineIds
+      );
+      selectInfo.pointInfo = this.isSelectPoint(
+        position,
+        exceptVectorIds.exceptPointId,
+        exceptVectorIds.exceptLineIds
+      );
     }
     // selectInfo.pointInfo = this.isSelectPoint(
     //   position,
@@ -83,23 +102,44 @@ export default class ListenLayer {
     // );
 
     if (!vType || vType == VectorType.CurveLine) {
-      selectInfo.curvePointInfo = this.isSelectCurvePoint(position, exceptVectorIds.exceptCurvePointId);
-      selectInfo.curveLineInfo = this.isSelectCurveLine(position, exceptVectorIds.exceptCurveLineId);
+      selectInfo.curvePointInfo = this.isSelectCurvePoint(
+        position,
+        exceptVectorIds.exceptCurvePointId
+      );
+      selectInfo.curveLineInfo = this.isSelectCurveLine(
+        position,
+        exceptVectorIds.exceptCurveLineId
+      );
     }
 
     //if (!vType || vType == VectorType.Circle) {
-    selectInfo.circleInfo = this.isSelectCircle(position, exceptVectorIds.exceptCircleId);
+    selectInfo.circleInfo = this.isSelectCircle(
+      position,
+      exceptVectorIds.exceptCircleId
+    );
     //}
 
     //if (!vType) {
     //交叉口拐弯处的控制点
-    selectInfo.crossPointInfo = this.isSelectCrossCrossPoint(position, exceptVectorIds.exceptCrossCrossPointId);
-    selectInfo.textInfo = this.isSelectText(position, exceptVectorIds.exceptTextId);
-    selectInfo.magnifierInfo = this.isSelectMagnifier(position, exceptVectorIds.exceptMagnifierId);
+    selectInfo.crossPointInfo = this.isSelectCrossCrossPoint(
+      position,
+      exceptVectorIds.exceptCrossCrossPointId
+    );
+    selectInfo.textInfo = this.isSelectText(
+      position,
+      exceptVectorIds.exceptTextId
+    );
+    selectInfo.magnifierInfo = this.isSelectMagnifier(
+      position,
+      exceptVectorIds.exceptMagnifierId
+    );
     //
 
     if (!vType || vType == VectorType.SVG) {
-      selectInfo.svgInfo = this.isSelectSVG(position, exceptVectorIds.exceptSVGId);
+      selectInfo.svgInfo = this.isSelectSVG(
+        position,
+        exceptVectorIds.exceptSVGId
+      );
     }
 
     this.setModifyPoint(position, selectInfo);
@@ -139,11 +179,19 @@ export default class ListenLayer {
           }
         }
       } else {
-        if ((Math.abs(position.x - curvePoint.x) * coordinate.zoom) / coordinate.defaultZoom < Constant.minAdsorbPix) {
+        if (
+          (Math.abs(position.x - curvePoint.x) * coordinate.zoom) /
+            coordinate.defaultZoom <
+          Constant.minAdsorbPix
+        ) {
           seqInfo.linkedCurvePointIdX = curvePointId;
           seqInfo.x = curvePoint.x;
         }
-        if ((Math.abs(position.y - curvePoint.y) * coordinate.zoom) / coordinate.defaultZoom < Constant.minAdsorbPix) {
+        if (
+          (Math.abs(position.y - curvePoint.y) * coordinate.zoom) /
+            coordinate.defaultZoom <
+          Constant.minAdsorbPix
+        ) {
           seqInfo.linkedPointIdY = curvePointId;
           seqInfo.y = curvePoint.y;
         }
@@ -152,7 +200,9 @@ export default class ListenLayer {
 
     if (curvePointInfo.curvePointId) {
       curvePointInfo.linkedCurvePointId = curvePointInfo.curvePointId;
-      const linkedCurvePoint = dataService.getCurvePoint(curvePointInfo.curvePointId);
+      const linkedCurvePoint = dataService.getCurvePoint(
+        curvePointInfo.curvePointId
+      );
       curvePointInfo.x = linkedCurvePoint.x;
       curvePointInfo.y = linkedCurvePoint.y;
     } else {
@@ -164,10 +214,16 @@ export default class ListenLayer {
         curvePointInfo.linkedCurvePointIdY = seqInfo.linkedCurvePointIdY;
         curvePointInfo.y = seqInfo.y;
       }
-      if (curvePointInfo.hasOwnProperty("y") && !curvePointInfo.hasOwnProperty("x")) {
+      if (
+        curvePointInfo.hasOwnProperty("y") &&
+        !curvePointInfo.hasOwnProperty("x")
+      ) {
         curvePointInfo.x = position.x;
       }
-      if (curvePointInfo.hasOwnProperty("x") && !curvePointInfo.hasOwnProperty("y")) {
+      if (
+        curvePointInfo.hasOwnProperty("x") &&
+        !curvePointInfo.hasOwnProperty("y")
+      ) {
         curvePointInfo.y = position.y;
       }
     }
@@ -182,12 +238,20 @@ export default class ListenLayer {
     };
     const curveLines = dataService.getCurveLines();
     for (const curveLineId in curveLines) {
-      if (exceptCurveLineIds && (exceptCurveLineIds.hasOwnProperty(curveLineId) || exceptCurveLineIds == curveLineId)) {
+      if (
+        exceptCurveLineIds &&
+        (exceptCurveLineIds.hasOwnProperty(curveLineId) ||
+          exceptCurveLineIds == curveLineId)
+      ) {
         continue;
       }
       const curveLine = dataService.getCurveLine(curveLineId);
 
-      let joinInfo = this.distanceForBezier(position, curveLine.curves, Constant.minAdsorbPix);
+      let joinInfo = this.distanceForBezier(
+        position,
+        curveLine.curves,
+        Constant.minAdsorbPix
+      );
       //选中了路
       if (joinInfo.distance < Constant.minAdsorbPix) {
         curveLineInfo = {
@@ -251,11 +315,19 @@ export default class ListenLayer {
           }
         }
       } else {
-        if ((Math.abs(position.x - point.x) * coordinate.zoom) / coordinate.defaultZoom < Constant.minAdsorbPix) {
+        if (
+          (Math.abs(position.x - point.x) * coordinate.zoom) /
+            coordinate.defaultZoom <
+          Constant.minAdsorbPix
+        ) {
           seqInfo.linkedPointIdX = pointId;
           seqInfo.x = point.x;
         }
-        if ((Math.abs(position.y - point.y) * coordinate.zoom) / coordinate.defaultZoom < Constant.minAdsorbPix) {
+        if (
+          (Math.abs(position.y - point.y) * coordinate.zoom) /
+            coordinate.defaultZoom <
+          Constant.minAdsorbPix
+        ) {
           seqInfo.linkedPointIdY = pointId;
           seqInfo.y = point.y;
         }
@@ -308,7 +380,8 @@ export default class ListenLayer {
         line.getCategory() == VectorCategory.Line.ExtendedPositionLine ||
         line.getCategory() == VectorCategory.Line.GuideLocationLine ||
         line.getCategory() == VectorCategory.Line.GuidePositionLine ||
-        (line.getCategory() == VectorCategory.Line.PositionLine && line.getLocationMode() != Constant.angleLocationMode)
+        (line.getCategory() == VectorCategory.Line.PositionLine &&
+          line.getLocationMode() != Constant.angleLocationMode)
       ) {
         continue;
       }
@@ -386,7 +459,12 @@ export default class ListenLayer {
       //     };
       //   }
       // }
-      const flag = mathUtil.isPointInElliptic(position, circle.center, circle.radiusX, circle.radiusY);
+      const flag = mathUtil.isPointInElliptic(
+        position,
+        circle.center,
+        circle.radiusX,
+        circle.radiusY
+      );
       if (flag) {
         circleInfo = {
           circleId: circleId,
@@ -433,10 +511,18 @@ export default class ListenLayer {
           }
         }
       } else {
-        if ((Math.abs(position.x - roadPoint.x) * coordinate.zoom) / coordinate.defaultZoom < Constant.minAdsorbPix) {
+        if (
+          (Math.abs(position.x - roadPoint.x) * coordinate.zoom) /
+            coordinate.defaultZoom <
+          Constant.minAdsorbPix
+        ) {
           seqInfo.linkedRoadPointIdX = roadPointId;
           seqInfo.x = roadPoint.x;
-        } else if ((Math.abs(position.y - roadPoint.y) * coordinate.zoom) / coordinate.defaultZoom < Constant.minAdsorbPix) {
+        } else if (
+          (Math.abs(position.y - roadPoint.y) * coordinate.zoom) /
+            coordinate.defaultZoom <
+          Constant.minAdsorbPix
+        ) {
           seqInfo.linkedRoadPointIdY = roadPointId;
           seqInfo.y = roadPoint.y;
         }
@@ -459,10 +545,16 @@ export default class ListenLayer {
         roadPointInfo.y = seqInfo.y;
       }
 
-      if (roadPointInfo.hasOwnProperty("y") && !roadPointInfo.hasOwnProperty("x")) {
+      if (
+        roadPointInfo.hasOwnProperty("y") &&
+        !roadPointInfo.hasOwnProperty("x")
+      ) {
         roadPointInfo.x = position.x;
       }
-      if (roadPointInfo.hasOwnProperty("x") && !roadPointInfo.hasOwnProperty("y")) {
+      if (
+        roadPointInfo.hasOwnProperty("x") &&
+        !roadPointInfo.hasOwnProperty("y")
+      ) {
         roadPointInfo.y = position.y;
       }
     }
@@ -502,10 +594,18 @@ export default class ListenLayer {
           }
         }
       } else {
-        if ((Math.abs(position.x - curveRoadPoint.x) * coordinate.zoom) / coordinate.defaultZoom < Constant.minAdsorbPix) {
+        if (
+          (Math.abs(position.x - curveRoadPoint.x) * coordinate.zoom) /
+            coordinate.defaultZoom <
+          Constant.minAdsorbPix
+        ) {
           seqInfo.linkedCurveRoadPointIdX = curveRoadPointId;
           seqInfo.x = curveRoadPoint.x;
-        } else if ((Math.abs(position.y - curveRoadPoint.y) * coordinate.zoom) / coordinate.defaultZoom < Constant.minAdsorbPix) {
+        } else if (
+          (Math.abs(position.y - curveRoadPoint.y) * coordinate.zoom) /
+            coordinate.defaultZoom <
+          Constant.minAdsorbPix
+        ) {
           seqInfo.linkedCurveRoadPointIdY = curveRoadPointId;
           seqInfo.y = curveRoadPoint.y;
         }
@@ -513,22 +613,33 @@ export default class ListenLayer {
     }
 
     if (curveRoadPointInfo.curveRoadPointId) {
-      curveRoadPointInfo.linkedCurveRoadPointId = curveRoadPointInfo.curveRoadPointId;
-      const linkedCurvePoint = dataService.getCurveRoadPoint(curveRoadPointInfo.curveRoadPointId);
+      curveRoadPointInfo.linkedCurveRoadPointId =
+        curveRoadPointInfo.curveRoadPointId;
+      const linkedCurvePoint = dataService.getCurveRoadPoint(
+        curveRoadPointInfo.curveRoadPointId
+      );
       curveRoadPointInfo.x = linkedCurvePoint.x;
       curveRoadPointInfo.y = linkedCurvePoint.y;
     } else {
       if (seqInfo.hasOwnProperty("linkedCurveRoadPointIdX")) {
-        curveRoadPointInfo.linkedCurveRoadPointIdX = seqInfo.linkedCurveRoadPointIdX;
+        curveRoadPointInfo.linkedCurveRoadPointIdX =
+          seqInfo.linkedCurveRoadPointIdX;
         curveRoadPointInfo.x = seqInfo.x;
       } else if (seqInfo.hasOwnProperty("linkedCurveRoadPointIdY")) {
-        curveRoadPointInfo.linkedCurveRoadPointIdY = seqInfo.linkedCurveRoadPointIdY;
+        curveRoadPointInfo.linkedCurveRoadPointIdY =
+          seqInfo.linkedCurveRoadPointIdY;
         curveRoadPointInfo.y = seqInfo.y;
       }
-      if (curveRoadPointInfo.hasOwnProperty("y") && !curveRoadPointInfo.hasOwnProperty("x")) {
+      if (
+        curveRoadPointInfo.hasOwnProperty("y") &&
+        !curveRoadPointInfo.hasOwnProperty("x")
+      ) {
         curveRoadPointInfo.x = position.x;
       }
-      if (curveRoadPointInfo.hasOwnProperty("x") && !curveRoadPointInfo.hasOwnProperty("y")) {
+      if (
+        curveRoadPointInfo.hasOwnProperty("x") &&
+        !curveRoadPointInfo.hasOwnProperty("y")
+      ) {
         curveRoadPointInfo.y = position.y;
       }
     }
@@ -565,13 +676,25 @@ export default class ListenLayer {
       let rightLine = mathUtil.createLine1(rightEdge.start, rightEdge.end);
       let rightJoin = mathUtil.getJoinLinePoint(position, rightLine);
 
-      let leftSideLine = leftEdge.roadSide ? mathUtil.createLine1(leftEdge.roadSide.start, leftEdge.roadSide.end) : null;
-      let leftSideJoin = leftSideLine ? mathUtil.getJoinLinePoint(position, leftSideLine) : null;
-
-      let rightSideLine = rightEdge.roadSide ? mathUtil.createLine1(rightEdge.roadSide.start, rightEdge.roadSide.end) : null;
-      let rightSideJoin = rightSideLine ? mathUtil.getJoinLinePoint(position, rightSideLine) : null;
+      let leftSideLine = leftEdge.roadSide
+        ? mathUtil.createLine1(leftEdge.roadSide.start, leftEdge.roadSide.end)
+        : null;
+      let leftSideJoin = leftSideLine
+        ? mathUtil.getJoinLinePoint(position, leftSideLine)
+        : null;
+
+      let rightSideLine = rightEdge.roadSide
+        ? mathUtil.createLine1(rightEdge.roadSide.start, rightEdge.roadSide.end)
+        : null;
+      let rightSideJoin = rightSideLine
+        ? mathUtil.getJoinLinePoint(position, rightSideLine)
+        : null;
       let distance = this.getDistance(position, join);
-      if (mathUtil.isContainForSegment(join, startPoint, endPoint) && (mathUtil.isContainForSegment(position, join, leftJoin) || mathUtil.isContainForSegment(position, join, rightJoin))) {
+      if (
+        mathUtil.isContainForSegment(join, startPoint, endPoint) &&
+        (mathUtil.isContainForSegment(position, join, leftJoin) ||
+          mathUtil.isContainForSegment(position, join, rightJoin))
+      ) {
         if (!roadInfo.roadId || distance < roadInfo.distance) {
           roadInfo = {
             roadId: roadId,
@@ -603,8 +726,11 @@ export default class ListenLayer {
 
       distance = this.getDistance(position, leftJoin);
       if (
-        (mathUtil.isContainForSegment(leftJoin, leftEdge.start, leftEdge.end) && distance < Constant.minAdsorbPix / 2) ||
-        (mathUtil.isContainForSegment(join, startPoint, endPoint) && leftSideJoin && mathUtil.isContainForSegment(position, leftSideJoin, leftJoin))
+        (mathUtil.isContainForSegment(leftJoin, leftEdge.start, leftEdge.end) &&
+          distance < Constant.minAdsorbPix / 2) ||
+        (mathUtil.isContainForSegment(join, startPoint, endPoint) &&
+          leftSideJoin &&
+          mathUtil.isContainForSegment(position, leftSideJoin, leftJoin))
       ) {
         if (!edgeInfo.edgeId || distance < edgeInfo.distance) {
           edgeInfo = {
@@ -619,8 +745,15 @@ export default class ListenLayer {
       distance = this.getDistance(position, rightJoin);
 
       if (
-        (mathUtil.isContainForSegment(rightJoin, rightEdge.start, rightEdge.end) && distance < Constant.minAdsorbPix / 2) ||
-        (mathUtil.isContainForSegment(join, startPoint, endPoint) && rightSideJoin && mathUtil.isContainForSegment(position, rightSideJoin, rightJoin))
+        (mathUtil.isContainForSegment(
+          rightJoin,
+          rightEdge.start,
+          rightEdge.end
+        ) &&
+          distance < Constant.minAdsorbPix / 2) ||
+        (mathUtil.isContainForSegment(join, startPoint, endPoint) &&
+          rightSideJoin &&
+          mathUtil.isContainForSegment(position, rightSideJoin, rightJoin))
       ) {
         if (!edgeInfo.edgeId || distance < edgeInfo.distance) {
           edgeInfo = {
@@ -633,10 +766,16 @@ export default class ListenLayer {
       }
     }
 
-    if (roadInfo.roadId && (!edgeInfo.edgeId || roadInfo.distance < edgeInfo.distance)) {
+    if (
+      roadInfo.roadId &&
+      (!edgeInfo.edgeId || roadInfo.distance < edgeInfo.distance)
+    ) {
       const linkedRoad = dataService.getRoad(roadInfo.roadId);
       const linkedRoadLine = roadService.getMidLine(linkedRoad);
-      const linkedPosition = mathUtil.getJoinLinePoint(position, linkedRoadLine);
+      const linkedPosition = mathUtil.getJoinLinePoint(
+        position,
+        linkedRoadLine
+      );
 
       roadInfo.x = linkedPosition.x;
       roadInfo.y = linkedPosition.y;
@@ -700,14 +839,33 @@ export default class ListenLayer {
       console.log("isSelectCurveRoad:" + JSON.stringify(joinInfo));
       //检查edge
       const leftCurveEdge = dataService.getCurveRoadEdge(curveRoad.leftEdgeId);
-      const leftJoinInfo = this.distanceForBezier(position, leftCurveEdge.curves, Constant.minAdsorbPix);
+      const leftJoinInfo = this.distanceForBezier(
+        position,
+        leftCurveEdge.curves,
+        Constant.minAdsorbPix
+      );
 
-      const rightCurveEdge = dataService.getCurveRoadEdge(curveRoad.rightEdgeId);
-      const rightJoinInfo = this.distanceForBezier(position, rightCurveEdge.curves, Constant.minAdsorbPix);
+      const rightCurveEdge = dataService.getCurveRoadEdge(
+        curveRoad.rightEdgeId
+      );
+      const rightJoinInfo = this.distanceForBezier(
+        position,
+        rightCurveEdge.curves,
+        Constant.minAdsorbPix
+      );
 
-      let line1 = mathUtil.createLine1(joinInfo.position, leftJoinInfo.position);
+      let line1 = mathUtil.createLine1(
+        joinInfo.position,
+        leftJoinInfo.position
+      );
       let position1 = mathUtil.getJoinLinePoint(position, line1);
-      if (mathUtil.isContainForSegment(position1, joinInfo.position, leftJoinInfo.position)) {
+      if (
+        mathUtil.isContainForSegment(
+          position1,
+          joinInfo.position,
+          leftJoinInfo.position
+        )
+      ) {
         if (joinInfo.distance < curveRoad.leftWidth) {
           curveRoadInfo = {
             curveRoadId: curveRoadId,
@@ -719,10 +877,19 @@ export default class ListenLayer {
         }
         curveRoadInfo.dir = "left";
       } else {
-        let line2 = mathUtil.createLine1(joinInfo.position, rightJoinInfo.position);
+        let line2 = mathUtil.createLine1(
+          joinInfo.position,
+          rightJoinInfo.position
+        );
 
         let position2 = mathUtil.getJoinLinePoint(position, line2);
-        if (mathUtil.isContainForSegment(position2, joinInfo.position, rightJoinInfo.position)) {
+        if (
+          mathUtil.isContainForSegment(
+            position2,
+            joinInfo.position,
+            rightJoinInfo.position
+          )
+        ) {
           if (joinInfo.distance < curveRoad.rightWidth) {
             curveRoadInfo = {
               curveRoadId: curveRoadId,
@@ -737,7 +904,10 @@ export default class ListenLayer {
       }
 
       if (leftJoinInfo.distance < Constant.minAdsorbPix) {
-        const index = mathUtil.getCurvesIndexForCurvesPoints(leftJoinInfo.position, curveRoad.points);
+        const index = mathUtil.getCurvesIndexForCurvesPoints(
+          leftJoinInfo.position,
+          curveRoad.points
+        );
         curveEdgeInfo = {
           curveEdgeId: curveRoad.leftEdgeId,
           type: VectorType.CurveRoadEdge,
@@ -747,7 +917,10 @@ export default class ListenLayer {
           y: leftJoinInfo.position.y,
         };
       } else if (rightJoinInfo.distance < Constant.minAdsorbPix) {
-        const index = mathUtil.getCurvesIndexForCurvesPoints(rightJoinInfo.position, curveRoad.points);
+        const index = mathUtil.getCurvesIndexForCurvesPoints(
+          rightJoinInfo.position,
+          curveRoad.points
+        );
         curveEdgeInfo = {
           curveEdgeId: curveRoad.rightEdgeId,
           type: VectorType.CurveRoadEdge,
@@ -758,7 +931,11 @@ export default class ListenLayer {
         };
       }
     }
-    if (curveRoadInfo.curveRoadId && (!curveEdgeInfo.curveEdgeId || curveRoadInfo.distance < curveEdgeInfo.distance)) {
+    if (
+      curveRoadInfo.curveRoadId &&
+      (!curveEdgeInfo.curveEdgeId ||
+        curveRoadInfo.distance < curveEdgeInfo.distance)
+    ) {
       // console.log("选中的CurveRoad:" + curveRoadInfo.curveRoadId);
       return curveRoadInfo;
     } else if (curveEdgeInfo.curveEdgeId) {
@@ -843,46 +1020,60 @@ export default class ListenLayer {
     };
     const svgs = dataService.getSVGs();
 
-    /**-----暴力做法 */
+    // /**-----暴力做法 */
+    // for (const svgId in svgs) {
+    //   if (svgId == exceptSVGId) {
+    //     continue;
+    //   }
+    //   const svg = dataService.getSVG(svgId);
+    //   for (let i = 0; i < svg.points.length; ++i) {
+    //     let distance = this.getDistance(position, svg.points[i]);
+    //     // if (!svgInfo.svgId && distance < Constant.minAdsorbPix / 5) { //改大图例四个点的选择范围
+    //     if (!svgInfo.svgId && distance < Constant.minAdsorbPix / 2) {
+    //       svgInfo = {
+    //         svgId: svgId,
+    //         distance: distance,
+    //         type: VectorType.SVG,
+    //         index: i,
+    //         x: position.x,
+    //         y: position.y,
+    //       };
+    //     } else if (svgInfo.svgId && distance < svgInfo.distance) {
+    //       svgInfo = {
+    //         svgId: svgId,
+    //         distance: distance,
+    //         type: VectorType.SVG,
+    //         index: i,
+    //         x: position.x,
+    //         y: position.y,
+    //       };
+    //     }
+    //   }
+    // }
+    // /**----- */
+
     for (const svgId in svgs) {
       if (svgId == exceptSVGId) {
         continue;
       }
       const svg = dataService.getSVG(svgId);
-      for (let i = 0; i < svg.points.length; ++i) {
-        let distance = this.getDistance(position, svg.points[i]);
-        // if (!svgInfo.svgId && distance < Constant.minAdsorbPix / 5) { //改大图例四个点的选择范围
-        if (!svgInfo.svgId && distance < Constant.minAdsorbPix / 2) {
-          svgInfo = {
-            svgId: svgId,
-            distance: distance,
-            type: VectorType.SVG,
-            index: i,
-            x: position.x,
-            y: position.y,
-          };
-        } else if (svgInfo.svgId && distance < svgInfo.distance) {
-          svgInfo = {
-            svgId: svgId,
-            distance: distance,
-            type: VectorType.SVG,
-            index: i,
-            x: position.x,
-            y: position.y,
-          };
-        }
-      }
-    }
-    /**----- */
+      // let centerPoint = mathUtil.calculateCenterPoint(svg.points);
 
-    for (const svgId in svgs) {
-      if (svgId == exceptSVGId) {
-        continue;
+      let newDistance = this.getDistance(position, svg.center);
+      if (
+        this.getDistance(position, svg.controlAnglePoint) <
+        Constant.minAdsorbPix / 2
+      ) {
+        svgInfo = {
+          svgId: svgId,
+          type: VectorType.SVG,
+          index: 100, //表示选中旋转控制点
+          x: position.x,
+          y: position.y,
+        };
+        return svgInfo;
       }
-      const svg = dataService.getSVG(svgId);
-      let centerPoint = mathUtil.calculateCenterPoint(svg.points);
 
-      let newDistance = this.getDistance(position, centerPoint);
       for (let i = 0; i < svg.points.length; ++i) {
         let distance = this.getDistance(position, svg.points[i]);
 
@@ -909,9 +1100,6 @@ export default class ListenLayer {
           };
         }
       }
-      // if (svgInfo.svgId) {
-      //   return svgInfo;
-      // }
 
       let flag = mathUtil.isPointInPoly(position, svg.points);
       if (flag && !svgInfo.svgId) {
@@ -933,28 +1121,6 @@ export default class ListenLayer {
           newDistance: newDistance,
         };
       }
-
-      // if (!svgInfo.svgId && newDistance < Constant.minAdsorbPix / 2) {
-      //   svgInfo = {
-      //     svgId: svgId,
-      //     type: VectorType.SVG,
-      //     x: position.x,
-      //     y: position.y,
-      //     index: -1,
-      //     newDistance: newDistance,
-      //   };
-      //   break;
-      // } else if (svgInfo.svgId && newDistance < svgInfo.newDistance) {
-      //   svgInfo = {
-      //     svgId: svgId,
-      //     type: VectorType.SVG,
-      //     x: position.x,
-      //     y: position.y,
-      //     index: -1,
-      //     newDistance: newDistance,
-      //   };
-      //   break;
-      // }
     }
 
     return svgInfo;
@@ -1038,7 +1204,10 @@ export default class ListenLayer {
       this.modifyPoint.index = info.circleInfo.index;
       this.modifyPoint.x = info.circleInfo.x;
       this.modifyPoint.y = info.circleInfo.y;
-    } else if (info && (info.pointInfo.pointId || info.curvePointInfo.curvePointId)) {
+    } else if (
+      info &&
+      (info.pointInfo.pointId || info.curvePointInfo.curvePointId)
+    ) {
       this.modifyPoint = {};
       if (info.pointInfo.pointId && info.curvePointInfo.curvePointId) {
         if (info.pointInfo.distance < info.curvePointInfo.distance) {
@@ -1046,7 +1215,8 @@ export default class ListenLayer {
           this.modifyPoint.x = info.pointInfo.x;
           this.modifyPoint.y = info.pointInfo.y;
         } else {
-          this.modifyPoint.linkedCurvePointId = info.curvePointInfo.curvePointId;
+          this.modifyPoint.linkedCurvePointId =
+            info.curvePointInfo.curvePointId;
           this.modifyPoint.x = info.curvePointInfo.x;
           this.modifyPoint.y = info.curvePointInfo.y;
         }
@@ -1059,7 +1229,10 @@ export default class ListenLayer {
         this.modifyPoint.x = info.curvePointInfo.x;
         this.modifyPoint.y = info.curvePointInfo.y;
       }
-    } else if (info && (info.lineInfo.lineId || info.curveLineInfo.curveLineId)) {
+    } else if (
+      info &&
+      (info.lineInfo.lineId || info.curveLineInfo.curveLineId)
+    ) {
       this.modifyPoint = {};
       if (info.lineInfo.lineId && info.curveLineInfo.curveLineId) {
         if (info.lineInfo.distance < info.curveLineInfo.distance) {
@@ -1086,14 +1259,22 @@ export default class ListenLayer {
       this.modifyPoint.index = info.svgInfo.index;
       this.modifyPoint.x = info.svgInfo.x;
       this.modifyPoint.y = info.svgInfo.y;
-    } else if (info && (info.roadPointInfo.roadPointId || info.curveRoadPointInfo.curveRoadPointId)) {
-      if (info.roadPointInfo.roadPointId && info.curveRoadPointInfo.curveRoadPointId) {
+    } else if (
+      info &&
+      (info.roadPointInfo.roadPointId ||
+        info.curveRoadPointInfo.curveRoadPointId)
+    ) {
+      if (
+        info.roadPointInfo.roadPointId &&
+        info.curveRoadPointInfo.curveRoadPointId
+      ) {
         if (info.roadPointInfo.distance < info.curveRoadPointInfo.distance) {
           this.modifyPoint.linkedRoadPointId = info.roadPointInfo.roadPointId;
           this.modifyPoint.x = info.roadPointInfo.x;
           this.modifyPoint.y = info.roadPointInfo.y;
         } else {
-          this.modifyPoint.linkedCurveRoadPointId = info.curveRoadPointInfo.curveRoadPointId;
+          this.modifyPoint.linkedCurveRoadPointId =
+            info.curveRoadPointInfo.curveRoadPointId;
           this.modifyPoint.x = info.curveRoadPointInfo.x;
           this.modifyPoint.y = info.curveRoadPointInfo.y;
         }
@@ -1102,11 +1283,15 @@ export default class ListenLayer {
         this.modifyPoint.x = info.roadPointInfo.x;
         this.modifyPoint.y = info.roadPointInfo.y;
       } else if (info.curveRoadPointInfo.curveRoadPointId) {
-        this.modifyPoint.linkedCurveRoadPointId = info.curveRoadPointInfo.curveRoadPointId;
+        this.modifyPoint.linkedCurveRoadPointId =
+          info.curveRoadPointInfo.curveRoadPointId;
         this.modifyPoint.x = info.curveRoadPointInfo.x;
         this.modifyPoint.y = info.curveRoadPointInfo.y;
       }
-    } else if (info && (info.roadEdgeInfo.roadId || info.curveRoadEdgeInfo.curveRoadId)) {
+    } else if (
+      info &&
+      (info.roadEdgeInfo.roadId || info.curveRoadEdgeInfo.curveRoadId)
+    ) {
       this.modifyPoint = {};
       if (info.roadEdgeInfo.roadId && info.curveRoadEdgeInfo.curveRoadId) {
         if (roadEdgeInfo.distance < info.curveRoadEdgeInfo.distance) {
@@ -1131,7 +1316,10 @@ export default class ListenLayer {
         this.modifyPoint.y = info.curveRoadEdgeInfo.y;
         this.modifyPoint.dir = info.curveRoadEdgeInfo.dir;
       }
-    } else if (info && (info.roadEdgeInfo.edgeId || info.curveRoadEdgeInfo.curveEdgeId)) {
+    } else if (
+      info &&
+      (info.roadEdgeInfo.edgeId || info.curveRoadEdgeInfo.curveEdgeId)
+    ) {
       this.modifyPoint = {};
       if (info.roadEdgeInfo.edgeId && info.curveRoadEdgeInfo.curveEdgeId) {
         if (info.roadEdgeInfo.distance < info.curveRoadEdgeInfo.distance) {
@@ -1139,7 +1327,8 @@ export default class ListenLayer {
           this.modifyPoint.x = info.roadEdgeInfo.x;
           this.modifyPoint.y = info.roadEdgeInfo.y;
         } else {
-          this.modifyPoint.linkedCurveEdgeId = info.curveRoadEdgeInfo.curveEdgeId;
+          this.modifyPoint.linkedCurveEdgeId =
+            info.curveRoadEdgeInfo.curveEdgeId;
           this.modifyPoint.selectIndex = info.curveRoadEdgeInfo.selectIndex;
           this.modifyPoint.x = info.curveRoadEdgeInfo.x;
           this.modifyPoint.y = info.curveRoadEdgeInfo.y;
@@ -1156,40 +1345,57 @@ export default class ListenLayer {
       }
     } else if (info && info.crossPointInfo.crossCrossPointId) {
       this.modifyPoint = {};
-      this.modifyPoint.linkedCrossCrossPointId = info.crossPointInfo.crossCrossPointId;
+      this.modifyPoint.linkedCrossCrossPointId =
+        info.crossPointInfo.crossCrossPointId;
       this.modifyPoint.x = info.crossPointInfo.x;
       this.modifyPoint.y = info.crossPointInfo.y;
     } else if (info && info.roadPointInfo.linkedRoadPointIdX) {
       this.modifyPoint = {};
-      this.modifyPoint.linkedRoadPointIdX = info.roadPointInfo.linkedRoadPointIdX;
+      this.modifyPoint.linkedRoadPointIdX =
+        info.roadPointInfo.linkedRoadPointIdX;
       this.modifyPoint.x = info.roadPointInfo.x;
       this.modifyPoint.y = info.roadPointInfo.y;
     } else if (info && info.roadPointInfo.linkedRoadPointIdY) {
       this.modifyPoint = {};
-      this.modifyPoint.linkedRoadPointIdY = info.roadPointInfo.linkedRoadPointIdY;
+      this.modifyPoint.linkedRoadPointIdY =
+        info.roadPointInfo.linkedRoadPointIdY;
       this.modifyPoint.y = info.roadPointInfo.y;
       this.modifyPoint.x = info.roadPointInfo.x;
     } else if (info && info.curvePointInfo.linkedRoadPointIdX) {
       this.modifyPoint = {};
-      this.modifyPoint.linkedRoadPointIdX = info.curvePointInfo.linkedRoadPointIdX;
+      this.modifyPoint.linkedRoadPointIdX =
+        info.curvePointInfo.linkedRoadPointIdX;
       this.modifyPoint.x = info.curvePointInfo.x;
       this.modifyPoint.y = position.y;
     } else if (info && info.curvePointInfo.linkedRoadPointIdY) {
       this.modifyPoint = {};
-      this.modifyPoint.linkedRoadPointIdY = info.curvePointInfo.linkedRoadPointIdY;
+      this.modifyPoint.linkedRoadPointIdY =
+        info.curvePointInfo.linkedRoadPointIdY;
       this.modifyPoint.y = info.curvePointInfo.y;
       this.modifyPoint.x = position.x;
-    } else if (info && info.pointInfo.linkedPointIdX && !info.pointInfo.linkedPointIdY) {
+    } else if (
+      info &&
+      info.pointInfo.linkedPointIdX &&
+      !info.pointInfo.linkedPointIdY
+    ) {
       this.modifyPoint = {};
       this.modifyPoint.linkedPointIdX = info.pointInfo.linkedPointIdX;
       this.modifyPoint.x = info.pointInfo.x;
       this.modifyPoint.y = info.pointInfo.y;
-    } else if (info && info.pointInfo.linkedPointIdY && !info.pointInfo.linkedPointIdX) {
+    } else if (
+      info &&
+      info.pointInfo.linkedPointIdY &&
+      !info.pointInfo.linkedPointIdX
+    ) {
       this.modifyPoint = {};
       this.modifyPoint.linkedPointIdY = info.pointInfo.linkedPointIdY;
       this.modifyPoint.y = info.pointInfo.y;
       this.modifyPoint.x = info.pointInfo.x;
-    } else if (info && info.pointInfo.linkedPointIdY && info.pointInfo.linkedPointIdX) {
+    } else if (
+      info &&
+      info.pointInfo.linkedPointIdY &&
+      info.pointInfo.linkedPointIdX
+    ) {
       this.modifyPoint = {};
       this.modifyPoint.linkedPointIdX = info.pointInfo.linkedPointIdX;
       this.modifyPoint.linkedPointIdY = info.pointInfo.linkedPointIdY;
@@ -1210,40 +1416,103 @@ export default class ListenLayer {
         return false;
       }
     } else if (this.modifyPoint.linkedRoadPointId) {
-      stateService.setSelectItem(this.modifyPoint.linkedRoadPointId, VectorType.RoadPoint, SelectState.Select);
+      stateService.setSelectItem(
+        this.modifyPoint.linkedRoadPointId,
+        VectorType.RoadPoint,
+        SelectState.Select
+      );
     } else if (this.modifyPoint.linkedCurveRoadPointId) {
-      stateService.setSelectItem(this.modifyPoint.linkedCurveRoadPointId, VectorType.CurveRoadPoint, SelectState.Select, this.modifyPoint.dir);
+      stateService.setSelectItem(
+        this.modifyPoint.linkedCurveRoadPointId,
+        VectorType.CurveRoadPoint,
+        SelectState.Select,
+        this.modifyPoint.dir
+      );
     } else if (this.modifyPoint.linkedRoadId) {
-      stateService.setSelectItem(this.modifyPoint.linkedRoadId, VectorType.Road, SelectState.Select, this.modifyPoint.dir);
+      stateService.setSelectItem(
+        this.modifyPoint.linkedRoadId,
+        VectorType.Road,
+        SelectState.Select,
+        this.modifyPoint.dir
+      );
     } else if (this.modifyPoint.linkedCurveRoadId) {
-      stateService.setSelectItem(this.modifyPoint.linkedCurveRoadId, VectorType.CurveRoad, SelectState.Select, this.modifyPoint.dir);
+      stateService.setSelectItem(
+        this.modifyPoint.linkedCurveRoadId,
+        VectorType.CurveRoad,
+        SelectState.Select,
+        this.modifyPoint.dir
+      );
     } else if (this.modifyPoint.linkedCrossCrossPointId) {
-      stateService.setSelectItem(this.modifyPoint.linkedCrossCrossPointId, VectorType.CrossPoint, SelectState.Select);
+      stateService.setSelectItem(
+        this.modifyPoint.linkedCrossCrossPointId,
+        VectorType.CrossPoint,
+        SelectState.Select
+      );
     } else if (this.modifyPoint.textId) {
-      stateService.setSelectItem(this.modifyPoint.textId, VectorType.Text, SelectState.Select);
+      stateService.setSelectItem(
+        this.modifyPoint.textId,
+        VectorType.Text,
+        SelectState.Select
+      );
     } else if (this.modifyPoint.magnifierId) {
       // if (this.modifyPoint.index == 0) {
       //点击隐藏的放大镜不显示
-      stateService.setSelectItem(this.modifyPoint.magnifierId, VectorType.Magnifier, this.modifyPoint.index);
+      stateService.setSelectItem(
+        this.modifyPoint.magnifierId,
+        VectorType.Magnifier,
+        this.modifyPoint.index
+      );
       // } else {
       stateService.setSelectState(this.modifyPoint.index);
       // }
     } else if (this.modifyPoint.svgId) {
-      stateService.setSelectItem(this.modifyPoint.svgId, VectorType.SVG, this.modifyPoint.index);
+      stateService.setSelectItem(
+        this.modifyPoint.svgId,
+        VectorType.SVG,
+        this.modifyPoint.index
+      );
     } else if (this.modifyPoint.linkedEdgeId) {
-      stateService.setSelectItem(this.modifyPoint.linkedEdgeId, VectorType.RoadEdge, SelectState.Select);
+      stateService.setSelectItem(
+        this.modifyPoint.linkedEdgeId,
+        VectorType.RoadEdge,
+        SelectState.Select
+      );
     } else if (this.modifyPoint.linkedCurveEdgeId) {
-      stateService.setSelectItem(this.modifyPoint.linkedCurveEdgeId, VectorType.CurveRoadEdge, SelectState.Select);
+      stateService.setSelectItem(
+        this.modifyPoint.linkedCurveEdgeId,
+        VectorType.CurveRoadEdge,
+        SelectState.Select
+      );
     } else if (this.modifyPoint.linkedPointId) {
-      stateService.setSelectItem(this.modifyPoint.linkedPointId, VectorType.Point, SelectState.Select);
+      stateService.setSelectItem(
+        this.modifyPoint.linkedPointId,
+        VectorType.Point,
+        SelectState.Select
+      );
     } else if (this.modifyPoint.linkedCurvePointId) {
-      stateService.setSelectItem(this.modifyPoint.linkedCurvePointId, VectorType.CurvePoint, SelectState.Select);
+      stateService.setSelectItem(
+        this.modifyPoint.linkedCurvePointId,
+        VectorType.CurvePoint,
+        SelectState.Select
+      );
     } else if (this.modifyPoint.linkedLineId) {
-      stateService.setSelectItem(this.modifyPoint.linkedLineId, VectorType.Line, SelectState.Select);
+      stateService.setSelectItem(
+        this.modifyPoint.linkedLineId,
+        VectorType.Line,
+        SelectState.Select
+      );
     } else if (this.modifyPoint.linkedCurveLineId) {
-      stateService.setSelectItem(this.modifyPoint.linkedCurveLineId, VectorType.CurveLine, SelectState.Select);
+      stateService.setSelectItem(
+        this.modifyPoint.linkedCurveLineId,
+        VectorType.CurveLine,
+        SelectState.Select
+      );
     } else if (this.modifyPoint.linkedCircleId) {
-      stateService.setSelectItem(this.modifyPoint.linkedCircleId, VectorType.Circle, this.modifyPoint.index);
+      stateService.setSelectItem(
+        this.modifyPoint.linkedCircleId,
+        VectorType.Circle,
+        this.modifyPoint.index
+      );
     } else {
       stateService.clearSelectItem();
     }
@@ -1281,7 +1550,10 @@ export default class ListenLayer {
 
   //调整到与像素的长度一致
   getDistance(start, end) {
-    return (mathUtil.getDistance(start, end) * coordinate.zoom) / coordinate.defaultZoom;
+    return (
+      (mathUtil.getDistance(start, end) * coordinate.zoom) /
+      coordinate.defaultZoom
+    );
   }
 
   clear() {

+ 26 - 1
src/graphic/Renderer/Draw.js

@@ -1448,13 +1448,14 @@ export default class Draw {
     const height = mathUtil.getDistance(points[0], points[3]);
     const dires = [points[0], { ...points[0], x: 10000 }, points[1]];
     let angle = mathUtil.Angle(...dires) * (Math.PI / 180);
+    const rawAngle = angle;
     angle = mathUtil.isClockwise(dires) ? angle : -angle;
     this.context.save();
     this.context.translate(points[0].x, points[0].y);
     this.context.rotate(angle);
     this.context.scale(width / svgWidth, height / svgHidth);
-    console.log(width, height);
     const [style, label] = help.getVectorStyle(vector);
+
     this.context.lineWidth = style.lineWidth / (width / svgWidth);
     this.context.fillStyle = "rgba(0,0,0,0)";
     this.context.strokeStyle = "rgba(0,0,0,0)";
@@ -1480,6 +1481,8 @@ export default class Draw {
       this.context.stroke();
       this.context.fill();
       this.context.restore();
+      console.log(vector);
+
       vector.points.forEach((point) =>
         this.drawPoint({
           ...point,
@@ -1488,6 +1491,28 @@ export default class Draw {
           radius: 5,
         })
       );
+
+      const center = vector.center;
+      const len =
+        mathUtil.getDistance(vector.points[0], vector.points[2]) / 2 +
+        20 * coordinate.ratio;
+
+      const v = {
+        x: Math.cos(rawAngle + Math.PI / 2),
+        y: Math.sin(rawAngle + Math.PI / 2),
+      };
+      const p = {
+        x: center.x + v.x * len,
+        y: center.y + v.y * len,
+      };
+
+      vector.controlAnglePoint &&
+        this.drawPoint({
+          ...vector.controlAnglePoint,
+          fillColor: "#fff",
+          color: style.strokeStyle,
+          radius: 5,
+        });
     }
   }
 

+ 292 - 59
src/graphic/Util/MathUtil.js

@@ -32,7 +32,8 @@ export default class MathUtil {
     }
 
     const parametera = (point1.y - point2.y) / (point1.x - point2.x);
-    const parameterb = (point1.x * point2.y - point2.x * point1.y) / (point1.x - point2.x);
+    const parameterb =
+      (point1.x * point2.y - point2.x * point1.y) / (point1.x - point2.x);
     if (this.getFixed(parametera) == 0) {
       return { y: this.getFixed(parameterb) };
     }
@@ -81,7 +82,10 @@ export default class MathUtil {
     var perpendicularVector = { x: -slope, y: 1 };
 
     // 将垂直向量归一化为单位向量
-    var length = Math.sqrt(perpendicularVector.x * perpendicularVector.x + perpendicularVector.y * perpendicularVector.y);
+    var length = Math.sqrt(
+      perpendicularVector.x * perpendicularVector.x +
+        perpendicularVector.y * perpendicularVector.y
+    );
     perpendicularVector.x /= length;
     perpendicularVector.y /= length;
 
@@ -109,7 +113,9 @@ export default class MathUtil {
   }
 
   distanceForPoints(point1, point2) {
-    return Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2));
+    return Math.sqrt(
+      Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2)
+    );
   }
 
   //与line平行且两条线直接的距离是distance的两条线
@@ -200,7 +206,10 @@ export default class MathUtil {
     if (angle > 180) {
       angle = 360 - angle;
     }
-    if (Math.abs((angle1 + angle3) / 2 - angle) < Math.abs((angle2 + angle4) / 2 - angle)) {
+    if (
+      Math.abs((angle1 + angle3) / 2 - angle) <
+      Math.abs((angle2 + angle4) / 2 - angle)
+    ) {
       return { p1: point1, p2: point3 };
     } else {
       return { p1: point2, p2: point4 };
@@ -238,7 +247,10 @@ export default class MathUtil {
     if (this.isParallel(parameter1, parameter2)) {
       return null;
     }
-    if (typeof parameter1.a == "undefined" && typeof parameter2.a != "undefined") {
+    if (
+      typeof parameter1.a == "undefined" &&
+      typeof parameter2.a != "undefined"
+    ) {
       if (parameter1.x) {
         return {
           x: parameter1.x,
@@ -250,7 +262,10 @@ export default class MathUtil {
           y: parameter1.y,
         };
       }
-    } else if (typeof parameter2.a == "undefined" && typeof parameter1.a != "undefined") {
+    } else if (
+      typeof parameter2.a == "undefined" &&
+      typeof parameter1.a != "undefined"
+    ) {
       if (parameter2.x) {
         return {
           x: parameter2.x,
@@ -262,10 +277,16 @@ export default class MathUtil {
           y: parameter2.y,
         };
       }
-    } else if (typeof parameter2.a == "undefined" && typeof parameter1.a == "undefined") {
+    } else if (
+      typeof parameter2.a == "undefined" &&
+      typeof parameter1.a == "undefined"
+    ) {
       if (parameter1.hasOwnProperty("x") && parameter2.hasOwnProperty("y")) {
         return { x: parameter1.x, y: parameter2.y };
-      } else if (parameter1.hasOwnProperty("y") && parameter2.hasOwnProperty("x")) {
+      } else if (
+        parameter1.hasOwnProperty("y") &&
+        parameter2.hasOwnProperty("x")
+      ) {
         return { x: parameter2.x, y: parameter1.y };
       } else {
         return null;
@@ -276,8 +297,11 @@ export default class MathUtil {
       return null;
     }
 
-    let joinpointx = (parameter2.b - parameter1.b) / (parameter1.a - parameter2.a);
-    let joinpointy = (parameter1.a * parameter2.b - parameter2.a * parameter1.b) / (parameter1.a - parameter2.a);
+    let joinpointx =
+      (parameter2.b - parameter1.b) / (parameter1.a - parameter2.a);
+    let joinpointy =
+      (parameter1.a * parameter2.b - parameter2.a * parameter1.b) /
+      (parameter1.a - parameter2.a);
 
     let point = { x: joinpointx, y: joinpointy };
     return point;
@@ -294,8 +318,17 @@ export default class MathUtil {
     }
 
     // 线段所在直线的交点坐标 (x , y)
-    const x = ((b.x - a.x) * (d.x - c.x) * (c.y - a.y) + (b.y - a.y) * (d.x - c.x) * a.x - (d.y - c.y) * (b.x - a.x) * c.x) / denominator;
-    const y = -((b.y - a.y) * (d.y - c.y) * (c.x - a.x) + (b.x - a.x) * (d.y - c.y) * a.y - (d.x - c.x) * (b.y - a.y) * c.y) / denominator;
+    const x =
+      ((b.x - a.x) * (d.x - c.x) * (c.y - a.y) +
+        (b.y - a.y) * (d.x - c.x) * a.x -
+        (d.y - c.y) * (b.x - a.x) * c.x) /
+      denominator;
+    const y =
+      -(
+        (b.y - a.y) * (d.y - c.y) * (c.x - a.x) +
+        (b.x - a.x) * (d.y - c.y) * a.y -
+        (d.x - c.x) * (b.y - a.y) * c.y
+      ) / denominator;
 
     return { x: x, y: y };
   }
@@ -307,7 +340,12 @@ export default class MathUtil {
       const x = join.x;
       const y = join.y; // 交点在线段1上 且交点也在线段2上
       /** 2 判断交点是否在两条线段上 **/
-      if ((x - a.x) * (x - b.x) <= 0.001 && (y - a.y) * (y - b.y) <= 0.001 && (x - c.x) * (x - d.x) <= 0.001 && (y - c.y) * (y - d.y) <= 0.001) {
+      if (
+        (x - a.x) * (x - b.x) <= 0.001 &&
+        (y - a.y) * (y - b.y) <= 0.001 &&
+        (x - c.x) * (x - d.x) <= 0.001 &&
+        (y - c.y) * (y - d.y) <= 0.001
+      ) {
         // 返回交点p
         return {
           x: x,
@@ -379,6 +417,7 @@ export default class MathUtil {
       return ((2 * Math.PI - fi) * 180) / Math.PI;
     }
   }
+
   Angle1(o, s, e) {
     let cosfi = 0,
       fi = 0,
@@ -400,6 +439,28 @@ export default class MathUtil {
     return (fi * 180) / Math.PI;
   }
 
+  vectorAngle(p, p1, p2) {
+    let a = [];
+    let b = [];
+    a[0] = p1.x - p.x;
+    a[1] = p1.y - p.y;
+    b[0] = p2.x - p.x;
+    b[1] = p2.y - p.y;
+    const dot = a[0] * b[0] + a[1] * b[1]; // 点积
+    const det = a[0] * b[1] - a[1] * b[0]; // 叉积(用于符号判断)
+    const magA = Math.hypot(a[0], a[1]); // 向量a的模
+    const magB = Math.hypot(b[0], b[1]); // 向量b的模
+
+    if (magA === 0 || magB === 0) {
+      debugger;
+      return null; // 防止除以0
+    }
+
+    // 计算夹角(带方向)
+    const angle = Math.atan2(det, dot);
+    return -1 * angle;
+  }
+
   getArrow(start, end, ange = 30, L = 14) {
     let a = Math.atan2(end.y - start.y, end.x - start.x);
     let xC = end.x - L * Math.cos(a + (ange * Math.PI) / 180); // θ=30
@@ -477,7 +538,8 @@ export default class MathUtil {
     if (!minDis) {
       minDis = Constant.minLen;
     }
-    let dis1 = this.getDistance(startPoint, point) + this.getDistance(endPoint, point);
+    let dis1 =
+      this.getDistance(startPoint, point) + this.getDistance(endPoint, point);
     let dis2 = this.getDistance(startPoint, endPoint);
     if (Math.abs(dis1 - dis2) < minDis) {
       return true;
@@ -545,7 +607,8 @@ export default class MathUtil {
       const xj = pt2.x;
       const yj = pt2.y;
 
-      const intersect = yi > y != yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
+      const intersect =
+        yi > y != yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
       if (intersect) inside = !inside;
     }
 
@@ -554,7 +617,9 @@ export default class MathUtil {
 
   //a表示横轴,b表示竖轴
   isPointInElliptic(point, center, a, b) {
-    let r = Math.pow((point.x - center.x) / a, 2) + Math.pow((point.y - center.y) / b, 2);
+    let r =
+      Math.pow((point.x - center.x) / a, 2) +
+      Math.pow((point.y - center.y) / b, 2);
 
     if (r <= 1) {
       return true;
@@ -572,7 +637,10 @@ export default class MathUtil {
     const dis = this.getDistance(point1, point2);
     const dis1 = this.getDistance(join, point1);
     const dis2 = this.getDistance(join, point2);
-    if (this.getDistance(join, point1) > dis || this.getDistance(join, point2) > dis) {
+    if (
+      this.getDistance(join, point1) > dis ||
+      this.getDistance(join, point2) > dis
+    ) {
       // 在线段外
       if (dis1 < dis2 && dis1 < minDistance) {
         return { type: 1, join: point1 };
@@ -593,7 +661,10 @@ export default class MathUtil {
   }
 
   PointInSegment(Q, pi, pj, minDis) {
-    if (this.getDistance(Q, pi) < Constant.minAdsorbPix || this.getDistance(Q, pj) < Constant.minAdsorbPix) {
+    if (
+      this.getDistance(Q, pi) < Constant.minAdsorbPix ||
+      this.getDistance(Q, pj) < Constant.minAdsorbPix
+    ) {
       return true;
     }
 
@@ -648,7 +719,11 @@ export default class MathUtil {
     const dot_product_AP = AP.x * AB_direction.x + AP.y * AB_direction.y;
     const dot_product_BP = BP.x * AB_direction.x + BP.y * AB_direction.y;
     //return dot_product_AP >= 0 && dot_product_BP <= 0 && Math.abs(AP.x * BP.y - AP.y * BP.x) <= AB_length * Number.EPSILON;
-    return dot_product_AP >= 0 && dot_product_BP <= 0 && Math.abs(AP.x * BP.y - AP.y * BP.x) <= 0.01;
+    return (
+      dot_product_AP >= 0 &&
+      dot_product_BP <= 0 &&
+      Math.abs(AP.x * BP.y - AP.y * BP.x) <= 0.01
+    );
   }
 
   clonePoint(p1, p2) {
@@ -707,7 +782,12 @@ export default class MathUtil {
     }
     const join = this.getIntersectionPoint2(point1, point2, point3, point4);
     if (join != null) {
-      if (this.getDistance(point1, join) > dis && this.getDistance(point2, join) > dis && this.getDistance(point3, join) > dis && this.getDistance(point4, join) > dis) {
+      if (
+        this.getDistance(point1, join) > dis &&
+        this.getDistance(point2, join) > dis &&
+        this.getDistance(point3, join) > dis &&
+        this.getDistance(point4, join) > dis
+      ) {
         if (
           this.getDistance(point1, join) < this.getDistance(point1, point2) &&
           this.getDistance(point2, join) < this.getDistance(point1, point2) &&
@@ -720,7 +800,10 @@ export default class MathUtil {
         }
       }
     } else {
-      if (this.PointInSegment(point1, point3, point4) || this.PointInSegment(point2, point3, point4)) {
+      if (
+        this.PointInSegment(point1, point3, point4) ||
+        this.PointInSegment(point2, point3, point4)
+      ) {
         return true;
       }
     }
@@ -826,7 +909,8 @@ export default class MathUtil {
       return 0;
     }
     let s = points[0].y * (points[point_num - 1].x - points[1].x);
-    for (let i = 1; i < point_num; ++i) s += points[i].y * (points[i - 1].x - points[(i + 1) % point_num].x);
+    for (let i = 1; i < point_num; ++i)
+      s += points[i].y * (points[i - 1].x - points[(i + 1) % point_num].x);
     return Math.abs(s / 2.0);
   }
 
@@ -834,7 +918,13 @@ export default class MathUtil {
   getPolygonCore(points) {
     function Area(p0, p1, p2) {
       let area = 0.0;
-      area = p0.x * p1.y + p1.x * p2.y + p2.x * p0.y - p1.x * p0.y - p2.x * p1.y - p0.x * p2.y;
+      area =
+        p0.x * p1.y +
+        p1.x * p2.y +
+        p2.x * p0.y -
+        p1.x * p0.y -
+        p2.x * p1.y -
+        p0.x * p2.y;
       return area / 2;
     }
 
@@ -1302,9 +1392,15 @@ export default class MathUtil {
 
     let delta;
     if (v > 1) {
-      delta = this.pointMinus(p1, this.pointPlus(pt, this.pointScale(this.pointMinus(p2, pt), 1 / v)));
+      delta = this.pointMinus(
+        p1,
+        this.pointPlus(pt, this.pointScale(this.pointMinus(p2, pt), 1 / v))
+      );
     } else {
-      delta = this.pointMinus(this.pointPlus(pt, this.pointScale(this.pointMinus(p1, pt), v)), p2);
+      delta = this.pointMinus(
+        this.pointPlus(pt, this.pointScale(this.pointMinus(p1, pt), v)),
+        p2
+      );
     }
     delta = this.pointScale(delta, scale);
 
@@ -1323,7 +1419,12 @@ export default class MathUtil {
     const curves = [];
     let preControl1, preControl2;
     for (let i = 0; i < points.length - 2; i++) {
-      const { control1, control2 } = this.getCurvesControls(points[i], points[i + 1], points[i + 2], scale);
+      const { control1, control2 } = this.getCurvesControls(
+        points[i],
+        points[i + 1],
+        points[i + 2],
+        scale
+      );
 
       curves.push({
         start: points[i],
@@ -1386,7 +1487,9 @@ export default class MathUtil {
       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
     }
 
@@ -1405,8 +1508,16 @@ export default class MathUtil {
 
       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);
+        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];
@@ -1427,8 +1538,16 @@ export default class MathUtil {
     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;
-    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;
+    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;
+    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 };
   }
 
@@ -1443,8 +1562,16 @@ export default class MathUtil {
     // 参数化方式在曲线上取一系列的点
     var pointsOnCurve = [];
     for (var t = 0; t <= 1; t += 0.01) {
-      var x = Math.pow(1 - t, 3) * p0.x + 3 * Math.pow(1 - t, 2) * t * p1.x + 3 * (1 - t) * Math.pow(t, 2) * p2.x + Math.pow(t, 3) * p3.x;
-      var y = Math.pow(1 - t, 3) * p0.y + 3 * Math.pow(1 - t, 2) * t * p1.y + 3 * (1 - t) * Math.pow(t, 2) * p2.y + Math.pow(t, 3) * p3.y;
+      var x =
+        Math.pow(1 - t, 3) * p0.x +
+        3 * Math.pow(1 - t, 2) * t * p1.x +
+        3 * (1 - t) * Math.pow(t, 2) * p2.x +
+        Math.pow(t, 3) * p3.x;
+      var y =
+        Math.pow(1 - t, 3) * p0.y +
+        3 * Math.pow(1 - t, 2) * t * p1.y +
+        3 * (1 - t) * Math.pow(t, 2) * p2.y +
+        Math.pow(t, 3) * p3.y;
       pointsOnCurve.push({ x: x, y: y });
     }
 
@@ -1452,7 +1579,10 @@ export default class MathUtil {
     var shortestDistance = Number.MAX_VALUE;
     var closestPoint;
     for (var i = 0; i < pointsOnCurve.length; i++) {
-      var distance = Math.sqrt(Math.pow(pointsOnCurve[i].x - target.x, 2) + Math.pow(pointsOnCurve[i].y - target.y, 2));
+      var distance = Math.sqrt(
+        Math.pow(pointsOnCurve[i].x - target.x, 2) +
+          Math.pow(pointsOnCurve[i].y - target.y, 2)
+      );
       if (distance < shortestDistance) {
         shortestDistance = distance;
         closestPoint = pointsOnCurve[i];
@@ -1469,11 +1599,23 @@ export default class MathUtil {
     const { x: offsetX, y: offsetY } = position;
     let results = [];
     // 用 x 求出对应的 t,用 t 求相应位置的 y,再比较得出的 y 与 offsetY 之间的差值
-    const tsx = this.getThreeBezierT(curve.start.x, curve.controls[0].x, curve.controls[1].x, curve.end.x, offsetX);
+    const tsx = this.getThreeBezierT(
+      curve.start.x,
+      curve.controls[0].x,
+      curve.controls[1].x,
+      curve.end.x,
+      offsetX
+    );
     console.log(tsx);
     for (let x = 0; x < 3; x++) {
       if (tsx[x] <= 1 && tsx[x] >= 0) {
-        const point = this.getThreeBezierPoint(tsx[x], curve.start, curve.controls[0], curve.controls[1], curve.end);
+        const point = this.getThreeBezierPoint(
+          tsx[x],
+          curve.start,
+          curve.controls[0],
+          curve.controls[1],
+          curve.end
+        );
         // if (Math.abs(point.y - offsetY) < rang) {
         results.push({
           position: point,
@@ -1483,10 +1625,22 @@ export default class MathUtil {
       }
     }
     // 如果上述没有结果,则用 y 求出对应的 t,再用 t 求出对应的 x,与 offsetX 进行匹配
-    const tsy = this.getThreeBezierT(curve.start.y, curve.controls[0].y, curve.controls[1].y, curve.end.y, offsetY);
+    const tsy = this.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 = this.getThreeBezierPoint(tsy[y], curve.start, curve.controls[0], curve.controls[1], curve.end);
+        const point = this.getThreeBezierPoint(
+          tsy[y],
+          curve.start,
+          curve.controls[0],
+          curve.controls[1],
+          curve.end
+        );
         // if (Math.abs(point.x - offsetX) < rang) {
         results.push({
           position: point,
@@ -1527,9 +1681,15 @@ export default class MathUtil {
   getHitInfoForCurves(pos, curves, roadWidth) {
     let joinInfo;
     for (const curve of curves) {
-      const tempJoinInfo = curve.controls.length === 2 ? this.getHitInfoForThreeBezier(pos, curve, roadWidth / 2) : this.getHitInfoForTwoBezier(pos, curve);
-
-      if (!joinInfo || (tempJoinInfo && tempJoinInfo.distance < joinInfo.distance)) {
+      const tempJoinInfo =
+        curve.controls.length === 2
+          ? this.getHitInfoForThreeBezier(pos, curve, roadWidth / 2)
+          : this.getHitInfoForTwoBezier(pos, curve);
+
+      if (
+        !joinInfo ||
+        (tempJoinInfo && tempJoinInfo.distance < joinInfo.distance)
+      ) {
         joinInfo = tempJoinInfo;
       }
     }
@@ -1538,9 +1698,15 @@ export default class MathUtil {
 
   getHitInfoForCurve(pos, curve, roadWidth) {
     let joinInfo;
-    const tempJoinInfo = curve.controls.length === 2 ? this.getHitInfoForThreeBezier(pos, curve, roadWidth / 2) : this.getHitInfoForTwoBezier(pos, curve);
+    const tempJoinInfo =
+      curve.controls.length === 2
+        ? this.getHitInfoForThreeBezier(pos, curve, roadWidth / 2)
+        : this.getHitInfoForTwoBezier(pos, curve);
 
-    if (!joinInfo || (tempJoinInfo && tempJoinInfo.distance < joinInfo.distance)) {
+    if (
+      !joinInfo ||
+      (tempJoinInfo && tempJoinInfo.distance < joinInfo.distance)
+    ) {
       joinInfo = tempJoinInfo;
     }
     return joinInfo;
@@ -1570,7 +1736,10 @@ export default class MathUtil {
       }
     }
     if (index == -1) {
-      if (minDisToPoint > mathUtil.getDistance(position, points[points.length - 1])) {
+      if (
+        minDisToPoint >
+        mathUtil.getDistance(position, points[points.length - 1])
+      ) {
         return points.length;
       } else {
         return minPointIndex;
@@ -1604,7 +1773,10 @@ export default class MathUtil {
       }
     }
     if ((index = -1)) {
-      if (minDisToPoint > mathUtil.getDistance(position, points[points.length - 1])) {
+      if (
+        minDisToPoint >
+        mathUtil.getDistance(position, points[points.length - 1])
+      ) {
         return points.length - 2;
       } else {
         return minPointIndex;
@@ -1657,23 +1829,43 @@ export default class MathUtil {
         if (mathUtil.equalPoint(points[i], points[i + 1])) {
           return null;
         }
-        let leftEdgePoins1 = this.RectangleVertex(points[i], points[i + 1], leftWidth * 2);
-        let leftLine1 = mathUtil.createLine1(leftEdgePoins1.leftEdgeStart, leftEdgePoins1.leftEdgeEnd);
+        let leftEdgePoins1 = this.RectangleVertex(
+          points[i],
+          points[i + 1],
+          leftWidth * 2
+        );
+        let leftLine1 = mathUtil.createLine1(
+          leftEdgePoins1.leftEdgeStart,
+          leftEdgePoins1.leftEdgeEnd
+        );
         if (i != points.length - 2) {
           if (mathUtil.equalPoint(points[i + 2], points[i + 1])) {
             return null;
           }
-          let leftEdgePoins2 = this.RectangleVertex(points[i + 1], points[i + 2], leftWidth * 2);
-
-          let leftLine2 = mathUtil.createLine1(leftEdgePoins2.leftEdgeStart, leftEdgePoins2.leftEdgeEnd);
+          let leftEdgePoins2 = this.RectangleVertex(
+            points[i + 1],
+            points[i + 2],
+            leftWidth * 2
+          );
+
+          let leftLine2 = mathUtil.createLine1(
+            leftEdgePoins2.leftEdgeStart,
+            leftEdgePoins2.leftEdgeEnd
+          );
           let join = mathUtil.getIntersectionPoint(leftLine1, leftLine2);
           if (join != null) {
             leftEdgePoints[i + 1] = join;
           } else {
-            leftEdgePoints[i + 1] = mathUtil.getJoinLinePoint(points[i + 1], leftLine1);
+            leftEdgePoints[i + 1] = mathUtil.getJoinLinePoint(
+              points[i + 1],
+              leftLine1
+            );
           }
         } else {
-          leftEdgePoints[i + 1] = mathUtil.getJoinLinePoint(points[i + 1], leftLine1);
+          leftEdgePoints[i + 1] = mathUtil.getJoinLinePoint(
+            points[i + 1],
+            leftLine1
+          );
         }
         if (!leftEdgePoints[0]) {
           leftEdgePoints[0] = mathUtil.getJoinLinePoint(points[0], leftLine1);
@@ -1684,23 +1876,43 @@ export default class MathUtil {
         if (mathUtil.equalPoint(points[i], points[i + 1])) {
           return null;
         }
-        let rightEdgePoins1 = this.RectangleVertex(points[i], points[i + 1], rightWidth * 2);
-        let rightLine1 = mathUtil.createLine1(rightEdgePoins1.rightEdgeStart, rightEdgePoins1.rightEdgeEnd);
+        let rightEdgePoins1 = this.RectangleVertex(
+          points[i],
+          points[i + 1],
+          rightWidth * 2
+        );
+        let rightLine1 = mathUtil.createLine1(
+          rightEdgePoins1.rightEdgeStart,
+          rightEdgePoins1.rightEdgeEnd
+        );
         if (i != points.length - 2) {
           if (mathUtil.equalPoint(points[i + 2], points[i + 1])) {
             return null;
           }
-          let rightEdgePoins2 = this.RectangleVertex(points[i + 1], points[i + 2], rightWidth * 2);
-
-          let rightLine2 = mathUtil.createLine1(rightEdgePoins2.rightEdgeStart, rightEdgePoins2.rightEdgeEnd);
+          let rightEdgePoins2 = this.RectangleVertex(
+            points[i + 1],
+            points[i + 2],
+            rightWidth * 2
+          );
+
+          let rightLine2 = mathUtil.createLine1(
+            rightEdgePoins2.rightEdgeStart,
+            rightEdgePoins2.rightEdgeEnd
+          );
           let join = mathUtil.getIntersectionPoint(rightLine1, rightLine2);
           if (join != null) {
             rightEdgePoints[i + 1] = join;
           } else {
-            rightEdgePoints[i + 1] = mathUtil.getJoinLinePoint(points[i + 1], rightLine1);
+            rightEdgePoints[i + 1] = mathUtil.getJoinLinePoint(
+              points[i + 1],
+              rightLine1
+            );
           }
         } else {
-          rightEdgePoints[i + 1] = mathUtil.getJoinLinePoint(points[i + 1], rightLine1);
+          rightEdgePoints[i + 1] = mathUtil.getJoinLinePoint(
+            points[i + 1],
+            rightLine1
+          );
         }
 
         if (!rightEdgePoints[0]) {
@@ -1807,6 +2019,27 @@ export default class MathUtil {
     // 返回中心点坐标
     return { x: centerX, y: centerY };
   }
+
+  // angleBetween2D(point, point1, point2) {
+  //   let a = [];
+  //   let b = [];
+  //   a[0] = point1.x - point.x;
+  //   a[1] = point1.y - point.y;
+
+  //   b[0] = point2.x - point.x;
+  //   b[1] = point2.y - point.y;
+
+  //   const dot = a[0] * b[0] + a[1] * b[1]; // 点积
+  //   const det = a[0] * b[1] - a[1] * b[0]; // 叉积(用于符号判断)
+  //   const magA = Math.hypot(a[0], a[1]); // 向量a的模
+  //   const magB = Math.hypot(b[0], b[1]); // 向量b的模
+
+  //   if (magA === 0 || magB === 0) return null; // 防止除以0
+
+  //   // 计算夹角(带方向)
+  //   const angle = -1 * Math.atan2(det, dot); // 返回 [-π, π]
+  //   return angle;
+  // }
 }
 
 const mathUtil = new MathUtil();

+ 36 - 21
src/store/sync.ts

@@ -77,27 +77,33 @@ export const api = !global.android
         await window.open(await api.getFile(filename));
       },
       async getFile(url) {
-        const urlRaw = url;
-        getFilesIng.push(urlRaw);
+        try {
+          const urlRaw = url;
+          getFilesIng.push(urlRaw);
 
-        if (url.includes(baseURL)) {
-          url = url.substring(baseURL.length);
-        }
-        url = url.trim();
-        const paths = url.split("/");
-        const notBase64BaseTypes = [".png", ".jpg"];
-        const notBase64 = notBase64BaseTypes.some((type) =>
-          paths[paths.length - 1].includes(type)
-        );
-        if (notBase64) {
-          getFilesSuccess.push(urlRaw);
-          // await new Promise((resolve) => setTimeout(resolve, 2000));
-          return baseURL + url;
-        } else {
-          const data = await axios.get(url, { responseType: "blob" });
-          const base64 = await blobToBase64(data.data);
-          getFilesSuccess.push(urlRaw);
-          return URL.createObjectURL(base64ToBlob(base64));
+          if (url.includes(baseURL)) {
+            url = url.substring(baseURL.length);
+          }
+          url = url.trim();
+          const paths = url.split("/");
+          const notBase64BaseTypes = [".png", ".jpg"];
+          const notBase64 = notBase64BaseTypes.some((type) =>
+            paths[paths.length - 1].includes(type)
+          );
+          if (notBase64) {
+            getFilesSuccess.push(urlRaw);
+            // await new Promise((resolve) => setTimeout(resolve, 2000));
+            console.error(baseURL + url);
+            return baseURL + url;
+          } else {
+            const data = await axios.get(url, { responseType: "blob" });
+            const base64 = await blobToBase64(data.data);
+            getFilesSuccess.push(urlRaw);
+            return URL.createObjectURL(base64ToBlob(base64));
+          }
+        } catch (e) {
+          console.error("获取文件失败 url:", url);
+          throw e;
         }
       },
       async photograph(rotate = true) {
@@ -180,7 +186,16 @@ export const api = !global.android
             const apiName = `getImageCallback${global.count++}`;
             global[apiName] = (base64) => {
               getFilesSuccess.push(urlRaw);
-              resolve(URL.createObjectURL(base64ToBlob(base64)));
+              try {
+                resolve(URL.createObjectURL(base64ToBlob(base64)));
+              } catch (e) {
+                console.error(
+                  "getFile 失败 获取url:",
+                  fileUrl,
+                  "获取结果:",
+                  base64
+                );
+              }
               delete global[apiName];
             };
             global.android.getImage(fileUrl, apiName);

+ 12 - 7
src/views/scene/mode.vue

@@ -5,7 +5,7 @@
     :size="size"
     :style="{ '--size': `${size}px`, width: `${size}px`, height: `${size}px` }"
     :active-key="customMap.mode"
-    v-if="!disabledMap.mode"
+    v-if="!disabledMap.mode && menus.length > 1"
   />
 </template>
 
@@ -20,11 +20,6 @@ defineProps<{ size: number }>();
 
 const tabs = [
   {
-    mode: Mode.pano,
-    icon: "panorama_f",
-    activeIcon: "panorama_t",
-  },
-  {
     mode: Mode.cloud,
     icon: "point_c_f",
     activeIcon: "point_c_t",
@@ -40,7 +35,17 @@ const menus = computed(() =>
     onClick: () => (customMap.mode = tab.mode === Mode.pano ? Mode.cloud : Mode.pano),
   }))
 );
-customMap.mode = Number(localStorage.getItem(key)) || Mode.pano;
+
+if (!params.temp) {
+  tabs.unshift({
+    mode: Mode.pano,
+    icon: "panorama_f",
+    activeIcon: "panorama_t",
+  });
+  customMap.mode = Number(localStorage.getItem(key)) || Mode.pano;
+} else {
+  customMap.mode = Number(localStorage.getItem(key)) || Mode.cloud;
+}
 watch(
   () => customMap.mode,
   () => {