Last active
December 18, 2015 17:39
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
计算斜率: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