FastLED 3.9.15
Loading...
Searching...
No Matches
corkscrew.h
Go to the documentation of this file.
1#pragma once
2
31
32#include "fl/stl/allocator.h"
33#include "fl/math/geometry.h"
34#include "fl/math/math.h"
35#include "fl/gfx/tile2x2.h"
36#include "fl/stl/vector.h"
37#include "fl/stl/shared_ptr.h"
38#include "fl/stl/variant.h"
39#include "fl/stl/span.h"
40#include "fl/stl/int.h"
41#include "fl/stl/noexcept.h"
42
43namespace fl {
44
45// Forward declarations
46class Leds;
47class ScreenMap;
48template<typename T> class Grid;
49
50// Simple constexpr functions for compile-time corkscrew dimension calculation
51constexpr fl::u16 calculateCorkscrewWidth(float totalTurns, fl::u16 numLeds) {
52 return static_cast<fl::u16>(ceil_constexpr(static_cast<float>(numLeds) / totalTurns));
53}
54
55constexpr fl::u16 calculateCorkscrewHeight(float totalTurns, fl::u16 numLeds) {
56 return (calculateCorkscrewWidth(totalTurns, numLeds) * static_cast<int>(ceil_constexpr(totalTurns)) > numLeds) ?
57 static_cast<fl::u16>(ceil_constexpr(static_cast<float>(numLeds) / static_cast<float>(calculateCorkscrewWidth(totalTurns, numLeds)))) :
58 static_cast<fl::u16>(ceil_constexpr(totalTurns));
59}
60
64struct Gap {
65 int num_leds = 0; // Number of LEDs after which gap is activated, 0 = no gap
66 float gap = 0.0f; // Gap value from 0 to 1, represents percentage of width unit to add
67
68 Gap() FL_NOEXCEPT = default;
69 Gap(float g) : num_leds(0), gap(g) {} // Backwards compatibility constructor
70 Gap(int n, float g) : num_leds(n), gap(g) {} // New constructor with num_leds
71
72 // Rule of 5 for POD data
73 Gap(const Gap &other) FL_NOEXCEPT = default;
74 Gap &operator=(const Gap &other) = default;
75 Gap(Gap &&other) FL_NOEXCEPT = default;
76 Gap &operator=(Gap &&other) FL_NOEXCEPT = default;
77};
78
79// Maps a Corkscrew defined by the input to a cylindrical mapping for rendering
80// a densly wrapped LED corkscrew.
81class Corkscrew {
82 public:
83
84 // Pixel storage variants - can hold either external span or owned vector
85 using PixelStorage = fl::variant<fl::span<CRGB>, fl::vector_psram<CRGB>>;
86
87 // Iterator class moved from CorkscrewState
88 class iterator {
89 public:
91 using difference_type = fl::i32;
92 using pointer = vec2f *;
93 using reference = vec2f &;
95
96 iterator(const Corkscrew *corkscrew, fl::size position)
97 : mCorkscrew(corkscrew), mPosition(position) {}
98
99 vec2f operator*() const;
100
102 ++mPosition;
103 return *this;
104 }
105
107 iterator temp = *this;
108 ++mPosition;
109 return temp;
110 }
111
113 --mPosition;
114 return *this;
115 }
116
118 iterator temp = *this;
119 --mPosition;
120 return temp;
121 }
122
123 bool operator==(const iterator &other) const {
124 return mPosition == other.mPosition;
125 }
126
127 bool operator!=(const iterator &other) const {
128 return mPosition != other.mPosition;
129 }
130
131 difference_type operator-(const iterator &other) const {
132 return static_cast<difference_type>(mPosition) -
133 static_cast<difference_type>(other.mPosition);
134 }
135
136 private:
138 fl::size mPosition;
139 };
140
141 // Constructors that integrate input parameters directly
142 // Primary constructor with default values for invert and gapParams
143 Corkscrew(float totalTurns, fl::u16 numLeds, bool invert = false, const Gap& gapParams = Gap());
144
145 // Constructor with external pixel buffer - these pixels will be drawn to directly
146 Corkscrew(float totalTurns, fl::span<CRGB> dstPixels, bool invert = false, const Gap& gapParams = Gap());
147
148 Corkscrew(const Corkscrew &) FL_NOEXCEPT = default;
150
151 // Caching control
152 void setCachingEnabled(bool enabled);
153
154 // Essential API - Core functionality
155 fl::u16 cylinderWidth() const { return mWidth; }
156 fl::u16 cylinderHeight() const { return mHeight; }
157
158 // Enhanced surface handling with shared_ptr
159 // Note: Input surface will be created on first call
161
162 // Draw like a regular rectangle surface - access input surface directly
164
165 // Draw the corkscrew by reading from the internal surface and populating LED pixels
166 void draw(bool use_multi_sampling = true);
167
168 // Pixel storage access - works with both external and owned pixels
169 // This represents the pixels that will be drawn after draw() is called
170 CRGB* rawData();
171
172 // Returns span of pixels that will be written to when draw() is called
174
175 fl::size pixelCount() const;
176 // Create and return a fully constructed ScreenMap for this corkscrew
177 // Each LED index will be mapped to its exact position on the cylindrical surface
178 fl::ScreenMap toScreenMap(float diameter = 0.5f) const;
179
180 // STL-style container interface
181 fl::size size() const;
182 iterator begin() { return iterator(this, 0); }
183 iterator end() { return iterator(this, size()); }
184
185 // Non-essential API - Lower level access
186 vec2f at_no_wrap(fl::u16 i) const;
187 vec2f at_exact(fl::u16 i) const;
188 Tile2x2_u8_wrap at_wrap(float i) const;
189
190 // Clear all buffers and free memory
191 void clear();
192
193 // Fill the input surface with a color
194 void fillInputSurface(const CRGB& color);
195
196 private:
197 // For internal use. Splats the pixel on the surface which
198 // extends past the width. This extended Tile2x2 is designed
199 // to be wrapped around with a Tile2x2_u8_wrap.
200 Tile2x2_u8 at_splat_extrapolate(float i) const;
201
202 // Read from fl::Grid<CRGB> object and populate our internal rectangular buffer
203 // by sampling from the XY coordinates mapped to each corkscrew LED position
204 // use_multi_sampling = true will use multi-sampling to sample from the source grid,
205 // this will give a little bit better accuracy and the screenmap will be more accurate.
206 void readFrom(const fl::Grid<CRGB>& source_grid, bool use_multi_sampling = true);
207
208 // Read from rectangular buffer using multi-sampling and store in target grid
209 // Uses Tile2x2_u8_wrap for sub-pixel accurate sampling with proper blending
210 void readFromMulti(const fl::Grid<CRGB>& target_grid) const;
211
212 // Initialize the rectangular buffer if not already done
213 void initializeBuffer() const;
214
215 // Initialize the cache if not already done and caching is enabled
216 void initializeCache() const;
217
218 // Calculate the tile at position i without using cache
220
221 // Core corkscrew parameters (moved from CorkscrewInput)
222 float mTotalTurns = 19.0f; // Total turns of the corkscrew
223 fl::u16 mNumLeds = 144; // Number of LEDs
224 Gap mGapParams; // Gap parameters for gap accounting
225 bool mInvert = false; // If true, reverse the mapping order
226
227 // Cylindrical mapping dimensions (moved from CorkscrewState)
228 fl::u16 mWidth = 0; // Width of cylindrical map (circumference of one turn)
229 fl::u16 mHeight = 0; // Height of cylindrical map (total vertical segments)
230
231 // Enhanced pixel storage - variant supports both external and owned pixels
233 bool mOwnsPixels = false; // Track whether we own the pixel data
234
235 // Input surface for drawing operations
237
238 // Caching for Tile2x2_u8_wrap objects
240 mutable bool mCacheInitialized = false;
241 bool mCachingEnabled = true; // Default to enabled
242};
243
244} // namespace fl
bool operator!=(const iterator &other) const
Definition corkscrew.h:127
iterator & operator--()
Definition corkscrew.h:112
difference_type operator-(const iterator &other) const
Definition corkscrew.h:131
const Corkscrew * mCorkscrew
Definition corkscrew.h:137
iterator(const Corkscrew *corkscrew, fl::size position)
Definition corkscrew.h:96
iterator operator--(int)
Definition corkscrew.h:117
iterator & operator++()
Definition corkscrew.h:101
iterator operator++(int)
Definition corkscrew.h:106
fl::bidirectional_iterator_tag iterator_category
Definition corkscrew.h:94
bool operator==(const iterator &other) const
Definition corkscrew.h:123
fl::variant< fl::span< CRGB >, fl::vector_psram< CRGB > > PixelStorage
Definition corkscrew.h:85
fl::shared_ptr< fl::Grid< CRGB > > & getOrCreateInputSurface()
Tile2x2_u8 at_splat_extrapolate(float i) const
Tile2x2_u8_wrap calculateTileAtWrap(float i) const
Corkscrew(Corkscrew &&) FL_NOEXCEPT=default
void setCachingEnabled(bool enabled)
Corkscrew(const Corkscrew &) FL_NOEXCEPT=default
fl::ScreenMap toScreenMap(float diameter=0.5f) const
Corkscrew(float totalTurns, fl::u16 numLeds, bool invert=false, const Gap &gapParams=Gap())
fl::Grid< CRGB > & surface()
fl::u16 mWidth
Definition corkscrew.h:228
iterator end()
Definition corkscrew.h:183
fl::u16 cylinderWidth() const
Definition corkscrew.h:155
fl::span< CRGB > data()
fl::u16 mNumLeds
Definition corkscrew.h:223
iterator begin()
Definition corkscrew.h:182
void readFromMulti(const fl::Grid< CRGB > &target_grid) const
bool mCacheInitialized
Definition corkscrew.h:240
float mTotalTurns
Definition corkscrew.h:222
void fillInputSurface(const CRGB &color)
fl::u16 mHeight
Definition corkscrew.h:229
PixelStorage mPixelStorage
Definition corkscrew.h:232
vec2f at_exact(fl::u16 i) const
fl::shared_ptr< fl::Grid< CRGB > > mInputSurface
Definition corkscrew.h:236
fl::vector< Tile2x2_u8_wrap > mTileCache
Definition corkscrew.h:239
void initializeBuffer() const
void initializeCache() const
Tile2x2_u8_wrap at_wrap(float i) const
fl::size size() const
void draw(bool use_multi_sampling=true)
vec2f at_no_wrap(fl::u16 i) const
void readFrom(const fl::Grid< CRGB > &source_grid, bool use_multi_sampling=true)
fl::u16 cylinderHeight() const
Definition corkscrew.h:156
fl::size pixelCount() const
bool mCachingEnabled
Definition corkscrew.h:241
fl::Corkscrew corkscrew(CORKSCREW_TURNS, NUM_LEDS)
constexpr int ceil_constexpr(float value) FL_NOEXCEPT
Definition math.h:287
vec2< float > vec2f
Definition geometry.h:333
constexpr fl::u16 calculateCorkscrewHeight(float totalTurns, fl::u16 numLeds)
Definition corkscrew.h:55
constexpr fl::u16 calculateCorkscrewWidth(float totalTurns, fl::u16 numLeds)
Definition corkscrew.h:51
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NOEXCEPT
Representation of an 8-bit RGB pixel (Red, Green, Blue)
Definition crgb.h:38
Gap & operator=(const Gap &other)=default
Gap(const Gap &other) FL_NOEXCEPT=default
Gap() FL_NOEXCEPT=default
Gap & operator=(Gap &&other) FL_NOEXCEPT=default
Gap(Gap &&other) FL_NOEXCEPT=default
int num_leds
Definition corkscrew.h:65
Gap(int n, float g)
Definition corkscrew.h:70
float gap
Definition corkscrew.h:66
Struct representing gap parameters for corkscrew mapping.
Definition corkscrew.h:64