`

点集的最小面积包围矩形

阅读更多

typedef double typev;
const double eps = 1e-8;
const int N = 50005;
int sign(double d){
    return d < -eps ? -1 : (d > eps);
}
struct point{
    typev x, y;
    point operator-(point d){
        point dd;
        dd.x = this->x - d.x;
        dd.y = this->y - d.y;
        return dd;
    }
    point operator+(point d){
        point dd;
        dd.x = this->x + d.x;
        dd.y = this->y + d.y;
        return dd;
    }
    void read(){ scanf("%lf%lf", &x, &y); }
}ps[N];
int n, cn;
double dist(point d1, point d2){
    return sqrt(pow(d1.x - d2.x, 2.0) + pow(d1.y - d2.y, 2.0));
}
double dist2(point d1, point d2){
    return pow(d1.x - d2.x, 2.0) + pow(d1.y - d2.y, 2.0);
}
bool cmp(point d1, point d2){
    return d1.y < d2.y || (d1.y == d2.y && d1.x < d2.x);
}
//st1-->ed1叉乘st2-->ed2的值
typev xmul(point st1, point ed1, point st2, point ed2){
    return (ed1.x - st1.x) * (ed2.y - st2.y) - (ed1.y - st1.y) * (ed2.x - st2.x);
}
typev dmul(point st1, point ed1, point st2, point ed2){
    return (ed1.x - st1.x) * (ed2.x - st2.x) + (ed1.y - st1.y) * (ed2.y - st2.y);
}
//多边形类
struct poly{
    static const int N = 50005; //点数的最大值
    point ps[N+5]; //逆时针存储多边形的点,[0,pn-1]存储点
    int pn;  //点数
    poly() { pn = 0; }
    //加进一个点
    void push(point tp){
        ps[pn++] = tp;
    }
    //第k个位置
    int trim(int k){
        return (k+pn)%pn;
    }
    void clear(){ pn = 0; }
};
//返回含有n个点的点集ps的凸包
poly graham(point* ps, int n){
    sort(ps, ps + n, cmp);
    poly ans;
    if(n <= 2){
        for(int i = 0; i < n; i++){
            ans.push(ps[i]);
        }
        return ans;
    }
    ans.push(ps[0]);
    ans.push(ps[1]);
    point* tps = ans.ps;
    int top = -1;
    tps[++top] = ps[0];
    tps[++top] = ps[1];
    for(int i = 2; i < n; i++){
        while(top > 0 && xmul(tps[top - 1], tps[top], tps[top - 1], ps[i]) <= 0) top--;
        tps[++top] = ps[i];
    }
    int tmp = top;  //注意要赋值给tmp!
    for(int i = n - 2; i >= 0; i--){
        while(top > tmp && xmul(tps[top - 1], tps[top], tps[top - 1], ps[i]) <= 0) top--;
        tps[++top] = ps[i];
    }
    ans.pn = top;
    return ans;
}
//求点p到st->ed的垂足,列参数方程
point getRoot(point p, point st, point ed){
    point ans;
    double u=((ed.x-st.x)*(ed.x-st.x)+(ed.y-st.y)*(ed.y-st.y));
    u = ((ed.x-st.x)*(ed.x-p.x)+(ed.y-st.y)*(ed.y-p.y))/u;
    ans.x = u*st.x+(1-u)*ed.x;
    ans.y = u*st.y+(1-u)*ed.y;
    return ans;
}
//next为直线(st,ed)上的点,返回next沿(st,ed)右手垂直方向延伸l之后的点
point change(point st, point ed, point next, double l){
    point dd;
    dd.x = -(ed - st).y;
    dd.y = (ed - st).x;
    double len = sqrt(dd.x * dd.x + dd.y * dd.y);
    dd.x /= len, dd.y /= len;
    dd.x *= l, dd.y *= l;
    dd = dd + next;
    return dd;
}
//求含n个点的点集ps的最小面积矩形,并把结果放在ds(ds为一个长度是4的数组即可,ds中的点是逆时针的)中,并返回这个最小面积。
double getMinAreaRect(point* ps, int n, point* ds){
    int cn, i;
    double ans;
    point* con;
    poly tpoly = graham(ps, n);
    con = tpoly.ps;
    cn = tpoly.pn;
    if(cn <= 2){
        ds[0] = con[0]; ds[1] = con[1];
        ds[2] = con[1]; ds[3] = con[0];
        ans=0;
    }else{
        int  l, r, u;
        double tmp, len;
        con[cn] = con[0];
        ans = 1e40;
        l = i = 0;
        while(dmul(con[i], con[i+1], con[i], con[l])
            >= dmul(con[i], con[i+1], con[i], con[(l-1+cn)%cn])){
                l = (l-1+cn)%cn;
        }
        for(r=u=i = 0; i < cn; i++){
            while(xmul(con[i], con[i+1], con[i], con[u])
                <= xmul(con[i], con[i+1], con[i], con[(u+1)%cn])){
                    u = (u+1)%cn;
            }
            while(dmul(con[i], con[i+1], con[i], con[r])
                <= dmul(con[i], con[i+1], con[i], con[(r+1)%cn])){
                    r = (r+1)%cn;
            }
            while(dmul(con[i], con[i+1], con[i], con[l])
                >= dmul(con[i], con[i+1], con[i], con[(l+1)%cn])){
                    l = (l+1)%cn;
            }
            tmp = dmul(con[i], con[i+1], con[i], con[r]) - dmul(con[i], con[i+1], con[i], con[l]);
            tmp *= xmul(con[i], con[i+1], con[i], con[u]);
            tmp /= dist2(con[i], con[i+1]);
            len = xmul(con[i], con[i+1], con[i], con[u])/dist(con[i], con[i+1]);
            if(sign(tmp - ans) < 0){
                ans = tmp;
                ds[0] = getRoot(con[l], con[i], con[i+1]);
                ds[1] = getRoot(con[r], con[i+1], con[i]);
                ds[2] = change(con[i], con[i+1], ds[1], len);
                ds[3] = change(con[i], con[i+1], ds[0], len);
            }
        }
    }
    return ans+eps;
}
 
0
0
分享到:
评论

相关推荐

    C#求点集的最小包围矩形

    C# 求点集的最小包围矩形,供大家参考,具体内容如下 思路: 1、求点集的中心点 2、将点集绕矩形进行一系列角度的旋转,并求记录旋转点集的包围矩形的面积和旋转角度; 3、将面积最小的矩形绕点集中心点旋转回去。 ...

    凸多边形最小面积四边形包围盒算法

    例如,在机器人路径规划中,最小包围盒可以帮助机器人高效地避免障碍物;在计算机图形学中,用于优化渲染过程,减少不必要的计算量;在地理信息系统中,用于快速检索空间数据。 #### 二、凸多边形最小面积四边形...

    最小外接矩形

    在计算机科学和图形学中,"最小外接矩形"(Minimum Bounding Rectangle,MBR)是一个重要概念,它指的是能够完全包围一个几何对象的最小的轴对齐矩形。这个几何对象可以是点集、多边形或其他形状。在处理大量数据时...

    matlab计算目标最小外接矩形

    这个任务的目的是找到一个最小的矩形,该矩形能够完全包围给定的目标或者一组点。在提供的描述中提到了`minboundrect`函数,它是MATLAB用于解决这个问题的一个内置工具。 `minboundrect`函数是MATLAB Image ...

    matlab 求最小外接矩形

    该算法首先找到点集的最小和最大的x和y坐标,然后通过一系列旋转找到覆盖所有点的最小面积矩形。关键在于找到合适的旋转角度,每次旋转都会改变矩形的宽高比,直到找到最优解。 在MATLAB中实现这个算法,我们需要...

    matlab计算最小外界矩形

    在计算机视觉和图像处理领域,计算最小外界矩形是一项常用的任务,它可以帮助我们找到一个对象在图像中的最小包围框,从而有效地对目标进行定位。在本案例中,我们将重点讨论如何使用MATLAB来实现这一功能,特别是在...

    zuobiao.rar_前景提取_外接矩形_提取前景目标_最小矩形_矩形 目标

    最小矩形(也称为最小外接矩形)是相对于外接矩形的一个特例,它是指包围一个对象的最小面积的矩形。在图像处理中,最小矩形通常用于减少噪声、简化形状并减少计算复杂性。例如,在机器视觉系统中,最小矩形可以提供...

    matlab求最小矩形

    `minboundrect.m`函数的目的是找到包围给定轮廓的最小面积矩形。在图像处理中,轮廓通常是通过边缘检测算法(如Canny、Sobel或Prewitt)获得的像素集合。这个最小矩形将尽可能地贴合轮廓,同时保持其长宽比,使得...

    ROI提取_ROI_matlab_最小矩形;分割旋转_

    在图像处理中,如果有一个不规则的边界,我们可以找到一个包围这个边界的最小矩形,使得该矩形完全覆盖这个边界,且矩形的长宽比是最小的。MATLAB提供了`minboundrect`函数来实现这个功能,它能计算出边界点集的最小...

    minboundrect.rar_矩形提取

    这个矩形的边可能与形状的边界平行,目的是最小化矩形的面积,同时确保形状的所有部分都在矩形内部。 在Matlab中,"minboundrect"函数是用于计算二维点集的最小外接矩形。这个函数接收一个二维坐标数组作为输入,...

    python opencv minAreaRect 生成最小外接矩形的方法

    在Python的OpenCV库中,`minAreaRect()`函数是一个非常实用的工具,它用于找到一个二维点集的最小面积包围矩形。这个方法对于处理图像处理和计算机视觉任务,如对象检测、形状分析和图像分割等场景非常有用。下面...

    Python实现图片查找轮廓、多边形拟合、最小外接矩形代码

    为了筛选出感兴趣的轮廓,代码还计算了轮廓的面积(`cv2.contourArea()`)和最小外接矩形(`cv2.minAreaRect()`和`cv2.boxPoints()`),并根据长宽比、面积和多边形顶点数进行过滤。例如,只选择长宽比小于10且面积在20...

    找矩形顶点.zip

    它是一个具有最小面积的轴对齐矩形,能够完全包含所有的点或对象。在Halcon中,这个概念通常应用于检测不规则形状的物体,以便进行定位、测量或识别。 Halcon提供的`get_rectangle2_points`函数就是用来获取这样的...

    049_輪廓包覆(boundingRect、minAreaRect) _ 阿洲的程式教學1

    其中,`boundingRect`、`minAreaRect`和`minEnclosingCircle`是三个非常重要的函数,它们用于计算图像轮廓的包围矩形、最小面积旋转矩形和最小覆盖圆。这些函数在物体识别、图像分割、目标跟踪等领域有着广泛的应用...

    matl_三维点云精简_

    最小包围盒(Minimum Bounding Box, MBB)是包围三维点集的最小体积矩形盒,它的六个面都平行于坐标轴。在点云精简中,我们可以依据点到包围盒边界的距离来剔除那些对形状影响较小的点,从而达到减少点数量的目的。...

    二维最小边界框:快速计算一组二维点的最小边界框-matlab开发

    计算一组 2D 点的最小边界框,类似于 John D'Errico 的“最小边界矩形”。 然而: - 算法是完全矢量化的(matlab 实现,没有 for 循环)。 因此对于大的点集更好- 它只计算最小面积矩形,而不是最小周长

    matlab开发-2最小边界框

    在二维空间中,一个最小边界框是能够完全包围一组点的最小矩形,它的边平行于坐标轴。这个矩形具有最小的面积,同时包含所有给定点。在各种领域,如计算机图形学、地理信息系统和图像处理中,最小边界框的计算都有...

    calc_OriBoundingBox​(data):此函数近似于 3D 数据点集的最小边界框 (OBB)。-matlab开发

    定向边界框相比于无定向的最小外接矩形(Minimum Enclosing Rectangle, MER),具有更好的空间适应性,尤其是在处理形状不规则的数据集时。`calc_OriBoundingBox` 的工作原理可以分为以下几个关键步骤: 1. **数据...

    minboundrect_matlab_识别_

    这个矩形能够完全包围输入的点集,同时具有最小的面积。在图像识别中,我们通常需要对图像中的特定形状或物体进行定位和提取,这时`minboundrect`就能派上用场。 首先,我们需要理解该函数的基本语法和输入参数。`...

    2018吉林省数学建模竞赛A题__自己做的相关结果和代码

    再者,最小外接矩形是在一组点集上找到的最小面积的矩形,它包围了所有的点。在实际应用中,这个概念常用于对象定位和尺寸估计。算法通常基于旋转卡尔曼滤波或旋转卡尔曼树等数据结构来找到最小外接矩形,它可以帮助...

Global site tag (gtag.js) - Google Analytics