2
Copyright (c) 2010-2013 Matthias Richter
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:
11
The above copyright notice and this permission notice shall be included in
12
all copies or substantial portions of the Software.
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.
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
28
local sqrt, cos, sin = math.sqrt, math.cos, math.sin
31
vector.__index = vector
33
local function new(x,y)
34
return setmetatable({x = x or 0, y = y or 0}, vector)
37
local function isvector(v)
38
return getmetatable(v) == vector
41
function vector:clone()
42
return new(self.x, self.y)
45
function vector:unpack()
49
function vector:__tostring()
50
return "("..tonumber(self.x)..","..tonumber(self.y)..")"
53
function vector.__unm(a)
54
return new(-a.x, -a.y)
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)
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)
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)
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
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)
83
function vector.__eq(a,b)
84
return a.x == b.x and a.y == b.y
87
function vector.__lt(a,b)
88
return a.x < b.x or (a.x == b.x and a.y < b.y)
91
function vector.__le(a,b)
92
return a.x <= b.x and a.y <= b.y
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)
100
function vector:len2()
101
return self.x * self.x + self.y * self.y
104
function vector:len()
105
return sqrt(self.x * self.x + self.y * self.y)
108
function vector.dist(a, b)
109
assert(isvector(a) and isvector(b), "dist: wrong argument types (<vector> expected)")
112
return sqrt(dx * dx + dy * dy)
115
function vector:normalize_inplace()
118
self.x, self.y = self.x / l, self.y / l
123
function vector:normalized()
124
return self:clone():normalize_inplace()
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
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)
138
function vector:perpendicular()
139
return new(-self.y, self.x)
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)
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)
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
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
169
function vector:trimmed(maxLen)
170
return self:clone():trim_inplace(maxLen)
175
return setmetatable({new = new, isvector = isvector},
176
{__call = function(_, ...) return new(...) end})