From 0cdd1d021f146fe233d83525b5fbb46468d21bd4 Mon Sep 17 00:00:00 2001 From: Orange Date: Tue, 10 Mar 2026 18:39:20 +0300 Subject: [PATCH] added triangle to lua --- include/omath/lua/lua.hpp | 1 + source/lua/lua.cpp | 1 + source/lua/lua_triangle.cpp | 48 ++++++++++++++++ tests/lua/triangle_tests.lua | 82 ++++++++++++++++++++++++++++ tests/lua/unit_test_lua_triangle.cpp | 47 ++++++++++++++++ 5 files changed, 179 insertions(+) create mode 100644 source/lua/lua_triangle.cpp create mode 100644 tests/lua/triangle_tests.lua create mode 100644 tests/lua/unit_test_lua_triangle.cpp diff --git a/include/omath/lua/lua.hpp b/include/omath/lua/lua.hpp index 91a043f..6585740 100644 --- a/include/omath/lua/lua.hpp +++ b/include/omath/lua/lua.hpp @@ -16,6 +16,7 @@ namespace omath::lua static void register_vec3(sol::table& omath_table); static void register_vec4(sol::table& omath_table); static void register_color(sol::table& omath_table); + static void register_triangle(sol::table& omath_table); static void register_shared_types(sol::table& omath_table); static void register_engines(sol::table& omath_table); }; diff --git a/source/lua/lua.cpp b/source/lua/lua.cpp index c1e173e..275d86e 100644 --- a/source/lua/lua.cpp +++ b/source/lua/lua.cpp @@ -18,6 +18,7 @@ namespace omath::lua register_vec3(omath_table); register_vec4(omath_table); register_color(omath_table); + register_triangle(omath_table); register_shared_types(omath_table); register_engines(omath_table); } diff --git a/source/lua/lua_triangle.cpp b/source/lua/lua_triangle.cpp new file mode 100644 index 0000000..28ecdcf --- /dev/null +++ b/source/lua/lua_triangle.cpp @@ -0,0 +1,48 @@ +// +// Created by orange on 10.03.2026. +// +#ifdef OMATH_ENABLE_LUA +#include "omath/lua/lua.hpp" +#include +#include + +namespace omath::lua +{ + void LuaInterpreter::register_triangle(sol::table& omath_table) + { + using Vec3f = omath::Vector3; + using Tri3f = omath::Triangle; + + omath_table.new_usertype( + "Triangle", sol::constructors(), + + "vertex1", + sol::property([](const Tri3f& t) { return t.m_vertex1; }, + [](Tri3f& t, const Vec3f& v) { t.m_vertex1 = v; }), + "vertex2", + sol::property([](const Tri3f& t) { return t.m_vertex2; }, + [](Tri3f& t, const Vec3f& v) { t.m_vertex2 = v; }), + "vertex3", + sol::property([](const Tri3f& t) { return t.m_vertex3; }, + [](Tri3f& t, const Vec3f& v) { t.m_vertex3 = v; }), + + "calculate_normal", &Tri3f::calculate_normal, + "side_a_length", &Tri3f::side_a_length, + "side_b_length", &Tri3f::side_b_length, + "side_a_vector", &Tri3f::side_a_vector, + "side_b_vector", &Tri3f::side_b_vector, + "hypot", &Tri3f::hypot, + "is_rectangular", &Tri3f::is_rectangular, + "mid_point", &Tri3f::mid_point, + + sol::meta_function::to_string, + [](const Tri3f& t) + { + return std::format("Triangle(({}, {}, {}), ({}, {}, {}), ({}, {}, {}))", + t.m_vertex1.x, t.m_vertex1.y, t.m_vertex1.z, + t.m_vertex2.x, t.m_vertex2.y, t.m_vertex2.z, + t.m_vertex3.x, t.m_vertex3.y, t.m_vertex3.z); + }); + } +} // namespace omath::lua +#endif diff --git a/tests/lua/triangle_tests.lua b/tests/lua/triangle_tests.lua new file mode 100644 index 0000000..566b23b --- /dev/null +++ b/tests/lua/triangle_tests.lua @@ -0,0 +1,82 @@ +local function approx(a, b, eps) return math.abs(a - b) < (eps or 1e-5) end + +function Triangle_Constructor_default() + local t = omath.Triangle.new() + assert(t.vertex1.x == 0 and t.vertex1.y == 0 and t.vertex1.z == 0) + assert(t.vertex2.x == 0 and t.vertex2.y == 0 and t.vertex2.z == 0) + assert(t.vertex3.x == 0 and t.vertex3.y == 0 and t.vertex3.z == 0) +end + +function Triangle_Constructor_vertices() + local v1 = omath.Vec3.new(1, 0, 0) + local v2 = omath.Vec3.new(0, 1, 0) + local v3 = omath.Vec3.new(0, 0, 1) + local t = omath.Triangle.new(v1, v2, v3) + assert(t.vertex1.x == 1 and t.vertex1.y == 0 and t.vertex1.z == 0) + assert(t.vertex2.x == 0 and t.vertex2.y == 1 and t.vertex2.z == 0) + assert(t.vertex3.x == 0 and t.vertex3.y == 0 and t.vertex3.z == 1) +end + +function Triangle_Vertex_mutation() + local t = omath.Triangle.new() + t.vertex1 = omath.Vec3.new(5, 6, 7) + assert(t.vertex1.x == 5 and t.vertex1.y == 6 and t.vertex1.z == 7) +end + +-- Right triangle: v1=(0,3,0), v2=(0,0,0), v3=(4,0,0) — sides 3, 4, hypot 5 +function Triangle_SideALength() + local t = omath.Triangle.new(omath.Vec3.new(0, 3, 0), omath.Vec3.new(0, 0, 0), omath.Vec3.new(4, 0, 0)) + assert(approx(t:side_a_length(), 3.0)) +end + +function Triangle_SideBLength() + local t = omath.Triangle.new(omath.Vec3.new(0, 3, 0), omath.Vec3.new(0, 0, 0), omath.Vec3.new(4, 0, 0)) + assert(approx(t:side_b_length(), 4.0)) +end + +function Triangle_Hypot() + local t = omath.Triangle.new(omath.Vec3.new(0, 3, 0), omath.Vec3.new(0, 0, 0), omath.Vec3.new(4, 0, 0)) + assert(approx(t:hypot(), 5.0)) +end + +function Triangle_SideAVector() + local t = omath.Triangle.new(omath.Vec3.new(0, 3, 0), omath.Vec3.new(0, 0, 0), omath.Vec3.new(4, 0, 0)) + local a = t:side_a_vector() + assert(approx(a.x, 0) and approx(a.y, 3) and approx(a.z, 0)) +end + +function Triangle_SideBVector() + local t = omath.Triangle.new(omath.Vec3.new(0, 3, 0), omath.Vec3.new(0, 0, 0), omath.Vec3.new(4, 0, 0)) + local b = t:side_b_vector() + assert(approx(b.x, 4) and approx(b.y, 0) and approx(b.z, 0)) +end + +function Triangle_IsRectangular_true() + local t = omath.Triangle.new(omath.Vec3.new(0, 3, 0), omath.Vec3.new(0, 0, 0), omath.Vec3.new(4, 0, 0)) + assert(t:is_rectangular() == true) +end + +function Triangle_IsRectangular_false() + -- equilateral-ish triangle, not rectangular + local t = omath.Triangle.new(omath.Vec3.new(0, 1, 0), omath.Vec3.new(-1, 0, 0), omath.Vec3.new(1, 0, 0)) + assert(t:is_rectangular() == false) +end + +function Triangle_MidPoint() + local t = omath.Triangle.new(omath.Vec3.new(3, 0, 0), omath.Vec3.new(0, 3, 0), omath.Vec3.new(0, 0, 3)) + local m = t:mid_point() + assert(approx(m.x, 1.0) and approx(m.y, 1.0) and approx(m.z, 1.0)) +end + +function Triangle_CalculateNormal() + -- flat triangle in XY plane — normal should be (0, 0, 1) + local t = omath.Triangle.new(omath.Vec3.new(0, 1, 0), omath.Vec3.new(0, 0, 0), omath.Vec3.new(1, 0, 0)) + local n = t:calculate_normal() + assert(approx(n.x, 0) and approx(n.y, 0) and approx(n.z, 1)) +end + +function Triangle_ToString() + local t = omath.Triangle.new(omath.Vec3.new(1, 0, 0), omath.Vec3.new(0, 1, 0), omath.Vec3.new(0, 0, 1)) + local s = tostring(t) + assert(s == "Triangle((1, 0, 0), (0, 1, 0), (0, 0, 1))") +end diff --git a/tests/lua/unit_test_lua_triangle.cpp b/tests/lua/unit_test_lua_triangle.cpp new file mode 100644 index 0000000..096017b --- /dev/null +++ b/tests/lua/unit_test_lua_triangle.cpp @@ -0,0 +1,47 @@ +// +// Created by orange on 10.03.2026. +// +#include +#include +#include + +class LuaTriangle : public ::testing::Test +{ +protected: + lua_State* L = nullptr; + + void SetUp() override + { + L = luaL_newstate(); + luaL_openlibs(L); + omath::lua::LuaInterpreter::register_lib(L); + if (luaL_dofile(L, LUA_SCRIPTS_DIR "/triangle_tests.lua") != LUA_OK) + FAIL() << lua_tostring(L, -1); + } + + void TearDown() override { lua_close(L); } + + void check(const char* func_name) + { + lua_getglobal(L, func_name); + if (lua_pcall(L, 0, 0, 0) != LUA_OK) + { + FAIL() << lua_tostring(L, -1); + lua_pop(L, 1); + } + } +}; + +TEST_F(LuaTriangle, Constructor_default) { check("Triangle_Constructor_default"); } +TEST_F(LuaTriangle, Constructor_vertices) { check("Triangle_Constructor_vertices"); } +TEST_F(LuaTriangle, Vertex_mutation) { check("Triangle_Vertex_mutation"); } +TEST_F(LuaTriangle, SideALength) { check("Triangle_SideALength"); } +TEST_F(LuaTriangle, SideBLength) { check("Triangle_SideBLength"); } +TEST_F(LuaTriangle, Hypot) { check("Triangle_Hypot"); } +TEST_F(LuaTriangle, SideAVector) { check("Triangle_SideAVector"); } +TEST_F(LuaTriangle, SideBVector) { check("Triangle_SideBVector"); } +TEST_F(LuaTriangle, IsRectangular_true) { check("Triangle_IsRectangular_true"); } +TEST_F(LuaTriangle, IsRectangular_false) { check("Triangle_IsRectangular_false"); } +TEST_F(LuaTriangle, MidPoint) { check("Triangle_MidPoint"); } +TEST_F(LuaTriangle, CalculateNormal) { check("Triangle_CalculateNormal"); } +TEST_F(LuaTriangle, ToString) { check("Triangle_ToString"); }