Python矩形和圆的关系,矩形和多边形的关系

目录

一、基本思路

二、矩形和圆的关系

验证思路

三、矩形和多边形的关系

验证思路:


一、基本思路

本文主要处理的是相交和不相交,因为地理数据保存较多,需要运用最小外接矩阵

1.根据radius_2_coordinate方法获得圆的最小外接矩阵

# 获取多边形的最小外接矩阵            
max = np.max(num['polygonArr'], axis=0)
min = np.min(num['polygonArr'], axis=0)

2.筛选原矩阵与最小外接矩阵的交集

3.循环交集的内容,使用intersect_check_garden验证圆,使用intersect_check_polygon验证多边形

二、矩形和圆的关系

验证思路

圆和矩阵存在多种关系:圆在矩阵内,圆与矩阵相交,矩阵在圆内,圆与矩阵不相交。我的实际需求分析后发现,矩阵在园内与圆与矩阵相交可以同时验证。

1.圆在矩阵内

主要使用isInPolygon方法判断圆的圆心是否在矩阵内。

2.圆与矩阵相交,矩阵在圆内

运用的主要思路:计算圆心到矩阵四个边的最短距离,与圆的半径比较,存在小于半径的值,就是圆与矩阵相交,矩阵在圆内关系,反之,圆与矩阵不相交

import numpy as np
import math
from math import cos


def coordinate_2_radius(Longitude, Latitude):
    '''
    参考地址:https://blog.csdn.net/Dust_Evc/article/details/102847870?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-7.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-7.control
    度数与弧度转化公式:1°=π/180°,1rad=180°/π。
    地球半径:6371000M
    地球周长:2 * 6371000M  * π = 40030173
    纬度38°地球周长:40030173 * cos38 = 31544206M
    任意地球经度周长:40030173M
    经度(东西方向)1M实际度:360°/31544206M=1.141255544679108e-5=0.00001141
    纬度(南北方向)1M实际度:360°/40030173M=8.993216192195822e-6=0.00000899
    '''
    # R = 6371000
    # L = 2 * math.pi * R
    Lng_l = 40030173  # 当前经度地球周长
    Lat_l = Lng_l * cos(Latitude * math.pi / 180)  # 当前纬度地球周长,弧度转化为度数
    # print(Lat_l)
    Lat_C = Lat_l / 360
    Lng_C = Lng_l / 360
    Latitude_m = Latitude * Lat_C
    Longitude_m = Longitude * Lng_C
    return Latitude_m, Longitude_m


def radius_2_coordinate(Longitude, Latitude, radius):
    '''
    参考地址:https://blog.csdn.net/Dust_Evc/article/details/102847870?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-7.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-7.control
    度数与弧度转化公式:1°=π/180°,1rad=180°/π。
    地球半径:6371000M
    地球周长:2 * 6371000M  * π = 40030173
    纬度38°地球周长:40030173 * cos38 = 31544206M
    任意地球经度周长:40030173M
    经度(东西方向)1M实际度:360°/31544206M=1.141255544679108e-5=0.00001141
    纬度(南北方向)1M实际度:360°/40030173M=8.993216192195822e-6=0.00000899
    '''
    Lng_l = 40076000  # 当前经度地球周长
    Lat_l = Lng_l * cos(Latitude * math.pi / 180)  # 当前纬度地球周长,弧度转化为度数
    Lat_C = Lat_l / 360
    Lng_C = Lng_l / 360
    radius_lat = radius / Lat_C
    radius_lng = radius / Lng_C
    # print(radius_lng, radius_lat)
    return radius_lat, radius_lng


