Advertisement
Guest User

python code for 2D circle-surface

a guest
Oct 24th, 2013
754
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.56 KB | None | 0 0
  1. import pygame
  2. import random
  3. import math
  4.  
  5. pygame.init()
  6.  
  7. screen = pygame.display.set_mode([300,300])
  8.  
  9. def random_point_coud_2D(n, radius=10, deviation=3):
  10.     pts = [(0, 0)]*n
  11.     for i in range(n):
  12.         angle = random.random() * 2 * math.pi
  13.         rad = random.gauss(radius, deviation)
  14.         pts[i] = (math.cos(angle)*rad, math.sin(angle)*rad)
  15.     return pts
  16.  
  17. def translate_pts(pts, shift):
  18.     return [(pt[0] + shift[0], pt[1] + shift[1])for pt in pts]
  19.  
  20. def pt_center(pts):
  21.     if(len(pts) == 0):
  22.         return (0,0)
  23.     sum_x = 0
  24.     sum_y = 0
  25.     for (x, y) in pts:
  26.         sum_x += x
  27.         sum_y += y
  28.     return (sum_x / len(pts), sum_y / len(pts))
  29.  
  30. def dot(ptA, ptB):
  31.     return ptA[0]*ptB[0] + ptA[1]*ptB[1]
  32.  
  33. def crossz(ptA, ptB):
  34.     return ptA[0]*ptB[1] - ptA[1]*ptB[0]
  35.  
  36. def norm(vec):
  37.     l = math.sqrt(vec[0]*vec[0] + vec[1]*vec[1])
  38.     return (vec[0] / l, vec[1] / l)
  39.  
  40. def point_in_triangle(pt, edges):
  41.     for (ptA, ptB) in edges:
  42.         vecside = norm((ptB[0]-ptA[0], ptB[1]-ptA[1]))
  43.         vecpt = norm((pt[0]-ptA[0], pt[1]-ptA[1]))
  44.         side = (crossz(vecside, vecpt) > 0) # pt is on correct side of this edge
  45.         proj = 0 <= dot(vecside, vecpt) and dot(vecside, vecpt) <= 1 # pt lies between A and B in projection
  46.         if(not (side and proj)):
  47.             # test failed for any edge.. fails overall
  48.             return False
  49.     return True
  50.  
  51. # this is a hack. horrible n^3 time
  52. def get_center_triangle(pts):
  53.     # sort points in terms of angle from x-axis
  54.     pts.sort( cmp=lambda (ax, ay), (bx, by): cmp(math.atan2(ay, ax), math.atan2(by, bx)))
  55.     # test every combination of 3 points
  56.     for i in range(len(pts)):
  57.         ptA = pts[i]
  58.         for j in range(len(pts)):
  59.             if j == i:
  60.                 continue
  61.             ptB = pts[j]
  62.             for k in range(len(pts)):
  63.                 if k == j or k == i:
  64.                     continue
  65.                 ptC = pts[k]
  66.                 if point_in_triangle((0,0), [(ptA, ptB), (ptB, ptC), (ptC, ptA)]):
  67.                     return (ptA, ptB, ptC)
  68.     print "NO CENTER TRIANGLE FOUND"
  69.     return None
  70.  
  71. def surface(pts):
  72.     center = pt_center(pts)
  73.     tx = -center[0]
  74.     ty = -center[1]
  75.     pts = translate_pts(pts, (tx, ty))
  76.     # tricky part: initialization
  77.     # initialize edges such that you have a triangle with the origin inside of it
  78.     # in 3D, this will be a tetrahedron.
  79.     ptA, ptB, ptC = get_center_triangle(pts)
  80.     print ptA, ptB, ptC
  81.     # tracking edges we've already included (triangles in 3D)
  82.     edges = [(ptA, ptB), (ptB, ptC), (ptC, ptA)]
  83.     # loop over all other points
  84.     pts.remove(ptA)
  85.     pts.remove(ptB)
  86.     pts.remove(ptC)
  87.     for pt in pts:
  88.         ptA = (0,0)
  89.         ptB = (0,0)
  90.         # find the edge that this point will be splitting
  91.         for (ptA, ptB) in edges:
  92.             if crossz(ptA, pt) > 0 and crossz(pt, ptB) > 0:
  93.                 break
  94.         edges.remove((ptA, ptB))
  95.         edges.append((ptA, pt))
  96.         edges.append((pt, ptB))
  97.     # translate everything back
  98.     edges = [((ptA[0] - tx, ptA[1] - ty), (ptB[0] - tx, ptB[1] - ty)) for (ptA, ptB) in edges]
  99.     return edges
  100.  
  101. # PYGAME/GRAPHICS
  102.  
  103. def clear_screen():
  104.     screen.fill([255,255,255])
  105.  
  106. def draw_pts(pts, clear=True, size=1):
  107.     if clear:
  108.         clear_screen()
  109.     for pt in pts:
  110.         pygame.draw.circle(screen, (0, 0, 0), (int(pt[0]), int(pt[1])), size)
  111.  
  112. def draw_lines(lines, clear=True, size=1):
  113.     if(clear):
  114.         clear_screen()
  115.     for line in lines:
  116.         pygame.draw.line(screen, (0,0,0), (int(line[0][0]), int(line[0][1])), (int(line[1][0]), int(line[1][1])), size)
  117.  
  118. def draw_scene(pts, lines):
  119.     draw_pts(pts, size=3)
  120.     draw_lines(lines, clear=False)
  121.     pygame.display.update()
  122.  
  123. if __name__ == '__main__':
  124.     pts = random_point_coud_2D(100, radius=100, deviation=10)
  125.     pts = translate_pts(pts, (150, 150))
  126.     # draw_scene(pts, [])
  127.     # pause = raw_input()
  128.     draw_scene(pts, surface(pts))
  129.     pause = raw_input()
  130.     pygame.quit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement