imported from "final" folder
This commit is contained in:
270
.pio/libdeps/esp01_1m/FastLED/examples/Chromancer/gen.py
Normal file
270
.pio/libdeps/esp01_1m/FastLED/examples/Chromancer/gen.py
Normal 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()
|
||||
Reference in New Issue
Block a user