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;
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

儿时可乖了

混口饭吃,大佬们,赏点吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值