【可视化工具】JavaFx实现自适应屏幕的TSP路径可视化

简介: 【可视化工具】JavaFx实现自适应屏幕的TSP路径可视化

@[toc]


代码

/**
 * @Author:WSKH
 * @ClassName:PlotUtil
 * @ClassType:
 * @Description:
 * @Date:2022/6/6/13:13
 * @Email:1187560563@qq.com
 * @Blog:https://blog.csdn.net/weixin_51545953?type=blog
 */
public class PlotUtil extends javafx.application.Application {

    // 可视化区域的宽度
    int stageW = 1000;
    // 可视化区域的高度
    int stageH = 1000;
    // 坐标偏移
    int offsetX = 100;
    int offsetY = 100;

    // 主要函数
    @Override
    public void start(Stage primaryStage) throws Exception {

        // 初始化画布和面板
        AnchorPane pane = new AnchorPane();
        Canvas canvas = initCanvas(stageW - offsetX * 2, stageH - offsetY * 2);
        canvas.relocate(offsetX, offsetY);
        pane.getChildren().add(canvas);

        // 读取城市坐标文件
        List<double[]> locationList = getLocationList();

        // 用数组型禁忌搜索算法求解TSP问题
        ArrayTS_TSP arrayTSModel = new ArrayTS_TSP(new ArrayList<>(locationList));
        arrayTSModel.solve();

        // 获取最佳路径
        int[] bestPath = arrayTSModel.bestGh.clone();

        // 按照屏幕尺寸等比例调整城市坐标
        List<double[]> fitLocationList = fitLocation(locationList);

        // 绘制城市
        HashMap<Integer, Circle> map = new HashMap<>();
        List<Circle> circleList = new ArrayList<>();
        for (double[] position : fitLocationList) {
            Circle circle = new Circle(position[0], position[1], 5);
            pane.getChildren().add(circle);
            circleList.add(circle);
        }

        // 添加播放按钮
        Button button = new Button("播放");
        final int[] pCnt = {0};
        button.setOnAction(new EventHandler<ActionEvent>() {
            // 按钮点击事件
            @Override
            public void handle(ActionEvent event) {
                // 路径 动画
                Timeline animation = new Timeline(new KeyFrame(Duration.millis(50), new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent event) {
                        if (pCnt[0] < bestPath.length - 1) {
                            int cur = bestPath[pCnt[0]];
                            int next = bestPath[pCnt[0] + 1];
                            double[] p1 = fitLocationList.get(cur);
                            double[] p2 = fitLocationList.get(next);
                            Path path = new Path();
                            path.getElements().add(new MoveTo(p1[0], p1[1]));
                            path.getElements().add(new LineTo(p2[0], p2[1]));
                            pane.getChildren().add(path);
                            pCnt[0]++;
                        }else if(pCnt[0] == bestPath.length - 1){
                            int cur = bestPath[pCnt[0]];
                            int next = bestPath[0];
                            double[] p1 = fitLocationList.get(cur);
                            double[] p2 = fitLocationList.get(next);
                            Path path = new Path();
                            path.getElements().add(new MoveTo(p1[0], p1[1]));
                            path.getElements().add(new LineTo(p2[0], p2[1]));
                            pane.getChildren().add(path);
                            pCnt[0]++;
                        }
                    }
                }));
                animation.setCycleCount(Timeline.INDEFINITE);
                animation.play();
            }
        });
        pane.getChildren().add(button);

        // 一切就绪,准备展示
        primaryStage.setTitle("TSP路径可视化");
        primaryStage.setScene(new Scene(pane, stageW, stageH));
        primaryStage.show();
    }

    private List<double[]> fitLocation(List<double[]> locationList) {
        // 获取宽度和高度方向上的最大值
        double maxX = locationList.get(0)[0];
        double maxY = locationList.get(0)[1];
        for (double[] position : locationList) {
            maxX = Math.max(maxX, position[0]);
            maxY = Math.max(maxY, position[1]);
        }
        // 计算缩放比例
        double rateX = (stageW - 2 * offsetX) / maxX;
        double rateY = (stageH - 2 * offsetY) / maxY;
        // 按照比例自适应调整
        List<double[]> fitLocationList = new ArrayList<>();
        for (double[] position : locationList) {
            fitLocationList.add(new double[]{position[0] * rateX + offsetX, position[1] * rateY + offsetY});
        }
        return fitLocationList;
    }

    // 初始化画布对象
    private Canvas initCanvas(double l, double w) {
        Canvas canvas = new Canvas(l, w);
        GraphicsContext gc = canvas.getGraphicsContext2D();
        // 边框
        gc.setStroke(Color.BLACK);
        gc.setLineWidth(2);
        gc.strokeRect(0, 0, l, w);
        // 填充
        gc.setFill(new Color(127 / 255d, 255 / 255d, 170 / 255d, 1d));
        gc.fillRect(0, 0, l, w);
        return canvas;
    }

    private List<double[]> getLocationList() throws IOException {
        FileInputStream fis = new FileInputStream("src/main/java/Algorithm/TSP问题/data/att48.txt");
        List<double[]> locationList = new ArrayList<>();
        int len = 0;
        StringBuilder sb = new StringBuilder();
        while ((len = fis.read()) != -1) {
            sb.append((char) len);
        }
        fis.close();
        String[] split = sb.toString().split("\n");
        for (String s : split) {
            String[] s1 = s.split(" ");
            double[] doubles = new double[]{Double.parseDouble(s1[1]), Double.parseDouble(s1[2])};
            locationList.add(doubles.clone());
        }
        return locationList;
    }

    public static void main(String[] args) {
        launch(args);
    }

}

