【发布时间】:2014-08-07 19:02:00
【问题描述】:
当我的列表有很多点时,我在 graham 扫描算法中遇到了问题,但每次都可以在点数很少的情况下正常工作。我做了一些截图:
角度计算:
public static double angle(MyVector3D vec1, MyVector3D vec2)
{
return Math.Atan2(vec2.Y - vec1.Y, vec2.X - vec1.X) * 180 / Math.PI;
}
按极角排序点取决于最大 Y 点:
//bubblesort
private void sortList()
{
double temp = 0.0;
MyVector3D tempVector = new MyVector3D();
for (int i = 1; i < points.Count; i++)
{
for (int j = 1; j < points.Count - 1; j++)
{
if (angles[j] < angles[j + 1])
{
temp = angles[j + 1];
tempVector = points[j + 1];
angles[j + 1] = angles[j];
points[j + 1] = points[j];
angles[j] = temp;
points[j] = tempVector;
}
}
}
逆时针方法:
private double ccw(MyVector3D vec1, MyVector3D vec2, MyVector3D vec3)
{
// ccwTest = ((vec2.X - vec1.X) * (vec3.Y - vec1.Y)) - ((vec2.Y - vec1.Y) * (vec3.X - vec1.X));
return ((vec2.X - vec1.X) * (vec3.Y - vec1.Y)) - ((vec2.Y - vec1.Y) * (vec3.X - vec1.X));
}
格雷厄姆扫描算法:
for (int i = 2; i < points.Count; i++)
{
while (ccw(points[M - 1], points[M], points[i]) > 0)
{
if (M > 1)
{
points.RemoveAt(M);
M -= 1;
i--;
}
else if (i == points.Count - 1)
{
break;
}
else
{
i += 1;
}
}
//goodPoints.Add(points[M]);
//listBoxInfos.Items.Add("g" + (int)points[M].X + "," + (int)points[M].Y + "," + 0);
//listBoxInfos.Items.Add("ccw" + ccwTest);
M += 1;
}
我真的不知道为什么我的程序在 800+ 点上爆炸...很难调试,因为算法在 300,400,500... 点上运行得很好。
Ty 获取信息。
【问题讨论】:
-
冒泡排序中的
points是什么?for (...)循环中不应该以“0”而不是“1”开头吗? -
这是 cavas 上的点列表(每个点都带有 x,y,z(0) 坐标)。角度列表是最大 Y 点与其他点之间的计算角度列表。当我对角度进行排序时,我也会对点列表进行排序,然后在格雷厄姆扫描开始之前用最大 Y 点和点 [最大 Y 点的索引)替换点 [0]。
-
查看 wikipedia 伪代码,我发现您使用的是 ccw>0 而不是 ccw
-
当 ccw == 0 时,while 循环不执行,这意味着该点保留在列表中并且是凸包的一部分。
-
让 points[M-1] 与 points[i] 处于相同的坐标。然后知道: ccw = ((vec2.X - vec1.X) * (vec3.Y - vec1.Y)) - ((vec2.Y - vec1.Y) * (vec3.X - vec1.X)) 有点[M-1]对应vec1,points[i]对应vec3。用 vec1 替换 vec3 我们得到: ccw = ((vec2.X - vec1.X) * (vec1.Y - vec1.Y)) - ((vec2.Y - vec1.Y) * (vec1.X - vec1.X )) 我们可以清楚地看到这将是 == 0。既然您确认如果 ccw == 0 点将保留在凸包中,那么这将使您的包的一部分成为两条完全重叠的线,除非我弄错了某处。
标签: c# wpf algorithm computational-geometry