GPS和桩号互转

news2024/11/25 10:35:27

文章目录

  • 前言
  • 一、通过bigmap软件生成坐标信息csv
  • 二、Java实现
    • 1.CSV分隔
    • 2.计算
      • 2.1 读取gps_data.csv
      • 2.2 读取piles.csv
      • 2.3 进行线性插值
      • 2.4 返回值实体
      • 2.5 根据GPS坐标计算距离工具
      • 2.6 根据GPS坐标读取桩号
      • 2.7 根据桩号读取GPS坐标(根据距离计算,找到最近的桩号)


前言

本文核心功能: 1.通过GPS坐标获取对应的桩号 2.通过桩号获取对应的GPS坐标


一、通过bigmap软件生成坐标信息csv

对于不规则曲线的公路,使用线性插值来计算桩号的经纬度仍然是可行的,但我们需要确保插值的精度更高。这通常意味着需要更多的GPS点来覆盖整个公路,确保每段路都有足够的数据点以进行准确的插值。

软件:在这里插入图片描述
官方教程地址:链接

重点:比如需要计算的是一条蜿蜒曲折的公路,需要在软件内,沿着公路走向描点连线;注意公路起点(桩号K0+000)

示例:
在这里插入图片描述
间隔距离:间隔距离越小,倒时候转换时就越精确(如下图,如果设置为100米,则整条线等分为100米一段),保存为CSV文件
在这里插入图片描述
导出的csv示例(50米等分):
在这里插入图片描述

二、Java实现

1.CSV分隔

将bigemap导出的csv文件分成两份
第一份:gps_data.csv
包含经纬度和距离信息
在这里插入图片描述

第二份:piles.csv
包含桩号名称和对应的距离信息
在这里插入图片描述

2.计算

2.1 读取gps_data.csv

    /**
     * 该函数用于从指定文件路径读取GPS数据,并将每行数据转换为GPSPointConvert对象后存入列表返回。具体步骤如下:
     * 通过BufferedReader逐行读取文件内容;
     * 每行数据以逗号分割,提取纬度、经度和距离信息;
     * 将提取的数据创建成GPSPointConvert对象并添加到列表中;
     * 最终返回包含所有GPS点的列表
     * @param filePath
     * @return
     * @throws IOException
     */
    private static List<GPSPointConvert> readGPSData(String filePath) throws IOException {
        List<GPSPointConvert> gpsData = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = br.readLine()) != null) {
                String[] parts = line.split(",");
                double latitude = Double.parseDouble(parts[0]);
                double longitude = Double.parseDouble(parts[1]);
                double distance = Double.parseDouble(parts[2]);
                gpsData.add(new GPSPointConvert(latitude, longitude, distance));
            }
        }
        return gpsData;
    }

2.2 读取piles.csv

    /**
     * 该函数用于从指定的文件中读取数据并转换为PileConvert对象列表。具体步骤如下:
     * 创建一个空的PileConverts列表。
     * 使用BufferedReader读取指定的文件。
     * 循环读取文件的每一行,直到没有内容为止。
     * 将每一行用逗号分割成两部分。
     * 第一部分作为名称,第二部分解析为double类型的距离。
     * 创建一个新的PileConvert对象,传入名称和距离作为参数。
     * 将新对象添加到PileConverts列表中。
     * 返回PileConverts列表
     * @param filePath
     * @return
     * @throws IOException
     */
    private static List<PileConvert> readPileConvertData(String filePath) throws IOException {
        List<PileConvert> PileConverts = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = br.readLine()) != null) {
                String[] parts = line.split(",");
                String name = parts[0];
                double distance = Double.parseDouble(parts[1]);
                PileConverts.add(new PileConvert(name, distance));
            }
        }
        return PileConverts;
    }

2.3 进行线性插值

    /**
     * 该函数用于根据给定的桩点距离,在GPS数据点间进行线性插值以确定桩点的实际经纬度位置。具体步骤如下:
     * 遍历每个桩点PileConvert;
     * 查找最近的两个GPS点p1和p2,使得p1到p2的距离覆盖目标桩点距离;
     * 计算插值比例ratio;
     * 利用ratio插值计算出桩点的纬度latitude和经度longitude;
     * 创建新的GPSPointConvert对象并添加到结果列表中。
     * @param gpsData
     * @param PileConverts
     * @return
     */
    private static List<GPSPointConvert> interpolatePileConvertPositions(List<GPSPointConvert> gpsData, List<PileConvert> PileConverts) {
        List<GPSPointConvert> PileConvertPositions = new ArrayList<>();
        int currentIndex = 0;

        for (PileConvert PileConvert : PileConverts) {
            double targetDistance = PileConvert.getDistance();

            while (currentIndex < gpsData.size() - 1 && gpsData.get(currentIndex + 1).getDistance() < targetDistance) {
                currentIndex++;
            }

            if (currentIndex >= gpsData.size() - 1) {
                break;
            }

            GPSPointConvert p1 = gpsData.get(currentIndex);
            GPSPointConvert p2 = gpsData.get(currentIndex + 1);

            double ratio = (targetDistance - p1.getDistance()) / (p2.getDistance() - p1.getDistance());
            double latitude = p1.getLatitude() + ratio * (p2.getLatitude() - p1.getLatitude());
            double longitude = p1.getLongitude() + ratio * (p2.getLongitude() - p1.getLongitude());
            PileConvertPositions.add(new GPSPointConvert(latitude,longitude,targetDistance));
        }

        return PileConvertPositions;
    }

