python计算长方形面积代码_python – 为给定点找到最小面积矩形以计算...

该博客介绍了一个Python程序,用于在O(n)时间内找到给定凸包点集的最小面积包围矩形。程序首先利用Graham扫描算法在O(nlogn)时间内找到凸包,然后维护三个索引分别指向最左边、相对和最右边的点,通过比较旋转坐标找到最大直径,从而确定最小面积矩形。文章提供了代码示例和输出解析,强调了浮点数精度问题可能导致的误差,并给出了调整方法。
摘要由CSDN通过智能技术生成

给定一组点的凸包中的n个点的顺时针有序列表,找到最小面积包围矩形是O(n)操作. (对于凸壳发现,在O(n log n)时间内,见activestate.com recipe 66527或看到相当紧凑的Graham scan code at tixxit.net.)

下面的python程序使用类似于通常的O(n)算法的技术来计算凸多边形的最大直径.也就是说,它维持三个索引(iL,iP,iR)到相对于给定基线的最左边,相对和最右边的点.每个指数最多通过n个点.接下来显示程序的示例输出(带有添加的标题):

i iL iP iR Area

0 6 8 0 203.000

1 6 8 0 211.875

2 6 8 0 205.800

3 6 10 0 206.250

4 7 12 0 190.362

5 8 0 1 203.000

6 10 0 4 201.385

7 0 1 6 203.000

8 0 3 6 205.827

9 0 3 6 205.640

10 0 4 7 187.451

11 0 4 7 189.750

12 1 6 8 203.000

例如,i = 10条目表示相对于从点10到11的基线,点0最左边,点4相反,点7最右边,产生187.451单位的面积.

请注意,代码使用mostfar()来推进每个索引. mx,我对mostfar()的参数告诉它要测试什么极端;例如,对于mx,my = -1,0,mostfar()将尝试最大化-rx(其中rx是点的旋转x),从而找到最左边的点.请注意,如果mx * rx my * ry> = best在不精确的算术中完成,则可能应该使用epsilon容差:当船体有多个点时,舍入误差可能是一个问题并导致方法错误地不推进索引.

代码如下所示.船体数据取自上面的问题,没有相关的大偏差和相同的小数位.

#!/usr/bin/python

import math

hull = [(23.45, 57.39), (23.45, 60.39), (24.45, 63.39),

(26.95, 68.39), (28.45, 69.89), (34.95, 71.89),

(36.45, 71.89), (37.45, 70.39), (37.45, 64.89),

(36.45, 63.39), (34.95, 61.39), (26.95, 57.89),

(25.45, 57.39), (23.45, 57.39)]

def mostfar(j, n, s, c, mx, my): # advance j to extreme point

xn, yn = hull[j][0], hull[j][1]

rx, ry = xn*c - yn*s, xn*s + yn*c

best = mx*rx + my*ry

while True:

x, y = rx, ry

xn, yn = hull[(j+1)%n][0], hull[(j+1)%n][1]

rx, ry = xn*c - yn*s, xn*s + yn*c

if mx*rx + my*ry >= best:

j = (j+1)%n

best = mx*rx + my*ry

else:

return (x, y, j)

n = len(hull)

iL = iR = iP = 1 # indexes left, right, opposite

pi = 4*math.atan(1)

for i in range(n-1):

dx = hull[i+1][0] - hull[i][0]

dy = hull[i+1][1] - hull[i][1]

theta = pi-math.atan2(dy, dx)

s, c = math.sin(theta), math.cos(theta)

yC = hull[i][0]*s + hull[i][1]*c

xP, yP, iP = mostfar(iP, n, s, c, 0, 1)

if i==0: iR = iP

xR, yR, iR = mostfar(iR, n, s, c, 1, 0)

xL, yL, iL = mostfar(iL, n, s, c, -1, 0)

area = (yP-yC)*(xR-xL)

print ' {:2d} {:2d} {:2d} {:2d} {:9.3f}'.format(i, iL, iP, iR, area)

注意:要获得最小区域包围矩形的长度和宽度,请修改上面的代码,如下所示.这将产生一个输出线

Min rectangle: 187.451 18.037 10.393 10 0 4 7

其中第二个和第三个数字表示矩形的长度和宽度,四个整数给出位于其两侧的点的索引号.

# add after pi = ... line:

minRect = (1e33, 0, 0, 0, 0, 0, 0) # area, dx, dy, i, iL, iP, iR

# add after area = ... line:

if area < minRect[0]:

minRect = (area, xR-xL, yP-yC, i, iL, iP, iR)

# add after print ... line:

print 'Min rectangle:', minRect

# or instead of that print, add:

print 'Min rectangle: ',

for x in ['{:3d} '.format(x) if isinstance(x, int) else '{:7.3f} '.format(x) for x in minRect]:

print x,

print

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值