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