1.1 用到的技术栈
  • geotools 
  • JTS
  • Jgrapht
1.2 实现思路
          // 定义栅格网格参数private static final double CELL_SIZE_DEGREES = 0.005;private static int gridWidth = 0;//格子高度 index + 1private static int gridHeight = 0;//格子宽度// 1. 读取GeoJSON文件File geoJsonFile = new File("C:/aaa/src/main/resources/" + "map.geojson");SimpleFeatureCollection features = readGeoJson(geoJsonFile);// 2. 获取边界范围Envelope envelope = getEnvelope(features);// 3. 创建栅格网格GridCell[][] grid = createGrid(envelope);// 4. 将GeoJSON要素栅格化rasterizeFeatures(features, grid, envelope);// 5. 构建图结构SimpleWeightedGraph<GridCell, DefaultWeightedEdge> graph = buildGraph(grid);// 6. 定义起点和终点  new GridCell[gridHeight][gridWidth];GridCell start = grid[2][2]; // 左下角GridCell end = grid[gridHeight -1][gridWidth - 1]; // 右上角// 7. 运行A*算法AStarShortestPath<GridCell, DefaultWeightedEdge> aStar = new AStarShortestPath<>(graph, new ManhattanDistance());GraphPath<GridCell, DefaultWeightedEdge> path = aStar.getPath(start, end);// 8. 输出结果if (path != null) {System.out.println("找到路径,长度: " + path.getLength());for (GridCell cell : path.getVertexList()) {System.out.println("[" + cell.centerX + ", " + cell.centerY + "],");}} else {System.out.println("未找到路径");}}
  • 读取GeoJSON文件
    // 读取GeoJSON文件private static SimpleFeatureCollection readGeoJson(File file) throws IOException {FeatureJSON fjson = new FeatureJSON();try (FileInputStream in = new FileInputStream(file)) {return (SimpleFeatureCollection) fjson.readFeatureCollection(in);}}
  •  利用图形边界创建栅格网格
// 创建栅格网格private static GridCell[][] createGrid(Envelope envelope) {double minLon = envelope.getMinX() - CELL_SIZE_DEGREES * 1.5;double minLat = envelope.getMinY() - CELL_SIZE_DEGREES * 1.5;double maxLon = envelope.getMaxX() + CELL_SIZE_DEGREES * 1.5;double maxLat = envelope.getMaxY() + CELL_SIZE_DEGREES * 1.5;gridWidth = (int) Math.ceil((maxLon - minLon) / CELL_SIZE_DEGREES);gridHeight = (int) Math.ceil((maxLat - minLat) / CELL_SIZE_DEGREES);GridCell[][] grid = new GridCell[gridHeight][gridWidth];for (int y = 0; y < gridHeight; y++) {for (int x = 0; x < gridWidth; x++) {// 3. 计算当前单元格的左下角坐标 (minX, minY)// 3. 计算当前单元格的左下角坐标 (minX, minY)double currentCellMinX = minLon + x * CELL_SIZE_DEGREES;double currentCellMinY = minLat + y * CELL_SIZE_DEGREES;// 4. 计算当前单元格的右上角坐标 (maxX, maxY)double currentCellMaxX = currentCellMinX + CELL_SIZE_DEGREES;double currentCellMaxY = currentCellMinY + CELL_SIZE_DEGREES;// 5. 计算当前单元格的中心点坐标double centerX = currentCellMinX + CELL_SIZE_DEGREES / 2.0;double centerY = currentCellMinY + CELL_SIZE_DEGREES / 2.0;grid[y][x] = new GridCell(x, y,centerX,centerY);}}return grid;}// 网格单元类static class GridCell {final int x, y; // 网格坐标final double centerX, centerY; // 地理坐标boolean isObstacle = false;GridCell(int x, int y, double centerX, double centerY) {this.x = x;this.y = y;this.centerX = centerX;this.centerY = centerY;}@Overridepublic String toString() {return "Cell(" + x + "," + y + ")" + "lonlat(" + centerX + "," + centerY + ")" ;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;GridCell gridCell = (GridCell) o;return x == gridCell.x && y == gridCell.y;}@Overridepublic int hashCode() {return 31 * x + y;}}
  •  栅格化要素
    // 栅格化要素private static void rasterizeFeatures(SimpleFeatureCollection features, GridCell[][] grid, Envelope envelope)throws FactoryException, TransformException {try (SimpleFeatureIterator it = features.features()) {while (it.hasNext()) {SimpleFeature feature = it.next();Geometry geom = (Geometry) feature.getDefaultGeometry();// 检查每个网格单元是否与几何图形相交for (int y = 0; y < gridHeight; y++) {for (int x = 0; x < gridWidth; x++) {GridCell cell = grid[y][x];GeometryFactory geometryFactory = new GeometryFactory();// 定义矩形的边界 (minX, minY) 到 (maxX, maxY)double minX = cell.centerX - CELL_SIZE_DEGREES / 2;double minY = cell.centerY - CELL_SIZE_DEGREES / 2;double maxX = cell.centerX + CELL_SIZE_DEGREES / 2;double maxY = cell.centerY + CELL_SIZE_DEGREES / 2;// 2. 定义矩形的顶点坐标 (按顺时针或逆时针顺序,最后一个点与第一个点相同)Coordinate[] coords = new Coordinate[] {new Coordinate(minX, minY), // 左下new Coordinate(maxX, minY), // 右下new Coordinate(maxX, maxY), // 右上new Coordinate(minX, maxY), // 左上new Coordinate(minX, minY)  // 回到左下,闭合环};// 3. (可选,如果你需要更复杂的序列,这里直接用Coordinate数组)// CoordinateSequence coordinateSequence = geometryFactory.getCoordinateSequenceFactory().create(coords);// 4. 创建 LinearRing (外部边界)LinearRing shell = geometryFactory.createLinearRing(coords);// 5. 创建 Polygon (矩形)// 第二个参数是内孔的 LinearRing 数组,对于简单矩形,通常是空的Polygon rectangle = geometryFactory.createPolygon(shell, null);//                        Point point = new GeometryFactory().createPoint(new Coordinate(cell.centerX, cell.centerY));if (geom.intersects(rectangle)) {cell.isObstacle = true;}}}}}}
  • 构建图结构
    // 构建图结构private static SimpleWeightedGraph<GridCell, DefaultWeightedEdge> buildGraph(GridCell[][] grid) {SimpleWeightedGraph<GridCell, DefaultWeightedEdge> graph =new SimpleWeightedGraph<>(DefaultWeightedEdge.class);// 添加所有顶点for (int y = 0; y < gridHeight; y++) {for (int x = 0; x < gridWidth; x++) {if (!grid[y][x].isObstacle) {graph.addVertex(grid[y][x]);}}}// 添加边(8连通)for (int y = 0; y < gridHeight; y++) {for (int x = 0; x < gridWidth; x++) {if (grid[y][x].isObstacle) continue;// 检查8个相邻方向for (int dy = -1; dy <= 1; dy++) {for (int dx = -1; dx <= 1; dx++) {if (dx == 0 && dy == 0) continue; // 跳过自身int nx = x + dx;int ny = y + dy;if (nx >= 0 && nx < gridWidth && ny >= 0 && ny < gridHeight) {if (!grid[ny][nx].isObstacle && graph.containsVertex(grid[ny][nx])) {DefaultWeightedEdge edge = graph.addEdge(grid[y][x], grid[ny][nx]);if (edge != null) {// 对角线距离为√2,直线距离为1double weight = (dx != 0 && dy != 0) ? Math.sqrt(2) : 1.0;graph.setEdgeWeight(edge, weight);}}}}}}}return graph;}
  • 实现启发函数
    public static class ManhattanDistance implements AStarAdmissibleHeuristic<GridCell> {@Overridepublic double getCostEstimate(GridCell source, GridCell target) {double dx = Math.abs(source.x - target.x);double dy = Math.abs(source.y - target.y);return dx + dy;//            double dx = source.centerX - target.centerX;
//            double dy = source.centerY - target.centerY;
//            return Math.sqrt(dx * dx + dy * dy);}}
  • 完美实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/93178.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/93178.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/93178.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot 默认使用 CGLIB,但CGLIB 无法代理 final 类或 final 方法

那么当这两件事冲突时&#xff0c;Spring Boot 是怎么“解决”的呢&#xff1f;答案是&#xff1a;它不解决&#xff0c;也无法解决。当这种情况发生时&#xff0c;你的应用程序会直接启动失败。这不是 Spring Boot 的疏忽&#xff0c;而是由 CGLIB 的底层原理和 Java 语言的规…

cuda编程笔记(10)--memory access 优化

全局内存访问优化&#xff08;Coalesced Access&#xff09; 什么是 Coalesced Access&#xff1f; 定义&#xff1a;一个 warp&#xff08;32 个线程&#xff09;在同一指令中访问全局内存时&#xff0c;如果这些访问请求可以合并成尽可能少的内存事务&#xff08;通常是 32…

闲庭信步使用图像验证平台加速FPGA的开发:第三十一课——车牌识别的FPGA实现(3)车牌字符分割预处理

&#xff08;本系列只需要modelsim即可完成数字图像的处理&#xff0c;每个工程都搭建了全自动化的仿真环境&#xff0c;只需要双击top_tb.bat文件就可以完成整个的仿真&#xff0c;大大降低了初学者的门槛&#xff01;&#xff01;&#xff01;&#xff01;如需要该系列的工程…

电子电气架构 --- 汽车软件全生命周期

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

力扣面试150(41/150)

7.25 56. 合并区间 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 我的思路&#xff1a; 左端点升序…

【隧道篇 / IPsec】(7.6) ❀ 01. 利用向导快速建立IPsec安全隧道 (点对点) ❀ FortiGate 防火墙

【简介】相信很多人已经习惯利用导向快速创建VPN了&#xff0c;而且已经有部分尝鲜者已经用上了FortiOS 7.6&#xff0c;但是会发现FortiOS 7.6下的VPN向导改变了很多&#xff0c;一时无法下手&#xff0c;下面我们来看看最常见的点对点是如何配置的。环境介绍在配置IPsec VPN之…

PLLIP核

。1 号红色框内的速度等级代表着设备的速度 等级&#xff0c;保存默认就好&#xff1b;2 号红色框内设置输入频率&#xff1b;3 号红色框选择 PLL 的工作模式。我们 开发板用的晶振是 50MHz 的&#xff0c;故在 2 号红色框内我们填写 50MHz&#xff1b;我们在 3 号红色框内选正…

1.1 Deep learning?pytorch ?深度学习训练出来的模型通常有效但无法解释合理性? 如何 解释?

DL 是什么&#xff0c;你如何理解DL模型&#xff1f; DL 对于我而言&#xff0c;就是人类试图想通过数学语言描述人类学习过程的一门技术&#xff0c;或者说学科。 因此 DL 模型 相当于 数学 的 一个 funciton &#xff0c;有输入&#xff0c;通过function处理&#xff0c;得…

java实现在工具类中注入其他对象方式

方案1&#xff1a; Slf4j Component public class ChatdocApiClient {Value("${chatdoc.app-id}")private String appId;Value("${chatdoc.secret}")private String secret;Value("${chatdoc.domain}")private String domain;private final Rest…

electron中IPC 渲染进程与主进程通信方法解析

electron中ipcRenderer.invoke、ipcRenderer.on、ipcRenderer.send、ipcRenderer.sendSync作用与区别 IPC 渲染进程与主进程通信方法解析 ipcRenderer 的这几个方法作用不完全相同&#xff0c;它们适用于不同的通信场景&#xff0c;核心区别在于通信方向、是否需要响应以及同步…

epoll_event 事件类型详解

epoll_event 事件类型详解 epoll_event 是 Linux epoll I/O 多路复用机制的核心结构体&#xff0c;其中的事件类型决定了 epoll 监控的行为和触发条件。以下是各种事件类型的详细解析&#xff1a; epoll_event 结构体 #include <sys/epoll.h>typedef union epoll_data {v…

设计自己的小传输协议 导论与概念

设计自己的小传输协议 导论与概念 1&#xff1a;聊一聊协议头设计 ​ 早在《TCP/IP详解》中的第一句话中&#xff0c;我们就知道协议的含义是这样的&#xff1a;协议是通信双方共同遵守的一套规则&#xff0c;提供格式定义、语义解释等&#xff0c;使不同设备或软件能够正确交…

iOS —— 天气预报仿写总结

在iOS中&#xff0c;最常见的网络请求方式是NSURLSession&#xff0c;它是苹果推荐的现代API&#xff0c;简单安全且易于拓展。一次完整的网络请求流程&#xff1a;构造 NSURL 对象创建 NSURLSessionDataTask发起请求&#xff08;resume&#xff09;在回调中解析数据回到主线程…

MySQL 8.4 Windows 版安装记录与步骤参考

导语&#xff1a; MySQL 作为广泛使用的开源数据库管理系统&#xff0c;是许多开发者和学习者的必备工具。最近有朋友询问安装过程&#xff0c;正好整理了 MySQL 8.4 在 Windows 系统下的安装步骤和一些注意事项&#xff0c;分享给有需要的朋友做个参考。关于 MySQL&#xff1a…

七、搭建springCloudAlibaba2021.1版本分布式微服务-skywalking9.0链路追踪

前言链路追踪介绍 对于一个大型的几十个&#xff0c;几百个微服务构成的微服务架构系统&#xff0c;通常会遇到下面的一系列问题。 如何串联整个调用链路&#xff0c;快速定位问题&#xff1f;如何澄清各个微服务之间的依赖关系&#xff1f;如何进行各个微服务接口的性能分析&a…

深入理解大语言模型生成参数:temperature、top\_k、top\_p 等全解析

在使用大语言模型&#xff08;如 GPT-4、LLaMA、ChatGLM 等&#xff09;进行文本生成任务时&#xff0c;很多开发者会面对各种“生成参数”&#xff0c;如 temperature、top_k、top_p、repetition_penalty 等。这些参数虽然看起来抽象&#xff0c;但掌握它们的意义和配置技巧&a…

vulhub Web Machine(N7)靶场攻略

下载地址&#xff1a; https://download.vulnhub.com/webmachine/Web-Machine-N7.ova 使用方法&#xff1a; 靶场下载好以后不用解压&#xff0c;需要使用Oracle VirtualBox虚拟机打开&#xff0c;用VMware会报错。安装Oracle VirtualBox虚拟机时安装地址不能随便选择&#…

【机器学习深度学习】模型微调:多久才算微调完成?——如何判断微调收敛,何时终止训练

目录 前言 一、微调过程的目标&#xff1a;优化模型表现 二、微调需要多久&#xff1f; 微调时间无法确定 三、如何判断微调何时收敛&#xff1f; 3.1 观察Loss的下降趋势 3.2 损失值趋于平稳&#xff0c;意味着收敛 如何识别收敛&#xff1f; 3.3 验证Loss的波动&…

红队视角:实战渗透测试中漏洞利用的进阶技巧与防御

红队作为渗透测试的 “攻击方”&#xff0c;其核心价值不仅在于发现漏洞&#xff0c;更在于挖掘漏洞的深度利用方式 —— 通过绕过防护措施、组合低危漏洞形成攻击链&#xff0c;暴露企业真实安全风险。从红队视角解析漏洞利用的进阶技巧&#xff0c;既能帮助防御方理解攻击思路…

OpenHarmony BUILD.gn中执行脚本

在OpenHarmony编译构建中笔者经常遇到这样的场景——需要执行sh脚本完成某些操作。笔者将OpenHarmony BUILD.gn中执行脚本的方法分享如下&#xff1a; 前置知识点 1.能够把自定义的子系统加入OpenHarmony源码的编译构建&#xff0c;请参考&#xff1a;https://ost.51cto.com/…