FastLED 3.9.15
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 {
37fl::string unique_missing_name(const char *prefix) {
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
46vec2f XYPath::at(float alpha, const TransformFloat &tx) {
47 // return compute_float(alpha, tx);
48 return mPathRenderer->at(alpha, tx);
49}
50
52 mPathRenderer->setDrawBounds(width, height);
53}
54
55void XYPath::setScale(float scale) { mPathRenderer->setScale(scale); }
56
57string XYPath::name() const { 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) {
65 mPathRenderer->rasterize(from, to, steps, raster, optional_alpha_gen);
66}
67
68vec2f XYPath::at(float alpha) { 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) {
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) { return at(alpha, mTransform); }
138
139vec2f XYPathRenderer::at(float alpha, const TransformFloat &tx) {
140 return compute_float(alpha, tx);
141}
142
143XYPathPtr XYPath::NewPointPath(float x, float y) {
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) {
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
169XYPathPtr XYPath::NewCirclePath(u16 width, u16 height) {
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
181XYPathPtr XYPath::NewHeartPath(u16 width, u16 height) {
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
202 const fl::shared_ptr<RosePathParams> &params) {
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
222 const fl::shared_ptr<GielisCurveParams> &params) {
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
232 const fl::shared_ptr<CatmullRomParams> &params) {
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) {
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(
260 "Bounds with an origin other than 0,0 is not supported yet");
261 }
262 auto w = bounds.width();
263 auto h = bounds.height();
264 out->setDrawBounds(w, h);
265 }
266 return out;
267}
268
272
273void XYPath::drawColor(const CRGB &color, float from, float to, Leds *leds,
274 int steps) {
275 XYRasterU8Sparse &raster = get_tls_raster();
276 raster.clear();
277 steps = steps > 0 ? steps : calculateSteps(from, to);
278 rasterize(from, to, steps, raster);
279 raster.draw(color, leds);
280}
281
282void XYPath::drawGradient(const Gradient &gradient, float from, float to,
283 Leds *leds, int steps) {
284 XYRasterU8Sparse &raster = get_tls_raster();
285 raster.clear();
286 steps = steps > 0 ? steps : calculateSteps(from, to);
287 rasterize(from, to, steps, raster);
288 raster.drawGradient(gradient, leds);
289}
290
291int XYPath::calculateSteps(float from, float to) {
292 float diff = fl::clamp(fl::abs(to - from), 0.0f, 1.0f);
293 return fl::max(1, 200 * diff);
294}
295
296bool XYPath::hasDrawBounds() const { return mPathRenderer->hasDrawBounds(); }
297
298} // namespace fl
299
300#endif // FL_IS_AVR
fl::CRGB leds[NUM_LEDS]
fl::UISlider scale("Scale", 4,.1, 4,.1)
static T & instance() FL_NOEXCEPT
Definition singleton.h:133
void scale(u8 scale)
XYPathGeneratorPtr mPath
Definition xypath.h:132
static XYPathPtr NewCustomPath(const fl::function< vec2f(float)> &path, const rect< i16 > &drawbounds=rect< i16 >(), const TransformFloat &transform=TransformFloat(), const char *name=nullptr)
int calculateSteps(float from, float to)
static XYPathPtr NewPhyllotaxisPath(u16 width=0, u16 height=0, const fl::shared_ptr< PhyllotaxisParams > &args=fl::make_shared< PhyllotaxisParams >())
void drawColor(const CRGB &color, float from, float to, Leds *leds, int steps=-1)
static XYPathPtr NewHeartPath()
static XYPathPtr NewArchimedeanSpiralPath()
Tile2x2_u8 at_subpixel(float alpha)
void setScale(float scale)
vec2f at(float alpha)
static XYPathPtr NewPointPath(float x, float y)
bool hasDrawBounds() const
static XYPathPtr NewGielisCurvePath(u16 width=0, u16 height=0, const fl::shared_ptr< GielisCurveParams > &params=fl::make_shared< GielisCurveParams >())
void drawGradient(const Gradient &gradient, float from, float to, Leds *leds, int steps=-1)
void setTransform(const TransformFloat &transform)
string name() const
static XYPathPtr NewCatmullRomPath(u16 width=0, u16 height=0, const fl::shared_ptr< CatmullRomParams > &params=fl::make_shared< CatmullRomParams >())
virtual ~XYPath() FL_NOEXCEPT
static XYPathPtr NewLinePath(float x0, float y0, float x1, float y1)
XYPathRendererPtr mPathRenderer
Definition xypath.h:133
fl::function< u8(float)> AlphaFunction
Definition xypath.h:84
static XYPathPtr NewRosePath(u16 width=0, u16 height=0, const fl::shared_ptr< RosePathParams > &params=fl::make_shared< RosePathParams >())
XYPath(XYPathGeneratorPtr path, TransformFloat transform=TransformFloat())
void setDrawBounds(u16 width, u16 height)
void rasterize(float from, float to, int steps, XYRasterU8Sparse &raster, AlphaFunction *optional_alpha_gen=nullptr)
static XYPathPtr NewCirclePath()
TransformFloat & transform()
TransformFloat & transform()
vec2f compute(float alpha)
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)
void onTransformFloatChanged()
void setScale(float scale)
vec2f at(float alpha)
void setDrawBounds(u16 width, u16 height)
fl::UISlider steps("Steps", 100.0f, 1.0f, 200.0f, 1.0f)
fl::XYRaster raster(WIDTH, HEIGHT)
#define FL_WARN(X)
Definition log.h:276
fl::string unique_missing_name(const char *prefix)
unsigned char u8
Definition stdint.h:131
constexpr common_type_t< T, U > max(T a, U b) FL_NOEXCEPT
Definition math.h:75
XYRasterU8Sparse XYRaster
Definition raster.h:8
AtomicFake< T > atomic
Definition atomic.h:26
u8 u8 height
Definition blur.h:186
FASTLED_FORCE_INLINE U map_range(T value, T in_min, T in_max, U out_min, U out_max) FL_NOEXCEPT
Definition math.h:174
vec2< float > vec2f
Definition geometry.h:333
u8 width
Definition blur.h:186
shared_ptr< T > make_shared(Args &&... args) FL_NOEXCEPT
Definition shared_ptr.h:414
constexpr enable_if< is_fixed_point< T >::value, T >::type abs(T x) FL_NOEXCEPT
constexpr enable_if< is_fixed_point< T >::value, T >::type clamp(T x, T lo, T hi) FL_NOEXCEPT
Base definition for an LED controller.
Definition crgb.hpp:179
corkscrew_args args
Definition old.h:149
#define FL_NOEXCEPT
Representation of an 8-bit RGB pixel (Red, Green, Blue)
Definition crgb.h:38
bool empty() const FL_NOEXCEPT
Definition geometry.h:455
u16 width() const FL_NOEXCEPT
Definition geometry.h:451
u16 height() const FL_NOEXCEPT
Definition geometry.h:453
vec2< T > mMin
Definition geometry.h:437