123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- import sys
- from math import *
- import fromcubic
- import tocubic
- import cornu
- 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'
- def fit_cubic_superfast(z0, z1, arclen, th0, th1, aab):
- chord = hypot(z1[0] - z0[0], z1[1] - z0[1])
- cth0, sth0 = cos(th0), sin(th0)
- cth1, sth1 = -cos(th1), -sin(th1)
- armlen = .66667 * arclen
- a = armlen * aab
- b = armlen - a
- bz = [z0, (z0[0] + cth0 * a, z0[1] + sth0 * a),
- (z1[0] + cth1 * b, z1[1] + sth1 * b), z1]
- return bz
- def fit_cubic(z0, z1, arclen, th_fn, fast, aabmin = 0, aabmax = 1.):
- chord = hypot(z1[0] - z0[0], z1[1] - z0[1])
- if (arclen < 1.000001 * chord):
- return [z0, z1], 0
- th0 = th_fn(0)
- th1 = th_fn(arclen)
- imax = 4
- jmax = 10
- if fast:
- imax = 1
- jmax = 0
- for i in range(imax):
- for j in range(jmax + 1):
- if jmax == 0:
- aab = 0.5 * (aabmin + aabmax)
- else:
- aab = aabmin + (aabmax - aabmin) * j / jmax
- if fast == 2:
- bz = fit_cubic_superfast(z0, z1, arclen, th0, th1, aab)
- else:
- bz = tocubic.fit_cubic_arclen(z0, z1, arclen, th0, th1, aab)
- score = tocubic.measure_bz_rk4(bz, arclen, th_fn)
- print '% aab =', aab, 'score =', score
- sys.stdout.flush()
- if j == 0 or score < best_score:
- best_score = score
- best_aab = aab
- best_bz = bz
- daab = .06 * (aabmax - aabmin)
- aabmin = max(0, best_aab - daab)
- aabmax = min(1, best_aab + daab)
- print '%--- best_aab =', best_aab
- return best_bz, best_score
- def cornu_to_cubic(t0, t1, figno):
- if figno == 1:
- aabmin = 0
- aabmax = 0.4
- elif figno == 2:
- aabmin = 0.5
- aabmax = 1.
- else:
- aabmin = 0
- aabmax = 1.
- fast = 0
- if figno == 3:
- fast = 1
- elif figno == 4:
- fast = 2
- def th_fn(s):
- return (s + t0) ** 2
- y0, x0 = cornu.eval_cornu(t0)
- y1, x1 = cornu.eval_cornu(t1)
- bz, score = fit_cubic((x0, y0), (x1, y1), t1 - t0, th_fn, fast, aabmin, aabmax)
- return bz, score
- def plot_k_of_bz(bz):
- dbz = tocubic.bz_deriv(bz)
- ddbz = tocubic.bz_deriv(dbz)
- cmd = 'moveto'
- ss = [0]
- def arclength_deriv(x, ss):
- dx, dy = tocubic.bz_eval(dbz, x)
- return [hypot(dx, dy)]
- dt = 0.01
- t = 0
- for i in range(101):
- dx, dy = tocubic.bz_eval(dbz, t)
- ddx, ddy = tocubic.bz_eval(ddbz, t)
- k = (ddy * dx - dy * ddx) / (dx * dx + dy * dy) ** 1.5
- print 100 + 500 * ss[0], 100 + 200 * k, cmd
- cmd = 'lineto'
- dsdx = arclength_deriv(t, ss)
- tocubic.rk4(ss, dsdx, t, .01, arclength_deriv)
- t += dt
- print 'stroke'
- def plot_k_nominal(s0, s1):
- k0 = 2 * s0
- k1 = 2 * s1
- print 'gsave 0.5 setlinewidth'
- print 100, 100 + 200 * k0, 'moveto'
- print 100 + 500 * (s1 - s0), 100 + 200 * k1, 'lineto'
- print 'stroke grestore'
- def simple_bez():
- eps_prologue(95, 126, 552, 508, 0)
- tocubic.plot_prolog()
- print '/ss 1.5 def'
- print '/circle { ss 0 moveto currentpoint exch ss sub exch ss 0 360 arc } bind def'
- bz, score = cornu_to_cubic(.5, 1.1, 2)
- fromcubic.plot_bzs([[bz]], (-400, 100), 1000, True)
- print 'stroke'
- print '/Times-Roman 12 selectfont'
- print '95 130 moveto ((x0, y0)) show'
- print '360 200 moveto ((x1, y1)) show'
- print '480 340 moveto ((x2, y2)) show'
- print '505 495 moveto ((x3, y3)) show'
- print 'showpage'
- eps_trailer()
- def fast_bez(figno):
- if figno == 3:
- y1 = 520
- else:
- y1 = 550
- eps_prologue(95, 140, 552, y1, 0)
- tocubic.plot_prolog()
- print '/ss 1.5 def'
- print '/circle { ss 0 moveto currentpoint exch ss sub exch ss 0 360 arc } bind def'
- bz, score = cornu_to_cubic(.5, 1.1, figno)
- fromcubic.plot_bzs([[bz]], (-400, 100), 1000, True)
- print 'stroke'
- plot_k_nominal(.5, 1.1)
- plot_k_of_bz(bz)
- print 'showpage'
- eps_trailer()
- def bezfig(s1):
- eps_prologue(95, 38, 510, 550, 0)
- #print '0.5 0.5 scale 500 100 translate'
- tocubic.plot_prolog()
- print '/ss 1.5 def'
- print '/circle { ss 0 moveto currentpoint exch ss sub exch ss 0 360 arc } bind def'
- bz, score = cornu_to_cubic(.5, 0.85, 1)
- fromcubic.plot_bzs([[bz]], (-400, 0), 1000, True)
- print 'stroke'
- plot_k_nominal(.5, 0.85)
- plot_k_of_bz(bz)
- bz, score = cornu_to_cubic(.5, 0.85, 2)
- fromcubic.plot_bzs([[bz]], (-400, 100), 1000, True)
- print 'stroke'
- print 'gsave 0 50 translate'
- plot_k_nominal(.5, .85)
- plot_k_of_bz(bz)
- print 'grestore'
- print 'showpage'
- import sys
- if __name__ == '__main__':
- figno = int(sys.argv[1])
- if figno == 0:
- simple_bez()
- elif figno == 1:
- bezfig(1.0)
- elif figno == 2:
- bezfig(0.85)
- else:
- fast_bez(figno)
- #fast_bez(4)
|