纯Java环境下在线地图路网数据至GeoJSON与WKT的格式转换实现

目录

前言

一、在线地图道路查询

[1. 百度路网查询](#1. 百度路网查询)

[2. 高德路网查询](#2. 高德路网查询)

二、Java实现路网转换

[1. 技术路线](#1. 技术路线)

[2. 转为WKT](#2. 转为WKT)

[3. 转为GeoJSON](#3. 转为GeoJSON)

三、成果展示

[1. QGIS展示](#1. QGIS展示)

[2. 叠加底图](#2. 叠加底图)

四、总结


前言

随着GIS(地理信息系统)技术在智慧城市、路径规划、交通调度等领域的深度渗透,在线地图路网数据的高效获取与格式适配已成为后端开发的核心需求之一。百度、高德等主流在线地图开放平台,通过RESTful API等方式提供了丰富的路网数据,但返回的原生数据格式多为平台自定义JSON,难以直接适配PostGIS空间数据库存储、QGIS可视化分析等主流GIS工具的使用需求。GeoJSON作为轻量级地理空间数据交换标准,凭借简洁的结构和良好的跨平台兼容性,成为前端可视化与数据传输的首选格式;而WKT(Well-Known Text)作为OGC规范定义的空间数据文本表示方式,在空间查询、数据库存储中具备不可替代的优势,二者的格式转换是打通在线地图数据与GIS生态的关键环节。

当前虽存在各类格式转换工具,但多依赖第三方GIS组件或混合开发环境,存在耦合度高、可移植性差、难以嵌入Java后端服务等问题。纯Java环境下的转换方案虽有零散实践,但缺乏完整的技术链路支撑------从主流在线地图API的路网数据抓取、清洗,到标准化的GeoJSON与WKT双向转换,再到转换成果的可视化验证,尚未形成一套可复用、高可靠的实现方案。同时,百度与高德地图的路网数据结构存在差异,如何统一解析不同平台的返回数据、规避坐标偏移问题,以及基于JTS等工具包实现高效转换,成为开发者面临的核心痛点。

基于此,本文聚焦纯Java开发环境,搭建从在线地图路网数据获取到格式转换、成果展示的全流程实现方案。全文将按照"数据获取-转换实现-成果验证-总结展望"的逻辑展开,先介绍百度、高德地图路网查询API的调用方式与数据解析技巧,再详细阐述Java环境下的技术路线设计,以及基于JTS工具包与JSON解析库实现路网数据至WKT、GeoJSON格式的转换细节,随后通过QGIS工具完成转换成果的可视化展示与底图叠加验证,最终总结方案的优势与可优化方向,为Java开发者提供一套高效、可复用的在线地图路网数据格式转换实践参考,助力打通在线地图与GIS生态的数据壁垒。

一、在线地图道路查询

本节将简单介绍如何使用百度地图和高德地图这两个在线地图平台来进行道路名称的检索。通过介绍具体检索和路线信息的获取,让大家了解如何手工获取这些数据。

1. 百度路网查询

我们可以在百度地图的首页的搜索框中实现对道路名称的检索,如下图:

调用成功后,返回JSON格式数据,包含单条道路的完整信息,坐标数据采用百度墨卡托坐标系(BD-09),需注意后续转换时的坐标适配。可以打开调试面板来查看请求参数,如下所示:

可以看出在载荷信息中,对请求的数据进行了加密。这里暂时先不用管,接下来看看具体的道路信息。点击左边搜索结果中的道路名称,前端发送接口,得到一下信息:

以上通过官网搜索可以获取的道路信息。只是需要注意的是,这里返回的坐标是百度的坐标,不是经纬度的坐标,在实际进行处理时需要进行转换。关于如何转换,可以翻阅之前的博客进行了解。

2. 高德路网查询

同样的,下面来看看高德是如何进行操作的。

与百度地图不同的是,高德的请求载荷没有加密,可以看到很直观的请求,请求数据如下:

来看看点击详情获取什么数据,

同样注意,这里的数据虽然是经纬度的形式,但是是增加了偏移的,如需转换,可以搜索相关资源。

二、Java实现路网转换

本节将介绍如何纯Java实现将路网数据转换成GeoJSON和WKT数据。为方便讲解,这里使用的数据是高德的数据,百度的数据也是可以转换的,需要处理后就可以,这里暂时不做讲解。

1. 技术路线

本文采用纯Java环境实现路网数据格式转换。整体技术路线分为4个步骤:第一步,通过调用高德路网页面,获取原生JSON数据;第二步,通过解析JSON,提取道路名称、坐标串等信息,转换为标准化Java实体类,并完成GCJ-02坐标系到WGS84坐标系的转换(可选);第三步,将标准化实体类转换为WKT格式;第四步,将实体类转换为GeoJSON格式,完成整个转换流程。该技术路线无需依赖任何第三方GIS软件或混合开发环境,可直接嵌入Java后端服务,具备高可移植性、低耦合度的优势。

首先需要封装一个Point点对象,用于接收每个坐标点信息,关键代码如下:

java 复制代码
public static class Point {
    public double longitude;
    public double latitude;
        
    public Point(double longitude, double latitude) {
        this.longitude = longitude;
        this.latitude = latitude;
    }
        
    @Override
    public String toString() {
        return String.format("Point(%.6f, %.6f)", longitude, latitude);
    }
}

然后将通过解析返回的JSON中的道路信息,获取道路信息坐标点,并将其转换为List集合,核心代码如下:

java 复制代码
/**
     * 将高德路线shape字符串转换为Point列表
     * @param shapeStr 高德路线shape字符串(分号分隔的经纬度对)
     * @return Point列表
     */
    public static List<Point> parseShapeToPoints(String shapeStr) {
        List<Point> points = new ArrayList<>();
        
        // 按分号分割获取所有坐标对
        String[] coordPairs = shapeStr.split(";");
        
        for (String coordPair : coordPairs) {
            // 处理可能的分隔符(可能是竖线或分号)
            if (coordPair.contains("|")) {
                String[] subPairs = coordPair.split("\\|");
                for (String subPair : subPairs) {
                    Point point = parseSingleCoordinate(subPair);
                    if (point != null) {
                        points.add(point);
                    }
                }
            } else {
                Point point = parseSingleCoordinate(coordPair);
                if (point != null) {
                    points.add(point);
                }
            }
        }
        
        return points;
    }

在转换的时候,需要解析单个坐标字符串,并且转换成Point对象,代码如下:

java 复制代码
/**
 * 解析单个坐标对字符串
*/
private static Point parseSingleCoordinate(String coordPair) {
    if (coordPair == null || coordPair.trim().isEmpty()) {
        return null;
    }
        
    String[] lonLat = coordPair.split(",");
    if (lonLat.length == 2) {
        try {
            double longitude = Double.parseDouble(lonLat[0].trim());
            double latitude = Double.parseDouble(lonLat[1].trim());
            return new Point(longitude, latitude);
        } catch (NumberFormatException e) {
            System.err.println("解析坐标失败: " + coordPair);
        }
    }
    return null;
}

2. 转为WKT

WKT格式用于表示空间几何对象,路网数据多为线串(LineString)或多线串(MultiLineString),其中单条道路对应LineString,多条关联道路对应MultiLineString。将道路解析成WKT的关键代码如下:

java 复制代码
/**
 * 将Point列表转换为WKT格式的LineString
*/
public static String toWKTLineString(List<Point> points) {
    if (points == null || points.isEmpty()) {
        return null;
    }
        
    StringBuilder sb = new StringBuilder("LINESTRING (");
    for (int i = 0; i < points.size(); i++) {
        Point p = points.get(i);
        sb.append(String.format("%.6f %.6f", p.longitude, p.latitude));
        if (i < points.size() - 1) {
            sb.append(", ");
        }
     }
     sb.append(")");
     return sb.toString();
}

3. 转为GeoJSON

GeoJSON格式采用JSON结构表示地理空间数据,核心包含"type"(几何类型)、"coordinates"(坐标数组)、"properties"(属性信息,如道路名称、类型)等字段。转换过程中,需注意GeoJSON的坐标顺序与JTS默认顺序一致,同时确保属性字段的完整性,便于后续QGIS可视化时展示道路信息。转换GeoJSON的代码如下:

java 复制代码
/**
 * 将Point列表转换为GeoJSON格式的LineString
*/
public static String toGeoJSONLineString(List<Point> points) {
    if (points == null || points.isEmpty()) {
        return null;
    }
    StringBuilder sb = new StringBuilder();
    sb.append("{\n");
    sb.append("  \"type\": \"Feature\",\n");
    sb.append("  \"geometry\": {\n");
    sb.append("    \"type\": \"LineString\",\n");
    sb.append("    \"coordinates\": [\n");
    for (int i = 0; i < points.size(); i++) {
        Point p = points.get(i);
        sb.append(String.format("      [%.6f, %.6f]", p.longitude, p.latitude));
        if (i < points.size() - 1) {
            sb.append(",");
        }
        sb.append("\n");
    }
    sb.append("    ]\n");
    sb.append("  },\n");
    sb.append("  \"properties\": {}\n");
    sb.append("}");
    return sb.toString();
}

最后调用生成转换数据的代码如下,(请注意,如果使用以下代码,请注意补全数据才可以):

java 复制代码
public static void main(String[] args) {
        // 您的数据
        String shapeData = "113.177455,28.116717;..."; // 完整数据
        
        // 解析为点列表
        List<Point> points = parseShapeToPoints(shapeData);
        
        System.out.println("解析完成,共 " + points.size() + " 个点");
        
        // 输出前5个点作为示例
        System.out.println("\n前5个点:");
        for (int i = 0; i < Math.min(5, points.size()); i++) {
            System.out.println(points.get(i));
        }
        
        // 转换为WKT格式
        String wkt = toWKTLineString(points);
        System.out.println("\nWKT格式:");
        System.out.println(wkt.substring(0, Math.min(100, wkt.length())) + "...");
        
        // 转换为GeoJSON格式
        String geojson = toGeoJSONLineString(points);
        System.out.println("\nGeoJSON格式:");
        System.out.println(geojson);
        System.out.println("--------------------------------------------------");
        System.out.println(geojson.substring(0, Math.min(200, geojson.length())) + "...");
}

运行以上代码后可以看到控制有如下输出:

可以直接将以上的结果新建一个GeoJSON的文件,将具体的数据复制进去保存即可。

三、成果展示

本节将使用QGIS来对生成的数据进行展示,包括叠加影像底图的方式。为了展示贴合的结果,影像底图使用高德影像数据。

1. QGIS展示

QGIS是开源免费的GIS可视化工具,支持WKT、GeoJSON等多种空间数据格式的导入与展示,可直观验证转换成果的准确性。展示步骤如下:第一步,导入数据:打开QGIS,通过"添加矢量图层"功能,选择"文件"类型,分别导入转换后的WKT文件(.wkt)和GeoJSON文件(.geojson);第二步,配置样式:导入后,QGIS会自动识别几何类型(LineString),可通过"属性-样式"功能,设置道路的颜色、线宽,区分不同类型的道路(如高速用红色粗线,国道用蓝色中线);第三步,验证准确性:放大地图,查看道路的走向、连接关系是否与在线地图一致,核对道路名称等属性信息是否完整,确认转换无偏差。

2. 叠加底图

为进一步验证路网数据的准确性,可在QGIS中叠加高德在线影像底图,对比转换后的路网与底图路网的匹配度。操作步骤如下:第一步,使用xyz图层添加高德影像,加载至QGIS画布;第二步,叠加路网:将转换后的WKT/GeoJSON路网图层,叠加到底图上方;第三步,验证匹配度:查看路网是否与底图道路完全重合,坐标是否无偏移,确保转换后的路网数据可直接用于实际GIS应用。

叠加底图验证后,可确认本文实现的转换方案能够准确还原在线地图路网信息,满足实际应用需求。

四、总结

本文围绕纯Java环境下在线地图路网数据至GeoJSON与WKT的格式转换,完成了从数据获取、转换实现到成果展示的全流程实践,核心总结如下:本文实现了高德地图路网数据的获取与解析;搭建了纯Java环境下的转换框架,无需依赖第三方GIS组件,实现了路网数据至WKT、GeoJSON格式的高效转换,具备高可移植性、低耦合度的优势,可直接嵌入Java后端服务;通过QGIS可视化与底图叠加验证,确认转换成果准确可靠,能够完美适配PostGIS存储、前端可视化等主流GIS应用场景。同时,本文方案仍存在可优化方向:一是可增加多线程并发获取路网数据的功能,提升大规模区域路网数据的获取效率;二是可优化坐标系转换算法,进一步提升坐标精度;三是可扩展支持更多在线地图平台(如腾讯地图)的路网数据转换。后续将针对这些方向进行优化,打造更完善、更高效的纯Java路网数据格式转换方案,为GIS相关Java开发提供更全面的技术支撑。本文路网获取使用手动获取的模式,如需在线服务,建议联系高德或百度的官方平台。行文仓促,定有不足之处,欢迎各位朋友在评论区批评指正,不胜感激。