Port of the reference's strict_subgamut: project, then triangle-route.
| 817 | |
| 818 | // Port of the reference's strict_subgamut: project, then triangle-route. |
| 819 | inline bool strict_with_projection(const DiodeProfile& p, ProfileCache& cache, |
| 820 | float s_r, float s_g, float s_b, |
| 821 | float out[4]) { |
| 822 | fastled_mirror::build_cache(&p, &cache); // shared cache builder |
| 823 | out[0] = out[1] = out[2] = out[3] = 0.0f; |
| 824 | float X_t[3]; |
| 825 | if (cache.has_source_space) { |
| 826 | const float s[3] = { s_r, s_g, s_b }; |
| 827 | matvec3(cache.M_src, s, X_t); |
| 828 | } else { |
| 829 | X_t[0] = cache.P_R[0]*s_r + cache.P_G[0]*s_g + cache.P_B[0]*s_b; |
| 830 | X_t[1] = cache.P_R[1]*s_r + cache.P_G[1]*s_g + cache.P_B[1]*s_b; |
| 831 | X_t[2] = cache.P_R[2]*s_r + cache.P_G[2]*s_g + cache.P_B[2]*s_b; |
| 832 | } |
| 833 | if (X_t[0]+X_t[1]+X_t[2] < 1e-9f) return true; |
| 834 | float xy_t[2]; |
| 835 | project_to_hull(p, X_t, xy_t); |
| 836 | // After projection xy_t is guaranteed in-hull; run normal triangle routing. |
| 837 | struct SG { const float* a; const float* b; const float* c; |
| 838 | const float (*Pinv)[3]; int ia,ib,ic; }; |
| 839 | const SG sgs[3] = { |
| 840 | { p.xy_r, p.xy_g, cache.xy_w, cache.P_RGW_inv, 0,1,3 }, |
| 841 | { p.xy_r, p.xy_b, cache.xy_w, cache.P_RBW_inv, 0,2,3 }, |
| 842 | { p.xy_b, p.xy_g, cache.xy_w, cache.P_BGW_inv, 2,1,3 }, |
| 843 | }; |
| 844 | const float kEps = 1e-4f; |
| 845 | for (int k = 0; k < 3; ++k) { |
| 846 | const SG& sg = sgs[k]; |
| 847 | float bary[3]; |
| 848 | if (!barycentric_xy(xy_t, sg.a, sg.b, sg.c, bary)) continue; |
| 849 | if (bary[0] < -kEps || bary[1] < -kEps || bary[2] < -kEps) continue; |
| 850 | float t[3]; matvec3(sg.Pinv, X_t, t); |
| 851 | if (t[0] < -kEps || t[1] < -kEps || t[2] < -kEps) continue; |
| 852 | if (t[0] < 0) t[0] = 0; if (t[1] < 0) t[1] = 0; if (t[2] < 0) t[2] = 0; |
| 853 | float m = t[0]; if (t[1] > m) m = t[1]; if (t[2] > m) m = t[2]; |
| 854 | if (m > 1.0f) { float inv = 1.0f/m; t[0]*=inv; t[1]*=inv; t[2]*=inv; } |
| 855 | out[sg.ia] = t[0]; out[sg.ib] = t[1]; out[sg.ic] = t[2]; |
| 856 | return true; |
| 857 | } |
| 858 | return false; |
| 859 | } |
| 860 | |
| 861 | } // namespace reference |
| 862 |
no test coverage detected