FastLED 3.9.15
Loading...
Searching...
No Matches
xypath.cpp
Go to the documentation of this file.
1
2
3#ifdef __AVR__
4
5// do nothing
6
7#else
8
9#include <math.h>
10
11#include "fl/assert.h"
12#include "fl/function.h"
13#include "fl/gradient.h"
14#include "fl/lut.h"
15#include "fl/map_range.h"
16#include "fl/math_macros.h"
17#include "fl/raster.h"
18#include "fl/xypath.h"
19#include "fl/xypath_renderer.h"
20
21#include "fl/atomic.h"
22#include "fl/thread_local.h"
23
24namespace fl {
25
26namespace { // anonymous namespace
27
29 static ThreadLocal<XYRasterU8Sparse> tls_raster;
30 return tls_raster.access();
31}
32
33} // namespace
34
35namespace xypath_detail {
36fl::string unique_missing_name(const char *prefix) {
37 static fl::atomic<u32> sUniqueName(0);
38 u32 id = ++sUniqueName;
39 string name = prefix;
40 name += id;
41 return name;
42}
43} // namespace xypath_detail
44
45vec2f XYPath::at(float alpha, const TransformFloat &tx) {
46 // return compute_float(alpha, tx);
47 return mPathRenderer->at(alpha, tx);
48}
49
50void XYPath::setDrawBounds(u16 width, u16 height) {
51 mPathRenderer->setDrawBounds(width, height);
52}
53
54void XYPath::setScale(float scale) { mPathRenderer->setScale(scale); }
55
56string XYPath::name() const { return mPath->name(); }
58 return mPathRenderer->at_subpixel(alpha);
59}
60
61void XYPath::rasterize(float from, float to, int steps,
63 XYPath::AlphaFunction *optional_alpha_gen) {
64 mPathRenderer->rasterize(from, to, steps, raster, optional_alpha_gen);
65}
66
67vec2f XYPath::at(float alpha) { return mPathRenderer->at(alpha); }
68
70
75
77
79 float from, float to, int steps, XYRaster &raster,
80 fl::function<u8(float)> *optional_alpha_gen) {
81 for (int i = 0; i < steps; ++i) {
82 float alpha = fl::map_range<int, float>(i, 0, steps - 1, from, to);
83 Tile2x2_u8 tile = at_subpixel(alpha);
84 if (optional_alpha_gen) {
85 // Scale the tile based on the alpha value.
86 u8 a8 = (*optional_alpha_gen)(alpha);
87 tile.scale(a8);
88 }
89 raster.rasterize(tile);
90 }
91}
92
93void XYPathRenderer::setDrawBounds(u16 width, u16 height) {
94 // auto &tx = *(mGridTransform.mImpl);
95 auto &tx = mGridTransform;
96
97 // 1) map world‑X ∈ [–1..+1] → pixel‑X ∈ [0.5 .. width–0.5]
98 // scale_x = ( (width–0.5) – 0.5 ) / 2 = (width–1)/2
99 // offset_x = (width–0.5 + 0.5) / 2 = width/2
100 tx.set_scale_x((width - 1.0f) * 0.5f);
101 // tx.scale_x = (width - 1.0f) * 0.5f;
102 // tx.offset_x = width * 0.5f;
103 tx.set_offset_x(width * 0.5f);
104
105 // 2) map world‑Y ∈ [ -1 .. 1 ] → pixel‑Y ∈ [0.5 .. height–0.5]
106 // (your LinePath lives at Y=0, so it will sit at row‑0 center = 0.5)
107 // scale_y = (height–0.5) – 0.5 = height–1
108 // offset_y = 0.5
109 // tx.scale_y = (height - 1.0f) * 0.5f;
110 // tx.offset_y = height * 0.5f;
111
112 tx.set_scale_y((height - 1.0f) * 0.5f);
113 tx.set_offset_y(height * 0.5f);
114
116 mDrawBoundsSet = true;
117}
118
120 // Future use to allow recomputing the LUT.
121}
122
124
126 // mTransform.scale_x = scale;
127 // mTransform.scale_y = scale;
128 mTransform.set_scale(scale);
130}
131
133 return compute_float(alpha, mTransform);
134}
135
136vec2f XYPathRenderer::at(float alpha) { return at(alpha, mTransform); }
137
138vec2f XYPathRenderer::at(float alpha, const TransformFloat &tx) {
139 return compute_float(alpha, tx);
140}
141
142XYPathPtr XYPath::NewPointPath(float x, float y) {
143 auto path = fl::make_shared<PointPath>(x, y);
144 return fl::make_shared<XYPath>(path);
145}
146
147XYPathPtr XYPath::NewLinePath(float x0, float y0, float x1, float y1) {
148 LinePathParamsPtr p = fl::make_shared<LinePathParams>();
149 auto &params = *p;
150 params.x0 = x0;
151 params.y0 = y0;
152 params.x1 = x1;
153 params.y1 = y1;
154 auto path = fl::make_shared<LinePath>(p);
155 return fl::make_shared<XYPath>(path);
156}
157
159 auto path = fl::make_shared<LinePath>(params);
160 return fl::make_shared<XYPath>(path);
161}
162
164 auto path = fl::make_shared<CirclePath>();
165 return fl::make_shared<XYPath>(path);
166}
167
168XYPathPtr XYPath::NewCirclePath(u16 width, u16 height) {
169 CirclePathPtr path = fl::make_shared<CirclePath>();
170 XYPathPtr out = fl::make_shared<XYPath>(path);
171 out->setDrawBounds(width, height);
172 return out;
173}
174
176 HeartPathPtr path = fl::make_shared<HeartPath>();
177 return fl::make_shared<XYPath>(path);
178}
179
180XYPathPtr XYPath::NewHeartPath(u16 width, u16 height) {
181 HeartPathPtr path = fl::make_shared<HeartPath>();
182 XYPathPtr out = fl::make_shared<XYPath>(path);
183 out->setDrawBounds(width, height);
184 return out;
185}
186
187XYPathPtr XYPath::NewArchimedeanSpiralPath(u16 width, u16 height) {
188 ArchimedeanSpiralPathPtr path = fl::make_shared<ArchimedeanSpiralPath>();
189 XYPathPtr out = fl::make_shared<XYPath>(path);
190 out->setDrawBounds(width, height);
191 return out;
192}
193
195 ArchimedeanSpiralPathPtr path = fl::make_shared<ArchimedeanSpiralPath>();
196 XYPathPtr out = fl::make_shared<XYPath>(path);
197 return out;
198}
199
200XYPathPtr XYPath::NewRosePath(u16 width, u16 height,
201 const fl::shared_ptr<RosePathParams> &params) {
202 RosePathPtr path = fl::make_shared<RosePath>(params);
203 XYPathPtr out = fl::make_shared<XYPath>(path);
204 if (width > 0 && height > 0) {
205 out->setDrawBounds(width, height);
206 }
207 return out;
208}
209
210XYPathPtr XYPath::NewPhyllotaxisPath(u16 width, u16 height,
212 PhyllotaxisPathPtr path = fl::make_shared<PhyllotaxisPath>(args);
213 XYPathPtr out = fl::make_shared<XYPath>(path);
214 if (width > 0 && height > 0) {
215 out->setDrawBounds(width, height);
216 }
217 return out;
218}
219
220XYPathPtr XYPath::NewGielisCurvePath(u16 width, u16 height,
221 const fl::shared_ptr<GielisCurveParams> &params) {
222 GielisCurvePathPtr path = fl::make_shared<GielisCurvePath>(params);
223 XYPathPtr out = fl::make_shared<XYPath>(path);
224 if (width > 0 && height > 0) {
225 out->setDrawBounds(width, height);
226 }
227 return out;
228}
229
230XYPathPtr XYPath::NewCatmullRomPath(u16 width, u16 height,
231 const fl::shared_ptr<CatmullRomParams> &params) {
232 CatmullRomPathPtr path = fl::make_shared<CatmullRomPath>(params);
233 XYPathPtr out = fl::make_shared<XYPath>(path);
234 if (width > 0 && height > 0) {
235 out->setDrawBounds(width, height);
236 }
237 return out;
238}
239
240XYPathPtr XYPath::NewCustomPath(const fl::function<vec2f(float)> &f,
241 const rect<i16> &drawbounds,
243 const char *name) {
244
245 XYPathFunctionPtr path = fl::make_shared<XYPathFunction>(f);
246 path->setName(name);
247 if (!drawbounds.empty()) {
248 path->setDrawBounds(drawbounds);
249 }
250 XYPathPtr out = fl::make_shared<XYPath>(path);
251 if (!transform.is_identity()) {
252 out->setTransform(transform);
253 }
254 rect<i16> bounds;
255 if (path->hasDrawBounds(&bounds)) {
256 if (!bounds.mMin.is_zero()) {
257 // Set the bounds to the path's bounds
259 "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) {
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) {
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) {
291 float diff = fl::clamp(ABS(to - from), 0.0f, 1.0f);
292 return MAX(1, 200 * diff);
293}
294
295bool XYPath::hasDrawBounds() const { return mPathRenderer->hasDrawBounds(); }
296
297} // namespace fl
298
299#endif // __AVR__
CRGB leds[NUM_LEDS]
int y
Definition simple.h:93
int x
Definition simple.h:92
uint16_t scale
Definition Noise.ino:74
void scale(u8 scale)
Definition tile2x2.cpp:43
XYPathGeneratorPtr mPath
Definition xypath.h:131
static XYPathPtr NewCustomPath(const fl::function< vec2f(float)> &path, const rect< i16 > &drawbounds=rect< i16 >(), const TransformFloat &transform=TransformFloat(), const char *name=nullptr)
Definition xypath.cpp:240
int calculateSteps(float from, float to)
Definition xypath.cpp:290
static XYPathPtr NewPhyllotaxisPath(u16 width=0, u16 height=0, const fl::shared_ptr< PhyllotaxisParams > &args=fl::make_shared< PhyllotaxisParams >())
Definition xypath.cpp:210
void drawColor(const CRGB &color, float from, float to, Leds *leds, int steps=-1)
Definition xypath.cpp:272
static XYPathPtr NewHeartPath()
Definition xypath.cpp:175
static XYPathPtr NewArchimedeanSpiralPath()
Definition xypath.cpp:194
Tile2x2_u8 at_subpixel(float alpha)
Definition xypath.cpp:57
virtual ~XYPath()
Definition xypath.cpp:76
void setScale(float scale)
Definition xypath.cpp:54
vec2f at(float alpha)
Definition xypath.cpp:67
static XYPathPtr NewPointPath(float x, float y)
Definition xypath.cpp:142
bool hasDrawBounds() const
Definition xypath.cpp:295
static XYPathPtr NewGielisCurvePath(u16 width=0, u16 height=0, const fl::shared_ptr< GielisCurveParams > &params=fl::make_shared< GielisCurveParams >())
Definition xypath.cpp:220
void drawGradient(const Gradient &gradient, float from, float to, Leds *leds, int steps=-1)
Definition xypath.cpp:281
void setTransform(const TransformFloat &transform)
Definition xypath.cpp:268
string name() const
Definition xypath.cpp:56
static XYPathPtr NewCatmullRomPath(u16 width=0, u16 height=0, const fl::shared_ptr< CatmullRomParams > &params=fl::make_shared< CatmullRomParams >())
Definition xypath.cpp:230
static XYPathPtr NewLinePath(float x0, float y0, float x1, float y1)
Definition xypath.cpp:147
XYPathRendererPtr mPathRenderer
Definition xypath.h:132
fl::function< u8(float)> AlphaFunction
Definition xypath.h:83
static XYPathPtr NewRosePath(u16 width=0, u16 height=0, const fl::shared_ptr< RosePathParams > &params=fl::make_shared< RosePathParams >())
Definition xypath.cpp:200
XYPath(XYPathGeneratorPtr path, TransformFloat transform=TransformFloat())
Definition xypath.cpp:71
void setDrawBounds(u16 width, u16 height)
Definition xypath.cpp:50
void rasterize(float from, float to, int steps, XYRasterU8Sparse &raster, AlphaFunction *optional_alpha_gen=nullptr)
Definition xypath.cpp:61
static XYPathPtr NewCirclePath()
Definition xypath.cpp:163
TransformFloat & transform()
Definition xypath.cpp:69
TransformFloat & transform()
Definition xypath.cpp:123
vec2f compute(float alpha)
Definition xypath.cpp:132
Tile2x2_u8 at_subpixel(float alpha)
TransformFloat mTransform
TransformFloat mGridTransform
vec2f compute_float(float alpha, const TransformFloat &tx)
void rasterize(float from, float to, int steps, XYRasterU8Sparse &raster, fl::function< u8(float)> *optional_alpha_gen=nullptr)
Definition xypath.cpp:78
void onTransformFloatChanged()
Definition xypath.cpp:119
void setScale(float scale)
Definition xypath.cpp:125
vec2f at(float alpha)
Definition xypath.cpp:136
void setDrawBounds(u16 width, u16 height)
Definition xypath.cpp:93
UISlider steps("Steps", 100.0f, 1.0f, 200.0f, 1.0f)
XYRaster raster(WIDTH, HEIGHT)
#define ABS(x)
Definition math_macros.h:45
#define MAX(a, b)
Definition math_macros.h:37
XYRasterU8Sparse & get_tls_raster()
Definition xypath.cpp:28
fl::string unique_missing_name(const char *prefix)
Definition xypath.cpp:36
unsigned char u8
Definition int.h:17
XYRasterU8Sparse XYRaster
Definition raster.h:8
AtomicFake< T > atomic
Definition atomic.h:21
FASTLED_FORCE_INLINE T clamp(T value, T min, T max)
Definition clamp.h:10
ThreadLocalFake< T > ThreadLocal
vec2< float > vec2f
Definition geometry.h:333
shared_ptr< T > make_shared(Args &&... args)
Definition shared_ptr.h:348
IMPORTANT!
Definition crgb.h:20
corkscrew_args args
Definition old.h:150
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:86
u16 height() const
Definition geometry.h:435
u16 width() const
Definition geometry.h:433
bool empty() const
Definition geometry.h:437
vec2< T > mMin
Definition geometry.h:419
#define FASTLED_WARN
Definition warn.h:7