将平行线偏移到给定线

2024-09-30 20:21:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我想画一条与给定X,Y坐标平行的线,下面的代码有助于绘制

import numpy as np
import matplotlib.pyplot as plt

x = [187, 879, 722, 322]

y = [341, 344, 112, 112]


newX = []
newY = []

def findIntesection(p1x, p1y, p2x, p2y, p3x,p3y, p4x, p4y):
    dx12 = p2x - p1x
    dy12 = p2y - p1y
    dx34 = p4x - p3x
    dy34 = p4y - p3y

    denominator = (dy12*dx34-dx12*dy34)

    t1 = ((p1x - p3x) * dy34 + (p3y - p1y) * dx34)/ denominator

    t2 = ((p3x - p1x) * dy12 + (p1y - p3y) * dx12)/ -denominator;
    
    intersectX = p1x + dx12 * t1
    intersectY = p1y + dy12 * t1

    if (t1 < 0): t1 = 0
    elif (t1 > 1): t1 = 1
    if (t2 < 0): t2 = 0
    elif (t2 > 1): t2 = 1
    
    return intersectX,intersectY

def normalizeVec(x,y):
    distance = np.sqrt(x*x+y*y)
    return x/distance, y/distance

def getEnlarged(oldX, oldY, offset):
    num_points = len(oldX)
    
    for j in range(num_points):
        i = j - 1
        if i < 0:
            i += num_points
        k = (j + 1) % num_points

        vec1X =  oldX[j] - oldX[i]
        vec1Y =  oldY[j] - oldY[i]
        v1normX, v1normY = normalizeVec(vec1X,vec1Y)
        v1normX *= offset
        v1normY *= offset
        n1X = -v1normY
        n1Y = v1normX
        pij1X = oldX[i] + n1X
        pij1Y = oldY[i] + n1Y
        pij2X = oldX[j] + n1X
        pij2Y = oldY[j] + n1Y

        vec2X =  oldX[k] - oldX[j]
        vec2Y =  oldY[k] - oldY[j]
        v2normX, v2normY = normalizeVec(vec2X,vec2Y)
        v2normX *= offset
        v2normY *= offset
        n2X = -v2normY
        n2Y = v2normX
        pjk1X = oldX[j] + n2X
        pjk1Y = oldY[j] + n2Y
        pjk2X = oldX[k] + n2X
        pjk2Y = oldY[k] + n2Y
        
        intersectX,intersetY = findIntesection(pij1X,pij1Y,pij2X,pij2Y,pjk1X,pjk1Y,pjk2X,pjk2Y)
        
        #print(intersectX,intersetY)
        
        newX.append(intersectX)
        newY.append(intersetY)

getEnlarged(x, y, 20)

plt.plot(x, y)
plt.plot(newX, newY)
plt.show()

结果如下

enter image description here

在这里,它是给我们的梯形图的每条线画平行线的好结果,但我希望它是一个封闭的形状,而不是开放的形状 我想把第一个坐标和最后一个坐标连接起来,这样它就会形成一个闭合的形状。任何帮助都将不胜感激


Tags: pltnumpointsoffsett1t2p1xp1y
2条回答

只需将第一个坐标附加到列表的末尾

x.append(x[0])
y.append(y[0])
newX.append(newX[0])
newY.append(newY[0])

在绘图之前,将其放置在右侧。这是我的output

使用来自here的方法

outer_ccw参数组合顶点顺序和所需偏移方向。对于CCW顺序和外部多边形,它是1,对于内部多边形,它应该是-1

def makeOffsetPoly(oldX, oldY, offset, outer_ccw = 1):
    num_points = len(oldX)

    for curr in range(num_points):
        prev = (curr + num_points - 1) % num_points
        next = (curr + 1) % num_points

        vnX =  oldX[next] - oldX[curr]
        vnY =  oldY[next] - oldY[curr]
        vnnX, vnnY = normalizeVec(vnX,vnY)
        nnnX = vnnY
        nnnY = -vnnX

        vpX =  oldX[curr] - oldX[prev]
        vpY =  oldY[curr] - oldY[prev]
        vpnX, vpnY = normalizeVec(vpX,vpY)
        npnX = vpnY * outer_ccw
        npnY = -vpnX * outer_ccw

        bisX = (nnnX + npnX) * outer_ccw
        bisY = (nnnY + npnY) * outer_ccw

        bisnX, bisnY = normalizeVec(bisX,  bisY)
        bislen = offset /  np.sqrt(1 + nnnX*npnX + nnnY*npnY)

        newX.append(oldX[curr] + bislen * bisnX)
        newY.append(oldY[curr] + bislen * bisnY)

x = [0, 100, 60, 40]
y = [0, 0, 50, 50]
makeOffsetPoly(x, y, 20)
print(newX, newY)

>>>[-29.424478775259594, 129.4244787752596, 66.79706177729007, 33.202938222709925] 
   [-14.14213562373095, -14.14213562373095, 64.14213562373095, 64.14213562373095]

enter image description here

相关问题 更多 >