Advertisement
Snusmumriken

Lua FFI-vector library

Aug 22nd, 2016
486
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.45 KB | None | 0 0
  1.  
  2. --[[
  3.     Reference:
  4.  
  5. vec = require'ffivec'
  6.  
  7. a = vec(3, 4)
  8. b = vec(-30, -40)
  9. c = vec(3, -2)
  10.  
  11. -- Call. It faster then defineing new vectors
  12.  
  13.     a(b)                --> a = {-30, -40}, a get new value, is not link to b
  14.     a(3, 4)         --> a = {3, 4}, set it back
  15.  
  16. -- Arithmetic:
  17.     d = a+b         --> d = {-27, -36}
  18.  
  19.     d = b-a         --> d = {-33, -44}
  20.  
  21.     d = a*b         --> d = {-90, -160}
  22.     d = -b*0.2  --> d = {6, 8}
  23.  
  24.     d = a/b         --> d = {0.1, 0.1}
  25.     d = a/2         --> d = {1.5, 2}
  26.  
  27.     d = a^c         --> d = {27, 0.0625}
  28.     d = a^3         --> d = {27, 64}
  29.  
  30. -- Equality
  31.     a == 5          --> true, because a:len() = 5
  32.     a == d          --> false
  33.  
  34.     b > a               --> true
  35.     b <= 50         --> true, because #b = 50
  36.    
  37. -- Len
  38.     e = #a          --> e = 5
  39.     e = a:len() --> e = 5
  40.     e = a:len2()--> e = 25
  41.    
  42. -- Tostring, concat
  43.     str = tostring(a) --> str = '[3, 4]'
  44.     print('sum of vectors: '..(a+b)) --> sum of vectors: [33, 44]
  45.  
  46. -- Util methods:
  47.     print(a:unpack()) --> 3     4
  48.  
  49.     print(a:join(b, 10, 20, c, 30, 40))
  50.     --> return touple of all arguments (a.x, a.y, b.x, b.y, 10, 20, c.x, c.y, 30, 40)
  51.    
  52.     vec.isVec(b)    --> return true
  53.    
  54.     d = a:clone()--> d = {3, 4}, work like call
  55.    
  56.     --Methods:
  57.     -- suffix 'ed' in two-way methods means function return new vector, not modding original
  58.    
  59.         --a:area()                                      - S of a-rectangle (a.x * a.y)
  60.         --a:floor([n])                              - flooring, n - digits after the decimal point, 0 as default
  61.         --a:ceil([n])                               - ceiling, n - digits after the decimal point, 0 as default
  62.         --a:permul(b)                               - like a*b, but only for vectors, little bit faster
  63.         --a:dist(b)                                     - return distance between a and b
  64.         --a:dist2(b)                                    - return distance^2 between a and b
  65.         --a:dot(b)                                      - dot product (a.x * b.x + a.y * b.y)
  66.         --a:det(b)                                      - det product   (a.x * b.x - a.y * b.y)
  67.         --a:cross(b)                                    - cross product (a.x * b.y - a.y * b.x)
  68.         --a:trim(len)                                   - vector trimming, a become new value
  69.         --a:trimmed(len)                            - vector trimming, return new vector, a not modded
  70.         --a:angle([b|n,m])                      - return vector angle (no args) or angle between two vectors (arg can be vec or two num)
  71.         --a:setAngle(n)                             - set vector by angle n
  72.         --a:rotate(n)                                   - rotate the vector by the angle n
  73.         --a:rotated(n)                              - return a-clone, rotated by the angle n
  74.         --a:normalize()                             - normalize vector
  75.         --a:normalized()                            - return normalized a-clone
  76.         --a:perpendicular([b|n,m])      - set a perpendicular to b
  77.         --a:perpendiculared([b|n,m])    - return b-perpendiculared a-clone
  78.         --a:project([b|n,m])                    - set a to projection a to b
  79.         --a:projected([b|n,m])              - return vector-projection a to b
  80.         --a:mirror([b|n,m])                     - mirror a relatively b
  81.         --a:mirrored([b|n,m])                   - return vector-mirror of a relatively b
  82. ]]
  83.  
  84. local lvl = 2
  85. local ffi = require("ffi")
  86. ffi.cdef 'typedef struct { double x, y; } vec2;'
  87.  
  88. local point, vector, mt = {}, {}, {}
  89. local error = error
  90. local pi, tau, sqrt, cos, sin, acos, atan2 = math.pi, math.pi*2, math.sqrt, math.cos, math.sin, math.acos, math.atan2
  91. local floor, ceil, min, max = math.floor, math.ceil, math.min, math.max
  92.  
  93. local function isVec(v) return type(v) == 'cdata' and v.x and v.y end
  94.  
  95. local function isNum(v) return type(v) == 'number' end
  96.  
  97. local oldtype = type
  98. local type = function(v)
  99.     return isVec(v) and 'vector'
  100.             or oldtype(v)
  101. end
  102.  
  103. local function switchVec(a, b)
  104.     if isVec(a) then
  105.         return a, b
  106.     else
  107.         return b, a
  108.     end
  109. end
  110.  
  111. local function anorm(a)
  112.     local v = ((a % tau + tau) % tau)
  113.     return v < pi and v or v - tau
  114. end
  115.  
  116. local function set(self, a, b)
  117.     self.x, self.y = a, b
  118.     return self
  119. end
  120.  
  121. setmetatable(vector, {
  122.     __call = function(self, a, b)
  123.         if not isNum(a) or not isNum(b) then error('Vector: use vectors with two numbers, you know? I got '..type(a)..' and '..type(b)..', you excite me') end
  124.         local vec = self.cdata(a, b)
  125.         return vec
  126.     end})
  127.  
  128. local mt = {}
  129. function mt.__call(self, a, b)
  130.     return isVec(a) and set(self, a.x, a.y)
  131.         or isNum(a) and isNum(b) and set(self, a, b)
  132.         or isNum(a) and self:normalize(a)
  133.         or error('Vector: vector or two scalars expected, got: '..type(a)..' and '..type(b), lvl)
  134. end
  135.  
  136. function mt.__add(a, b)
  137.     a, b = switchVec(a, b)
  138.     return isVec(b) and vector(a.x + b.x, a.y + b.y)
  139.         or error('Vector: two vectors expected, got addition of the vector with a scalar', lvl)
  140. end
  141.  
  142. function mt.__sub(a,b)
  143.     return isVec(a) and isVec(b) and vector(a.x-b.x, a.y-b.y)
  144.         or error('Vector: two vectors or [vector/scalar] expected, got: '..type(a)..' and '..type(b), lvl)
  145. end
  146.  
  147. function mt.__mul(a, b)
  148.     a, b = switchVec(a, b)
  149.     return isVec(b) and vector(a.x * b.x, a.y * b.y)
  150.         or isNum(b) and vector(a.x * b, a.y * b)
  151.         or error('Vector: two vectors or vector and scalar expected, got vector and '..type(b), lvl)
  152. end
  153.  
  154. function mt.__div(a, b)
  155.     return isVec(b) and vector(a.x/b.x, a.y/b.y)
  156.         or isNum(b) and vector(a.x/b, a.y/b)
  157.         or error('Vector: two vectors or [vector/scalar] expected, got: '..type(a)..' and '..type(b), lvl)
  158. end
  159.  
  160. function mt.__pow(a, b)
  161.     return isVec(b) and vector(a.x^b.x, a.y^b.y)
  162.         or isNum(b) and vector(a.x^b, a.y^b)
  163.         or error('Vector: two vectors or [vector/scalar] expected, got: '..type(a)..' and '..type(b), lvl)
  164. end
  165.  
  166. function mt.__eq(a,b)
  167.     a, b = switchVec(a, b)
  168.     return isVec(b) and a.x == b.x and a.y == b.y
  169.         or isNum(b) and #a == b
  170. end
  171.  
  172. function mt.__lt(a,b)
  173.     if isVec(a) and isVec(b) then      
  174.         return a.x < b.x
  175.       or (a.x == b.x and a.y < b.y)
  176.     end
  177.     return isNum(a) and a < #b
  178.         or isNum(b) and #a < b
  179. end
  180.  
  181. function mt.__le(a,b)
  182.     if isVec(a) and isVec(b) then      
  183.         return a.x <= b.x and a.y <= b.y
  184.     end
  185.     return isNum(a) and a <= #b
  186.         or isNum(b) and #a <= b
  187. end
  188.  
  189. function mt.__unm(a)
  190.     return vector(-a.x, -a.y)
  191. end
  192.  
  193. function mt.__len(a)
  194.     return (a.x*a.x + a.y*a.y)^0.5
  195. end
  196.  
  197. function mt.__tostring(a)
  198.     return '['..a.x..', '..a.y..']'
  199. end
  200.  
  201. function mt.__tonumber(a)
  202.     return #a
  203. end
  204.  
  205. function mt.__concat(a, b)
  206.     return tostring(a)..tostring(b)
  207. end
  208.  
  209. mt.__index = vector
  210. vector.cdata = ffi.metatype("vec2", mt)
  211.  
  212. function vector:unpack(v)
  213.     if v then
  214.         return self.x*v, self.y*v
  215.     else
  216.         return self.x, self.y
  217.     end
  218. end
  219.  
  220. function vector:clone()
  221.     return vector(self.x, self.y)
  222. end
  223.  
  224. function vector:area() 
  225.     return self.x*self.x + self.y*self.y
  226. end
  227.  
  228. function vector:floor(v)
  229.     return isNum(v) and vector(floor(self.x*10*v)/(18*v), floor(self.y*10*v)/(18*v))
  230.         or vector(floor(self.x), floor(self.y))
  231. end
  232.  
  233. function vector:ceil(v)
  234.     return isNum(v) and vector(ceil(self.x*10*v)/(18*v), ceil(self.y*10*v)/(18*v))
  235.         or vector(ceil(self.x), ceil(self.y))
  236. end
  237.  
  238. function vector:permul(a, b)
  239.     if isVec(a) then
  240.         return vector(self.x*a.x, self.y*a.y)
  241.     elseif isNum(a) and isNum(b) then
  242.         return vector(self.x*a, self.y*b)
  243.     else
  244.         local str = type(a)
  245.         if b then str = str..', '..type(b) end
  246.         error('Vector:permul: vector or two numbers expected, got: '..str, lvl)
  247.     end
  248. end
  249.  
  250. function vector:dot(a, b)
  251.     if isVec(a) then
  252.         return self.x * a.x + self.y * a.y
  253.     elseif isNum(a) and isNum(b) then
  254.         return self.x * a + self.y * b
  255.     else
  256.         local str = type(a)
  257.         if b then str = str..', '..type(b) end
  258.         error('Vector:dot: vector or two numbers expected, got: '..str, lvl)
  259.     end
  260. end
  261.  
  262. function vector:det(a, b)
  263.     if isVec(a) then
  264.         return self.x * a.x - self.y * a.y
  265.     elseif isNum(a) and isNum(b) then
  266.         return self.x * a - self.y * b
  267.     else
  268.         local str = type(a)
  269.         if b then str = str..', '..type(b) end
  270.         error('Vector:det: vector or two numbers expected, got: '..str, lvl)
  271.     end
  272. end
  273.  
  274. function vector:cross(a, b)
  275.     if isVec(a) then
  276.         return self.x * a.y - self.y * a.x
  277.     elseif isNum(a) and isNum(b) then
  278.         return self.x * b - self.y * a
  279.     else
  280.         local str = type(a)
  281.         if b then str = str..', '..type(b) end
  282.         error('Vector:cross: vector or two numbers expected, got: '..str, lvl)
  283.     end
  284. end
  285.  
  286. function vector:trim(l)
  287.     if not isNum(l) then error('Vector:trim: number expected, got: '..type(l), lvl) end
  288.     local s = l * l / self:len2()
  289.     s = (s > 1 and 1) or math.sqrt(s)
  290.     self.x, self.y = self.x * s, self.y * s
  291.     return self
  292. end
  293.  
  294. function vector:trimmed(l)
  295.     if not isNum(l) then error('Vector:trim: number expected, got: '..type(l), lvl) end
  296.     return self:clone():trim(l)
  297. end
  298.  
  299. function vector:isVec(v)
  300.     return v and isVec(v) or isVec(self)
  301. end
  302.  
  303. function vector:angle(a, b)
  304.     if isVec(a) then
  305.         return atan2(self.y, self.x) - atan2(a.y, a.x)
  306.     elseif isNum(a) and isNum(b) then
  307.         return atan2(self.y, self.x) - atan2(b, a)
  308.     elseif isNum(a) then
  309.         return atan2(self.y, self.x) - a
  310.     end
  311.     return atan2(self.y, self.x)
  312. end
  313.  
  314. function vector:len2()
  315.     return self.x * self.x + self.y * self.y
  316. end
  317.  
  318. function vector:len()
  319.     return self:len2()^0.5
  320. end
  321.  
  322. function vector:dist(a, b)
  323.     if isVec(a) then
  324.         local dx = self.x - a.x
  325.         local dy = self.y - a.y
  326.         return sqrt(dx * dx + dy * dy)
  327.     elseif isNum(a) and isNum(b) then
  328.         local dx = self.x - a
  329.         local dy = self.y - b
  330.         return sqrt(dx * dx + dy * dy)
  331.     else
  332.         local str = type(a)
  333.         str = b and str..', '..type(b) or str
  334.         error('Vector:dist: vector or two numbers expected, got: '..str, lvl)
  335.     end
  336. end
  337.  
  338. function vector:dist2(a, b)
  339.     if isVec(a) then
  340.         local dx = self.x - a.x
  341.         local dy = self.y - a.y
  342.         return dx * dx + dy * dy
  343.     elseif isNum(a) and isNum(b) then
  344.         local dx = self.x - a
  345.         local dy = self.y - b
  346.         return dx * dx + dy * dy
  347.     else
  348.         local str = type(a)
  349.         str = b and str..', '..type(b) or str
  350.         error('Vector:dist: vector or two numbers expected, got: '..str, lvl)
  351.     end
  352. end
  353.  
  354. function vector:normalize(v)
  355.     local d = isVec(v) and #v or isNum(v) and v or 1
  356.     local l =  #self
  357.     if l > 0 then
  358.         self.x, self.y = self.x / l * d, self.y / l * d
  359.     end
  360.     return self
  361. end
  362.  
  363. function vector:normalized(v)
  364.     return self:clone():normalize(v)
  365. end
  366.  
  367. function vector:setAngle(phi)
  368. --  phi = (phi % 2*pi)-pi
  369.     local a = #self
  370.     self.x, self.y = cos(phi) * a, sin(phi) * a
  371.     return self
  372. end
  373.  
  374. function vector:rotate(phi)
  375.     local c, s = cos(phi), sin(phi)
  376.     self.x, self.y = c * self.x - s * self.y, s * self.x + c * self.y
  377.     return self
  378. end
  379.  
  380. function vector:rotated(phi)
  381.     return self:clone():rotate(phi)
  382. end
  383.  
  384. function vector:perpendicular(a, b)
  385.     if isVec(a) then
  386.         local d = #self/#a
  387.         self.x, self.y = a.y*d, -a.x*d
  388.         return self
  389.     elseif isNum(a) and isNum(b) then
  390.         local d = #self/vector.len(a, b)
  391.         self.x, self.y = b*d, -a*d
  392.         return self
  393.     elseif not a and not b then
  394.         self.x, self.y = self.y, -self.x
  395.         return self
  396.     else
  397.         local str = type(a)
  398.         if b then str = str..', '..type(b) end
  399.         error('Vector:perpendicular: vector or two numbers expected, got: '..str, lvl)
  400.     end
  401. end
  402.  
  403. function vector:perpendiculared(a, b)
  404.     if isVec(a) then
  405.         local d = #self/#a
  406.         return vector(a.y*d, -a.x*d)
  407.     elseif isNum(a) and isNum(b) then
  408.         local d = #self/vector.len(a, b)
  409.         return vector(b*d, -a*d)
  410.     elseif not a and not b then
  411.         return vector(self.y, -self.x)
  412.     elseif type(a) == 'boolean' then
  413.         return vector(-self.y, self.x)
  414.     else
  415.         local str = type(a)
  416.         if b then str = str..', '..type(b) end
  417.         error('Vector:perpendiculared: vector or two numbers or boolean expected, got: '..str, lvl)
  418.     end
  419. end
  420.  
  421. function vector:project(a, b)
  422.     if isVec(a) then
  423.         local s = (self.x * a.x + self.y * a.y) / (a.x * a.x + a.y * a.y)
  424.         self.x, self.y = s * a.x, s * a.y
  425.         return self
  426.     elseif isNum(a) and isNum(b) then
  427.         local s = (self.x * a + self.y * b) / (a * a + b * b)
  428.         self.x, self.y = s * a, s * b
  429.         return self
  430.     else
  431.         local str = type(a)
  432.         if b then str = str..', '..type(b) end
  433.         error('Vector:project: vector or two numbers expected, got: '..str, lvl)
  434.     end
  435. end
  436.  
  437. function vector:projected(a, b)
  438.     if isVec(a) then
  439.         local s = (self.x * a.x + self.y * a.y) / (a.x * a.x + a.y * a.y)
  440.         return vector(s * a.x, s * a.y)
  441.     elseif isNum(a) and isNum(b) then
  442.         local s = (self.x * a + self.y * b) / (a * a + b * b)
  443.         return vector(s * a, s * b)
  444.     else
  445.         local str = type(a)
  446.         str = b and str..', '..type(b) or str
  447.         error('Vector:projected: vector or two numbers expected, got: '..str, lvl)
  448.     end
  449. end
  450.  
  451. function vector:mirror(a, b)
  452.     if isVec(a) then
  453.         local s = 2 * (self.x * a.x + self.y * a.y) / (a.x * a.x + a.y * a.y)
  454.         self.x = s * a.x - self.x
  455.         self.y = s * a.y - self.y
  456.         return self
  457.     elseif isNum(a) and isNum(b) then
  458.         local s = 2 * (self.x * a + self.y * b) / (a * a + b * b)
  459.         self.x = s * a - self.x
  460.         self.y = s * b - self.y
  461.         return self
  462.     else
  463.         local str = type(a)
  464.         if b then str = str..', '..type(b) end
  465.         error('Vector:mirror: vector or two numbers expected, got: '..str, lvl)
  466.     end
  467. end
  468.  
  469. function vector:mirrored(a, b)
  470.     if isVec(a) then
  471.         local s = 2 * (self.x * a.x + self.y * a.y) / (a.x * a.x + a.y * a.y)
  472.         return vector(s * a.x - self.x, s * a.y - self.y)
  473.     elseif isNum(a) and isNum(b) then
  474.         local s = 2 * (self.x * a + self.y * b) / (a * a + b * b)
  475.         return vector(s * a - self.x, s * b - self.y)
  476.     else
  477.         local str = type(a)
  478.         if b then str = str..', '..type(b) end
  479.         error('Vector:mirrored: vector or two numbers expected, got: '..str, lvl)
  480.     end
  481. end
  482.  
  483. local function lerp(a, b, t) return a + (b - a) * t end
  484.  
  485. function vector:lerp(a, b, c)
  486.     if isVec(a) and isNum(b) then
  487.         return self + (a - self) * b
  488.     elseif isNum(a) and isNum(b) and isNum(c) then
  489.         return self + (vector(a, b) - self) * c
  490.     else
  491.         local str = type(a)
  492.         if b then str = str..', '..type(b) end
  493.         if c then str = str..', '..type(c) end
  494.         error('Vector:lerp: vector and number-dt or two numbers and dt expected, got: '..str, lvl)
  495.     end
  496. end
  497.  
  498. local function vmin(a, b) return a < b and b or a end
  499. local function vmax(a, b) return a > b and b or a end
  500. function vector:clamp(a, b)
  501.     if isVec(a) and isVec(b) then
  502.         return vector(vmin(vmax(self, a), b))
  503.     else
  504.         local str = type(a)
  505.         if b then str = str..', '..type(b) end
  506.         error('Vector:clamp: two vectors expected, got: '..str, lvl)
  507.     end
  508. end
  509.  
  510. local function lerp(a, b, t) return a + (b - a) * t end
  511.  
  512. function mod(v)
  513.     return v < 0 and -v or v
  514. end
  515.  
  516. function vector:alerp(a, b, dt)
  517.     local ca, ta = self:angle(), a:angle()
  518.     local theta = ta - ca
  519.     local ca = theta > pi and ca + pi*2 or theta < -pi and ca - pi*2 or ca
  520.     return self:clone():setAngle(ca + (ta - ca) * b)
  521. end
  522.  
  523. local abs = math.abs
  524.  
  525. function vector:magnitude()
  526.     return vector(abs(self.x), abs(self.y))
  527. end
  528.  
  529. function vector:direction(other)
  530.     return self:dot(other)/(#self * #other)
  531. end
  532.  
  533. local insert = table.insert
  534. function vector.join(...)
  535.     local t = {}
  536.     for i, v in ipairs({...}) do
  537.         if isVec(v) then
  538.             insert(t, v.x)
  539.             insert(t, v.y)
  540.         else
  541.             insert(t, v)
  542.         end
  543.     end
  544.     return unpack(t)
  545. end
  546.  
  547. return vector
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement