-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvector.lua
More file actions
163 lines (145 loc) · 4.37 KB
/
vector.lua
File metadata and controls
163 lines (145 loc) · 4.37 KB
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
---@type string
local class = require("ccClass")
---@class Vector
---@field x number
---@field y number
---@field z number
---@field new string @Create a new Vector
---@field add string @Add two vectors
---@field sub string @Subtract two vectors
---@field mul string @Multiply by value
---@field div string @Divide by value
---@field unm string @negate the vector
---@field dot string @dot product of two vectors
---@field cross string @cross product of two vectors
---@field length string @magnitude / length of the vector
---@field norm string @normalize the vector
---@field round string @round the vector
---@field toString string @Returns a String of the vector
---@field equals string @check if two vectors are equal
---@type Vector
---@diagnostic disable-next-line: missing-fields
local Vector = {}
---Create a new Vector
---@param x number
---@param y number
---@param z number
---@return Vector
function Vector.new(x, y, z)
assert(type(x) == "number", "x must be a number")
assert(type(y) == "number", "y must be a number")
assert(type(z) == "number", "z must be a number")
local mt = {
__add = Vector.add,
__sub = Vector.sub,
__mul = Vector.mul,
__div = Vector.div,
__unm = Vector.unm,
__tostring = Vector.toString,
__eq = Vector.equals,
__index = Vector
}
local v = setmetatable({}, mt)
v.x = x or 0
v.y = y or 0
v.z = z or 0
return v
end
--- Add two vectors
---@param other Vector
---@return Vector
function Vector:add(other)
return Vector.new(self.x + other.x, self.y + other.y, self.z + other.z)
end
--- Subtract two vectors
---@param other Vector
---@return Vector
function Vector:sub(other)
return Vector.new(self.x - other.x, self.y - other.y, self.z - other.z)
end
--- Multiply by value
---@param value number
---@return Vector
function Vector:mul(value)
return Vector.new(self.x * value, self.y * value, self.z * value)
end
--- Divide by value
---@param value number
---@return Vector
function Vector:div(value)
return Vector.new(self.x / value, self.y / value, self.z / value)
end
--- negate the vector
---@return Vector
function Vector:unm()
return Vector.new(-self.x, -self.y, -self.z)
end
--- dot product of two vectors
---@param other Vector
---@return number
function Vector:dot(other)
return self.x * other.x + self.y * other.y + self.z * other.z
end
--- cross product of two vectors
---@param other Vector
---@return Vector
function Vector:cross(other)
return Vector.new(
self.y * other.z - self.z * other.y,
self.z * other.x - self.x * other.z,
self.x * other.y - self.y * other.x
)
end
--- magnitude / length of the vector
---@return number
function Vector:length()
return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
end
---normalize the vector
---@return Vector
function Vector:norm()
return self:mul(1/self:length())
end
--- round the vector
---@return Vector
---@param tolerance number -- default 1.0. - f.e.: 0.1 will round to the nearest 0.1
---@source https://github.com/cc-tweaked/CC-Tweaked/blob/d77f5f135f9251d027cc900dc27fd80160b632b9/projects/core/src/main/resources/data/computercraft/lua/rom/apis/vector.lua#L168
function Vector:round(tolerance)
tolerance = tolerance or 1.0
return Vector.new(
math.floor((self.x + tolerance * 0.5) / tolerance) * tolerance,
math.floor((self.y + tolerance * 0.5) / tolerance) * tolerance,
math.floor((self.z + tolerance * 0.5) / tolerance) * tolerance
)
end
--- Returns a String of the vector
---@return string
function Vector:toString()
return self.x .. "," .. self.y .. "," .. self.z
end
--- check if two vectors are equal
---@param other any
---@return boolean
function Vector:equals(other)
return self.x == other.x and self.y == other.y and self.z == other.z
end
---Rotate the vector by a given angle (90, 180, 270 degrees) around the Z-axis
---@param angle number @The angle to rotate (90, 180, or 270)
---@return Vector
function Vector:rotate(angle)
local newX, newZ
if angle == 90 then
newX = -self.z
newZ = self.x
elseif angle == 180 then
newX = -self.x
newZ = -self.z
elseif angle == 270 then
newX = self.z
newZ = -self.x
else
error("Invalid angle. Only 90, 180, and 270 degrees are supported.")
end
return Vector.new(newX,self.y, newZ)
end
return Vector