可视化效果

在这里插入图片描述

目录
相关文章
|
13天前
|
JSON 数据可视化 前端开发
地图可视化神器Kepler.gl 3.0终于来了!
地图可视化神器Kepler.gl 3.0终于来了!
|
27天前
cesium加载魔方立方体
【8月更文挑战第16天】
|
4月前
|
数据可视化 数据挖掘 API
C++ Qt开发:Charts绘制各类图表详解
Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍`TreeWidget`与`QCharts`的常用方法及灵活运用。在之前的文章中笔者介绍了如何使用`QCharts`模块来绘制简单的折线图并对通用API接口进行了概括,本章我们通过在`TreeWidget`组件中提取数据,并依次实现柱状图、饼状图、堆叠图、百分比图、散点图等。
314 5
C++ Qt开发:Charts绘制各类图表详解
|
4月前
|
XML 前端开发 Java
【Android App】三维处理中三维投影OpenGL功能的讲解及实战(附源码和演示 超详细必看)
【Android App】三维处理中三维投影OpenGL功能的讲解及实战(附源码和演示 超详细必看)
57 1
|
4月前
|
定位技术 Python
pyecharts从入门到精通-地图专题Map-带时间轴与网格的复杂绘图
pyecharts从入门到精通-地图专题Map-带时间轴与网格的复杂绘图
|
4月前
|
XML Java Android开发
【Android App】勾勒出三维立方体和球体以及它们的转动图形讲解及实战(附源码和演示视频 超详细)
【Android App】勾勒出三维立方体和球体以及它们的转动图形讲解及实战(附源码和演示视频 超详细)
77 0
|
11月前
259Echarts - 3D 路径图(Airline on Globe)
259Echarts - 3D 路径图(Airline on Globe)
38 0
|
定位技术
GIS开发:mapbox gl几种底图的加载
GIS开发:mapbox gl几种底图的加载
259 0
|
JSON 数据格式
Cesium开发:模型的CZML文件
Cesium开发:模型的CZML文件
409 0
|
编解码 算法 数据可视化
Tsp遍历路径可视化【javaFx实现--详细注释】
Tsp遍历路径可视化【javaFx实现--详细注释】
104 0