java jts获取线上任意一点到起点的距离

java jts获取线上任意一点到起点的距离

近期项目要求计算某段公路上一辆车的运行轨迹,通过路上的设备实时获取车辆的经纬度信息并发送到后台接收。
抽象出来就是获取线上任意一点到起点的距离,按照一定每秒一次的频率去计算就获取该点的运动轨迹了。
主要通过使用jts的工具类来计算。

<dependency>
            <groupId>com.vividsolutions</groupId>
            <artifactId>jts</artifactId>
            <version>1.13</version>
</dependency>

jts使用样例
jts官方API文档
期间需要将经纬度转换成平面坐标。这里使用墨卡托进行坐标转换。
具体参考了如下文章,本文就不再引用了直接使用其工具类。
墨卡托经纬度转换平面坐标

正文代码如下:

@Data
@NoArgsConstructor
public class ExtLine {
    private String wkt;//原始的线的wkt信息
    private JSONObject geojson;
    private Coordinate[] coordinates;//组成线的每个端点的信息(经纬度已转换成平面坐标)
    private LineString line;//经过墨卡托转换后的线的对象
    private Double[] distances;//保存每个节点距离起点的距离
}
/**
     * @param wkt  原始线的wkt信息  需要经过墨卡托转换
     * @return ExtLine
     * 通过wkt创建ExtLine  该类中包含了各个点位的距离起点信息
     * */
    public static ExtLine createExtLine(String wkt) throws ParseException {
        WKTReader reader = new WKTReader();
        LineString lineString = (LineString) reader.read(wkt);
        ExtLine extLine = new ExtLine();
        extLine.setWkt(wkt);
        Coordinate[] row = lineString.getCoordinates();
        Coordinate[] result = new Coordinate[row.length];
        Double[] distance = new Double[row.length];
        for (int i = 0; i < row.length; i++) {
            double lng = row[i].x;
            double lat = row[i].y;
            double rate = Math.cos(Math.toRadians(lat));//墨卡托转成平面坐标计算距离时会拉伸长度使得结果偏大,需要对结果乘以当前纬度的cos值
            Map<String, Double> tmp = new HashMap<>();
            tmp = CoordConverter.convertLL2MC(lng, lat);//经过墨卡托转换
            Coordinate coordinate = new Coordinate(tmp.get("x"), tmp.get("y"));
            result[i] = coordinate;
            if (i == 0) {
                //起点位置
                distance[0] = 0.0D;
            } else {
                //计算并保存每个节点距离起点的长度
                LineString tempLine = geometryFactory.createLineString(Arrays.copyOf(result,i+1));
                distance[i] = tempLine.getLength() * rate;
            }
        }
        extLine.setDistances(distance);
        extLine.setCoordinates(result);
        extLine.setLine(geometryFactory.createLineString(result));
        System.out.println(distance[row.length-1]);
        return extLine;
    }

    /**
     * @param extLine  将上一步的计算好距离的信息对象传入
     * @param wkt 某点的wkt信息
     * @return double 返回某条线上的起点到某点的距离
     * */
    public static double getDistance(ExtLine extLine,String wkt) throws ParseException {
        WKTReader reader = new WKTReader();
        Point point = (Point) reader.read(wkt);//获取某点的信息(不一定要在线上)
        Coordinate coordinate = point.getCoordinate();
        double lng = coordinate.x;
        double lat = coordinate.y;
        Map<String,Double> map = CoordConverter.convertLL2MC(lng,lat);//将经纬度转换成平面坐标
        Coordinate transCoordinate = new Coordinate(map.get("x"),map.get("y"));
        LineString lineString = extLine.getLine();
        LocationIndexedLine indexedLine = new LocationIndexedLine(lineString);
        LinearLocation linearLocation = indexedLine.indexOf(transCoordinate);
        int index = linearLocation.getSegmentIndex();//获取某点距离线上最近的节点的index
        Coordinate[] coordinates = extLine.getCoordinates();
        Coordinate lastPoint = coordinates[index];
        System.out.println(index);
        LineString temp = geometryFactory.createLineString(new Coordinate[]{lastPoint,transCoordinate});//计算线上距离某点最近的点和某点的距离  
        double distance = temp.getLength()+extLine.getDistances()[index];//两者相加即所求距离
        return distance;
    }

代码的图片说明如下:

线由节点1,2,3,4,5组成,需要计算点6到起点的距离(非计算点1和点6的直线距离 这样误差太大了) 需要计算点1-4的距离 这个步骤在createExtLine时就完成了 后续只需传入ExtLine 和点6的wkt 计算点4和点6的距离 d1 最后把点1-4的距离d2 return d1+d2即可。
如何计算点6距离线上某个节点最近通过linearLocation.getSegmentIndex();即可得到最近的前一个节点。

第一次写博客感觉写的不是很清楚,希望对这方面有需求的朋友有所帮助吧。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值