2.4 返回值实体

import lombok.Data;

import java.io.Serializable;

/**
 * gps桩号转换-GPS
 */
@Data
public class GPSPointConvert implements Serializable {
    private static final long serialVersionUID = 1L;

    private Double latitude;
    private Double longitude;
    private Double distance;

    public GPSPointConvert(double latitude, double longitude, double targetDistance) {
        this.latitude = latitude;
        this.longitude = longitude;
        this.distance = targetDistance;
    }
}

import lombok.Data;

import java.io.Serializable;

/**
 * gps桩号转换-桩号
 */
@Data
public class PileConvert implements Serializable {
    private static final long serialVersionUID = 1L;

   private String name;
   private Double distance;

    public PileConvert(String name, double distance) {
        this.name = name;
        this.distance = distance;
    }
}

2.5 根据GPS坐标计算距离工具

import java.text.DecimalFormat;

/**
 *
 * @描 述: 高德地图对应经纬度计算距离
 */
public class LocationUtils {
    // 地球赤道半径
    private static double EARTH_RADIUS = 6378.137;

    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    /**
     * @描述 经纬度获取距离
     * @参数  [lat1, lng1, lat2, lng2]
     * @返回值 double 米
     **/
    public static double getDistance(double lat1, double lng1, double lat2,
                                     double lng2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lng1) - rad(lng2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
            + Math.cos(radLat1) * Math.cos(radLat2)
            * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        s = Math.round(s * 10000d) / 10000d;
        //保留三位小数
        DecimalFormat df = new DecimalFormat("0.000");
        String format = df.format(s * 1000);
        return Double.parseDouble(format);
    }

    /**
     * 获取两个经纬度的中心
     * @param args
     */
    public static double[] getCenter(double lat1, double lng1, double lat2,
                                     double lng2) {
        double[] center = new double[2];
        center[0] = (lat1 + lat2) / 2;
        center[1] = (lng1 + lng2) / 2;
        return center;
    }

//    public static void main(String[] args) {
//
//        double distance = getDistance(43.819579,  82.586068,
//                29.35, 106.33);
//        System.out.println("距离" + distance + "千米");
//    }
}

2.6 根据GPS坐标读取桩号

 /**
     * 根据桩号读取GPS坐标
     * @param pileName 桩号 格式:K00+000
     */
    public String getPileConvert(String pileName) throws IOException {

        // 读取GPS轨迹数据
        List<GPSPointConvert> gpsData = readGPSData("gps_data.csv");
        // 读取桩号数据
        List<PileConvert> PileConverts = readPileConvertData("piles.csv");

        // 插值计算桩号位置
        List<GPSPointConvert> PileConvertPositions = interpolatePileConvertPositions(gpsData, PileConverts);
        String result="";
        // 输出经纬度
        double distanceResult =99999;
        for (int i = 0; i < PileConvertPositions.size(); i++) {
            PileConvert pileConvert = PileConverts.get(i);
            String name = pileConvert.getName().replace("K","");
            String[] split = name.split("\\+");
            //循环值
            double v = Double.parseDouble(split[0])*1000+Double.parseDouble(split[1]);

            String[] split1 = pileName.replace("K","").split(" ");
            //等待被判断的值
            double v1 = Double.parseDouble(split1[0])*1000+Double.parseDouble(split1[1]);
            //计算绝对差值
            double distance = Math.abs(v - v1);
            if(distance<distanceResult){
                distanceResult=distance;
                result=PileConvertPositions.get(i).getLatitude()+","+PileConvertPositions.get(i).getLongitude();
            }

        }
        return result;
    }

