我们要计算一段圆弧的外接矩形,肯定起码知道了这段圆弧的数据,比如圆心,半径,起始点(StartPoint),结束点(EndPoint),起始角度(StartAngle),夹角(SweepAngle),结束角度(EndAngle)等
1.我的思路是以圆心为坐标原点,构建坐标轴,判断这段圆弧和那个轴有交点,那么这就是外接矩形的一个边界值了
比如下面这个圆弧,我以圆心为坐标轴原点,建立坐标系,那么矩形的最上边和最右边的值就可以确定了
然后通过创建一个List,默认情况将起始点,结束点的坐标传入
List<PointF> corners = new()
{
new PointF(StartPoint),
new PointF(EndPoint)
};
图中这种情况呢,再添加右和上两个点的坐标
//右,上
corners.Add(new PointF((float)(Center.X + Radius), (float)Center.Y));
corners.Add(new PointF((float)Center.X, (float)(Center.Y + Radius)));
最后呢,可通过
方式一:遍历List,获取最大最小值来构建外接矩形。
方式二:
// 初始化最大最小值
float minX = float.MaxValue;
float minY = float.MaxValue;
float maxX = float.MinValue;
float maxY = float.MinValue;
if (corners.Count > 0)
{
minX = corners.Min(p => p.X);
minY = corners.Min(p => p.Y);
maxX = corners.Max(p => p.X);
maxY = corners.Max(p => p.Y);
}
return new RectangleF(minX, minY, maxX - minX, maxY - minY);
2.那么问题的关键就变成了如何确定圆弧和哪个轴有交点的问题了,这个时候就必须根据圆弧的角度参数来确定了
我是将坐标系平移和反转了,所以我的坐标系是这样,逆时针为正。
接下来我们要判断,起始角和结束角的关系,就可以确定圆弧跨那个象限了,就能知道和那个轴有交点
//这里是考虑到夹角是有正负的,即圆弧也是有方向(我的逆时针为正)
double endAngle;
if (SweepAngle > 0)
{
//夹角为正,计算结束角,并确保夹角在0-360之间
endAngle = (StartAngle + SweepAngle) % 360;
}
else
{
//夹角为负,计算结束角,并确保夹角在0-360之间
endAngle = (StartAngle + (360 - Math.Abs(SweepAngle))) % 360;
}
接下来我只讲一下夹角为正的情况(逆时针方向)。
//情况一:StartAngle在第一象限时,分为4种情况分类讨论
if (StartAngle >= 0 && StartAngle <= 90)
{
//1.结束角在第二象限,我们在添加起始点,结束点的基础上,再添加最上面的点即可
if (endAngle < 180 && endAngle >= 90)
{
//上
corners.Add(new PointF((float)Center.X, (float)(Center.Y + Radius)));
}
//2.结束角在第三象限,再添加上和左即可
else if (endAngle < 270 && endAngle >= 180)
{
//上,左
corners.Add(new PointF((float)Center.X, (float)(Center.Y + Radius)));
corners.Add(new PointF((float)(Center.X - Radius), (float)Center.Y));
}
//3.结束角在第四象限,再添加上,左,下即可
else if (endAngle < 360 && endAngle >= 270)
{
//上,左,下
corners.Add(new PointF((float)Center.X, (float)(Center.Y + Radius)));
corners.Add(new PointF((float)(Center.X - Radius), (float)Center.Y));
corners.Add(new PointF((float)Center.X, (float)(Center.Y - Radius)));
}
//4.结束角在第一象限,这时还得注意
//如果起始角小于结束角,说明圆弧只存在于第一象限,那就不用再添加了,两个点就可以确定外接矩形大小了;
//如果起始角大于结束角,说明这条弧跨越了1234象限,又回到了第一象限,已经快接近整圆了,这时就要将上下左右四个边界值全部添加进去
if (StartAngle > endAngle)
{
if (endAngle > 0 && endAngle < 90)
{
//下,右,上,左
corners.Add(new PointF((float)Center.X, (float)(Center.Y - Radius)));
corners.Add(new PointF((float)(Center.X + Radius), (float)Center.Y));
corners.Add(new PointF((float)Center.X, (float)(Center.Y + Radius)));
corners.Add(new PointF((float)(Center.X - Radius), (float)Center.Y));
}
}
然而这只是夹角为正时,所以夹角的正负需要为2种情况来讨论
因此在夹角为正时,起始角有会4种情况
在每一种起始角之中,又分了4种结束角的情况。
因此一共有2*4*4=32种情况,这里就不再一一赘述了