Python中的最小封闭平行四边形

Python中的最小封闭平行四边形,python,matlab,geometry,bounding-box,bounding,Python,Matlab,Geometry,Bounding Box,Bounding,我有一组定义凸多边形的点,并希望使用Python和/或NumPy找到具有最小面积的封闭平行四边形 以下是一些可能有用的资源,但我自己无法充分理解它们: 非常感谢您的帮助。O(n)解并不重要。如果你想要最小周长包围平行四边形, 我下面的论文提供了一个线性时间算法。 所有的最小封闭形状算法都依赖于“旋转卡钳” 从某种意义上说,你可以从上图中推断 布萨尼、尤尼特、玛丽·利亚·卡克尔、约瑟夫·奥洛克和利昂娜·斯巴拉科。“清扫包围平行四边形的最小周长:最佳碎屑清理”,加拿大。计算机形态。《几何》,

我有一组定义凸多边形的点,并希望使用Python和/或NumPy找到具有最小面积的封闭平行四边形

以下是一些可能有用的资源,但我自己无法充分理解它们:


非常感谢您的帮助。O(n)解并不重要。

如果你想要最小周长包围平行四边形, 我下面的论文提供了一个线性时间算法。

所有的最小封闭形状算法都依赖于“旋转卡钳” 从某种意义上说,你可以从上图中推断

布萨尼、尤尼特、玛丽·利亚·卡克尔、约瑟夫·奥洛克和利昂娜·斯巴拉科。“清扫包围平行四边形的最小周长:最佳碎屑清理”,加拿大。计算机形态。《几何》,第167-170页。2010 ()

下面是我使用的纯Python O(n)实现:

import math

"""
Minimal Enclosing Parallelogram

area, v1, v2, v3, v4 = mep(convex_polygon)

convex_polygon - array of points. Each point is a array [x, y] (1d array of 2 elements)
points should be presented in clockwise order.

the algorithm used is described in the following paper:
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.53.9659&rep=rep1&type=pdf
"""

def distance(p1, p2, p):
    return abs(((p2[1]-p1[1])*p[0] - (p2[0]-p1[0])*p[1] + p2[0]*p1[1] - p2[1]*p1[0]) /
        math.sqrt((p2[1]-p1[1])**2 + (p2[0]-p1[0])**2))

def antipodal_pairs(convex_polygon):
    l = []
    n = len(convex_polygon)
    p1, p2 = convex_polygon[0], convex_polygon[1]

    t, d_max = None, 0
    for p in range(1, n):
        d = distance(p1, p2, convex_polygon[p])
        if d > d_max:
            t, d_max = p, d
    l.append(t)

    for p in range(1, n):
        p1, p2 = convex_polygon[p % n], convex_polygon[(p+1) % n]
        _p, _pp = convex_polygon[t % n], convex_polygon[(t+1) % n]
        while distance(p1, p2, _pp) > distance(p1, p2, _p):
            t = (t + 1) % n
            _p, _pp = convex_polygon[t % n], convex_polygon[(t+1) % n]
        l.append(t)

    return l


# returns score, area, points from top-left, clockwise , favouring low area
def mep(convex_polygon):
    def compute_parallelogram(convex_polygon, l, z1, z2):
        def parallel_vector(a, b, c):
            v0 = [c[0]-a[0], c[1]-a[1]]
            v1 = [b[0]-c[0], b[1]-c[1]]
            return [c[0]-v0[0]-v1[0], c[1]-v0[1]-v1[1]]

        # finds intersection between lines, given 2 points on each line.
        # (x1, y1), (x2, y2) on 1st line, (x3, y3), (x4, y4) on 2nd line.
        def line_intersection(x1, y1, x2, y2, x3, y3, x4, y4):
            px = ((x1*y2 - y1*x2)*(x3 - x4) - (x1 - x2)*(x3*y4 - y3*x4))/((x1-x2)*(y3-y4) - (y1-y2)*(x3-x4))
            py = ((x1*y2 - y1*x2)*(y3 - y4) - (y1 - y2)*(x3*y4 - y3*x4))/((x1-x2)*(y3-y4) - (y1-y2)*(x3-x4))
            return px, py


        # from each antipodal point, draw a parallel vector,
        # so ap1->ap2 is parallel to p1->p2
        #    aq1->aq2 is parallel to q1->q2
        p1, p2 = convex_polygon[z1 % n], convex_polygon[(z1+1) % n]
        q1, q2 = convex_polygon[z2 % n], convex_polygon[(z2+1) % n]
        ap1, aq1 = convex_polygon[l[z1 % n]], convex_polygon[l[z2 % n]]
        ap2, aq2 = parallel_vector(p1, p2, ap1), parallel_vector(q1, q2, aq1)

        a = line_intersection(p1[0], p1[1], p2[0], p2[1], q1[0], q1[1], q2[0], q2[1])
        b = line_intersection(p1[0], p1[1], p2[0], p2[1], aq1[0], aq1[1], aq2[0], aq2[1])
        d = line_intersection(ap1[0], ap1[1], ap2[0], ap2[1], q1[0], q1[1], q2[0], q2[1])
        c = line_intersection(ap1[0], ap1[1], ap2[0], ap2[1], aq1[0], aq1[1], aq2[0], aq2[1])

        s = distance(a, b, c) * math.sqrt((b[0]-a[0])**2 + (b[1]-a[1])**2)
        return s, a, b, c, d


    z1, z2 = 0, 0
    n = len(convex_polygon)

    # for each edge, find antipodal vertice for it (step 1 in paper).
    l = antipodal_pairs(convex_polygon)

    so, ao, bo, co, do, z1o, z2o = 100000000000, None, None, None, None, None, None

    # step 2 in paper.
    for z1 in range(0, n):
        if z1 >= z2:
            z2 = z1 + 1
        p1, p2 = convex_polygon[z1 % n], convex_polygon[(z1+1) % n]
        a, b, c = convex_polygon[z2 % n], convex_polygon[(z2+1) % n], convex_polygon[l[z2 % n]]
        if distance(p1, p2, a) >= distance(p1, p2, b):
            continue

        while distance(p1, p2, c) > distance(p1, p2, b):
            z2 += 1
            a, b, c = convex_polygon[z2 % n], convex_polygon[(z2+1) % n], convex_polygon[l[z2 % n]]

        st, at, bt, ct, dt = compute_parallelogram(convex_polygon, l, z1, z2)

        if st < so:
            so, ao, bo, co, do, z1o, z2o = st, at, bt, ct, dt, z1, z2

    return so, ao, bo, co, do, z1o, z2o
导入数学
"""
最小封闭平行四边形
面积,v1,v2,v3,v4=mep(凸多边形)
凸多边形-点的数组。每个点是一个数组[x,y](2个元素的一维数组)
各点应按顺时针顺序显示。
使用的算法在以下文件中进行了描述:
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.53.9659&rep=rep1&type=pdf
"""
def距离(p1、p2、p):
返回abs(((p2[1]-p1[1])*p[0]-(p2[0]-p1[0])*p[1]+p2[0]*p1[1]-p2[1]*p1[0])/
数学sqrt((p2[1]-p1[1])**2+(p2[0]-p1[0])**2))
def反足对(凸多边形):
l=[]
n=len(凸多边形)
p1,p2=凸多边形[0],凸多边形[1]
t、 d_max=无,0
对于范围(1,n)内的p:
d=距离(p1,p2,凸多边形[p])
如果d>d_最大值:
t、 d_max=p,d
l、 附加(t)
对于范围(1,n)内的p:
p1,p2=凸多边形[p%n],凸多边形[(p+1)%n]
_p、 _pp=凸多边形[t%n],凸多边形[(t+1)%n]
当距离(p1,p2,_-pp)>距离(p1,p2,_-p)时:
t=(t+1)%n
_p、 _pp=凸多边形[t%n],凸多边形[(t+1)%n]
l、 附加(t)
返回l
#返回分数、面积、从左上角开始的分数、顺时针方向、偏向低面积
def mep(凸多边形):
def计算平行四边形(凸多边形,l,z1,z2):
def平行_矢量(a、b、c):
v0=[c[0]-a[0],c[1]-a[1]]
v1=[b[0]-c[0],b[1]-c[1]]
返回[c[0]-v0[0]-v1[0],c[1]-v0[1]-v1[1]]
#查找直线之间的交点,每条直线上给定2个点。
#(x1,y1),(x2,y2)在第1行,(x3,y3),(x4,y4)在第2行。
def线_交叉点(x1、y1、x2、y2、x3、y3、x4、y4):
px=((x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4))
py=((x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4))
返回px,py
#从每个对极点,画一个平行向量,
#所以ap1->ap2与p1->p2平行
#aq1->aq2与q1->q2平行
p1,p2=凸多边形[z1%n],凸多边形[(z1+1)%n]
q1,q2=凸多边形[z2%n],凸多边形[(z2+1)%n]
ap1,aq1=凸多边形[l[z1%n]],凸多边形[l[z2%n]]
ap2,aq2=平行_向量(p1,p2,ap1),平行_向量(q1,q2,aq1)
a=线与线的交点(p1[0]、p1[1]、p2[0]、p2[1]、q1[0]、q1[1]、q2[0]、q2[1])
b=直线交叉点(p1[0]、p1[1]、p2[0]、p2[1]、aq1[0]、aq1[1]、aq2[0]、aq2[1])
d=线与线的交点(ap1[0]、ap1[1]、ap2[0]、ap2[1]、q1[0]、q1[1]、q2[0]、q2[1])
c=线路交叉点(ap1[0]、ap1[1]、ap2[0]、ap2[1]、aq1[0]、aq1[1]、aq2[0]、aq2[1])
s=距离(a,b,c)*数学sqrt((b[0]-a[0])**2+(b[1]-a[1])**2)
返回s、a、b、c、d
z1,z2=0,0
n=len(凸多边形)
#对于每一条边,找到它的对足垂直(本文中的步骤1)。
l=对足对(凸多边形)
所以,ao,bo,co,do,z1o,z2o=10000000000,无,无,无,无,无,无
#第二步在纸上。
对于范围(0,n)内的z1:
如果z1>=z2:
z2=z1+1
p1,p2=凸多边形[z1%n],凸多边形[(z1+1)%n]
a、 b,c=凸多边形[z2%n],凸多边形[(z2+1)%n],凸多边形[l[z2%n]]
如果距离(p1,p2,a)>=距离(p1,p2,b):
持续
当距离(p1,p2,c)>距离(p1,p2,b)时:
z2+=1
a、 b,c=凸多边形[z2%n],凸多边形[(z2+1)%n],凸多边形[l[z2%n]]
st,at,bt,ct,dt=计算平行四边形(凸多边形,l,z1,z2)
如果st
谢谢-非常有用的资源。在我的情况下,最小周长可能还可以,但我对你的数学理解不够好,无法从你的论文中实现这一点,至少不能在一周内实现!你有有效缩进的版本吗?@TobiasHermann我不确定这里什么是无效的。。。我遗漏了什么吗?在尝试使用代码时遇到的第一个错误是缩进问题()。只要试着从你的答案中复制并运行代码即可没问题。有机会投票支持我的答案吗?;)