2014-01-19 27 views
0

我想實現一個表示線串的類。我有一個名爲「Point」的類, 表示一個帶有2個座標的點,我想用它來存儲線串的內部頂點 。 我想出了這段代碼:如何使用點類表示線串

class Point(object): 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

class LineString(Point): 
    def __init__(self, point): 
     self.point = point 

,但我不知道如何在線串 顯示多個點,以支持像一個線串:

lin = LineString((1, 1), (0, 2), (3,6)) 

我不知道線串中可能出現的點數。 新代碼:

class Point(object): 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

class LineString(Point): 
    def __init(self, *points): 
     #~ self.points=points 
     self.points = [] 
     for point in points: 
      if not isinstance(point, Point): 
       point = Point(*point) 
      self.points.append(point) 

    def length(self): 
     L = len(self.points) 
     return L 




if __name__ == '__main__': 
    # Tests for LineString 
    # =================================== 
    lin1 = LineString((1, 1), (0, 2)) 
    assert len(lin1.points) == sqrt(2.0) 

回答

1

*argumentname給你的構造可變參數:

class LineString(Point): 
    def __init__(self, *points): 
     self.points = points 

您可以根據需要元組轉換爲Point()實例:

class LineString(Point): 
    def __init__(self, *points): 
     self.points = [] 
     for point in points: 
      if not isinstance(point, Point): 
       point = Point(*point) 
      self.points.append(point) 

在這兩種情況下self.points現在是一個Python list對象。請注意在Point(*point)調用中使用鏡像語法; point元組的元素作爲單獨的參數應用於Point.__init__()方法,傳入(1, 1)元組作爲xy的兩個參數。

現在你可以建立一個線串有兩種:

lin = LineString((1, 1), (0, 2), (3,6)) 

演示:

>>> lin = LineString((1, 1), (0, 2), (3,6)) 
>>> len(lin.points) 
3 
>>> lin.points[0] 
<__main__.Point object at 0x108988fd0> 
>>> lin.points[0].x, lin.points[0].y 
(1, 1) 
+0

謝謝,但我怎樣才能提取線串的長度,例如? –

+1

@ f.ashouri:'len(self.points)';它只是一個列表對象。 –

+0

對我來說,它會拋出一個錯誤:LineString的對象沒有任何屬性'points' –

1

線不點,也不是線串。 Liskov Substitution Principle指出,應該始終可以將派生類的實例替換爲其父類之一。考慮以下代碼:

def move_point(point, xdist, ydist): 
    return Point(point.x + xdist, point.y + ydist) 

p = Point(3, 4) 
q = move_point(p, 5, 6) 
assert q.x == 8 and q.y == 10 

r = LineString((2, 3), (5, 4), (8, 6)) 
s = move_point(r, 5, 6) # ??? 

s可能是什麼?什麼是一串線的(x, y)座標?

解決這個問題的方法很簡單,就是不要從Point派生LineString。相反,代碼應該是這個樣子:

def pairwise(iterable): 
    "s -> (s0,s1), (s1,s2), (s2, s3), ..." 
    ... # see implementation details @ http://docs.python.org/2.7/library/itertools.html#recipes 

class Point(object): 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

def distance(point1, point2): 
    ... # needs implementing 

class Line(object): 
    def __init__(self, a, b): # a and b must be Points 
     self.a = a 
     self.b = b 

    @property 
    def length(self): 
     return distance(self.a, self.b) 

class LineString(object): 
    def __init(self, *points): 
     # We assume that points consists only of proper Point instances. 
     # If people pass invalid arguments, it's their problem. 
     self.points = points 

    @property 
    def length(self): 
     return sum(distance(p1, p2) for p1, p2 in pairwise(self.points)) 

if __name__ == '__main__': 
    lin1 = LineString((1, 1), (0, 2)) 
    assert lin1.length == sqrt(2.0) 

此外,浮點運算有時會產生奇怪的結果:

>>> .1 + .2 == .3 
False 
>>> .1 + .2 
0.30000000000000004 

有關說明,請參閱http://floating-point-gui.de

相關問題