Browse Source

解决合并冲突

feature/rail
LiLongLong 5 months ago
parent
commit
0283e4ef69
  1. 10
      src/pages/measure/components/MeasureAction.tsx
  2. 72
      src/pages/measure/components/SectionalView.tsx
  3. 31
      src/pages/measure/components/graph/AreaLayer.tsx
  4. 88
      src/pages/measure/components/graph/GridLayer.tsx
  5. 31
      src/pages/measure/components/graph/MarkLayer.tsx
  6. 31
      src/pages/measure/components/graph/RealtimeLayer.tsx
  7. 209
      src/pages/measure/components/graph/StandardLayer.tsx
  8. 60
      src/utils/index.ts

10
src/pages/measure/components/MeasureAction.tsx

@ -1,9 +1,10 @@
import { Button, Checkbox, CheckboxProps, Radio, RadioChangeEvent, message } from "antd";
import { useState, useEffect } from "react";
import { useNavigate } from "react-router";
import SectionalView from "./SectionalView";
import { startMeasurement } from "../../../services/measure/analysis"
import { createWebSocket, sharedWsUrl } from "../../../services/socket";
import GridLayer from "./graph/GridLayer";
import StandardLayer from "./graph/StandardLayer";
export default function MeasureAction() {
const navigate = useNavigate();
@ -41,8 +42,11 @@ export default function MeasureAction() {
}
return (
<div className="flex h-full ">
<div className="flex-none border">
<SectionalView width={840} height={600} leftPadding={30} rightPadding={10} topPadding={10} bottomPadding={30} columns={10} rows={7} cellNum={10} />
<div className="flex-none border relative">
<GridLayer width={840} height={600} leftPadding={30} rightPadding={10} topPadding={10} bottomPadding={30} columns={10} rows={7} colCellNum={1} rowCellNum={2} />
<div className="absolute top-0">
<StandardLayer width={840} height={600} leftPadding={30} rightPadding={10} topPadding={10} bottomPadding={30} columns={10} rows={7} />
</div>
</div>
<div className="w-[300px] flex-none py-6">
<h1 className="font-medium text-xl text-center"></h1>

72
src/pages/measure/components/SectionalView.tsx

@ -1,72 +0,0 @@
import { useCallback, useEffect, useRef } from "react";
const primaryLineColor = "rgb(203,213,245)";
const subLineColor = "rgb(226,231,232)";
export default function SectionalView(props: {
width: number;
height: number;
leftPadding: number;
rightPadding: number;
topPadding: number;
bottomPadding: number;
columns: number;
rows: number;
cellNum: number;
}) {
const xStartPx = props.leftPadding;
const xEndPx = props.width - props.rightPadding;
const xStepPx = (props.width - props.leftPadding - props.rightPadding) / props.columns;
const xUnitPx = xStepPx / props.cellNum;
const yStartPx = props.topPadding;
const yEndPx = props.height - props.bottomPadding;
const yStepPx = (props.height - props.topPadding - props.bottomPadding) / props.rows;
const yUnitPx = yStepPx / props.cellNum;
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const drawGrid = useCallback((ctx: CanvasRenderingContext2D) => {
ctx.beginPath();
ctx.strokeStyle = subLineColor;
for (let i = 1; i < props.columns * props.cellNum; ++i) {
if (i % props.cellNum === 0) continue;
ctx.moveTo(xStartPx + xUnitPx * i, yStartPx);
ctx.lineTo(xStartPx + xUnitPx * i, yEndPx);
}
for (let j = 1; j < props.rows * props.cellNum; ++j) {
if (j % props.cellNum === 0) continue;
ctx.moveTo(xStartPx, yStartPx + yUnitPx * j);
ctx.lineTo(xEndPx, yStartPx + yUnitPx * j);
}
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = primaryLineColor;
for (let i = 0; i <= props.columns; ++i) {
ctx.moveTo(xStartPx + xStepPx * i, yStartPx);
ctx.lineTo(xStartPx + xStepPx * i, yEndPx);
}
for (let j = 0; j <= props.rows; ++j) {
ctx.moveTo(xStartPx, yStartPx + yStepPx * j);
ctx.lineTo(xEndPx, yStartPx + yStepPx * j);
}
ctx.stroke();
},[props.cellNum, props.columns, props.rows, xEndPx, xStartPx, xStepPx, xUnitPx, yEndPx, yStartPx, yStepPx, yUnitPx])
useEffect(() => {
// 获取canvas的2D绘图上下文
const canvas = canvasRef.current;
if (!canvas) return;
const context = canvas.getContext("2d");
if (!context) return;
// 使用context对象进行绘图
drawGrid(context);
}, [drawGrid]);
return (
<div>
<canvas ref={canvasRef} width={props.width} height={props.height}></canvas>
</div>
);
}

31
src/pages/measure/components/graph/AreaLayer.tsx

@ -0,0 +1,31 @@
import { useCallback, useEffect, useRef } from "react";
export default function AreaLayer(props: {
width: number;
height: number;
leftPadding: number;
rightPadding: number;
topPadding: number;
bottomPadding: number;
}) {
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const draw = useCallback((ctx: CanvasRenderingContext2D) => {
// 使用context对象进行绘图
ctx.fillStyle = "skyblue"; // 设置填充颜色
ctx.fillRect(50, 50, 150, 100); // 绘制一个矩形
}, []);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const context = canvas.getContext("2d");
if (!context) return;
draw(context);
}, [draw]);
return (
<div>
<canvas ref={canvasRef} width={props.width} height={props.height}></canvas>
</div>
);
}

