|
|
@@ -115,677 +115,561 @@ export default {
|
|
|
}
|
|
|
});
|
|
|
},
|
|
|
- updateChart() {
|
|
|
- console.log("=== LeafRootOutlineData 详细结构 ===");
|
|
|
- console.log("数据类型:", this.type);
|
|
|
- console.log(
|
|
|
- "完整数据:",
|
|
|
- JSON.parse(JSON.stringify(this.LeafRootOutlineData))
|
|
|
- );
|
|
|
-
|
|
|
- if (!this.chartInstance) {
|
|
|
- console.warn("图表实例未初始化,无法更新图表");
|
|
|
- this.initializeChart();
|
|
|
- return;
|
|
|
- }
|
|
|
+updateChart() {
|
|
|
+ console.log("=== LeafRootOutlineData 详细结构 ===");
|
|
|
+ console.log("数据类型:", this.type);
|
|
|
+ console.log(
|
|
|
+ "完整数据:",
|
|
|
+ JSON.parse(JSON.stringify(this.LeafRootOutlineData))
|
|
|
+ );
|
|
|
+
|
|
|
+ if (!this.chartInstance) {
|
|
|
+ console.warn("图表实例未初始化,无法更新图表");
|
|
|
+ this.initializeChart();
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- // 1) 原始数据 → 四舍五入到4位(保持数值类型)
|
|
|
- const xRaw = (this.LeafRootOutlineData?.first_blade?.xdata || []).map(
|
|
|
- (v) => Number(Number(v).toFixed(4))
|
|
|
- );
|
|
|
+ // === 修改点 1:坐标零点偏移计算 ===
|
|
|
+ // 两种类型都以叶根1中心点作为零点进行偏移
|
|
|
+ let centerXOffset = 0;
|
|
|
+ let centerYOffset = 0;
|
|
|
+
|
|
|
+ if (this.type === "LeafRootOutline" || this.type === "LeafTipProfile") {
|
|
|
+ // 获取叶片1中心点作为坐标零点
|
|
|
+ if (
|
|
|
+ this.LeafRootOutlineData?.blade_center?.xdata?.length > 0 &&
|
|
|
+ this.LeafRootOutlineData?.blade_center?.xdata[0] !== undefined &&
|
|
|
+ this.LeafRootOutlineData?.blade_center?.ydata?.length > 0 &&
|
|
|
+ this.LeafRootOutlineData?.blade_center?.ydata[0] !== undefined
|
|
|
+ ) {
|
|
|
+ centerXOffset = this.LeafRootOutlineData.blade_center.xdata[0];
|
|
|
+ centerYOffset = this.LeafRootOutlineData.blade_center.ydata[0];
|
|
|
+ console.log("使用叶根1中心点作为坐标零点:", {
|
|
|
+ X偏移量: centerXOffset.toFixed(4),
|
|
|
+ Y偏移量: centerYOffset.toFixed(4)
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ console.warn("没有中心点数据,坐标轴不进行偏移");
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- // 处理基础3条叶片数据(叶根和叶片都有的)
|
|
|
- const y1Raw = this.LeafRootOutlineData.first_blade.ydata.map((v) =>
|
|
|
+ // 1) 原始数据 → 四舍五入到4位(保持数值类型)
|
|
|
+ const xRawOriginal = (this.LeafRootOutlineData?.first_blade?.xdata || []).map(
|
|
|
+ (v) => Number(Number(v).toFixed(4))
|
|
|
+ );
|
|
|
+
|
|
|
+ // 处理基础3条叶片数据
|
|
|
+ const y1Raw = this.LeafRootOutlineData.first_blade.ydata.map((v) =>
|
|
|
+ Number(Number(v).toFixed(4))
|
|
|
+ );
|
|
|
+ const y2Raw = this.LeafRootOutlineData.second_blade.ydata.map((v) =>
|
|
|
+ Number(Number(v).toFixed(4))
|
|
|
+ );
|
|
|
+ const y3Raw = this.LeafRootOutlineData.third_blade.ydata.map((v) =>
|
|
|
+ Number(Number(v).toFixed(4))
|
|
|
+ );
|
|
|
+
|
|
|
+ // 2) 根据类型决定是否处理旋转叶片数据
|
|
|
+ let y4Raw, y5Raw, y6Raw;
|
|
|
+ let hasRotateData = false;
|
|
|
+ let allRawY = [y1Raw, y2Raw, y3Raw];
|
|
|
+
|
|
|
+ // 只有在叶片轮廓拟合图中才处理旋转叶片数据
|
|
|
+ if (this.type === "LeafRootOutline") {
|
|
|
+ // 检查旋转叶片数据是否存在,存在则处理
|
|
|
+ if (this.LeafRootOutlineData?.first_rotate_blade?.ydata?.length > 0) {
|
|
|
+ y4Raw = this.LeafRootOutlineData.first_rotate_blade.ydata.map((v) =>
|
|
|
Number(Number(v).toFixed(4))
|
|
|
);
|
|
|
- const y2Raw = this.LeafRootOutlineData.second_blade.ydata.map((v) =>
|
|
|
+ allRawY.push(y4Raw);
|
|
|
+ hasRotateData = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.LeafRootOutlineData?.second_rotate_blade?.ydata?.length > 0) {
|
|
|
+ y5Raw = this.LeafRootOutlineData.second_rotate_blade.ydata.map((v) =>
|
|
|
Number(Number(v).toFixed(4))
|
|
|
);
|
|
|
- const y3Raw = this.LeafRootOutlineData.third_blade.ydata.map((v) =>
|
|
|
+ allRawY.push(y5Raw);
|
|
|
+ hasRotateData = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.LeafRootOutlineData?.third_rotate_blade?.ydata?.length > 0) {
|
|
|
+ y6Raw = this.LeafRootOutlineData.third_rotate_blade.ydata.map((v) =>
|
|
|
Number(Number(v).toFixed(4))
|
|
|
);
|
|
|
+ allRawY.push(y6Raw);
|
|
|
+ hasRotateData = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- // 2) 根据类型决定是否处理旋转叶片数据
|
|
|
- let y4Raw, y5Raw, y6Raw;
|
|
|
- let hasRotateData = false;
|
|
|
- let allRawY = [y1Raw, y2Raw, y3Raw];
|
|
|
-
|
|
|
- // 只有在叶片轮廓拟合图中才处理旋转叶片数据
|
|
|
- if (this.type === "LeafRootOutline") {
|
|
|
- // 检查旋转叶片数据是否存在,存在则处理
|
|
|
- if (this.LeafRootOutlineData?.first_rotate_blade?.ydata?.length > 0) {
|
|
|
- y4Raw = this.LeafRootOutlineData.first_rotate_blade.ydata.map((v) =>
|
|
|
- Number(Number(v).toFixed(4))
|
|
|
- );
|
|
|
- allRawY.push(y4Raw);
|
|
|
- hasRotateData = true;
|
|
|
- }
|
|
|
-
|
|
|
- if (this.LeafRootOutlineData?.second_rotate_blade?.ydata?.length > 0) {
|
|
|
- y5Raw = this.LeafRootOutlineData.second_rotate_blade.ydata.map((v) =>
|
|
|
- Number(Number(v).toFixed(4))
|
|
|
- );
|
|
|
- allRawY.push(y5Raw);
|
|
|
- hasRotateData = true;
|
|
|
- }
|
|
|
-
|
|
|
- if (this.LeafRootOutlineData?.third_rotate_blade?.ydata?.length > 0) {
|
|
|
- y6Raw = this.LeafRootOutlineData.third_rotate_blade.ydata.map((v) =>
|
|
|
- Number(Number(v).toFixed(4))
|
|
|
- );
|
|
|
- allRawY.push(y6Raw);
|
|
|
- hasRotateData = true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 3) 计算 minValue
|
|
|
- const allMinValues = allRawY.map((arr) => Math.min(...arr));
|
|
|
- const minYAmongAll = Math.min(...allMinValues);
|
|
|
- const minValue = Number((minYAmongAll - 0.1).toFixed(4));
|
|
|
-
|
|
|
- // 4) 归一化基础Y数据
|
|
|
- const y1 = y1Raw.map((v) => Number((v - minValue).toFixed(4)));
|
|
|
- const y2 = y2Raw.map((v) => Number((v - minValue).toFixed(4)));
|
|
|
- const y3 = y3Raw.map((v) => Number((v - minValue).toFixed(4)));
|
|
|
-
|
|
|
- // 5) 根据类型决定是否归一化旋转叶片数据
|
|
|
- let y4, y5, y6;
|
|
|
- if (hasRotateData && this.type === "LeafRootOutline") {
|
|
|
- if (y4Raw) y4 = y4Raw.map((v) => Number((v - minValue).toFixed(4)));
|
|
|
- if (y5Raw) y5 = y5Raw.map((v) => Number((v - minValue).toFixed(4)));
|
|
|
- if (y6Raw) y6 = y6Raw.map((v) => Number((v - minValue).toFixed(4)));
|
|
|
- }
|
|
|
-
|
|
|
- // 6) 基于"归一化后的数据"计算等比例范围
|
|
|
- const allY = [...y1, ...y2, ...y3];
|
|
|
- if (hasRotateData && this.type === "LeafRootOutline") {
|
|
|
- if (y4) allY.push(...y4);
|
|
|
- if (y5) allY.push(...y5);
|
|
|
- if (y6) allY.push(...y6);
|
|
|
- }
|
|
|
+ // 3) 计算 minValue(已废弃,但保留变量)
|
|
|
+ const allMinValues = allRawY.map((arr) => Math.min(...arr));
|
|
|
+ const minYAmongAll = Math.min(...allMinValues);
|
|
|
+ const minValue = Number((minYAmongAll - 0.1).toFixed(4));
|
|
|
+
|
|
|
+ // 4) Y数据根据类型决定偏移方式
|
|
|
+ let y1, y2, y3;
|
|
|
+
|
|
|
+ // === 修改点 2:Y数据全部改为使用 centerYOffset 偏移 ===
|
|
|
+ if (this.type === "LeafRootOutline" || this.type === "LeafTipProfile") {
|
|
|
+ // 叶片轮廓拟合图和叶根轮廓拟合图:Y轴都进行偏移
|
|
|
+ y1 = y1Raw.map(v => Number((v - centerYOffset).toFixed(4)));
|
|
|
+ y2 = y2Raw.map(v => Number((v - centerYOffset).toFixed(4)));
|
|
|
+ y3 = y3Raw.map(v => Number((v - centerYOffset).toFixed(4)));
|
|
|
+ } else {
|
|
|
+ // 理论上不会执行,保留原始 minValue 归一化逻辑
|
|
|
+ y1 = y1Raw.map(v => Number((v - minValue).toFixed(4)));
|
|
|
+ y2 = y2Raw.map(v => Number((v - minValue).toFixed(4)));
|
|
|
+ y3 = y3Raw.map(v => Number((v - minValue).toFixed(4)));
|
|
|
+ }
|
|
|
|
|
|
- const minX = Math.min(...xRaw);
|
|
|
- const maxX = Math.max(...xRaw);
|
|
|
- const xRange = Number((maxX - minX).toFixed(4));
|
|
|
-
|
|
|
- const maxY = Math.max(...allY);
|
|
|
- const { clientWidth: w, clientHeight: h } = this.chartInstance.getDom();
|
|
|
- const aspectRatio = w / h;
|
|
|
-
|
|
|
- // 让单位像素一致:目标 yRange = xRange / (w/h)
|
|
|
- const targetYRange = Number((xRange / aspectRatio).toFixed(4));
|
|
|
-
|
|
|
- // === 重要修改:针对拟合圆的特殊处理 ===
|
|
|
- // 如果是叶根轮廓拟合图且有拟合圆,需要保持纵横比1:1
|
|
|
- let yMin = 0;
|
|
|
- let yMax = Number(Math.max(maxY, targetYRange).toFixed(4));
|
|
|
-
|
|
|
- // 检查是否有拟合圆数据
|
|
|
- const hasCircleData =
|
|
|
- this.type === "LeafTipProfile" &&
|
|
|
- (this.LeafRootOutlineData?.first_circle ||
|
|
|
- this.LeafRootOutlineData?.second_circle ||
|
|
|
- this.LeafRootOutlineData?.third_circle);
|
|
|
-
|
|
|
- // === 关键修改:计算拟合圆的真实范围 ===
|
|
|
- let circleXMin = Infinity,
|
|
|
- circleXMax = -Infinity;
|
|
|
- let circleYMin = Infinity,
|
|
|
- circleYMax = -Infinity;
|
|
|
- let circleNormalizedYMin = Infinity,
|
|
|
- circleNormalizedYMax = -Infinity;
|
|
|
-
|
|
|
- if (hasCircleData) {
|
|
|
- // 计算所有拟合圆的实际范围
|
|
|
- const circleConfigs = [
|
|
|
- { key: "first_circle" },
|
|
|
- { key: "second_circle" },
|
|
|
- { key: "third_circle" },
|
|
|
- ];
|
|
|
-
|
|
|
- circleConfigs.forEach((config) => {
|
|
|
- const circleData = this.LeafRootOutlineData[config.key];
|
|
|
- if (circleData?.xdata?.length > 0 && circleData?.ydata?.length > 0) {
|
|
|
- const thisCircleXMin = Math.min(...circleData.xdata);
|
|
|
- const thisCircleXMax = Math.max(...circleData.xdata);
|
|
|
- const thisCircleYMin = Math.min(...circleData.ydata);
|
|
|
- const thisCircleYMax = Math.max(...circleData.ydata);
|
|
|
-
|
|
|
- circleXMin = Math.min(circleXMin, thisCircleXMin);
|
|
|
- circleXMax = Math.max(circleXMax, thisCircleXMax);
|
|
|
- circleYMin = Math.min(circleYMin, thisCircleYMin);
|
|
|
- circleYMax = Math.max(circleYMax, thisCircleYMax);
|
|
|
-
|
|
|
- // 计算归一化后的Y范围
|
|
|
- const thisNormalizedYMin = thisCircleYMin - minValue;
|
|
|
- const thisNormalizedYMax = thisCircleYMax - minValue;
|
|
|
- circleNormalizedYMin = Math.min(
|
|
|
- circleNormalizedYMin,
|
|
|
- thisNormalizedYMin
|
|
|
- );
|
|
|
- circleNormalizedYMax = Math.max(
|
|
|
- circleNormalizedYMax,
|
|
|
- thisNormalizedYMax
|
|
|
- );
|
|
|
- }
|
|
|
- });
|
|
|
+ // 5) 根据类型决定是否归一化旋转叶片数据
|
|
|
+ let y4, y5, y6;
|
|
|
+ if (hasRotateData && this.type === "LeafRootOutline") {
|
|
|
+ if (y4Raw) y4 = y4Raw.map((v) => Number((v - centerYOffset).toFixed(4)));
|
|
|
+ if (y5Raw) y5 = y5Raw.map((v) => Number((v - centerYOffset).toFixed(4)));
|
|
|
+ if (y6Raw) y6 = y6Raw.map((v) => Number((v - centerYOffset).toFixed(4)));
|
|
|
+ }
|
|
|
|
|
|
- console.log("拟合圆实际范围:", {
|
|
|
- circleXMin: circleXMin.toFixed(4),
|
|
|
- circleXMax: circleXMax.toFixed(4),
|
|
|
- circleYMin: circleYMin.toFixed(4),
|
|
|
- circleYMax: circleYMax.toFixed(4),
|
|
|
- circleNormalizedYMin: circleNormalizedYMin.toFixed(4),
|
|
|
- circleNormalizedYMax: circleNormalizedYMax.toFixed(4),
|
|
|
- });
|
|
|
+ // 6) 基于"偏移后的数据"计算等比例范围
|
|
|
+ const allY = [...y1, ...y2, ...y3];
|
|
|
+ if (hasRotateData && this.type === "LeafRootOutline") {
|
|
|
+ if (y4) allY.push(...y4);
|
|
|
+ if (y5) allY.push(...y5);
|
|
|
+ if (y6) allY.push(...y6);
|
|
|
+ }
|
|
|
|
|
|
- // 对于拟合圆,我们需要保持1:1的纵横比,让圆形不被压扁
|
|
|
- // 计算拟合圆的X和Y范围
|
|
|
- const circleXRange = circleXMax - circleXMin;
|
|
|
- const circleNormalizedYRange =
|
|
|
- circleNormalizedYMax - circleNormalizedYMin;
|
|
|
-
|
|
|
- // 取X和Y范围中的较大值作为基准
|
|
|
- const baseRange = Math.max(circleXRange, circleNormalizedYRange);
|
|
|
-
|
|
|
- // 确保Y轴范围足够大以显示拟合圆
|
|
|
- yMax = Math.max(maxY, baseRange, targetYRange);
|
|
|
-
|
|
|
- console.log("拟合圆模式:强制保持1:1纵横比", {
|
|
|
- circleXRange: circleXRange.toFixed(4),
|
|
|
- circleNormalizedYRange: circleNormalizedYRange.toFixed(4),
|
|
|
- baseRange: baseRange.toFixed(4),
|
|
|
- maxY: maxY.toFixed(4),
|
|
|
- targetYRange: targetYRange.toFixed(4),
|
|
|
- finalYMax: yMax.toFixed(4),
|
|
|
+ // === 关键修改:对X数据进行偏移 ===
|
|
|
+ const xRaw = (this.type === "LeafRootOutline" || this.type === "LeafTipProfile")
|
|
|
+ ? xRawOriginal.map(v => Number((v - centerXOffset).toFixed(4))) // 两种类型都偏移
|
|
|
+ : xRawOriginal; // 其他情况保持原样
|
|
|
+
|
|
|
+ const minX = Math.min(...xRaw);
|
|
|
+ const maxX = Math.max(...xRaw);
|
|
|
+ const xRange = Number((maxX - minX).toFixed(4));
|
|
|
+
|
|
|
+ const minY = Math.min(...allY);
|
|
|
+ const maxY = Math.max(...allY);
|
|
|
+
|
|
|
+ const { clientWidth: w, clientHeight: h } = this.chartInstance.getDom();
|
|
|
+ const aspectRatio = w / h;
|
|
|
+ const targetYRange = Number((xRange / aspectRatio).toFixed(4));
|
|
|
+
|
|
|
+ // 检查是否有拟合圆数据
|
|
|
+ const hasCircleData =
|
|
|
+ this.type === "LeafTipProfile" &&
|
|
|
+ (this.LeafRootOutlineData?.first_circle ||
|
|
|
+ this.LeafRootOutlineData?.second_circle ||
|
|
|
+ this.LeafRootOutlineData?.third_circle);
|
|
|
+
|
|
|
+ // === 关键修改:计算拟合圆的真实范围 ===
|
|
|
+ let circleXMinGlobal = Infinity,
|
|
|
+ circleXMaxGlobal = -Infinity;
|
|
|
+ let circleNormalizedYMinGlobal = Infinity,
|
|
|
+ circleNormalizedYMaxGlobal = -Infinity;
|
|
|
+
|
|
|
+ // === 新增:处理拟合圆数据(只针对 LeafTipProfile)===
|
|
|
+ const circleSeries = [];
|
|
|
+ if (this.type === "LeafTipProfile") {
|
|
|
+ const circleConfigs = [
|
|
|
+ { key: "first_circle", name: "叶根1拟合圆", color: "#F44336" },
|
|
|
+ { key: "second_circle", name: "叶根2拟合圆", color: "#4CAF50" },
|
|
|
+ { key: "third_circle", name: "叶根3拟合圆", color: "#FFA726" },
|
|
|
+ ];
|
|
|
+
|
|
|
+ circleConfigs.forEach((config, index) => {
|
|
|
+ const circleData = this.LeafRootOutlineData[config.key];
|
|
|
+
|
|
|
+ if (circleData?.xdata?.length > 0 && circleData?.ydata?.length > 0) {
|
|
|
+
|
|
|
+ // === 修改点 3:拟合圆数据使用 centerYOffset 偏移 ===
|
|
|
+ const circlePoints = circleData.xdata.map((x, i) => [
|
|
|
+ Number((x - centerXOffset).toFixed(4)), // X轴使用 centerXOffset 偏移
|
|
|
+ Number((circleData.ydata[i] - centerYOffset).toFixed(4)), // Y轴使用 centerYOffset 偏移
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // === 计算偏移后的拟合圆Y值范围 ===
|
|
|
+ const normalizedYValues = circleData.ydata.map(y => y - centerYOffset);
|
|
|
+ const normalizedXValues = circleData.xdata.map(x => x - centerXOffset);
|
|
|
+
|
|
|
+ const thisNormalizedYMin = Math.min(...normalizedYValues);
|
|
|
+ const thisNormalizedYMax = Math.max(...normalizedYValues);
|
|
|
+ const thisNormalizedXMin = Math.min(...normalizedXValues);
|
|
|
+ const thisNormalizedXMax = Math.max(...normalizedXValues);
|
|
|
+
|
|
|
+ // 更新全局范围
|
|
|
+ circleXMinGlobal = Math.min(circleXMinGlobal, thisNormalizedXMin);
|
|
|
+ circleXMaxGlobal = Math.max(circleXMaxGlobal, thisNormalizedXMax);
|
|
|
+ circleNormalizedYMinGlobal = Math.min(circleNormalizedYMinGlobal, thisNormalizedYMin);
|
|
|
+ circleNormalizedYMaxGlobal = Math.max(circleNormalizedYMaxGlobal, thisNormalizedYMax);
|
|
|
+
|
|
|
+ circleSeries.push({
|
|
|
+ name: config.name,
|
|
|
+ type: "line",
|
|
|
+ showSymbol: false,
|
|
|
+ lineStyle: {
|
|
|
+ width: 2,
|
|
|
+ type: "dashed", // 虚线区分
|
|
|
+ color: config.color,
|
|
|
+ },
|
|
|
+ itemStyle: { color: config.color },
|
|
|
+ data: circlePoints,
|
|
|
+ smooth: true, // 拟合圆需要平滑
|
|
|
});
|
|
|
}
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- // === 关键修改:调整X轴显示范围,确保拟合圆完全显示 ===
|
|
|
- // 计算所有需要显示的数据的X范围(包括拟合圆)
|
|
|
- const allDisplayXMin = Math.min(
|
|
|
- minX,
|
|
|
- circleXMin !== Infinity ? circleXMin : minX
|
|
|
- );
|
|
|
- const allDisplayXMax = Math.max(
|
|
|
- maxX,
|
|
|
- circleXMax !== -Infinity ? circleXMax : maxX
|
|
|
- );
|
|
|
- const allDisplayXRange = allDisplayXMax - allDisplayXMin;
|
|
|
-
|
|
|
- // 为显示增加10%的边距
|
|
|
- const xMargin = allDisplayXRange * 0.1;
|
|
|
- const yMargin = yMax * 0.1;
|
|
|
+ // === 关键修改:调整坐标轴显示范围 - 计算实际数据边界 ===
|
|
|
+ // 计算所有需要显示的数据的X范围(包括拟合圆)
|
|
|
+ const allDisplayXMin = Math.min(
|
|
|
+ minX,
|
|
|
+ circleXMinGlobal !== Infinity ? circleXMinGlobal : minX
|
|
|
+ );
|
|
|
+ const allDisplayXMax = Math.max(
|
|
|
+ maxX,
|
|
|
+ circleXMaxGlobal !== -Infinity ? circleXMaxGlobal : maxX
|
|
|
+ );
|
|
|
+ const allDisplayXRange = allDisplayXMax - allDisplayXMin;
|
|
|
+
|
|
|
+ // 计算所有需要显示的数据的Y范围(包括拟合圆)
|
|
|
+ const allDisplayYMin = Math.min(
|
|
|
+ minY,
|
|
|
+ circleNormalizedYMinGlobal !== Infinity ? circleNormalizedYMinGlobal : minY
|
|
|
+ );
|
|
|
+ const allDisplayYMax = Math.max(
|
|
|
+ maxY,
|
|
|
+ circleNormalizedYMaxGlobal !== -Infinity ? circleNormalizedYMaxGlobal : maxY
|
|
|
+ );
|
|
|
+ const allDisplayYRange = allDisplayYMax - allDisplayYMin;
|
|
|
+
|
|
|
+ // 为显示增加10%的边距
|
|
|
+ const xMargin = allDisplayXRange * 0.1;
|
|
|
+ const yMargin = allDisplayYRange * 0.1;
|
|
|
+
|
|
|
+ // 1. 初始计算轴系边界 (包含边距)
|
|
|
+ let xAxisMin = allDisplayXMin - xMargin;
|
|
|
+ let xAxisMax = allDisplayXMax + xMargin;
|
|
|
+ let yAxisMin = allDisplayYMin - yMargin;
|
|
|
+ let yAxisMax = allDisplayYMax + yMargin;
|
|
|
+
|
|
|
+ // X轴范围处理逻辑
|
|
|
+ if (allDisplayXMin >= 0) {
|
|
|
+ xAxisMin = 0;
|
|
|
+ }
|
|
|
|
|
|
- const xAxisMin = Math.max(0, allDisplayXMin - xMargin); // X轴从0开始
|
|
|
- const xAxisMax = allDisplayXMax + xMargin;
|
|
|
- const yAxisMax = yMax + yMargin;
|
|
|
+ // 调整X轴最大值为整洁数值(只在叶片轮廓拟合图中)
|
|
|
+ if (this.type === "LeafRootOutline") {
|
|
|
+ const adjustedXAxisMax = Math.ceil(xAxisMax * 10) / 10;
|
|
|
+ xAxisMax = adjustedXAxisMax + 0.02; // 增加0.02的边距
|
|
|
+ }
|
|
|
|
|
|
- console.log("坐标轴显示范围:", {
|
|
|
- 原始X范围: `${minX.toFixed(4)}-${maxX.toFixed(4)}`,
|
|
|
- 拟合圆X范围: `${circleXMin.toFixed(4)}-${circleXMax.toFixed(4)}`,
|
|
|
- 最终X范围: `${xAxisMin.toFixed(4)}-${xAxisMax.toFixed(4)}`,
|
|
|
- Y轴范围: `0-${yAxisMax.toFixed(4)}`,
|
|
|
+ // Y轴范围处理逻辑
|
|
|
+ if (allDisplayYMin >= 0) {
|
|
|
+ yAxisMin = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log("坐标轴显示范围:", {
|
|
|
+ 最终X范围: `${xAxisMin.toFixed(4)}-${xAxisMax.toFixed(4)}`,
|
|
|
+ 最终Y范围: `${yAxisMin.toFixed(4)}-${yAxisMax.toFixed(4)}`,
|
|
|
+ 实际数据X最小值: allDisplayXMin.toFixed(4),
|
|
|
+ 实际数据Y最小值: allDisplayYMin.toFixed(4),
|
|
|
+ });
|
|
|
+
|
|
|
+ // 生成所有Y轴标签
|
|
|
+ const yLabels = Array.from(new Set(allY.map((v) => v.toFixed(1))));
|
|
|
+ const xLabels = xRaw.map((v) => v.toFixed(1));
|
|
|
+
|
|
|
+ // 准备中心点数据
|
|
|
+ const centerSeries = [];
|
|
|
+ const baseColors = ["#F44336", "#4CAF50", "#FFA726"]; // 基础叶片颜色
|
|
|
+ const testColors = ["#FF0000", "#00FF00", "#0000FF"]; // 测试颜色
|
|
|
+
|
|
|
+ // === 修改点 4:中心点数据偏移逻辑扩展到 LeafTipProfile ===
|
|
|
+ if (
|
|
|
+ this.LeafRootOutlineData?.blade_center?.xdata?.length > 0 &&
|
|
|
+ this.LeafRootOutlineData?.blade_center?.ydata?.length > 0
|
|
|
+ ) {
|
|
|
+ const centerData = this.LeafRootOutlineData.blade_center;
|
|
|
+ const isOffsetType = (this.type === "LeafRootOutline" || this.type === "LeafTipProfile");
|
|
|
+
|
|
|
+ // 为叶片1-3添加中心点
|
|
|
+ for (
|
|
|
+ let i = 0;
|
|
|
+ i < Math.min(3, centerData.xdata.length, centerData.ydata.length);
|
|
|
+ i++
|
|
|
+ ) {
|
|
|
+ const centerX = isOffsetType
|
|
|
+ ? Number((centerData.xdata[i] - centerXOffset).toFixed(4))
|
|
|
+ : Number(centerData.xdata[i].toFixed(4));
|
|
|
+
|
|
|
+ let centerY = isOffsetType
|
|
|
+ ? Number((centerData.ydata[i] - centerYOffset).toFixed(4))
|
|
|
+ : Number((centerData.ydata[i] - minValue).toFixed(4)); // 理论上不会执行
|
|
|
+
|
|
|
+ centerSeries.push({
|
|
|
+ name: this.keys === "blade_tip" ? `叶根${i + 1}中心点` : `叶片${i + 1}中心点`,
|
|
|
+ type: "scatter",
|
|
|
+ symbolSize: 10,
|
|
|
+ itemStyle: { color: baseColors[i] },
|
|
|
+ data: [[centerX, centerY]],
|
|
|
});
|
|
|
+ }
|
|
|
|
|
|
- // === 关键修改:根据X轴范围动态设置Y轴刻度(只针对叶根轮廓拟合图)===
|
|
|
- // 生成所有Y轴标签
|
|
|
- const yLabels = Array.from(new Set(allY.map((v) => v.toFixed(1))));
|
|
|
- const xLabels = xRaw.map((v) => v.toFixed(1));
|
|
|
-
|
|
|
- // 准备中心点数据 - 判断逻辑
|
|
|
- const centerSeries = [];
|
|
|
-
|
|
|
- // 定义颜色配置
|
|
|
- const baseColors = ["#F44336", "#4CAF50", "#FFA726"]; // 基础叶片颜色
|
|
|
- const testColors = ["#FF0000", "#00FF00", "#0000FF"]; // 测试颜色
|
|
|
-
|
|
|
- // 如果blade_center存在且有数据,使用实际数据
|
|
|
- if (
|
|
|
- this.LeafRootOutlineData?.blade_center?.xdata?.length > 0 &&
|
|
|
- this.LeafRootOutlineData?.blade_center?.ydata?.length > 0
|
|
|
+ // 只有在叶片轮廓拟合图且有旋转数据时,才为旋转叶片添加中心点
|
|
|
+ if (this.type === "LeafRootOutline" && hasRotateData) {
|
|
|
+ for (
|
|
|
+ let i = 3;
|
|
|
+ i < Math.min(6, centerData.xdata.length, centerData.ydata.length);
|
|
|
+ i++
|
|
|
) {
|
|
|
- const centerData = this.LeafRootOutlineData.blade_center;
|
|
|
- console.log("使用实际的blade_center数据:", centerData);
|
|
|
-
|
|
|
- // 为叶片1-3添加中心点
|
|
|
- for (
|
|
|
- let i = 0;
|
|
|
- i < Math.min(3, centerData.xdata.length, centerData.ydata.length);
|
|
|
- i++
|
|
|
- ) {
|
|
|
- centerSeries.push({
|
|
|
- name:
|
|
|
- this.keys === "blade_tip"
|
|
|
- ? `叶根${i + 1}中心点`
|
|
|
- : `叶片${i + 1}中心点`,
|
|
|
- type: "scatter",
|
|
|
- symbolSize: 10,
|
|
|
- itemStyle: { color: baseColors[i] },
|
|
|
- data: [
|
|
|
- [
|
|
|
- Number(centerData.xdata[i].toFixed(4)),
|
|
|
- Number((centerData.ydata[i] - minValue).toFixed(4)),
|
|
|
- ],
|
|
|
- ],
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- // 只有在叶片轮廓拟合图且有旋转数据时,才为旋转叶片添加中心点
|
|
|
- if (this.type === "LeafRootOutline" && hasRotateData) {
|
|
|
- for (
|
|
|
- let i = 3;
|
|
|
- i < Math.min(6, centerData.xdata.length, centerData.ydata.length);
|
|
|
- i++
|
|
|
- ) {
|
|
|
- centerSeries.push({
|
|
|
- name: `旋转叶片${i - 2}中心点`,
|
|
|
- type: "scatter",
|
|
|
- symbolSize: 10,
|
|
|
- itemStyle: { color: baseColors[i - 3] },
|
|
|
- data: [
|
|
|
- [
|
|
|
- Number(centerData.xdata[i].toFixed(4)),
|
|
|
- Number((centerData.ydata[i] - minValue).toFixed(4)),
|
|
|
- ],
|
|
|
- ],
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 如果没有blade_center,使用固定数据
|
|
|
- console.log("blade_center不存在或数据为空,使用固定测试数据");
|
|
|
- const testBladeCenter = {
|
|
|
- xdata: [1.1409272443980873, 1.1486257802831674, 1.1449090600730372],
|
|
|
- ydata: [88.97949196195555, 88.9672705736207, 88.98638594209639],
|
|
|
- };
|
|
|
-
|
|
|
- // 根据类型决定添加多少个中心点
|
|
|
- const pointCount = 3;
|
|
|
- for (let i = 0; i < pointCount; i++) {
|
|
|
- const centerY = Number(
|
|
|
- (testBladeCenter.ydata[i] - minValue).toFixed(4)
|
|
|
- );
|
|
|
- centerSeries.push({
|
|
|
- name:
|
|
|
- this.keys === "blade_tip"
|
|
|
- ? `叶根${i + 1}中心点(测试)`
|
|
|
- : `叶片${i + 1}中心点(测试)`,
|
|
|
- type: "scatter",
|
|
|
- symbolSize: 12,
|
|
|
- itemStyle: { color: testColors[i] },
|
|
|
- data: [[Number(testBladeCenter.xdata[i].toFixed(4)), centerY]],
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // === 新增:处理拟合圆数据(只针对叶根轮廓拟合图) ===
|
|
|
- const circleSeries = [];
|
|
|
- if (this.type === "LeafTipProfile") {
|
|
|
- // 定义拟合圆名称和颜色
|
|
|
- const circleConfigs = [
|
|
|
- { key: "first_circle", name: "叶根1拟合圆", color: "#F44336" },
|
|
|
- { key: "second_circle", name: "叶根2拟合圆", color: "#4CAF50" },
|
|
|
- { key: "third_circle", name: "叶根3拟合圆", color: "#FFA726" },
|
|
|
- ];
|
|
|
-
|
|
|
- // 循环处理三个拟合圆数据
|
|
|
- circleConfigs.forEach((config, index) => {
|
|
|
- const circleData = this.LeafRootOutlineData[config.key];
|
|
|
-
|
|
|
- if (circleData?.xdata?.length > 0 && circleData?.ydata?.length > 0) {
|
|
|
- console.log(`处理${config.name}数据:`, circleData);
|
|
|
-
|
|
|
- // 处理拟合圆数据点 - 保持原始比例
|
|
|
- const circlePoints = circleData.xdata.map((x, i) => [
|
|
|
- Number(x.toFixed(4)),
|
|
|
- Number((circleData.ydata[i] - minValue).toFixed(4)),
|
|
|
- ]);
|
|
|
-
|
|
|
- // 计算拟合圆的范围,用于检查是否保持圆形
|
|
|
- const circleXMin = Math.min(...circleData.xdata);
|
|
|
- const circleXMax = Math.max(...circleData.xdata);
|
|
|
- const circleYMin = Math.min(...circleData.ydata);
|
|
|
- const circleYMax = Math.max(...circleData.ydata);
|
|
|
- const circleXRange = circleXMax - circleXMin;
|
|
|
- const circleYRange = circleYMax - circleYMin;
|
|
|
-
|
|
|
- console.log(
|
|
|
- `${config.name}范围: X(${circleXRange.toFixed(
|
|
|
- 4
|
|
|
- )}), Y(${circleYRange.toFixed(4)})`
|
|
|
- );
|
|
|
-
|
|
|
- circleSeries.push({
|
|
|
- name: config.name,
|
|
|
- type: "line",
|
|
|
- showSymbol: false,
|
|
|
- lineStyle: {
|
|
|
- width: 2,
|
|
|
- type: "dashed", // 虚线区分
|
|
|
- color: config.color,
|
|
|
- },
|
|
|
- itemStyle: { color: config.color },
|
|
|
- data: circlePoints,
|
|
|
- smooth: true, // 拟合圆需要平滑
|
|
|
- });
|
|
|
- } else {
|
|
|
- console.log(`${config.name}数据不存在或为空`);
|
|
|
- }
|
|
|
+ const centerX = Number((centerData.xdata[i] - centerXOffset).toFixed(4));
|
|
|
+ const centerY = Number((centerData.ydata[i] - centerYOffset).toFixed(4));
|
|
|
+
|
|
|
+ centerSeries.push({
|
|
|
+ name: `旋转叶片${i - 2}中心点`,
|
|
|
+ type: "scatter",
|
|
|
+ symbolSize: 10,
|
|
|
+ itemStyle: { color: baseColors[i - 3] },
|
|
|
+ data: [[centerX, centerY]],
|
|
|
});
|
|
|
}
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 测试数据逻辑...
|
|
|
+ const testBladeCenter = {
|
|
|
+ xdata: [1.1409272443980873, 1.1486257802831674, 1.1449090600730372],
|
|
|
+ ydata: [88.97949196195555, 88.9672705736207, 88.98638594209639],
|
|
|
+ };
|
|
|
+ const pointCount = 3;
|
|
|
+ const isOffsetType = (this.type === "LeafRootOutline" || this.type === "LeafTipProfile");
|
|
|
+
|
|
|
+ for (let i = 0; i < pointCount; i++) {
|
|
|
+ const centerX = isOffsetType
|
|
|
+ ? Number((testBladeCenter.xdata[i] - centerXOffset).toFixed(4))
|
|
|
+ : Number(testBladeCenter.xdata[i].toFixed(4));
|
|
|
+
|
|
|
+ let centerY = isOffsetType
|
|
|
+ ? Number((testBladeCenter.ydata[i] - centerYOffset).toFixed(4))
|
|
|
+ : Number((testBladeCenter.ydata[i] - minValue).toFixed(4));
|
|
|
+
|
|
|
+ centerSeries.push({
|
|
|
+ name: this.keys === "blade_tip" ? `叶根${i + 1}中心点(测试)` : `叶片${i + 1}中心点(测试)`,
|
|
|
+ type: "scatter",
|
|
|
+ symbolSize: 12,
|
|
|
+ itemStyle: { color: testColors[i] },
|
|
|
+ data: [[centerX, centerY]],
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- // 准备所有叶片系列
|
|
|
- const series = [
|
|
|
- // 基础叶片1-3轮廓
|
|
|
- {
|
|
|
- name: this.keys === "blade_tip" ? "叶根1轮廓" : "叶片1轮廓",
|
|
|
- type: "line",
|
|
|
- showSymbol: false,
|
|
|
- lineStyle: { width: 2, type: "solid" },
|
|
|
- itemStyle: { color: "#F44336" },
|
|
|
- data: xRaw.map((x, i) => [x, y1[i]]),
|
|
|
- smooth: true,
|
|
|
- },
|
|
|
- {
|
|
|
- name: this.keys === "blade_tip" ? "叶根2轮廓" : "叶片2轮廓",
|
|
|
- type: "line",
|
|
|
- showSymbol: false,
|
|
|
- lineStyle: { width: 2, type: "solid" },
|
|
|
- itemStyle: { color: "#4CAF50" },
|
|
|
- data: xRaw.map((x, i) => [x, y2[i]]),
|
|
|
- smooth: true,
|
|
|
- },
|
|
|
- {
|
|
|
- name: this.keys === "blade_tip" ? "叶根3轮廓" : "叶片3轮廓",
|
|
|
- type: "line",
|
|
|
- showSymbol: false,
|
|
|
- lineStyle: { width: 2, type: "solid" },
|
|
|
- itemStyle: { color: "#FFA726" },
|
|
|
- data: xRaw.map((x, i) => [x, y3[i]]),
|
|
|
- smooth: true,
|
|
|
- },
|
|
|
- ];
|
|
|
-
|
|
|
- // 动态图例数据
|
|
|
- const legendData = [
|
|
|
- this.keys === "blade_tip" ? "叶根1轮廓" : "叶片1轮廓",
|
|
|
- this.keys === "blade_tip" ? "叶根2轮廓" : "叶片2轮廓",
|
|
|
- this.keys === "blade_tip" ? "叶根3轮廓" : "叶片3轮廓",
|
|
|
- ];
|
|
|
-
|
|
|
- // 动态添加旋转叶片系列(仅在叶片轮廓拟合图中)
|
|
|
- if (this.type === "LeafRootOutline" && hasRotateData) {
|
|
|
- // 添加旋转叶片4-6轮廓
|
|
|
- const rotateSeries = [];
|
|
|
-
|
|
|
- if (y4) {
|
|
|
- rotateSeries.push({
|
|
|
- name: "旋转叶片1轮廓",
|
|
|
- type: "line",
|
|
|
- showSymbol: false,
|
|
|
- lineStyle: { width: 2, type: "dashed" }, // 虚线区分
|
|
|
- itemStyle: { color: "#F44336" },
|
|
|
- data: xRaw.map((x, i) => [x, y4[i]]),
|
|
|
- smooth: true,
|
|
|
- });
|
|
|
- legendData.push("旋转叶片1轮廓");
|
|
|
- }
|
|
|
-
|
|
|
- if (y5) {
|
|
|
- rotateSeries.push({
|
|
|
- name: "旋转叶片2轮廓",
|
|
|
- type: "line",
|
|
|
- showSymbol: false,
|
|
|
- lineStyle: { width: 2, type: "dashed" },
|
|
|
- itemStyle: { color: "#4CAF50" },
|
|
|
- data: xRaw.map((x, i) => [x, y5[i]]),
|
|
|
- smooth: true,
|
|
|
- });
|
|
|
- legendData.push("旋转叶片2轮廓");
|
|
|
- }
|
|
|
-
|
|
|
- if (y6) {
|
|
|
- rotateSeries.push({
|
|
|
- name: "旋转叶片3轮廓",
|
|
|
- type: "line",
|
|
|
- showSymbol: false,
|
|
|
- lineStyle: { width: 2, type: "dashed" },
|
|
|
- itemStyle: { color: "#FFA726" },
|
|
|
- data: xRaw.map((x, i) => [x, y6[i]]),
|
|
|
- smooth: true,
|
|
|
- });
|
|
|
- legendData.push("旋转叶片3轮廓");
|
|
|
- }
|
|
|
-
|
|
|
- // 将旋转叶片系列添加到主系列中
|
|
|
- series.push(...rotateSeries);
|
|
|
- }
|
|
|
-
|
|
|
- // 添加拟合圆系列(仅在叶根轮廓拟合图中)
|
|
|
- if (this.type === "LeafTipProfile" && circleSeries.length > 0) {
|
|
|
- series.push(...circleSeries);
|
|
|
- // 将拟合圆添加到图例
|
|
|
- circleSeries.forEach((circle) => {
|
|
|
- legendData.push(circle.name);
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- // 添加中心点系列
|
|
|
- series.push(...centerSeries);
|
|
|
-
|
|
|
- // 动态设置颜色和图例
|
|
|
- let colors = ["#F44336", "#4CAF50", "#FFA726"];
|
|
|
-
|
|
|
- if (this.type === "LeafRootOutline" && hasRotateData) {
|
|
|
- colors = [...colors, "#F44336", "#4CAF50", "#FFA726"];
|
|
|
- }
|
|
|
-
|
|
|
- if (this.type === "LeafTipProfile" && circleSeries.length > 0) {
|
|
|
- // 为叶根轮廓拟合图添加拟合圆的颜色
|
|
|
- colors = [...colors, "#F44336", "#4CAF50", "#FFA726"];
|
|
|
- }
|
|
|
-
|
|
|
- // === 关键修改:为叶根轮廓拟合图创建规则的Y轴刻度 ===
|
|
|
- let yAxisConfig;
|
|
|
- if (this.type === "LeafTipProfile") {
|
|
|
- // 对于叶根轮廓拟合图,创建规则的Y轴刻度
|
|
|
- // 计算需要多少个0.2的间隔来覆盖Y轴范围
|
|
|
- const interval = 0.2; // 固定间隔0.2
|
|
|
- const tickCount = Math.ceil(yAxisMax / interval);
|
|
|
-
|
|
|
- // 生成刻度值数组:0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, ...
|
|
|
- const ticks = [];
|
|
|
- for (let i = 0; i <= tickCount; i++) {
|
|
|
- ticks.push(i * interval);
|
|
|
- }
|
|
|
-
|
|
|
- // 调整Y轴最大值,使其是0.2的整数倍
|
|
|
- const adjustedYAxisMax = Math.ceil(yAxisMax / interval) * interval;
|
|
|
+ // 准备所有叶片系列
|
|
|
+ const series = [
|
|
|
+ {
|
|
|
+ name: this.keys === "blade_tip" ? "叶根1轮廓" : "叶片1轮廓",
|
|
|
+ type: "line",
|
|
|
+ showSymbol: false,
|
|
|
+ lineStyle: { width: 2, type: "solid" },
|
|
|
+ itemStyle: { color: "#F44336" },
|
|
|
+ data: xRaw.map((x, i) => [x, y1[i]]),
|
|
|
+ smooth: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: this.keys === "blade_tip" ? "叶根2轮廓" : "叶片2轮廓",
|
|
|
+ type: "line",
|
|
|
+ showSymbol: false,
|
|
|
+ lineStyle: { width: 2, type: "solid" },
|
|
|
+ itemStyle: { color: "#4CAF50" },
|
|
|
+ data: xRaw.map((x, i) => [x, y2[i]]),
|
|
|
+ smooth: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: this.keys === "blade_tip" ? "叶根3轮廓" : "叶片3轮廓",
|
|
|
+ type: "line",
|
|
|
+ showSymbol: false,
|
|
|
+ lineStyle: { width: 2, type: "solid" },
|
|
|
+ itemStyle: { color: "#FFA726" },
|
|
|
+ data: xRaw.map((x, i) => [x, y3[i]]),
|
|
|
+ smooth: true,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ const legendData = [
|
|
|
+ this.keys === "blade_tip" ? "叶根1轮廓" : "叶片1轮廓",
|
|
|
+ this.keys === "blade_tip" ? "叶根2轮廓" : "叶片2轮廓",
|
|
|
+ this.keys === "blade_tip" ? "叶根3轮廓" : "叶片3轮廓",
|
|
|
+ ];
|
|
|
+
|
|
|
+ if (this.type === "LeafRootOutline" && hasRotateData) {
|
|
|
+ const rotateSeries = [];
|
|
|
+ if (y4) {
|
|
|
+ rotateSeries.push({
|
|
|
+ name: "旋转叶片1轮廓",
|
|
|
+ type: "line",
|
|
|
+ showSymbol: false,
|
|
|
+ lineStyle: { width: 2, type: "dashed" },
|
|
|
+ itemStyle: { color: "#F44336" },
|
|
|
+ data: xRaw.map((x, i) => [x, y4[i]]),
|
|
|
+ smooth: true,
|
|
|
+ });
|
|
|
+ legendData.push("旋转叶片1轮廓");
|
|
|
+ }
|
|
|
+ if (y5) {
|
|
|
+ rotateSeries.push({
|
|
|
+ name: "旋转叶片2轮廓",
|
|
|
+ type: "line",
|
|
|
+ showSymbol: false,
|
|
|
+ lineStyle: { width: 2, type: "dashed" },
|
|
|
+ itemStyle: { color: "#4CAF50" },
|
|
|
+ data: xRaw.map((x, i) => [x, y5[i]]),
|
|
|
+ smooth: true,
|
|
|
+ });
|
|
|
+ legendData.push("旋转叶片2轮廓");
|
|
|
+ }
|
|
|
+ if (y6) {
|
|
|
+ rotateSeries.push({
|
|
|
+ name: "旋转叶片3轮廓",
|
|
|
+ type: "line",
|
|
|
+ showSymbol: false,
|
|
|
+ lineStyle: { width: 2, type: "dashed" },
|
|
|
+ itemStyle: { color: "#FFA726" },
|
|
|
+ data: xRaw.map((x, i) => [x, y6[i]]),
|
|
|
+ smooth: true,
|
|
|
+ });
|
|
|
+ legendData.push("旋转叶片3轮廓");
|
|
|
+ }
|
|
|
+ series.push(...rotateSeries);
|
|
|
+ }
|
|
|
|
|
|
- console.log("叶根轮廓拟合图 - 规则Y轴刻度:", {
|
|
|
- 原始Y轴最大值: yAxisMax.toFixed(4),
|
|
|
- 调整后Y轴最大值: adjustedYAxisMax.toFixed(4),
|
|
|
- 刻度间隔: interval,
|
|
|
- 刻度数量: tickCount + 1,
|
|
|
- 刻度值: ticks.map((v) => v.toFixed(1)),
|
|
|
- });
|
|
|
+ if (this.type === "LeafTipProfile" && circleSeries.length > 0) {
|
|
|
+ series.push(...circleSeries);
|
|
|
+ circleSeries.forEach((circle) => {
|
|
|
+ legendData.push(circle.name);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ series.push(...centerSeries);
|
|
|
|
|
|
- yAxisConfig = {
|
|
|
- type: "value",
|
|
|
- name: "距离(m)",
|
|
|
- nameLocation: "middle",
|
|
|
- nameTextStyle: { fontWeight: "bold", padding: [0, 0, 40, 0] },
|
|
|
- min: 0,
|
|
|
- max: adjustedYAxisMax,
|
|
|
- interval: interval,
|
|
|
- axisLabel: {
|
|
|
- formatter: function (value) {
|
|
|
- // 显示小数点后1位
|
|
|
- return value.toFixed(1);
|
|
|
- },
|
|
|
- },
|
|
|
- };
|
|
|
- } else {
|
|
|
- // 其他类型图表保持原来的逻辑
|
|
|
- yAxisConfig = {
|
|
|
- type: "value",
|
|
|
- name: "距离(m)",
|
|
|
- nameLocation: "middle",
|
|
|
- nameTextStyle: { fontWeight: "bold", padding: [0, 0, 40, 0] },
|
|
|
- min: yMin,
|
|
|
- max: yAxisMax,
|
|
|
- axisLabel: {
|
|
|
- formatter: function (value) {
|
|
|
- return value.toFixed(1);
|
|
|
- },
|
|
|
- },
|
|
|
- };
|
|
|
- }
|
|
|
+ let colors = ["#F44336", "#4CAF50", "#FFA726"];
|
|
|
+ if ((this.type === "LeafRootOutline" && hasRotateData) || (this.type === "LeafTipProfile" && circleSeries.length > 0)) {
|
|
|
+ colors = [...colors, "#F44336", "#4CAF50", "#FFA726"];
|
|
|
+ }
|
|
|
|
|
|
- const option = {
|
|
|
- grid: { left: 80, right: 40, top: 40, bottom: 60 },
|
|
|
- color: colors,
|
|
|
- toolbox: {
|
|
|
- feature: {
|
|
|
- dataZoom: { yAxisIndex: "none" },
|
|
|
- restore: {},
|
|
|
- saveAsImage: {},
|
|
|
- myCustomTool1: {
|
|
|
- show: true,
|
|
|
- title: "标注",
|
|
|
- icon: `image://${new URL(
|
|
|
- "@/assets/analyse/mark.png",
|
|
|
- import.meta.url
|
|
|
- )}`,
|
|
|
- onclick: () => this.WhetherToDisplay(),
|
|
|
- },
|
|
|
- myCustomTool2: {
|
|
|
- show: true,
|
|
|
- title: "全屏",
|
|
|
- icon: `image://${new URL(
|
|
|
- "@/assets/analyse/fullScreen.png",
|
|
|
- import.meta.url
|
|
|
- )}`,
|
|
|
- onclick: () => this.fullScreen(),
|
|
|
- },
|
|
|
- myCustomTool3: {
|
|
|
- show: true,
|
|
|
- title: "退出全屏",
|
|
|
- icon: `image://${new URL(
|
|
|
- "@/assets/analyse/exitFullScreen.png",
|
|
|
- import.meta.url
|
|
|
- )}`,
|
|
|
- onclick: () => this.exitFullScreen(),
|
|
|
- },
|
|
|
- },
|
|
|
- },
|
|
|
- xAxis: {
|
|
|
- type: "value",
|
|
|
- name: "距离(m)",
|
|
|
- nameLocation: "middle",
|
|
|
- nameTextStyle: { fontWeight: "bold", padding: [20, 0, 0, 0] },
|
|
|
- min: xAxisMin, // 使用调整后的最小值
|
|
|
- max: xAxisMax, // 使用调整后的最大值
|
|
|
- splitNumber: 15, // 保持原来的15个刻度
|
|
|
- data: [...new Set(xLabels)],
|
|
|
- splitLine: { show: true, lineStyle: { color: "rgb(220,220,220)" } },
|
|
|
+ // === Y轴配置 ===
|
|
|
+ const yAxisConfig = {
|
|
|
+ type: "value",
|
|
|
+ name: "距离(m)",
|
|
|
+ nameLocation: "middle",
|
|
|
+ nameTextStyle: { fontWeight: "bold", padding: [0, 0, 40, 0] },
|
|
|
+ min: yAxisMin,
|
|
|
+ max: yAxisMax,
|
|
|
+ interval: 0.2,
|
|
|
+ axisLabel: {
|
|
|
+ formatter: function (value) {
|
|
|
+ return value.toFixed(1);
|
|
|
+ },
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ const option = {
|
|
|
+ grid: { left: 80, right: 40, top: 40, bottom: 60 },
|
|
|
+ color: colors,
|
|
|
+ toolbox: {
|
|
|
+ feature: {
|
|
|
+ dataZoom: { yAxisIndex: "none" },
|
|
|
+ restore: {},
|
|
|
+ saveAsImage: {},
|
|
|
+ myCustomTool1: {
|
|
|
+ show: true,
|
|
|
+ title: "标注",
|
|
|
+ icon: `image://${new URL("@/assets/analyse/mark.png", import.meta.url)}`,
|
|
|
+ onclick: () => this.WhetherToDisplay(),
|
|
|
},
|
|
|
- yAxis: yAxisConfig,
|
|
|
- tooltip: {
|
|
|
- trigger: "axis",
|
|
|
- valueFormatter: (v) => (typeof v === "number" ? v.toFixed(4) : v),
|
|
|
- position: (pt) => [pt[0], "10%"],
|
|
|
- confine: false, // 允许tooltip超出图表区域
|
|
|
- appendToBody: true, // 将tooltip附加到body,避免被父容器遮挡
|
|
|
+ myCustomTool2: {
|
|
|
+ show: true,
|
|
|
+ title: "全屏",
|
|
|
+ icon: `image://${new URL("@/assets/analyse/fullScreen.png", import.meta.url)}`,
|
|
|
+ onclick: () => this.fullScreen(),
|
|
|
},
|
|
|
- legend: {
|
|
|
- data: legendData,
|
|
|
- left: 0,
|
|
|
- top: 0,
|
|
|
+ myCustomTool3: {
|
|
|
+ show: true,
|
|
|
+ title: "退出全屏",
|
|
|
+ icon: `image://${new URL("@/assets/analyse/exitFullScreen.png", import.meta.url)}`,
|
|
|
+ onclick: () => this.exitFullScreen(),
|
|
|
},
|
|
|
- series: series,
|
|
|
- };
|
|
|
-
|
|
|
- this.chartInstance.setOption(option, true);
|
|
|
-
|
|
|
- // ======== 动态高度计算 ========
|
|
|
- this.$nextTick(() => {
|
|
|
- const maxYLabelLen = [...new Set(yLabels)].length;
|
|
|
- const chartDom = this.$refs[`chart${this.keys}`];
|
|
|
- const chartWidth = chartDom.clientWidth;
|
|
|
- const grid =
|
|
|
- option.grid && option.grid[0]
|
|
|
- ? option.grid[0]
|
|
|
- : { left: 0, right: 0 };
|
|
|
- const xAxisWidth =
|
|
|
- chartWidth - (parseInt(grid.left) || 0) - (parseInt(grid.right) || 0);
|
|
|
- const xAxisWidthPerLabel = xAxisWidth / 15;
|
|
|
-
|
|
|
- // 默认高度
|
|
|
- let baseHeight = 400;
|
|
|
-
|
|
|
- // 如果 y 轴的刻度文本比 x 轴长,则增加高度
|
|
|
- if (maxYLabelLen > [...new Set(xLabels)].length) {
|
|
|
- baseHeight = maxYLabelLen * xAxisWidthPerLabel;
|
|
|
- } else if (maxYLabelLen < [...new Set(xLabels)].length) {
|
|
|
- const xAxisWidthPerLabelAll =
|
|
|
- xAxisWidth / [...new Set(xLabels)].length;
|
|
|
- baseHeight = maxYLabelLen * xAxisWidthPerLabelAll;
|
|
|
+ },
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: "value",
|
|
|
+ name: "距离(m)",
|
|
|
+ nameLocation: "middle",
|
|
|
+ nameTextStyle: { fontWeight: "bold", padding: [20, 0, 0, 0] },
|
|
|
+ min: xAxisMin,
|
|
|
+ max: xAxisMax,
|
|
|
+ splitNumber: 15,
|
|
|
+ data: [...new Set(xLabels)],
|
|
|
+ splitLine: { show: true, lineStyle: { color: "rgb(220,220,220)" } },
|
|
|
+ axisLabel: {
|
|
|
+ formatter: function (value) {
|
|
|
+ return value.toFixed(1);
|
|
|
}
|
|
|
+ },
|
|
|
+ interval: 0.2,
|
|
|
+ },
|
|
|
+ yAxis: yAxisConfig,
|
|
|
+ tooltip: {
|
|
|
+ trigger: "axis",
|
|
|
+ valueFormatter: (v) => (typeof v === "number" ? v.toFixed(4) : v),
|
|
|
+ position: (pt) => [pt[0], "10%"],
|
|
|
+ confine: false,
|
|
|
+ appendToBody: true,
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ data: legendData,
|
|
|
+ left: 0,
|
|
|
+ top: 0,
|
|
|
+ },
|
|
|
+ series: series,
|
|
|
+ };
|
|
|
+
|
|
|
+ this.chartInstance.setOption(option, true);
|
|
|
+
|
|
|
+ // ======== 动态高度计算 ========
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const maxYLabelLen = [...new Set(yLabels)].length;
|
|
|
+ const chartDom = this.$refs[`chart${this.keys}`];
|
|
|
+ const chartWidth = chartDom.clientWidth;
|
|
|
+ const grid = option.grid && option.grid[0] ? option.grid[0] : { left: 0, right: 0 };
|
|
|
+ const xAxisWidth = chartWidth - (parseInt(grid.left) || 0) - (parseInt(grid.right) || 0);
|
|
|
+ const xAxisWidthPerLabel = xAxisWidth / 15;
|
|
|
+
|
|
|
+ let baseHeight = 400;
|
|
|
+
|
|
|
+ if (maxYLabelLen > [...new Set(xLabels)].length) {
|
|
|
+ baseHeight = maxYLabelLen * xAxisWidthPerLabel;
|
|
|
+ } else if (maxYLabelLen < [...new Set(xLabels)].length) {
|
|
|
+ const xAxisWidthPerLabelAll = xAxisWidth / [...new Set(xLabels)].length;
|
|
|
+ baseHeight = maxYLabelLen * xAxisWidthPerLabelAll;
|
|
|
+ }
|
|
|
|
|
|
- // 如果是拟合圆模式,需要保持1:1的比例
|
|
|
- if (hasCircleData) {
|
|
|
- // 根据X和Y轴范围的比例计算合适的高度,保持1:1比例
|
|
|
- const xDisplayRange = xAxisMax - xAxisMin;
|
|
|
- const yDisplayRange = yAxisMax - yMin;
|
|
|
- const rangeRatio = xDisplayRange / yDisplayRange;
|
|
|
-
|
|
|
- // 保持1:1比例所需的高度
|
|
|
- const heightFor1to1 = chartWidth / rangeRatio;
|
|
|
- baseHeight = Math.max(baseHeight, heightFor1to1);
|
|
|
-
|
|
|
- console.log("拟合圆模式:调整高度以保持1:1比例", {
|
|
|
- xDisplayRange: xDisplayRange.toFixed(4),
|
|
|
- yDisplayRange: yDisplayRange.toFixed(4),
|
|
|
- rangeRatio: rangeRatio.toFixed(4),
|
|
|
- chartWidth,
|
|
|
- heightFor1to1: heightFor1to1.toFixed(0),
|
|
|
- finalHeight: baseHeight,
|
|
|
- });
|
|
|
- }
|
|
|
+ // 拟合圆模式保持1:1比例
|
|
|
+ if (hasCircleData) {
|
|
|
+ const xDisplayRange = xAxisMax - xAxisMin;
|
|
|
+ const yDisplayRange = yAxisMax - yAxisMin;
|
|
|
+ const rangeRatio = xDisplayRange / yDisplayRange;
|
|
|
+ const heightFor1to1 = chartWidth / rangeRatio;
|
|
|
+ baseHeight = Math.max(baseHeight, heightFor1to1);
|
|
|
+ }
|
|
|
|
|
|
- chartDom.style.height = baseHeight + "px";
|
|
|
- console.log(
|
|
|
- "每个刻度线的距离",
|
|
|
- xAxisWidthPerLabel,
|
|
|
- `chart${this.keys}`,
|
|
|
- baseHeight,
|
|
|
- "当前类型:",
|
|
|
- this.type,
|
|
|
- "渲染系列数量:",
|
|
|
- legendData.length,
|
|
|
- "X范围:",
|
|
|
- xAxisMin.toFixed(2),
|
|
|
- "-",
|
|
|
- xAxisMax.toFixed(2),
|
|
|
- "Y范围:",
|
|
|
- yMin.toFixed(2),
|
|
|
- "-",
|
|
|
- yAxisMax.toFixed(2)
|
|
|
- );
|
|
|
-
|
|
|
- // 重新调整 ECharts 大小
|
|
|
- this.chartInstance.resize();
|
|
|
- });
|
|
|
+ chartDom.style.height = baseHeight + "px";
|
|
|
+ this.chartInstance.resize();
|
|
|
+ });
|
|
|
|
|
|
- // 防止重复绑定 resize 事件
|
|
|
- if (this._onResizeEqualScale) {
|
|
|
- window.removeEventListener("resize", this._onResizeEqualScale);
|
|
|
- }
|
|
|
- this._onResizeEqualScale = () => this.updateChart();
|
|
|
- window.addEventListener("resize", this._onResizeEqualScale);
|
|
|
- },
|
|
|
+ if (this._onResizeEqualScale) {
|
|
|
+ window.removeEventListener("resize", this._onResizeEqualScale);
|
|
|
+ }
|
|
|
+ this._onResizeEqualScale = () => this.updateChart();
|
|
|
+ window.addEventListener("resize", this._onResizeEqualScale);
|
|
|
+},
|
|
|
// 标注是否显示
|
|
|
WhetherToDisplay() {
|
|
|
// 切换显示状态
|