# How to draw a wiggle line with Python

• Last year I wrote a Drawbot tutorial on Medium.
If you want to jump directly into the code, here's the source:

``````##############################
# Draw Wiggles using Drawbot #
##############################

"""
Script by Roberto Arista, you can find the related tutorial here: https://medium.com/@roberto_arista/how-to-draw-a-wiggle-between-two-points-with-python-and-drawbot-788006c18fb0
You can find drawbot here: http://www.drawbot.com/
Code distributed with no guarantee, use at your own risk
"""

### Modules
from math import radians, atan2, sqrt, sin, cos
from collections import namedtuple

### Constants
BLACK = (0, 0, 0)
Point = namedtuple('Point', ['x', 'y'])

### Function & procedures
def calcAngle(pt1, pt2):
return atan2((pt2.y - pt1.y), (pt2.x - pt1.x))

def calcDistance(pt1, pt2):
return sqrt((pt1.x - pt2.x)**2 + (pt1.y - pt2.y)**2)

def calcWiggle(pt1, pt2, waveLength, waveHeight, curveSquaring=.57):
assert 0 <= curveSquaring <= 1, 'curveSquaring should be a value between 0 and 1: {}'.format(curveSquaring)
assert waveLength > 0, 'waveLength smaller or equal to zero: {}'.format(waveLength)

diagonal = calcDistance(pt1, pt2)

howManyWaves = diagonal//int(waveLength)
waveInterval = diagonal/float(howManyWaves)
maxBcpLength = sqrt((waveInterval/4.)**2+(waveHeight/2.)**2)
bcpLength = maxBcpLength*curveSquaring
bcpInclination = calcAngle(Point(0,0), Point(waveInterval/4., waveHeight/2.))

wigglePoints = [pt1]
prevFlexPt = pt1
polarity = 1
for waveIndex in range(0, int(howManyWaves*2)):
bcpOut = Point(prevFlexPt.x+cos(bcpOutAngle)*bcpLength, prevFlexPt.y+sin(bcpOutAngle)*bcpLength)

bcpIn = Point(flexPt.x+cos(bcpInAngle)*bcpLength, flexPt.y+sin(bcpInAngle)*bcpLength)

wigglePoints.append((bcpOut, bcpIn, flexPt))

polarity *= -1
prevFlexPt = flexPt

return wigglePoints

def drawCurvesSequence(wigglePoints):
myBez = BezierPath()
myBez.moveTo(wigglePoints)
for eachBcpOut, eachBcpIn, eachAnchor in wigglePoints[1:]:
myBez.curveTo(eachBcpOut, eachBcpIn, eachAnchor)
myBez.endPath()
drawPath(myBez)

### Variables
pt1 = Point(50, 50)
pt2 = Point(150, 60)

### Instructions
size(400, 400)

oval(pt1.x-1, pt1.y-1, 2, 2)
oval(pt2.x-1, pt2.y-1, 2, 2)

stroke(*BLACK)
strokeWidth(.5)
fill(None)

wigglePoints = calcWiggle(pt1, pt2, 16, 36, .7)
drawCurvesSequence(wigglePoints)
``````