2.7 根据桩号读取GPS坐标(根据距离计算,找到最近的桩号)

    /**
     * 根据GPS坐标读取桩号
     */
    public String getPileConvert(GPSPointConvert gpsPointConvert) throws IOException {
        // 读取GPS轨迹数据
        List<GPSPointConvert> gpsData = readGPSData("gps_data.csv");
        // 读取桩号数据
        List<PileConvert> PileConverts = readPileConvertData("piles.csv");

        // 插值计算桩号位置
        List<GPSPointConvert> PileConvertPositions = interpolatePileConvertPositions(gpsData, PileConverts);

        // 查询距离最近的桩点
        double distanceResult =99999;
        String result="";
        for (int i = 0; i < PileConvertPositions.size(); i++) {
            GPSPointConvert gPSPointConvert = PileConvertPositions.get(i);
            double longitude = gpsPointConvert.getLongitude();
            double latitude = gpsPointConvert.getLatitude();
            //找到距离最近的桩点
            Double longitude1 = gPSPointConvert.getLongitude();
            Double latitude1 = gPSPointConvert.getLatitude();
            double distance = LocationUtils.getDistance(latitude, longitude, latitude1, longitude1);
            if(distance<distanceResult){
                distanceResult=distance;
                result=PileConverts.get(i).getName();
            }

        }
        return result;
    }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

短视频SDK解决方案,智能技术加持,提升创作效率

随着社交媒体、直播电商、在线教育等领域的蓬勃发展&#xff0c;短视频以其独特的魅力迅速崛起&#xff0c;成为内容创作与传播的新风口。为了助力企业和个人轻松拥抱视频化趋势&#xff0c;美摄科技匠心打造了一套高效、易用的短视频SDK解决方案&#xff0c;以“轻编辑&#x…

【高级IO-2】IO多路转接之Select(概念及代码实例)

文章目录 I/O 多路转接 之 Select1. 了解select2. select 函数原型① fd_set 结构② 详细理解参数&#xff08;readfds为例&#xff09; 3. 理解select的执行过程4. select代码实例&#xff1a;监视多个文件描述符5. Socket就绪条件6. select代码实例&#xff1a;多路复用服务器…

每日掌握一个科研插图·2D密度图|24-08-21

小罗碎碎念 在统计学和数据可视化领域&#xff0c;探索两个定量变量之间的关系是一种常见的需求。为了更深入地理解这种关系&#xff0c;我们可以使用多种图形表示方法&#xff0c;这些方法在本质上是对传统图形的扩展和变体。 散点图&#xff1a;这是最基本的图形&#xff0c…

什么是 JavaConfig?

什么是 JavaConfig&#xff1f; &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; JavaConfig是Spring框架的一项创新&#xff0c;它允许开发者使用纯Java代码来配置Spring IoC容器&#xff0c;从而避免了繁琐的XML配置。这一特性带来了诸多优…

【微信小程序】导入项目

1.在微信开发工具中&#xff0c;点击【导入项目】 2.在打开的界面中执行2个步骤 1.找到要导入项目的路径2.AppID要改成自己的AppID 3.package.json包初始化【装包之前要确保有package.json文件】 1.在【资源管理器】空白处&#xff0c;点击鼠标右键&#xff0c;选择【】&am…

免费的真是太香了!Chainlit接入抖音 Coze AI知识库接口快速实现自定义用户聊天界面

前言 由于Coze 只提供了一个分享用的网页应用&#xff0c;网页访问地址没法自定义&#xff0c;虽然可以接入NextWeb/ChatGPT web/open webui等开源应用。但是如果我们想直接给客户应用&#xff0c;还需要客户去设置配置&#xff0c;里面还有很多我们不想展示给客户的东西怎么办…

[Python可视化]空气污染物浓度地图可视化

[Python可视化]空气污染物浓度地图可视化&#xff0c;果然是路边浓度最大 在本篇文章中&#xff0c;我将展示如何使用 Python 结合 OSMnx、NetworkX 和 GeoPandas 等库&#xff0c;计算给定路径的最短路线&#xff0c;并基于该路径穿过的网格单元计算总污染量。最终&#xff0c…

uniapp 修复使用 uni.saveImageToPhotosAlbum 方法在部分安卓手机上保存失败

场景&#xff1a;使用 uni.saveImageToPhotosAlbum 保存图片&#xff0c;其他手机都是可以的&#xff0c;但在鸿蒙系统的手机上出现了bug&#xff0c;报错Object {errMsg:"savelmageToPhotosAlbum:fai..errMsg:savelmageToPhotosAlbum:fail invalid filetype"} 原因&…

数学建模学习(116):全面解析梯度下降算法及其在机器学习中的应用与优化

文章目录 1.梯度下降简介1.1 梯度下降的数学原理1.2 学习率的选择2 梯度下降变体3.梯度下降优化器3.1 动量法(Momentum)3.2 AdaGrad3.3 RMSprop3.4 Adam3.5 Python 使用不同优化器训练线性回归模型4.案例:使用梯度下降优化加利福尼亚房价预测模型4.1. 数据准备4.2. 模型训练…

【dotnet】Ubuntu 24.04安装dotnet 8.0报错

我的环境是Ubuntu 24.04&#xff0c;64位&#xff0c;使用azure的虚拟机。 报错文字如下&#xff1a; kidfuazurefu:~$ sudo apt install dotnet-sdk-8.0 Reading package lists... Done Building dependency tree... Done Reading state information... Done Some packages c…

数学生物学-3-固定点、稳定性和蛛网图(Fixed Points, Stability, and Cobwebbing)

在前一篇博客中&#xff0c;我们研究了一些离散时间模型的例子。特别是&#xff0c;我们推导出了离散逻辑方程的重要例子。 数学生物学-2-离散时间模型(Discrete Time Models&#xff09;-CSDN博客 在本篇文章中&#xff0c;我们将考虑离散时间模型的一般形式&#xff08;在数…

超声波水表是什么?量程比又是什么?

一、超声波水表概述 1.定义&#xff1a; 超声波水表是一种利用超声波技术来测量水流速度&#xff0c;进而计算出流经管道的水体积流量的计量设备。它通过发送和接收超声波信号的时间差来确定水流的速度&#xff0c;从而精确地计量水的流量。 2.工作原理&#xff1a; 超声波…

勇闯计算机视觉(第一关--环境激活)

以下内容&#xff0c;皆为原创&#xff0c;制作实属不易&#xff0c;多谢帅锅和镁铝观看和关注。 一.什么是计算机视觉 计算机视觉是人工智能的一个分支&#xff0c;它使计算机能够从图像或多维数据中解释和理解视觉信息。计算机视觉的目标是模拟人类视觉系统的能力&#xff0c…

普元EOS-数据实体运行时动态增加property

1 前言 在Java开发读取数据的时候&#xff0c;一般都采用ORM方式将数据表的字段映射到实体对象中。 数据表中有一个字段&#xff0c;实体对象就有一个字段。 但很多时候&#xff0c;我们在读取的数据和显示的数据不同&#xff0c;比如&#xff0c;读取的是部门id&#xff0c…

java多线程(七)AQS(AbstractQueuedSynchronizer)技术解析:以赛跑起跑场景为例

AQS概括 核心思想 AQS&#xff08;AbstractQueuedSynchronizer&#xff09;是Java并发包中的一个核心同步器框架&#xff0c;它定义了一套多线程访问共享资源的同步机制。 其核心思想是&#xff1a;利用一个volatile的int类型的变量state来表示同步状态&#xff0c;并通过一…

微信自动回复,周末也能轻松应对!

相信很多人都有过这样的经历&#xff1a;休息的时候&#xff0c;手机响个不停&#xff0c;生怕漏掉一个客户消息&#xff0c;结果一不小心就让客户流失了&#xff01; 要想解决这个问题&#xff0c;你只需一个多微管理系统&#xff0c;让我们一起来看看它的自动回复设置吧&…

这个方法完美解决我的Jenkins插件不能下载安装的问题

1、打开这个地址&#xff08;前提是jenkins是开启的哦&#xff09;http://localhost:8080/pluginManager/advanced 。 2、在最下面update site 改成http://updates.jenkins.io/update-center.json 。 3、服务列表中关闭jenkins&#xff0c;再重新启动&#xff0c;就能联网下载了…

叉车AI行车防撞监控系统方案,二级报警区域,守护人与车的安全!

九盾叉车AI行车防撞监控系统安装在叉车驾驶室顶的前后单独安装ADAS摄像头&#xff0c;结合深度学习算法以完成机器视觉的识别工作&#xff0c;分别安装在车辆护顶架前后方&#xff0c;进行180二级区域视频监控&#xff0c;同时解决二个方向维度的视野盲区&#xff0c;可根据距离…

数据结构(6.2_4)——图的基本操作

注&#xff1a;只探讨邻接矩阵和邻接表怎么实现图的基本操作 Adjacent(G,x,y):判断图G是否存在边<x,y>或(x,y) 领接矩阵 邻接表 有向图&#xff1a; Neighbors(G,x):列出图G中与结点x邻接的边 有向图 InsertVertex(G,x):在图G中插入顶点x DeleteVertex(G,x):在图G中删除…

【蓝桥杯集训100题】scratch时间计算 蓝桥杯scratch比赛专项预测编程题 集训模拟练习题第26题

目录 scratch时间计算 一、题目要求 编程实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、解题思路 1、思路分析 2、详细过程 四、程序编写 五、考点分析 六、推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 5、python资料 scratc…