我正在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以下的部分;”如果扫描线(SL)为空怎么办?同样,当我将I插入X时,我应该用endpoint =’intersect’标记它并将其附加到末尾,这样当循环到达这个部分时进入主循环的“else”语句或者我得到了整个算法错误?
这将是完美的,有人可以通过Python,Ruby等简单实现向我展示链接,因为我发现很难遵循伪代码并将其与C示例相匹配.
最佳答案 您的参考链接从我的位置失败.我会参考
the Wikipedia article,这是相当不错的.
How do I determine “the segment above segE in SL;” and “the segment below segE in SL;”
该算法需要BST用于在y的关键字上排序的当前扫描线交叉点,即按垂直顺序排序.所以上面的部分是BST的继任者,下面的部分是BST的前身.在BST中查找给定节点的前任和后继是标准的东西.密钥K的前身是K左边最右边的节点.后继节点是K的最左边节点.有几种计算方法.最简单的方法是使用父指针向后行走,然后从K向下行走.基于堆栈的迭代器是另一个.
what to do if the sweep line (SL) is empty?
继续处理事件队列.空扫描线仅表示没有段在其当前x位置处交叉.
Also when inserting I into X, should I mark it with endpoint = ‘intersect’ and append it to the end …?
事件队列必须按点的x坐标排序.插入交集时,它也必须按x坐标顺序排列.必须将其标记为交叉点,因为交叉点的处理方式与端点不同.当它是x顺序中的第一个剩余项目时,它将在适当的时候处理.
请注意,Bentley Ottman – 就像几乎所有几何算法一样 – 因浮点不准确而臭名昭着.此外,该算法通常给出一个“一般位置”假设,它假设所有令人讨厌的垂直边缘,点边重合,边缘重叠等情况.我最强烈的建议是使用有理算术.即便如此,获得完全稳健,正确的实施也是一项重大成就.你可以通过极少数的免费实现来说明这一点!