|
@@ -8,6 +8,8 @@ import UIEvents from "@/graphic/enum/UIEvents.js";
|
|
|
import VectorCategory from "@/graphic/enum/VectorCategory.js";
|
|
|
import Settings from "@/graphic/Settings.js";
|
|
|
import SVGIcons from "../CanvasStyle/ImageLabels/SVGIcons";
|
|
|
+import VectorStyle from "@/graphic/enum/VectorStyle.js";
|
|
|
+import VectorWeight from "@/graphic/enum/VectorWeight.js";
|
|
|
|
|
|
const imgCache = {};
|
|
|
const help = {
|
|
@@ -200,6 +202,139 @@ const help = {
|
|
|
ctx.fillText(text, -textCenter.x, -textCenter.y);
|
|
|
ctx.restore();
|
|
|
},
|
|
|
+ isTriangleClockwise(p1, p2, p3) {
|
|
|
+ const crossProduct = (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y);
|
|
|
+ return crossProduct < 0;
|
|
|
+ },
|
|
|
+ drawStyleLine(ctx, line, style = VectorStyle.SingleSolidLine, weight = VectorStyle.Thinning) {
|
|
|
+ ctx.save();
|
|
|
+ style = style || VectorStyle.SingleSolidLine
|
|
|
+ ctx.beginPath();
|
|
|
+ const lineWidth = Settings.lineWidth * (ctx.lineWidth || 1) * (weight === VectorWeight.Bold ? 2 : 1);
|
|
|
+
|
|
|
+ switch (style) {
|
|
|
+ case VectorStyle.PointDrawLine:
|
|
|
+ case VectorStyle.SingleDashedLine:
|
|
|
+ case VectorStyle.SingleSolidLine:
|
|
|
+ ctx.lineWidth = lineWidth
|
|
|
+ if (style === VectorStyle.SingleDashedLine) {
|
|
|
+ ctx.setLineDash([8 * coordinate.ratio, 8 * coordinate.ratio]);
|
|
|
+ } else if (style === VectorStyle.PointDrawLine) {
|
|
|
+ ctx.setLineDash([6 * coordinate.ratio, 6* coordinate.ratio, 2 * coordinate.ratio]);
|
|
|
+ }
|
|
|
+
|
|
|
+ ctx.moveTo(line[0].x, line[0].y);
|
|
|
+ ctx.lineTo(line[1].x, line[1].y);
|
|
|
+ break
|
|
|
+ // 单实线
|
|
|
+ case VectorStyle.DoubleDashedLine:
|
|
|
+ case VectorStyle.DoubleSolidLine:
|
|
|
+ if (style === VectorStyle.DoubleDashedLine) {
|
|
|
+ ctx.setLineDash([8 * coordinate.ratio, 8 * coordinate.ratio]);
|
|
|
+ }
|
|
|
+ ctx.lineWidth = lineWidth * 4
|
|
|
+ ctx.moveTo(line[0].x, line[0].y);
|
|
|
+ ctx.lineTo(line[1].x, line[1].y);
|
|
|
+ ctx.stroke();
|
|
|
+
|
|
|
+
|
|
|
+ ctx.moveTo(line[0].x, line[0].y);
|
|
|
+ ctx.lineTo(line[1].x, line[1].y);
|
|
|
+ ctx.lineWidth = lineWidth * 2
|
|
|
+ ctx.strokeStyle = 'rgb(255,255,255)'
|
|
|
+ break
|
|
|
+ case VectorStyle.BrokenLine:
|
|
|
+ const ldis = 5 * coordinate.ratio
|
|
|
+ if (mathUtil.getDistance(...line) < ldis * 2) {
|
|
|
+ ctx.moveTo(line[0].x, line[0].y);
|
|
|
+ ctx.lineTo(line[1].x, line[1].y);
|
|
|
+ } else {
|
|
|
+ const start = mathUtil.translate(line[0], line[1], line[0], ldis)
|
|
|
+ const end = mathUtil.translate(line[0], line[1], line[1], -ldis)
|
|
|
+ const lineDis = mathUtil.getDistance(start, end)
|
|
|
+ const len = Math.ceil(lineDis / (6 * coordinate.ratio))
|
|
|
+ const split = lineDis / len
|
|
|
+
|
|
|
+ const points = [start]
|
|
|
+ let temp = start
|
|
|
+ for (let i = 0; i < len ; i++) {
|
|
|
+ temp = mathUtil.translate(temp, line[1], temp, split)
|
|
|
+ points.push(temp)
|
|
|
+ }
|
|
|
+
|
|
|
+ ctx.moveTo(line[0].x, line[0].y);
|
|
|
+ ctx.lineTo(start.x, start.y);
|
|
|
+ for (let i = 0; i < points.length - 1; i++) {
|
|
|
+ const vTop = help.getPerpendicularPoint(
|
|
|
+ points[i],
|
|
|
+ points[i + 1],
|
|
|
+ mathUtil.lineCenter(points[i], points[i + 1]),
|
|
|
+ (split * ((i%2) ? -1 : 1)) / 2
|
|
|
+ )
|
|
|
+ ctx.lineTo(vTop.x, vTop.y);
|
|
|
+ }
|
|
|
+ ctx.lineTo(end.x, end.y);
|
|
|
+ ctx.lineTo(line[1].x, line[1].y);
|
|
|
+ }
|
|
|
+ ctx.lineWidth = lineWidth
|
|
|
+ break
|
|
|
+ case VectorStyle.Greenbelt:
|
|
|
+ const dis = 4 * coordinate.ratio
|
|
|
+ const size = 8 * coordinate.ratio
|
|
|
+ const p1 = help.getPerpendicularPoint(
|
|
|
+ line[0], line[1], line[0], dis
|
|
|
+ )
|
|
|
+ const p2 = help.getPerpendicularPoint(
|
|
|
+ line[0], line[1], line[1], dis
|
|
|
+ )
|
|
|
+ const p3 = help.getPerpendicularPoint(
|
|
|
+ p1, p2, p2, size
|
|
|
+ )
|
|
|
+ const p4 = help.getPerpendicularPoint(
|
|
|
+ p1, p2, p1, size
|
|
|
+ )
|
|
|
+
|
|
|
+ ctx.beginPath()
|
|
|
+ ctx.lineWidth = lineWidth
|
|
|
+ ctx.moveTo(line[0].x, line[0].y);
|
|
|
+ ctx.lineTo(line[1].x, line[1].y);
|
|
|
+ ctx.stroke();
|
|
|
+ ctx.beginPath()
|
|
|
+ ctx.moveTo(p4.x, p4.y);
|
|
|
+ ctx.lineTo(p1.x, p1.y);
|
|
|
+ ctx.lineTo(p2.x, p2.y);
|
|
|
+ ctx.lineTo(p3.x, p3.y);
|
|
|
+ ctx.stroke();
|
|
|
+
|
|
|
+
|
|
|
+ const rdis = 6 * coordinate.ratio
|
|
|
+ const lineDis = mathUtil.getDistance(p3, p4)
|
|
|
+ const len = Math.ceil(lineDis / rdis)
|
|
|
+ const split = lineDis / len
|
|
|
+ const points = [p3]
|
|
|
+ const geo = [p4, {...p4, x: 999}, p3]
|
|
|
+ let angle = (mathUtil.Angle1(...geo) / 180) * Math.PI
|
|
|
+ const isClock = help.isTriangleClockwise(...geo) || angle === 0
|
|
|
+
|
|
|
+ angle = isClock ? -angle : angle
|
|
|
+
|
|
|
+ let temp = p3
|
|
|
+ for (let i = 0; i < len; i++) {
|
|
|
+ temp = mathUtil.translate(temp, p4, temp, split)
|
|
|
+ points.push(temp)
|
|
|
+ }
|
|
|
+ for (let i = 0; i < points.length - 1; i++) {
|
|
|
+ const center = mathUtil.lineCenter(points[i], points[i+1])
|
|
|
+ ctx.beginPath()
|
|
|
+ ctx.arc(center.x, center.y, split / 2, angle, angle + Math.PI, !isClock)
|
|
|
+ ctx.stroke();
|
|
|
+ }
|
|
|
+ ctx.lineWidth = lineWidth
|
|
|
+ break
|
|
|
+ }
|
|
|
+ ctx.stroke();
|
|
|
+ ctx.restore();
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
export default class Draw {
|
|
@@ -327,6 +462,7 @@ export default class Draw {
|
|
|
ctx.save();
|
|
|
ctx.beginPath();
|
|
|
help.setVectorStyle(ctx, null, "Lane");
|
|
|
+ ctx.lineWidth *= Settings.lineWidth
|
|
|
ctx.setLineDash(Style.Lane.dash);
|
|
|
ctx.moveTo(start.x, start.y);
|
|
|
ctx.lineTo(end.x, end.y);
|
|
@@ -346,6 +482,7 @@ export default class Draw {
|
|
|
: dataService.getRoadPoint(vector.startId);
|
|
|
const end = isTemp ? vector.end : dataService.getRoadPoint(vector.endId);
|
|
|
|
|
|
+
|
|
|
const drawRoadEdgeChild = (edgeVector) => {
|
|
|
const flag = mathUtil.isSameDirForVector(
|
|
|
start,
|
|
@@ -355,12 +492,9 @@ export default class Draw {
|
|
|
);
|
|
|
|
|
|
if (flag) {
|
|
|
- ctx.beginPath();
|
|
|
const point1 = coordinate.getScreenXY(edgeVector.start);
|
|
|
const point2 = coordinate.getScreenXY(edgeVector.end);
|
|
|
- ctx.moveTo(point1.x, point1.y);
|
|
|
- ctx.lineTo(point2.x, point2.y);
|
|
|
- ctx.stroke();
|
|
|
+ help.drawStyleLine(ctx, [point1, point2], edgeVector.style, edgeVector.weight)
|
|
|
}
|
|
|
if (import.meta.env.DEV) {
|
|
|
this.drawTextByInfo(
|
|
@@ -383,8 +517,13 @@ export default class Draw {
|
|
|
ctx.save();
|
|
|
isTemp && (ctx.globalAlpha = 0.3);
|
|
|
help.setVectorStyle(ctx, leftEdge);
|
|
|
+ let [style, fo] = help.getVectorStyle(vector)
|
|
|
+ fo && help.setStyle(ctx, style)
|
|
|
drawRoadEdgeChild(leftEdge);
|
|
|
+
|
|
|
help.setVectorStyle(ctx, rightEdge);
|
|
|
+ fo && help.setStyle(ctx, style)
|
|
|
+
|
|
|
drawRoadEdgeChild(rightEdge);
|
|
|
ctx.restore();
|
|
|
|
|
@@ -452,14 +591,15 @@ export default class Draw {
|
|
|
const ctx = this.context;
|
|
|
ctx.save();
|
|
|
help.setVectorStyle(ctx, vector);
|
|
|
+ ctx.lineWidth *= Settings.lineWidth
|
|
|
for (let coves of covesArray) {
|
|
|
help.drawCoves(ctx, coves);
|
|
|
}
|
|
|
ctx.restore();
|
|
|
}
|
|
|
|
|
|
- this.drawCurveRoadEdge(dataService.getCurveRoadEdge(vector.rightEdgeId));
|
|
|
- this.drawCurveRoadEdge(dataService.getCurveRoadEdge(vector.leftEdgeId));
|
|
|
+ this.drawCurveRoadEdge(dataService.getCurveRoadEdge(vector.rightEdgeId), vector);
|
|
|
+ this.drawCurveRoadEdge(dataService.getCurveRoadEdge(vector.leftEdgeId), vector);
|
|
|
vector.leftLanesCurves &&
|
|
|
vector.leftLanesCurves.forEach(this.drawCurveLan.bind(this));
|
|
|
vector.rightLanesCurves &&
|
|
@@ -470,11 +610,14 @@ export default class Draw {
|
|
|
// }
|
|
|
}
|
|
|
|
|
|
- drawCurveRoadEdge(vector, isTemp) {
|
|
|
+ drawCurveRoadEdge(vector, roadVector) {
|
|
|
const [coves] = help.transformCoves([vector.curves]);
|
|
|
const ctx = this.context;
|
|
|
+ const [style, select] = help.getVectorStyle(roadVector)
|
|
|
ctx.save();
|
|
|
help.setVectorStyle(ctx, vector);
|
|
|
+ select && help.setStyle(ctx, style)
|
|
|
+ ctx.lineWidth *= Settings.lineWidth
|
|
|
help.drawCoves(ctx, coves);
|
|
|
ctx.restore();
|
|
|
|
|
@@ -489,6 +632,7 @@ export default class Draw {
|
|
|
ctx.save();
|
|
|
|
|
|
help.setVectorStyle(ctx, null, "CurveLan");
|
|
|
+ ctx.lineWidth *= Settings.lineWidth
|
|
|
ctx.setLineDash(Style.Lane.dash);
|
|
|
help.drawCoves(ctx, coves);
|
|
|
ctx.restore();
|
|
@@ -697,7 +841,7 @@ export default class Draw {
|
|
|
if (Settings.selectBasePointId === vector.vectorId) {
|
|
|
style = {
|
|
|
...style,
|
|
|
- fillStyle: "red",
|
|
|
+ strokeStyle: "rgba(255,255,255,1)",
|
|
|
out: style.out && {
|
|
|
...style.out,
|
|
|
strokeStyle: "red",
|
|
@@ -712,14 +856,15 @@ export default class Draw {
|
|
|
}
|
|
|
|
|
|
if (vector.category === "BasePoint") {
|
|
|
+ ctx.font = `${22}px Microsoft YaHei`
|
|
|
const bound = help.getTextCenter(ctx, "基准点")
|
|
|
const textPt = {
|
|
|
- y: pt.y - bound.height,
|
|
|
- x: pt.x - (bound.width / 2)
|
|
|
+ y: vector.y + bound.height,
|
|
|
+ x: vector.x - (bound.width / 2)
|
|
|
}
|
|
|
|
|
|
ctx.fillStyle = style.fillStyle
|
|
|
- this.drawTextByInfo(coordinate.getXYFromScreen(textPt), "基准点", 0, false);
|
|
|
+ this.drawTextByInfo(textPt, "基准点", 0, false);
|
|
|
} else {
|
|
|
if (import.meta.env.DEV) {
|
|
|
if (vector.vectorId) {
|
|
@@ -800,12 +945,13 @@ export default class Draw {
|
|
|
this.context.lineTo(points[1].x, points[1].y);
|
|
|
this.context.lineTo(points[2].x, points[2].y);
|
|
|
this.context.lineTo(points[3].x, points[3].y);
|
|
|
- this.context.strokeStyle = "red"
|
|
|
+ this.context.strokeStyle = style.strokeStyle
|
|
|
+ this.context.lineWidth = 2 * coordinate.ratio
|
|
|
this.context.setLineDash([6 * coordinate.ratio, 2 * coordinate.ratio]);
|
|
|
this.context.closePath();
|
|
|
this.context.stroke();
|
|
|
this.context.restore();
|
|
|
- vector.points.forEach(point => this.drawPoint({...point, color: 'red', radius: 5 }))
|
|
|
+ vector.points.forEach(point => this.drawPoint({...point, color: style.strokeStyle, radius: 5 }))
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -900,11 +1046,7 @@ export default class Draw {
|
|
|
this.context.setLineDash(style.dash);
|
|
|
}
|
|
|
|
|
|
- this.context.beginPath();
|
|
|
- this.context.moveTo(start.x, start.y);
|
|
|
- this.context.lineTo(end.x, end.y);
|
|
|
- this.context.stroke();
|
|
|
- this.context.restore();
|
|
|
+ help.drawStyleLine(this.context, [start, end], vector.style, vector.weight)
|
|
|
|
|
|
const drawPoints = () => {
|
|
|
// if (attr) {
|