Skip to content

XmasTreeLayout

XmasTreeLayout is a 3D Layout module that maps one or more LED strings onto a conical Christmas-tree shape. Each string winds from the base (y=0, widest) to the tip (y=height-1, single centre point) using the golden-angle distribution so consecutive LEDs rotate ~137.5° around the axis. The result is a naturally scattered, non-repeating spiral that looks organic without any runtime randomness — positions are fully deterministic.

Purpose

A real Christmas tree is a 3D cone, not a flat triangle. With XmasTreeLayout any 3D effect renders on the full virtual cube and only the cells occupied by the spiral string(s) receive colour. The WebGL previewer renders the lit LEDs as a 3D point cloud, showing the conical silhouette from any orbit angle.

Controls

Key UI type Min Max Default Description
ledsPerString slider 8 500 50 LEDs per string
strings slider 1 8 1 Number of strings, spread evenly around the cone
height slider 4 32 12 Virtual grid height; also sets cone radius and grid width

Total physical LEDs: strings * ledsPerString.

Wiring

Add as a child of a DriverLayer:

{ "type": "XmasTreeLayout", "id": "tree1", "parent_id": "driver1",
  "props": { "height": 16, "ledsPerString": 100, "strings": 2 } }

Behaviour

  • Virtual grid: (2h-1) x h x (2h-1). Default height=12 gives a 23 x 12 x 23 cube (6348 virtual cells, 50 physical LEDs).
  • Cone geometry: at normalised position t along the string (0=base, 1=tip), the LED sits at height y = round(t * (h-1)) and cone radius r = (1-t) * (h-1). Radius shrinks linearly from h-1 at the base to 0 at the tip.
  • Golden-angle spiral: consecutive LEDs rotate by 2.3999... radians (~137.5°), the golden angle. This gives the most uniform coverage of the cone surface without bunching.
  • Multiple strings: string s starts with an angular offset of s * 2π / strings, so strings spread evenly around the circumference.
  • Tip mapping: the last LED in every string always maps to the virtual centre-top cell (h-1, h-1, h-1).
  • onUpdate: any control change triggers onChildrenReady() on the parent DriverLayer to rebuild the PhysMap.

LED count and grid size

height ledsPerString strings total LEDs virtual grid
8 30 1 30 15 x 8 x 15
12 50 1 50 23 x 12 x 23
16 100 2 200 31 x 16 x 31
24 200 3 600 47 x 24 x 47

Test coverage

See Non-Rectangular Layouts:

  • Extent is (2h-1) x h x (2h-1) with d == w (square footprint)
  • physCount equals strings * ledsPerString
  • First LED decodes to y=0 (base layer)
  • Last LED decodes to (cx, h-1, cz) (centre tip)
  • All virtual indices within 3D grid bounds
  • Two strings produce double the LED count

Source