FastLED 3.9.15
Loading...
Searching...
No Matches
raster_sparse.h
Go to the documentation of this file.
1
2#pragma once
3
4/*
5A sparse path through an xy grid. When a value is set != 0, it will get stored
6in the sparse grid. The raster will only store the values that are set, and will
7not allocate memory for the entire grid. This is useful for large grids where
8only a small number of pixels are set.
9*/
10
11#include <stdint.h>
12
13#include "fl/geometry.h"
14#include "fl/grid.h"
15#include "fl/hash_map.h"
16#include "fl/map.h"
17#include "fl/namespace.h"
18#include "fl/slice.h"
19#include "fl/tile2x2.h"
20#include "fl/xymap.h"
21
23struct CRGB;
25
26#ifndef FASTLED_RASTER_SPARSE_INLINED_COUNT
27#define FASTLED_RASTER_SPARSE_INLINED_COUNT 128
28#endif
29
30namespace fl {
31
32class XYMap;
33class Gradient;
34class Tile2x2_u8;
35
36// A raster of uint8_t values. This is a sparse raster, meaning that it will
37// only store the values that are set.
39 public:
40 XYRasterU8Sparse() = default;
45
47 mSparseGrid.clear();
48 mCache.clear();
49 return *this;
50 }
51
52 XYRasterU8Sparse &clear() { return reset(); }
53
54 void rasterize(const vec2<int> &pt, uint8_t value) {
55 // Turn it into a Tile2x2_u8 tile and see if we can cache it.
56 write(pt, value);
57 }
58
59 void setSize(uint16_t width, uint16_t height) {
61 }
62
63 void setBounds(const rect<int> &bounds) {
65 mAbsoluteBoundsSet = true;
66 }
67
70
71 iterator begin() { return mSparseGrid.begin(); }
72 const_iterator begin() const { return mSparseGrid.begin(); }
73 iterator end() { return mSparseGrid.end(); }
74 const_iterator end() const { return mSparseGrid.end(); }
75 size_t size() const { return mSparseGrid.size(); }
76 bool empty() const { return mSparseGrid.empty(); }
77
78 void rasterize(const Slice<const Tile2x2_u8> &tiles);
79 void rasterize(const Tile2x2_u8 &tile) { rasterize_internal(tile); }
80
81 void rasterize_internal(const Tile2x2_u8 &tile,
82 const rect<int> *optional_bounds = nullptr);
83
84 // Renders the subpixel tiles to the raster. Any previous data is
85 // cleared. Memory will only be allocated if the size of the raster
86 // increased. void rasterize(const Slice<const Tile2x2_u8> &tiles);
87 // uint8_t &at(uint16_t x, uint16_t y) { return mGrid.at(x, y); }
88 // const uint8_t &at(uint16_t x, uint16_t y) const { return mGrid.at(x,
89 // y); }
90
91 Pair<bool, uint8_t> at(uint16_t x, uint16_t y) const {
92 const uint8_t *val = mSparseGrid.find_value(vec2<int>(x, y));
93 if (val != nullptr) {
94 return {true, *val};
95 }
96 return {false, 0};
97 }
98
99 rect<int> bounds() const {
100 if (mAbsoluteBoundsSet) {
101 return mAbsoluteBounds;
102 }
103 return bounds_pixels();
104 }
105
107 int min_x = 0;
108 bool min_x_set = false;
109 int min_y = 0;
110 bool min_y_set = false;
111 int max_x = 0;
112 bool max_x_set = false;
113 int max_y = 0;
114 bool max_y_set = false;
115 for (const auto &it : mSparseGrid) {
116 const vec2<int> &pt = it.first;
117 if (!min_x_set || pt.x < min_x) {
118 min_x = pt.x;
119 min_x_set = true;
120 }
121 if (!min_y_set || pt.y < min_y) {
122 min_y = pt.y;
123 min_y_set = true;
124 }
125 if (!max_x_set || pt.x > max_x) {
126 max_x = pt.x;
127 max_x_set = true;
128 }
129 if (!max_y_set || pt.y > max_y) {
130 max_y = pt.y;
131 max_y_set = true;
132 }
133 }
134 return rect<int>(min_x, min_y, max_x + 1, max_y + 1);
135 }
136
137 // Warning! - SLOW.
138 uint16_t width() const { return bounds().width(); }
139 uint16_t height() const { return bounds().height(); }
140
141 void draw(const CRGB &color, const XYMap &xymap, CRGB *out);
142
143 void drawGradient(const Gradient &gradient, const XYMap &xymap, CRGB *out);
144
145 // Inlined, yet customizable drawing access. This will only send you
146 // pixels that are within the bounds of the XYMap.
147 template <typename XYVisitor>
148 void draw(const XYMap &xymap, XYVisitor &visitor) {
149 for (const auto &it : mSparseGrid) {
150 auto pt = it.first;
151 if (!xymap.has(pt.x, pt.y)) {
152 continue;
153 }
154 uint32_t index = xymap(pt.x, pt.y);
155 uint8_t value = it.second;
156 if (value > 0) { // Something wrote here.
157 visitor.draw(pt, index, value);
158 }
159 }
160 }
161
162 static const int kMaxCacheSize = 8; // Max size for tiny cache.
163
164 void write(const vec2<int> &pt, uint8_t value) {
165 // FASTLED_WARN("write: " << pt.x << "," << pt.y << " value: " <<
166 // value); mSparseGrid.insert(pt, value);
167
168 uint8_t **cached = mCache.find_value(pt);
169 if (cached) {
170 uint8_t *val = *cached;
171 if (*val < value) {
172 *val = value;
173 }
174 return;
175 }
176 if (mCache.size() <= kMaxCacheSize) {
177 // cache it.
178 uint8_t *v = mSparseGrid.find_value(pt);
179 if (v == nullptr) {
180 // FASTLED_WARN("write: " << pt.x << "," << pt.y << " value: "
181 // << value);
182 if (mSparseGrid.needs_rehash()) {
183 // mSparseGrid is about to rehash, so we need to clear the
184 // small cache because it shares pointers.
185 mCache.clear();
186 }
187
188 mSparseGrid.insert(pt, value);
189 return;
190 }
191 mCache.insert(pt, v);
192 if (*v < value) {
193 *v = value;
194 }
195 return;
196 } else {
197 // overflow, clear cache and write directly.
198 mCache.clear();
199 mSparseGrid.insert(pt, value);
200 return;
201 }
202 }
203
204 private:
205 using Key = vec2<int>;
206 using Value = uint8_t;
213 // Small cache for the last N writes to help performance.
217 bool mAbsoluteBoundsSet = false;
218};
219
220} // namespace fl
XYMap xymap(WIDTH, HEIGHT, SERPENTINE)
uint32_t x[NUM_LAYERS]
Definition Fire2023.ino:82
uint32_t y[NUM_LAYERS]
Definition Fire2023.ino:83
Definition xymap.h:43
void write(const vec2< int > &pt, uint8_t value)
fl::HashMap< Key, Value, HashKey, EqualToKey, FASTLED_HASHMAP_INLINED_COUNT > HashMapLarge
void setBounds(const rect< int > &bounds)
uint16_t height() const
void draw(const XYMap &xymap, XYVisitor &visitor)
void setSize(uint16_t width, uint16_t height)
XYRasterU8Sparse & clear()
XYRasterU8Sparse(int width, int height)
XYRasterU8Sparse()=default
fl::HashMap< vec2< int >, uint8_t >::const_iterator const_iterator
void rasterize(const Tile2x2_u8 &tile)
const_iterator begin() const
static const int kMaxCacheSize
fl::rect< int > mAbsoluteBounds
Pair< bool, uint8_t > at(uint16_t x, uint16_t y) const
EqualTo< Key > EqualToKey
HashMap< vec2< int >, uint8_t *, FastHashKey, EqualToKey, kMaxCacheSize > mCache
void rasterize_internal(const Tile2x2_u8 &tile, const rect< int > *optional_bounds=nullptr)
XYRasterU8Sparse(const XYRasterU8Sparse &)=delete
fl::HashMap< vec2< int >, uint8_t >::iterator iterator
const_iterator end() const
FastHash< Key > FastHashKey
size_t size() const
XYRasterU8Sparse & reset()
void draw(const CRGB &color, const XYMap &xymap, CRGB *out)
HashMapLarge mSparseGrid
void drawGradient(const Gradient &gradient, const XYMap &xymap, CRGB *out)
uint16_t width() const
rect< int > bounds_pixels() const
rect< int > bounds() const
void rasterize(const vec2< int > &pt, uint8_t value)
#define FASTLED_HASHMAP_INLINED_COUNT
Definition hash_map.h:43
#define FASTLED_NAMESPACE_END
Definition namespace.h:23
Implements the FastLED namespace macros.
Implements a simple red square effect for 2D LED grids.
Definition crgb.h:16
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:55
Definition pair.h:5
uint16_t width() const
Definition geometry.h:236
uint16_t height() const
Definition geometry.h:238