c#凸多边形算法学习
#region 凸多边形选择
/**********************************************
寻找凸包的graham 扫描法
PointFSet为输入的点集;
ch为输出的凸包上的点集,按照逆时针方向排列;
n为PointFSet中的点的数目
len为输出的凸包上的点的个数
**********************************************/
const double INF=1E200;
const double EP=1E-10;
// 返回两点之间欧氏距离
public double distance(PointF p1, PointF p2)
{
return Math.Sqrt( (p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
}
/******************************************************************************
r=multiplY(sp,ep,op),得到(sp-op)*(ep-op)的叉积
r>0:ep在矢量opsp的逆时针方向;
r=0:opspep三点共线;
r<0:ep在矢量opsp的顺时针方向
*******************************************************************************/
//叉积就是2向量形成的平行四边形的面积
public double multiplY(PointF sp,PointF ep,PointF op)
{
return((sp.X-op.X)*(ep.Y-op.Y)-(ep.X-op.X)*(sp.Y-op.Y));
}
bool cmp(PointF[] points, PointF a, PointF b)
{
// 如果三点在同一直线上,那么按相对于points[0]由近到远排序
if (multiplY(points[0], a, b) == 0) return distance(points[0], a) < distance(points[0], b);
//如果三点不在同一直线上,那么a在b->points[0]的左侧,也就是从下向上,从右向左排序
//按极角有小到大排序。
else return multiplY(points[0], a, b) > 0;
}
/// <summary>
///
/// </summary>
/// <param name="a"></param>
/// <param name="p"></param>
/// <param name="r"></param>
/// <returns></returns>
public int partition(PointF[] a, int p, int r)
{
int i=p,j=r+1,k;
double ang,dis;
PointF R,S;
k=(p+r)/2;//防止快排退化
R=a[p];
a[p]=a[k];
a[k]=R;
R=a[p];
dis=distance(R,a[0]);
while(true)
{
while(true)
{
++i;
if(i>r)
{
i=r;
break;
}
ang=multiplY(R,a[i],a[0]);
if(ang>0)
break;
else if(ang==0)
{
if(distance(a[i],a[0])>dis)
break;
}
}
while(true)
{
--j;
if(j<p)
{
j=p;
break;
}
ang=multiplY(R,a[j],a[0]);
if(ang<0)
break;
else if(ang==0)
{
if(distance(a[j],a[0])<dis)
break;
}
}
if(i>=j)break;
S=a[i];
a[i]=a[j];
a[j]=S;
}
a[p]=a[j];
a[j]=R;
return j;
}
/// <summary>
/// 按角度排序
/// </summary>
/// <param name="a"></param>
/// <param name="p"></param>
/// <param name="r"></param>
public void anglesort(PointF[] a,int p,int r)
{
if(p<r)
{
int q=partition(a,p,r);
anglesort(a,p,q-1);
anglesort(a,q+1,r);
}
}
/// <summary>
/// Graham_scan
/// </summary>
/// <param name="PointFSet"></param>
/// <param name="n"></param>
/// <returns></returns>
public PointF[] Graham_scan(PointF[] PointFSet,int n)
{
PointF[] ch = new PointF[n];
int len;
int i,k=0,top=2;
PointF tmp;
// 选取PointFSet中Y坐标最小的点PointFSet[k],如果这样的点有多个,则取最左边的一个
for (i = 1; i < n; i++)
{
if (PointFSet[i].Y < PointFSet[k].Y || (PointFSet[i].Y == PointFSet[k].Y) && (PointFSet[i].X < PointFSet[k].X))
{
k = i;
}
}
tmp=PointFSet[0];
PointFSet[0]=PointFSet[k];
PointFSet[k]=tmp; // 现在PointFSet中Y坐标最小的点在PointFSet[0]
/* 对顶点按照相对PointFSet[0]的极角从小到大进行排序,极角相同
的按照距离PointFSet[0]从近到远进行排序 */
anglesort(PointFSet,1,n-1);
ch[0]=PointFSet[0];
ch[1]=PointFSet[1];
ch[2]=PointFSet[2];
for (i=3;i<n;i++)
{
while (multiplY(PointFSet[i],ch[top],ch[top-1])>0) top--;
ch[++top]=PointFSet[i];
}
len=top+1;
PointF[] temp = new PointF[len];
for (int j = 0; j < len; j++)
{
temp[j] = ch[j];
}
return temp;
}
#endregion 凸多边形选择
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· Open-Sora 2.0 重磅开源!