30 auto end_float = jsonArray.
end_array<
float>();
32 using T =
decltype(*begin_float);
37 for (
auto it = begin_float; it != end_float; ++it) {
41 auto parseResult = *it;
42 if (!parseResult.has_error()) {
43 result.push_back(parseResult.get_value());
45 FL_WARN(
"jsonArrayToFloatVector: ParseResult<float> has error: " << parseResult.get_error().message);
53 float cm_led_diameter,
float completion) {
57 float circumference = numLeds * cm_between_leds;
58 float radius = circumference / (2 *
PI);
61 float totalAngle = completion * 2 *
PI;
62 float gapAngle = 2 *
PI - totalAngle;
65 float startAngle = -
PI / 2 + gapAngle / 2.0f;
69 (completion < 1.0f && numLeds > 1) ? (numLeds - 1) : numLeds;
71 for (
int i = 0; i < numLeds; ++i) {
72 float angle = startAngle + (i * totalAngle) / divisor;
73 float x = radius * cos(angle) * 2;
74 float y = radius * sin(angle) * 2;
89 FL_WARN(
"ScreenMap::ParseJson called with FASTLED_NO_JSON");
91 *err =
"JSON is not supported in this build";
103 if (!jsonDoc.has_value()) {
104 *err =
"Failed to parse JSON";
105 FL_WARN(
"Failed to parse JSON");
109 if (!jsonDoc.is_object()) {
110 *err =
"JSON root is not an object";
111 FL_WARN(
"JSON root is not an object");
116 if (!jsonDoc.contains(
"map")) {
117 *err =
"Missing 'map' key in JSON";
118 FL_WARN(
"Missing 'map' key in JSON");
123 auto mapObj = jsonDoc[
"map"];
124 if (!mapObj.has_value() || !mapObj.is_object()) {
125 *err =
"Invalid 'map' object in JSON";
126 FL_WARN(
"Invalid 'map' object in JSON");
130 auto jsonMapOpt = mapObj.as_object();
131 if (!jsonMapOpt || jsonMapOpt->empty()) {
132 *err =
"Failed to parse map from JSON or map is empty";
133 FL_WARN(
"Failed to parse map from JSON or map is empty");
137 auto& jsonMap = *jsonMapOpt;
140 for (
const auto& kv : jsonMap) {
141 auto name = kv.first;
146 *err =
"Null value for segment " + name;
153 *err =
"Invalid value for segment " + name;
158 *err =
"Segment value for " + name +
" is not an object";
164 *err =
"Missing x array for " + name;
168 if (!val[
"x"].has_value() || !val[
"x"].
is_array()) {
169 *err =
"Invalid x array for " + name;
178 *err =
"Missing y array for " + name;
182 if (!val[
"y"].has_value() || !val[
"y"].
is_array()) {
183 *err =
"Invalid y array for " + name;
191 float diameter = -1.0f;
193 auto diameterOpt = val[
"diameter"].
as_float();
195 diameter =
static_cast<float>(*diameterOpt);
200 if (n != x_array.
size() || n != y_array.
size()) {
201 if (n != x_array.
size()) {
203 if (n != y_array.
size()) {
208 for (
size_t i = 0; i < n; i++) {
209 segment_map.
set(i,
vec2f{x_array[i], y_array[i]});
211 (*segmentMaps)[name] =
fl::move(segment_map);
218 const char *screenMapName,
ScreenMap *screenmap,
222 bool ok =
ParseJson(jsonStrScreenMap, &segmentMaps, err);
226 if (segmentMaps.
size() == 0) {
229 if (segmentMaps.
contains(screenMapName)) {
230 *screenmap = segmentMaps[screenMapName];
233 string _err =
"ScreenMap not found: ";
234 _err.
append(screenMapName);
246 FL_WARN(
"ScreenMap::toJson called with FASTLED_NO_JSON");
250 FL_WARN(
"ScreenMap::toJson called with nullptr doc");
261 for (
const auto& kv : segmentMaps) {
262 if (kv.second.getLength() == 0) {
263 FL_WARN(
"ScreenMap::toJson called with empty segment: " <<
fl::string(kv.first));
267 auto& name = kv.first;
268 auto& segment = kv.second;
269 float diameter = segment.getDiameter();
273 for (u16 i = 0; i < segment.getLength(); i++) {
279 for (u16 i = 0; i < segment.getLength(); i++) {
286 segmentObj.
set(
"x", xArray);
287 segmentObj.
set(
"y", yArray);
288 segmentObj.
set(
"diameter",
fl::Json(
static_cast<double>(diameter)));
291 mapObj.
set(name, segmentObj);
295 doc->
set(
"map", mapObj);
299 FL_WARN(
"ScreenMap::toJson generated JSON: " << debugStr);
304 string *jsonBuffer) {
306 toJson(segmentMaps, &doc);
342 other.mLookUpTable.reset();
360 vec2f screen_coords = lut[
x];
361 return screen_coords;
381 float minX = data[0].
x;
382 float maxX = data[0].
x;
383 float minY = data[0].
y;
384 float maxY = data[0].
y;
386 for (u32 i = 1; i <
length; i++) {
387 const vec2f &p = lut[i];
388 minX =
MIN(minX, p.
x);
389 maxX =
MAX(maxX, p.
x);
390 minY =
MIN(minY, p.
y);
391 maxY =
MAX(maxY, p.
y);
394 return {maxX - minX, maxY - minY};
420 if (
this != &other) {
429 if (
this != &other) {
434 other.mDiameter = -1.0f;
441 for (u32 i = 0; i <
length; i++) {
442 vec2f &curr = data[i];
fl::string to_string() const
JsonValue::template array_iterator< T > begin_array()
JsonValue::template array_iterator< T > end_array()
bool contains(size_t idx) const
void set(const fl::string &key, const Json &value)
void push_back(const Json &value)
fl::optional< float > as_float() const
static Json parse(const fl::string &txt)
bool contains(const Key &key) const
static void toJson(const fl::fl_map< string, ScreenMap > &, fl::Json *doc)
static bool ParseJson(const char *jsonStrScreenMap, fl::fl_map< string, ScreenMap > *segmentMaps, string *err=nullptr)
ScreenMap & operator=(const ScreenMap &other)
void setDiameter(float diameter)
static ScreenMap Circle(int numLeds, float cm_between_leds=1.5f, float cm_led_diameter=0.5f, float completion=1.0f)
void set(u16 index, const vec2f &p)
void addOffset(const vec2f &p)
const vec2f & operator[](u32 x) const
static void toJsonStr(const fl::fl_map< string, ScreenMap > &, string *jsonBuffer)
static const vec2f & empty()
vec2f mapToIndex(u32 x) const
LUTXYFLOATPtr mLookUpTable
float getDiameter() const
Result type for promise operations.
string & append(const BitsetFixed< N > &bs)
FastLED's Elegant JSON Library: fl::Json
Implements the FastLED namespace macros.
constexpr remove_reference< T >::type && move(T &&t) noexcept
void swap(array< T, N > &lhs, array< T, N > &rhs) noexcept(noexcept(lhs.swap(rhs)))
shared_ptr< T > make_shared(Args &&... args)
MapRedBlackTree< Key, T, Compare, fl::allocator_slab< char > > fl_map
HeapVector< T, Allocator > vector
fl::vector< float > jsonArrayToFloatVector(const fl::Json &jsonArray)