计算几何

2020-12-09  本文已影响0人  hehehehe
import numpy as np
import math
import time
from datetime import datetime
import Tools_geoTools as geotool
from shapely.geometry import Point,LineString

EPS = 1E-10

def vecCross(vec1 : list,vec2 : list):
    """
    a.x * b.y - a.y * b.x;
    """
    return vec1[0] * vec2[1] - vec1[1] * vec2[0]

def vecDot(vec1 : list,vec2 : list):
    """
    a.x * b.x + a.y * b.y
    """
    return vec1[0] * vec2[0] + vec1[1] * vec2[1]

def vecNorm(vec : list):
    """
    a.x * a.x + a.y * a.y
    """
    return vec[0] * vec[0] + vec[1] * vec[1]

def vecLen(vec : list):
    """
    a.x * a.x + a.y * a.y1//
    """
    return math.sqrt(vecNorm(vec))

def getVec(p1 : list, p2 : list):
    """
    拿到向量p1p2
    """
    return p2[0] - p1[0], p2[1] - p1[1]

def getAngle(p1 : list, p2 : list , p3 : list, p4 : list) -> float:
    """
    计算向量p1p2和p3p4角度
    """
    vec1 = getVec(p1,p2)
    vec2 = getVec(p3,p4)
    return math.acos(vecDot(vec1,vec2)/vecLen(vec1)/vecLen(vec2))

# def vecLen(p1 : list, p2 : list) -> float:
#     """
#     计算向量p1p2的模
#     """
#     vec = getVec(p1,p2)
#     return np.linalg.norm(vec)

def vecNormal(p1 : list, p2 : list) -> tuple:
    """
    计算向量p1p2的法向量
    """
    vec = getVec(p1,p2)
    length = vecLen(p1,p2)
    return (-vec[1]/length,vec[0]/length)

def pointLineDistance(p : list, line_a : list, line_b : list) -> float:
    """
    计算p和向量line_aline_b的距离
    """
    v = getVec(line_a,p)
    u = getVec(line_a,line_b)
    return math.fabs(vecCross(v,u))/vecLen(getVec(line_a,line_b))

def pointSegmentDistance(p : list, line_a : list, line_b : list) -> float:
    """
    计算p和线段line_aline_b的距离
    """
    if(vecDot(getVec(line_a,line_b),getVec(line_a,p)) < 0.0):
        return vecLen(getVec(line_a,p))
    if(vecDot(getVec(line_b,line_a),getVec(line_b,p)) < 0.0):
        return vecLen(getVec(line_b,p))
    return pointLineDistance(p,line_a,line_b)

def getFootPoint(point, line_p1, line_p2):
    """
    @point, line_p1, line_p2 : [x, y, z]
    """
    x0 = point[0]
    y0 = point[1]
    z0 = point[2]

    x1 = line_p1[0]
    y1 = line_p1[1]
    z1 = line_p1[2]

    x2 = line_p2[0]
    y2 = line_p2[1]
    z2 = line_p2[2]

    k = -((x1 - x0) * (x2 - x1) + (y1 - y0) * (y2 - y1) + (z1 - z0) * (z2 - z1)) / \
        ((x2 - x1) ** 2 + (y2 - y1) ** 2 + (z2 - z1) ** 2)*1.0

    xn = k * (x2 - x1) + x1
    yn = k * (y2 - y1) + y1
    zn = k * (z2 - z1) + z1

    return (xn, yn, zn)

def project(point, line_p1, line_p2):
    """
    点point在线段line_p1, line_p2上的投影
    """
    base = getVec(line_p1,line_p2) 
    r = vecDot(getVec(line_p1,point), base) / vecNorm(getVec(line_p1,line_p2))
    return np.array(line_p1) + np.array(base) * r

def symmetrical(point, line_p1, line_p2):
    """
    计算point和线段line_aline_b的对称点
    """
    return np.array(point) + (getFootPoint2(point, line_p1, line_p2) - np.array(point)) * 2.0

def isParallel(p1 : list, p2 : list , p3 : list, p4 : list):
    """
    判断向量p1p2和p3p4是否平行
    """
    vec1 = getVec(p1,p2)
    vec2 = getVec(p3,p4)
    return np.cross(vec1,vec2) - 0 < EPS

def isOrthogonal(p1 : list, p2 : list , p3 : list, p4 : list):
    """
    判断向量p1p2和p3p4是垂直
    """
    vec1 = getVec(p1,p2)
    vec2 = getVec(p3,p4)
    return np.dot(vec1,vec2) - 0 < EPS

def clockWise(point, line_p1, line_p2):
    vec1 = getVec(point,line_p1)
    vec2 = getVec(point,line_p2)
    """
    判断向量之间的位置关系
    """
    if(np.cross(vec1,vec2) > EPS):
        return 1
    if(np.cross(vec1,vec2) < -EPS):
        return -1
    if(np.dot(vec1,vec2) < -EPS):
        return 0
    if(vecLen(point,line_p1) < vecLen(point,line_p2)):
        return -2
    if(vecLen(point,line_p1) > vecLen(point,line_p2)):
        return 2
    return 123

def pointSegmentClockWise(point, line_p1, line_p2):
    vec1 = getVec(point,line_p1)
    vec2 = getVec(point,line_p2)
    """
    判断点和线段之间的位置关系
    """
    if (vecLen(point,line_p1) < EPS):
        return "位于p1"
    if (vecLen(point,line_p2) < EPS):
        return "位于p2"
    if(np.cross(vec1,vec2) > EPS):
        return "在左边"
    if(np.cross(vec1,vec2) < -EPS):
        return "在右边"
    if(np.dot(vec1,vec2) < -EPS):
        return "在线段上"
    if(vecLen(point,line_p1) < vecLen(point,line_p2)):
        return "在线后"
    if(vecLen(point,line_p1) > vecLen(point,line_p2)):
        return "在线前"
    return 123

def pointSegmentClockWiseOnly(point, line_p1, line_p2):
    vec1 = getVec(point,line_p1)
    vec2 = getVec(point,line_p2)
    """
    仅用于判断左右位置关系
    用于判断线段是否相交
    """
    if(np.cross(vec1,vec2) > EPS):
        return 1
    if(np.cross(vec1,vec2) < -EPS):
        return -1
    return 0

def segmentIntersect(p1 : list, p2 : list , p3 : list, p4 : list):
    """
    判断线段是否相交
    这里必须and了下 要使的p1和p3都满足
    """
    bool1 = pointSegmentClockWiseOnly(p1,p2,p3) * pointSegmentClockWiseOnly(p1,p2,p4) <= 0
    bool2 = pointSegmentClockWiseOnly(p3,p2,p1) * pointSegmentClockWiseOnly(p3,p4,p2) <= 0
    return bool1 and bool2

def segmentDistance(p1 : list, p2 : list , p3 : list, p4 : list):     
    if segmentIntersect(p1,p2,p3,p4):
        return 0.0
    return np.min([np.min([pointSegmentDistance(p1,p3,p4),pointSegmentDistance(p2,p3,p4)]),
        np.min([pointSegmentDistance(p3,p1,p2),pointSegmentDistance(p4,p1,p2)])])

def segmentCrossPoint(p1 : list, p2 : list , p3 : list, p4 : list):  
    if not segmentIntersect(p1,p2,p3,p4):
        return None   
    base = getVec(p3,p4)
    d1 = np.linalg.norm(np.cross(base,getVec(p3,p1)))
    d2 = np.linalg.norm(np.cross(base,getVec(p3,p2)))
    t =d1 / (d1+d2) 
    return p1 + getVec(p1,p2) * t

def lineCrossPoint(p1 : list, p2 : list , p3 : list, p4 : list): 
    
    v= getVec(p1,p2)
    w= getVec(p3,p4)
    u= getVec(p3,p1) 
    t= np.cross(w, u) / np.cross(v, w);  
    return p1 + v * t;  

def lineCrossPointAdvance(p1 : list, p2 : list , p3 : list, p4 : list):   
    a1 = p1[1] - p2[1];  
    b1 = p2[0] - p1[0];  
    c1 = np.cross(p1,p2);  
    a2 = p3[1] - p4[1]; 
    b2 = p4[0] - p3[0]; 
    c2 = np.cross(p3,p4);  
    d = a1 * b2 - a2 * b1; 
    x =  (b1 * c2 - b2 * c1) / d
    y = (c1 * a2 - c2 * a1) / d
    return [x, y];  