def isInPolygon(point, polygon):  ##  检测点是否在多边形内,输入([x,y], polygon_list也就是点组成的list)
    # 使用水平射线检测
    x, y = point[0], point[1]
    nCross = 0
    for i in range(len(polygon)):
        p1 = polygon[i]
        p2 = polygon[(i + 1) % len(polygon)]
        # 特殊情况:边界p1p2 与 y=p0.y平行,不计数
        if (p1[1] == p2[1]): continue
        # 交点在p1p2延长线上,注意是小于,不计数
        if (y < min(p1[1], p2[1])): continue
        # 交点在p1p2延长线上,注意是大于等于,不计数
        if (y >= max(p1[1], p2[1])): continue
        # 求交点的 X 坐标;根据相似三角形计算
        crossx = (y - p1[1]) * (p2[0] - p1[0]) / (p2[1] - p1[1]) + p1[0]
        # 只统计单边交点
        if (crossx >= x):
            nCross = nCross + 1
    # min_dis = get_dis_point2polygon(point, polygon)
    # if abs(min_dis)<1e-2:  ##  求点到哪个边距离最小,是否为0,为0则表示在边界上
    #     return 1
    return (nCross % 2 == 1)


def get_nearest_distance(point, line):
    # 获取线段 与 点的最短距离
    # print('get_nearest_distance')

    def get_foot(point, line):
        # 获取直线 与 点的垂足
        start_x, start_y = line[0], line[1]
        end_x, end_y = line[2], line[3]
        pa_x, pa_y = point

        p_foot = [0, 0]
        if line[0] == line[3]:
            p_foot[0] = line[0]
            p_foot[1] = point[1]
            return p_foot
        k = (end_y - start_y) * 1.0 / (end_x - start_x)
        a = k
        b = -1.0
        c = start_y - k * start_x
        p_foot[0] = (b * b * pa_x - a * b * pa_y - a * c) / (a * a + b * b)
        p_foot[1] = (a * a * pa_y - a * b * pa_x - b * c) / (a * a + b * b)
        return p_foot

    def get_nearest_point(point, line):
        #  计算点到线段的最近点
        pt1_x, pt1_y = line[0], line[1]
        pt2_x, pt2_y = line[2], line[3]
        point_x, point_y = point[0], point[1]
        if (pt2_x - pt1_x) != 0:
            k = (pt2_y - pt1_y) / (pt2_x - pt1_x)
            # 该直线方程为:
            # y = k* ( x - pt1_x) + pt1_y
            # 其垂线的斜率为 - 1 / k,
            # 垂线方程为:
            # y = (-1/k) * (x - point_x) + point_y
            # 联立两直线方程解得:
            x = (k ** 2 * pt1_x + k * (point_y - pt1_y) + point_x) / (k ** 2 + 1)
            y = k * (x - pt1_x) + pt1_y
            return (x, y)
        elif min(pt1_y, pt2_y) < point[1] < max(pt1_y, pt2_y):
            return get_foot(point, line)
        else:
            l1 = np.hypot(pt1_y - point[1], pt1_x - point[0])
            l2 = np.hypot(pt2_y - point[1], pt2_x - point[0])
            return (pt1_x, pt1_y) if l1 < l2 else (pt2_x, pt2_y)

    nearest_point = get_nearest_point(point, line)
    # print(nearest_point)
    x, y = coordinate_2_radius(nearest_point[0], nearest_point[1])
    point_x, point_y = coordinate_2_radius(point[0], point[1])
    distance = math.sqrt((x - point_x) * (x - point_x) + (y - point_y) * (y - point_y))
    # print(nearest_point[0], nearest_point[1], point[0], point[1], distance)
    return distance


