我已基本遵循{{3}}每一步,因为我编写了这个小凸包可视化器。它通常按预期工作,但在更高的输入尺寸下,通常会出现错误点。
程序首先填充ArrayList<Point>
一定数量的随机生成的Point
个对象。然后,它会找到Point
最低y
。如果多个Point
个对象共享最低值,则使用具有最低x
的对象。
接下来,相对于上面找到的特定ArrayList<Double>
,它会生成每Point
个Point
个角度。它会快速排序这些角度及其对应的Point
个对象,以生成带有排序值的ArrayList<Point>
。
下一步是我相信我的问题所在。首先,我复制ArrayList<Point>
并将其称为edges
(请注意,如果我没有使用原始ArrayList<Point>
进行可视化,则无需克隆)对于任何三个有序Point
1}}} {} {}}中的对象我们会调用edges
,A
和B,
,如果从C
到AB
则右转,然后BC
应从船体中排除,并从B
中删除。我通过取十字积的z值确定转弯是向右还是向左(负z意味着edges
到AB
是右转)。该程序删除任何导致右转的点并继续。
BC
为了循环多次,我主要添加了// loops through the orders points. any time a right turn is
// encountered, the middle point is removed
edges = new ArrayList<Point>();
edges.addAll(points);
boolean changed = true;
while (changed) {
changed = false;
for (int i = 0; i < edges.size() - 2; i++) {
if (isRightTurn(edges.get(i), edges.get(i + 1),
edges.get(i + 2))) {
edges.remove(i + 1);
changed = true;
i--;
}
}
if (isRightTurn(edges.get(edges.size() - 2),
edges.get(edges.size() - 1), edges.get(0))) {
edges.remove(edges.size() - 1);
changed = true;
}
}
// uses the z-value of the cross product of AB and AC (ABxAC) to determine
// the direction of the turn.
public static boolean isRightTurn(Point a, Point b, Point c) {
if ((b.getX() - a.getX()) * (c.getY() - a.getY())
- (b.getY() - a.getY()) * (c.getX() - a.getX()) < 0)
return true;
return false;
}
变量,以便在跳过某些内容时进行验证。但是,错误仍然存在。有时,它按预期工作。
但是,通常至少有一些不正确的changed
个对象。
现在我注意到的是,直到左转弯发生,有多个Point
正确左转,但仍然是错误的,因为它们最终位于应该是凸包的内部。这可能是回溯的问题吗?我觉得反复循环应该抓住这些情况。
答案 0 :(得分:1)
以下是在对点进行排序后构建凸包的正确方法:
onHull = new List()
for p <- sorted list of points(including the first one)
while onHull.size() >= 2 && isRight(onHull[onHull.size() - 2], onHull[onHull.size() - 1], p)
onHull.popBack()
onHull.pushBack(p)
return onHull