Dukales

http://stackoverflow.com/questions/19145115

Nov 23rd, 2013
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.91 KB | None | 0 0
  1. function using()
  2.     return error('using: ' .. arg[0] .. ' <number of points>')
  3. end
  4.  
  5. function points_from_file(infile)
  6.     local points = {}
  7.     local infile = io.open(infile, 'r')
  8.     local d = infile:read('*number')
  9.     if d ~= 2 then
  10.         error('dimensions is not two')
  11.     end
  12.     local n = infile:read('*number')
  13.     while true do
  14.         local x, y = infile:read('*number', '*number')
  15.         if not x and not y then
  16.             break
  17.         end
  18.         if not x or not y then
  19.             error('wrong format of input file: line does not contain two coordinates')
  20.         end
  21.         table.insert(points, {x, y})
  22.     end
  23.     infile:close()
  24.     if n ~= #points then
  25.         error('second line not contain real count of points')
  26.     end
  27.     return points
  28. end
  29.  
  30. if not arg then
  31.     error("script should use as standalone")
  32. end
  33. if #arg ~= 1 then
  34.     using()
  35. end
  36. local n = tonumber(arg[1])
  37. if not n then
  38.     using()
  39. end
  40. local bounding_box = math.sqrt(math.pi) / 2.0
  41. local fnp = os.tmpname()
  42. local fnchp = os.tmpname()
  43. os.execute('rbox ' .. n .. ' B' .. bounding_box .. ' D2 n t | tee ' .. fnp .. ' | qhull p | tee ' .. fnchp .. ' > nul') -- Windows specific part is "> nul"
  44. local sp = points_from_file(fnp) -- source points
  45. os.remove(fnp)
  46. local chp = points_from_file(fnchp) -- convex hull points
  47. os.remove(fnchp)
  48. local m = #chp
  49. if m < 3 then
  50.     io.stderr:write('convex hull consist of less than three points')
  51.     return
  52. end
  53. local pole = {0.0, 0.0} -- offset of polar origin relative to cartesian origin
  54. for _, point in ipairs(chp) do
  55.     pole[1] = pole[1] + point[1]
  56.     pole[2] = pole[2] + point[2]
  57. end
  58. pole[1] = pole[1] / m
  59. pole[2] = pole[2] / m
  60. print("pole = ", pole[1], pole[2])
  61. local chcc = {}
  62. for _, point in ipairs(chp) do
  63.     table.insert(chcc, {point[1] - pole[1], point[2] - pole[2]})
  64. end
  65. local theta_min = 2.0 * math.pi -- angle between abscissa ort of cartesian and ort of polar coordinates
  66. local rho_mean = 0.0
  67. local rho_max = 0.0
  68. local chpc = {} -- {theta, rho} pairs
  69. for _, point in ipairs(chcc) do
  70.     local rho = math.sqrt(point[1] * point[1] + point[2] * point[2])
  71.     local theta = math.atan2(point[2], point[1])
  72.     if theta < 0.0 then -- [-pi:pi] -> [0:2 * pi]
  73.         theta = theta + 2.0 * math.pi
  74.     end
  75.     table.insert(chpc, {theta, rho})
  76.     if theta_min > theta then
  77.         theta_min = theta
  78.     end
  79.     rho_mean = rho_mean + rho
  80.     if rho_max < rho then
  81.         rho_max = rho
  82.     end
  83. end
  84. theta_min = -theta_min
  85. rho_mean = rho_mean / m
  86. rho_max = rho_max / rho_mean
  87. for pos, point in ipairs(chpc) do
  88.     local theta = (point[1] + theta_min) / math.pi -- [0:2 * pi] -> [0:2]
  89.     local rho = point[2] / rho_mean
  90.     table.remove(chpc, pos)
  91.     table.insert(chpc, pos, {theta, rho})
  92. end
  93. table.sort(chpc, function (lhs, rhs) return lhs[1] < rhs[1] end)
  94. -- table.insert(chpc, {chpc[#chpc][1] - 2.0 * math.pi, chpc[#chpc][2]})
  95. table.insert(chpc, {2.0, chpc[1][2]})
  96. -- table.sort(chpc, function (lhs, rhs) return lhs[1] < rhs[1] end)
  97.  
  98. local solution = {}
  99. solution.x = {}
  100. solution.y = {}
  101. for _, point in ipairs(chpc) do
  102.     table.insert(solution.x, point[1])
  103.     table.insert(solution.y, point[2])
  104. end
  105. solution.c = {}
  106. for i, xi in ipairs(solution.x) do
  107.     local c = solution.y[i]
  108.     for j, xj in ipairs(solution.x) do
  109.         if i ~= j then
  110.             c = c / (xi - xj)
  111.         end
  112.     end
  113.     solution.c[i] = c
  114. end
  115. function solution:monomial(i, x)
  116.     local y = self.c[i]
  117.     for j, xj in ipairs(solution.x) do
  118.         if xj == x then
  119.             if i == j then
  120.                 return self.y[i]
  121.             else
  122.                 return 0.0
  123.             end
  124.         end
  125.         if i ~= j then
  126.             y = y * (x - xj)
  127.         end
  128.     end
  129.     return y
  130. end
  131. function solution:polynomial(x)
  132.     local y = self:monomial(1, x)
  133.     for i = 2, #solution.y do
  134.         y = y + self:monomial(i, x)
  135.     end
  136.     return y
  137. end
  138.  
  139. local gnuplot = io.popen('gnuplot', 'w')
  140.  
  141. gnuplot:write('reset;\n')
  142. gnuplot:write('set terminal wxt 1;\n')
  143. gnuplot:write(string.format('set xrange [%f:%f];\n', -bounding_box, bounding_box))
  144. gnuplot:write(string.format('set yrange [%f:%f];\n', -bounding_box, bounding_box))
  145. gnuplot:write('set size square;\n')
  146. gnuplot:write(string.format('set xtics %f;\n', 0.1))
  147. gnuplot:write(string.format('set ytics %f;\n', 0.1))
  148. gnuplot:write('set grid xtics ytics;\n')
  149. gnuplot:write('plot "-" using 1:2 notitle with points, "-" using 1:2:3:4 notitle with vectors;\n')
  150. for _, point in ipairs(sp) do
  151.     gnuplot:write(string.format('%f %f\n', point[1], point[2]))
  152. end
  153. gnuplot:write('e\n')
  154. for _, point in ipairs(chcc) do
  155.     gnuplot:write(string.format('%f %f %f %f\n', pole[1], pole[2], point[1], point[2]))
  156. end
  157. gnuplot:write('e\n')
  158. gnuplot:flush();
  159.  
  160. gnuplot:write('reset;\n')
  161. gnuplot:write('set terminal wxt 2;\n')
  162. gnuplot:write('set border 0;\n')
  163. gnuplot:write('unset xtics;\n')
  164. gnuplot:write('unset ytics;\n')
  165. gnuplot:write('set polar;\n')
  166. gnuplot:write('set grid polar;\n')
  167. gnuplot:write('set trange [-pi:2 * pi];\n')
  168. gnuplot:write(string.format('set rrange [-0:%f];\n', rho_max))
  169. gnuplot:write('set size square;\n')
  170. gnuplot:write('set view equal xy;\n')
  171. -- gnuplot:write(string.format('set xlabel "%f";\n', rho_mean - 1.0))
  172. gnuplot:write(string.format('set arrow 1 from 0,0 to %f,%f;\n', rho_max * math.cos(theta_min), rho_max * math.sin(theta_min)))
  173. gnuplot:write(string.format('set label 1 " origin" at %f,%f left rotate by %f;\n', rho_max * math.cos(theta_min), rho_max * math.sin(theta_min), math.deg(theta_min)))
  174. gnuplot:write('plot "-" using 1:2:3:4 notitle with vectors, "-" using 1:2 notitle with lines, "-" using 1:2 notitle with lines;\n')
  175. for _, point in ipairs(chpc) do
  176.     gnuplot:write(string.format('0 0 %f %f\n', point[1] * math.pi, point[2]))
  177. end
  178. gnuplot:write('e\n')
  179. for _, point in ipairs(chpc) do
  180.     gnuplot:write(string.format('%f %f\n', point[1] * math.pi, point[2]))
  181. end
  182. gnuplot:write('e\n')
  183. do
  184.     local points_count = 512
  185.     local dx = 2.0 / points_count
  186.     local x = 0.0
  187.     for i = 1, points_count do
  188.         gnuplot:write(string.format('%f %f\n', x * math.pi, solution:polynomial(x)))
  189.         x = x + dx
  190.     end
  191.     gnuplot:write('e\n')
  192. end
  193. gnuplot:flush();
  194.  
  195. gnuplot:write('reset;\n')
  196. gnuplot:write('set terminal wxt 3;\n')
  197. gnuplot:write(string.format('set xrange [-1:2];\n'))
  198. gnuplot:write(string.format('set yrange [0:2];\n'))
  199. gnuplot:write(string.format('set size ratio %f;\n', rho_max / 3.0))
  200. gnuplot:write(string.format('set xtics %f;\n', 0.5))
  201. gnuplot:write(string.format('set ytics %f;\n', 0.5))
  202. gnuplot:write('set grid xtics ytics;\n')
  203. gnuplot:write(string.format('set arrow 1 nohead from 0,%f to 2,%f linetype 3;\n', chpc[1][2], chpc[1][2]))
  204. gnuplot:write(string.format('set label 1 "glue points " at 0,%f right;\n', chpc[1][2]))
  205. gnuplot:write('plot "-" using 1:2 notitle with lines, "-" using 1:2 notitle with lines;\n')
  206. for _, point in ipairs(chpc) do
  207.     gnuplot:write(string.format('%f %f\n', point[1], point[2]))
  208. end
  209. gnuplot:write('e\n')
  210. do
  211.     local points_count = 512
  212.     local dx = 2.0 / points_count
  213.     local x = 0.0
  214.     for i = 1, points_count do
  215.         gnuplot:write(string.format('%f %f\n', x, solution:polynomial(x)))
  216.         x = x + dx
  217.     end
  218.     gnuplot:write('e\n')
  219. end
  220. gnuplot:flush();
  221.  
  222. os.execute('pause');
  223. gnuplot:write('exit\n');
  224. gnuplot:flush();
  225. gnuplot:close()
Add Comment
Please, Sign In to add comment