def rasterize_stuff(stuff): if isinstance(stuff, gr.Polygon): pts = [(pt.x-PADDING, pt.y-PADDING) for pt in poly.points] return ras.rasterize_poly(pts) elif isinstance(stuff, gr.Circle): return ras.rasterize_circle((poly.center.x, poly.center.y), int(poly.radius))
def check_circle(center, radius): for x, y in ras.rasterize_circle(center, radius): if used[x][y]: new_radius = math.ceil(math.sqrt((x-center[0])**2 + (y-center[1])**2)) if new_radius < radius: return new_radius else: return radius - 1 return None
def circle_fill(ranges, circle_count, minrad, maxrad, decay, postfix): width = ranges[0][1] - 2*ranges[0][0] + 1 height = ranges[1][1] - 2*ranges[1][0] + 1 used = [[False for y in range(height)] for x in range(width)] used_count = 0 total_count = width * height maxrad = original_maxrad = maxrad fi = maxrad/total_count def maxrad_no_decay(): pass def maxrad_uniform_decay(): nonlocal maxrad, fi maxrad = max(5, int(fi*(total_count - used_count))) def maxrad_log_decay(): nonlocal maxrad, fi fi = math.log((1 + (total_count - used_count) / total_count), 2) maxrad = min(max(5, int(fi*(total_count - used_count))), original_maxrad) maxrad_decay = { "none": maxrad_no_decay, "uniform": maxrad_uniform_decay, "log": maxrad_log_decay }[decay] maxrad_decay() def check_circle(center, radius): for x, y in ras.rasterize_circle(center, radius): if used[x][y]: new_radius = math.ceil(math.sqrt((x-center[0])**2 + (y-center[1])**2)) if new_radius < radius: return new_radius else: return radius - 1 return None circles = [] print("Will generate", circle_count, "random circles") progress = u.make_progressbar(circle_count, timeit=True) while len(circles) < circle_count: x, y = random.randint(0, width), random.randint(0, height) cropdrad = -1 maxrad_cropped = min(x, y, width-x, height-y, maxrad) for radius in range(0, maxrad_cropped): if used[x-radius][y] or used[x+radius][y] or used[x][y-radius] or used[x][y+radius]: break cropdrad = radius if cropdrad < minrad: continue radius = cropdrad while radius >= minrad: new_radius = check_circle((x,y), radius) if new_radius is None: for cx, cy in ras.rasterize_circle((x,y), radius): used[cx][cy] = True used_count += 1 circles.append(gr.Circle(gr.Point(x + ranges[0][0], y + ranges[1][0]), radius)) maxrad_decay() progress() break else: radius = new_radius print("Area coverage {:.2f}%".format((used_count / total_count) * 100)) if postfix: print("Postfixing") progress = u.make_progressbar(len(circles), timeit=True) for i in range(0, len(circles)): progress() for j in range(0, len(circles)): if i==j: break abx = circles[j].center.x - circles[i].center.x aby = circles[j].center.y - circles[i].center.y r = circles[j].radius + circles[i].radius d2 = abd2 = abx**2 + aby**2 if d2 < r**2 - 0.01: fact = 0.5*(r - math.sqrt(d2)) / math.sqrt(abd2) abx *= fact aby *= fact circles[j].center.x += abx circles[j].center.y += aby circles[i].center.x -= abx circles[i].center.y -= aby return circles