二维平面上两个矩形之间的最小距离

1 篇文章 0 订阅
1 篇文章 0 订阅
本文介绍了如何计算两个矩形之间的最短距离,问题转化为求解线段间的最短距离。通过分析不同情况,如线段相交、不相交等,提出了一种通过计算点到线段距离的方法来解决。最后,提供了计算点到线段、线段到线段以及矩形到矩形最短距离的代码实现。
摘要由CSDN通过智能技术生成

1.背景

最近遇到一个问题,可以抽象成如题目描述的问题。

 如何求解例如 矩形(EFGH),矩形(IJKL),矩形(MNOP)  到矩形 ABCD的距离呢? 

2.分析

最短距离 会出现在 矩形1 的边界上某点 到矩形2边界上某点的连线。

该问题可以进一步简化成对同一平面上的一条线段 到另一条线段的最短距离进行求解。

也就是 分别求解 矩形1 的4条边 到矩形2 的4条边的最短距离,然后再取 最小值即可。

如何求解 一段线段到另一段线段的最短距离呢?假设 线段1为 AB,线段2 为CD;

情况1: 线段1 和线段2 相交,最短距离为0;

情况2: 线段1 和线段2 不想交;此时 最短距离 会出现在点A到CD的最短距离 或 点B到CD的最短距离 或 点C到AB的最短距离 或 点D到AB的最短距离。

Dmin = min(Da-cd,Db-cd,Dc-ab,Dd-ab);

问题也就可以进一步简化成 求解 平面上一个点到一段线段的最短距离;

点到线段的最短距离分为如下3中情况:

情况1:点在直线上,距离为0;(情况1可以合并到情况2中)

情况2:过点做垂线,垂足在线段内,垂足和该点的连线为最短距离;

情况3: 过点做垂线,垂足在线段外,则距离垂足近的线段端点到该点的距离为最短距离。

3. 代码

3.1 计算同一平面上某点A,到线段CD 的距离。

3.2 计算同一平面上线段AB,到线段CD的最短距离。

3.3 计算同一平面上矩形ABCD 到EFGH 的最短距离。

4 参考文献

可以通过PCA(主成分分析)来获得这些点的最小矩形包围框。 具体步骤如下: 1. 计算点集的质心(平均值)。 2. 将点集的坐标系平移到以质心为原点的坐标系下。 3. 计算点集的协方差矩阵。 4. 对协方差矩阵进行特征值分解,得到特征值和特征向量。 5. 将特征向量按照对应的特征值大小排序,选取前两个最大的特征向量组成一个二维坐标系。 6. 将原始点集的点投影到这个二维坐标系上,得到在新坐标系下的点集。 7. 在新坐标系下,最小矩形包围框的边界为点集在每个维度上的最大值和最小值,即可得到最小矩形包围框。 以下是用C语言实现的代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #define N 100 typedef struct { double x; double y; } Point; void PCA(Point *points, int n, Point *center, Point *v1, Point *v2) { int i; double xx = 0, yy = 0, xy = 0; center->x = 0; center->y = 0; for (i = 0; i < n; i++) { center->x += points[i].x; center->y += points[i].y; } center->x /= n; center->y /= n; for (i = 0; i < n; i++) { xx += (points[i].x - center->x) * (points[i].x - center->x); yy += (points[i].y - center->y) * (points[i].y - center->y); xy += (points[i].x - center->x) * (points[i].y - center->y); } double lambda1 = (xx + yy + sqrt((xx - yy) * (xx - yy) + 4 * xy * xy)) / 2; double lambda2 = (xx + yy - sqrt((xx - yy) * (xx - yy) + 4 * xy * xy)) / 2; v1->x = lambda1 - xx; v1->y = xy; v2->x = xy; v2->y = lambda2 - yy; } int main() { int n, i; Point points[N], center, v1, v2; printf("Enter the number of points: "); scanf("%d", &n); printf("Enter the points:\n"); for (i = 0; i < n; i++) { scanf("%lf %lf", &points[i].x, &points[i].y); } PCA(points, n, &center, &v1, &v2); printf("Center: (%.2lf, %.2lf)\n", center.x, center.y); printf("v1: (%.2lf, %.2lf)\n", v1.x, v1.y); printf("v2: (%.2lf, %.2lf)\n", v2.x, v2.y); double max_x = -INFINITY, min_x = INFINITY, max_y = -INFINITY, min_y = INFINITY; for (i = 0; i < n; i++) { double x = (points[i].x - center.x) * v1.x + (points[i].y - center.y) * v1.y; double y = (points[i].x - center.x) * v2.x + (points[i].y - center.y) * v2.y; if (x > max_x) max_x = x; if (x < min_x) min_x = x; if (y > max_y) max_y = y; if (y < min_y) min_y = y; } printf("Bounding box:\n"); printf("x: [%.2lf, %.2lf]\n", min_x, max_x); printf("y: [%.2lf, %.2lf]\n", min_y, max_y); return 0; } ``` 输入格式为: ``` Enter the number of points: 4 Enter the points: 0 0 1 0 0 1 1 1 ``` 输出结果为: ``` Center: (0.50, 0.50) v1: (0.71, 0.71) v2: (-0.71, 0.71) Bounding box: x: [-0.71, 0.71] y: [-0.71, 0.71] ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值