vector_spec.lua 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. _G.vector = {}
  2. dofile("builtin/common/math.lua")
  3. dofile("builtin/common/vector.lua")
  4. describe("vector", function()
  5. describe("new()", function()
  6. it("constructs", function()
  7. assert.same({x = 0, y = 0, z = 0}, vector.new())
  8. assert.same({x = 1, y = 2, z = 3}, vector.new(1, 2, 3))
  9. assert.same({x = 3, y = 2, z = 1}, vector.new({x = 3, y = 2, z = 1}))
  10. assert.is_true(vector.check(vector.new()))
  11. assert.is_true(vector.check(vector.new(1, 2, 3)))
  12. assert.is_true(vector.check(vector.new({x = 3, y = 2, z = 1})))
  13. local input = vector.new({ x = 3, y = 2, z = 1 })
  14. local output = vector.new(input)
  15. assert.same(input, output)
  16. assert.equal(input, output)
  17. assert.is_false(rawequal(input, output))
  18. assert.equal(input, input:new())
  19. end)
  20. it("throws on invalid input", function()
  21. assert.has.errors(function()
  22. vector.new({ x = 3 })
  23. end)
  24. assert.has.errors(function()
  25. vector.new({ d = 3 })
  26. end)
  27. end)
  28. end)
  29. it("zero()", function()
  30. assert.same({x = 0, y = 0, z = 0}, vector.zero())
  31. assert.same(vector.new(), vector.zero())
  32. assert.equal(vector.new(), vector.zero())
  33. assert.is_true(vector.check(vector.zero()))
  34. end)
  35. it("copy()", function()
  36. local v = vector.new(1, 2, 3)
  37. assert.same(v, vector.copy(v))
  38. assert.same(vector.new(v), vector.copy(v))
  39. assert.equal(vector.new(v), vector.copy(v))
  40. assert.is_true(vector.check(vector.copy(v)))
  41. end)
  42. it("indexes", function()
  43. local some_vector = vector.new(24, 42, 13)
  44. assert.equal(24, some_vector[1])
  45. assert.equal(24, some_vector.x)
  46. assert.equal(42, some_vector[2])
  47. assert.equal(42, some_vector.y)
  48. assert.equal(13, some_vector[3])
  49. assert.equal(13, some_vector.z)
  50. some_vector[1] = 100
  51. assert.equal(100, some_vector.x)
  52. some_vector.x = 101
  53. assert.equal(101, some_vector[1])
  54. some_vector[2] = 100
  55. assert.equal(100, some_vector.y)
  56. some_vector.y = 102
  57. assert.equal(102, some_vector[2])
  58. some_vector[3] = 100
  59. assert.equal(100, some_vector.z)
  60. some_vector.z = 103
  61. assert.equal(103, some_vector[3])
  62. end)
  63. it("direction()", function()
  64. local a = vector.new(1, 0, 0)
  65. local b = vector.new(1, 42, 0)
  66. assert.equal(vector.new(0, 1, 0), vector.direction(a, b))
  67. assert.equal(vector.new(0, 1, 0), a:direction(b))
  68. end)
  69. it("distance()", function()
  70. local a = vector.new(1, 0, 0)
  71. local b = vector.new(3, 42, 9)
  72. assert.is_true(math.abs(43 - vector.distance(a, b)) < 1.0e-12)
  73. assert.is_true(math.abs(43 - a:distance(b)) < 1.0e-12)
  74. assert.equal(0, vector.distance(a, a))
  75. assert.equal(0, b:distance(b))
  76. end)
  77. it("length()", function()
  78. local a = vector.new(0, 0, -23)
  79. assert.equal(0, vector.length(vector.new()))
  80. assert.equal(23, vector.length(a))
  81. assert.equal(23, a:length())
  82. end)
  83. it("normalize()", function()
  84. local a = vector.new(0, 0, -23)
  85. assert.equal(vector.new(0, 0, -1), vector.normalize(a))
  86. assert.equal(vector.new(0, 0, -1), a:normalize())
  87. assert.equal(vector.new(), vector.normalize(vector.new()))
  88. end)
  89. it("floor()", function()
  90. local a = vector.new(0.1, 0.9, -0.5)
  91. assert.equal(vector.new(0, 0, -1), vector.floor(a))
  92. assert.equal(vector.new(0, 0, -1), a:floor())
  93. end)
  94. it("round()", function()
  95. local a = vector.new(0.1, 0.9, -0.5)
  96. assert.equal(vector.new(0, 1, -1), vector.round(a))
  97. assert.equal(vector.new(0, 1, -1), a:round())
  98. end)
  99. it("ceil()", function()
  100. local a = vector.new(0.1, 0.9, -0.5)
  101. assert.equal(vector.new(1, 1, 0), vector.ceil(a))
  102. assert.equal(vector.new(1, 1, 0), a:ceil())
  103. end)
  104. it("sign()", function()
  105. local a = vector.new(-120.3, 0, 231.5)
  106. assert.equal(vector.new(-1, 0, 1), vector.sign(a))
  107. assert.equal(vector.new(-1, 0, 1), a:sign())
  108. assert.equal(vector.new(0, 0, 1), vector.sign(a, 200))
  109. assert.equal(vector.new(0, 0, 1), a:sign(200))
  110. end)
  111. it("abs()", function()
  112. local a = vector.new(-123.456, 0, 13)
  113. assert.equal(vector.new(123.456, 0, 13), vector.abs(a))
  114. assert.equal(vector.new(123.456, 0, 13), a:abs())
  115. end)
  116. it("apply()", function()
  117. local i = 0
  118. local f = function(x)
  119. i = i + 1
  120. return x + i
  121. end
  122. local f2 = function(x, opt1, opt2, opt3)
  123. return x + opt1 + opt2 + opt3
  124. end
  125. local a = vector.new(0.1, 0.9, -0.5)
  126. assert.equal(vector.new(1, 1, 0), vector.apply(a, math.ceil))
  127. assert.equal(vector.new(1, 1, 0), a:apply(math.ceil))
  128. assert.equal(vector.new(0.1, 0.9, 0.5), vector.apply(a, math.abs))
  129. assert.equal(vector.new(0.1, 0.9, 0.5), a:apply(math.abs))
  130. assert.equal(vector.new(1.1, 2.9, 2.5), vector.apply(a, f))
  131. assert.equal(vector.new(4.1, 5.9, 5.5), a:apply(f))
  132. local b = vector.new(1, 2, 3)
  133. assert.equal(vector.new(4, 5, 6), vector.apply(b, f2, 1, 1, 1))
  134. assert.equal(vector.new(4, 5, 6), b:apply(f2, 1, 1, 1))
  135. end)
  136. it("combine()", function()
  137. local a = vector.new(1, 2, 3)
  138. local b = vector.new(3, 2, 1)
  139. assert.equal(vector.add(a, b), vector.combine(a, b, function(x, y) return x + y end))
  140. assert.equal(vector.new(3, 2, 3), vector.combine(a, b, math.max))
  141. assert.equal(vector.new(1, 2, 1), vector.combine(a, b, math.min))
  142. end)
  143. it("equals()", function()
  144. local function assertE(a, b)
  145. assert.is_true(vector.equals(a, b))
  146. end
  147. local function assertNE(a, b)
  148. assert.is_false(vector.equals(a, b))
  149. end
  150. assertE({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
  151. assertE({x = -1, y = 0, z = 1}, {x = -1, y = 0, z = 1})
  152. assertE({x = -1, y = 0, z = 1}, vector.new(-1, 0, 1))
  153. local a = {x = 2, y = 4, z = -10}
  154. assertE(a, a)
  155. assertNE({x = -1, y = 0, z = 1}, a)
  156. assert.equal(vector.new(1, 2, 3), vector.new(1, 2, 3))
  157. assert.is_true(vector.new(1, 2, 3):equals(vector.new(1, 2, 3)))
  158. assert.not_equal(vector.new(1, 2, 3), vector.new(1, 2, 4))
  159. assert.is_true(vector.new(1, 2, 3) == vector.new(1, 2, 3))
  160. assert.is_false(vector.new(1, 2, 3) == vector.new(1, 3, 3))
  161. end)
  162. it("metatable is same", function()
  163. local a = vector.new()
  164. local b = vector.new(1, 2, 3)
  165. assert.equal(true, vector.check(a))
  166. assert.equal(true, vector.check(b))
  167. assert.equal(vector.metatable, getmetatable(a))
  168. assert.equal(vector.metatable, getmetatable(b))
  169. assert.equal(vector.metatable, a.metatable)
  170. end)
  171. it("sort()", function()
  172. local a = vector.new(1, 2, 3)
  173. local b = vector.new(0.5, 232, -2)
  174. local sorted = {vector.new(0.5, 2, -2), vector.new(1, 232, 3)}
  175. assert.same(sorted, {vector.sort(a, b)})
  176. assert.same(sorted, {a:sort(b)})
  177. end)
  178. it("angle()", function()
  179. assert.equal(math.pi, vector.angle(vector.new(-1, -2, -3), vector.new(1, 2, 3)))
  180. assert.equal(math.pi/2, vector.new(0, 1, 0):angle(vector.new(1, 0, 0)))
  181. end)
  182. it("dot()", function()
  183. assert.equal(-14, vector.dot(vector.new(-1, -2, -3), vector.new(1, 2, 3)))
  184. assert.equal(0, vector.new():dot(vector.new(1, 2, 3)))
  185. end)
  186. it("cross()", function()
  187. local a = vector.new(-1, -2, 0)
  188. local b = vector.new(1, 2, 3)
  189. assert.equal(vector.new(-6, 3, 0), vector.cross(a, b))
  190. assert.equal(vector.new(-6, 3, 0), a:cross(b))
  191. end)
  192. it("offset()", function()
  193. assert.same({x = 41, y = 52, z = 63}, vector.offset(vector.new(1, 2, 3), 40, 50, 60))
  194. assert.equal(vector.new(41, 52, 63), vector.offset(vector.new(1, 2, 3), 40, 50, 60))
  195. assert.equal(vector.new(41, 52, 63), vector.new(1, 2, 3):offset(40, 50, 60))
  196. end)
  197. it("is()", function()
  198. local some_table1 = {foo = 13, [42] = 1, "bar", 2}
  199. local some_table2 = {1, 2, 3}
  200. local some_table3 = {x = 1, 2, 3}
  201. local some_table4 = {1, 2, z = 3}
  202. local old = {x = 1, y = 2, z = 3}
  203. local real = vector.new(1, 2, 3)
  204. assert.is_false(vector.check(nil))
  205. assert.is_false(vector.check(1))
  206. assert.is_false(vector.check(true))
  207. assert.is_false(vector.check("foo"))
  208. assert.is_false(vector.check(some_table1))
  209. assert.is_false(vector.check(some_table2))
  210. assert.is_false(vector.check(some_table3))
  211. assert.is_false(vector.check(some_table4))
  212. assert.is_false(vector.check(old))
  213. assert.is_true(vector.check(real))
  214. assert.is_true(real:check())
  215. end)
  216. it("global pairs", function()
  217. local out = {}
  218. local vec = vector.new(10, 20, 30)
  219. for k, v in pairs(vec) do
  220. out[k] = v
  221. end
  222. assert.same({x = 10, y = 20, z = 30}, out)
  223. end)
  224. it("abusing works", function()
  225. local v = vector.new(1, 2, 3)
  226. v.a = 1
  227. assert.equal(1, v.a)
  228. local a_is_there = false
  229. for key, value in pairs(v) do
  230. if key == "a" then
  231. a_is_there = true
  232. assert.equal(value, 1)
  233. break
  234. end
  235. end
  236. assert.is_true(a_is_there)
  237. end)
  238. it("add()", function()
  239. local a = vector.new(1, 2, 3)
  240. local b = vector.new(1, 4, 3)
  241. local c = vector.new(2, 6, 6)
  242. assert.equal(c, vector.add(a, {x = 1, y = 4, z = 3}))
  243. assert.equal(c, vector.add(a, b))
  244. assert.equal(c, a:add(b))
  245. assert.equal(c, a + b)
  246. assert.equal(c, b + a)
  247. end)
  248. it("subtract()", function()
  249. local a = vector.new(1, 2, 3)
  250. local b = vector.new(2, 4, 3)
  251. local c = vector.new(-1, -2, 0)
  252. assert.equal(c, vector.subtract(a, {x = 2, y = 4, z = 3}))
  253. assert.equal(c, vector.subtract(a, b))
  254. assert.equal(c, a:subtract(b))
  255. assert.equal(c, a - b)
  256. assert.equal(c, -b + a)
  257. end)
  258. it("multiply()", function()
  259. local a = vector.new(1, 2, 3)
  260. local b = vector.new(2, 4, 3)
  261. local c = vector.new(2, 8, 9)
  262. local s = 2
  263. local d = vector.new(2, 4, 6)
  264. assert.equal(c, vector.multiply(a, {x = 2, y = 4, z = 3}))
  265. assert.equal(c, vector.multiply(a, b))
  266. assert.equal(d, vector.multiply(a, s))
  267. assert.equal(d, a:multiply(s))
  268. assert.equal(d, a * s)
  269. assert.equal(d, s * a)
  270. assert.equal(-a, -1 * a)
  271. end)
  272. it("divide()", function()
  273. local a = vector.new(1, 2, 3)
  274. local b = vector.new(2, 4, 3)
  275. local c = vector.new(0.5, 0.5, 1)
  276. local s = 2
  277. local d = vector.new(0.5, 1, 1.5)
  278. assert.equal(c, vector.divide(a, {x = 2, y = 4, z = 3}))
  279. assert.equal(c, vector.divide(a, b))
  280. assert.equal(d, vector.divide(a, s))
  281. assert.equal(d, a:divide(s))
  282. assert.equal(d, a / s)
  283. assert.equal(d, 1/s * a)
  284. assert.equal(-a, a / -1)
  285. end)
  286. it("to_string()", function()
  287. local v = vector.new(1, 2, 3.14)
  288. assert.same("(1, 2, 3.14)", vector.to_string(v))
  289. assert.same("(1, 2, 3.14)", v:to_string())
  290. assert.same("(1, 2, 3.14)", tostring(v))
  291. end)
  292. it("from_string()", function()
  293. local v = vector.new(1, 2, 3.14)
  294. assert.is_true(vector.check(vector.from_string("(1, 2, 3.14)")))
  295. assert.same({v, 13}, {vector.from_string("(1, 2, 3.14)")})
  296. assert.same({v, 12}, {vector.from_string("(1,2 ,3.14)")})
  297. assert.same({v, 12}, {vector.from_string("(1,2,3.14,)")})
  298. assert.same({v, 11}, {vector.from_string("(1 2 3.14)")})
  299. assert.same({v, 15}, {vector.from_string("( 1, 2, 3.14 )")})
  300. assert.same({v, 15}, {vector.from_string(" ( 1, 2, 3.14) ")})
  301. assert.same({vector.new(), 8}, {vector.from_string("(0,0,0) ( 1, 2, 3.14) ")})
  302. assert.same({v, 22}, {vector.from_string("(0,0,0) ( 1, 2, 3.14) ", 8)})
  303. assert.same({v, 22}, {vector.from_string("(0,0,0) ( 1, 2, 3.14) ", 9)})
  304. assert.same(nil, vector.from_string("nothing"))
  305. end)
  306. -- This function is needed because of floating point imprecision.
  307. local function almost_equal(a, b)
  308. if type(a) == "number" then
  309. return math.abs(a - b) < 0.00000000001
  310. end
  311. return vector.distance(a, b) < 0.000000000001
  312. end
  313. describe("rotate_around_axis()", function()
  314. it("rotates", function()
  315. assert.True(almost_equal({x = -1, y = 0, z = 0},
  316. vector.rotate_around_axis({x = 1, y = 0, z = 0}, {x = 0, y = 1, z = 0}, math.pi)))
  317. assert.True(almost_equal({x = 0, y = 1, z = 0},
  318. vector.rotate_around_axis({x = 0, y = 0, z = 1}, {x = 1, y = 0, z = 0}, math.pi / 2)))
  319. assert.True(almost_equal({x = 4, y = 1, z = 1},
  320. vector.rotate_around_axis({x = 4, y = 1, z = 1}, {x = 4, y = 1, z = 1}, math.pi / 6)))
  321. end)
  322. it("keeps distance to axis", function()
  323. local rotate1 = {x = 1, y = 3, z = 1}
  324. local axis1 = {x = 1, y = 3, z = 2}
  325. local rotated1 = vector.rotate_around_axis(rotate1, axis1, math.pi / 13)
  326. assert.True(almost_equal(vector.distance(axis1, rotate1), vector.distance(axis1, rotated1)))
  327. local rotate2 = {x = 1, y = 1, z = 3}
  328. local axis2 = {x = 2, y = 6, z = 100}
  329. local rotated2 = vector.rotate_around_axis(rotate2, axis2, math.pi / 23)
  330. assert.True(almost_equal(vector.distance(axis2, rotate2), vector.distance(axis2, rotated2)))
  331. local rotate3 = {x = 1, y = -1, z = 3}
  332. local axis3 = {x = 2, y = 6, z = 100}
  333. local rotated3 = vector.rotate_around_axis(rotate3, axis3, math.pi / 2)
  334. assert.True(almost_equal(vector.distance(axis3, rotate3), vector.distance(axis3, rotated3)))
  335. end)
  336. it("rotates back", function()
  337. local rotate1 = {x = 1, y = 3, z = 1}
  338. local axis1 = {x = 1, y = 3, z = 2}
  339. local rotated1 = vector.rotate_around_axis(rotate1, axis1, math.pi / 13)
  340. rotated1 = vector.rotate_around_axis(rotated1, axis1, -math.pi / 13)
  341. assert.True(almost_equal(rotate1, rotated1))
  342. local rotate2 = {x = 1, y = 1, z = 3}
  343. local axis2 = {x = 2, y = 6, z = 100}
  344. local rotated2 = vector.rotate_around_axis(rotate2, axis2, math.pi / 23)
  345. rotated2 = vector.rotate_around_axis(rotated2, axis2, -math.pi / 23)
  346. assert.True(almost_equal(rotate2, rotated2))
  347. local rotate3 = {x = 1, y = -1, z = 3}
  348. local axis3 = {x = 2, y = 6, z = 100}
  349. local rotated3 = vector.rotate_around_axis(rotate3, axis3, math.pi / 2)
  350. rotated3 = vector.rotate_around_axis(rotated3, axis3, -math.pi / 2)
  351. assert.True(almost_equal(rotate3, rotated3))
  352. end)
  353. it("is right handed", function()
  354. local v_before1 = {x = 0, y = 1, z = -1}
  355. local v_after1 = vector.rotate_around_axis(v_before1, {x = 1, y = 0, z = 0}, math.pi / 4)
  356. assert.True(almost_equal(vector.normalize(vector.cross(v_after1, v_before1)), {x = 1, y = 0, z = 0}))
  357. local v_before2 = {x = 0, y = 3, z = 4}
  358. local v_after2 = vector.rotate_around_axis(v_before2, {x = 1, y = 0, z = 0}, 2 * math.pi / 5)
  359. assert.True(almost_equal(vector.normalize(vector.cross(v_after2, v_before2)), {x = 1, y = 0, z = 0}))
  360. local v_before3 = {x = 1, y = 0, z = -1}
  361. local v_after3 = vector.rotate_around_axis(v_before3, {x = 0, y = 1, z = 0}, math.pi / 4)
  362. assert.True(almost_equal(vector.normalize(vector.cross(v_after3, v_before3)), {x = 0, y = 1, z = 0}))
  363. local v_before4 = {x = 3, y = 0, z = 4}
  364. local v_after4 = vector.rotate_around_axis(v_before4, {x = 0, y = 1, z = 0}, 2 * math.pi / 5)
  365. assert.True(almost_equal(vector.normalize(vector.cross(v_after4, v_before4)), {x = 0, y = 1, z = 0}))
  366. local v_before5 = {x = 1, y = -1, z = 0}
  367. local v_after5 = vector.rotate_around_axis(v_before5, {x = 0, y = 0, z = 1}, math.pi / 4)
  368. assert.True(almost_equal(vector.normalize(vector.cross(v_after5, v_before5)), {x = 0, y = 0, z = 1}))
  369. local v_before6 = {x = 3, y = 4, z = 0}
  370. local v_after6 = vector.rotate_around_axis(v_before6, {x = 0, y = 0, z = 1}, 2 * math.pi / 5)
  371. assert.True(almost_equal(vector.normalize(vector.cross(v_after6, v_before6)), {x = 0, y = 0, z = 1}))
  372. end)
  373. end)
  374. describe("rotate()", function()
  375. it("rotates", function()
  376. assert.True(almost_equal({x = -1, y = 0, z = 0},
  377. vector.rotate({x = 1, y = 0, z = 0}, {x = 0, y = math.pi, z = 0})))
  378. assert.True(almost_equal({x = 0, y = -1, z = 0},
  379. vector.rotate({x = 1, y = 0, z = 0}, {x = 0, y = 0, z = math.pi / 2})))
  380. assert.True(almost_equal({x = 1, y = 0, z = 0},
  381. vector.rotate({x = 1, y = 0, z = 0}, {x = math.pi / 123, y = 0, z = 0})))
  382. end)
  383. it("is counterclockwise", function()
  384. local v_before1 = {x = 0, y = 1, z = -1}
  385. local v_after1 = vector.rotate(v_before1, {x = math.pi / 4, y = 0, z = 0})
  386. assert.True(almost_equal(vector.normalize(vector.cross(v_after1, v_before1)), {x = 1, y = 0, z = 0}))
  387. local v_before2 = {x = 0, y = 3, z = 4}
  388. local v_after2 = vector.rotate(v_before2, {x = 2 * math.pi / 5, y = 0, z = 0})
  389. assert.True(almost_equal(vector.normalize(vector.cross(v_after2, v_before2)), {x = 1, y = 0, z = 0}))
  390. local v_before3 = {x = 1, y = 0, z = -1}
  391. local v_after3 = vector.rotate(v_before3, {x = 0, y = math.pi / 4, z = 0})
  392. assert.True(almost_equal(vector.normalize(vector.cross(v_after3, v_before3)), {x = 0, y = 1, z = 0}))
  393. local v_before4 = {x = 3, y = 0, z = 4}
  394. local v_after4 = vector.rotate(v_before4, {x = 0, y = 2 * math.pi / 5, z = 0})
  395. assert.True(almost_equal(vector.normalize(vector.cross(v_after4, v_before4)), {x = 0, y = 1, z = 0}))
  396. local v_before5 = {x = 1, y = -1, z = 0}
  397. local v_after5 = vector.rotate(v_before5, {x = 0, y = 0, z = math.pi / 4})
  398. assert.True(almost_equal(vector.normalize(vector.cross(v_after5, v_before5)), {x = 0, y = 0, z = 1}))
  399. local v_before6 = {x = 3, y = 4, z = 0}
  400. local v_after6 = vector.rotate(v_before6, {x = 0, y = 0, z = 2 * math.pi / 5})
  401. assert.True(almost_equal(vector.normalize(vector.cross(v_after6, v_before6)), {x = 0, y = 0, z = 1}))
  402. end)
  403. end)
  404. it("dir_to_rotation()", function()
  405. -- Comparing rotations (pitch, yaw, roll) is hard because of certain ambiguities,
  406. -- e.g. (pi, 0, pi) looks exactly the same as (0, pi, 0)
  407. -- So instead we convert the rotation back to vectors and compare these.
  408. local function forward_at_rot(rot)
  409. return vector.rotate(vector.new(0, 0, 1), rot)
  410. end
  411. local function up_at_rot(rot)
  412. return vector.rotate(vector.new(0, 1, 0), rot)
  413. end
  414. local rot1 = vector.dir_to_rotation({x = 1, y = 0, z = 0}, {x = 0, y = 1, z = 0})
  415. assert.True(almost_equal({x = 1, y = 0, z = 0}, forward_at_rot(rot1)))
  416. assert.True(almost_equal({x = 0, y = 1, z = 0}, up_at_rot(rot1)))
  417. local rot2 = vector.dir_to_rotation({x = 1, y = 1, z = 0}, {x = 0, y = 0, z = 1})
  418. assert.True(almost_equal({x = 1/math.sqrt(2), y = 1/math.sqrt(2), z = 0}, forward_at_rot(rot2)))
  419. assert.True(almost_equal({x = 0, y = 0, z = 1}, up_at_rot(rot2)))
  420. for i = 1, 1000 do
  421. local rand_vec = vector.new(math.random(), math.random(), math.random())
  422. if vector.length(rand_vec) ~= 0 then
  423. local rot_1 = vector.dir_to_rotation(rand_vec)
  424. local rot_2 = {
  425. x = math.atan2(rand_vec.y, math.sqrt(rand_vec.z * rand_vec.z + rand_vec.x * rand_vec.x)),
  426. y = -math.atan2(rand_vec.x, rand_vec.z),
  427. z = 0
  428. }
  429. assert.True(almost_equal(rot_1, rot_2))
  430. end
  431. end
  432. end)
  433. it("in_area()", function()
  434. assert.True(vector.in_area(vector.zero(), vector.new(-10, -10, -10), vector.new(10, 10, 10)))
  435. assert.True(vector.in_area(vector.new(-2, 5, -8), vector.new(-10, -10, -10), vector.new(10, 10, 10)))
  436. assert.True(vector.in_area(vector.new(-10, -10, -10), vector.new(-10, -10, -10), vector.new(10, 10, 10)))
  437. assert.False(vector.in_area(vector.new(-10, -10, -10), vector.new(10, 10, 10), vector.new(-11, -10, -10)))
  438. end)
  439. it("random_in_area()", function()
  440. local min = vector.new(-100, -100, -100)
  441. local max = vector.new(100, 100, 100)
  442. for i = 1, 1000 do
  443. local random = vector.random_in_area(min, max)
  444. assert.True(vector.in_area(random, min, max))
  445. end
  446. end)
  447. end)