88
src/pages/measure/components/graph/GridLayer.tsx

@ -0,0 +1,88 @@
import { useCallback, useEffect, useRef } from "react";
const primaryLineColor = "rgb(203,213,245)";
const subLineColor = "rgb(226,231,232)";
export default function GridLayer(props: {
width: number;
height: number;
leftPadding: number;
rightPadding: number;
topPadding: number;
bottomPadding: number;
columns: number;
rows: number;
colCellNum: number;
rowCellNum: number;
}) {
const xStartPx = props.leftPadding;
const xEndPx = props.width - props.rightPadding;
const xStepPx = (props.width - props.leftPadding - props.rightPadding) / props.columns;
const xUnitPx = xStepPx / props.colCellNum;
const yStartPx = props.topPadding;
const yEndPx = props.height - props.bottomPadding;
const yStepPx = (props.height - props.topPadding - props.bottomPadding) / props.rows;
const yUnitPx = yStepPx / props.rowCellNum;
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const drawGrid = useCallback(
(ctx: CanvasRenderingContext2D) => {
ctx.beginPath();
ctx.strokeStyle = subLineColor;
for (let i = 1; i < props.columns * props.colCellNum; ++i) {
if (i % props.colCellNum === 0) continue;
ctx.moveTo(xStartPx + xUnitPx * i, yStartPx);
ctx.lineTo(xStartPx + xUnitPx * i, yEndPx);
}
for (let j = 1; j < props.rows * props.rowCellNum; ++j) {
if (j % props.rowCellNum === 0) continue;
ctx.moveTo(xStartPx, yStartPx + yUnitPx * j);
ctx.lineTo(xEndPx, yStartPx + yUnitPx * j);
}
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = primaryLineColor;
for (let i = 0; i <= props.columns; ++i) {
ctx.moveTo(xStartPx + xStepPx * i, yStartPx);
ctx.lineTo(xStartPx + xStepPx * i, yEndPx);
}
for (let j = 0; j <= props.rows; ++j) {
ctx.moveTo(xStartPx, yStartPx + yStepPx * j);
ctx.lineTo(xEndPx, yStartPx + yStepPx * j);
}
ctx.stroke();
},
[
props.colCellNum,
props.columns,
props.rowCellNum,
props.rows,
xEndPx,
xStartPx,
xStepPx,
xUnitPx,
yEndPx,
yStartPx,
yStepPx,
yUnitPx,
]
);
useEffect(() => {
// 获取canvas的2D绘图上下文
const canvas = canvasRef.current;
if (!canvas) return;
const context = canvas.getContext("2d");
if (!context) return;
// 使用context对象进行绘图
drawGrid(context);
}, [drawGrid]);
return (
<div>
<canvas ref={canvasRef} width={props.width} height={props.height}></canvas>
</div>
);
}

31
src/pages/measure/components/graph/MarkLayer.tsx

@ -0,0 +1,31 @@
import { useCallback, useEffect, useRef } from "react";
export default function MarkLayer(props: {
width: number;
height: number;
leftPadding: number;
rightPadding: number;
topPadding: number;
bottomPadding: number;
}) {
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const draw = useCallback((ctx: CanvasRenderingContext2D) => {
// 使用context对象进行绘图
ctx.fillStyle = "skyblue"; // 设置填充颜色
ctx.fillRect(50, 50, 150, 100); // 绘制一个矩形
}, []);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const context = canvas.getContext("2d");
if (!context) return;
draw(context);
}, [draw]);
return (
<div>
<canvas ref={canvasRef} width={props.width} height={props.height}></canvas>
</div>
);
}

31
src/pages/measure/components/graph/RealtimeLayer.tsx

@ -0,0 +1,31 @@
import { useCallback, useEffect, useRef } from "react";
export default function RealtimeLayer(props: {
width: number;
height: number;
leftPadding: number;
rightPadding: number;
topPadding: number;
bottomPadding: number;
}) {
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const draw = useCallback((ctx: CanvasRenderingContext2D) => {
// 使用context对象进行绘图
ctx.fillStyle = "skyblue"; // 设置填充颜色
ctx.fillRect(50, 50, 150, 100); // 绘制一个矩形
}, []);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const context = canvas.getContext("2d");
if (!context) return;
draw(context);
}, [draw]);
return (
<div>
<canvas ref={canvasRef} width={props.width} height={props.height}></canvas>
</div>
);
}

209
src/pages/measure/components/graph/StandardLayer.tsx

