From 79f480a980c26a34c01112f8b707e12b0189a95f Mon Sep 17 00:00:00 2001 From: Yevhen Boichuk Date: Fri, 9 Oct 2026 13:26:15 +0300 Subject: [PATCH] fix: fix geometry logic --- src/apps/lua/lualilka_geometry.cpp | 11 +++++++---- src/apps/lua/lualilka_imageTransform.cpp | 25 ++++++++++++------------ src/apps/lua/luarunner.cpp | 14 +++++++++++++ src/apps/lua/luarunner.h | 2 ++ src/apps/mjs/mjsgeometry.cpp | 11 ++++++++--- 5 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/apps/lua/lualilka_geometry.cpp b/src/apps/lua/lualilka_geometry.cpp index 9499a8e4..97cad8dd 100644 --- a/src/apps/lua/lualilka_geometry.cpp +++ b/src/apps/lua/lualilka_geometry.cpp @@ -16,16 +16,19 @@ int lualilka_geometry_intersectLines(lua_State* L) { float dx = luaL_checknumber(L, 7); float dy = luaL_checknumber(L, 8); - // I have no idea what I'm doing - Copilot wrote this for me, lol + // Solve A + t * (B - A) = C + u * (D - C) using 2D cross products: segments intersect when t, u are in [0, 1] + float rx = bx - ax, ry = by - ay; // B - A + float sx = dx - cx, sy = dy - cy; // D - C + float qx = cx - ax, qy = cy - ay; // C - A - float denominator = (by - ay) * (dx - cx) - (bx - ax) * (dy - cy); + float denominator = rx * sy - ry * sx; if (denominator == 0) { lua_pushboolean(L, false); return 1; } - float t = ((cy - ay) * (dx - cx) - (cx - ax) * (dy - cy)) / denominator; - float u = -((ay - by) * (cx - ax) - (ax - bx) * (cy - ay)) / denominator; + float t = (qx * sy - qy * sx) / denominator; + float u = (qx * ry - qy * rx) / denominator; if (t >= 0 && t <= 1 && u >= 0 && u <= 1) { lua_pushboolean(L, true); diff --git a/src/apps/lua/lualilka_imageTransform.cpp b/src/apps/lua/lualilka_imageTransform.cpp index a5f687f3..699ea8da 100644 --- a/src/apps/lua/lualilka_imageTransform.cpp +++ b/src/apps/lua/lualilka_imageTransform.cpp @@ -67,7 +67,7 @@ static int lualilka_imageTransform_get_matrix(lua_State* L) { for (int i = 0; i < 2; ++i) { lua_newtable(L); for (int j = 0; j < 2; ++j) { - lua_pushinteger(L, (*userdata)->matrix[i][j]); + lua_pushnumber(L, (*userdata)->matrix[i][j]); lua_rawseti(L, -2, j + 1); } lua_rawseti(L, -2, i + 1); @@ -77,26 +77,27 @@ static int lualilka_imageTransform_get_matrix(lua_State* L) { static int lualilka_imageTransform_set_matrix(lua_State* L) { lilka::Transform** userdata = TRANSFORM_PTR(luaL_checkudata(L, 1, IMAGE_TRANSFORM)); - if (!lua_istable(L, 2)) { - return luaL_error(L, "Expected a table as the second argument"); - } + luaL_checktype(L, 2, LUA_TTABLE); + // Validate the whole matrix first, so a bad argument leaves the transform untouched + float matrix[2][2]; for (int i = 0; i < 2; ++i) { - lua_rawgeti(L, 2, i + 1); + if (lua_rawgeti(L, 2, i + 1) != LUA_TTABLE) { + return luaL_error(L, "Expected a 2x2 table, row %d is not a table", i + 1); + } for (int j = 0; j < 2; ++j) { lua_rawgeti(L, -1, j + 1); - - if (!lua_isnumber(L, -1)) { - lua_pop(L, 2); - return luaL_error(L, "Element at (%d, %d) is not a number", i, j); + int isNumber = 0; + matrix[i][j] = lua_tonumberx(L, -1, &isNumber); + if (!isNumber) { + return luaL_error(L, "Element at (%d, %d) is not a number", i + 1, j + 1); } - - (*userdata)->matrix[i][j] = lua_tonumber(L, -1); lua_pop(L, 1); } - lua_pop(L, 1); } + + memcpy((*userdata)->matrix, matrix, sizeof(matrix)); return 0; } diff --git a/src/apps/lua/luarunner.cpp b/src/apps/lua/luarunner.cpp index 00f30535..18ecfbb9 100644 --- a/src/apps/lua/luarunner.cpp +++ b/src/apps/lua/luarunner.cpp @@ -249,6 +249,19 @@ void AbstractLuaRunnerApp::luaTeardown() { lua_close(L); } +void AbstractLuaRunnerApp::resetCanvasState() { + for (lilka::Canvas* c : {canvas, backCanvas}) { + if (!c) continue; + // Match defaults of a freshly constructed lilka::Canvas + c->setFont(FONT_10x20); + c->setTextBound(0, 0, c->width(), c->height()); + c->setTextColor(lilka::colors::White); + c->setTextSize(1); + c->setTextWrap(true); + c->setCursor(0, 0); + } +} + int AbstractLuaRunnerApp::execute() { // Calls Lua code that's on top of the stack (previously loaded with luaL_loadfile or luaL_loadstring) @@ -256,6 +269,7 @@ int AbstractLuaRunnerApp::execute() { if (jmpCode == 0) { // Run script + resetCanvasState(); canvas->fillScreen(0); int retCode = lua_pcall(L, 0, LUA_MULTRET, 0); if (retCode) { diff --git a/src/apps/lua/luarunner.h b/src/apps/lua/luarunner.h index 1aa191ce..b1097a7f 100644 --- a/src/apps/lua/luarunner.h +++ b/src/apps/lua/luarunner.h @@ -28,6 +28,8 @@ class AbstractLuaRunnerApp : public App { void luaSetup(const char* dir); void luaTeardown(); int execute(); + // Restore default text state on both canvas buffers, so scripts don't inherit runner UI settings + void resetCanvasState(); lua_State* L; }; diff --git a/src/apps/mjs/mjsgeometry.cpp b/src/apps/mjs/mjsgeometry.cpp index 6262b7d4..97ab4e71 100644 --- a/src/apps/mjs/mjsgeometry.cpp +++ b/src/apps/mjs/mjsgeometry.cpp @@ -12,14 +12,19 @@ static void mjs_geometry_intersect_lines(struct mjs* mjs) { float dx = mjs_get_double(mjs, mjs_arg(mjs, 6)); float dy = mjs_get_double(mjs, mjs_arg(mjs, 7)); - float denominator = (by - ay) * (dx - cx) - (bx - ax) * (dy - cy); + // Solve A + t * (B - A) = C + u * (D - C) using 2D cross products: segments intersect when t, u are in [0, 1] + float rx = bx - ax, ry = by - ay; // B - A + float sx = dx - cx, sy = dy - cy; // D - C + float qx = cx - ax, qy = cy - ay; // C - A + + float denominator = rx * sy - ry * sx; if (denominator == 0) { mjs_return(mjs, mjs_mk_boolean(mjs, 0)); return; } - float t = ((cy - ay) * (dx - cx) - (cx - ax) * (dy - cy)) / denominator; - float u = -((ay - by) * (cx - ax) - (ax - bx) * (cy - ay)) / denominator; + float t = (qx * sy - qy * sx) / denominator; + float u = (qx * ry - qy * rx) / denominator; mjs_return(mjs, mjs_mk_boolean(mjs, t >= 0 && t <= 1 && u >= 0 && u <= 1)); }