FastLED 3.9.15
Loading...
Searching...
No Matches

◆ generateMap()

void fl::generateMap ( const Corkscrew::Input & input,
CorkscrewOutput & output )

Definition at line 12 of file corkscrew.cpp.

12 {
13 // Calculate circumference per turn from height and total angle
14 float circumferencePerTurn = input.totalHeight * TWO_PI / input.totalAngle;
15
16 // Calculate vertical segments based on number of turns
17 // For a single turn (2π), we want exactly 1 vertical segment
18 // For two turns (4π), we want exactly 2 vertical segments
19 uint16_t verticalSegments = round(input.totalAngle / TWO_PI);
20
21 // Calculate width based on LED density per turn
22 float ledsPerTurn = static_cast<float>(input.numLeds) / verticalSegments;
23
24 // Determine cylindrical dimensions
25 output.height = verticalSegments;
26 output.width = ceil(ledsPerTurn);
27
28 output.mapping.clear();
29
30 // If numLeds is specified, use that for mapping size instead of grid
31 if (input.numLeds > 0) {
32 output.mapping.reserve(input.numLeds);
33
34 // Generate LED mapping based on numLeds
35 for (uint16_t i = 0; i < input.numLeds; ++i) {
36 // Calculate position along the corkscrew (0.0 to 1.0)
37 float position = static_cast<float>(i) / (input.numLeds - 1);
38
39 // Calculate angle and height
40 float angle = position * input.totalAngle;
41 float height = position * verticalSegments;
42
43 // Calculate circumference position
44 float circumference = fmodf(angle * circumferencePerTurn / TWO_PI,
45 circumferencePerTurn);
46
47 // Store the mapping
48 output.mapping.push_back({circumference, height});
49 }
50 } else {
51 // Original grid-based mapping
52 output.mapping.reserve(output.width * output.height);
53
54 // Corrected super sampling step size
55 float thetaStep = 0.5f / output.width;
56 float hStep = 0.5f / output.height;
57
58 // Precompute angle per segment
59 float anglePerSegment = input.totalAngle / verticalSegments;
60
61 // Loop over cylindrical pixels
62 for (uint16_t h = 0; h < output.height; ++h) {
63 float segmentOffset = input.offsetCircumference * h;
64 for (uint16_t w = 0; w < output.width; ++w) {
65 vec2f sample = {0, 0};
66 // 2x2 supersampling
67 for (uint8_t ssH = 0; ssH < 2; ++ssH) {
68 for (uint8_t ssW = 0; ssW < 2; ++ssW) {
69 float theta =
70 (w + 0.5f + ssW * thetaStep) / output.width;
71 float height = (h + 0.5f + ssH * hStep) / output.height;
72
73 // Corkscrew projection (θ,h)
74 float corkscrewTheta =
75 theta * TWO_PI + anglePerSegment * h;
76 float corkscrewH = height * verticalSegments;
77
78 // Apply circumference offset
79 float corkscrewCircumference = fmodf(
80 corkscrewTheta * circumferencePerTurn / TWO_PI +
81 segmentOffset,
82 circumferencePerTurn);
83
84 // Accumulate samples
85 sample.x += corkscrewCircumference;
86 sample.y += corkscrewH;
87 }
88 }
89
90 // Average the supersampled points
91 sample.x *= 0.25f;
92 sample.y *= 0.25f;
93
94 output.mapping.push_back(sample);
95 }
96 }
97 }
98
99 // Apply inversion if requested
100 if (input.invert) {
101 fl::reverse(output.mapping.begin(), output.mapping.end());
102 }
103}
#define TWO_PI
Definition corkscrew.cpp:6
T ceil(T value)
Definition math.h:18
vec2< float > vec2f
Definition geometry.h:318
void reverse(Iterator first, Iterator last)
Definition algorithm.h:8
float offsetCircumference
Definition corkscrew.h:52
fl::vector< fl::vec2f, fl::allocator_psram< fl::vec2f > > mapping
Definition corkscrew.h:66
#define round(x)
Definition util.h:10

References ceil(), fl::CorkscrewOutput::height, fl::CorkscrewInput::invert, fl::CorkscrewOutput::mapping, fl::CorkscrewInput::numLeds, fl::CorkscrewInput::offsetCircumference, reverse(), round, fl::CorkscrewInput::totalAngle, fl::CorkscrewInput::totalHeight, TWO_PI, fl::CorkscrewOutput::width, fl::vec2< T >::x, and fl::vec2< T >::y.

Referenced by fl::Corkscrew::Corkscrew(), and fl::Corkscrew::generateMap().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: