判断[点]是否在[多边形]内的三种方法

Oracle
Oracle Database 21c Express Edition Release 21.0.0.0.0
-- OracleSpatial函数
SELECT 
	sdo_inside( 
		sdo_geometry( 
			2001, 
			NULL, 
			SDO_POINT_TYPE(
				118.439140, 
				31.385456, 
				NULL
			), 
			NULL, 
			NULL 
		), 
		SDO_GEOMETRY( 
			2003, 
			NULL, 
			NULL, 
			sdo_elem_info_array(
				1, 
				2003, 
				2
			), 
			SDO_ORDINATE_ARRAY( 
				118.392992, 31.381136 , 
				118.39694, 31.377399 , 
				118.433933, 31.378169 , 
				118.479852, 31.372599 , 
				118.510322, 31.366883 , 
				118.51663, 31.394503 , 
				118.435605, 31.436145 , 
				118.392992, 31.381136 -- [闭合多边形,终点需与起点保持一致]
			) 
		) 
	) 
FROM DUAL 
;

Java
/**
 * <p>
 * 经纬度DTO
 * </p>
 *
 * @author jpge
 * @since 2024/04/28
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GeoPoint implements Serializable {

    private static final long serialVersionUID = 4815643503634826077L;

    /**
     * 经度
     */
    private BigDecimal longitude;

    /**
     * 纬度
     */
    private BigDecimal latitude;

}
   /**
     * 检查多边形是否包含了某点
     *
     * @param vertices 多边形顶点
     * @param point    某点[非闭合多边形,即最开始点只会出现一次,最终点不为最开始点]
     * @return 是否包含
     */
    public boolean containsPointJava(GeoPoint point, List<GeoPoint> vertices) {
        int verticesCount = vertices.size();
        int nCross = 0;
        for (int i = 0; i < verticesCount; ++i) {
            GeoPoint p1 = vertices.get(i);
            GeoPoint p2 = vertices.get((i + 1) % verticesCount);

            // 求解 y=p.y 与 p1 p2 的交点
            if (p1.getLatitude().equals(p2.getLatitude())) {   // p1p2 与 y=p0.y平行
                continue;
            }
            if (
                    point.getLatitude().compareTo(
                            p1.getLatitude().min(p2.getLatitude())
                    ) < 0
            ) { // 交点在p1p2延长线上
                continue;
            }
            if (
                    point.getLatitude().compareTo(
                            p1.getLatitude().max(p2.getLatitude())
                    ) >= 0
            ) { // 交点在p1p2延长线上
                continue;
            }
            // 求交点的 X 坐标
            BigDecimal x =
                    (point.getLatitude().subtract(p1.getLatitude())
                    ).multiply(p2.getLatitude().subtract(p1.getLatitude()))
                            .divide(
                                    (p2.getLatitude().subtract(p1.getLatitude())
                                    ).add(p1.getLatitude()), RoundingMode.HALF_UP);
            if (x.compareTo(point.getLatitude()) > 0) { // 只统计单边交点
                nCross++;
            }
        }
        // 单边交点为偶数,点在多边形之外
        return (nCross % 2 == 1);
    }

GeoTools
        <!-- https://mvnrepository.com/artifact/org.geotools/gt-main -->
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-main</artifactId>
            <version>${geotools.version}</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/lib/gt-main-24.0.jar</systemPath>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.geotools/gt-main -->
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-metadata</artifactId>
            <version>${geotools.version}</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/lib/gt-metadata-24.7.jar</systemPath>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.geotools/gt-main -->
        <dependency>
            <groupId>org.locationtech</groupId>
            <artifactId>jts-core</artifactId>
            <version>1.16.0-RC1</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/lib/jts-core-1.16.0-RC1.jar</systemPath>
        </dependency>
        
        
        
        
	<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
                    <includeSystemScope>true</includeSystemScope>
                </configuration>
            </plugin>
        </plugins>
    </build>

	/**
     * 判断点是否在范围内
     *
     * @param point  点
     * @param radius 范围[非闭合多边形,即最开始点只会出现一次,最终点不为最开始点][方法内会处理为闭合多边形]
     * @return 是否在范围内
     */
    @Override
    public boolean containsPointGeoTools(GeoPoint point, List<GeoPoint> radius) {

        List<Coordinate> collect = radius.stream().map(
                geoPoint -> new Coordinate(
                        geoPoint.getLongitude().doubleValue(),
                        geoPoint.getLatitude().doubleValue()
                )
        ).collect(Collectors.toList());

        collect.add(
                new Coordinate(
                        radius.get(0).getLongitude().doubleValue(),
                        radius.get(0).getLatitude().doubleValue()
                )
        );


        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();

        // 定义多边形的坐标序列,顺序很重要,需要按照顺时针或逆时针顺序给出
        Coordinate[] coordinates = new Coordinate[collect.size()];
        collect.toArray(coordinates);

        LinearRing linearRing = geometryFactory.createLinearRing(coordinates);
        Polygon polygon = geometryFactory.createPolygon(linearRing, null);

        // 待判断的点
        Coordinate pointToCheck = new Coordinate(
                point.getLongitude().doubleValue(),
                point.getLatitude().doubleValue()
        );

        // 判断点是否在多边形内
        return polygon.contains(geometryFactory.createPoint(pointToCheck));
    }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值