FastLED 3.10.8
Loading...
Searching...
No Matches
xypath.cpp.hpp
Go to the documentation of this file.
1
2#include "platforms/is_platform.h"
3
4#ifdef FL_IS_AVR
5
6// do nothing
7
8#else
9
10#include "fl/math/math.h"
11
12#include "fl/stl/assert.h"
13#include "fl/stl/function.h"
14#include "fl/gfx/gradient.h"
15#include "fl/math/lut.h"
16#include "fl/math/math.h"
17#include "fl/math/math.h"
18#include "fl/gfx/raster.h"
19#include "fl/gfx/xypath.h"
21
22#include "fl/stl/atomic.h"
23#include "fl/stl/singleton.h"
24#include "fl/stl/noexcept.h"
25
26namespace fl {
27
28namespace { // anonymous namespace
29
33
34} // namespace
35
36namespace xypath_detail {
38 static fl::atomic<u32> sUniqueName(0); // okay static in header
39 u32 id = ++sUniqueName;
40 string name = prefix;
41 name += id;
42 return name;
43}
44} // namespace xypath_detail
45
47 // return compute_float(alpha, tx);
48 return mPathRenderer->at(alpha, tx);
49}
50
52 mPathRenderer->setDrawBounds(width, height);
53}
54
56
57string XYPath::name() const FL_NO_EXCEPT { return mPath->name(); }
59 return mPathRenderer->at_subpixel(alpha);
60}
61
62void XYPath::rasterize(float from, float to, int steps,
64 XYPath::AlphaFunction *optional_alpha_gen) FL_NO_EXCEPT {
65 mPathRenderer->rasterize(from, to, steps, raster, optional_alpha_gen);
66}
67
68vec2f XYPath::at(float alpha) FL_NO_EXCEPT { return mPathRenderer->at(alpha); }
69
71
76
78
80 float from, float to, int steps, XYRaster &raster,
81 fl::function<u8(float)> *optional_alpha_gen) FL_NO_EXCEPT {
82 for (int i = 0; i < steps; ++i) {
83 float alpha = fl::map_range<int, float>(i, 0, steps - 1, from, to);
84 Tile2x2_u8 tile = at_subpixel(alpha);
85 if (optional_alpha_gen) {
86 // Scale the tile based on the alpha value.
87 u8 a8 = (*optional_alpha_gen)(alpha);
88 tile.scale(a8);
89 }
90 raster.rasterize(tile);
91 }
92}
93
95 // auto &tx = *(mGridTransform.mImpl);
96 auto &tx = mGridTransform;
97
98 // 1) map world‑X ∈ [–1..+1] → pixel‑X ∈ [0.5 .. width–0.5]
99 // scale_x = ( (width–0.5) – 0.5 ) / 2 = (width–1)/2
100 // offset_x = (width–0.5 + 0.5) / 2 = width/2
101 tx.set_scale_x((width - 1.0f) * 0.5f);
102 // tx.scale_x = (width - 1.0f) * 0.5f;
103 // tx.offset_x = width * 0.5f;
104 tx.set_offset_x(width * 0.5f);
105
106 // 2) map world‑Y ∈ [ -1 .. 1 ] → pixel‑Y ∈ [0.5 .. height–0.5]
107 // (your LinePath lives at Y=0, so it will sit at row‑0 center = 0.5)
108 // scale_y = (height–0.5) – 0.5 = height–1
109 // offset_y = 0.5
110 // tx.scale_y = (height - 1.0f) * 0.5f;
111 // tx.offset_y = height * 0.5f;
112
113 tx.set_scale_y((height - 1.0f) * 0.5f);
114 tx.set_offset_y(height * 0.5f);
115
117 mDrawBoundsSet = true;
118}
119
121 // Future use to allow recomputing the LUT.
122}
123
125
127 // mTransform.scale_x = scale;
128 // mTransform.scale_y = scale;
129 mTransform.set_scale(scale);
131}
132
134 return compute_float(alpha, mTransform);
135}
136
137vec2f XYPathRenderer::at(float alpha) FL_NO_EXCEPT { return at(alpha, mTransform); }
138
140 return compute_float(alpha, tx);
141}
142
143XYPathPtr XYPath::NewPointPath(float x, float y) FL_NO_EXCEPT {
144 auto path = fl::make_shared<PointPath>(x, y);
145 return fl::make_shared<XYPath>(path);
146}
147
148XYPathPtr XYPath::NewLinePath(float x0, float y0, float x1, float y1) FL_NO_EXCEPT {
149 LinePathParamsPtr p = fl::make_shared<LinePathParams>();
150 auto &params = *p;
151 params.x0 = x0;
152 params.y0 = y0;
153 params.x1 = x1;
154 params.y1 = y1;
155 auto path = fl::make_shared<LinePath>(p);
156 return fl::make_shared<XYPath>(path);
157}
158
160 auto path = fl::make_shared<LinePath>(params);
161 return fl::make_shared<XYPath>(path);
162}
163
165 auto path = fl::make_shared<CirclePath>();
166 return fl::make_shared<XYPath>(path);
167}
168
170 CirclePathPtr path = fl::make_shared<CirclePath>();
171 XYPathPtr out = fl::make_shared<XYPath>(path);
172 out->setDrawBounds(width, height);
173 return out;
174}
175
177 HeartPathPtr path = fl::make_shared<HeartPath>();
178 return fl::make_shared<XYPath>(path);
179}
180
182 HeartPathPtr path = fl::make_shared<HeartPath>();
183 XYPathPtr out = fl::make_shared<XYPath>(path);
184 out->setDrawBounds(width, height);
185 return out;
186}
187
189 ArchimedeanSpiralPathPtr path = fl::make_shared<ArchimedeanSpiralPath>();
190 XYPathPtr out = fl::make_shared<XYPath>(path);
191 out->setDrawBounds(width, height);
192 return out;
193}
194
196 ArchimedeanSpiralPathPtr path = fl::make_shared<ArchimedeanSpiralPath>();
197 XYPathPtr out = fl::make_shared<XYPath>(path);
198 return out;
199}
200
203 RosePathPtr path = fl::make_shared<RosePath>(params);
204 XYPathPtr out = fl::make_shared<XYPath>(path);
205 if (width > 0 && height > 0) {
206 out->setDrawBounds(width, height);
207 }
208 return out;
209}
210
213 PhyllotaxisPathPtr path = fl::make_shared<PhyllotaxisPath>(args);
214 XYPathPtr out = fl::make_shared<XYPath>(path);
215 if (width > 0 && height > 0) {
216 out->setDrawBounds(width, height);
217 }
218 return out;
219}
220
223 GielisCurvePathPtr path = fl::make_shared<GielisCurvePath>(params);
224 XYPathPtr out = fl::make_shared<XYPath>(path);
225 if (width > 0 && height > 0) {
226 out->setDrawBounds(width, height);
227 }
228 return out;
229}
230
233 CatmullRomPathPtr path = fl::make_shared<CatmullRomPath>(params);
234 XYPathPtr out = fl::make_shared<XYPath>(path);
235 if (width > 0 && height > 0) {
236 out->setDrawBounds(width, height);
237 }
238 return out;
239}
240
241XYPathPtr XYPath::NewCustomPath(const fl::function<vec2f(float)> &f,
242 const rect<i16> &drawbounds,
244 const char *name) FL_NO_EXCEPT {
245
246 XYPathFunctionPtr path = fl::make_shared<XYPathFunction>(f);
247 path->setName(name);
248 if (!drawbounds.empty()) {
249 path->setDrawBounds(drawbounds);
250 }
251 XYPathPtr out = fl::make_shared<XYPath>(path);
252 if (!transform.is_identity()) {
253 out->setTransform(transform);
254 }
255 rect<i16> bounds;
256 if (path->hasDrawBounds(&bounds)) {
257 if (!bounds.mMin.is_zero()) {
258 // Set the bounds to the path's bounds
259 FL_WARN("Bounds with an origin other than 0,0 is not supported yet");
260 }
261 auto w = bounds.width();
262 auto h = bounds.height();
263 out->setDrawBounds(w, h);
264 }
265 return out;
266}
267
271
272void XYPath::drawColor(const CRGB &color, float from, float to, Leds *leds,
273 int steps) FL_NO_EXCEPT {
274 XYRasterU8Sparse &raster = get_tls_raster();
275 raster.clear();
276 steps = steps > 0 ? steps : calculateSteps(from, to);
277 rasterize(from, to, steps, raster);
278 raster.draw(color, leds);
279}
280
281void XYPath::drawGradient(const Gradient &gradient, float from, float to,
282 Leds *leds, int steps) FL_NO_EXCEPT {
283 XYRasterU8Sparse &raster = get_tls_raster();
284 raster.clear();
285 steps = steps > 0 ? steps : calculateSteps(from, to);
286 rasterize(from, to, steps, raster);
287 raster.drawGradient(gradient, leds);
288}
289
290int XYPath::calculateSteps(float from, float to) FL_NO_EXCEPT {
291 float diff = fl::clamp(fl::abs(to - from), 0.0f, 1.0f);
292 return fl::max(1, 200 * diff);
293}
294
295bool XYPath::hasDrawBounds() const FL_NO_EXCEPT { return mPathRenderer->hasDrawBounds(); }
296
297} // namespace fl
298
299#endif // FL_IS_AVR
CRGB leds[1]
fl::UISlider scale("Scale", 4,.1, 4,.1)
static T & instance() FL_NO_EXCEPT
Definition singleton.h:133
void scale(u8 scale) FL_NO_EXCEPT
vec2f at(float alpha) FL_NO_EXCEPT
static XYPathPtr NewGielisCurvePath(u16 width=0, u16 height=0, const fl::shared_ptr< GielisCurveParams > &params=fl::make_shared< GielisCurveParams >()) FL_NO_EXCEPT
XYPathGeneratorPtr mPath
Definition xypath.h:132
bool hasDrawBounds() const FL_NO_EXCEPT
string name() const FL_NO_EXCEPT
int calculateSteps(float from, float to) FL_NO_EXCEPT
static XYPathPtr NewCustomPath(const fl::function< vec2f(float)> &path, const rect< i16 > &drawbounds=rect< i16 >(), const TransformFloat &transform=TransformFloat(), const char *name=nullptr) FL_NO_EXCEPT
Tile2x2_u8 at_subpixel(float alpha) FL_NO_EXCEPT
void setTransform(const TransformFloat &transform) FL_NO_EXCEPT
void drawGradient(const Gradient &gradient, float from, float to, Leds *leds, int steps=-1) FL_NO_EXCEPT
static XYPathPtr NewRosePath(u16 width=0, u16 height=0, const fl::shared_ptr< RosePathParams > &params=fl::make_shared< RosePathParams >()) FL_NO_EXCEPT
static XYPathPtr NewCatmullRomPath(u16 width=0, u16 height=0, const fl::shared_ptr< CatmullRomParams > &params=fl::make_shared< CatmullRomParams >()) FL_NO_EXCEPT
TransformFloat & transform() FL_NO_EXCEPT
static XYPathPtr NewPhyllotaxisPath(u16 width=0, u16 height=0, const fl::shared_ptr< PhyllotaxisParams > &args=fl::make_shared< PhyllotaxisParams >()) FL_NO_EXCEPT
void rasterize(float from, float to, int steps, XYRasterU8Sparse &raster, AlphaFunction *optional_alpha_gen=nullptr) FL_NO_EXCEPT
XYPath(XYPathGeneratorPtr path, TransformFloat transform=TransformFloat()) FL_NO_EXCEPT
static XYPathPtr NewArchimedeanSpiralPath() FL_NO_EXCEPT
static XYPathPtr NewHeartPath() FL_NO_EXCEPT
static XYPathPtr NewPointPath(float x, float y) FL_NO_EXCEPT
virtual ~XYPath() FL_NO_EXCEPT
void setScale(float scale) FL_NO_EXCEPT
XYPathRendererPtr mPathRenderer
Definition xypath.h:133
fl::function< u8(float)> AlphaFunction
Definition xypath.h:84
static XYPathPtr NewCirclePath() FL_NO_EXCEPT
void drawColor(const CRGB &color, float from, float to, Leds *leds, int steps=-1) FL_NO_EXCEPT
void setDrawBounds(u16 width, u16 height) FL_NO_EXCEPT
static XYPathPtr NewLinePath(float x0, float y0, float x1, float y1) FL_NO_EXCEPT
void setScale(float scale) FL_NO_EXCEPT
TransformFloat & transform() FL_NO_EXCEPT
TransformFloat mTransform
TransformFloat mGridTransform
void rasterize(float from, float to, int steps, XYRasterU8Sparse &raster, fl::function< u8(float)> *optional_alpha_gen=nullptr) FL_NO_EXCEPT
vec2f compute_float(float alpha, const TransformFloat &tx) FL_NO_EXCEPT
Tile2x2_u8 at_subpixel(float alpha) FL_NO_EXCEPT
void onTransformFloatChanged() FL_NO_EXCEPT
vec2f at(float alpha) FL_NO_EXCEPT
void setDrawBounds(u16 width, u16 height) FL_NO_EXCEPT
vec2f compute(float alpha) FL_NO_EXCEPT
fl::UISlider steps("Steps", 100.0f, 1.0f, 200.0f, 1.0f)
fl::XYRaster raster(WIDTH, HEIGHT)
#define FL_WARN(...)
Definition log.h:437
shared_ptr< T > make_shared(Args &&... args) FL_NO_EXCEPT
Definition shared_ptr.h:423
XYRasterU8Sparse & get_tls_raster() FL_NO_EXCEPT
fl::string unique_missing_name(const char *prefix) FL_NO_EXCEPT
unsigned char u8
Definition stdint.h:131
constexpr common_type_t< T, U > max(T a, U b) FL_NO_EXCEPT
Definition math.h:75
u8 u8 fract8 blur_amount FL_NO_EXCEPT
Definition blur.h:186
XYRasterU8Sparse XYRaster
Definition raster.h:8
AtomicFake< T > atomic
Definition atomic.h:26
u8 u8 height
Definition blur.h:186
constexpr enable_if< is_fixed_point< T >::value, T >::type clamp(T x, T lo, T hi) FL_NO_EXCEPT
vec2< float > vec2f
Definition geometry.h:333
FASTLED_FORCE_INLINE U map_range(T value, T in_min, T in_max, U out_min, U out_max) FL_NO_EXCEPT
Definition math.h:182
u8 width
Definition blur.h:186
constexpr enable_if< is_fixed_point< T >::value, T >::type abs(T x) FL_NO_EXCEPT
Base definition for an LED controller.
Definition crgb.hpp:179
corkscrew_args args
Definition old.h:149
Representation of an 8-bit RGB pixel (Red, Green, Blue)
Definition crgb.h:38
u16 width() const FL_NO_EXCEPT
Definition geometry.h:451
u16 height() const FL_NO_EXCEPT
Definition geometry.h:453
vec2< T > mMin
Definition geometry.h:437