def twoPointLineFunction(p1 : list, p2 : list):
    '''
    计算经过两点的直线方程,y= ax + b
    :param f_coords:
    :param l_coords:
    :return:
    '''
    try:
        gradient = (p2[1] - p1[1]) / (p2[0] - p1[0])
        bias = p1[1] - gradient * p1[0]
    except ZeroDivisionError:
        gradient = None
        bias = p1[0]
    return gradient, bias

def pointRotate(p1 : list,po : list,alpha : float) -> tuple:
    """
    返回点p以点o为圆心逆时针旋转alpha(单位:弧度)后所在的位置
    """
    vec = getVec(po,p1)
    x = vec[0] * math.cos(alpha) - vec[1] * math.sin(alpha) + po[0]
    y = vec[1] * math.cos(alpha) + vec[0] * math.sin(alpha) + po[1]
    return x,y

def pointOnSegment(p1 : list,line_p1 : list,line_p2 : list) -> bool:
    """
    判断点p是否在线段l上
    条件:(p在线段l所在的直线上) && (点p在以线段l为对角线的矩形内)
    return( (multiply(l.e,p,l.s)==0) &&
    ( ( (p.x-l.s.x)*(p.x-l.e.x)<=0 )&&( (p.y-l.s.y)*(p.y-l.e.y)<=0 ) ) );
    """
    vec1 = getVec(p1,line_p1)
    vec2 = getVec(p1,line_p2)
    isInLine = vecCross(vec1,vec2) > -EPS or vecCross(vec1,vec2) < EPS
    isInRectangle = ((p1[0] - line_p2[0]) * (p1[0] - line_p1[0]) <= 0) and \
     ((p1[1] - line_p2[1]) * (p1[1] - line_p1[1]) <=0)
    return isInLine and isInRectangle

def pointOnSegment2(p1 : list,line_p1 : list,line_p2 : list) -> bool:
    """
    判断点p是否在线段l上
    条件:(p在线段l所在的直线上) && (点p在以线段l为对角线的矩形内)
    return( (multiply(l.e,p,l.s)==0) &&
    ( ( (p.x-l.s.x)*(p.x-l.e.x)<=0 )&&( (p.y-l.s.y)*(p.y-l.e.y)<=0 ) ) );
    """
    vec1 = getVec(p1,line_p1)
    vec2 = getVec(p1,line_p2)
    isInLine = math.fabs(vecCross(vec1,vec2)) < EPS
    isInRectangle = vecDot(vec1,vec2) <= 0
    return isInLine and isInRectangle


def getLineByTwoPoints(p1 : list,p2 : list):
    """
    根据已知两点坐标,求过这两点的直线解析方程: a*x+b*y+c = 0  (a >= 0)
    """
    sign = 1;
    a = p2[1] - p1[1]
    if a < 0 :
        sign = -1
        a = -a
    b = sign * (p1[0] - p2[0])
    c = sign * (p1[1] * p2[0] - p1[0] * p2[1])
    return a,b,c