@ -0,0 +1,209 @@
import { useCallback, useEffect, useRef } from "react";
import { calculateCircleAbove, calculateCircleBelow } from "../../../../utils";
const unitPx = 8;
const pointsR: [number, number][] = [
[0, 0],
[9.949007022412, 0.1650166186941],
[25.35, 2.184814802617],
[35.4, 14.20034968551],
[36.31679456414, 32.538841443],
[32.90417417089, 37.53190928715],
[20.0, 41.8333134842],
];
const pointsL: [number, number][] = [
[-20.0, 41.83331348425],
[-32.90417417089, 37.53190928715],
[-36.31679456414, 32.538841443],
[-35.4, 14.20034968551],
[-25.35, 2.184814802617],
[-9.949007022412, 0.1650166186941],
[0, 0],
];
const pointsRight = pointsR.map(p => [p[0] * unitPx, p[1] * unitPx]);
const pointsLeft = pointsL.map(p => [p[0] * unitPx, p[1] * unitPx]);
export default function StandardLayer(props: {
width: number;
height: number;
leftPadding: number;
rightPadding: number;
topPadding: number;
bottomPadding: number;
columns: number;
rows: number;
}) {
const xStartPx = props.leftPadding;
const xEndPx = props.width - props.rightPadding;
const xStepPx = (props.width - props.leftPadding - props.rightPadding) / props.columns;
const yStartPx = props.topPadding;
const yEndPx = props.height - props.bottomPadding;
const yStepPx = (props.height - props.topPadding - props.bottomPadding) / props.rows;
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const draw = useCallback(
(ctx: CanvasRenderingContext2D) => {
ctx.strokeStyle = "#999";
// 偏移原点
const xOffset = (xEndPx - xStartPx) / 2;
const yOffset = yStepPx * 2;
const yMax = yEndPx - yStartPx - yOffset;
ctx.translate(xStartPx + xOffset, yStartPx + yOffset);
// 绘制原点交叉线
ctx.moveTo(-xOffset, 0);
ctx.lineTo(xOffset, 0);
ctx.moveTo(0, -yOffset);
ctx.lineTo(0, yMax);
ctx.stroke();
// 绘制x轴y轴 单位数值
ctx.beginPath();
ctx.fillStyle = "#333333";
ctx.textAlign = "center";
ctx.font = "normal 14px system";
for (let index = -4; index < 5; index++) {
ctx.fillText((index * 10).toString(), xStepPx * index, yMax + 20);
}
for (let index = -1; index < 5; index++) {
ctx.fillText((-index * 10).toString(), -xOffset - (index > 0 ? 18 : 14), yStepPx * index + 4);
}
// 绘制标准线
ctx.beginPath();
ctx.strokeStyle = "red";
// ---- 右侧
let point0 = pointsRight[0];
let point1 = pointsRight[1];
ctx.moveTo(point0[0], point0[1]);
let param = calculateCircleBelow(point0[0], point0[1], point1[0], point1[1], 300 * unitPx);
console.log(param);
ctx.arc(
param.center.x,
param.center.y,
300 * unitPx,
param.anglesForCenter.startAngle,
param.anglesForCenter.endAngle
);
point0 = pointsRight[1];
point1 = pointsRight[2];
ctx.moveTo(point0[0], point0[1]);
param = calculateCircleBelow(point0[0], point0[1], point1[0], point1[1], 80 * unitPx);
console.log(param);
ctx.arc(
param.center.x,
param.center.y,
80 * unitPx,
param.anglesForCenter.startAngle,
param.anglesForCenter.endAngle
);
point0 = pointsRight[2];
point1 = pointsRight[3];
ctx.moveTo(point0[0], point0[1]);
param = calculateCircleBelow(point0[0], point0[1], point1[0], point1[1], 13 * unitPx);
console.log(param);
ctx.arc(
param.center.x,
param.center.y,
13 * unitPx,
param.anglesForCenter.startAngle,
param.anglesForCenter.endAngle
);
point0 = pointsRight[3];
point1 = pointsRight[4];
ctx.moveTo(point0[0], point0[1]);
ctx.lineTo(point1[0], point1[1]);
point0 = pointsRight[4];
point1 = pointsRight[5];
ctx.moveTo(point0[0], point0[1]);
param = calculateCircleAbove(point0[0], point0[1], point1[0], point1[1], 5 * unitPx);
console.log(param);
ctx.arc(param.center.x, param.center.y, 5 * unitPx, param.anglesForCenter.startAngle, param.anglesForCenter.endAngle);
point0 = pointsRight[5];
point1 = pointsRight[6];
ctx.moveTo(point0[0], point0[1]);
ctx.lineTo(point1[0], point1[1]);
// ---- 左侧
point0 = pointsLeft[0];
point1 = pointsLeft[1];
ctx.moveTo(point0[0], point0[1]);
ctx.lineTo(point1[0], point1[1]);
point0 = pointsLeft[1];
point1 = pointsLeft[2];
ctx.moveTo(point0[0], point0[1]);
param = calculateCircleAbove(point0[0], point0[1], point1[0], point1[1], 5 * unitPx);
console.log(param);
ctx.arc(param.center.x, param.center.y, 5 * unitPx, param.anglesForCenter.startAngle, param.anglesForCenter.endAngle);
point0 = pointsLeft[2];
point1 = pointsLeft[3];
ctx.moveTo(point0[0], point0[1]);
ctx.lineTo(point1[0], point1[1]);
point0 = pointsLeft[3];
point1 = pointsLeft[4];
ctx.moveTo(point0[0], point0[1]);
param = calculateCircleBelow(point0[0], point0[1], point1[0], point1[1], 13 * unitPx);
console.log(param);
ctx.arc(
param.center.x,
param.center.y,
13 * unitPx,
param.anglesForCenter.startAngle,
param.anglesForCenter.endAngle
);
point0 = pointsLeft[4];
point1 = pointsLeft[5];
ctx.moveTo(point0[0], point0[1]);
param = calculateCircleBelow(point0[0], point0[1], point1[0], point1[1], 80 * unitPx);
console.log(param);
ctx.arc(
param.center.x,
param.center.y,
80 * unitPx,
param.anglesForCenter.startAngle,
param.anglesForCenter.endAngle
);
point0 = pointsLeft[5];
point1 = pointsLeft[6];
ctx.moveTo(point0[0], point0[1]);
param = calculateCircleBelow(point0[0], point0[1], point1[0], point1[1], 300 * unitPx);
console.log(param);
ctx.arc(
param.center.x,
param.center.y,
300 * unitPx,
param.anglesForCenter.startAngle,
param.anglesForCenter.endAngle
);
ctx.stroke();
// ctx.fillRect(100, 100, 150, 100); // 绘制一个矩形
},
[xEndPx, xStartPx, xStepPx, yEndPx, yStartPx, yStepPx]
);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const context = canvas.getContext("2d");
if (!context) return;
draw(context);
}, [draw]);
return (
<div>
<canvas ref={canvasRef} width={props.width} height={props.height}></canvas>
</div>
);
}

