imported from "final" folder

This commit is contained in:
2025-11-28 12:12:50 +01:00
parent f9288986cf
commit ff8e725b35
1061 changed files with 225150 additions and 96 deletions

View File

@@ -0,0 +1,270 @@
"""
Generates the hexegon using math.
"""
from dataclasses import dataclass
from enum import Enum
import json
from math import pi, cos, sin
LED_PER_STRIP = 14
SPACE_PER_LED = 30.0 # Increased for better visibility
LED_DIAMETER = SPACE_PER_LED / 4
MIRROR_X = True # Diagramed from the reverse side. Reverse the x-axis
SMALLEST_ANGLE = 360 / 6
class HexagonAngle(Enum):
UP = 90
DOWN = 270
RIGHT_UP = 30
RIGHT_DOWN = 360 - 30
LEFT_UP = 150 # (RIGHT_DOWN + 180) % 360
LEFT_DOWN = 210 # (RIGHT_UP + 180) % 360
def toRads(angle: float) -> float:
return angle * (pi / 180)
@dataclass
class Point:
x: float
y: float
@staticmethod
def toJson(points: list["Point"]) -> list[dict]:
x_values = [p.x for p in points]
y_values = [p.y for p in points]
# round
x_values = [round(x, 4) for x in x_values]
y_values = [round(y, 4) for y in y_values]
if MIRROR_X:
x_values = [-x for x in x_values]
return {"x": x_values, "y": y_values, "diameter": LED_DIAMETER}
def copy(self) -> "Point":
return Point(self.x, self.y)
def __repr__(self) -> str:
x_rounded = round(self.x, 2)
y_rounded = round(self.y, 2)
return f"({x_rounded}, {y_rounded})"
def next_point(pos: Point, angle: HexagonAngle, space: float) -> Point:
degrees = angle.value
angle_rad = toRads(degrees)
x = pos.x + space * cos(angle_rad)
y = pos.y + space * sin(angle_rad)
return Point(x, y)
def gen_points(
input: list[HexagonAngle], leds_per_strip: int, startPos: Point,
exclude: list[int] | None = None,
add_last: bool = False
) -> list[Point]:
points: list[Point] = []
if (not input) or (not leds_per_strip):
return points
exclude = exclude or []
# Start FSM. Start pointer get's put into the accumulator.
curr_point: Point = Point(startPos.x, startPos.y)
# points.append(curr_point)
last_angle = input[0]
for i,angle in enumerate(input):
excluded = i in exclude
values = list(range(leds_per_strip))
last_angle = angle
for v in values:
last_angle = angle
curr_point = next_point(curr_point, angle, SPACE_PER_LED)
if not excluded:
points.append(curr_point)
#if i == len(input) - 1:
# break
# Next starting point
curr_point = next_point(curr_point, last_angle, SPACE_PER_LED)
#if not excluded:
# points.append(curr_point)
if add_last:
points.append(curr_point)
return points
def main() -> None:
startPos = Point(0, 0)
hexagon_angles = [
HexagonAngle.UP,
HexagonAngle.RIGHT_UP,
HexagonAngle.RIGHT_DOWN,
HexagonAngle.DOWN,
HexagonAngle.LEFT_DOWN,
HexagonAngle.LEFT_UP,
]
points = gen_points(hexagon_angles, LED_PER_STRIP, startPos)
print(points)
def simple_test() -> None:
startPos = Point(0, 0)
hexagon_angles = [
HexagonAngle.UP,
]
points = gen_points(hexagon_angles, LED_PER_STRIP, startPos)
print(points)
# assert len(points) == LED_PER_STRIP + 1
def two_angle_test() -> None:
startPos = Point(0, 0)
hexagon_angles = [
HexagonAngle.UP,
HexagonAngle.UP,
]
points = gen_points(hexagon_angles, LED_PER_STRIP, startPos)
print(points)
# assert len(points) == LED_PER_STRIP * 2, f"Expected {LED_PER_STRIP * 2} points, got {len(points)} points"
def two_angle_test2() -> None:
print("two_angle_test2")
startPos = Point(0, 0)
hexagon_angles = [
HexagonAngle.UP,
HexagonAngle.DOWN,
]
points = gen_points(hexagon_angles, LED_PER_STRIP, startPos)
print(points)
# assert len(points) == LED_PER_STRIP * 2, f"Expected {LED_PER_STRIP * 2} points, got {len(points)} points"
# Red is defined by this instruction tutorial: https://voidstar.dozuki.com/Guide/Chromance+Assembly+Instructions/6
def find_red_anchor_point() -> list[Point]:
hexagon_angles = [
HexagonAngle.LEFT_UP,
HexagonAngle.LEFT_UP,
HexagonAngle.UP,
HexagonAngle.RIGHT_UP,
]
points = gen_points(hexagon_angles, LED_PER_STRIP, Point(0, 0), add_last=True)
return points
def find_green_anchore_point() -> list[Point]:
hexagon_angles = [
HexagonAngle.RIGHT_UP,
HexagonAngle.RIGHT_UP,
HexagonAngle.UP,
]
points = gen_points(hexagon_angles, LED_PER_STRIP, Point(0, 0), add_last=True)
return points
RED_ANCHOR_POINT = find_red_anchor_point()[-1]
BLACK_ANCHOR_POINT = Point(0,0) # Black
GREEN_ANCHOR_POINT = find_green_anchore_point()[-1]
BLUE_ANCHOR_POINT = Point(0, 0)
def generate_red_points() -> list[Point]:
starting_point = RED_ANCHOR_POINT.copy()
hexagon_angles = [
HexagonAngle.UP,
HexagonAngle.LEFT_UP,
HexagonAngle.LEFT_DOWN,
HexagonAngle.DOWN,
HexagonAngle.RIGHT_DOWN,
HexagonAngle.UP,
HexagonAngle.LEFT_UP
]
points = gen_points(hexagon_angles, LED_PER_STRIP, starting_point, exclude=[5])
return points
def generate_black_points() -> list[Point]:
starting_point = BLACK_ANCHOR_POINT.copy()
hexagon_angles = [
HexagonAngle.LEFT_UP,
HexagonAngle.LEFT_UP,
HexagonAngle.UP,
HexagonAngle.RIGHT_UP,
HexagonAngle.RIGHT_DOWN,
HexagonAngle.DOWN,
HexagonAngle.LEFT_DOWN,
HexagonAngle.UP,
HexagonAngle.LEFT_UP,
HexagonAngle.UP,
HexagonAngle.RIGHT_UP,
]
points = gen_points(hexagon_angles, LED_PER_STRIP, starting_point)
return points
def generate_green_points() -> list[Point]:
starting_point = GREEN_ANCHOR_POINT.copy()
hexagon_angles = [
HexagonAngle.RIGHT_UP,
HexagonAngle.UP,
HexagonAngle.LEFT_UP,
HexagonAngle.LEFT_DOWN,
HexagonAngle.DOWN,
HexagonAngle.RIGHT_DOWN, # skip
HexagonAngle.LEFT_DOWN, # skip
HexagonAngle.LEFT_UP,
HexagonAngle.UP,
HexagonAngle.RIGHT_UP,
HexagonAngle.LEFT_UP,
HexagonAngle.LEFT_DOWN,
HexagonAngle.RIGHT_DOWN,
HexagonAngle.RIGHT_UP, # skip
HexagonAngle.RIGHT_DOWN,
]
points = gen_points(hexagon_angles, LED_PER_STRIP, starting_point, exclude=[5,6,13])
return points
def generate_blue_points() -> list[Point]:
starting_point = BLUE_ANCHOR_POINT.copy()
hexagon_angles = [
HexagonAngle.RIGHT_UP,
HexagonAngle.RIGHT_UP,
HexagonAngle.UP,
HexagonAngle.LEFT_UP,
HexagonAngle.LEFT_DOWN,
HexagonAngle.LEFT_DOWN,
HexagonAngle.RIGHT_DOWN, # skip
HexagonAngle.RIGHT_DOWN,
HexagonAngle.UP,
HexagonAngle.RIGHT_UP,
HexagonAngle.UP,
HexagonAngle.RIGHT_UP,
]
points = gen_points(hexagon_angles, LED_PER_STRIP, starting_point, exclude=[6])
return points
def unit_test() -> None:
#simple_test()
#two_angle_test()
out = {}
map = out.setdefault("map", {})
map.update({
"red_segment": Point.toJson(generate_red_points()),
"back_segment": Point.toJson(generate_black_points()),
"green_segment": Point.toJson(generate_green_points()),
"blue_segment": Point.toJson(generate_blue_points()),
})
print(json.dumps(out))
# write it out to a file
with open("output.json", "w") as f:
f.write(json.dumps(out))
if __name__ == "__main__":
unit_test()