Skip to content

Instantly share code, notes, and snippets.

@rangercyh
Last active December 18, 2015 17:39
Show Gist options
  • Save rangercyh/5819798 to your computer and use it in GitHub Desktop.
Save rangercyh/5819798 to your computer and use it in GitHub Desktop.
a function to draw a triangle from three vertexs, don't to traversal every point restrict in the rectangle
--[[
计算斜率:0和无穷大的情况简化处理了
]]
function get_slope(nPosX1, nPosY1, nPosX2, nPosY2, nPosX3, nPosY3)
local nSlope1, nSlope2, nSlope3
if nPosX1 == nPosX2 then
nSlope1 = 99999999 --设置一个近似无穷斜率
else
nSlope1 = (nPosY1 - nPosY2) / (nPosX1 - nPosX2)
end
if nPosX2 == nPosX3 then
nSlope2 = 99999999
else
nSlope2 = (nPosY2 - nPosY3) / (nPosX2 - nPosX3)
end
if nPosX3 == nPosX1 then
nSlope3 = 99999999
else
nSlope3 = (nPosY3 - nPosY1) / (nPosX3 - nPosX1)
end
if nSlope1 == 0 then
nSlope1 = 0.0000001
end
if nSlope2 == 0 then
nSlope2 = 0.0000001
end
if nSlope3 == 0 then
nSlope3 = 0.0000001
end
return nSlope1, nSlope2, nSlope3
end
--[[
获取最长边对应的顶点以及边判断的顺序
]]
function get_max_angle_pos(tbLine1, tbLine2, tbLine3)
local nMaxLine = math.max(tbLine1[1], tbLine2[1], tbLine3[1])
local tbStartPos = {}
local tbSlopeJudge = {}
if nMaxLine == tbLine1[1] then
tbStartPos = tbLine1[2]
table.insert(tbSlopeJudge, tbLine2[3]) --后期简化代码
table.insert(tbSlopeJudge, tbLine3[3])
table.insert(tbSlopeJudge, tbLine1[3])
elseif nMaxLine == tbLine2[1] then
tbStartPos = tbLine2[2]
table.insert(tbSlopeJudge, tbLine1[3])
table.insert(tbSlopeJudge, tbLine3[3])
table.insert(tbSlopeJudge, tbLine2[3])
else
tbStartPos = tbLine3[2]
table.insert(tbSlopeJudge, tbLine1[3])
table.insert(tbSlopeJudge, tbLine2[3])
table.insert(tbSlopeJudge, tbLine3[3])
end
return tbStartPos, tbSlopeJudge
end
--[[
获取起始点对应的增长方向
]]
function get_add_dir(tbStartPos, nMaxX, nMinX, nMaxY, nMinY)
local nAddX = 0
local nAddY = 0
if tbStartPos[1] == nMaxX then
nAddX = -1
elseif tbStartPos[1] == nMinX then
nAddX = 1
end
if tbStartPos[2] == nMaxY then
nAddY = -1
elseif tbStartPos[2] == nMinY then
nAddY = 1
end
return nAddX, nAddY
end
--[[
神奇的函数:计算出对应点与三角形三条线相交的交点,并决定正确的范围
]]
function getIntersection(tbSlopeJudge, nPoint, nDir, nMin, nMax)
local tbLimit = {}
local nMinC, nMaxC
local nC1, nC2, nC3 --交点
if (nDir == 1) or (nDir == 2) then --x
nC1 = math.floor(tbSlopeJudge[1][1] * nPoint + tbSlopeJudge[1][2])
nC2 = math.floor(tbSlopeJudge[2][1] * nPoint + tbSlopeJudge[2][2])
nC3 = math.floor(tbSlopeJudge[3][1] * nPoint + tbSlopeJudge[3][2])
elseif (nDir == 3) or (nDir == 4) then --y
nC1 = math.floor((nPoint - tbSlopeJudge[1][2]) / tbSlopeJudge[1][1])
nC2 = math.floor((nPoint - tbSlopeJudge[2][2]) / tbSlopeJudge[2][1])
nC3 = math.floor((nPoint - tbSlopeJudge[3][2]) / tbSlopeJudge[3][1])
end
nMinC, nMaxC = math.min(nC1, nC2), math.max(nC1, nC2)
--用矩形范围加以限制,保证点不超出矩形区域
nMinC = math.max(nMinC, nMin)
nMaxC = math.min(nMaxC, nMax)
--与发散点所对的边的交点如果在这个限制范围内,就截短范围
if (nC3 >= nMinC) and (nC3 < nMaxC) then
if tbSlopeJudge[3][1] > 0 then --正斜率且正向增长就替换最大范围,负斜率负向增长就替换最小范围
if math.fmod(nDir, 2) == 1 then
nMinC = nC3
else
nMaxC = nC3
end
elseif tbSlopeJudge[3][1] < 0 then
if math.fmod(nDir, 2) == 1 then
nMaxC = nC3
else
nMinC = nC3
end
end
end
table.insert(tbLimit, nMinC)
table.insert(tbLimit, nMaxC)
return tbLimit
end
--[[
按照方向来填充三角形所包含的点
]]
function fill_triangle_point(nAddX, nAddY, tbStartPos, tbSlopeJudge, nMinY, nMaxY, nMinX, nMaxX)
local tbTrianglePos = {}
local nDir = 0
if nAddX ~= 0 then
--决定x的扩展范围
local nLimitX = 0
if nAddX > 0 then
nLimitX = nMaxX
nDir = 1
elseif nAddX < 0 then
nLimitX = nMinX
nDir = 2
end
for x = tbStartPos[1], nLimitX, nAddX do
--找出x增加后y被三角形所夹的范围,范围内的点都在三角形内
local tbNode = getIntersection(tbSlopeJudge, x, nDir, nMinY, nMaxY)
for y = tbNode[1], tbNode[2] do
table.insert(tbTrianglePos, {x, y})
end
end
elseif nAddY ~= 0 then
--决定y的扩展范围
local nLimitY = 0
if nAddY > 0 then
nLimitY = nMaxY
nDir = 3
elseif nAddY < 0 then
nLimitY = nMinY
nDir = 4
end
for y = tbStartPos[2], nLimitY, nAddY do
--找出y增加后x被三角形所夹的范围,范围内的点都在三角形内
local tbNode = getIntersection(tbSlopeJudge, y, nDir, nMinX, nMaxX)
for x = tbNode[1], tbNode[2] do
table.insert(tbTrianglePos, {x, y})
end
end
end
return tbTrianglePos
end
--[[
绘制三角形区域
]]
function create_triangle(tbPos1, tbPos2, tbPos3)
local nPosX1, nPosY1 = unpack(tbPos1)
local nPosX2, nPosY2 = unpack(tbPos2)
local nPosX3, nPosY3 = unpack(tbPos3)
--找出包围三角形的最小矩形
local nMaxX = math.max(nPosX1, nPosX2, nPosX3)
local nMinX = math.min(nPosX1, nPosX2, nPosX3)
local nMaxY = math.max(nPosY1, nPosY2, nPosY3)
local nMinY = math.min(nPosY1, nPosY2, nPosY3)
--求出每条边的斜率并处理斜率为无穷和0的情况(有优化的方案可以减小此情况下的计算量)
local nSlope1, nSlope2, nSlope3 = get_slope(nPosX1, nPosY1, nPosX2, nPosY2, nPosX3, nPosY3)
--直线方程:y = kx + b
local nB1 = nPosY1 - nSlope1 * nPosX1
local nB2 = nPosY2 - nSlope2 * nPosX2
local nB3 = nPosY3 - nSlope3 * nPosX3
--计算每条边的长度
local nLine1 = math.sqrt((nPosY2 - nPosY1)^2 + (nPosX2 - nPosX1)^2) --pos3
local nLine2 = math.sqrt((nPosY3 - nPosY2)^2 + (nPosX3 - nPosX2)^2) --pos1
local nLine3 = math.sqrt((nPosY1 - nPosY3)^2 + (nPosX1 - nPosX3)^2) --pos2
--找到最长边对应的那个顶点作为发散起始点
local tbStartPos, tbSlopeJudge = get_max_angle_pos({nLine1, tbPos3, { nSlope1, nB1 }},
{nLine2, tbPos1, { nSlope2, nB2 }},
{nLine3, tbPos2, { nSlope3, nB3 }})
--判断起始点所处的位置,决定发散的方向
local nAddX, nAddY = get_add_dir(tbStartPos, nMaxX, nMinX, nMaxY, nMinY)
--终于到正文了,根据发散方向依次计算在三角形内的点
return fill_triangle_point(nAddX, nAddY, tbStartPos, tbSlopeJudge, nMinY, nMaxY, nMinX, nMaxX)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment