Java中使用JTS实现WKT字符串读取转换线、查找LineString的list中距离最近的线、LineString做缓冲区扩展并计算点在缓冲区内的方位角

这篇具有很好参考价值的文章主要介绍了Java中使用JTS实现WKT字符串读取转换线、查找LineString的list中距离最近的线、LineString做缓冲区扩展并计算点在缓冲区内的方位角。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

场景

Java中使用JTS对空间几何计算(读取WKT、距离、点在面内、长度、面积、相交等):

Java中使用JTS对空间几何计算(读取WKT、距离、点在面内、长度、面积、相交等)_jts-core_霸道流氓气质的博客-CSDN博客

Java+GeoTools实现WKT数据根据EPSG编码进行坐标系转换:

Java+GeoTools实现WKT数据根据EPSG编码进行坐标系转换_霸道流氓气质的博客-CSDN博客

基于gis的业务场景中,需要在地图中录入区域数据的wkt数据,然后根据某个坐标点判断是属于哪个区域,

以及距离所属区域中最近的端点的方位角,比如坐标点位于某区域东南方向100米。

注:

博客:
霸道流氓气质_C#,架构之路,SpringBoot-CSDN博客

实现

1、参考上面引入jts的依赖。

首先数据库中存储的所有线的WKT数据为

Java中使用JTS实现WKT字符串读取转换线、查找LineString的list中距离最近的线、LineString做缓冲区扩展并计算点在缓冲区内的方位角,Java,java,list,python

其中region_name为线的名称,region_wkt为线的wkt字符串。

首先从数据库中读取所有的wkt字符串数据,并转换为map类型数据方便处理以及赋值线的名称到linestring的userData字段。

        List<LineString> regionList = new ArrayList<>();

        Map<String, List<LineString>> regionMap = new HashMap<>();

        //读取录入的区域位置信息
        RegionManagement param = RegionManagement.builder().deleteFlag(false).build();
        List<RegionManagement> regionManagements = regionManagementMapper.selectList(param);
        for (RegionManagement regionManagement : regionManagements) {
            LineString lineString = readWKT(regionManagement.getRegionWKT());
            RegionDTO regionDTO = JSON.parseObject(JSON.toJSONString(regionManagement), RegionDTO.class);
            regionDTO.setUpdateTime(regionManagement.getUpdateTime().toString());
            lineString.setUserData(regionDTO);
            regionList.add(lineString);
        }
        //将区域list流处理为map,方便快速查找
        Map<String, List<RegionManagement>> collect = regionManagements.stream().collect(Collectors.groupingBy(RegionManagement::getRegionName));
        for (String name : collect.keySet()) {
            List<LineString> tmp = new ArrayList<>();
            collect.get(name).forEach(item -> tmp.add(readWKT(item.getRegionWKT())));
            regionMap.put(name, tmp);
        }

这里的RegionManagement用来读取数据库中存储的wkt字符串等数据,实现为

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class RegionManagement {

    private Long id;
    private String regionName;
    private String regionWKT;
    // 0 false ; 1 true
    private boolean deleteFlag;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;

}

