Guest User

Untitled

a guest
Jan 22nd, 2011
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.75 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. class Point:
  4.     def __init__(self, x, y):
  5.         self.x = x
  6.         self.y = y
  7.     def __add__(self, other):
  8.         assert isinstance(other, Point)
  9.         return Point(self.x + other.x, self.y + other.y)
  10.     def __sub__(self, other):
  11.         assert isinstance(other, Point)
  12.         return Point(self.x - other.x, self.y - other.y)
  13.     def __mul__(self, other):
  14.         assert isinstance(other,int) or isinstance(other, float)
  15.         return Point(self.x*other, self.y*other)
  16.     def __str__(self):
  17.         return "(" + str(self.x) + "," + str(self.y) + ")"
  18.     def __repr__(self):
  19.         return "Point" + str(self)
  20.     def __eq__(self, other):
  21.         return self.x == other.x and self.y == other.y
  22.     def __ne__(self, other):
  23.         return not self.__eq__(other)
  24.  
  25. class Line:  # either a line, ray or line segment, depending on the context
  26.     def __init__(self, p, q):
  27.         self.p = p
  28.         self.q = q
  29.     def dist(self):
  30.         return self.q - self.p
  31.     def __str__(self):
  32.         return str(self.p) + "-" + str(self.q)
  33.     def __repr__(self):
  34.         return "Line(" + repr(self.p) + "," + repr(self.q) + ")"
  35.     def __eq__(self, other):
  36.         return self.p == other.p and self.q == other.q
  37.     def __ne__(self, other):
  38.         return not self.__eq__(other)
  39.  
  40. def tri_area(p, q, r):
  41.     'Returns twice the signed area of triangle p->q->r'
  42.     return ( p.x * q.y - p.y * q.x +
  43.              p.y * r.x - p.x * r.y +
  44.              q.x * r.y - r.x * q.y )
  45.  
  46. def intersect(l, m):
  47.     'Returns the intersection point of lines l and m.'
  48.     dl = l.dist()
  49.     dm = m.dist()
  50.     det = dm.x*dl.y - dl.x*dm.y
  51.     if det == 0: return None   # lines are parallel
  52.     d = m.p - l.p
  53.     f = (dm.x*d.y - dm.y*d.x)/det
  54.     return l.p + dl*f
  55.  
  56. def clip(l, m):
  57.     'Returns the line segment l clipped against the semiplane defined by m.'
  58.     a = tri_area(m.p, m.q, l.p)
  59.     b = tri_area(m.p, m.q, l.q)
  60.     if a >= 0 and b >= 0: return l     # entirely on the semiplane
  61.     if a <= 0 and b <= 0: return None  # entirely outside the semiplane
  62.     i = intersect(l, m)  # l and m cannot be parallel here
  63.     if a < 0: return Line(i, l.q)  # l.p is clipped away
  64.     if b < 0: return Line(l.p, i)  # l.q is clipped away
  65.     assert 0   # if I classified correctly, this can't happen!
  66.  
  67. def compress(a):
  68.     'Compresses a polygon by removing duplicate edges.'
  69.     return [ p for (i,p) in enumerate(a) if a[i-1] != p ]
  70.  
  71. def intersect_polygons(a, b):
  72.     'Returns the intersection of two polygons, which must be convex!'
  73.     for side in [ Line(b[i-1], b[i]) for i in range(len(b)) ]:
  74.         # Find points in polygon a after clipping to side:
  75.         c = []
  76.         for i in range(len(a)):
  77.             l = clip(Line(a[i-1], a[i]), side)
  78.             if l: c += [l.p, l.q]
  79.         # Remove duplicate endpoints:
  80.         a = [ p for (i,p) in enumerate(c) if p != c[i-1] ]
  81.     return a
  82.  
  83. a = [ Point(1,1), Point(5,3), Point(4,6) ]
  84. b = [ Point(1,1), Point(7,3), Point(2,6) ]
  85. c = intersect_polygons(a, b)
  86. print(c)
Advertisement
Add Comment
Please, Sign In to add comment