由于您创建的多边形仅具有轴对齐的边,您可以根据垂直板计算总面积。
假设我们得到了一个顶点列表V。我假设我们已经在这个列表中进行了换行,所以我们可以为每个顶点 v in V 查询 V.next(v)。对于最后一个,结果是第一个。
首先,尝试找到最左边和最右边的点,以及到达最左边点的顶点(以线性时间)。
x = 0 // current x-position
xMin = inf, xMax = -inf // leftmost and rightmost point
leftVertex = null // leftmost vertex
foreach v in V
x = x + (v is left ? -1 : v is right ? 1 : 0)
xMax = max(x, xMax)
if x < xMin
xMin = x
leftVertex = V.next(v)
现在我们创建一个简单的数据结构:对于每个垂直平板,我们保留一个最大堆(排序列表也可以,但我们只需要在最后重复获取最大元素)。
width = xMax - xMin
heaps = new MaxHeap[width]
我们现在从顶点leftVertex(我们在第一步中找到的最左边的顶点)开始跟踪形状。我们现在选择这个顶点有 x/y 位置 (0, 0),只是因为它方便。
x = 0, y = 0
v = leftVertex
do
if v is left
x = x-1 // use left endpoint for index
heaps[x].Add(y) // first dec, then store
if v is right
heaps[x].Add(y) // use left endpoint for index
x = x+1 // first store, then inc
if v is up
y = y+1
if v is down
y = y-1
v = V.next(v)
until v = leftVertex
您可以在O(n log n) 时间内构建此结构,因为添加到堆需要对数时间。
最后,我们需要从堆中计算面积。对于格式正确的输入,我们需要从堆中获取两个连续的 y 值并将它们相减。
area = 0
foreach heap in heaps
while heap not empty
area += heap.PopMax() - heap.PopMax() // each polygon's area
return area
同样,这需要O(n log n) 时间。
我将算法移植到 java 实现中(请参阅Ideone)。两个样本运行:
public static void main (String[] args) {
// _
// | |_
// |_ _ |
Direction[] input = { Direction.Up, Direction.Up,
Direction.Right, Direction.Down,
Direction.Right, Direction.Down,
Direction.Left, Direction.Left };
System.out.println(computeArea(input));
// _
// |_|_
// |_|
Direction[] input2 = { Direction.Up, Direction.Right,
Direction.Down, Direction.Down,
Direction.Right, Direction.Up,
Direction.Left, Direction.Left };
System.out.println(computeArea(input2));
}
返回(如预期):
3
2