60
src/utils/index.ts

@ -3,3 +3,63 @@ export function formatRemainTime(seconds: number) {
const sec = (seconds % 60).toFixed();
return min.padStart(2, "0") + ":" + sec.padStart(2, "0");
}
export function calculateCircleInfo(x1: number, y1: number, x2: number, y2: number, radius: number) {
// 计算P1到P2的中点
const xm = (x1 + x2) / 2;
const ym = (y1 + y2) / 2;
// P1到P2的距离的一半
const dx = x2 - x1;
const dy = y2 - y1;
const d = Math.sqrt(dx * dx + dy * dy) / 2;
// 如果距离大于直径,则无法形成圆
if (d > radius) {
throw new Error("Given points are too far apart for the given radius.");
}
// 计算垂直平分线的方向向量
const len = Math.sqrt(radius * radius - d * d);
const nx = dy / (2 * d);
const ny = -dx / (2 * d);
// 计算两个可能的圆心
const cx1 = xm + nx * len;
const cy1 = ym + ny * len;
const cx2 = xm - nx * len;
const cy2 = ym - ny * len;
// 使用atan2计算起始角和结束角
function calculateAngle(cx: number, cy: number, px: number, py: number) {
return Math.atan2(py - cy, px - cx);
}
const startAngle1 = calculateAngle(cx1, cy1, x1, y1);
const endAngle1 = calculateAngle(cx1, cy1, x2, y2);
const startAngle2 = calculateAngle(cx2, cy2, x1, y1);
const endAngle2 = calculateAngle(cx2, cy2, x2, y2);
return [
{ center: { x: cx1, y: cy1 }, anglesForCenter: { startAngle: startAngle1, endAngle: endAngle1 } },
{ center: { x: cx2, y: cy2 }, anglesForCenter: { startAngle: startAngle2, endAngle: endAngle2 } },
];
}
export type CenterAndAngle = ReturnType<typeof calculateCircleBelow>;
export function calculateCircleBelow(x1: number, y1: number, x2: number, y2: number, radius: number) {
const results = calculateCircleInfo(x1, y1, x2, y2, radius);
if (results[0].center.y > results[1].center.y) {
return results[0];
} else {
return results[1];
}
}
export function calculateCircleAbove(x1: number, y1: number, x2: number, y2: number, radius: number) {
const results = calculateCircleInfo(x1, y1, x2, y2, radius);
if (results[0].center.y < results[1].center.y) {
return results[0];
} else {
return results[1];
}
}
Loading…
Cancel
Save