"mirror" 上的二维线反射
2D Line reflection on a "mirror"
所以我断断续续地研究了一个星期,谷歌搜索等等,但我还没有找到如何做到这一点。
我有一个 "rays" 的 table 和一个 "lines" 的 table,我希望这些线充当镜子并在光线击中时反射光线一条线。想象一下激光从镜子上反射回来,那种反射。我已经进行了交点检测,但我不知道如何正确计算反射角并沿该方向延伸光线。
代码:
--the table rays is a table of tables, and each table inside is formatted as such:
--rays[x] = {100,200,150,600,200,400}, where (100,200) are ordered pairs, etc.
--The table lines simply contains values for x1,y1,x2,y2
for i,ray in ipairs(rays) do
for j,line in ipairs(lines) do
if line.x2 ~= nil and #ray>3 then
print(line.x2..' '..line.y2)
iX, iY = intersect.test(ray[#ray-3],ray[#ray-2],
ray[#ray-1],ray[#ray],line.x1,line.y1,line.x2,line.y2)
--The above code takes each ray and
--sees if it intersects with a line, with the intersect.test function
--Then if it does, where iX and iY aren't nil, it continues
if iX ~= nil and iY ~= nil then
local rayA = (180/math.pi)*math.atan(getSlope(ray[#ray-3],ray[#ray-2],ray[#ray-1],ray[#ray]))
local lineA = (180/math.pi)*math.atan(getSlope(line.x1,line.y1,line.x2,line.y2))
local normalA = (180/math.pi)*math.atan(-1/getSlope(line.x1,line.y1,line.x2,line.y2))
--Here I'm calculating the angle in degrees. For the final code all those atans will
--be out of there for optimization, but its easiest now to see the actual angle
print(rayA..' '..lineA..' '..normalA)
ray[#ray-1]=iX
ray[#ray]=iY
--This little part just create a point on the ray right at the intersection
--The code after this is my attempt, which doesn't work
local reflectA = normalA-rayA
local reflectR = 2*reflectA+rayA
print(reflectR)
reflectR = reflectR/(180/math.pi)
local rSlope = math.tan(reflectR)
local offset = 0
ray[#ray+1]=iX+offset
ray[#ray+1]=iY+(offset*rSlope)
end
end
end
end
我卡在最后一节了。它有点创建了一个从线上反弹的线段,但有时它会越过线,而且它永远不是正确的反射角度。任何关于我应该如何做的指示都将不胜感激。
如果可以避免,最好避免使用斜率和角度,因为您将不得不处理烦人的特殊情况,例如斜率是 +ve 或 -ve 无穷大等等。
如果你能计算出直线的法线(蓝色箭头),那么你就可以用点积来做反射:
计算直线的法线是这样完成的:
local normalY = line.x2 - line.x1
local normalX = line.y1 - line.y2
local normalLength = math.sqrt(normalX * normalX + normalY * normalY)
normalX = normalX / normalLength
normalY = normalY / normalLength
然后你需要计算从线和射线的交点到射线尖端的矢量(已经"through"你想要反射的线的点):
local rayX = rayTipX - iX
local rayY = rayTipY - iY
然后计算点积:
local dotProduct = (rayX * normalX) + (rayY * normalY)
这告诉我们光线沿法线方向穿过交点多远(绿线的长度)。要找到绿线的向量,请将线法线乘以点积:
local dotNormalX = dotProduct * normalX
local dotNormalY = dotProduct * normalY
如果我们对这个向量求反然后乘以它(得到绿线加粉线),然后把它加到光线的尖端,我们将得到光线的反射尖端:
local reflectedRayTipX = rayTipX - (dotNormalX * 2)
local reflectedRayTipY = rayTipY - (dotNormalY * 2)
所以我断断续续地研究了一个星期,谷歌搜索等等,但我还没有找到如何做到这一点。
我有一个 "rays" 的 table 和一个 "lines" 的 table,我希望这些线充当镜子并在光线击中时反射光线一条线。想象一下激光从镜子上反射回来,那种反射。我已经进行了交点检测,但我不知道如何正确计算反射角并沿该方向延伸光线。
代码:
--the table rays is a table of tables, and each table inside is formatted as such:
--rays[x] = {100,200,150,600,200,400}, where (100,200) are ordered pairs, etc.
--The table lines simply contains values for x1,y1,x2,y2
for i,ray in ipairs(rays) do
for j,line in ipairs(lines) do
if line.x2 ~= nil and #ray>3 then
print(line.x2..' '..line.y2)
iX, iY = intersect.test(ray[#ray-3],ray[#ray-2],
ray[#ray-1],ray[#ray],line.x1,line.y1,line.x2,line.y2)
--The above code takes each ray and
--sees if it intersects with a line, with the intersect.test function
--Then if it does, where iX and iY aren't nil, it continues
if iX ~= nil and iY ~= nil then
local rayA = (180/math.pi)*math.atan(getSlope(ray[#ray-3],ray[#ray-2],ray[#ray-1],ray[#ray]))
local lineA = (180/math.pi)*math.atan(getSlope(line.x1,line.y1,line.x2,line.y2))
local normalA = (180/math.pi)*math.atan(-1/getSlope(line.x1,line.y1,line.x2,line.y2))
--Here I'm calculating the angle in degrees. For the final code all those atans will
--be out of there for optimization, but its easiest now to see the actual angle
print(rayA..' '..lineA..' '..normalA)
ray[#ray-1]=iX
ray[#ray]=iY
--This little part just create a point on the ray right at the intersection
--The code after this is my attempt, which doesn't work
local reflectA = normalA-rayA
local reflectR = 2*reflectA+rayA
print(reflectR)
reflectR = reflectR/(180/math.pi)
local rSlope = math.tan(reflectR)
local offset = 0
ray[#ray+1]=iX+offset
ray[#ray+1]=iY+(offset*rSlope)
end
end
end
end
我卡在最后一节了。它有点创建了一个从线上反弹的线段,但有时它会越过线,而且它永远不是正确的反射角度。任何关于我应该如何做的指示都将不胜感激。
如果可以避免,最好避免使用斜率和角度,因为您将不得不处理烦人的特殊情况,例如斜率是 +ve 或 -ve 无穷大等等。
如果你能计算出直线的法线(蓝色箭头),那么你就可以用点积来做反射:
计算直线的法线是这样完成的:
local normalY = line.x2 - line.x1
local normalX = line.y1 - line.y2
local normalLength = math.sqrt(normalX * normalX + normalY * normalY)
normalX = normalX / normalLength
normalY = normalY / normalLength
然后你需要计算从线和射线的交点到射线尖端的矢量(已经"through"你想要反射的线的点):
local rayX = rayTipX - iX
local rayY = rayTipY - iY
然后计算点积:
local dotProduct = (rayX * normalX) + (rayY * normalY)
这告诉我们光线沿法线方向穿过交点多远(绿线的长度)。要找到绿线的向量,请将线法线乘以点积:
local dotNormalX = dotProduct * normalX
local dotNormalY = dotProduct * normalY
如果我们对这个向量求反然后乘以它(得到绿线加粉线),然后把它加到光线的尖端,我们将得到光线的反射尖端:
local reflectedRayTipX = rayTipX - (dotNormalX * 2)
local reflectedRayTipY = rayTipY - (dotNormalY * 2)