目录
本文主要处理的是相交和不相交,因为地理数据保存较多,需要运用最小外接矩阵
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两点求直线方程