• Python处理矩形和圆的关系,处理矩形和多边形的关系


    目录

    一、基本思路

    二、矩形和圆的关系

    验证思路

    三、矩形和多边形的关系

    验证思路:


    一、基本思路

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

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

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

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

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

    二、矩形和圆的关系

    验证思路

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

    1.圆在矩阵内

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

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

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

    1. import numpy as np
    2. import math
    3. from math import cos
    4. def coordinate_2_radius(Longitude, Latitude):
    5. '''
    6. 参考地址: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
    7. 度数与弧度转化公式:1°=π/180°,1rad=180°/π。
    8. 地球半径:6371000M
    9. 地球周长:2 * 6371000M * π = 40030173
    10. 纬度38°地球周长:40030173 * cos38 = 31544206M
    11. 任意地球经度周长:40030173M
    12. 经度(东西方向)1M实际度:360°/31544206M=1.141255544679108e-5=0.00001141
    13. 纬度(南北方向)1M实际度:360°/40030173M=8.993216192195822e-6=0.00000899
    14. '''
    15. # R = 6371000
    16. # L = 2 * math.pi * R
    17. Lng_l = 40030173 # 当前经度地球周长
    18. Lat_l = Lng_l * cos(Latitude * math.pi / 180) # 当前纬度地球周长,弧度转化为度数
    19. # print(Lat_l)
    20. Lat_C = Lat_l / 360
    21. Lng_C = Lng_l / 360
    22. Latitude_m = Latitude * Lat_C
    23. Longitude_m = Longitude * Lng_C
    24. return Latitude_m, Longitude_m
    25. def radius_2_coordinate(Longitude, Latitude, radius):
    26. '''
    27. 参考地址: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
    28. 度数与弧度转化公式:1°=π/180°,1rad=180°/π。
    29. 地球半径:6371000M
    30. 地球周长:2 * 6371000M * π = 40030173
    31. 纬度38°地球周长:40030173 * cos38 = 31544206M
    32. 任意地球经度周长:40030173M
    33. 经度(东西方向)1M实际度:360°/31544206M=1.141255544679108e-5=0.00001141
    34. 纬度(南北方向)1M实际度:360°/40030173M=8.993216192195822e-6=0.00000899
    35. '''
    36. Lng_l = 40076000 # 当前经度地球周长
    37. Lat_l = Lng_l * cos(Latitude * math.pi / 180) # 当前纬度地球周长,弧度转化为度数
    38. Lat_C = Lat_l / 360
    39. Lng_C = Lng_l / 360
    40. radius_lat = radius / Lat_C
    41. radius_lng = radius / Lng_C
    42. # print(radius_lng, radius_lat)
    43. return radius_lat, radius_lng
    44. def isInPolygon(point, polygon): ## 检测点是否在多边形内,输入([x,y], polygon_list也就是点组成的list)
    45. # 使用水平射线检测
    46. x, y = point[0], point[1]
    47. nCross = 0
    48. for i in range(len(polygon)):
    49. p1 = polygon[i]
    50. p2 = polygon[(i + 1) % len(polygon)]
    51. # 特殊情况:边界p1p2 与 y=p0.y平行,不计数
    52. if (p1[1] == p2[1]): continue
    53. # 交点在p1p2延长线上,注意是小于,不计数
    54. if (y < min(p1[1], p2[1])): continue
    55. # 交点在p1p2延长线上,注意是大于等于,不计数
    56. if (y >= max(p1[1], p2[1])): continue
    57. # 求交点的 X 坐标;根据相似三角形计算
    58. crossx = (y - p1[1]) * (p2[0] - p1[0]) / (p2[1] - p1[1]) + p1[0]
    59. # 只统计单边交点
    60. if (crossx >= x):
    61. nCross = nCross + 1
    62. # min_dis = get_dis_point2polygon(point, polygon)
    63. # if abs(min_dis)<1e-2: ## 求点到哪个边距离最小,是否为0,为0则表示在边界上
    64. # return 1
    65. return (nCross % 2 == 1)
    66. def get_nearest_distance(point, line):
    67. # 获取线段 与 点的最短距离
    68. # print('get_nearest_distance')
    69. def get_foot(point, line):
    70. # 获取直线 与 点的垂足
    71. start_x, start_y = line[0], line[1]
    72. end_x, end_y = line[2], line[3]
    73. pa_x, pa_y = point
    74. p_foot = [0, 0]
    75. if line[0] == line[3]:
    76. p_foot[0] = line[0]
    77. p_foot[1] = point[1]
    78. return p_foot
    79. k = (end_y - start_y) * 1.0 / (end_x - start_x)
    80. a = k
    81. b = -1.0
    82. c = start_y - k * start_x
    83. p_foot[0] = (b * b * pa_x - a * b * pa_y - a * c) / (a * a + b * b)
    84. p_foot[1] = (a * a * pa_y - a * b * pa_x - b * c) / (a * a + b * b)
    85. return p_foot
    86. def get_nearest_point(point, line):
    87. # 计算点到线段的最近点
    88. pt1_x, pt1_y = line[0], line[1]
    89. pt2_x, pt2_y = line[2], line[3]
    90. point_x, point_y = point[0], point[1]
    91. if (pt2_x - pt1_x) != 0:
    92. k = (pt2_y - pt1_y) / (pt2_x - pt1_x)
    93. # 该直线方程为:
    94. # y = k* ( x - pt1_x) + pt1_y
    95. # 其垂线的斜率为 - 1 / k,
    96. # 垂线方程为:
    97. # y = (-1/k) * (x - point_x) + point_y
    98. # 联立两直线方程解得:
    99. x = (k ** 2 * pt1_x + k * (point_y - pt1_y) + point_x) / (k ** 2 + 1)
    100. y = k * (x - pt1_x) + pt1_y
    101. return (x, y)
    102. elif min(pt1_y, pt2_y) < point[1] < max(pt1_y, pt2_y):
    103. return get_foot(point, line)
    104. else:
    105. l1 = np.hypot(pt1_y - point[1], pt1_x - point[0])
    106. l2 = np.hypot(pt2_y - point[1], pt2_x - point[0])
    107. return (pt1_x, pt1_y) if l1 < l2 else (pt2_x, pt2_y)
    108. nearest_point = get_nearest_point(point, line)
    109. # print(nearest_point)
    110. x, y = coordinate_2_radius(nearest_point[0], nearest_point[1])
    111. point_x, point_y = coordinate_2_radius(point[0], point[1])
    112. distance = math.sqrt((x - point_x) * (x - point_x) + (y - point_y) * (y - point_y))
    113. # print(nearest_point[0], nearest_point[1], point[0], point[1], distance)
    114. return distance
    115. 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):
    116. """
    117. 与园的相交检查
    118. """
    119. # print('intersect_check_garden')
    120. radius_lng, radius_lat = radius_2_coordinate(point_lng, point_lat, radius)
    121. # point_lng_max = point_lng + radius_lng
    122. # point_lng_min = point_lng - radius_lng
    123. # point_lat_max = point_lat + radius_lat
    124. # point_lat_min = point_lat - radius_lat
    125. # # 1.圆在图形内
    126. # xmin = min(q1_x, q2_x, q3_x, q4_x)
    127. # xmax = max(q1_x, q2_x, q3_x, q4_x)
    128. # ymin = min(q1_y, q2_y, q3_y, q4_y)
    129. # ymax = max(q1_y, q2_y, q3_y, q4_y)
    130. if isInPolygon([point_lng, point_lat], [[q1_x, q1_y], [q2_x, q2_y], [q3_x, q3_y], [q4_x, q4_y]]):
    131. print("圆在图形内")
    132. return True
    133. # if xmin < point_lng_max < xmax and xmin < point_lng_min < xmax:
    134. # return True
    135. #
    136. # if ymin < point_lat_max < ymax and ymin < point_lat_min < ymax:
    137. # return True
    138. # 2.圆与图形相交为True,圆在图形不想交相交为False,
    139. distance1 = get_nearest_distance([point_lng, point_lat], [q1_x, q1_y, q2_x, q2_y])
    140. if distance1 < radius:
    141. return True
    142. distance2 = get_nearest_distance([point_lng, point_lat], [q2_x, q2_y, q3_x, q3_y])
    143. if distance2 < radius:
    144. return True
    145. distance3 = get_nearest_distance([point_lng, point_lat], [q3_x, q3_y, q4_x, q4_y])
    146. if distance3 < radius:
    147. return True
    148. distance4 = get_nearest_distance([point_lng, point_lat], [q4_x, q4_y, q1_x, q1_y])
    149. if distance4 < radius:
    150. return True
    151. distance5 = get_nearest_distance([point_lng, point_lat], [q1_x, q1_y, q3_x, q3_y])
    152. if distance5 < radius:
    153. return True
    154. distance6 = get_nearest_distance([point_lng, point_lat], [q2_x, q2_y, q4_x, q4_y])
    155. if distance6 < radius:
    156. return True
    157. return False

    三、矩形和多边形的关系

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

    验证思路:

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

    1.多边形在矩阵内

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

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

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

    1. def intersect_check_polygon(polygon, q1_x, q1_y, q2_x, q2_y, q3_x, q3_y, q4_x, q4_y):
    2. """
    3. 与多边形的相交检查
    4. polygon:多边形的list
    5. """
    6. def get_points(start_x, start_y, end_x, end_y):
    7. # print(start_x, start_y, end_x, end_y)
    8. if end_x - start_x != 0:
    9. k = (end_y - start_y) * 1.0 / (end_x - start_x)
    10. # y = start_y + k * (x - start_x) # 2个点组成的直线
    11. division = 10 # 线段切割次数
    12. point_list = [] # 线段上点的集合
    13. for i in range(0, division):
    14. x = start_x * i / 10 + start_x
    15. if x < end_x:
    16. y = start_y + k * (x - start_x)
    17. point_list.append([x, y])
    18. return point_list
    19. def line_polygon(polygon, start_x, start_y, end_x, end_y):
    20. # 线段是否与多边形相交
    21. points = get_points(start_x, start_y, end_x, end_y)
    22. if points:
    23. for point in get_points(start_x, start_y, end_x, end_y):
    24. if isInPolygon(point, polygon):
    25. return True
    26. return False
    27. # 1.多边形在图形内
    28. if isInPolygon([polygon[0][0], polygon[0][1]], [[q1_x, q1_y], [q2_x, q2_y], [q3_x, q3_y], [q4_x, q4_y]]):
    29. print("多边形在图形内")
    30. return True
    31. # 2.图形与多边的相交为True,其他为False
    32. if line_polygon(polygon, q1_x, q1_y, q2_x, q2_y):
    33. return True
    34. if line_polygon(polygon, q2_x, q2_y, q3_x, q3_y):
    35. return True
    36. if line_polygon(polygon, q1_x, q1_y, q2_x, q2_y):
    37. return True
    38. if line_polygon(polygon, q3_x, q3_y, q4_x, q4_y):
    39. return True
    40. if line_polygon(polygon, q2_x, q2_y, q4_x, q4_y):
    41. return True
    42. if line_polygon(polygon, q1_x, q1_y, q3_x, q3_y):
    43. return True
    44. return False

    参考链接:

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

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

  • 相关阅读:
    时空数据挖掘二(城市计算)
    哈夫曼树哈夫曼编码知识点
    java计算机毕业设计企业公开招聘系统源码+数据库+系统+lw文档+mybatis+运行部署
    Jenkins部署的Windows爬虫机如何配置
    Nacos配置
    文件部署到服务器
    解决storybook中组件的tailwindcss类不生效问题
    MFC删除Button控件具体操作
    Allegro如何快速将目标旋转90度操作指导
    【Linux】最新CentOS8内核升级
  • 原文地址:https://blog.csdn.net/qq_15028721/article/details/126975704