if __name__ == '__main__':
    # print(getAngle([0,0],[1,0],[0,0],[1,1]) * 180 / 3.14)
    # print(vecNormal([0,0],[10,0]))
    # print(pointLineDistance([2,-1],[0,2],[2,0]))
    # p1,p2,p3,p4 = [1,0],[0,1],[0,2],[2,0]
    # print(pointSegmentDistance([1,0],[0,1],[0,2]))
    # print(getFootPoint([1,-1,0],[1,0,0],[0,1,0]))
    # print(getFootPoint2([0,0],[1,0],[0,10]))
    # print(isParallel([0,0],[1,0],[0,0],[0,10]))
    # print(isOrthogonal([0,0],[1,0],[0,0],[0,10]))
    # print(symmetrical([0,0],[1,0],[0,1]))
    # print(clockWise([0,1],[0,0],[0,1]))
    # print(segmentIntersect([0,0],[1.1,1.8],[0,2],[2,0]))
    # print(segmentDistance([0,0],[1,1],[1,0],[2,0]))
    # print(segmentCrossPoint([0,0],[1.1,1.8],[0,2],[2,0]))
    # start1 = time.perf_counter()
    # # print(pointSegmentDistance([1,0],[0,1],[0,2]))
    # print(pointSegmentDistance([0.5,0.5],[0,2],[2,0]))
    # end1 = time.perf_counter()
    # print(end1-start1)
    # start2 = time.perf_counter()
    # print(geotool.distance_point2segment((0.5,0.5),((0,2),(2,0))))
    # end2 = time.perf_counter()
    # print(str(end2-start2))
    # start3 = time.perf_counter()
    # line = LineString([(0,2),(2,0)])
    # point = Point(0.5,0.5)
    # print(point.distance(line))
    # end3 = time.perf_counter()
    # print(end3-start3)
    # print(point_in_2segment((1,1),((2,0),(0,1))))
    # print(lineCrossPointAdvance([0,0],[1.1,1.8],[0,2],[2,0]))
    # print(intersection_2line([],[]))
    # print(twoPointLineFunction([0,0],[1,2]))
    # print(pointRotate([1,1],[0,0],45 * 3.14/180))
    # start3 = time.perf_counter()
    # print(pointOnSegment2([1.99,1.998],[0,0],[2,2]))
    # start4 = time.perf_counter()
    # print(start4-start3)
    print(getLineByTwoPoints([1,1],[2,4]))


    # print(pointSegmentClockWise([0,1.1],[0,0],[0,1]))
    # print(pointSegmentClockWise([0,1],[0,0],[0,1]))
    # print(pointSegmentClockWise([0,0.8],[0,0],[0,1]))
    # print(pointSegmentClockWise([0,0.2],[0,0],[0,1]))
    # print(pointSegmentClockWise([0,0],[0,0],[0,1]))
    # print(pointSegmentClockWise([0,-0.1],[0,0],[0,1]))
    # print("============")
    # print(pointSegmentClockWise([1,1.1],[0,0],[0,1]))
    # print(pointSegmentClockWise([1,1],[0,0],[0,1]))
    # print(pointSegmentClockWise([1,0.8],[0,0],[0,1]))
    # print(pointSegmentClockWise([1,0.2],[0,0],[0,1]))
    # print(pointSegmentClockWise([1,0],[0,0],[0,1]))
    # print(pointSegmentClockWise([1,-0.1],[0,0],[0,1]))
    # print("============")
    # print(pointSegmentClockWise([-1,1.1],[0,0],[0,1]))
    # print(pointSegmentClockWise([-1,1],[0,0],[0,1]))
    # print(pointSegmentClockWise([-1,0.8],[0,0],[0,1]))
    # print(pointSegmentClockWise([-1,0.2],[0,0],[0,1]))
    # print(pointSegmentClockWise([-1,0],[0,0],[0,1]))
    # print(pointSegmentClockWise([-1,-0.1],[0,0],[0,1]))
    # print("============")
    # print(pointSegmentClockWise([0.5,0.5],[2,0],[0,2]))
    # print(pointSegmentClockWise([1.5,1.5],[2,0],[0,2]))



    # print(segmentIntersect([0,0],[1,1.5],[1,0],[1,1]))
    # print(segmentIntersect([0,0],[1,1],[1,0],[1,1]))
    # print(segmentIntersect([0,0],[1,0.9],[1,0],[1,1]))
    # print(segmentIntersect([0,0],[1,0],[1,0],[1,1]))
    # print(segmentIntersect([0,0],[1,-0.1],[1,0],[1,1]))
    # print("============")

    # print(segmentIntersect([0,0],[0.5,0.5],[1,0],[1,1]))
    # print(segmentIntersect([0,0],[1,1],[1,0],[1,0.5]))
    # print(segmentIntersect([0,0],[0.5,0.5],[1,0],[1,1]))
    # print(segmentIntersect([0,0],[0.5,0.5],[0,2],[2,0]))
    # print(np.cross([0,1],[-1,1]))

 
上一篇下一篇

猜你喜欢

热点阅读