xushiting 2 anni fa
parent
commit
f1429757ab

+ 22 - 0
src/graphic/Controls/MoveCircle.js

@@ -0,0 +1,22 @@
+import { dataService } from "../Service/DataService";
+import { mathUtil } from "../Util/MathUtil";
+
+export default class MoveCircle {
+  constructor() {}
+
+  moveFull(circleId, dx, dy) {
+    dx = dx;
+    dy = -dy;
+    let circle = dataService.getCircle(circleId);
+    circle.center.x += dx;
+    circle.center.y += dy;
+  }
+
+  moveRing(position, circleId) {
+    let circle = dataService.getCircle(circleId);
+    circle.setRadius(mathUtil.getDistance(circle.center, position));
+  }
+}
+
+const moveCircle = new MoveCircle();
+export { moveCircle };

+ 17 - 0
src/graphic/Layer.js

@@ -17,6 +17,7 @@ import { addMagnifier } from "./Controls/AddMagnifier";
 import { addSVG } from "./Controls/AddSVG";
 import { moveRoad } from "./Controls/MoveRoad";
 import { moveLine } from "./Controls/MoveLine";
+import { moveCircle } from "./Controls/MoveCircle";
 import { coordinate } from "./Coordinate";
 import Render from "./Renderer/Render";
 import { draw } from "./Renderer/Draw";
@@ -534,6 +535,22 @@ export default class Layer {
           needAutoRedraw = true;
         }
         break;
+      case LayerEvents.MoveCircle:
+        if (draggingItem != null) {
+          if (draggingItem.state == SelectState.Select) {
+            moveCircle.moveFull(
+              draggingItem.vectorId,
+              (dx * coordinate.defaultZoom) / coordinate.zoom,
+              (dy * coordinate.defaultZoom) / coordinate.zoom
+            );
+            this.lastX = X;
+            this.lastY = Y;
+          } else {
+            moveCircle.moveRing(position, draggingItem.vectorId);
+          }
+          needAutoRedraw = true;
+        }
+        break;
       case LayerEvents.MoveText:
         needAutoRedraw = true;
         if (draggingItem != null) {

+ 80 - 4
src/graphic/ListenLayer.js

@@ -62,12 +62,12 @@ export default class ListenLayer {
       position,
       exceptVectorIds.exceptLineId
     );
-    // selectInfo.curveLineInfo = this.isSelectCurveLine(
-    //   position,
-    //   exceptVectorIds.exceptCurveLineId
-    // );
     selectInfo.curveLineInfo = {};
     selectInfo.curvePointInfo = {};
+    selectInfo.circleInfo = this.isSelectCircle(
+      position,
+      exceptVectorIds.exceptCircleId
+    );
     //交叉口拐弯处的控制点
     selectInfo.controlPointInfo = this.isSelectCrossControlPoint(
       position,
@@ -193,6 +193,70 @@ export default class ListenLayer {
     return lineInfo;
   }
 
+  isSelectCircle(position, exceptCircleId) {
+    let circleInfo = {
+      circleId: null,
+      type: null,
+      distance: null,
+    };
+    const circles = dataService.getCircles();
+    for (const circleId in circles) {
+      if (circleId == exceptCircleId) {
+        continue;
+      }
+      const circle = dataService.getCircle(circleId);
+      const distance = mathUtil.getDistance(position, circle.center);
+      if (distance < circle.radius - Constant.minAdsorbPix) {
+        if (circleInfo.circleId == null || distance < circleInfo.distance) {
+          circleInfo = {
+            circleId: circleId,
+            type: VectorType.Circle,
+            distance: distance,
+            select: SelectState.Select,
+            x: circle.center.x,
+            y: circle.center.y,
+          };
+        }
+      } else if (
+        distance > circle.radius - Constant.minAdsorbPix &&
+        distance < circle.radius + Constant.minAdsorbPix
+      ) {
+        if (circleInfo.circleId == null || distance < circleInfo.distance) {
+          const joins = mathUtil.getInsertPointBetweenCircleAndLine(
+            circle.center.x,
+            circle.center.y,
+            position.x,
+            position.y,
+            circle.center.x,
+            circle.center.y,
+            circle.radius
+          );
+          let join = {};
+          if (
+            mathUtil.getDistance(joins[0], position) <
+            mathUtil.getDistance(joins[1], position)
+          ) {
+            join.x = joins[0].x;
+            join.y = joins[0].y;
+          } else {
+            join.x = joins[1].x;
+            join.y = joins[1].y;
+          }
+          circleInfo = {
+            circleId: circleId,
+            type: VectorType.Circle,
+            distance: Math.abs(distance - circle.radius),
+            select: SelectState.CircleRing, //选中环
+            x: join.x,
+            y: join.y,
+          };
+        }
+      }
+    }
+
+    return circleInfo;
+  }
+
   // isSelectCurveLine(position, exceptCurveLineId) {
   //   let curveLineInfo = {
   //     curveLineId: null,
@@ -892,6 +956,12 @@ export default class ListenLayer {
         this.modifyPoint.x = info.curveLineInfo.x;
         this.modifyPoint.y = info.curveLineInfo.y;
       }
+    } else if (info && info.circleInfo.circleId) {
+      this.modifyPoint = {};
+      this.modifyPoint.linkedCircleId = info.circleInfo.circleId;
+      this.modifyPoint.select = info.circleInfo.select;
+      this.modifyPoint.x = info.circleInfo.x;
+      this.modifyPoint.y = info.circleInfo.y;
     } else if (info && info.roadPointInfo.linkedRoadPointIdX) {
       this.modifyPoint = {};
       this.modifyPoint.linkedRoadPointIdX =
@@ -1018,6 +1088,12 @@ export default class ListenLayer {
         VectorType.CurveLine,
         SelectState.Select
       );
+    } else if (this.modifyPoint.linkedCircleId) {
+      stateService.setSelectItem(
+        this.modifyPoint.linkedCircleId,
+        VectorType.Circle,
+        this.modifyPoint.select
+      );
     }
 
     let newSelectItem = stateService.getSelectItem();

+ 7 - 2
src/graphic/Service/StateService.js

@@ -28,6 +28,7 @@ export default class StateService {
     this.selectItem = {};
     this.selectItem.vectorId = vectorId;
     this.selectItem.type = type;
+    this.selectItem.state = state;
 
     if (type == VectorType.Line) {
       const line = dataService.getLine(vectorId);
@@ -52,7 +53,9 @@ export default class StateService {
 
   setDraggingItem(draggingItem) {
     this.draggingItem = draggingItem;
-    if (this.draggingItem.type == VectorType.Line) {
+    if (this.draggingItem == null) {
+      return;
+    } else if (this.draggingItem.type == VectorType.Line) {
       const line = dataService.getLine(this.draggingItem.vectorId);
       this.draggingItem.category = line.getCategory();
     } else if (this.draggingItem.type == VectorType.Point) {
@@ -71,7 +74,9 @@ export default class StateService {
 
   setFocusItem(focusItem) {
     this.focusItem = focusItem;
-    if (this.focusItem.type == VectorType.Line) {
+    if (this.focusItem == null) {
+      return;
+    } else if (this.focusItem.type == VectorType.Line) {
       const line = dataService.getLine(this.focusItem.vectorId);
       this.focusItem.category = line.getCategory();
     } else if (this.focusItem.type == VectorType.Point) {

+ 66 - 0
src/graphic/Util/MathUtil.js

@@ -1049,6 +1049,72 @@ export default class MathUtil {
     return points;
   }
 
+  //求圆和直线之间的交点
+  /**
+   * 求圆和直线之间的交点
+   * 直线方程:y = kx + b
+   * 圆的方程:(x - m)² + (x - n)² = r²
+   * x1, y1 = 线坐标1, x2, y2 = 线坐标2, m, n = 圆坐标, r = 半径
+   */
+  getInsertPointBetweenCircleAndLine(x1, y1, x2, y2, m, n, radius) {
+    let insertPoints = [];
+    if (Math.abs(x1 - x2) < 0.5) {
+      insertPoints[0] = {
+        x: x1,
+        y: n - Math.sqrt(radius * radius - Math.pow(x1 - m, 2)),
+      };
+      insertPoints[1] = {
+        x: x1,
+        y: n + Math.sqrt(radius * radius - Math.pow(x1 - m, 2)),
+      };
+      return insertPoints;
+    }
+    // console.log(x1, y1, x2, y2, m, n, radius)
+    let kbArr = this.binaryEquationGetKB(x1, y1, x2, y2);
+    let k = kbArr[0];
+    let b = kbArr[1];
+
+    let aX = 1 + k * k;
+    let bX = 2 * k * (b - n) - 2 * m;
+    let cX = m * m + (b - n) * (b - n) - radius * radius;
+
+    let xArr = this.quadEquationGetX(aX, bX, cX);
+    xArr.forEach((x) => {
+      let y = k * x + b;
+      insertPoints.push({ x: x, y: y });
+    });
+    return insertPoints;
+  }
+
+  /**
+   * 求二元一次方程的系数
+   * y1 = k * x1 + b => k = (y1 - b) / x1
+   * y2 = k * x2 + b => y2 = ((y1 - b) / x1) * x2 + b
+   */
+  binaryEquationGetKB(x1, y1, x2, y2) {
+    let k = (y1 - y2) / (x1 - x2);
+    let b = (x1 * y2 - x2 * y1) / (x1 - x2);
+    return [k, b];
+  }
+
+  /**
+   * 一元二次方程求根
+   * ax² + bx + c = 0
+   */
+  quadEquationGetX(a, b, c) {
+    let xArr = [];
+    let result = Math.pow(b, 2) - 4 * a * c;
+    if (result > 0) {
+      xArr.push((-b + Math.sqrt(result)) / (2 * a));
+      xArr.push((-b - Math.sqrt(result)) / (2 * a));
+    }
+    //else if (result == 0) {
+    else {
+      xArr.push(-b / (2 * a));
+    }
+    return xArr;
+  }
+
   angleTo(v1, v2) {
     const denominator = Math.sqrt(this.lengthSq(v1) * this.lengthSq(v2));
     if (denominator === 0) return 90;

+ 1 - 18
src/graphic/enum/SelectState.js

@@ -1,22 +1,5 @@
 const SelectState = {
   Select: "select",
-  /*,
-    focus: "focus",
-    selectArrow: "selectArrow", // beam,flue  focus后,选中下面的箭头
-    dragging: "dragging",
-    error: "error",
-    full: "full",
-    building: "building",
-    rotate: "rotate",
-    resize: "resize",
-    num1: 1,
-    num2: 2,
-    num3: 3,
-    num4: 4,
-    num5: 5,
-    num6: 6,
-    num7: 7,
-    num8: 8,
-    */
+  CircleRing: "circleRing",
 };
 export default SelectState;