调用读取wkt字符串并转换为jts的LineString对象的方法readWKT实现为

    //读取wkt数据为LineString
    public LineString readWKT(String regionWKT){
        GeometryFactory fact = new GeometryFactory();
        WKTReader reader = new WKTReader(fact);
        LineString geometry1 = null;
        try {
            geometry1 = (LineString) reader.read(regionWKT);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return geometry1;
    }

中间获取所需要的数据的RegionDTO的实现为

import lombok.Data;

@Data
public class RegionDTO {
    private Long id;
    private String regionName;
    private String updateTime;
}

2、将要判断方位的坐标值声明为Point2D对象

        //目标点位
        Point2D.Double carPoint = new Point2D.Double(36582834.745, 4259820.7951);

3、获取距离目标点位最近的线

        //获取离目标点位最近的线
        LineString lineString = findNearestLine(carPoint, 10D, regionList);

这里调用的findNearestLine方法的实现

    //查找最近的线,jts工具做线的缓冲区,扩展宽度为10
    public  LineString findNearestLine(java.awt.geom.Point2D.Double point, Double FuzzyLookupRange, List<LineString> lineStringList) {
        Point a = createPoint(point.getX(), point.getY());
        return lineStringList.parallelStream().filter((lineString) -> lineString.buffer(FuzzyLookupRange).contains(a)).min((o1, o2) -> {
            Double ax = o1.distance(a);
            Double axx = o2.distance(a);
            return ax.compareTo(axx);
        }).orElse(null);
    }

这里调用了createPoint用来创建point对象

    //根据坐标x y创建点对象
    public static Point createPoint(Double x, Double y) {
        GeometryFactory a = JTSFactoryFinder.getGeometryFactory();
        return a.createPoint(new Coordinate(x, y));
    }

然后使用lineString.buffer方法对线做缓冲区,扩展宽度为10,即将线向外扩充成类似区域的概念,判断点是否在扩充后

的区域内,如果有多个区域,则取距离最小的一个。

LineString.buffer方法的使用可参考:

Geometry (JTS Topology Suite 1.13 API) - Javadoc Extreme)

Computes a buffer area around this geometry having the given width. The buffer of a Geometry is the Minkowski sum or difference of the geometry

with a disc of radius abs(distance).

Mathematically-exact buffer area boundaries can contain circular arcs.

To represent these arcs using linear geometry they must be approximated with line segments.

The buffer geometry is constructed using 8 segments per quadrant to approximate the circular arcs. The end cap style is CAP_ROUND.

The buffer operation always returns a polygonal result. The negative or zero-distance buffer of lines and points is always an empty Polygon.

 This is also the result for the buffers of degenerate (zero-area) polygons.

直译:

计算具有给定宽度的几何体周围的缓冲区。几何体的缓冲区是具有半径为abs(距离)的圆盘的几何体的Minkowski和或差。

数学上精确的缓冲区边界可以包含圆弧。要使用线性几何图形表示这些圆弧,必须使用线段对其进行近似。

缓冲区几何结构使用每个象限8个线段来近似圆弧。端盖样式为cap_ROUND。

缓冲区操作总是返回多边形结果。直线和点的负或零距离缓冲区始终为空多边形。

这也是退化(零面积)多边形缓冲区的结果。

Java中使用JTS实现WKT字符串读取转换线、查找LineString的list中距离最近的线、LineString做缓冲区扩展并计算点在缓冲区内的方位角,Java,java,list,python

然后获取距离最近的线的名称并输出

        //获取离目标点位最近的线
        LineString lineString = findNearestLine(carPoint, 10D, regionList);
        String regionName = "区域位置为空";
        if (lineString != null) {
            RegionDTO userData = (RegionDTO) lineString.getUserData();
            regionName = userData.getRegionName();
        }

        System.out.println(regionName);

4、获取坐标点相对于该线的方位角

        String azimuth;

        if (!regionName.equals("区域位置为空")) {
            List<LineString> lineStringList = regionMap.get(regionName);
            LineString closeLine;
            if (lineStringList.size() > 1) {
                closeLine = findNearestLine(carPoint, 10D, lineStringList);
            } else {
                closeLine = lineStringList.get(0);
            }
            //获取线的两个端点
            Point startPoint = closeLine.getStartPoint();
            Point endPoint = closeLine.getEndPoint();
            //获取点位到两个端点的距离
            double startDistance = startPoint.distance(createPoint(carPoint.getX(), carPoint.getY()));
            double endDistance = endPoint.distance(createPoint(carPoint.getX(), carPoint.getY()));
            //获取较近的点作为参考点判断方位距离
            if (startDistance <= endDistance) {
                //获取方位角
                azimuth = regionName + DirectionUtil.getAzimuth(startPoint.getX(), startPoint.getY(), carPoint.getX(), carPoint.getY()) + "方向路口" + BigDecimal.valueOf(startDistance).intValue() + "米";
            } else {
                azimuth = regionName + DirectionUtil.getAzimuth(endPoint.getX(), endPoint.getY(), carPoint.getX(), carPoint.getY()) + "方向路口" + BigDecimal.valueOf(endDistance).intValue() + "米";
            }
        } else {
            azimuth = "[" + carPoint.getX() + "," + carPoint.getY() + "]";
        }
        System.out.println(azimuth);

其中获取方位角的工具类DirectionUtil.getAzimuth实现

import org.locationtech.jts.geom.LineSegment;

public class DirectionUtil {

    /**
     * 笛卡尔坐标系
     */
    enum DirectionEnum {
        DUE_EAST("正东", "==0 || ==360"),
        DUE_NORTHEAST("东北", "==45"),
        DUE_NORTH("正北", "==90"),
        NORTH_NORTHWEST("西北", "90<theta<135"),
        DUE_WEST("正西", "==180"),
        WEST_SOUTHWEST("西南", "180<theta<225"),
        DUE_SOUTH("正南", "==270"),
        DUE_SOUTHEAST("东南", "==315");

        private String direction;
        private String describe;

        DirectionEnum(String direction, String describe) {
            this.direction = direction;
            this.describe = describe;
        }

        public String getDirection() {
            return direction;
        }

        public void setDirection(String direction) {
            this.direction = direction;
        }

        public String getDescribe() {
            return describe;
        }

        public void setDescribe(String describe) {
            this.describe = describe;
        }
    }


    /**
     * 获取方位角
     *
     * @param x1 观测点x
     * @param y1 观测点y
     * @param x2 目标点x
     * @param y2 目标点y
     * @return 返回距离观测点的方位角
     */
    public static String getAzimuth(double x1, double y1, double x2, double y2) {
        LineSegment lineSegment = new LineSegment(x1, y1, x2, y2);
        double angle1 = lineSegment.angle();
        double angle = Math.toDegrees(lineSegment.angle());
        if (angle < 0) {
            angle = angle + 360;
        }

        if ((0 < angle && angle < 12.5) || (347.5 < angle && angle < 360)) {
            return DirectionEnum.DUE_EAST.getDirection();
        } else if (12.5 < angle && angle < 77.5) {
            return DirectionEnum.DUE_NORTHEAST.getDirection();
        } else if (77.5 < angle && angle < 102.5) {
            return DirectionEnum.DUE_NORTH.getDirection();
        } else if (102.5 < angle && angle < 167.5) {
            return DirectionEnum.NORTH_NORTHWEST.getDirection();
        } else if (167.5 < angle && angle < 192.5) {
            return DirectionEnum.DUE_WEST.getDirection();
        } else if (192.5 < angle && angle < 257.5) {
            return DirectionEnum.WEST_SOUTHWEST.getDirection();
        } else if (257.5 < angle && angle < 282.5) {
            return DirectionEnum.DUE_SOUTH.getDirection();
        } else if (282.5 < angle && angle < 347.5) {
            return DirectionEnum.WEST_SOUTHWEST.getDirection();
        } else {
            return "ERROR";
        }
    }
}

逻辑就是对比目标点到线的两个端点的距离,取较近的进行判断,然后做方位角判断。

运行效果测试

Java中使用JTS实现WKT字符串读取转换线、查找LineString的list中距离最近的线、LineString做缓冲区扩展并计算点在缓冲区内的方位角,Java,java,list,python文章来源地址https://www.toymoban.com/news/detail-707500.html

