Skip to content

Instantly share code, notes, and snippets.

@FoamyGuy
Created December 6, 2025 17:40
Show Gist options
  • Select an option

  • Save FoamyGuy/aa97201f18161e718f0d12159a914541 to your computer and use it in GitHub Desktop.

Select an option

Save FoamyGuy/aa97201f18161e718f0d12159a914541 to your computer and use it in GitHub Desktop.
import math
import bitmaptools
import displayio
import supervisor
import time
from adafruit_usb_host_mouse import find_and_init_boot_mouse
def split_points(_points):
_xs = []
_ys = []
for point in _points:
_xs.append(point[0])
_ys.append(point[1])
return bytes(_xs), bytes(_ys)
def distance(point_a, point_b):
x1, y1 = point_a
x2, y2 = point_b
return math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
def point_in_polygon(point, polygon):
"""
Determine if a point is inside a polygon using ray casting algorithm.
Args:
point: tuple (x, y) representing the point to test
polygon: list of tuples [(x1, y1), (x2, y2), ...] representing polygon vertices
Returns:
bool: True if point is inside polygon, False otherwise
"""
x, y = point
n = len(polygon)
inside = False
# Iterate through each edge of the polygon
p1x, p1y = polygon[0]
for i in range(1, n + 1):
p2x, p2y = polygon[i % n]
# Check if point is within the y-bounds of this edge
if y > min(p1y, p2y):
if y <= max(p1y, p2y):
if x <= max(p1x, p2x):
# Calculate x-intersection of the ray with the edge
if p1y != p2y:
x_intersection = (y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x
# If edge is vertical or point is to the left of intersection, toggle
if p1x == p2x or x <= x_intersection:
inside = not inside
p1x, p1y = p2x, p2y
return inside
def find_point_in_polygon(polygon):
# a_vertex = polygon[0]
#
# for _x in range(-3, 4):
# for _y in range(-3, 4):
# checking_point = (a_vertex[0] + _x, a_vertex[1] + _y)
# if point_in_polygon(checking_point, polygon):
# if snowflake_bmp[checking_point] == 1:
# return checking_point
if len(polygon) == 3:
x1, y1 = polygon[0]
x2, y2 = polygon[1]
x3, y3 = polygon[2]
centroid_x = (x1 + x2 + x3) // 3
centroid_y = (y1 + y2 + y3) // 3
return (centroid_x, centroid_y)
for i in range(len(polygon)):
point = polygon[i]
for j in range(len(polygon)):
checking_point = polygon[j]
if i != j and j != i + 1 and j != i - 1:
x1, y1 = point
x2, y2 = checking_point
midway = ((x1 + x2) // 2, (y1 + y2) // 2)
if point_in_polygon(midway, polygon):
if snowflake_bmp[midway] == 1:
print(midway)
return midway
return None
CLICK_COOLDOWN = 0.5
last_click_time = -1
display = supervisor.runtime.display
main_group = displayio.Group()
display.root_group = main_group
palette = displayio.Palette(3)
palette[0] = 0x000066
palette[1] = 0xffffff
palette[2] = 0xff0000
snowflake_bmp = displayio.Bitmap(120, 120, 3)
snowflake_bmp.fill(1)
top_left_tg = displayio.TileGrid(snowflake_bmp, pixel_shader=palette)
main_group.append(top_left_tg)
# points = [(0, 0), (40, 0), (0, 40)]
# xs, ys = split_points(points)
# bitmaptools.draw_polygon(snowflake_bmp, xs, ys, 0)
# bitmaptools.boundary_fill(snowflake_bmp, 1,1, 0, 1)
top_right_tg = displayio.TileGrid(snowflake_bmp, pixel_shader=palette)
top_right_tg.flip_x = True
top_right_tg.x = top_left_tg.x + top_left_tg.tile_width
main_group.append(top_right_tg)
bottom_left_tg = displayio.TileGrid(snowflake_bmp, pixel_shader=palette)
bottom_left_tg.flip_y = True
bottom_left_tg.y = top_left_tg.y + top_left_tg.tile_height
main_group.append(bottom_left_tg)
bottom_right_tg = displayio.TileGrid(snowflake_bmp, pixel_shader=palette)
bottom_right_tg.flip_x = True
bottom_right_tg.flip_y = True
bottom_right_tg.x = top_left_tg.x + top_left_tg.tile_width
bottom_right_tg.y = top_left_tg.y + top_left_tg.tile_height
main_group.append(bottom_right_tg)
mouse = find_and_init_boot_mouse()
if mouse is None:
raise RuntimeError("No mouse found connected to USB Host")
# add the mouse tile grid to the main group
main_group.append(mouse.tilegrid)
clicked_points = []
# display.auto_refresh = False
while True:
# update mouse
pressed_btns = mouse.update()
mouse.x = min(mouse.x, top_left_tg.x + top_left_tg.tile_width - 1)
mouse.y = min(mouse.y, top_left_tg.y + top_left_tg.tile_height - 1)
now = time.monotonic()
if pressed_btns:
if "left" in pressed_btns and now >= last_click_time + CLICK_COOLDOWN:
# print(pressed_btns)
last_click_time = now
cur_clicked_point = ((mouse.x, mouse.y))
if len(clicked_points) == 0:
clicked_points.append(cur_clicked_point)
snowflake_bmp[cur_clicked_point] = 0
display.refresh()
continue
if distance(cur_clicked_point, clicked_points[0]) < 10:
# points = [(0, 0), (40, 0), (0, 40)]
xs, ys = split_points(clicked_points)
bitmaptools.draw_polygon(snowflake_bmp, xs, ys, 0)
inner_point = find_point_in_polygon(clicked_points)
print(f"polygon: ", clicked_points)
bitmaptools.boundary_fill(snowflake_bmp, inner_point[0], inner_point[1], 0, 1)
snowflake_bmp[inner_point] = 2
clicked_points.clear()
display.refresh()
else:
clicked_points.append(cur_clicked_point)
snowflake_bmp[cur_clicked_point] = 0
display.refresh()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment