summaryrefslogtreecommitdiff
path: root/pos.lua
blob: ba1a404d52d33ce6ccd362232536b0ee5ecc303a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
local class = require'r.class'
local rmath = require'r.math'

local Pos = class()
function Pos.new(cls)
	return setmetatable({},cls)
end
function Pos.init(self,x,y)
	self.x = x
	self.y = y
	return self
end
function Pos.make(cls,...)
	return cls:new():init(...)
end
function Pos.__add(self,other)
	return Pos:make(self.x+other.x,self.y+other.y)
end
function Pos.__sub(self,other)
	return Pos:make(self.x-other.x,self.y-other.y)
end
function Pos.__unm(self) return Pos(-self.x,-self.y)  end
function Pos.__mul(a,b)
	if type(a) == "number" then
		return Pos:make(a*b.x,a*b.y)
	elseif type(b) == "number" then
		return Pos:make(a.x*b,a.y*b)
	else
		error("can only multiply Pos by scalar")
	end

end
function Pos.__div(a,b)
	assert(type(b) == "number","can only divide Pos by scalar")
	return a*(1/b)
end
function Pos.__eq(a,b) return a.x==b.x and a.y==b.y end
function Pos.lensq(self) return self.x^2 + self.y^2 end
function Pos.len(self) return math.sqrt(self:lensq()) end
function Pos.norm(self)
	local l = self:len()
	if l < 0.00001 then return Pos(0,0) else return self/l end end
function Pos.l1(self) return math.abs(self.x) + math.abs(self.y) end
function Pos.linf(self) return math.max(math.abs(self.x),math.abs(self.y)) end
function Pos.dot(self,other) return self.x*other.x+self.y*other.y end
function Pos.vals(self) return self.x, self.y end
function Pos.floor(self) return Pos:make(math.floor(self.x),math.floor(self.y)) end
function Pos.ceil(self) return Pos:make(math.ceil(self.x),math.ceil(self.y)) end
function Pos.round(self) return Pos:make(rmath.round(self.x),rmath.round(self.y)) end
function Pos.divmod(self,size) local div = (self/size):floor() return div, self-div*size end
function Pos.__tostring(self)
	return string.format("(%.2f,%.2f)",self.x,self.y)
end
function Pos.key(self) return self.x .. ':' .. self.y end
function Pos.unkey(cls,k)
	local a,b = k:match"(%-?%d+):(%-?%d+)"
	return Pos(tonumber(a),tonumber(b)) end
function Pos.rot(self,a)
	local c,s = math.cos(a),math.sin(a)
	-- [ C, -S ]
	-- [ S,  C ] 
	return Pos(self.x*c - self.y*s, self.x*s + self.y*c) end
function Pos.sproj(self,b) return self:dot(b:norm()) end
function Pos.proj(self,b) return self:sproj(b)*b:norm() end
function Pos.angle(self) return (math.atan2 or math.atan)(self.y,self.x) end

-- inplace arithmetic
function Pos.addby (self,by) self.x=self.x+by.x  self.y=self.y+by.y end
function Pos.addbyv(self,x,y)self.x=self.x+x     self.y=self.y+y    end
function Pos.subby (self,by) self.x=self.x-by.x  self.y=self.y-by.y end
function Pos.subbyv(self,x,y)self.x=self.x-x     self.y=self.y-y    end
function Pos.mulby (self,by) self.x=self.x*by    self.y=self.y*by   end
function Pos.divby (self,by) self.x=self.x/by    self.y=self.y/by   end

return Pos