到了这里,关于Java中使用JTS实现WKT字符串读取转换线、查找LineString的list中距离最近的线、LineString做缓冲区扩展并计算点在缓冲区内的方位角的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用Java实现高效的字符串匹配算法

    摘要:字符串匹配是计算机领域中的一个重要问题,有着广泛的应用场景。在本篇博客文章中,我们将介绍几种高效的字符串匹配算法,并给出使用Java语言实现的代码示例,希望能对读者理解和应用这些算法有所帮助。 一、KMP算法 KMP算法(Knuth-Morris-Pratt算法)是一种经典的

    2024年02月16日
    浏览(44)
  • java 处理常量字符串过长 & springboot 项目读取 resouces 文件夹下的文件内容

    项目里面有一长串的加密字符串(最长的万多个字符),需要拼接作为参数发送给第三方。 如果我们使用 枚举 定义的话,idea 编译的时候就会出现编译报错 网上还有一个说法,说是编译器问题,修改 idea 工具的编译为 eclipse 即可。 但是结果我仍然不满意,所以我决定把他放在

    2023年04月13日
    浏览(117)
  • springboot yml文件自定义配置的读取、使用 字符串 数组 对象 集合

    .yml 配置 controller代码 实体类 Student.java Users.java User.java 方式一、 http://localhost:9801/test/test1 方式二、 http://localhost:9801/test/test2 方式三、 http://localhost:9801/test/test3 参考: SpringBoot:yml文件详解-CSDN博客 https://www.jb51.net/article/216769.htm

    2024年02月05日
    浏览(51)
  • c++读取字符串字符时出错

    这是我做的一个c++爬虫程序但是在抓取网页的时候string类型传递出现了问题 以下是图片代码  url的值是 \\\"http://desk.zol.com.cn/\\\" 我不知道为什么数据传递会出问题 请大佬指教 后面重新启动一遍编译器查一查断点有突然没问题了 ,真是个玄学的问题。我还以为是mallco出问题了

    2024年02月12日
    浏览(71)
  • Java如何实现截取字符串

    在实际工作中有一些地方需要用到截取字符串的方法,所以在此记录下截取字符串的几种方法。 .substring() StringUtils.substring() split()+正则表达式 这个是比较常用的一个方法。 此方法有两种形式: 实例代码: 需要注意的是: 计数从0开始 ,如果超过了字符串长度则会报错: 计

    2023年04月18日
    浏览(48)
  • 字符串去重(Java实现)

    步骤 输入字符串 字符串转换成字符串数组 数组转换为List集合 将List集合转化为Set集合(Set集合不允许重复值) Set集合转换为数组 数组拼接成字符串 具体代码实现如下: 其实原理很简单,就是利用Set集合的特性来消除重复元素。

    2024年02月13日
    浏览(31)
  • Java实现字符串加密与解密

    我们在设计登录程序时需要用到保存用户名和密码的功能,如果是直接写入到txt文件中保存很容易被木马程序识破,所以就必须先对密码加密,只留存密文。 今天介绍的是使用 十六进 制转换的方式加密数据。 得到结果: 757376662d312d6d7064626d697074752d323534342d717974646b 现在我们将

    2024年02月11日
    浏览(52)
  • 如何读取带空格的字符串?

    scanf()函数在读取字符时,识别到空格就会终止读取,那么如何读取带空格的字符串呢? 从标准输入(stdin)(指的是键盘输入)读取字符,并将它们作为 C 字符串存储到 str 中,直到达到换行字符或文件末尾。 即gets()函数会一直读取字符直到遇到换行符n(回车)或文件末尾截

    2024年02月07日
    浏览(60)
  • Java实现两字符串相似度算法

    编辑距离:是衡量两个字符串之间差异的度量,它表示 将一个字符串转换为另一个字符串所需的最少编辑操作次数 (插入、删除、替换)。 计算方法可以有多种,其中一种 常见 的方法是 将编辑距离归一化为0到1之间的范围 (归一化编辑距离(Normalized Edit Distance)), 将编

    2024年02月05日
    浏览(74)
  • Java使用substring()方法截取字符串

    substring()方法是java String类的常用方法,作用是返回字符串的子字符串。 beginIndex是起始索引值(包括),从0开始。该方法将字符串从beginIndex位置开始截取,一直到字符串末尾。 示例: 输出: beginIndex是起始索引值(包括),从0开始,endIndex是结束索引值(不包括)。该方法

    2024年02月13日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包