Advertisement
Ktlo

Vector module

Aug 30th, 2015
262
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.00 KB | None | 0 0
  1. local math = require "math"
  2. local concat = require "table".concat
  3. local format = require "string".format
  4. local setmetatable = setmetatable
  5. local type, error = type, error
  6. local rawset, rawget = rawset, rawget
  7. --В таких моментах задумываешься над разумностью поступка. Не хватает using
  8. local pow, sqrt, max, floor, acos, sin, cos, modf, pi = math.pow, math.sqrt, math.max, math.floor, math.acos, math.sin, math.cos, math.modf, math.pi
  9. math = nil
  10.  
  11. local vector
  12. local function check(o) --Проверка вектора
  13.     local t = type(o)
  14.     if not (t == "table" and o.object == "vector") then
  15.         error("attempt to perform arithmetic on a "..t.." value", 3)
  16.     end
  17. end
  18. local __index = {
  19.     tostring = function(self, f) --Перевод вектора в строку
  20.         f = type(f) == "number" and f >= 0 and f or 3
  21.         f = "%."..f.."f"
  22.         local r = { }
  23.         for i = 1, self.n do
  24.             local n = self[i]
  25.             r[i] = format(modf(n) == n and "%1d" or f, n)
  26.         end
  27.         return "{"..concat(r, "; ").."}"
  28.     end;
  29.     add = function(a, b) --Сложение
  30.         check(a)
  31.         check(b)
  32.         local v = { }
  33.         for i = 1, max(a.n, b.n) do
  34.             v[i] = (a[i] or 0) + (b[i] or 0)
  35.         end
  36.         return vector(v)
  37.     end;
  38.     sub = function(a, b) --Вычитание
  39.         check(a)
  40.         check(b)
  41.         local v = { }
  42.         for i = 1, max(a.n, b.n) do
  43.             v[i] = (a[i] or 0) - (b[i] or 0)
  44.         end
  45.         return vector(v)
  46.     end;
  47.     mul = function(a, b) --Умножение на скаляр и произведение векторов
  48.         local t1 = type(a)
  49.         local t2 = type(b)
  50.         local v = { }
  51.         if t1 == "number" then
  52.             check(b)
  53.             for i = 1, b.n do
  54.                 v[i] = b[i] * a
  55.             end
  56.         elseif t2 == "number" then
  57.             check(a)
  58.             for i = 1, a.n do
  59.                 v[i] = a[i] * b
  60.             end
  61.         else
  62.             check(a)
  63.             check(b)
  64.             v = a:cross(b)
  65.         end
  66.         return vector(v)
  67.     end;
  68.     div = function(a, b) --Деление на скаляр
  69.         check(a)
  70.         local t = type(b)
  71.         if t ~= "number" then
  72.             error("attempt to perform arithmetic on a "..t.." value", 3)
  73.         end
  74.         local v = { }
  75.         for i = 1, a.n do
  76.             v[i] = a[i] / b
  77.         end
  78.         return vector(v)
  79.     end;
  80.     len = function(self) --Нахождение длинны вектора
  81.         local r = 0
  82.         for i = 1, self.n do
  83.             r = r + pow(self[i], 2)
  84.         end
  85.         return sqrt(r)
  86.     end;
  87.     dot = function(a, b) --Скалярное произведение
  88.         check(a)
  89.         check(b)
  90.         local r = 0
  91.         for i = 1, max(a.n, b.n) do
  92.             r = r + (a[i] or 0) * (b[i] or 0)
  93.         end
  94.         return r
  95.     end;
  96.     cross = function(a, b) --Произведение векторов
  97.         check(a)
  98.         check(b)
  99.         local v = {
  100.             (a[2] or 0) * (b[3] or 0) - (a[3] or 0) * (b[2] or 0);
  101.             (a[3] or 0) * (b[1] or 0) - (a[1] or 0) * (b[3] or 0);
  102.             (a[1] or 0) * (b[2] or 0) - (a[2] or 0) * (b[1] or 0);
  103.         }
  104.         return vector(v)
  105.     end;
  106.     normalize = function(self) --Нормализация вектора
  107.         return self / #self
  108.     end;
  109.     angle = function(a, b) --Нахождение угла вектора
  110.         check(a)
  111.         check(b)
  112.         a, b = a:normalize(), b:normalize()
  113.         return acos(a:dot(b))
  114.     end;
  115.     rotate = function(v, g, a, b) --Поворот вектора
  116.         local r = { }
  117.         local c, s = cos(g), sin(g)
  118.         for i = 1, v.n do
  119.             r[i] = i == a and v[a] * c - v[b] * s or b == i and v[a] * s + v[b] * c or v[i]
  120.         end
  121.         return vector(r)
  122.     end;
  123.     round = function(self, d) --Округление вектора
  124.         local v = { }
  125.         d = type(d) == "number" and d or 0.5
  126.         for i = 1, self.n do
  127.             local a, b = modf(self[i])
  128.             v[i] = b < d and a or a + 1
  129.         end
  130.         return vector(v)
  131.     end;
  132.     eq = function(a, b) --Сравнение
  133.         if not (type(a) == "table" and a.object == "vector") or not (type(a) == "table" and a.object == "vector") then
  134.             return false
  135.         end
  136.         local r = true
  137.         for i = 1, max(a.n, b.n) do
  138.             if a[i] ~= b[i] then
  139.                 r = false
  140.                 break
  141.             end
  142.         end
  143.         return r
  144.     end;
  145.     object = "vector"; --Тип объекта
  146. }
  147.  
  148. local meta = {
  149.     __index = __index;
  150.     __tostring = __index.tostring;
  151.     __add = __index.add;
  152.     __sub = __index.sub;
  153.     __mul = __index.mul;
  154.     __div = __index.div;
  155.     __len = __index.len;
  156.     __eq = __index.eq;
  157.     __newindex = function(self, d, n)
  158.         local a = type(d)
  159.         local b = type(n)
  160.         if not (a == "number" and d == floor(d) and d > 0) then
  161.             error("invalid dimension type (signed integer expected, got "..(a == "number" and d ~= floor(d) and "float" or a)..")", 2)
  162.         end
  163.         if b ~= "number" then
  164.             error("invalid coordinate type (number expected, got "..b..")")
  165.         end
  166.         d = floor(d)
  167.         for i = 1, d-1 do
  168.             if not rawget(self, i) then
  169.                 rawset(self, i, 0)
  170.             end
  171.         end
  172.         rawset(self, d, n)
  173.         rawset(self, "n", d)
  174.     end;
  175. }
  176.  
  177. vector = function(v) -- Устанавливает новый вектор
  178.     v.n = #v
  179.     return setmetatable(v, meta)
  180. end
  181.  
  182. return function( ... ) --Установка вектора для пользователя
  183.     local v = { ... }
  184.     for i=1, #v do
  185.         local t = type(v[i])
  186.         if t ~= "number" then
  187.             error("bad argument #"..i.." (number expected, got "..t..")")
  188.         end
  189.     end
  190.     return vector(v)
  191. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement