Java 生成Gis缓冲区并校验点是否在缓冲区内

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

gis通过GeometryFactory 进行绘制缓冲区,并校验坐标点是否在缓冲区内

通过java来实现缓冲区绘制及点校验


一、缓冲区是什么?

‌GIS缓冲区是地理信息系统(GIS)中的一种空间分析功能,它指的是围绕地理对象(如点、线、多边形实体)一定宽度的区域,用于分析地理对象的影响范围或服务范围。‌

缓冲区分析在GIS中扮演着重要的角色,它不仅可以用来分析地理对象的影响范围,如化工厂排放废气的污染范围或服务范围,洪涝灾害的淹没区,还可以用来表示地理现象的服务范围,如河流的灌溉范围、电力线路的供电范围、超市、医院的服务范围等。缓冲区分析通过计算在点、线、多边形实体周围自动形成满足一定距离要求的区域,这些区域通常用于确定影响范围,是气候评价应用比较多的另一个空间分析功能。

缓冲区的建立有三种基本情况:一是基于点要素的缓冲区,通常以点为圆心、以一定距离为半径的圆;二是基于线要素的缓冲区,通常是以线为中心轴线,距中心轴线一定距离的平行条带多边形;三是基于面要素多边形边界的缓冲区,向外或向内扩展一定距离以生成新的多边形。这种分析方法在农业、城市规划、生态保护等诸多领域都有广泛的应用,是实现数据在二维空间扩展的信息分析方法之一‌

二、使用步骤

Maven 依赖

<dependency>
	<groupId>org.locationtech.jts</groupId>
	<artifactId>jts-core</artifactId>
	<version>1.19.0</version>
</dependency>
<!-- 工具类 -->
<dependency>
   <groupId>cn.hutool</groupId>
   <artifactId>hutool-all</artifactId>
   <version>5.8.27</version>
</dependency>

代码

缓冲区生成

	/**
     * 线缓冲区生成
     * @param distance 距离(米)
     * @param lineStr 线列表 116.403322,39.920255;116.392651,39.914283;116.405433,39.910075
     * @return 缓冲区坐标
     */
    public static String getGeometry(double distance,String lineStr) {
        GeometryFactory geometryFactory = new GeometryFactory();
        //没有线坐标或者没有距离时直接返回
        if(StrUtil.isBlank(lineStr) || distance<1){
            return lineStr;
        }
        String[] lines = lineStr.split(";");
        Coordinate[] coordinates = new Coordinate[lines.length];
        for (int i = 0; i < lines.length; i++) {
            String[] lngLat = lines[i].split(",");
            Coordinate coordinate = new Coordinate(Double.parseDouble(lngLat[0]),Double.parseDouble(lngLat[1]));
            coordinates[i] = coordinate;
        }
        // 创建一条线
        LineString line = geometryFactory.createLineString(coordinates);

        // 缓冲区半径
        double bufferDistance = metersToDegrees(distance);
//        System.out.println(bufferDistance);
        //米 = 缓冲区距离(度) * 111,000 * cos(纬度 * π / 180)
//        System.out.println(bufferDistance);

        // 缓冲区参数
        BufferParameters bufferParameters = new BufferParameters();
        bufferParameters.setEndCapStyle(BufferParameters.CAP_SQUARE);
        bufferParameters.setJoinStyle(BufferParameters.JOIN_ROUND);
        // 设置四分之一段数,控制圆角的平滑程度
        bufferParameters.setQuadrantSegments(8);

        // 缓冲区操作
        BufferOp bufferOp = new BufferOp(line, bufferParameters);

        // 计算缓冲区
        Geometry bufferGeometry = bufferOp.getResultGeometry(bufferDistance);
        // 输出缓冲区的WKT表示
//        System.out.println(bufferGeometry.toText());
        return Arrays.stream(bufferGeometry.getCoordinates()).map(point->point.x+","+ point.y).collect(Collectors.joining(";"));
    }

将米转换为度

    // 地球在赤道的平均半径,单位:米
    private static final double EARTH_RADIUS = 6371000;

    /**
     * 将米转换为经纬度上的角度变化(以度为单位)。
     * 这是一个简化的计算,没有考虑地球的椭球形状和具体的地理位置。
     *
     * @param meters 距离,单位:米
     * @return 角度变化,单位:度
     */
    public static double metersToDegrees(double meters) {
        // 将米转换为弧度
        double radians = meters / EARTH_RADIUS;
        // 将弧度转换为度
        return Math.toDegrees(radians);
    }

校验是否在缓冲区内

代码如下:

    /**
     * 判断是否在多边形区域内
     *
     * @param pointStr  要判断的点坐标
     * @param pointsStr 边界点列表,多个坐标分号分隔,经纬度逗号分隔
     * @return boolean
     */
    public static boolean isInPolygon(String pointStr, String pointsStr) {
        if (StrUtil.isBlank(pointStr) || StrUtil.isBlank(pointsStr) || !pointsStr.contains(",") || pointStr.contains("null") || pointsStr.contains("null")) {
            return false;
        }
        String[] p = pointStr.split(",");
        // 将要判断的横纵坐标组成一个点
        Point2D.Double point = new Point.Double(Double.parseDouble(p[0]), Double.parseDouble(p[1]));
        // 将区域各顶点的横纵坐标放到一个点集合里面
        List<Point2D.Double> polygon = Arrays.stream(pointsStr.split(";")).map(e -> {
            String[] poPoint = e.split(",");
            return new Point2D.Double(Double.parseDouble(poPoint[0]), Double.parseDouble(poPoint[1]));
        }).collect(Collectors.toList());
        return check(point, polygon);
    }
    /**
     * 一个点是否在多边形内
     *
     * @param point   要判断的点的横纵坐标
     * @param polygon 组成的顶点坐标集合
     * @return boolean
     */
    private static boolean check(Point2D.Double point, List<Point2D.Double> polygon) {
        java.awt.geom.GeneralPath peneralPath = new java.awt.geom.GeneralPath();

        Point2D.Double first = polygon.get(0);
        // 通过移动到指定坐标(以双精度指定),将一个点添加到路径中
        peneralPath.moveTo(first.x, first.y);
        polygon.remove(0);
        for (Point2D.Double d : polygon) {
            // 通过绘制一条从当前坐标到新指定坐标(以双精度指定)的直线,将一个点添加到路径中。
            peneralPath.lineTo(d.x, d.y);
        }
        // 将几何多边形封闭
        peneralPath.lineTo(first.x, first.y);
        peneralPath.closePath();
        // 测试指定的 Point2D 是否在 Shape 的边界内。
        return peneralPath.contains(point);
    }

样例

    public static void main(String[] args) {
        String geometry = getGeometry(50,"118.046541,36.869478;118.045225,36.868597;118.045217,36.868739");
        System.out.println("缓冲区:"+geometry);
        System.out.println("是否在缓冲区内:"+isInPolygon(geometry,"116.555,38.555"));
    }

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值