首先,我是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)]
此脚本返回此post problem之后所有可能区域的打印件。代码开发 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)解决方案:一个功能 按照Scott Hunter建议的第一个解决方案,我有一个问题是在get_minimum_area_rectangle()中集成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()。我有一个问题需要了解如何整合(抱歉不正确的术语)至少在这一点上
答案 0 :(得分:2)
您可以使用单个功能或两个功能,但它可能更简洁,更容易使用两个功能。您可以按原样保留mostfar
功能。然后,只需通过添加函数定义行将代码的后半部分转换为函数:
def get_minimum_area_rectangle(hull):
...然后缩进代码的其余部分(以n = len(hull)
开头)以形成函数体。您还需要更改函数以返回要获取的值(长度,宽度和面积)。这将使您的代码保持模块化和清洁,并且只需要很少的更改。
使用hull
的值列表似乎没有用于此目的。另一种方法是使用数组(如NumPy数组),但在这种情况下,您将迭代地遍历数据,一次一个项目,而不是同时跨多个数据点进行任何计算。所以列表应该没问题。访问列表中的项目很快,与您必须的数学相比,它不应该成为瓶颈。
答案 1 :(得分:1)
答案 2 :(得分:1)
这是一个如何从代码中创建仿函数对象并使用它的示例 - 以及对我认为值得的其他一些事情的一些更改。仿函数是一个实现函数角色但可以像对象一样操作的实体。
在Python中,两者之间的区别较小,因为函数已经是单例对象,但有时为一个对象创建一个专用类很有用。在这种情况下,它允许将辅助函数设置为私有类方法,而不是它是全局的或嵌套的,您似乎反对这样做。
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
答案 3 :(得分: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))