uva10173Smallest Bounding Rectangle (旋转卡壳之最小矩形)

本文详细介绍了如何通过使用点积和叉积来解决凸包问题,并利用这些方法计算最小外接矩形的面积。包括Graham扫描算法的实现和最小外接矩形面积的计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=13&problem=1114&mosmsg=Submission+received+with+ID+10328241


在求卡壳时,之前还傻傻地求出了矩形角落的三个点,而想以长乘心宽的方式求面积,后来发现这个挺麻烦的,而且矩形的点可能会在凸包的点上,还得延长出去。。。 搞了一阵子就没搞头了。。


求卡壳步骤可参考:http://cgm.cs.mcgill.ca/~orm/rotcal.html英文的解说。


最终以点积求长,叉积求宽的方式解决。。。


代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<math.h>
#define eps 1e-8
#define inf 1e10
#define maxn 1020
struct point{double x,y;}points[maxn],p[maxn];
int n;
double xmult(point p1,point p2,point p0)
{
	return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
bool cmp(const point &a,const point &b)
{
	if(a.y==b.y)return a.x<b.x;
	return a.y<b.y;
}

int Graham()
{
	std::sort(points,points+n,cmp);
	int i;
	p[0]=points[0];
	p[1]=points[1];
	int top=1;
	for(i=2;i<n;i++)
	{
		while(top&&xmult(p[top],points[i],p[top-1])>=0)top--;
		p[++top]=points[i];
	}
	int mid=top;
	for(i=n-2;i>=0;i--)
	{
		while(top>mid&&xmult(p[top],points[i],p[top-1])>=0)top--;
		p[++top]=points[i];
	}
	return top;
}
double min(double a,double b)
{
	return a>b? b: a;
}
double dmult(point p1,point p2,point p0)
{
	return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);
}
double distance(point p1,point p2)
{
	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
double rc_minarea()//×?D???D????y
{
	if(n<3)return 0;
	int minx=0,maxx=0,miny=0,maxy=0;
	int i;
	p[n]=p[0];p[n+1]=p[1];p[n+2]=p[2];
	for(i=1;i<n;i++)
	{
		if(p[minx].x>p[i].x||p[minx].x==p[i].x&&p[i].y<p[minx].y)minx=i;
		if(p[miny].y>p[i].y||p[miny].y==p[i].y&&p[i].x<p[miny].x)miny=i;
		if(p[maxx].x<p[i].x||p[maxx].x==p[i].x&&p[i].y>p[maxx].y)maxx=i;
		if(p[maxy].y<p[i].y||p[maxy].y==p[i].y&&p[i].x>p[maxy].x)maxy=i;
	}
	int l=minx,r=maxx,t=maxy,b=miny;
	double minn=(p[r].x-p[l].x)*(p[t].y-p[b].y);
	double  dl,dr,dt;
	for(i=0;i<n;i++)
	{
		while(dmult(p[r+1],p[i],p[i+1])-(dl=dmult(p[r],p[i],p[i+1]))>eps)
			r=(r+1)%n;
		while(dmult(p[l+1],p[i+1],p[i])-(dr=dmult(p[l],p[i+1],p[i]))>eps)
			l=(l+1)%n;
		while(xmult(p[t+1],p[i+1],p[i])-(dt=xmult(p[t],p[i+1],p[i]))>eps)
			t=(t+1)%n;
		double dis=distance(p[i],p[i+1]);
		minn=min(minn,dt/dis*(dl/dis+dr/dis-dis));
	}
	return minn;
}
int main()
{
	while(scanf("%d",&n),n)
	{
		int i;
		for(i=0;i<n;i++)
			scanf("%lf%lf",&points[i].x,&points[i].y);
		n=Graham();
		printf("%.4lf\n",rc_minarea());
	}
	return 0;
}


在Helicon AI (一种计算机视觉库) 中,`smallest_rectangle2` 算子通常用于找到图像区域内的最小边界框,即最小外接矩形。如果返回的矩形是斜的,说明原始目标不是正方形或者长宽比偏离了正常水平方向。为了将斜的外接矩形变回接近水平的方向,可以采取以下几个步骤: 1. **旋转坐标系**:首先,你需要确定矩形的中心点和角度。使用类似 `get_rotation_matrix` 的函数,根据角度旋转坐标轴,使得新的X轴尽量平行于原始矩形较长的那一边。 ```python import cv2 import numpy as np angle = calculate_angle(rect) rotation_matrix = get_rotation_matrix(angle) # Apply the rotation to your image or points if necessary rotated_points = apply_rotation(points, rotation_matrix) ``` 这里的 `calculate_angle`, `get_rotation_matrix`, 和 `apply_rotation` 需要你自己实现或者参考相关库提供的功能。 2. **计算新的尺寸**:应用旋转后,你可以计算新矩形的新宽度和高度,取两者中的较大值作为新的宽度,较小值作为高度,确保变为更接近水平的样子。 3. **调整矩形大小**:基于新的宽度和高度创建一个新的矩形,其位置保持不变,即保持原来矩形的左上角坐标。 4. **重新调整坐标**:如果需要,还需要对点集或像素数据进行相应的旋转,以便适应新的矩形。 5. **使用smallest_rectangle2或其他算子**:现在你应该有一个更接近水平的矩形,可以用`smallest_rectangle2` 或者其他边界框算子,如`minAreaRect` 或 `fitEllipse` 来确认新的边界框。 ```python new_rect = smallest_rectangle2(rotated_points) ``` 记得在每个步骤后检查结果的合理性,并根据实际需求进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值