我正在Lua中实现Bentley-Ottmann算法,使用位于here的伪代码在多边形中查找交叉点。
我对实现算法比较陌生,所以我无法理解它的所有部分。到目前为止,这是我的代码:
local function getPolygonIntersectingVertices( poly )
-- initializing and sorting X
local X = {}
for i = 1, table.getn( poly ) do
if i == 1 then
table.insert( X, { x = poly[i].x, y = poly[i].y, endpoint = 'left' } )
elseif i == table.getn( poly ) then
table.insert( X, { x = poly[i].x, y = poly[i].y, endpoint = 'right' } )
else
table.insert( X, { x = poly[i].x, y = poly[i].y, endpoint = 'right' })
table.insert( X, { x = poly[i].x, y = poly[i].y, endpoint = 'left' })
end
end
local sortxy = function( a, b )
if a.x < b.x then return true
elseif a.x > b.x then return false
elseif a.y <= b.y then return true
else return false end
end
table.sort( X, sortxy )
-- Main loop
local SL = {}
local L = {}
local E
local i = 1
while next(X) ~= nil do
E = { x = X[i].x, y = X[i].y, endpoint = X[i].endpoint }
if E.endpoint == 'left' then
-- left endpoint code here
elseif E.endpoint == 'right' then
-- right endpoint code here
else
end
table.remove( X, i )
end
return L
end
我的多边形是一个使用此结构的表:{{x = 1,y = 3},{x = 5,y = 6},...}
如何确定“ SL中segE以上的段; ”和“ SL中segE下方的段; ”以及扫描线(< strong> SL )是空的?同样,当我将I插入X时,我应该用 endpoint ='intersect'标记它并将其追加到末尾,这样当循环到达此部分时会进入主循环的“else”语句或我的整个算法错了吗?
如果有人可以通过Python,Ruby等简单的实现向我展示链接,那将是完美的,因为我发现很难遵循伪代码并将其与C ++示例相匹配。
答案 0 :(得分:2)
您的参考链接从我的位置失败。我将参考the Wikipedia article,这是相当不错的。
如何确定“SL中segE以上的段;”和“SL中segE下面的段;”
该算法需要BST用于在y的关键字上排序的当前扫描线交叉点,即按垂直顺序排序。所以上面的部分是BST的继任者,下面的部分是BST的前身。在BST中查找给定节点的前任和后继是标准的东西。密钥K的前身是K左边最右边的节点。后继节点是K的最左边节点。有几种计算方法。最简单的方法是使用父指针向后行走,然后从K向下行走。基于堆栈的迭代器是另一个。
如果扫描线(SL)为空怎么办?
继续处理事件队列。空扫描线只表示没有任何段在其当前x位置交叉。
同样,当我将I插入X时,我应该用endpoint ='intersect'标记它并将其追加到最后......?
事件队列必须在点的x坐标上保持排序。插入交集时,它也必须按x坐标顺序排列。必须将其标记为交叉点,因为交叉点的处理方式与端点不同。当它是x顺序中的第一个剩余项目时,它将在适当的时候处理。
请注意,Bentley Ottman - 就像几乎所有的几何算法一样 - 因浮点不准确而臭名昭着。此外,该算法通常给出一个“一般位置”假设,它假设所有令人讨厌的垂直边缘,点边重合,边缘重叠等情况。我最强烈的建议是使用有理算术。即便如此,获得完全稳健,正确的实施也是一项重大成就。你可以通过极少数的免费实现来说明这一点!