"Drawing an elephant with four complex parameters", Mayer et al, 2010
Available here: http://java-srv1.mpi-cbg.de/publications/getDocument.html?id=ff8080812daff75c012dc1b7bc10000c
Based on code from here: http://www.johndcook.com/blog/2011/06/21/how-to-fit-an-elephant/
Modified to make JavaScript animation possible (worker function needed)
... plus one complex number to wiggle the trunk and to add the elephant's eye
"""
Author: Piotr A. Zolnierczuk (zolnierczukp at ornl dot gov)
Based on a paper by:
Drawing an elephant with four complex parameters
Jurgen Mayer, Khaled Khairy, and Jonathon Howard,
Am. J. Phys. 78, 648 (2010), DOI:10.1119/1.3254017
"""
import numpy as np
# elephant parameters
p1, p2, p3, p4 = (50 - 30j, 18 + 8j, 12 - 10j, -14 - 60j )
p5 = 40 + 20j # wiggle factor and eyepiece
def fourier(t, C):
f = np.zeros(t.shape)
A, B = C.real, C.imag
for k in range(len(C)):
f = f + A[k]*np.cos(k*t) + B[k]*np.sin(k*t)
return f
def elephant(t, p1, p2, p3, p4, p5):
npar = 6
Cx = np.zeros((npar,), dtype='complex')
Cy = np.zeros((npar,), dtype='complex')
Cx[1] = p1.real*1j
Cx[2] = p2.real*1j
Cx[3] = p3.real
Cx[5] = p4.real
Cy[1] = p4.imag + p1.imag*1j
Cy[2] = p2.imag*1j
Cy[3] = p3.imag*1j
x = np.append(fourier(t,Cx), [-p5.imag])
y = np.append(fourier(t,Cy), [p5.imag])
# wiggle the trunk (
trunk_i = y>40
x_trunk = x[trunk_i]
N_trunk = len(x_trunk)
# x[trunk_i] = x_trunk * concatenate([linspace(1,p5.real,floor(N_trunk/2.0)),
# linspace(p5.real,1,ceil(N_trunk/2.0))])
x[trunk_i] = x_trunk + concatenate([linspace(0,p5.real,floor(N_trunk/2.0)),
linspace(p5.real,0,ceil(N_trunk/2.0))])
return x,y
def plot_elephant(wiggle=40, p4_real=14, t_p=1.0):
p1, p2, p3, p4 = (50 - 30j, 18 + 8j, 12 - 10j, - p4_real - 60j )
p5 = wiggle + 20j
t = np.linspace(0,2*np.pi,1000)
x, y = elephant(t, p1, p2, p3, p4, p5)
fig, ax = plt.subplots(figsize=(10, 7))
ax.plot(y,-x,'.')
#x_p, y_p = elephant(array(t_p/1000.0*2*pi), p1, p2, p3, p4, p5)
#ax.plot(y_p,-x_p,'ro')
ax.set_xlim(-80, 100)
ax.set_ylim(-80, 100)
fig.suptitle('elephant with wiggle parameter = ' + str(wiggle))
return fig
#fig = plot_elephant(wiggle=0.5)
#plot_elephant(wiggle=10, p4_real=10)
ipywidgets can be downloaded from here: https://github.com/jakevdp/ipywidgets
from ipywidgets import StaticInteract, RangeWidget, RadioWidget
StaticInteract(plot_elephant, wiggle=RangeWidget(0,40,5))