在函数中实现脚本.有什么建议吗



首先,我对Python(编程领域)很陌生,但我希望学习和转换jwpat7开发的函数。给定从凸包导出的一组点

hull= [(560023.44957588764,6362057.3904932579), 
(560023.44957588764,6362060.3904932579), 
(560024.44957588764,6362063.3904932579), 
(560026.94957588764,6362068.3904932579), 
(560028.44957588764,6362069.8904932579), 
(560034.94957588764,6362071.8904932579), 
(560036.44957588764,6362071.8904932579), 
(560037.44957588764,6362070.3904932579), 
(560037.44957588764,6362064.8904932579), 
(560036.44957588764,6362063.3904932579), 
(560034.94957588764,6362061.3904932579), 
(560026.94957588764,6362057.8904932579), 
(560025.44957588764,6362057.3904932579), 
(560023.44957588764,6362057.3904932579)]

这个脚本返回了这个帖子问题之后所有可能的区域的打印。代码由开发jwpat7是:

import math
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)

结果是:

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

我希望创建一个返回最小矩形的长度、宽度和面积的函数。例如:

Length, Width, Area = get_minimum_area_rectangle(hull)
print Length, Width, Area
18.036, 10.392, 187.451

我的问题是:

  1. 我需要创建一个函数还是两个函数。例如:defmostfar和get_minimum_rea_rectangle
  2. 赫尔是一个价值列表。它是最好的格式吗?
  3. 按照一个函数的方法,我有一个在内部集成mostfar的问题

提前感谢

1) 解决方案:一个函数按照Scott Hunter提出的第一个解决方案,我在get_minimum_area_ctangle()中集成mostfar()时遇到了一个问题。任何建议或帮助都非常感谢,因为我可以学习。

#!/usr/bin/python
import math
def get_minimum_area_rectangle(hull):
# get pi greek
pi = 4*math.atan(1)
# number of points
n = len(hull)
# indexes left, right, opposite
iL = iR = iP = 1
# work clockwise direction
for i in range(n-1):
# distance on x axis
dx = hull[i+1][0] - hull[i][0]
# distance on y axis
dy = hull[i+1][1] - hull[i][1]
# get orientation angle of the edge
theta = pi-math.atan2(dy, dx)
s, c = math.sin(theta), math.cos(theta)
yC = hull[i][0]*s + hull[i][1]*c

在上面的jwpat7示例之后,我需要使用mostfar()。我有一个问题来理解如何在这一点上集成(对不起,术语不正确)

  1. 您可以使用单个函数或两个函数,但使用两个函数可能更干净、更容易。您可以将mostfar函数保留为原样。然后,只需通过添加函数定义行将代码的后半部分转换为函数:

    def get_minimum_area_rectangle(hull):
    

    …,然后缩进代码的其余部分(从n = len(hull)开始)以形成函数的主体。您还需要更改函数以返回想要获得的值(长度、宽度和面积)。这将使您的代码保持模块化和干净,并且只需要很少的更改。

  2. 为此,使用hull的值列表似乎很好。另一种选择是使用数组(如NumPy数组),但在这种情况下,您将一次迭代一项地处理数据,而不是同时在多个数据点上进行任何计算。所以一份清单应该没问题。访问列表中的项目很快,与你必须做的数学运算相比,这不应该是一个瓶颈

下面是一个如何将其从代码中变成函子对象并使用它的示例,以及对我认为值得做的其他一些事情的一些更改。函子是一个实体,它充当函数的角色,但可以像对象一样操作。

在Python中,由于函数已经是单例对象,所以两者之间的区别较小,但有时为函数创建一个专门的类是有用的。在这种情况下,它允许将helper函数制作成一个私有类方法,而不是全局的或嵌套的(您似乎反对这样做)。

