最小外接矩形

  1. 得到凸包
    参考上篇文章
  2. 算法思路
    参考这篇文章,链接。依次计算相邻点角度,反向旋转所有凸包点集,计算最小外接正矩形以及面积。往复迭代所有凸包点,得到面积最小的解,反向旋转调整角度即可得到最终解。
    在这里插入图片描述
  3. 参考代码
public void MiniBoundingRect(List<MilPoint> Src, ref RectAngle rectAngle)
{
	double dArea = 0;
	MilPoint ptCnt = new MilPoint();
	CalBoundingRect(Src, ref rectAngle, ref dArea);
	rectAngle.ptCenter.CopyTo(ref ptCnt);

	for (int i = 0; i <= Src.Count; i++)
	{
		RectAngle rectAngleTmp = new RectAngle();
		double dArea_ = 0;
		List<MilPoint> ptsTmp = new List<MilPoint>();
		double angle = Math.Atan2(Src[i % (Src.Count - 1)].y - Src[(i + 1) % (Src.Count - 1)].y, Src[i % (Src.Count - 1)].x - Src[(i + 1) % (Src.Count - 1)].x);

		for (int j = 0; j < Src.Count; j++)
		{
			MilPoint ptTmp = new MilPoint();
			RotatePt(Src[j], ptCnt, ref ptTmp, angle);
			ptsTmp.Add(ptTmp);
		}

		CalBoundingRect(ptsTmp, ref rectAngleTmp, ref dArea_);

		if (dArea_ < dArea)
		{
			RotatePt(rectAngleTmp.ptCenter, ptCnt, ref rectAngle.ptCenter, angle * (-1));
			rectAngle.Width = rectAngleTmp.Width;
			rectAngle.Height = rectAngleTmp.Height;
			rectAngle.Angle = angle / Math.PI * 180 * (-1); // 这里乘-1是为了匹配外部算法角度正方向
			dArea = dArea_;
		}
	}
}

public double Cross(MilPoint a, MilPoint b, MilPoint c)//计算叉积
{
	return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
}

public double Dist(MilPoint a, MilPoint b)//计算距离
{
	return Math.Sqrt((a.x - b.x) * (a.x - b.x) * 1.0 + (a.y - b.y) * (a.y - b.y));
}

public void RotatePt(MilPoint nodeSrc, MilPoint nodeCent, ref MilPoint nodeOut, double dangle)
{
	double dX = nodeSrc.x - nodeCent.x;
	double dY = nodeSrc.y - nodeCent.y;
	double dSin = Math.Sin(dangle);
	double dCos = Math.Cos(dangle);

	nodeOut.x = dCos * dX + dSin * dY + nodeCent.x;
	nodeOut.y = dCos * dY - dSin * dX + nodeCent.y;
}

public void CalBoundingRect(List<MilPoint> nodes, ref RectAngle rectAngle, ref double dArea)
{
	MilPoint nodeOutTL = new MilPoint();
	MilPoint nodeOutBR = new MilPoint();

	nodeOutTL.x = nodes[0].x;
	nodeOutTL.y = nodes[0].y;
	nodeOutBR.x = nodes[0].x;
	nodeOutBR.y = nodes[0].y;
	for (int i = 0; i < nodes.Count; i++)
	{
	if (nodes[i].x < nodeOutTL.x)
		nodeOutTL.x = nodes[i].x;
	if (nodes[i].y < nodeOutTL.y)
		nodeOutTL.y = nodes[i].y;

	if (nodes[i].x > nodeOutBR.x)
		nodeOutBR.x = nodes[i].x;
	if (nodes[i].y > nodeOutBR.y)
		nodeOutBR.y = nodes[i].y;
	}
	rectAngle.ptCenter.x = (nodeOutBR.x + nodeOutTL.x) / 2;
	rectAngle.ptCenter.y = (nodeOutBR.y + nodeOutTL.y) / 2;
	rectAngle.Width = Math.Abs(nodeOutBR.x - nodeOutTL.x);
	rectAngle.Height = Math.Abs(nodeOutBR.y - nodeOutTL.y);
	rectAngle.Angle = 0;
	dArea = rectAngle.Width * rectAngle.Height;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值