如何计算圆弧的外接矩形

我们要计算一段圆弧的外接矩形,肯定起码知道了这段圆弧的数据,比如圆心,半径,起始点(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种情况,这里就不再一一赘述了

C#中,求解圆弧的最小外接矩形通常涉及到几何计算。给定一个圆弧,我们需要确定这个圆弧所在的圆的中心点、半径以及圆弧起点和终点的角度。假设已知圆心坐标(x0, y0),半径r,以及圆弧上两个端点的角度(θ1, θ2) (以弧度表示),可以按照以下步骤找到最小外接矩形: 1. **确定圆弧的边界**: - 计算两个端点的直角坐标(x1, y1), (x2, y2),使用公式 `x = x0 + r * cos(θ)` 和 `y = y0 + r * sin(θ)`。 2. **求解矩形的边长**: - 矩形的一条边将通过圆心并与圆弧垂直,这条边的长度等于圆心到任意一点的水平距离加上圆的直径,即 `d = abs(x1 - x0) + 2 * r`。 - 另一条对角线长度等于圆的直径 `l = 2 * r`。 3. **计算旋转角度**: - 为了得到最小的矩形,我们希望矩形的宽和高尽量接近。因此,如果`d > l`,则旋转90度,使得长边变为宽边,宽边变为原来直径的长度。 4. **构造矩形**: - 最终矩形的位置基于圆心,宽和高分别由`d`和`l`确定。如果需要,你可以进一步调整矩形的位置使其落在坐标轴上,以便于后续操作。 下面是伪代码形式的示例: ```csharp public Point[] GetMinimumBoundingRectangle(Point center, double radius, double startAngle, double endAngle) { // ...上述计算过程... if (d > l) { double temp = d; d = l; l = temp; // 旋转90度 center = new Point(center.Y, center.X); } return new Point[] { new Point(center.X - l / 2, center.Y - d / 2), new Point(center.X + l / 2, center.Y - d / 2), new Point(center.X + l / 2, center.Y + d / 2), new Point(center.X - l / 2, center.Y + d / 2)}; } // 使用 Point[] rectanglePoints = GetMinimumBoundingRectangle(new Point(0, 0), 5, Math.PI / 4, 3 * Math.PI / 4); ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值