python进行点和线段、直线、多边形的交点、距离,垂直等处理——代码

相关内容目录:

目录

1.基本的点和线段,多边形的表示:

 2.已知两点的坐标,求直线的解析方程:

3.计算两直线的交点:

4.计算两直线的夹角:

5.获取直线 与 点的垂足

6.计算点到线段的距离最近点:

7.计算点到直线的距离:

8.计算任意凸多边形的面积:

9.计算圆和直线的交点:

10.判断点到多边形边界的最小距离:

11.断点是否在多边形内:


1.基本的点和线段,多边形的表示:

import numpy as np
import math
import matplotlib.pyplot as plt
from shapely.geometry import LineString
from shapely.geometry import Point

point = [10,10]     # 点,x,y
line = [1,2,12,10]  # 线段或直线,x1,y1, x2,y2
polygon = [[0,0], [8,2], [12,9], [5,10]]  # 多边形,几个点的列表
line_area = polygon+[polygon[0]]
plt.plot([i[0] for i in line_area], [i[1] for i in line_area])
plt.scatter(point[0], point[1], s=100, c='r')
plt.plot(line[::2], line[1::2])
plt.show()

 2.已知两点的坐标,求直线的解析方程:

# 根据已知两点坐标,求过这两点的直线解析方程: a*x+b*y+c = 0  (a >= 0)
def getLinearEquation(p1x, p1y, p2x, p2y):
    sign = 1
    a = p2y - p1y
    if a < 0:
        sign = -1
        a = sign * a
    b = sign * (p1x - p2x)
    c = sign * (p1y * p2x - p1x * p2y)
    #return [a, b, c]
    #y=kx+bb
    k=-a/b 
    bb= -c/b
    return k,bb

3.计算两直线的交点:

def cross_point(line1,line2):   ##  计算两直线的交点
    [x1,y1,x2,y2]=line1#取四点坐标
    [x3,y3,x4,y4]=line2
    k1=(y2-y1)*1.0/(x2-x1)#计算k1,由于点均为整数,需要进行浮点数转化
    b1=y1*1.0-x1*k1*1.0#整型转浮点型是关键
    if (x4-x3)==0:#L2直线斜率不存在操作
        k2=None
        b2=0
    else:
        k2=(y4-y3)*1.0/(x4-x3)#斜率存在操作
        b2=y3*1.0-x3*k2*1.0
    if k2==None:
        x=x3
    else:
        x=(b2-b1)*1.0/(k1-k2)
    y=k1*x*1.0+b1*1.0
    return [x,y]

4.计算两直线的夹角:

##  计算两直线的夹角
def GetCrossAngle(line1, line2):
    [x1,y1,x2,y2]=line1
    [x3,y3,x4,y4]=line2
    arr_0 = np.array([(x2 - x1), (y2 - y1)])
    arr_1 = np.array([(x4 - x3), (y4 - y3)])
    cos_value = (float(arr_0.dot(arr_1)) / (np.sqrt(arr_0.dot(arr_0)) * np.sqrt(arr_1.dot(arr_1))))
    if cos_value>1:
        cos_value=1
    elif cos_value<-1:
        cos_value=-1
    return np.arccos(cos_value)

5.获取直线 与 点的垂足

## 获取直线 与 点的垂足
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

6.计算点到线段的距离最近点:

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 )
    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)
    #该直线方程为:
    #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)

7.计算点到直线的距离:

def get_distance_point2line(point, line):   ##  计算点到直线的距离
    """
    Args:
        point: [x0, y0]
        line: [x1, y1, x2, y2]
    """
    line_point1, line_point2 = np.array(line[0:2]), np.array(line[2:])
    vec1 = line_point1 - point
    vec2 = line_point2 - point
    m=np.linalg.norm(line_point1 - line_point2)
    if m==0:
        print('error')
        return 0
    else:
        distance = np.abs(np.cross(vec1, vec2)) / m
    return distance

8.计算任意凸多边形的面积:

def polygon_area(polygon):  ##计算多边形面积
    """
    compute polygon area
    polygon: list with shape [n, 2], n is the number of polygon points
    """
    area = 0
    q = polygon[-1]
    for p in polygon:
        area += p[0] * q[1] - p[1] * q[0]
        q = p
    return abs(area) / 2.0

