在函数中实现一个脚本。一些建议?

问题描述 投票:0回答:4

首先,我对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_area_rectangle,我需要创建一个函数还是两个函数。
  2. hull是一个值的列表。这是最好的格式吗?
    1. 遵循一个函数的方法,我有一个问题,就是如何将最远的值整合到一个函数中。

先谢谢你

1)解决方案:一个函数按照Scott Hunter建议的第一个解决方案,我有一个问题,要把mostfar()整合到get_minimum_area_rectangle()里面。任何建议或帮助都非常感激,因为我可以学习。

#!/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()。我有一个问题要了解如何在这一点上整合(对不起,这个词用得不对)mostfar。

python performance algorithm coding-style styles
4个回答
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

2
投票
  1. 你可以使用一个函数或两个函数 但使用两个函数可能会更干净和容易一些。你可以把 mostfar 函数的原样。然后,只需通过添加函数定义行将代码的后半部分转换成函数。

    def get_minimum_area_rectangle(hull):
    

    ...然后将代码的其余部分缩进(以... ...为起点)。n = len(hull))来构成函数的主体。你还想改变函数来返回你想得到的值(长度、宽度和面积)。这将使你的代码保持模块化和简洁,并且只需要很少的改动。

  2. 使用值的列表来获取 hull 似乎可以满足这个目的。另一种选择是使用一个数组(比如NumPy数组),但在这种情况下,你是在反复检查数据,一次一个项目,而不是同时对多个数据点进行任何计算。所以,一个列表应该是可以的。在列表中访问项目的速度很快,和你要做的数学相比,这应该不会是一个瓶颈。


1
投票
  1. 你当然可以把它作为一个函数来做:稍微修改一下mostfar,不是打印找到的区域,而是跟踪最小的&的信息。 或者你可以让它把打印的值收集到一个lst中,然后G.E.A.R.可以用它来寻找最小值。

EDIT: (我忽略了一些代码是在mostfar之外的)我会把 "脚本 "部分(mostfar之后的代码)包装成一个函数,然后按照上面的描述修改那个函数。 然后,你的 "脚本 "就会调用那个函数,或者,如果使用第二个修改,从返回的列表中找到最小值。

  1. 我不觉得你对hull的表示有什么问题。

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))
© www.soinside.com 2019 - 2024. All rights reserved.