计算多边形的面积

时间:2016-06-06 03:49:11

标签: python

从网站下载shapes.py并使用类Circle,类Polygon和方法区域扩展它。类Circle和Polygon应该从Shape继承。对于圆,在创建时必须指定半径, str 方法应返回与Line和Rectangle相同样式的字符串:对于矩形,在创建时,顶点列表必须遵循以下示例正是如此将方法区域添加到Line,Rectangle,Circle类。线的面积为零,矩形和圆的面积应计算在 通常的方式。为此,从数学中导入pi。具有顶点的非自相交多边形的区域定义为here

其中每个with表示多边形的顶点(“角”),和。请注意,如果点是逆时针顺序,则凸多边形的面积为正,如果它们是顺时针顺序,则为负。 (维基百科页面采用绝对值来避免负面区域。请勿在此处执行此操作。)

以下是一些测试用例:

   g = Group()
    l = Line(1, 2, 5, 6); g.add(l); print(l)
 Line from (1, 2) to (5, 6)
    r = Rectangle(-2, -3, 2, 3); g.add(r); print(r)
 Rectangle at (-2, -3), width 2, height 3
    c = Circle(1, -5, 1); g.add(c); print(c)
 Circle at (1, -5), radius 1
    p = Polygon([(0, 0), (4, 0), (2, 2), (4, 4), (0, 4), (2, 2)]); g.add(p);     print(p)
 Polygon with [(0, 0), (4, 0), (2, 2), (4, 4), (0, 4), (2, 2)]
    print(g); g.move(1, 1); print(g)
 Group with:
  Circle at (1, -5), radius 1
  Rectangle at (-2, -3), width 2, height 3
  Line from (1, 2) to (5, 6)
  Polygon with [(0, 0), (4, 0), (2, 2), (4, 4), (0, 4), (2, 2)]
 Group with:
  Circle at (2, -4), radius 1
  Rectangle at (-1, -2), width 2, height 3
  Line from (2, 3) to (6, 7)
  Polygon with [(1, 1), (5, 1), (3, 3), (5, 5), (1, 5), (3, 3)]
    l.area(), r.area(), c.area(), p.area(), g.area()
  (0, 6, 3.141592653589793, 8.0, 17.141592653589793)

我是Python的新手,并且不知道如何处理这个问题。任何帮助,将不胜感激!谢谢!

2 个答案:

答案 0 :(得分:1)

我还没有完成代码。但是为你创造了一个学习和开始填充的结构。

Shape是基类,Line,Circle,Rectangle和Polygon是子类(继承)。 [假设你有OOP的想法]

class Group(object):
    """docstring for Group"""

    def __init__(self):
        super(Group, self).__init__()
        self.shapes = list()

    def add(self, shape):
        self.shapes.append(shape)

    def move(self, dx, dy):
        for shape in self.shapes:
            print "Moving %s by (%d, %d)" % (shape, dx, dy)
            shape.move(dx, dy)

    def __str__(self):
        return "Group with: " + ", ".join((str(shape) for shape in self.shapes))


class Shape(object):
    """docstring for Shape"""

    def __init__(self):
        super(Shape, self).__init__()

    def print_details(self):
        pass

    def area(self):
        pass


class Line(Shape):
    """docstring for Line"""

    def __init__(self, x1, y1, x2, y2):
        super(Line, self).__init__()
        self.x1 = x1
        self.y1 = y1
        self.x2 = x2
        self.y2 = y2

    def area(self):
        return 0

    def __str__(self):
        return "Line from (%s, %s) to (%s, %s)" % (self.x1, self.y1, self.x2, self.y2)


class Rectangle(Shape):
    """docstring for Line"""

    def __init__(self, x1, y1, x2, y2):
        super(Rectangle, self).__init__()
        self.x1 = x1
        self.y1 = y1
        self.x2 = x2
        self.y2 = y2

    def area(self):
        return self._width * self._height

    def __str__(self):
        return "Rectangle at (%s, %s), width %s, height %s" % (
          self.x1, self.y1, self._width(), self._height())

    def _width(self):
        return abs(self.x1 - self.x2)

    def _height(self):
        return abs(self.y1 - self.y2)

class Circle(Shape):
  """docstring for Circle"""
  def __init__(self, x, y, radius):
    super(Circle, self).__init__()
    self.x = x
    self.y = y
    self.radius = radius

  def area(self):
    pass

  def __str__(self):
    return "Circle ....."

class Polygon(Shape):
    """docstring for Line"""

    def __init__(self, vertices):
        super(Polygon, self).__init__()
        if type(vertices) is list and len(vertices) > 0 and type(vertices[0]) is tuple:
            self.vertices = vertices
        else:
            raise Exception("Invalid syntax")

    def area(self):
        area = 0
        for index in range(len(self.vertices) - 1):
            v1 = self.vertices[index]
            v2 = self.vertices[index + 1]
            area += ((v1[0] * v2[1]) - (v2[0] * v1[1]))
        area = 0.5 * area
        return area

    def __str__(self):
        return "Polygon with %s" % str(self.vertices)

g = Group()

l = Line(1, 2, 5, 6)
g.add(l)
print(l) #Line from (1, 2) to (5, 6) 

r = Rectangle(-2, -3, 2, 3)
g.add(r)
print(r) #Rectangle at (-2, -3), width 2, height 3

c = Circle(1, -5, 1)
g.add(c)
print(c) #Circle at (1, -5), radius 1

p = Polygon([(0, 0), (4, 0), (2, 2), (4, 4), (0, 4), (2, 2)])
g.add(p)
print(p) #Polygon with [(0, 0), (4, 0), (2, 2), (4, 4), (0, 4), (2, 2)] 

print(g)
g.move(1, 1)
print(g) #Group with: Circle at (1, -5), radius 1 Rectangle at (-2, -3), width 2, height 3 Line from (1, 2) to (5, 6) Polygon with [(0, 0), (4, 0), (2, 2), (4, 4), (0, 4), (2, 2)] Group with: Circle at (2, -4), radius 1 Rectangle at (-1, -2), width 2, height 3 Line from (2, 3) to (6, 7) Polygon with [(1, 1), (5, 1), (3, 3), (5, 5), (1, 5), (3, 3)] l.area(), r.area(), c.area(), p.area(), g.area() (0, 6, 3.141592653589793, 8.0, 17.141592653589793)

如果您有疑问,请随时提出更多问题

答案 1 :(得分:-1)

这是鞋带公式(http://en.wikipedia.org/wiki/Shoelace_formula),我在http://www.cgafaq.info/wiki/Polygon_Area的python中发现了一个可能的实现。这个网站似乎已经关闭了,但我发现这个形状相似的模块命名为相同的源(https://toblerity.org/shapely/shapely.algorithms.html

所以,如果你想在python中使用公式,这在我看来是可靠的:

def signed_area(coords):
    """Return the signed area enclosed by a ring using the linear time
algorithm at http://www.cgafaq.info/wiki/Polygon_Area. A value >= 0
indicates a counter-clockwise oriented ring.
return 0, if the ring is not closed
"""
    xs, ys = map(list, zip(*coords))
    xs.append(xs[1])
    ys.append(ys[1])
    return sum(xs[i]*(ys[i+1]-ys[i-1]) for i in range(1, len(coords)))/2.0

正如文档字符串所示,在一个闭环上,第一个坐标对等于最后一个,signed_area返回该区域。如果环未关闭,则返回值为零。如果结果为negativ,则多边形的方向为顺时针方向,如果为正方向,则多边形为逆时针方向。

如果您的多边形由多个环组成,则添加每个环的带符号区域,因为外环和内环具有不同的方向,从而产生相反的符号。