凸包的c#实现算法
前段时间看到生成凸包的Graham算法,查了一些资料,没看到c#版的,于是想动手写一个,该程序草草完成,其中有值得优化的地方,诸位可自行改正。
Graham算法的原理:
(1)给定一个点集P={P0,P1,.....Pn),找出点集中Y值最小的点,如果Y值最小的点有多个,可选择其中X值最小的 www.zzzyk.com
(2)假设上一步找出的点位P0,现在对剩下的点进行极角排序,按逆时针(本程序是这样,其他的方式是一样的)极角从小到大排序,假定排序结果集为{p1,p2,p3,p4,....pn}。注意,这里不一定有N个点,因为可能存在几个点的极角相同,这时取据P0距最远的点,也或者你设定了一个极角阈值,当两个点的极角差小于该阈值时,取据P0距离远的点,这时生成的凸包有一点点误差,误差的大小取决于你设置的阈值。本程序没采用阈值,所以生成的凸包理论上不存在误差。
在进行极角排序时,不需要真的算法每个点的极角(注意,这里的极角是该点与P0相对于X轴的夹角),只需要使用向量叉积来判断即可,这个过程我使用了链表来存储排序结果,因为这个过程会进行频繁的插入。
(3)将p0,p1,p3入栈,p0,p1这两个点肯定在凸包上(原因很简单,p0不用解释了吧,p1因为它是极角最小的且为第一个点),p2则不一定在凸包上,然后进行循环(for(int i=2;i<n;i++),判定栈顶的下一个点,栈顶点,及p[i]点这三点组成的折线段是否向左转,如果是的话,则p[i]入栈;否则,当前位于栈顶的点不在凸包上,弹栈(该过程进行回朔,确保之前的所有点转向正确,这个步骤很重要,不然不能生成凸多边形),最后返回栈即可。
下面是整个代码:
算法部分:
class ConvexAogrithm
{
private List<PointF> nodes;
private Stack<PointF> sortedNodes;
public PointF[] sor_nodes;
public ConvexAogrithm(List<PointF> points)
{
nodes = points;
}
private double DistanceOfNodes(PointF p0, PointF p1)
{
if (p0.IsEmpty || p1.IsEmpty)
return 0.0;
return Math.Sqrt((p1.X - p0.X) * (p1.X - p0.X) + (p1.Y - p0.Y) * (p1.Y - p0.Y));
}
public void GetNodesByAngle( out PointF p0)
{
LinkedList<PointF> list_node = new LinkedList<PointF>();
p0 = GetMinYPoint();
LinkedListNode<PointF> node = new LinkedListNode<PointF>(nodes[0]);
list_node.AddFirst(node);
for (int i = 1; i < nodes.Count; i++)
{
int direct = IsClockDirection(p0, node.Value, nodes[i]);
if (direct == 1)
{
list_node.AddLast(nodes[i]);
node = list_node.Last;
//node.Value = nodes[i];
}
else if (direct == -10)
{
list_node.Last.Value = nodes[i];
//node = list_node.Last
//node.Value = nodes[i];
}
else if (direct == 10)
continue;
else if (direct == -1)
{
LinkedListNode<PointF> temp = node.Previous;
while (temp != null && IsClockDirection(p0, temp.Value, nodes[i]) == -1)
{
temp = temp.Previous;
}
补充:软件开发 , C# ,