Here's the code for the specific scenario. It'll run as is and has no dependencies.

-- create new vertices for a shape after it is rotated
local function rotatePolygon(vertices,r)
-- matrixRotate returns rotation matrix for angle theta
local function matrixRotate(theta)
local t = setmetatable({},mt)
t[1] = {math.cos(theta),math.sin(theta)}
t[2] = {-math.sin(theta),math.cos(theta)}
return t
end
-- multiply two matrices and return the resulting matrix
local function matrixMultiply( m1, m2 )
-- matrixMultiply source: https://github.com/davidm/lua-matrix/blob/master/lua/matrix.lua
if #m1[1] ~= #m2 then
return nil
end
local res = {}
for i = 1, #m1 do
res[i] = {}
for j = 1, #m2[1] do
res[i][j] = 0
for k = 1, #m2 do
res[i][j] = res[i][j] + m1[i][k] * m2[k][j]
end
end
end
return res
end
local matrix = {}
-- turn the vertices table into a matrix
for i = 1, #vertices*0.5 do
matrix[i] = {}
matrix[i][1] = vertices[i*2-1]
matrix[i][2] = vertices[i*2]
end
-- create a rotation matrix for the given rotation
local matrixRotation = matrixRotate(math.rad(r))
-- multiply the vertices matrix with the rotation metrix
local matrixFinal = matrixMultiply(matrix,matrixRotation)
-- update the original vertices and turn the matrix back into a table
for i = 1, #matrixFinal do
vertices[i*2-1] = matrixFinal[i][1]
vertices[i*2] = matrixFinal[i][2]
end
return vertices
end
-- doLinesIntersect source: https://gist.github.com/HoraceBury/9431861
local function doLinesIntersect( a, b, c, d )
-- parameter conversion
local L1 = {X1=a.x,Y1=a.y,X2=b.x,Y2=b.y}
local L2 = {X1=c.x,Y1=c.y,X2=d.x,Y2=d.y}
-- Denominator for ua and ub are the same, so store this calculation
local _d = (L2.Y2 - L2.Y1) * (L1.X2 - L1.X1) - (L2.X2 - L2.X1) * (L1.Y2 - L1.Y1)
-- Make sure there is not a division by zero - this also indicates that the lines are parallel.
-- If n_a and n_b were both equal to zero the lines would be on top of each
-- other (coincidental). This check is not done because it is not
-- necessary for this implementation (the parallel check accounts for this).
if (_d == 0) then
return false
end
-- n_a and n_b are calculated as seperate values for readability
local n_a = (L2.X2 - L2.X1) * (L1.Y1 - L2.Y1) - (L2.Y2 - L2.Y1) * (L1.X1 - L2.X1)
local n_b = (L1.X2 - L1.X1) * (L1.Y1 - L2.Y1) - (L1.Y2 - L1.Y1) * (L1.X1 - L2.X1)
-- Calculate the intermediate fractional point that the lines potentially intersect.
local ua = n_a / _d
local ub = n_b / _d
-- The fractional point will be between 0 and 1 inclusive if the lines
-- intersect. If the fractional calculation is larger than 1 or smaller
-- than 0 the lines would need to be longer to intersect.
if (ua >= 0 and ua <= 1 and ub >= 0 and ub <= 1) then
local x = L1.X1 + (ua * (L1.X2 - L1.X1))
local y = L1.Y1 + (ua * (L1.Y2 - L1.Y1))
return {x=x, y=y}
end
return false
end
local light = display.newCircle(0,0,4)
light:setFillColor(1,1,0)
light.brightness = 1
local shadow = display.newPolygon( 222, 186, {-86,-25,-65,-46,-8,-49,50,6,21,37,-41,102,-63,81,-21,38,-36,23,-64,39,-85,18,-64,-4} )
shadow:setFillColor(1,0,0,0.5)
local vertices = {-40,-30,-20,-30,-20,10,0,10,0,-10,20,-10,20,10,40,10,40,30,-40,30}
local object = display.newPolygon( 240, 160, vertices )
object.rotation = 224
-- light coordinates 1: five decimals, which ultimately lead to intersect
light.x = 346.34442
light.y = 104.40447
-- light coordinates 2: four decimals, which no longer lead to intersect
-- light.x = 346.3444
-- light.y = 104.4044
local rotatedVertices = rotatePolygon(vertices,object.rotation)
local function newVertex(vX,vY)
local shadowLength = math.sqrt((vX-light.x)^2+(vY-light.y)^2)*(0.5*light.brightness)
local shadowAngle = math.deg(math.atan2(vY-light.y,vX-light.x))
local dx = math.sin(math.rad(shadowAngle-90))*shadowLength
local dy = math.cos(math.rad(shadowAngle-90))*shadowLength
vX = vX-dx
vY = vY+dy
return vX, vY
end
local vertex = {}
vertex[#vertex+1] = {}
vertex[#vertex].x, vertex[#vertex].y = newVertex(rotatedVertices[5]+object.x, rotatedVertices[6]+object.y)
vertex[#vertex+1] = {}
vertex[#vertex].x, vertex[#vertex].y = newVertex(rotatedVertices[7]+object.x, rotatedVertices[8]+object.y)
vertex[#vertex+1] = {}
vertex[#vertex].x, vertex[#vertex].y = newVertex(rotatedVertices[13]+object.x, rotatedVertices[14]+object.y)
vertex[#vertex+1] = {}
vertex[#vertex].x, vertex[#vertex].y = newVertex(rotatedVertices[15]+object.x, rotatedVertices[16]+object.y)
local line12 = display.newLine(vertex[1].x,vertex[1].y,vertex[2].x,vertex[2].y)
local line34 = display.newLine(vertex[3].x,vertex[3].y,vertex[4].x,vertex[4].y)
local number = {}
for k = 1, 4 do
number[k] = display.newText( k, vertex[k].x,vertex[k].y, native.systemFont, 12 )
number[k]:setFillColor(1,1,0)
end
-- method 1: using the actual, non-rounded numbers
---------------------------------------------------
local intersect = doLinesIntersect( vertex[1], vertex[2], vertex[3], vertex[4] )
-- method 2: print the values and use them directly
---------------------------------------------------
-- print(vertex[1].x,vertex[1].y,vertex[2].x,vertex[2].y,vertex[3].x,vertex[3].y,vertex[4].x,vertex[4].y)
-- vertex[1].x = 218.82785887369
-- vertex[1].y = 197.84741793315
-- vertex[2].x = 197.24766486353
-- vertex[2].y = 177.00766681938
-- vertex[3].x = 175.66747085337
-- vertex[3].y = 156.16791570561
-- vertex[4].x = 154.08727684321
-- vertex[4].y = 135.32816459184
-- method 3: use floored (or rounded) values
---------------------------------------------------
-- for i = 1, 4 do
-- vertex[i].x = math.floor(vertex[i].x)
-- vertex[i].y = math.floor(vertex[i].y)
-- end
local intersect = doLinesIntersect( vertex[1], vertex[2], vertex[3], vertex[4] )
print("---")
if intersect == false then
print("The lines do not intersect.")
else
print("The lines intersect at x: "..intersect.x..", y: "..intersect.y)
end
local distance = math.sqrt((vertex[2].x-vertex[3].x)^2+(vertex[2].y-vertex[3].y)^2)
print("The distance between vertex 2 and 3 is "..distance.."px.")

I replaced my own intersect function with Horace Bury's that I found online just to ensure that his function returns the same results as mine, which it does.

I reiterate, the reason why I believe that this has to do with number precision in lua is because,

1) if the light's coordinates are given with four decimal points instead of five, then the intersect no longer occurs.

2) if the four vertices are not altered, then the intersect occurs (as long as light uses 5 decimals), but

3) if the four vertices are rounded, floored or printed out and inserted with 11 decimal point accuracy, then the intersect no longer occurs.

I am interested in why this kind behaviour of happening. This isn't really a debugging issue.