最小包络矩形的算法和代码
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TPolyVertex = record //浮点型顶点定义
X: Double;
Y: Double
end;
TMinRect = record //矩形记录
p1: TPolyVertex;
p2: TPolyVertex;
p3: TPolyVertex;
p4: TPolyVertex;
Size: Double;
Degree: Double;
end;
TPolyArray = array of TPolyVertex; //多边型浮点数组类型
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1 : TForm1;
RandomPoly : TPolyArray;
implementation
{$R *.dfm}
procedure PloyRotate(var SrcPoly, DstPoly: TPolyArray; Value: Double);
var
I, H : Integer;
CosV, SinV : Double; //旋转变换
begin
H := High(SrcPoly);
SetLength(DstPoly, H + 1);
CosV := Cos(Value); SinV := Sin(Value);
for I := 0 to H do
begin
DstPoly[I].X := SrcPoly[I].X * CosV - SrcPoly[I].Y * SinV;
DstPoly[I].Y := SrcPoly[I].X * SinV + SrcPoly[I].Y * CosV;
end;
end;
function BuildMinRect(Poly: TPolyArray): TMinRect; //求最小水平包含矩形
var
I : Integer;
HMin, HMax, VMin, VMax : Double;
begin
HMin := 999999999999; HMax := -999999999999;
VMin := 999999999999; VMax := -999999999999;
for I := 0 to High(Poly) do
begin
if Poly[I].X < HMin then HMin := Poly[I].X;
if Poly[I].X > HMax then HMax := Poly[I].X;
if Poly[I].Y < VMin then VMin := Poly[I].Y;
if Poly[I].Y > VMax then VMax := Poly[I].Y;
end;
Result.p1.X := HMin; Result.p1.Y := VMin;
Result.p2.X := HMax; Result.p2.Y := VMin;
Result.p3.X := HMax; Result.p3.Y := VMax;
Result.p4.X := HMin; Result.p4.Y := VMax;
Result.Size := ((HMax - HMin) * (VMax - VMin));
end;
procedure TForm1.Button1Click(Sender: TObject);
var
TempPoly : TPolyArray;
I, J : Integer;
SizeMin, Step, Degree : Double;
ARect, MinRect : TMinRect;
RectPoly : TPolyArray;
begin
J := Random(10) + 3;
RandSeed := GetTickCount;
SetLength(RandomPoly, J);
for I := 0 to J - 1 do //随机的多边形生成
begin
RandomPoly[I].X := Random(300) + 100;
RandomPoly[I].Y := Random(300) + 50;
end;
Degree := 0;
Step := PI / 720; //精确度
SizeMin := 9999999999999999;
while Degree < PI do //角度递增旋转
begin
PloyRotate(RandomPoly, TempPoly, Degree); //变换
ARect := BuildMinRect(TempPoly); //求水平包含矩形
if ARect.Size < SizeMin then
begin
SizeMin := ARect.Size; //记录最小面积的包含矩形
MinRect := ARect;
MinRect.Degree := Degree;
end;
Degree := Degree + Step;
end;
SetLength(TempPoly, 4);
TempPoly[0] := MinRect.p1; TempPoly[1] := MinRect.p2;
TempPoly[2] := MinRect.p3; TempPoly[3] := MinRect.p4;
PloyRotate(TempPoly, RectPoly, -MinRect.Degree); //反向变换结果矩形
Canvas.Brush.Color := Clwhite;
Canvas.Rectangle(Canvas.Cliprect); //清除原内容
Canvas.Pen.Color := ClBlue; //画多边形
Canvas.Moveto(Round(RandomPoly[0].X), Round(RandomPoly[0].Y));
for I := 1 to J - 1 do
Canvas.Lineto(Round(RandomPoly[I].X), Round(RandomPoly[I].Y));
Canvas.Lineto(Round(RandomPoly[0].X), Round(RandomPoly[0].Y));
Canvas.Pen.Color := ClRed; //画包含矩形
Canvas.Moveto(Round(RectPoly[0].X), Round(RectPoly[0].Y));
for I := 1 to 3 do
Canvas.Lineto(Round(RectPoly[I].X), Round(RectPoly[I].Y));
Canvas.Lineto(Round(RectPoly[0].X), Round(RectPoly[0].Y));
while Degree < PI do //角度递增旋转
begin
PloyRotate(RandomPoly, TempPoly, Degree); //变换
ARect := BuildMinRect(TempPoly); //求水平包含矩形
if ARect.Size < SizeMin then
begin
SizeMin := ARect.Size; //记录最小面积的包含矩形
MinRect := ARect;
MinRect.Degree := Degree;
end;
Degree := Degree + Step;
end;
SetLength(TempPoly, 4);
TempPoly[0] := MinRect.p1;
TempPoly[1] := MinRect.p2;
TempPoly[2] := MinRect.p3;
TempPoly[3] := MinRect.p4;
PloyRotate(TempPoly, RectPoly, -MinRect.Degree); //反向变换结果矩形
Canvas.Brush.Color := Clwhite;
Canvas.Rectangle(Canvas.Cliprect); //清除原内容
Canvas.Pen.Color := ClBlue; //画多边形
Canvas.Moveto(Round(RandomPoly[0].X), Round(RandomPoly[0].Y));
for I := 1 to J - 1 do
Canvas.Lineto(Round(RandomPoly[I].X), Round(RandomPoly[I].Y));
Canvas.Lineto(Round(RandomPoly[0].X), Round(RandomPoly[0].Y));
Canvas.Pen.Color := ClRed; //画包含矩形
Canvas.Moveto(Round(RectPoly[0].X), Round(RectPoly[0].Y));
for I := 1 to 3 do
Canvas.Lineto(Round(RectPoly[I].X), Round(RectPoly[I].Y));
Canvas.Lineto(Round(RectPoly[0].X), Round(RectPoly[0].Y));
end;
end.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理