Java判断Geometry点是否在线Geometry LineString上

Java判断Geometry点是否在线上

这篇博客将实现一个简单的算法,判断地图上的一个点是否在已知的一条线上;首先地球为球面,经纬度为double类型保留有6~14位小数,直接的求距离不太合适。

Geometry point Geometry lineString
尝试了 lineString.intersects(point)、lineString.contains(point)、point.within(lineString) 都不起作用;

这里Amap提供了一个思路:求距离误差在分辨率的范围内就认为点在线上;

1. 效果图

效果图如下:分别为距离误差在分辨率大小、1/10分辨率、1/100分辨率、1/500分辨率就认为在点在线上。

可以看到距离误差越大,更多的点会被包括进来;
在这里插入图片描述

2. 源码

package com.demo.process;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;

import java.io.IOException;

/*************************************
 *Class Name: GeometryUtil
 *Description: <几何相关的操作类>
 *@author: Seminar
 *@since 1.0.0
 *************************************/
public class GeometryUtil {
    
    

    // 地球半径
    private static final double EARTH_RADIUS = 6378137;
    private static GeometryFactory gf = new GeometryFactory();

    /**
     * wkt 转geometry
     *
     * @param wkt
     * @return
     * @throws ParseException
     */
    public static Geometry wkt2Geo(String wkt) throws ParseException {
    
    
        WKTReader reader = new WKTReader(gf);
        Geometry geom = reader.read(wkt);
        return geom;
    }

    /**
     * 计算两个点之间的距离
     *
     * @param p1
     * @param p2
     * @return
     */
    public static double distance(Point p1, Point p2) {
    
    
        return distance(p1.getCoordinate(), p2.getCoordinate());
    }

    private static double haverSin(double theta) {
    
    
        double v = Math.sin(theta / 2);
        return v * v;
    }

    /**
     * 计算球面两点距离
     *
     * @param p1
     * @param p2
     * @return
     */
    public static double distance(Coordinate p1, Coordinate p2) {
    
    
        // 用haversine公式计算球面两点间的距离。
        // 经纬度转换成弧度
        double lat1 = Math.toRadians(p1.y);
        double lon1 = Math.toRadians(p1.x);
        double lat2 = Math.toRadians(p2.y);
        double lon2 = Math.toRadians(p2.x);
        // 差值
        double vLon = Math.abs(lon1 - lon2);
        double vLat = Math.abs(lat1 - lat2);
        // h is the great circle distance in radians, great
        // circle就是一个球体上的切面,它的圆心即是球心的一个周长最大的圆。
        double h = haverSin(vLat) + Math.cos(lat1) * Math.cos(lat2) * haverSin(vLon);
        double distance = 2 * EARTH_RADIUS * Math.asin(Math.sqrt(h));
        return distance;
    }

    /**
     * 判断点是否在线上
     *
     * @param a          点A
     * @param start      线起点start
     * @param end        线终点end
     * @param resolution 误差范围m
     * @return
     */
    public static boolean isPointOnSegment(Point a, Point start, Point end, double resolution) {
    
    
        boolean flag = false;
        double startAdis = distance(a, start);
        double endADis = distance(a, end);
        double dis = distance(start, end);
        if (startAdis + endADis >= dis - resolution && startAdis + endADis <= dis + resolution) {
    
    
            return true;
        }
        return flag;
    }

    public static void main(String[] args) throws ParseException, IOException {
    
    
        // 线几何
        String lineString = "LINESTRING (117.18292236328126 40.16208338164619, 119.01489257812501 39.48284540453334)";
        // 多点几何
        String multPoints = "MULTIPOINT ((118.23143005371095 39.64059509088577),(118.23143005371095 39.64006632964757),(118.23143005371095 39.639537564366705),(118.23211669921876 39.77476948529546),(118.23211669921876 39.77424175134451))";
        Geometry line = wkt2Geo(lineString);
        Geometry mulpoint = wkt2Geo(multPoints);
        double resolution = 305.7481;
        for (Coordinate coordinate : mulpoint.getCoordinates()) {
    
    
            // 判断点是否在线上
            Point point = gf.createPoint(coordinate);
            // 判断点是否在线上  geom.intersects(point)、point.within(geom) 这俩方法都不管用,以1/20分辨率当作误差范围
            if (isPointOnSegment(point, gf.createPoint(line.getCoordinates()[0]), gf.createPoint(line.getCoordinates()[1]), resolution)) {
    
    
                System.out.println(point.getCoordinate() + " on line");
            } else {
    
    
                System.err.println(point.getCoordinate() + " not on line");
            }
        }
    }
}

参考

猜你喜欢

转载自blog.csdn.net/qq_40985985/article/details/119000819
今日推荐