Advertisement
Guest User

Untitled

a guest
Dec 5th, 2019
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.72 KB | None | 0 0
  1. # Starts searching using average point, then
  2. # brute forces if the above fails.
  3. # A green circle signifies success using first method.
  4. # Blue signifies brute forced.
  5.  
  6. # CONTROLS: SPACEBAR to generate, ESC to quit
  7.  
  8. # This program draws a circle if possible,
  9. # otherwise no circle is drawn, and "NO SUCH CIRCLE"
  10. # is logged in the console
  11. # Percentage of points is rounded down to nearest integer
  12. # Also, I had to draw the points as larger than 1 pixel, otherwise
  13. # they were nearly invisible. This means some points may look like
  14. # they touch the circle, but are actually outside.
  15.  
  16. # ---------------------------------------
  17. # CHANGE THESE VALUES FOR TESTING
  18. # Number of points
  19. NUM_OF_POINTS_MIN = 1
  20. NUM_OF_POINTS_MAX = 1000
  21. # Canvas size in pixels
  22. CANVAS_WIDTH = 1000
  23. CANVAS_HEIGHT = 1000
  24. # Percentage of points to lie in circle
  25. PERCENTAGE = 0.5
  26. # ---------------------------------------
  27. # Importing modules
  28. import pygame, random, math, numpy
  29.  
  30. # FUNCTIONS FOR POINTS
  31. # ---------------------------------------
  32. # Generate a single point (x,y) where x,y runs [0,1]
  33. def generatePoint():
  34.     x = random.randint(0, CANVAS_WIDTH)
  35.     y = random.randint(0, CANVAS_HEIGHT)
  36.     return (x, y)
  37. # Generate list of N points
  38. def generateNPoints(N):
  39.     points = []
  40.     for i in range(N):
  41.         points.append(generatePoint())
  42.     return points
  43. # Generate a single number N where N runs [x,y]
  44. def generateN(x, y):
  45.     return random.randint(x, y)
  46. # Generate a random list of points
  47. def generatePoints():
  48.     N = generateN(NUM_OF_POINTS_MIN, NUM_OF_POINTS_MAX)
  49.     NPoints = generateNPoints(N)
  50.     return NPoints
  51. # Draw points on screen given a list of points
  52. def drawPoints(points, surface):
  53.     for point in points:
  54.         pygame.draw.circle(surface, (255, 255, 255), point, 1)
  55. # Calculate distance between 2 given points
  56. def calculateDist(point1, point2):
  57.     return math.hypot(point1[0] - point2[0], point1[1] - point2[1])
  58. # Given a set of points, find the average point
  59. def findAveragePoint(points):
  60.     average = [int(sum(x) / len(x)) for x in zip(*points)]
  61.     return average
  62. # Given a point, determine the furthest point from it
  63. def furthestPoint(fromPoint, points):
  64.     distances = [calculateDist(fromPoint, point) for point in points]
  65.     idx = distances.index(max(distances))
  66.     return points[idx]
  67. # ---------------------------------------
  68. # END FUNCTIONS FOR POINTS
  69.  
  70. # FUNCTIONS FOR CIRCLES
  71. # ---------------------------------------
  72. # Create a circle given center and radius
  73. def createCircle(center, radius):
  74.     return (center, radius)
  75. # Draw circle on screen given circle
  76. def drawCircle(circle, surface, color):
  77.     center, radius = circle
  78.     pygame.draw.circle(surface, color, center, radius, 1)
  79. # Check if a given circle is within bounds
  80. def circleInBounds(circle):
  81.     center, radius = circle
  82.     centerX, centerY = center
  83.     leftBound, rightBound, upBound, downBound = centerX - radius, centerX + radius, centerY - radius, centerY + radius
  84.     return leftBound in range(0, CANVAS_WIDTH + 1) and rightBound in range(0, CANVAS_WIDTH + 1) and upBound in range(0, CANVAS_HEIGHT + 1) and downBound in range(0, CANVAS_HEIGHT + 1)
  85. # ---------------------------------------
  86. # END FUNCTIONS FOR CIRCLES
  87.  
  88. # FUNCTIONS FOR MAIN ALGORITHM
  89. # ---------------------------------------
  90. # Given a circle and list of points, count the number of points
  91. # that fall on / in the circle
  92. def countPointsInCircle(circle, points):
  93.     count = 0
  94.     center, radius = circle
  95.     for point in points:
  96.         count += 1 if calculateDist(point, center) <= radius else 0
  97.     return count
  98. def circleRcoverN(center, points, N, canvas):
  99.     x = center[0]
  100.     y = center[1]
  101.     maxRadius = min([x, y, CANVAS_WIDTH - x, CANVAS_HEIGHT - y])
  102.     for radius in range(maxRadius, 0, -1):
  103.         circle = createCircle(center, radius)
  104.         canvas.fill((0, 0, 0))
  105.         drawPoints(points, canvas)
  106.         drawCircle(circle, canvas, (255, 0, 0))
  107.         pygame.display.update()
  108.         pointsInCircle = countPointsInCircle(circle, points)
  109.         if (pointsInCircle == N): return circle
  110.         elif (pointsInCircle < N): return None
  111. # Given points and percentage, find a circle to cover
  112. # that many points
  113. def findCircle(points, percentage, canvas):
  114.     copyPoints = points.copy()
  115.     N = int(percentage * len(points))
  116.     while (len(copyPoints) > 0):
  117.         center = findAveragePoint(copyPoints)
  118.         circle = circleRcoverN(center, points, N, canvas)
  119.         if (circle != None): return circle
  120.         else: copyPoints.remove(furthestPoint(center, copyPoints))
  121.     return None
  122. def findCircleBrute(points, percentage, canvas):
  123.     N = int(percentage * len(points))
  124.     jump = 1 if CANVAS_WIDTH <= 10 else CANVAS_WIDTH // 10
  125.     for x in range(CANVAS_WIDTH // 2, CANVAS_WIDTH, jump):
  126.         for y in range(CANVAS_HEIGHT // 2, CANVAS_HEIGHT):
  127.             circle = circleRcoverN((x, y), points, N, canvas)
  128.             if (circle != None): return circle
  129.         for y in range(CANVAS_HEIGHT // 2 - 1, 0, -1):
  130.             circle = circleRcoverN((x, y), points, N, canvas)
  131.             if (circle != None): return circle
  132.     for x in range(CANVAS_WIDTH // 2, 0, -jump):
  133.         for y in range(CANVAS_HEIGHT // 2, CANVAS_HEIGHT):
  134.             circle = circleRcoverN((x, y), points, N, canvas)
  135.             if (circle != None): return circle
  136.         for y in range(CANVAS_HEIGHT // 2 - 1, 0, -1):
  137.             circle = circleRcoverN((x, y), points, N, canvas)
  138.             if (circle != None): return circle
  139.     return None
  140. # ---------------------------------------
  141. # END FUNCTIONS FOR MAIN ALGORITHM
  142.  
  143. # FUNCTIONS FOR PYGAME
  144. # ---------------------------------------
  145. # Main call for PyGame
  146. def main():
  147.     # Initialize PyGame
  148.     pygame.init()
  149.     canvas = pygame.display.set_mode([CANVAS_WIDTH, CANVAS_HEIGHT])
  150.     def initPyGame():
  151.         p = generatePoints()
  152.         c = findCircle(p, PERCENTAGE, canvas)
  153.         if (c != None):
  154.             canvas.fill((0, 0, 0))
  155.             drawPoints(p, canvas)
  156.             drawCircle(c, canvas, (0, 255, 0))
  157.             pygame.display.update()
  158.         else:
  159.             c2 = findCircleBrute(p, PERCENTAGE, canvas)
  160.             canvas.fill((0, 0, 0))
  161.             drawPoints(p, canvas)
  162.             drawCircle(c2, canvas, (0, 0, 255)) if c2 != None else print("NO BRUTE CIRCLE")
  163.             pygame.display.update()
  164.         while True:
  165.             for event in pygame.event.get():
  166.                 key = pygame.key.get_pressed()
  167.                 if event.type == pygame.QUIT or key[pygame.K_ESCAPE]:
  168.                     pygame.quit()
  169.                     exit()
  170.                 if key[pygame.K_SPACE]:
  171.                     initPyGame()
  172.     initPyGame()
  173. main()
  174. # ---------------------------------------
  175. # END OF FILE
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement