bzr branch
http://9ix.org/bzr/traderous
13
by Josh C
constant velocity for bullets. using hump.vector e9b86ef |
1 |
--[[ |
2 |
Copyright (c) 2010-2013 Matthias Richter |
|
3 |
||
4 |
Permission is hereby granted, free of charge, to any person obtaining a copy |
|
5 |
of this software and associated documentation files (the "Software"), to deal |
|
6 |
in the Software without restriction, including without limitation the rights |
|
7 |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
8 |
copies of the Software, and to permit persons to whom the Software is |
|
9 |
furnished to do so, subject to the following conditions: |
|
10 |
||
11 |
The above copyright notice and this permission notice shall be included in |
|
12 |
all copies or substantial portions of the Software. |
|
13 |
||
14 |
Except as contained in this notice, the name(s) of the above copyright holders |
|
15 |
shall not be used in advertising or otherwise to promote the sale, use or |
|
16 |
other dealings in this Software without prior written authorization. |
|
17 |
||
18 |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
19 |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
20 |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
21 |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
22 |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
23 |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
24 |
THE SOFTWARE. |
|
25 |
]]-- |
|
26 |
||
27 |
local assert = assert |
|
28 |
local sqrt, cos, sin = math.sqrt, math.cos, math.sin |
|
29 |
||
30 |
local vector = {} |
|
31 |
vector.__index = vector |
|
32 |
||
33 |
local function new(x,y) |
|
34 |
return setmetatable({x = x or 0, y = y or 0}, vector) |
|
35 |
end |
|
36 |
||
37 |
local function isvector(v) |
|
38 |
return getmetatable(v) == vector |
|
39 |
end |
|
40 |
||
41 |
function vector:clone() |
|
42 |
return new(self.x, self.y) |
|
43 |
end |
|
44 |
||
45 |
function vector:unpack() |
|
46 |
return self.x, self.y |
|
47 |
end |
|
48 |
||
49 |
function vector:__tostring() |
|
50 |
return "("..tonumber(self.x)..","..tonumber(self.y)..")" |
|
51 |
end |
|
52 |
||
53 |
function vector.__unm(a) |
|
54 |
return new(-a.x, -a.y) |
|
55 |
end |
|
56 |
||
57 |
function vector.__add(a,b) |
|
58 |
assert(isvector(a) and isvector(b), "Add: wrong argument types (<vector> expected)") |
|
59 |
return new(a.x+b.x, a.y+b.y) |
|
60 |
end |
|
61 |
||
62 |
function vector.__sub(a,b) |
|
63 |
assert(isvector(a) and isvector(b), "Sub: wrong argument types (<vector> expected)") |
|
64 |
return new(a.x-b.x, a.y-b.y) |
|
65 |
end |
|
66 |
||
67 |
function vector.__mul(a,b) |
|
68 |
if type(a) == "number" then |
|
69 |
return new(a*b.x, a*b.y) |
|
70 |
elseif type(b) == "number" then |
|
71 |
return new(b*a.x, b*a.y) |
|
72 |
else |
|
73 |
assert(isvector(a) and isvector(b), "Mul: wrong argument types (<vector> or <number> expected)") |
|
74 |
return a.x*b.x + a.y*b.y |
|
75 |
end |
|
76 |
end |
|
77 |
||
78 |
function vector.__div(a,b) |
|
79 |
assert(isvector(a) and type(b) == "number", "wrong argument types (expected <vector> / <number>)") |
|
80 |
return new(a.x / b, a.y / b) |
|
81 |
end |
|
82 |
||
83 |
function vector.__eq(a,b) |
|
84 |
return a.x == b.x and a.y == b.y |
|
85 |
end |
|
86 |
||
87 |
function vector.__lt(a,b) |
|
88 |
return a.x < b.x or (a.x == b.x and a.y < b.y) |
|
89 |
end |
|
90 |
||
91 |
function vector.__le(a,b) |
|
92 |
return a.x <= b.x and a.y <= b.y |
|
93 |
end |
|
94 |
||
95 |
function vector.permul(a,b) |
|
96 |
assert(isvector(a) and isvector(b), "permul: wrong argument types (<vector> expected)") |
|
97 |
return new(a.x*b.x, a.y*b.y) |
|
98 |
end |
|
99 |
||
100 |
function vector:len2() |
|
101 |
return self.x * self.x + self.y * self.y |
|
102 |
end |
|
103 |
||
104 |
function vector:len() |
|
105 |
return sqrt(self.x * self.x + self.y * self.y) |
|
106 |
end |
|
107 |
||
108 |
function vector.dist(a, b) |
|
109 |
assert(isvector(a) and isvector(b), "dist: wrong argument types (<vector> expected)") |
|
110 |
local dx = a.x - b.x |
|
111 |
local dy = a.y - b.y |
|
112 |
return sqrt(dx * dx + dy * dy) |
|
113 |
end |
|
114 |
||
115 |
function vector:normalize_inplace() |
|
116 |
local l = self:len() |
|
117 |
if l > 0 then |
|
118 |
self.x, self.y = self.x / l, self.y / l |
|
119 |
end |
|
120 |
return self |
|
121 |
end |
|
122 |
||
123 |
function vector:normalized() |
|
124 |
return self:clone():normalize_inplace() |
|
125 |
end |
|
126 |
||
127 |
function vector:rotate_inplace(phi) |
|
128 |
local c, s = cos(phi), sin(phi) |
|
129 |
self.x, self.y = c * self.x - s * self.y, s * self.x + c * self.y |
|
130 |
return self |
|
131 |
end |
|
132 |
||
133 |
function vector:rotated(phi) |
|
134 |
local c, s = cos(phi), sin(phi) |
|
135 |
return new(c * self.x - s * self.y, s * self.x + c * self.y) |
|
136 |
end |
|
137 |
||
138 |
function vector:perpendicular() |
|
139 |
return new(-self.y, self.x) |
|
140 |
end |
|
141 |
||
142 |
function vector:projectOn(v) |
|
143 |
assert(isvector(v), "invalid argument: cannot project vector on " .. type(v)) |
|
144 |
-- (self * v) * v / v:len2() |
|
145 |
local s = (self.x * v.x + self.y * v.y) / (v.x * v.x + v.y * v.y) |
|
146 |
return new(s * v.x, s * v.y) |
|
147 |
end |
|
148 |
||
149 |
function vector:mirrorOn(v) |
|
150 |
assert(isvector(v), "invalid argument: cannot mirror vector on " .. type(v)) |
|
151 |
-- 2 * self:projectOn(v) - self |
|
152 |
local s = 2 * (self.x * v.x + self.y * v.y) / (v.x * v.x + v.y * v.y) |
|
153 |
return new(s * v.x - self.x, s * v.y - self.y) |
|
154 |
end |
|
155 |
||
156 |
function vector:cross(v) |
|
157 |
assert(isvector(v), "cross: wrong argument types (<vector> expected)") |
|
158 |
return self.x * v.y - self.y * v.x |
|
159 |
end |
|
160 |
||
161 |
-- ref.: http://blog.signalsondisplay.com/?p=336 |
|
162 |
function vector:trim_inplace(maxLen) |
|
163 |
local s = maxLen * maxLen / self:len2() |
|
164 |
s = s < 1 and 1 or math.sqrt(s) |
|
165 |
self.x, self.y = self.x * s, self.y * s |
|
166 |
return self |
|
167 |
end |
|
168 |
||
169 |
function vector:trimmed(maxLen) |
|
170 |
return self:clone():trim_inplace(maxLen) |
|
171 |
end |
|
172 |
||
173 |
||
174 |
-- the module |
|
175 |
return setmetatable({new = new, isvector = isvector}, |
|
176 |
{__call = function(_, ...) return new(...) end}) |