123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859 |
- from math import *
- import array
- import sys
- import random
- import numarray as N
- import numarray.linear_algebra as la
- def eps_prologue(x0, y0, x1, y1, draw_box = False):
- print '%!PS-Adobe-3.0 EPSF'
- print '%%BoundingBox:', x0, y0, x1, y1
- print '%%EndComments'
- print '%%EndProlog'
- print '%%Page: 1 1'
- if draw_box:
- print x0, y0, 'moveto', x0, y1, 'lineto', x1, y1, 'lineto', x1, y0, 'lineto closepath stroke'
- def eps_trailer():
- print '%%EOF'
- # One step of 4th-order Runge-Kutta numerical integration - update y in place
- def rk4(y, dydx, x, h, derivs):
- hh = h * .5
- h6 = h * (1./6)
- xh = x + hh
- yt = []
- for i in range(len(y)):
- yt.append(y[i] + hh * dydx[i])
- dyt = derivs(xh, yt)
- for i in range(len(y)):
- yt[i] = y[i] + hh * dyt[i]
- dym = derivs(xh, yt)
- for i in range(len(y)):
- yt[i] = y[i] + h * dym[i]
- dym[i] += dyt[i]
- dyt = derivs(x + h, yt)
- for i in range(len(y)):
- y[i] += h6 * (dydx[i] + dyt[i] + 2 * dym[i])
- def run_elastica_half(sp, k0, lam1, lam2, n):
- def mec_derivs(x, ys):
- th, k = ys[2], ys[3]
- dx, dy = cos(th), sin(th)
- return [dx, dy, k, lam1 * dx + lam2 * dy, k * k]
- ys = [0, 0, 0, k0, 0]
- xyk = [(ys[0], ys[1], ys[3])]
- n = max(1, int(sp * n))
- h = float(sp) / n
- s = 0
- for i in range(n):
- dydx = mec_derivs(s, ys)
- rk4(ys, dydx, s, h, mec_derivs)
- xyk.append((ys[0], ys[1], ys[3]))
- return xyk, ys[2], ys[4]
- def run_elastica(sm, sp, k0, lam1, lam2, n = 100):
- xykm, thm, costm = run_elastica_half(-sm, k0, -lam1, lam2, n)
- xykp, thp, costp = run_elastica_half(sp, k0, lam1, lam2, n)
- xyk = []
- for i in range(1, len(xykm)):
- x, y, k = xykm[i]
- xyk.append((-x, y, k))
- xyk.reverse()
- xyk.extend(xykp)
- x = xyk[-1][0] - xyk[0][0]
- y = xyk[-1][1] - xyk[0][1]
- th = thm + thp
- sth, cth = sin(thm), cos(thm)
- x, y = x * cth - y * sth, x * sth + y * cth
- result = []
- maxk = 0
- for xt, yt, kt in xyk:
- maxk = max(maxk, kt)
- result.append((xt, yt, kt))
- cost = costm + costp
- return result, cost, x, y, th
- def run_mec_cos_pos(k, lam1, lam2, n = 1000):
- cost = 0
- th = 0
- x = 0
- y = 0
- dt = 1.0 / n
- result = [(0, 0)]
- for i in range(n):
- k1 = lam1 * cos(th) + lam2 * sin(th)
- cost += dt * k * k
- x += dt * cos(th)
- y += dt * sin(th)
- th += dt * k
- k += dt * k1
- result.append((x, y))
- return result, cost, x, y, th
- def run_mec_cos(k, lam1, lam2, n = 1000):
- resp, costp, xp, yp, thp = run_mec_cos_pos(k*.5, lam1*.25, lam2*.25, n)
- resm, costm, xm, ym, thm = run_mec_cos_pos(k*.5, lam1*-.25, lam2*.25, n)
- cost = (costp + costm) * .5
- x, y = xp + xm, yp - ym
- th = thp + thm
- sth, cth = .5 * sin(thm), .5 * cos(thm)
- x, y = x * cth - y * sth, x * sth + y * cth
- result = []
- for i in range(1, n):
- xt, yt = resm[n - i - 1]
- result.append((-xt * cth - yt * sth, -xt * sth + yt * cth))
- for i in range(n):
- xt, yt = resp[i]
- result.append((xt * cth - yt * sth, xt * sth + yt * cth))
- return result, cost, x, y, th
- def cross_prod(a, b):
- return [a[1] * b[2] - a[2] * b[1],
- a[2] * b[0] - a[0] * b[2],
- a[0] * b[1] - a[1] * b[0]]
- def solve_mec(constraint_fnl):
- delta = 1e-3
- params = [pi, 0, 0]
- for i in range(20):
- k, lam1, lam2 = params
- xys, cost, x, y, th = run_elastica(-.5, .5, k, lam1, lam2)
- #print i * .05, 'setgray'
- #plot(xys)
- c1c, c2c, costc = constraint_fnl(cost, x, y, th)
- print '% constraint_fnl =', c1c, c2c, 'cost =', costc
- dc1s = []
- dc2s = []
- for j in range(len(params)):
- params1 = N.array(params)
- params1[j] += delta
- k, lam1, lam2 = params1
- xys, cost, x, y, th = run_elastica(-.5, .5, k, lam1, lam2)
- c1p, c2p, costp = constraint_fnl(cost, x, y, th)
- params1 = N.array(params)
- params1[j] -= delta
- k, lam1, lam2 = params1
- xys, cost, x, y, th = run_elastica(-.5, .5, k, lam1, lam2)
- c1m, c2m, costm = constraint_fnl(cost, x, y, th)
- dc1s.append((c1p - c1m) / (2 * delta))
- dc2s.append((c2p - c2m) / (2 * delta))
- xp = cross_prod(dc1s, dc2s)
- xp = N.divide(xp, sqrt(N.dot(xp, xp))) # Normalize to unit length
- print '% dc1s =', dc1s
- print '% dc2s =', dc2s
- print '% xp =', xp
-
- # Compute second derivative wrt orthogonal vec
- params1 = N.array(params)
- for j in range(len(params)):
- params1[j] += delta * xp[j]
- k, lam1, lam2 = params1
- xys, cost, x, y, th = run_elastica(-.5, .5, k, lam1, lam2)
- c1p, c2p, costp = constraint_fnl(cost, x, y, th)
- print '% constraint_fnl+ =', c1p, c2p, 'cost =', costp
- params1 = N.array(params)
- for j in range(len(params)):
- params1[j] -= delta * xp[j]
- k, lam1, lam2 = params1
- xys, cost, x, y, th = run_elastica(-.5, .5, k, lam1, lam2)
- c1m, c2m, costm = constraint_fnl(cost, x, y, th)
- print '% constraint_fnl- =', c1m, c2m, 'cost =', costm
- d2cost = (costp + costm - 2 * costc) / (delta * delta)
- dcost = (costp - costm) / (2 * delta)
- print '% dcost =', dcost, 'd2cost =', d2cost
- if d2cost < 0: d2cost = .1
- # Make Jacobian matrix to invert
- jm = N.array([dc1s, dc2s, [x * d2cost for x in xp]])
- #print jm
- ji = la.inverse(jm)
- #print ji
- dp = N.dot(ji, [c1c, c2c, dcost])
- print '% dp =', dp
- print '% [right]=', [c1c, c2c, dcost]
- params -= dp * .1
- print '%', params
- sys.stdout.flush()
- return params
- def solve_mec_3constr(constraint_fnl, n = 30, initparams = None):
- delta = 1e-3
- if initparams:
- params = N.array(initparams)
- else:
- params = [3.14, 0, 0]
- for i in range(n):
- k, lam1, lam2 = params
- xys, cost, x, y, th = run_elastica(-.5, .5, k, lam1, lam2)
- c1c, c2c, c3c = constraint_fnl(cost, x, y, th)
- print '% constraint_fnl =', c1c, c2c, c3c
- dc1s = []
- dc2s = []
- dc3s = []
- for j in range(len(params)):
- params1 = N.array(params)
- params1[j] += delta
- k, lam1, lam2 = params1
- xys, cost, x, y, th = run_elastica(-.5, .5, k, lam1, lam2)
- c1p, c2p, c3p = constraint_fnl(cost, x, y, th)
- params1 = N.array(params)
- params1[j] -= delta
- k, lam1, lam2 = params1
- xys, cost, x, y, th = run_elastica(-.5, .5, k, lam1, lam2)
- c1m, c2m, c3m = constraint_fnl(cost, x, y, th)
- dc1s.append((c1p - c1m) / (2 * delta))
- dc2s.append((c2p - c2m) / (2 * delta))
- dc3s.append((c3p - c3m) / (2 * delta))
- # Make Jacobian matrix to invert
- jm = N.array([dc1s, dc2s, dc3s])
- #print jm
- ji = la.inverse(jm)
- dp = N.dot(ji, [c1c, c2c, c3c])
- if i < n/2: scale = .25
- else: scale = 1
- params -= scale * dp
- print '%', params
- return params
- def mk_ths_fnl(th0, th1):
- def fnl(cost, x, y, th):
- actual_th0 = atan2(y, x)
- actual_th1 = th - actual_th0
- print '% x =', x, 'y =', y, 'hypot =', hypot(x, y)
- return th0 - actual_th0, th1 - actual_th1, cost
- return fnl
- def mk_y_fnl(th0, th1, ytarg):
- def fnl(cost, x, y, th):
- actual_th0 = atan2(y, x)
- actual_th1 = th - actual_th0
- return th0 - actual_th0, th1 - actual_th1, ytarg - hypot(x, y)
- return fnl
- def solve_mec_nested_inner(th0, th1, y, fnl):
- innerfnl = mk_y_fnl(th0, th1, y)
- params = [th0 + th1, 1e-6, 1e-6]
- params = solve_mec_3constr(innerfnl, 10, params)
- k, lam1, lam2 = params
- xys, cost, x, y, th = run_elastica(-.5, .5, k, lam1, lam2, 100)
- c1, c2, c3 = fnl(cost, x, y, th)
- return c3, params
- # Solve (th0, th1) mec to minimize fnl; use solve_mec_3constr as inner loop
- # Use golden section search
- def solve_mec_nested(th0, th1, fnl):
- R = .61803399
- C = 1 - R
- ax, cx = .6, .85
- bx = .5 * (ax + cx)
- x0, x3 = ax, cx
- if abs(cx - bx) > abs(bx - ax):
- x1, x2 = bx, bx + C * (cx - bx)
- else:
- x1, x2 = bx - C * (bx - ax), bx
- f1, p = solve_mec_nested_inner(th0, th1, x1, fnl)
- f2, p = solve_mec_nested_inner(th0, th1, x2, fnl)
- for i in range(10):
- print '%', x0, x1, x2, x3, ':', f1, f2
- if f2 < f1:
- x0, x1, x2 = x1, x2, R * x2 + C * x3
- f1 = f2
- f2, p = solve_mec_nested_inner(th0, th1, x2, fnl)
- else:
- x1, x2, x3 = R * x1 + C * x0, x1, x2
- f2 = f1
- f1, p = solve_mec_nested_inner(th0, th1, x1, fnl)
- if f1 < f2:
- x = x1
- else:
- x = x2
- cc, p = solve_mec_nested_inner(th0, th1, x, fnl)
- return p
- def plot(xys):
- cmd = 'moveto'
- for xy in xys:
- print 306 + 200 * xy[0], 396 - 200 * xy[1], cmd
- cmd = 'lineto'
- print 'stroke'
- def mec_test():
- th0, th1 = 0, pi / 4
- fnl = mk_ths_fnl(th0, th1)
- params = solve_mec_nested(th0, th1, fnl)
- k, lam1, lam2 = params
- xys, cost, x, y, th = run_mec_cos(k, lam1, lam2, 1000)
- plot(xys)
- print '% run_mec_cos:', cost, x, y, th
- print '1 0 0 setrgbcolor'
- xys, cost, x, y, th = run_elastica(-.5, .5, k, lam1, lam2)
- print '%', xys
- plot(xys)
- print '% run_elastica:', cost, x, y, th
- print 'showpage'
- print '%', params
- def lenfig():
- print '306 720 translate'
- th0, th1 = pi / 2, pi / 2
- for i in range(1, 10):
- y = .1 * i + .003
- fnl = mk_y_fnl(th0, th1, y)
- params = solve_mec_3constr(fnl)
- k, lam1, lam2 = params
- print 'gsave 0.5 dup scale -306 -396 translate'
- xys, cost, x, y, th = run_elastica(-2, 2, k, lam1, lam2, 100)
- print 'gsave [2] 0 setdash'
- plot(xys)
- print 'grestore'
- xys, cost, x, y, th = run_elastica(-.5, .5, k, lam1, lam2, 100)
- plot(xys)
- print 'grestore'
- print '% y =', y, 'params =', params
- if lam2 < 0:
- mymaxk = k
- else:
- mymaxk = sqrt(k * k + 4 * lam2)
- lam = abs(lam2) / (mymaxk * mymaxk)
- print '-200 0 moveto /Symbol 12 selectfont (l) show'
- print '/Times-Roman 12 selectfont ( = %.4g) show' % lam
- print '0 -70 translate'
- print 'showpage'
- def lenplot(figno, th0, th1):
- result = []
- if figno in (1, 2):
- imax = 181
- elif figno == 3:
- imax = 191
- for i in range(1, imax):
- yy = .005 * i
- if figno in (1, 2) and i == 127:
- yy = 2 / pi
- if figno == 3 and i == 165:
- yy = .8270
- fnl = mk_y_fnl(th0, th1, yy)
- params = solve_mec_3constr(fnl)
- k, lam1, lam2 = params
- xys, cost, x0, y0, th = run_elastica(-.5, .5, k, lam1, lam2, 100)
- if lam2 < 0:
- mymaxk = k
- else:
- mymaxk = sqrt(k * k + 4 * lam2)
- lam = abs(lam2) / (mymaxk * mymaxk)
- result.append((yy, lam, cost))
- return result
- def lengraph(figno):
- if figno in (1, 2):
- eps_prologue(15, 47, 585, 543)
- th0, th1 = pi / 2, pi / 2
- yscale = 900
- ytic = .05
- ymax = 10
- elif figno == 3:
- eps_prologue(15, 47, 585, 592)
- th0, th1 = pi / 3, pi / 3
- yscale = 500
- ytic = .1
- ymax = 10
- x0 = 42
- xscale = 7.5 * 72
- y0 = 72
- print '/Times-Roman 12 selectfont'
- print '/ss 1.5 def'
- print '/circle { ss 0 moveto currentpoint exch ss sub exch ss 0 360 arc } bind def'
- print '.5 setlinewidth'
- print x0, y0, 'moveto', xscale, '0 rlineto 0', yscale * ytic * ymax, 'rlineto', -xscale, '0 rlineto closepath stroke'
- for i in range(0, 11):
- print x0 + .1 * i * xscale, y0, 'moveto 0 6 rlineto stroke'
- print x0 + .1 * i * xscale, y0 + ytic * ymax * yscale, 'moveto 0 -6 rlineto stroke'
- print x0 + .1 * i * xscale, y0 - 12, 'moveto'
- print '(%.1g) dup stringwidth exch -.5 mul exch rmoveto show' % (.1 * i)
- for i in range(0, 11):
- print x0, y0 + ytic * i * yscale, 'moveto 6 0 rlineto stroke'
- print x0 + xscale, y0 + ytic * i * yscale, 'moveto -6 0 rlineto stroke'
- print x0 - 3, y0 + ytic * i * yscale - 3.5, 'moveto'
- print '(%.2g) dup stringwidth exch neg exch rmoveto show' % (ytic * i)
- print x0 + .25 * xscale, y0 - 24, 'moveto (chordlen / arclen) show'
- print x0 - 14, y0 + ytic * ymax * yscale + 10, 'moveto /Symbol 12 selectfont (l) show'
- if figno in (1, 2):
- print x0 + 2 / pi * xscale, y0 - 18, 'moveto'
- print '(2/p) dup stringwidth exch -.5 mul exch rmoveto show'
- print 'gsave [3] 0 setdash'
- print x0, y0 + .25 * yscale, 'moveto', xscale, '0 rlineto stroke'
- if figno == 3:
- print x0, y0 + .5 * yscale, 'moveto', xscale, '0 rlineto stroke'
- xinterest = .81153
- print x0 + xinterest * xscale, y0, 'moveto 0', yscale * .5, 'rlineto stroke'
- print 'grestore'
- print '.75 setlinewidth'
- if 1:
- if figno in (1, 2):
- costscale = .01 * yscale
- elif figno == 3:
- costscale = .0187 * yscale
- lenresult = lenplot(figno, th0, th1)
- cmd = 'moveto'
- for x, y, cost in lenresult:
- print x0 + xscale * x, y0 + yscale * y, cmd
- cmd = 'lineto'
- print 'stroke'
- if figno in (2, 3):
- cmd = 'moveto'
- for x, y, cost in lenresult:
- print x0 + xscale * x, y0 + costscale * cost, cmd
- cmd = 'lineto'
- print 'stroke'
- cmd = 'moveto'
- for x, y, cost in lenresult:
- print x0 + xscale * x, y0 + costscale * x * cost, cmd
- cmd = 'lineto'
- print 'stroke'
- print '/Times-Roman 12 selectfont'
- if figno == 2:
- xlm, ylm = .75, 7
- xls, yls = .42, 15
- elif figno == 3:
- xlm, ylm = .6, 3
- xls, yls = .37, 15
- print x0 + xscale * xlm, y0 + costscale * ylm, 'moveto'
- print '(MEC cost) show'
- print x0 + xscale * xls, y0 + costscale * yls, 'moveto'
- print '(SIMEC cost) show'
- if figno == 1:
- minis = [(.05, 5, -5),
- (.26, -40, 10),
- (.4569466, -5, -10),
- (.55, 35, 12),
-
- (.6026, -60, 45),
- (.6046, -60, 15),
- (.6066, -60, -15),
-
- (.6213, -22, 10),
- (.6366198, 15, 22),
- (.66, 20, 10),
- (.9, 0, -10)]
- elif figno == 2:
- minis = [(.4569466, -5, -10),
- (.6366198, 15, 22)]
- elif figno == 3:
- minis = [(.741, 55, -10),
- (.81153, -30, 20),
- (.8270, 20, 30)]
- for yy, xo, yo in minis:
- fnl = mk_y_fnl(th0, th1, yy)
- params = solve_mec_3constr(fnl)
- k, lam1, lam2 = params
- if lam2 < 0:
- mymaxk = k
- else:
- mymaxk = sqrt(k * k + 4 * lam2)
- lam = abs(lam2) / (mymaxk * mymaxk)
- x = x0 + xscale * yy
- y = y0 + yscale * lam
- print 'gsave %g %g translate circle fill' % (x, y)
- print '%g %g translate 0.15 dup scale' % (xo, yo)
- print '-306 -396 translate'
- print '2 setlinewidth'
- if yy < .6 or yy > .61:
- s = 2
- elif yy == .6046:
- s = 2.8
- else:
- s = 5
- xys, cost, x, y, th = run_elastica(-s, s, k, lam1, lam2, 100)
- print 'gsave [10] 0 setdash'
- plot(xys)
- print 'grestore 6 setlinewidth'
- xys, cost, x, y, th = run_elastica(-.5, .5, k, lam1, lam2, 100)
- plot(xys)
- print 'grestore'
-
- print 'showpage'
- eps_trailer()
- def draw_axes(x0, y0, xscale, yscale, xmax, ymax, nx, ny):
- print '.5 setlinewidth'
- print '/Times-Roman 12 selectfont'
- print x0, y0, 'moveto', xscale * xmax, '0 rlineto 0', yscale * ymax, 'rlineto', -xscale * xmax, '0 rlineto closepath stroke'
- xinc = (xmax * xscale * 1.) / nx
- yinc = (ymax * yscale * 1.) / ny
- for i in range(0, nx + 1):
- if i > 0 and i < nx + 1:
- print x0 + xinc * i, y0, 'moveto 0 6 rlineto stroke'
- print x0 + xinc * i, y0 + ymax * yscale, 'moveto 0 -6 rlineto stroke'
- print x0 + xinc * i, y0 - 12, 'moveto'
- print '(%.2g) dup stringwidth exch -.5 mul exch rmoveto show' % ((i * xmax * 1.) / nx)
- for i in range(0, ny + 1):
- if i > 0 and i < ny + 1:
- print x0, y0 + yinc * i, 'moveto 6 0 rlineto stroke'
- print x0 + xmax * xscale, y0 + yinc * i, 'moveto -6 0 rlineto stroke'
- print x0 - 3, y0 + yinc * i - 3.5, 'moveto'
- print '(%.2g) dup stringwidth exch neg exch rmoveto show' % ((i * ymax * 1.) / ny)
-
- def mecchord():
- x0 = 72
- y0 = 72
- thscale = 150
- chscale = 400
- print '.5 setlinewidth'
- print '/ss 1.5 def'
- print '/circle { ss 0 moveto currentpoint exch ss sub exch ss 0 360 arc } bind def'
- draw_axes(x0, y0, thscale, chscale, 3.2, 1, 16, 10)
- print x0 + 1 * thscale, y0 - 28, 'moveto (angle) show'
- print 'gsave', x0 - 32, y0 + .25 * chscale, 'translate'
- print '90 rotate 0 0 moveto (chordlen / arclen) show'
- print 'grestore'
- cmd = 'moveto'
- for i in range(0, 67):
- s = i * .01
- xys, cost, x, y, th = run_elastica(-s, s, 4, 0, -8, 100)
- #plot(xys)
- if s > 0:
- ch = hypot(x, y) / (2 * s)
- else:
- ch = 1
- print '%', s, x, y, th, ch
- print x0 + thscale * th / 2, y0 + ch * chscale, cmd
- cmd = 'lineto'
- print 'stroke'
- print 'gsave %g %g translate circle fill' % (x0 + thscale * th / 2, y0 + ch * chscale)
- print '-30 15 translate 0.25 dup scale'
- print '-306 -396 translate'
- print '2 setlinewidth'
- plot(xys)
- print 'grestore'
- print 'gsave [2] 0 setdash'
- cmd = 'moveto'
- for i in range(0, 151):
- th = pi * i / 150.
- if th > 0:
- ch = sin(th) / th
- else:
- ch = 1
- print x0 + thscale * th, y0 + ch * chscale, cmd
- cmd = 'lineto'
- print 'stroke'
- print 'grestore'
- k0 = 4 * .4536 / (2 / pi)
- s = pi / (2 * k0)
- xys, cost, x, y, th = run_elastica(-s, s, k0, 0, 0, 100)
- th = pi
- ch = 2 / pi
- print 'gsave %g %g translate circle fill' % (x0 + thscale * th / 2, y0 + ch * chscale)
- print '30 15 translate 0.25 dup scale'
- print '-306 -396 translate'
- print '2 setlinewidth'
- plot(xys)
- print 'grestore'
- print x0 + 1.25 * thscale, y0 + .55 * chscale, 'moveto (MEC) show'
- print x0 + 2.3 * thscale, y0 + .35 * chscale, 'moveto (SIMEC) show'
- print 'showpage'
- def trymec(sm, sp):
- xys, thm, cost = run_elastica_half(abs(sm), 0, 1, 0, 10)
- xm, ym, km = xys[-1]
- if sm < 0:
- xm = -xm
- ym = -ym
- thm = -thm
- xys, thp, cost = run_elastica_half(abs(sp), 0, 1, 0, 10)
- xp, yp, kp = xys[-1]
- if sp < 0:
- xp = -xp
- yp = -yp
- thp = -thp
- chth = atan2(yp - ym, xp - xm)
- #print xm, ym, xp, yp, chth, thm, thp
- actual_th0 = chth - thm
- actual_th1 = thp - chth
- return actual_th0, actual_th1
- def findmec_old(th0, th1):
- guess_ds = sqrt(6 * (th1 - th0))
- guess_savg = 2 * (th1 + th0) / guess_ds
- sm = .5 * (guess_savg - guess_ds)
- sp = .5 * (guess_savg + guess_ds)
- #sm, sp = th0, th1
- for i in range(1):
- actual_th0, actual_th1 = trymec(sm, sp)
- guess_dth = 1./6 * (sp - sm) ** 2
- guess_avth = .5 * (sp + sm) * (sp - sm)
- guess_th0 = .5 * (guess_avth - guess_dth)
- guess_th1 = .5 * (guess_avth + guess_dth)
- print sm, sp, actual_th0, actual_th1, guess_th0, guess_th1
- def mecplots():
- print '2 dup scale'
- print '-153 -296 translate'
- scale = 45
- print '0.25 setlinewidth'
- print 306 - scale * pi/2, 396, 'moveto', 306 + scale * pi/2, 396, 'lineto stroke'
- print 306, 396 - scale * pi/2, 'moveto', 306, 396 + scale * pi/2, 'lineto stroke'
- print '/ss .5 def'
- print '/circle { ss 0 moveto currentpoint exch ss sub exch ss 0 360 arc } bind def'
- tic = .1
- maj = 5
- r0, r1 = 0, 81
- for i in range(r0, r1, maj):
- sm = i * tic
- cmd = 'moveto'
- for j in range(i, r1):
- sp = j * tic + 1e-3
- th0, th1 = trymec(sm, sp)
- print '%', sm, sp, th0, th1
- print 306 + scale * th0, 396 + scale * th1, cmd
- cmd = 'lineto'
- print 'stroke'
- for j in range(r0, r1, maj):
- sp = j * tic + 1e-3
- cmd = 'moveto'
- for i in range(0, j + 1):
- sm = i * tic
- th0, th1 = trymec(sm, sp)
- print '%', sm, sp, th0, th1
- print 306 + scale * th0, 396 + scale * th1, cmd
- cmd = 'lineto'
- print 'stroke'
- for i in range(r0, r1, maj):
- sm = i * tic
- for j in range(i, r1, maj):
- sp = j * tic + 1e-3
- th0, th1 = trymec(sm, sp)
- print 'gsave'
- print 306 + scale * th0, 596 + scale * th1, 'translate'
- print 'circle fill'
- uscale = 3
- xys, thm, cost = run_elastica_half(abs(sm), 0, 1, 0, 100)
- x0, y0 = xys[-1][0], xys[-1][1]
- if sm < 0:
- x0, y0 = -x0, -y0
- xys, thm, cost = run_elastica_half(abs(sp), 0, 1, 0, 100)
- x1, y1 = xys[-1][0], xys[-1][1]
- if sp < 0:
- x1, y1 = -x1, -y1
- cmd = 'moveto'
- for xy in xys:
- print xy[0] * uscale, xy[1] * uscale, cmd
- cmd = 'lineto'
- print 'stroke'
- print '1 0 0 setrgbcolor'
- print x0 * uscale, y0 * uscale, 'moveto'
- print x1 * uscale, y1 * uscale, 'lineto stroke'
- print 'grestore'
- print 'showpage'
- def findmec(th0, th1):
- delta = 1e-3
- if th0 < 0 and th0 - th1 < .1:
- sm = 5.
- sp = 6.
- else:
- sm = 3.
- sp = 5.
- params = [sm, sp]
- lasterr = 1e6
- for i in range(25):
- sm, sp = params
- ath0, ath1 = trymec(sm, sp)
- c1c, c2c = th0 - ath0, th1 - ath1
- err = c1c * c1c + c2c * c2c
- if 0:
- print '%findmec', sm, sp, ath0, ath1, err
- sys.stdout.flush()
- if err < 1e-9:
- return params
- if err > lasterr:
- return None
- lasterr = err
- dc1s = []
- dc2s = []
- for j in range(len(params)):
- params1 = N.array(params)
- params1[j] += delta
- sm, sp = params1
- ath0, ath1 = trymec(sm, sp)
- c1p, c2p = th0 - ath0, th1 - ath1
- params1 = N.array(params)
- params1[j] -= delta
- sm, sp = params1
- ath0, ath1 = trymec(sm, sp)
- c1m, c2m = th0 - ath0, th1 - ath1
- dc1s.append((c1p - c1m) / (2 * delta))
- dc2s.append((c2p - c2m) / (2 * delta))
- jm = N.array([dc1s, dc2s])
- ji = la.inverse(jm)
- dp = N.dot(ji, [c1c, c2c])
- if i < 4:
- scale = .5
- else:
- scale = 1
- params -= scale * dp
- if params[0] < 0: params[0] = 0.
- return params
- def mecrange(figtype):
- scale = 130
- eps_prologue(50, 110, 570, 630)
- print -50, 0, 'translate'
- print '0.5 setlinewidth'
- thlmin, thlmax = -pi/2, 2.4
- thrmin, thrmax = -2.2, pi / 2 + .2
- print 306 + scale * thlmin, 396, 'moveto', 306 + scale * thlmax, 396, 'lineto stroke'
- print 306, 396 + scale * thrmin, 'moveto', 306, 396 + scale * thrmax, 'lineto stroke'
- print 'gsave [2] 0 setdash'
- print 306, 396 + scale * pi / 2, 'moveto'
- print 306 + scale * thlmax, 396 + scale * pi / 2, 'lineto stroke'
- print 306 + scale * thlmin, 396 - scale * pi / 2, 'moveto'
- print 306 + scale * thlmax, 396 - scale * pi / 2, 'lineto stroke'
- print 306 + scale * pi / 2, 396 + scale * thrmin, 'moveto'
- print 306 + scale * pi / 2, 396 + scale * thrmax, 'lineto stroke'
- print 'grestore'
- print 306 + 3, 396 + scale * thrmax - 10, 'moveto'
- print '/Symbol 12 selectfont (q) show'
- print 0, -2, 'rmoveto'
- print '/Times-Italic 9 selectfont (right) show'
- print 306 - 18, 396 + scale * pi / 2 - 4, 'moveto'
- print '/Symbol 12 selectfont (p/2) show'
- print 306 + scale * 2.2, 396 - scale * pi / 2 + 2, 'moveto'
- print '/Symbol 12 selectfont (-p/2) show'
- print 306 + scale * pi/2 + 2, 396 + scale * thrmax - 10, 'moveto'
- print '/Symbol 12 selectfont (p/2) show'
- print 306 + scale * 2.2, 396 + 6, 'moveto'
- print '/Symbol 12 selectfont (q) show'
- print 0, -2, 'rmoveto'
- print '/Times-Italic 9 selectfont (left) show'
- print '/ss 0.8 def'
- print '/circle { ss 0 moveto currentpoint exch ss sub exch ss 0 360 arc } bind def'
- cmd = 'moveto'
- for i in range(0, 201):
- th = (i * .005 - .75 )* pi
- rmin = 1.5
- rmax = 2.5
- for j in range(20):
- r = (rmin + rmax) * .5
- th0 = r * cos(th)
- th1 = r * sin(th)
- if findmec(th0, th1) == None:
- rmax = r
- else:
- rmin = r
- r = (rmin + rmax) * .5
- th0 = r * cos(th)
- th1 = r * sin(th)
- print '%', r, th, th0, th1
- print 306 + scale * th0, 396 + scale * th1, cmd
- cmd = 'lineto'
- sys.stdout.flush()
- print 'stroke'
- sys.stdout.flush()
-
- for i in range(-11, 12):
- for j in range(-11, i + 1):
- th0, th1 = i * .196, j * .196
- print '%', th0, th1
- params = findmec(th0, th1)
- if params != None:
- sm, sp = params
- print 'gsave'
- print 306 + scale * th0, 396 + scale * th1, 'translate'
- uscale = 22
- k0, lam1, lam2 = justify_mec(sm, sp)
- xys, cost, x, y, th = run_elastica(-.5, .5, k0, lam1, lam2)
- cmdm = 'moveto'
- dx = xys[-1][0] - xys[0][0]
- dy = xys[-1][1] - xys[0][1]
- ch = hypot(dx, dy)
- chth = atan2(dy, dx)
- if figtype == 'mecrange':
- print 'circle fill'
- s = uscale * sin(chth) / ch
- c = uscale * cos(chth) / ch
- h = -xys[0][0] * s + xys[0][1] * c
- for xy in xys:
- print xy[0] * c + xy[1] * s, h + xy[0] * s - xy[1] * c, cmdm
- cmdm = 'lineto'
- elif figtype == 'mecrangek':
- ds = 1. / (len(xys) - 1)
- sscale = 13. / ch
- kscale = 3 * ch
- print 'gsave .25 setlinewidth'
- print sscale * -.5, 0, 'moveto', sscale, 0, 'rlineto stroke'
- print 'grestore'
- for l in range(len(xys)):
- print sscale * (ds * l - 0.5), kscale * xys[l][2], cmdm
- cmdm = 'lineto'
- print 'stroke'
- print 'grestore'
- sys.stdout.flush()
- print 'showpage'
- eps_trailer()
- # given sm, sp in [0, 1, 0] mec, return params for -0.5..0.5 segment
- def justify_mec(sm, sp):
- sc = (sm + sp) * 0.5
- xys, thc, cost = run_elastica_half(sc, 0, 1, 0, 100)
- print '% sc =', sc, 'thc =', thc
- k0, lam1, lam2 = xys[-1][2], cos(thc), -sin(thc)
- ds = sp - sm
- k0 *= ds
- lam1 *= ds * ds
- lam2 *= ds * ds
- return [k0, lam1, lam2]
- import sys
- figname = sys.argv[1]
- if len(figname) > 4 and figname[-4:] == '.pdf': figname = figname[:-4]
- if figname in ('lengraph1', 'lengraph2', 'lengraph3'):
- lengraph(int(figname[-1]))
- #mec_test()
- #lenfig()
- elif figname == 'mecchord':
- mecchord()
- elif figname in ('mecrange', 'mecrangek'):
- mecrange(figname)
- elif figname == 'mecplots':
- mecplots()
- elif figname == 'findmec':
- findmec(-.1, -.1)
- findmec(-.2, -.2)
|