k_p
k_p

Reputation: 313

offset a parallel line to a given line python

I want to draw parallel line to given X,Y coordinate below code helps to draw ,

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()

This gives result as below

enter image description here

Here it is giving good result by drawing parallel line to each line of our trapezoidal shaped , but i want it to be a closed shape in place of open shape i want to join the 1st and last coordinate so that it should form a closed shape. Any help will be appreciated .

Upvotes: 1

Views: 4732

Answers (2)

MBo
MBo

Reputation: 80137

Using approach from here

outer_ccw parameters combines vertex order and desired offset direction. For CCW order and outer polygon it is 1, for inner polygon it should be -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)/2)

        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

Upvotes: 6

Froge
Froge

Reputation: 1

Just append the first coordinates to the end of your lists.

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

Place this right before you plot. Here's my output

Upvotes: 0

Related Questions