9.计算圆和直线的交点:

def LineIntersectCircle(p,lsp,lep):     ##  计算圆和直线的交点,输出一个[[x,y],]
# p is the circle parameter, lsp and lep is the two end of the line
    x0,y0,r0 = p
    p = Point(x0,y0)
    c = p.buffer(r0).boundary
    l = LineString([lsp, lep])
    i = c.intersection(l)
    intersection = []
    if i.type=='Point':
        intersection.append(i.coords[0])
    elif i.type=='MultiPoint':
        for m in range(len(i.geoms)):
            intersection.append(i.geoms[m].coords[0])
            #print(i.geoms[m].coords[0])
    else:
        print('圆和直线没有交点', i.type)
    return intersection

10.判断点到多边形边界的最小距离:

def get_dis_point2polygon(point, area):     ##  判断点到多边形边界的最小距离
    line_list = []
    line_area = area+[area[0]]
    for i in range(len(line_area)-1):
        line_list.append([line_area[i][0], line_area[i][1], line_area[i+1][0], line_area[i+1][1]])
    dis=[]
    for i in line_list:
        foot  = get_nearest_point(point, i)
        if min(i[0],i[2])< foot[0] <max(i[0],i[2]) and min(i[1],i[3])< foot[1] <max(i[1],i[3]):
            dis.append(get_distance_point2line(point, i))
        else:
            dis.append(min(np.hypot(i[3]-point[1], i[2]-point[0]), np.hypot(i[1]-point[1], i[0]-point[0])))
    return min(dis)

11.断点是否在多边形内:

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)

  • 16
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
求两个几何多边形交点坐标可以用线段求交的思路来解决。具体步骤如下: 1. 对于每个多边形,遍历其所有边界线段,求出每条线段的参数方程。 2. 对于第一个多边形的每条线段,与第二个多边形的所有线段进行求交。 3. 对于每一组相交的线段,求出其交点坐标。 4. 将所有交点坐标存入列表中,并去除重复的。 下面是一个简单的 Python 代码实现: ```python def intersection(poly1, poly2): # poly1, poly2 分别为两个多边形的顶列表 def line_intersection(line1, line2): # 求两条线段交点坐标 x1, y1, x2, y2 = line1 x3, y3, x4, y4 = line2 d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4) if d == 0: return None x = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d y = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d return (x, y) def segment_intersection(seg1, seg2): # 求两个线段是否相交,相交则返回交点坐标 line1 = (poly1[seg1[0]][0], poly1[seg1[0]][1], poly1[seg1[1]][0], poly1[seg1[1]][1]) line2 = (poly2[seg2[0]][0], poly2[seg2[0]][1], poly2[seg2[1]][0], poly2[seg2[1]][1]) intersection_point = line_intersection(line1, line2) if intersection_point is None: return None if (intersection_point[0] < min(poly1[seg1[0]][0], poly1[seg1[1]][0]) or intersection_point[0] > max(poly1[seg1[0]][0], poly1[seg1[1]][0]) or intersection_point[1] < min(poly1[seg1[0]][1], poly1[seg1[1]][1]) or intersection_point[1] > max(poly1[seg1[0]][1], poly1[seg1[1]][1]) or intersection_point[0] < min(poly2[seg2[0]][0], poly2[seg2[1]][0]) or intersection_point[0] > max(poly2[seg2[0]][0], poly2[seg2[1]][0]) or intersection_point[1] < min(poly2[seg2[0]][1], poly2[seg2[1]][1]) or intersection_point[1] > max(poly2[seg2[0]][1], poly2[seg2[1]][1])): return None return intersection_point intersections = [] for i in range(len(poly1)): for j in range(len(poly2)): intersection_point = segment_intersection((i, (i+1)%len(poly1)), (j, (j+1)%len(poly2))) if intersection_point is not None: intersections.append(intersection_point) # 去除重复的 intersections = list(set(intersections)) return intersections ``` 其中,`poly1` 和 `poly2` 分别为两个多边形的顶列表,每个顶为一个二元组表示坐标。该函数返回两个多边形交点坐标列表。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值