| 355 | } |
| 356 | |
| 357 | void FlowFieldFloat::drawFlowVectors(fl::span<CRGB> leds) { |
| 358 | int w = (int)getWidth(); |
| 359 | int h = (int)getHeight(); |
| 360 | |
| 361 | // Helper: plot a single subpixel point via Tile2x2 through the XYMap. |
| 362 | auto plotTile = [&](const CRGB &color, float px, float py, |
| 363 | bool horiz) { |
| 364 | int ix = (int)floorf(px); |
| 365 | int iy = (int)floorf(py); |
| 366 | float fx = px - (float)ix; |
| 367 | float fy = py - (float)iy; |
| 368 | Tile2x2_u8 tile; |
| 369 | tile.setOrigin((u16)ix, (u16)iy); |
| 370 | if (horiz) { |
| 371 | // X profile: subpixel along y only (one column wide) |
| 372 | tile.at(0, 0) = (u8)((1.0f - fy) * 255.0f); |
| 373 | tile.at(1, 0) = 0; |
| 374 | tile.at(0, 1) = (u8)(fy * 255.0f); |
| 375 | tile.at(1, 1) = 0; |
| 376 | } else { |
| 377 | // Y profile: subpixel along x only (one row tall) |
| 378 | tile.at(0, 0) = (u8)((1.0f - fx) * 255.0f); |
| 379 | tile.at(1, 0) = (u8)(fx * 255.0f); |
| 380 | tile.at(0, 1) = 0; |
| 381 | tile.at(1, 1) = 0; |
| 382 | } |
| 383 | tile.draw(color, mXyMap, leds); |
| 384 | }; |
| 385 | |
| 386 | // Display amplitude: 0.3 = profile uses ~30% of the display around center. |
| 387 | constexpr float amp = 0.3f; |
| 388 | |
| 389 | // X profile (per-column): plot value as y-position — cyan. |
| 390 | // Interpolate between consecutive columns to fill gaps. |
| 391 | CRGB xColor(0, 255, 255); |
| 392 | float centerY = (float)(h - 1) * 0.5f; |
| 393 | float prevPy = 0.0f; |
| 394 | for (int x = 0; x < w; x++) { |
| 395 | float val = mXProf[x]; // [-1, 1] |
| 396 | float py = centerY - val * amp * centerY; |
| 397 | plotTile(xColor, (float)x, py, true); |
| 398 | if (x > 0) { |
| 399 | float dy = py - prevPy; |
| 400 | int gap = (int)fabsf(dy); |
| 401 | for (int s = 1; s < gap; s++) { |
| 402 | float t = (float)s / (float)gap; |
| 403 | float midY = prevPy + dy * t; |
| 404 | float midX = (float)(x - 1) + t; |
| 405 | plotTile(xColor, midX, midY, true); |
| 406 | } |
| 407 | } |
| 408 | prevPy = py; |
| 409 | } |
| 410 | |
| 411 | // Y profile (per-row): plot value as x-position — yellow. |
| 412 | // Interpolate between consecutive rows to fill gaps. |
| 413 | CRGB yColor(255, 255, 0); |
| 414 | float centerX = (float)(w - 1) * 0.5f; |