def intersect_check_garden(point_lng, point_lat, radius, q1_x, q1_y, q2_x, q2_y, q3_x, q3_y, q4_x, q4_y):
    """
    与园的相交检查
    """
    # print('intersect_check_garden')
    radius_lng, radius_lat = radius_2_coordinate(point_lng, point_lat, radius)

    # point_lng_max = point_lng + radius_lng
    # point_lng_min = point_lng - radius_lng
    # point_lat_max = point_lat + radius_lat
    # point_lat_min = point_lat - radius_lat
    # # 1.圆在图形内
    # xmin = min(q1_x, q2_x, q3_x, q4_x)
    # xmax = max(q1_x, q2_x, q3_x, q4_x)
    # ymin = min(q1_y, q2_y, q3_y, q4_y)
    # ymax = max(q1_y, q2_y, q3_y, q4_y)
    if isInPolygon([point_lng, point_lat], [[q1_x, q1_y], [q2_x, q2_y], [q3_x, q3_y], [q4_x, q4_y]]):
        print("圆在图形内")
        return True

    # if xmin < point_lng_max < xmax and xmin < point_lng_min < xmax:
    #     return True
    #
    # if ymin < point_lat_max < ymax and ymin < point_lat_min < ymax:
    #     return True
    # 2.圆与图形相交为True,圆在图形不想交相交为False,
    distance1 = get_nearest_distance([point_lng, point_lat], [q1_x, q1_y, q2_x, q2_y])
    if distance1 < radius:
        return True
    distance2 = get_nearest_distance([point_lng, point_lat], [q2_x, q2_y, q3_x, q3_y])
    if distance2 < radius:
        return True
    distance3 = get_nearest_distance([point_lng, point_lat], [q3_x, q3_y, q4_x, q4_y])
    if distance3 < radius:
        return True
    distance4 = get_nearest_distance([point_lng, point_lat], [q4_x, q4_y, q1_x, q1_y])
    if distance4 < radius:
        return True
    distance5 = get_nearest_distance([point_lng, point_lat], [q1_x, q1_y, q3_x, q3_y])
    if distance5 < radius:
        return True
    distance6 = get_nearest_distance([point_lng, point_lat], [q2_x, q2_y, q4_x, q4_y])
    if distance6 < radius:
        return True
    return False

三、矩形和多边形的关系

本文主要处理的是相交和不相交,基本思路:

验证思路:

多边形和矩阵存在多种关系:多边形在矩阵内,多边形与矩阵相交,矩阵在多边形内,多边形与矩阵不相交。我的实际需求分析后发现,矩阵在多边形内和多边形与矩阵相交可以同时验证。

1.多边形在矩阵内

主要使用isInPolygon方法判断圆的圆心是否在矩阵内。

2.多边形与矩阵相交,矩阵在多边形内

思路:根据矩阵的4个点左边,生成4条线段,根据line_polygon方法判断线段与多边形的关系(根据实际需要等分,我这里是10等分,每个点计算与多边形的关系)

def intersect_check_polygon(polygon, q1_x, q1_y, q2_x, q2_y, q3_x, q3_y, q4_x, q4_y):
    """
    与多边形的相交检查
    polygon:多边形的list
    """

    def get_points(start_x, start_y, end_x, end_y):
        # print(start_x, start_y, end_x, end_y)
        if end_x - start_x != 0:
            k = (end_y - start_y) * 1.0 / (end_x - start_x)
            # y = start_y + k * (x - start_x)  # 2个点组成的直线
            division = 10  # 线段切割次数
            point_list = []  # 线段上点的集合
            for i in range(0, division):
                x = start_x * i / 10 + start_x
                if x < end_x:
                    y = start_y + k * (x - start_x)
                    point_list.append([x, y])
            return point_list

    def line_polygon(polygon, start_x, start_y, end_x, end_y):
        # 线段是否与多边形相交
        points = get_points(start_x, start_y, end_x, end_y)
        if points:
            for point in get_points(start_x, start_y, end_x, end_y):
                if isInPolygon(point, polygon):
                    return True
        return False

    # 1.多边形在图形内
    if isInPolygon([polygon[0][0], polygon[0][1]], [[q1_x, q1_y], [q2_x, q2_y], [q3_x, q3_y], [q4_x, q4_y]]):
        print("多边形在图形内")
        return True

    # 2.图形与多边的相交为True,其他为False
    if line_polygon(polygon, q1_x, q1_y, q2_x, q2_y):
        return True
    if line_polygon(polygon, q2_x, q2_y, q3_x, q3_y):
        return True
    if line_polygon(polygon, q1_x, q1_y, q2_x, q2_y):
        return True
    if line_polygon(polygon, q3_x, q3_y, q4_x, q4_y):
        return True
    if line_polygon(polygon, q2_x, q2_y, q4_x, q4_y):
        return True
    if line_polygon(polygon, q1_x, q1_y, q3_x, q3_y):
        return True
    return False

参考链接:

python进行点和线段、直线、多边形的交点、距离,垂直等处理——代码_nature1949的博客-CSDN博客_python两点求直线方程

经纬度和米的换算_Dust_Evc的博客-CSDN博客_经纬度和米的换算

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我辈李想

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值