Переглянути джерело

试验-保存
1、添加土工击试验曲线配置

LHB 1 місяць тому
батько
коміт
3f7dd0dbf5

+ 9 - 5
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -5058,7 +5058,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
      */
     public void preCalc(FormData fd, TableElementConverter tec) {
         try {
-            if(fd.getCode().equals("m_20230410104313_1645256088125177856:key_19")){
+            if(fd.getCode().equals("m_20230410104301_1645256037877415936:key_27")){
                 System.out.println();
             }
             Formula formula = fd.getFormula();
@@ -5111,21 +5111,25 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                         //图片存放路径
 //                        String filePath = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
 //                        String listPdf = filePath + "/pdf/" + id + ".png";
-                        String listPdf = "C:\\upload\\pdf\\" + id + ".png";
+                        String listPdf = "C:\\upload\\pdf\\" + id + ".jpg";
 
                         //土界含水率试验检测记录表  TODO 存在两张类似的表但是init_table_name 不同
                         if(fd.getCode().contains("m_20230410104313_1645256088125177856")){
                             // 创建图表生成器
                             SoilTestChart generator = new SoilTestChart(points);
                             // 生成图表并保存为图片(不显示GUI窗口)
-                            generator.generateChart(listPdf, 400, 550);
-                        }else if (false){
+                            generator.generateChart(listPdf, 330, 360);
+                        }else if (fd.getCode().contains("m_20230410104301_1645256037877415936")){
+                            // 创建图表生成器
+                            SmoothCurveChartToImage generator = new SmoothCurveChartToImage(points, "含水率(%)", "干密度(g/cm³)", "最大干密度曲线");
 
+                            // 生成图表并保存为图片
+                            generator.generateChart(listPdf,800,185);
                         }
 
                         File tabPDF = ResourceUtil.getFile(listPdf);
                         //上传至oss
-                        BladeFile bladeFile = this.newIOSSClient.uploadFile(id + ".png", listPdf);
+                        BladeFile bladeFile = this.newIOSSClient.uploadFile(id + ".jpg", listPdf);
                         if (tabPDF.exists()) {
                             tabPDF.delete();
                         }

+ 278 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/SmoothCurveChartToImage.java

@@ -0,0 +1,278 @@
+package org.springblade.manager.utils;
+
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.ChartUtils;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.annotations.XYLineAnnotation;
+import org.jfree.chart.axis.NumberAxis;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.renderer.xy.XYSplineRenderer;
+import org.jfree.chart.ui.RectangleInsets;
+import org.jfree.data.xy.XYSeries;
+import org.jfree.data.xy.XYSeriesCollection;
+
+import java.awt.*;
+import java.awt.geom.Ellipse2D;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * 最大干密度曲线生成器
+ */
+public class SmoothCurveChartToImage {
+    private double[][] dataPoints;
+    private String xAxisLabel;
+    private String yAxisLabel;
+    private String chartTitle;
+
+    /**
+     * 构造函数
+     * @param dataPoints 二维数组,每行表示一个点 [x, y]
+     * @param xAxisLabel X轴标签
+     * @param yAxisLabel Y轴标签
+     * @param chartTitle 图表标题
+     */
+    public SmoothCurveChartToImage(double[][] dataPoints, String xAxisLabel, String yAxisLabel, String chartTitle) {
+        this.dataPoints = dataPoints;
+        this.xAxisLabel = xAxisLabel;
+        this.yAxisLabel = yAxisLabel;
+        this.chartTitle = chartTitle;
+    }
+
+    /**
+     * 生成图表并保存为图片
+     * @param filePath 文件路径
+     * @param width 图片宽度
+     * @param height 图片高度
+     */
+    public void generateChart(String filePath, int width, int height) {
+        // 创建数据集
+        XYSeries series = new XYSeries("数据点");
+
+        // 添加数据点
+        for (double[] point : dataPoints) {
+            if (point.length >= 2) {
+                series.add(point[0], point[1]);
+            }
+        }
+
+        XYSeriesCollection dataset = new XYSeriesCollection(series);
+
+        // 创建图表,不显示图例
+        JFreeChart chart = ChartFactory.createXYLineChart(
+                chartTitle,
+                xAxisLabel,
+                yAxisLabel,
+                dataset,
+                PlotOrientation.VERTICAL,
+                false,
+                true,
+                false
+        );
+
+        // 设置中文字体,防止乱码
+        chart.getTitle().setFont(new Font("微软雅黑", Font.BOLD, 16));
+
+        // 获取图表区域
+        XYPlot plot = chart.getXYPlot();
+
+        // 设置X轴和Y轴标签字体
+        NumberAxis domainAxis = (NumberAxis) plot.getDomainAxis();
+        domainAxis.setLabelFont(new Font("微软雅黑", Font.PLAIN, 12));
+        domainAxis.setTickLabelFont(new Font("微软雅黑", Font.PLAIN, 10));
+
+        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
+        rangeAxis.setLabelFont(new Font("微软雅黑", Font.PLAIN, 12));
+        rangeAxis.setTickLabelFont(new Font("微软雅黑", Font.PLAIN, 10));
+
+        // 调整Y轴范围,不从0开始
+        double minY = series.getMinY();
+        double maxY = series.getMaxY();
+        double range = maxY - minY;
+
+        // 设置Y轴范围,从最小值下方10%开始,到最大值上方10%结束
+        double lowerBound = minY - range * 0.1;
+        double upperBound = maxY + range * 0.1;
+
+        rangeAxis.setRange(lowerBound, upperBound);
+
+        // 调整X轴范围,使其更加合适
+        double minX = series.getMinX();
+        double maxX = series.getMaxX();
+        double xRange = maxX - minX;
+        domainAxis.setRange(minX - xRange * 0.1, maxX + xRange * 0.1);
+
+        // 使用样条渲染器创建平滑曲线
+        XYSplineRenderer renderer = new XYSplineRenderer();
+        renderer.setSeriesPaint(0, Color.BLUE);
+        renderer.setSeriesStroke(0, new BasicStroke(2.0f));
+        // 显示数据点
+        renderer.setSeriesShapesVisible(0, true);
+        // 设置数据点的形状为圆形
+        renderer.setSeriesShape(0, new Ellipse2D.Double(-3, -3, 6, 6));
+
+        plot.setRenderer(renderer);
+
+        // 设置图表背景和网格线
+        plot.setBackgroundPaint(Color.LIGHT_GRAY);
+        plot.setDomainGridlinePaint(Color.WHITE);
+        plot.setRangeGridlinePaint(Color.WHITE);
+        plot.setDomainGridlinesVisible(true);
+        plot.setRangeGridlinesVisible(true);
+
+        // 计算曲线上的峰值点
+        double[] peakPoint = findPeakOnCurve(dataset);
+        double peakX = peakPoint[0];
+        double peakY = peakPoint[1];
+
+        System.out.println("找到峰值点: (" + peakX + ", " + peakY + ")");
+
+        // 创建一个新的系列只包含峰值点
+        XYSeries peakSeries = new XYSeries("峰值点");
+        peakSeries.add(peakX, peakY);
+        dataset.addSeries(peakSeries);
+
+        // 为峰值点系列设置不同的渲染属性
+        renderer.setSeriesPaint(1, Color.RED);
+        renderer.setSeriesShapesVisible(1, true);
+        renderer.setSeriesShape(1, new Ellipse2D.Double(-3, -3, 6, 6));
+        renderer.setSeriesLinesVisible(1, false); // 不连接线
+
+        // 添加垂直线到X轴
+        XYLineAnnotation xLine = new XYLineAnnotation(
+                peakX, peakY, peakX, plot.getRangeAxis().getLowerBound(),
+                new BasicStroke(1.5f), Color.RED);
+        plot.addAnnotation(xLine);
+
+        // 添加垂直线到Y轴
+        XYLineAnnotation yLine = new XYLineAnnotation(
+                plot.getDomainAxis().getLowerBound(), peakY, peakX, peakY,
+                new BasicStroke(1.5f), Color.RED);
+        plot.addAnnotation(yLine);
+
+        // 设置背景网格线为实线
+        plot.setDomainGridlineStroke(new BasicStroke(1.0f));
+        plot.setRangeGridlineStroke(new BasicStroke(1.0f));
+        plot.setDomainGridlinePaint(Color.BLACK);
+        plot.setRangeGridlinePaint(Color.BLACK);
+        // 确保网格线可见
+        plot.setDomainGridlinesVisible(true);
+        plot.setRangeGridlinesVisible(true);
+        plot.setAxisOffset(new RectangleInsets(0, 0, 0, 0));
+
+        // 保存图表为图片文件
+        try {
+            File file = new File(filePath);
+            ChartUtils.saveChartAsPNG(file, chart, width, height);
+            System.out.println("图表已保存为: " + file.getAbsolutePath());
+        } catch (IOException e) {
+            System.err.println("保存图表时出错: " + e.getMessage());
+        }
+    }
+
+    // 在曲线上查找峰值点的方法
+    private static double[] findPeakOnCurve(XYSeriesCollection dataset) {
+        XYSeries series = dataset.getSeries(0);
+        int pointCount = series.getItemCount();
+
+        // 获取X和Y范围
+        double minX = series.getMinX();
+        double maxX = series.getMaxX();
+
+        // 在曲线上采样多个点来找到峰值
+        int samples = 1000; // 采样点数量
+        double step = (maxX - minX) / samples;
+
+        double peakX = minX;
+        double peakY = Double.NEGATIVE_INFINITY;
+
+        // 遍历采样点
+        for (int i = 0; i <= samples; i++) {
+            double x = minX + i * step;
+            double y = calculateSplineValue(series, x);
+
+            if (y > peakY) {
+                peakY = y;
+                peakX = x;
+            }
+        }
+
+        return new double[]{peakX, peakY};
+    }
+
+    // 计算样条曲线上某点的Y值
+    private static double calculateSplineValue(XYSeries series, double x) {
+        int n = series.getItemCount();
+
+        // 如果x超出数据范围,返回边界值
+        if (n == 0) return 0;
+        if (n == 1) return series.getY(0).doubleValue();
+
+        if (x <= series.getX(0).doubleValue()) {
+            return series.getY(0).doubleValue();
+        }
+        if (x >= series.getX(n - 1).doubleValue()) {
+            return series.getY(n - 1).doubleValue();
+        }
+
+        // 找到x所在的区间
+        int i = 0;
+        while (i < n - 1 && series.getX(i + 1).doubleValue() < x) {
+            i++;
+        }
+
+        // 获取相邻四个点用于三次样条计算
+        double x0 = (i > 0) ? series.getX(i - 1).doubleValue() : series.getX(i).doubleValue();
+        double x1 = series.getX(i).doubleValue();
+        double x2 = series.getX(i + 1).doubleValue();
+        double x3 = (i < n - 2) ? series.getX(i + 2).doubleValue() : series.getX(i + 1).doubleValue();
+
+        double y0 = (i > 0) ? series.getY(i - 1).doubleValue() : series.getY(i).doubleValue();
+        double y1 = series.getY(i).doubleValue();
+        double y2 = series.getY(i + 1).doubleValue();
+        double y3 = (i < n - 2) ? series.getY(i + 2).doubleValue() : series.getY(i + 1).doubleValue();
+
+        // 使用Catmull-Rom样条插值计算y值
+        return catmullRomSpline(x, x0, x1, x2, x3, y0, y1, y2, y3);
+    }
+
+    // Catmull-Rom样条插值算法
+    private static double catmullRomSpline(double x, double x0, double x1, double x2, double x3,
+                                           double y0, double y1, double y2, double y3) {
+        // 参数化t (0到1之间)
+        double t = (x - x1) / (x2 - x1);
+
+        // Catmull-Rom样条公式
+        double t2 = t * t;
+        double t3 = t2 * t;
+
+        return 0.5 * ((2 * y1) +
+                (-y0 + y2) * t +
+                (2 * y0 - 5 * y1 + 4 * y2 - y3) * t2 +
+                (-y0 + 3 * y1 - 3 * y2 + y3) * t3);
+    }
+
+    // 示例使用方法
+    public static void main11(String[] args) {
+        // 示例数据:二维数组,每行表示一个点 [含水率, 干密度]
+        double[][] points = {
+                {8.0, 1.75},
+                {12.0, 1.92},
+                {16.0, 2.05},
+                {20.0, 1.98},
+                {24.0, 1.86}
+        };
+
+        // 创建图表生成器
+        SmoothCurveChartToImage generator = new SmoothCurveChartToImage(
+                points,
+                "含水率(%)",
+                "干密度(g/cm³)",
+                "最大干密度曲线"
+        );
+
+        // 生成图表并保存为图片
+        generator.generateChart("SmoothCurveChart.png", 800, 185);
+    }
+}