poly3.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. # Numerical techniques for solving 3rd order polynomial spline systems
  2. # The standard representation is the vector of derivatives at s=0,
  3. # with -.5 <= s <= 5.
  4. #
  5. # Thus, \kappa(s) = k0 + k1 s + 1/2 k2 s^2 + 1/6 k3 s^3
  6. from math import *
  7. def eval_cubic(a, b, c, d, x):
  8. return ((d * x + c) * x + b) * x + a
  9. # integrate over s = [0, 1]
  10. def int_3spiro_poly(ks, n):
  11. x, y = 0, 0
  12. th = 0
  13. ds = 1.0 / n
  14. th1, th2, th3, th4 = ks[0], .5 * ks[1], (1./6) * ks[2], (1./24) * ks[3]
  15. k0, k1, k2, k3 = ks[0] * ds, ks[1] * ds, ks[2] * ds, ks[3] * ds
  16. s = 0
  17. result = [(x, y)]
  18. for i in range(n):
  19. sm = s + 0.5 * ds
  20. th = sm * eval_cubic(th1, th2, th3, th4, sm)
  21. cth = cos(th)
  22. sth = sin(th)
  23. km0 = ((1./6 * k3 * sm + .5 * k2) * sm + k1) * sm + k0
  24. km1 = ((.5 * k3 * sm + k2) * sm + k1) * ds
  25. km2 = (k3 * sm + k2) * ds * ds
  26. km3 = k3 * ds * ds * ds
  27. #print km0, km1, km2, km3
  28. u = 1 - km0 * km0 / 24
  29. v = km1 / 24
  30. u = 1 - km0 * km0 / 24 + (km0 ** 4 - 4 * km0 * km2 - 3 * km1 * km1) / 1920
  31. v = km1 / 24 + (km3 - 6 * km0 * km0 * km1) / 1920
  32. x += cth * u - sth * v
  33. y += cth * v + sth * u
  34. result.append((ds * x, ds * y))
  35. s += ds
  36. return result
  37. def integ_chord(k, n = 64):
  38. ks = (k[0] * .5, k[1] * .25, k[2] * .125, k[3] * .0625)
  39. xp, yp = int_3spiro_poly(ks, n)[-1]
  40. ks = (k[0] * -.5, k[1] * .25, k[2] * -.125, k[3] * .0625)
  41. xm, ym = int_3spiro_poly(ks, n)[-1]
  42. dx, dy = .5 * (xp + xm), .5 * (yp + ym)
  43. return hypot(dx, dy), atan2(dy, dx)
  44. # Return th0, th1, k0, k1 for given params
  45. def calc_thk(ks):
  46. chord, ch_th = integ_chord(ks)
  47. th0 = ch_th - (-.5 * ks[0] + .125 * ks[1] - 1./48 * ks[2] + 1./384 * ks[3])
  48. th1 = (.5 * ks[0] + .125 * ks[1] + 1./48 * ks[2] + 1./384 * ks[3]) - ch_th
  49. k0 = chord * (ks[0] - .5 * ks[1] + .125 * ks[2] - 1./48 * ks[3])
  50. k1 = chord * (ks[0] + .5 * ks[1] + .125 * ks[2] + 1./48 * ks[3])
  51. #print '%', (-.5 * ks[0] + .125 * ks[1] - 1./48 * ks[2] + 1./384 * ks[3]), (.5 * ks[0] + .125 * ks[1] + 1./48 * ks[2] + 1./384 * ks[3]), ch_th
  52. return th0, th1, k0, k1
  53. def calc_k1k2(ks):
  54. chord, ch_th = integ_chord(ks)
  55. k1l = chord * chord * (ks[1] - .5 * ks[2] + .125 * ks[3])
  56. k1r = chord * chord * (ks[1] + .5 * ks[2] + .125 * ks[3])
  57. k2l = chord * chord * chord * (ks[2] - .5 * ks[3])
  58. k2r = chord * chord * chord * (ks[2] + .5 * ks[3])
  59. return k1l, k1r, k2l, k2r
  60. def plot(ks):
  61. ksp = (ks[0] * .5, ks[1] * .25, ks[2] * .125, ks[3] * .0625)
  62. pside = int_3spiro_poly(ksp, 64)
  63. ksm = (ks[0] * -.5, ks[1] * .25, ks[2] * -.125, ks[3] * .0625)
  64. mside = int_3spiro_poly(ksm, 64)
  65. mside.reverse()
  66. for i in range(len(mside)):
  67. mside[i] = (-mside[i][0], -mside[i][1])
  68. pts = mside + pside[1:]
  69. cmd = "moveto"
  70. for j in range(len(pts)):
  71. x, y = pts[j]
  72. print 306 + 300 * x, 400 + 300 * y, cmd
  73. cmd = "lineto"
  74. print "stroke"
  75. x, y = pts[0]
  76. print 306 + 300 * x, 400 + 300 * y, "moveto"
  77. x, y = pts[-1]
  78. print 306 + 300 * x, 400 + 300 * y, "lineto .5 setlinewidth stroke"
  79. print "showpage"
  80. def solve_3spiro(th0, th1, k0, k1):
  81. ks = [0, 0, 0, 0]
  82. for i in range(5):
  83. th0_a, th1_a, k0_a, k1_a = calc_thk(ks)
  84. dth0 = th0 - th0_a
  85. dth1 = th1 - th1_a
  86. dk0 = k0 - k0_a
  87. dk1 = k1 - k1_a
  88. ks[0] += (dth0 + dth1) * 1.5 + (dk0 + dk1) * -.25
  89. ks[1] += (dth1 - dth0) * 15 + (dk0 - dk1) * 1.5
  90. ks[2] += (dth0 + dth1) * -12 + (dk0 + dk1) * 6
  91. ks[3] += (dth0 - dth1) * 360 + (dk1 - dk0) * 60
  92. #print '% ks =', ks
  93. return ks
  94. def iter_spline(pts, ths, ks):
  95. pass
  96. def solve_vee():
  97. kss = []
  98. for i in range(10):
  99. kss.append([0, 0, 0, 0])
  100. thl = [0] * len(kss)
  101. thr = [0] * len(kss)
  102. k0l = [0] * len(kss)
  103. k0r = [0] * len(kss)
  104. k1l = [0] * len(kss)
  105. k1r = [0] * len(kss)
  106. k2l = [0] * len(kss)
  107. k2r = [0] * len(kss)
  108. for i in range(10):
  109. for j in range(len(kss)):
  110. thl[j], thr[j], k0l[j], k0r[j] = calc_thk(kss[j])
  111. k0l[j], k1r[j], k2l[j], k2r[j] = calc_k1k2(kss[j])
  112. for j in range(len(kss) - 1):
  113. dth = thl[j + 1] + thr[j]
  114. if j == 5: dth += .1
  115. dk0 = k0l[j + 1] - k0r[j]
  116. dk1 = k1l[j + 1] - k1r[j]
  117. dk2 = k2l[j + 1] - k2r[j]
  118. if __name__ == '__main__':
  119. k0 = pi * 3
  120. ks = [0, k0, -2 * k0, 0]
  121. ks = [0, 0, 0, 0.01]
  122. #plot(ks)
  123. thk = calc_thk(ks)
  124. print '%', thk
  125. ks = solve_3spiro(0, 0, 0, 0.001)
  126. print '% thk =', calc_thk(ks)
  127. #plot(ks)
  128. print '%', ks
  129. print calc_k1k2(ks)