from math import atan2, cos, pi, sin
class GetMinimumAreaRectangle(object):
""" functor to find length, width, and area of the smallest rectangular
area of the given convex hull """
def __call__(self, hull):
self.hull = hull
mostfar = self._mostfar  # local reference
n = len(hull)
min_area = 10**100  # huge value
iL = iR = iP = 1  # indexes left, right, opposite
#        print '    {:>2s} {:>2s} {:>2s} {:>2s} {:>9s}'.format(
#                   'i', 'iL', 'iP', 'iR', 'area')
for i in xrange(n-1):
dx = hull[i+1][0] - hull[i][0]  # distance on x axis
dy = hull[i+1][1] - hull[i][1]  # distance on y axis
theta = pi-atan2(dy, dx)   # get orientation angle of the edge
s, c = sin(theta), 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)
l, w = (yP-yC), (xR-xL)
area = l*w
#            print '    {:2d} {:2d} {:2d} {:2d} {:9.3f}'.format(i, iL, iP, iR, area)
if area < min_area:
min_area, min_length, min_width = area, l, w
return (min_length, min_width, min_area)
def _mostfar(self, j, n, s, c, mx, my):
""" advance j to extreme point """
hull = self.hull  # local reference
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)
if __name__ == '__main__':
hull= [(560023.44957588764, 6362057.3904932579),
(560023.44957588764, 6362060.3904932579),
(560024.44957588764, 6362063.3904932579),
(560026.94957588764, 6362068.3904932579),
(560028.44957588764, 6362069.8904932579),
(560034.94957588764, 6362071.8904932579),
(560036.44957588764, 6362071.8904932579),
(560037.44957588764, 6362070.3904932579),
(560037.44957588764, 6362064.8904932579),
(560036.44957588764, 6362063.3904932579),
(560034.94957588764, 6362061.3904932579),
(560026.94957588764, 6362057.8904932579),
(560025.44957588764, 6362057.3904932579),
(560023.44957588764, 6362057.3904932579)]
gmar = GetMinimumAreaRectangle()  # create functor object
print "dimensions and area of smallest enclosing rectangular area:"
print "  {:.3f}(L) x {:.3f}(W) = {:.3f} area".format(*gmar(hull))  # use it

输出:

dimensions and area of smallest enclosing rectangular area:
10.393(L) x 18.037(W) = 187.451 area
  1. 您当然可以将其作为一个单独的函数来完成:稍微修改mostfar,以跟踪最小的&或者你可以让它收集它打印到lst中的值,然后G.E.a.R.可以用它来找到最小值

EDIT:(我错过了一些代码在mostfar之外)我会把"脚本"部分(mostfar之后的代码)包装成一个函数,并如上所述修改它。然后,您的"脚本"将只调用该函数,或者,如果使用第二次修改,则从返回的列表中查找最小值。

  1. 我认为你的船体表示没有任何问题

我发布了另一个答案,展示了如何按照我(和其他人)的建议进行操作,那就是将助手函数mostfar()嵌套在被调用的主函数中。这在Python中很容易做到,因为嵌套函数可以访问其封闭范围的局部变量(本例中为hull)。我还按照约定将函数重命名为_mostfar(),以表示某些东西是私有的,但这并不是绝对必要的(曾经,这里也绝对没有)。

正如你所看到的,大多数代码与我的另一个答案中的代码非常相似,尽管我确实简化了一些与嵌套函数无关的事情(所以它们可能会集成到你选择的任何答案中)。

from math import atan2, cos, pi, sin
def get_minimum_area_rectangle(hull):
""" find length, width, and area of the smallest rectangular
area of the given convex hull """
def _mostfar(j, n, s, c, mx, my):
""" advance j to extreme point """
xn, yn = hull[j]
rx, ry = xn*c - yn*s, xn*s + yn*c
best = mx*rx + my*ry
k = j + 1
while True:
x, y = rx, ry
xn, yn = hull[k % n]
rx, ry = xn*c - yn*s, xn*s + yn*c
if mx*rx + my*ry < best:
return (x, y, j)
else:
j, k = k % n, j + 1
best = mx*rx + my*ry
n = len(hull)
min_area = 10**100
iL = iR = iP = 1  # indexes left, right, opposite
#   print '    {:>2s} {:>2s} {:>2s} {:>2s} {:>9s}'.format(
#              'i', 'iL', 'iP', 'iR', 'area')
for i in xrange(n-1):
dx = hull[i+1][0] - hull[i][0]  # distance on x axis
dy = hull[i+1][1] - hull[i][1]  # distance on y axis
theta = pi-atan2(dy, dx)   # get orientation angle of the edge
s, c = sin(theta), 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)
l, w = (yP-yC), (xR-xL)
area = l*w
#       print '    {:2d} {:2d} {:2d} {:2d} {:9.3f}'.format(i, iL, iP, iR, area)
if area < min_area:
min_area, min_length, min_width = area, l, w
return (min_length, min_width, min_area)
if __name__ == '__main__':
hull= [(560023.44957588764, 6362057.3904932579),
(560023.44957588764, 6362060.3904932579),
(560024.44957588764, 6362063.3904932579),
(560026.94957588764, 6362068.3904932579),
(560028.44957588764, 6362069.8904932579),
(560034.94957588764, 6362071.8904932579),
(560036.44957588764, 6362071.8904932579),
(560037.44957588764, 6362070.3904932579),
(560037.44957588764, 6362064.8904932579),
(560036.44957588764, 6362063.3904932579),
(560034.94957588764, 6362061.3904932579),
(560026.94957588764, 6362057.8904932579),
(560025.44957588764, 6362057.3904932579),
(560023.44957588764, 6362057.3904932579)]
print "dimensions and area of smallest enclosing rectangular area:"
print "  {:.3f}(L) x {:.3f}(W) = {:.3f} area".format(
*get_minimum_area_rectangle(hull))

相关内容

  • 没有找到相关文章

最新更新