手写GIS二三维地理空间几何计算GeoTools工具类

Posted 洛阳泰山

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写GIS二三维地理空间几何计算GeoTools工具类相关的知识,希望对你有一定的参考价值。

 简介

  为了丰富网络上java gis空间计算的技术文章,我费了不少功夫,看了第三方开源工具geotools包的源码,把常用的几个计算封装成了一个工具类。目前工具类提供的方法有:

  1. polylineDivide 折线等分方法,就是把线段分成若干相等的点,求出分割点的坐标。
  2. pointAlong 根据某点占比线段的比例,求出该点的坐标。
  3. onLineSegment 判断点是否在线段上
  4. onLine 判断点是否在一条直线上
  5. midPoint 求线段中心点坐标
  6. nearestLineSegment 求距离目标点最近的线段
  7. distance 求某点到线段的距离 和 某点到某点的距离
  8. closestPoint 求目标点 ,距离线段上的最近点
  9. project  求目标点 在线段上的投影点
  10. projectionFactor 求目标点 在线段上的投影的投影系数

pom文件引入第三方jar包

       <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-main</artifactId>
            <version>24.3</version>
        </dependency>

 gis空间几何计算工具类代码(二维的计算,z坐标传0即可)


import org.geotools.geometry.jts.GeometryBuilder;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.LineSegment;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.Point;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class GeoTools 


    /**
     * 方法描述:  折线等分
     *
     * @param p0  起点
     * @param p1  终点
     * @param num 等分数
     * @throws
     * @Return @link List< Coordinate>
     * @author tarzan
     * @date 2022年02月22日 14:11:09
     */
    public static List<Coordinate> polylineDivide (Coordinate p0, Coordinate p1, int num) 
        double factor=1.0D/num;
        int points=num-1;
        List<Coordinate> coordinates = new ArrayList<>(points);
        for (int i = 0; i < points; i++) 
            coordinates.add(pointAlong(p0,p1,factor*(i+1)));
        
        return coordinates;
    

    /**
     * 方法描述: 线段比例点坐标计算
     *
     * @param p0
     * @param p1
     * @param factor
     * @return @link Coordinate
     * @throws
     * @author tarzan
     * @date 2022年02月23日 13:49:52
     */
    public static Coordinate pointAlong(Coordinate p0,Coordinate p1,double factor) 
        Coordinate coord = new Coordinate();
        coord.x = p0.x + factor * (p1.x - p0.x);
        coord.y = p0.y + factor * (p1.y - p0.y);
        coord.z = p0.y + factor * (p1.z - p0.z);
        return coord;
    

    /**
     * 方法描述:  判断点是否在线段上
     *
     * @param p     给定点
     * @param p0 线段开始点坐标
     * @param p1   线段结束点坐标
     * @Return @link boolean
     * @author tarzan
     * @date 2022年02月20日 16:51:49
     */
    public static boolean onLineSegment (Coordinate p, Coordinate p0, Coordinate p1) 
        double total = distance(p0, p1);
        double toStart = distance(p, p0);
        double toEnd = distance(p, p1);
        double diff = total - toEnd - toStart;
        return diff==0;
    
    /**
     * 方法描述:  判断点是否在一条直线上
     *
     * @param p     给定点
     * @param p0 线段开始点坐标
     * @param p1   线段结束点坐标
     * @Return @link boolean
     * @author tarzan
     * @date 2022年02月22日 16:51:49
     */
    public static boolean onLine(Coordinate p, Coordinate p0, Coordinate p1) 
        double lsLen = distance(p0, p1);
        double toStart = distance(p, p0);
        double toEnd = distance(p, p1);
        double diff = lsLen - toEnd - toStart;
        if(diff==0) return true;
        diff = toEnd - toStart - lsLen;
        if(diff==0) return true;
        diff = toStart - toEnd - lsLen;
        if(diff==0) return true;
        return false;
    


    /**
     * 方法描述: 线段中间点
     *
     * @param p0
     * @param p1
     * @return @link Coordinate
     * @throws
     * @author tarzan
     * @date 2022年02月23日 09:33:01
     */
    public static Coordinate midPoint(Coordinate p0, Coordinate p1) 
        return new Coordinate((p0.x + p1.x) / 2.0D, (p0.y + p1.y) / 2.0D, (p0.z + p1.z) / 2.0D);
    

    /**
     * 方法描述: 获取点离多段线最近的线及投影点
     *
     * @param
     * @return LineSegment
     * @auther tarzan
     * @date 2022年02月28日 14:09:10
     */
    public static LineSegment nearestLineSegment(Coordinate p, List<LineSegment> lines) 
        double distance = Double.MAX_VALUE;
        LineSegment result = null;
        for (LineSegment ls : lines) 
            double distance2 = distance(p,ls.p0,ls.p1);
            distance = Double.min(distance, distance2);
            if (distance2 <= distance) 
                result=ls;
            
        
        return result;
    

    /**
     * 方法描述: 点到线的距离
     *
     * @param p
     * @param p0
     * @param p1
     * @return @link double
     * @throws
     * @author tarzan
     * @date 2022年02月23日 09:21:13
     */
    public static double distance(Coordinate p, Coordinate p0,Coordinate p1) 
        GeometryBuilder builder = new GeometryBuilder();
        Point point = builder.pointZ(p.x, p.y, p.z);
        LineString ls = builder.lineStringZ(p0.x, p0.y, p0.z, p1.x, p1.y, p1.z);
        return point.distance(ls);
    

    /**
     * 方法描述:  点与点的距离
     *
     * @param p0
     * @param p1
     * @return @link double
     * @throws
     * @author tarzan
     * @date 2022年02月23日 09:30:03
     */
    public static double distance(Coordinate p0,Coordinate p1) 
        return p0.distance3D(p1);
    

    /**
     * 方法描述:  转换点坐标
     *
     * @param x
     * @param y
     * @param z
     * @return @link Coordinate
     * @throws
     * @author tarzan
     * @date 2022年02月22日 10:35:28
     */
    public static Coordinate getCoordinate(BigDecimal x, BigDecimal y, BigDecimal z)
        if(x==null)
            x=BigDecimal.ZERO;
        
        if(y==null)
            y=BigDecimal.ZERO;
        
        if(z==null)
            z=BigDecimal.ZERO;
        
        Coordinate coordinate=new Coordinate(x.doubleValue(),y.doubleValue(),z.doubleValue());
        return coordinate;
    


    /**
     * 方法描述:  点与线最近点计算
     *
     * @param p    给定点
     * @param p0 起始点
     * @param p1   结束点
     * @throws
     * @Return @link Coordinate
     * @author tarzan
     * @date 2021年08月03日 18:01:42
     */
    public static Coordinate closestPoint (Coordinate p, Coordinate p0, Coordinate p1) 
        double factor = projectionFactor(p,p0,p1);
        if (factor > 0.0D && factor < 1.0D) 
            return project(p,p0,p1);
         else 
            double dist0 = p0.distance3D(p);
            double dist1 = p1.distance3D(p);
            return dist0 < dist1 ? p0 : p1;
        
    

    /**
     * 方法描述: 点在线上的投影
     *
     * @param p
     * @param p0
     * @param p1
     * @return @link org.locationtech.jts.geom.Coordinate
     * @throws 
     * @author tarzan
     * @date 2022年02月23日 09:25:31
     */
    public static Coordinate project(Coordinate p,Coordinate p0, Coordinate p1) 
        if (!p.equals3D(p0) && !p.equals3D(p1)) 
            double r = projectionFactor(p,p0,p1);
            Coordinate coord = new Coordinate();
            coord.x = p0.x + r * (p1.x - p0.x);
            coord.y = p0.y + r * (p1.y - p0.y);
            coord.z = p0.z + r * (p1.z - p0.z);
            return coord;
         else 
            return new Coordinate(p);
        
    

    /**
     * 方法描述:  投影系数
     *
     * @param p
     * @param p0
     * @param p1
     * @return @link double
     * @throws
     * @author tarzan
     * @date 2022年02月23日 09:26:33
     */
    private static double projectionFactor(Coordinate p,Coordinate p0,Coordinate p1) 
        if (p.equals3D(p0)) 
            return 0.0D;
         else if (p.equals3D(p1)) 
            return 1.0D;
         else 
            return distance(p,p0,p1);
        
    




创作不易,花了不少时间和精力,如果对你有帮助,请点赞收藏,谢谢!!!

以上是关于手写GIS二三维地理空间几何计算GeoTools工具类的主要内容,如果未能解决你的问题,请参考以下文章

3D-GIS地理信息系统项目实施及目标

什么是空间数据模型他对GIS技术及其应用有何重要性

3D-GIS地理信息系统研发解决方案

GIS开发:GeoJSON文件压缩

打造开源GIS方案

地理空间云怎么找矢量图