|
28 | 28 |
|
29 | 29 |
|
30 | 30 | using System; |
| 31 | +using System.Collections.Generic; |
| 32 | + |
| 33 | +using Litipk.ColorSharp.LightSpectrums; |
31 | 34 |
|
32 | 35 |
|
33 | 36 | namespace Litipk.ColorSharp |
@@ -74,6 +77,8 @@ public sealed class CIEUCS : AConvertibleColor |
74 | 77 | */ |
75 | 78 | public double Y { get { return V; } } |
76 | 79 |
|
| 80 | + static List<CIEUCS> TemperatureChromaticities = null; |
| 81 | + |
77 | 82 | #endregion |
78 | 83 |
|
79 | 84 |
|
@@ -146,10 +151,10 @@ public CIEUCS (double U, double V, double u, double v, double W, AConvertibleCol |
146 | 151 | throw new ArgumentException ("Invalid color point"); |
147 | 152 | } |
148 | 153 |
|
149 | | - if (Math.Abs (U / (U + V + W) - u) > 8*double.Epsilon) { |
| 154 | + if (Math.Abs (U / (U + V + W) - u) > 1e-15) { |
150 | 155 | throw new ArgumentException ("Inconsistent data"); |
151 | 156 | } |
152 | | - if (Math.Abs (V / (U + V + W) - v) > 8*double.Epsilon) { |
| 157 | + if (Math.Abs (V / (U + V + W) - v) > 1e-15) { |
153 | 158 | throw new ArgumentException ("Inconsistent data"); |
154 | 159 | } |
155 | 160 |
|
@@ -177,6 +182,66 @@ public override bool IsInsideColorSpace(bool highPrecision = false) |
177 | 182 | return ToCIExyY ().IsInsideColorSpace (highPrecision); |
178 | 183 | } |
179 | 184 |
|
| 185 | + public override double GetCCT () |
| 186 | + { |
| 187 | + if (DataSource is BlackBodySpectrum) { |
| 188 | + return (DataSource as BlackBodySpectrum).CCT; |
| 189 | + } |
| 190 | + |
| 191 | + if (TemperatureChromaticities == null) { |
| 192 | + // Oversized to improve alignment (needs 302). |
| 193 | + TemperatureChromaticities = new List<CIEUCS> (512); |
| 194 | + |
| 195 | + // From 1000º K to 20000º K |
| 196 | + for (double t = 1000.0; t < 20001.0; t *= 1.01) { |
| 197 | + TemperatureChromaticities.Add ( |
| 198 | + new BlackBodySpectrum (t).ToCIEXYZ (SpectrumStrategy.Nm1Deg2).ToCIEUCS () |
| 199 | + ); |
| 200 | + } |
| 201 | + } |
| 202 | + |
| 203 | + int bestI = 0; |
| 204 | + double minDuv = double.PositiveInfinity; |
| 205 | + |
| 206 | + // First gross grained search |
| 207 | + // TODO: This is a naive search, must be improved! |
| 208 | + for (int i = 0; i < TemperatureChromaticities.Count; i++) { |
| 209 | + double tmpDuv = Math.Sqrt ( |
| 210 | + Math.Pow (u - TemperatureChromaticities [i].u, 2) + |
| 211 | + Math.Pow (v - TemperatureChromaticities [i].v, 2) |
| 212 | + ); |
| 213 | + |
| 214 | + if (minDuv > tmpDuv) { |
| 215 | + minDuv = tmpDuv; |
| 216 | + bestI = i; |
| 217 | + } |
| 218 | + } |
| 219 | + double bestTmp = TemperatureChromaticities [bestI].GetCCT (); |
| 220 | + |
| 221 | + // Preparing the following fine grained search |
| 222 | + double tMin = TemperatureChromaticities [ |
| 223 | + (bestI > 0) ? bestI - 1 : bestI |
| 224 | + ].GetCCT (); |
| 225 | + double tMax = TemperatureChromaticities [ |
| 226 | + (bestI < TemperatureChromaticities.Count - 1) ? bestI + 1 : bestI |
| 227 | + ].GetCCT (); |
| 228 | + double tDiff = (tMax - tMin) / 100.0; |
| 229 | + |
| 230 | + // Second fine grained search |
| 231 | + for (double t = tMin; t < tMax; t += tDiff) { |
| 232 | + var tmpUV = new BlackBodySpectrum (t).ToCIEXYZ (SpectrumStrategy.Nm1Deg2).ToCIEUCS (); |
| 233 | + |
| 234 | + double tmpDuv = Math.Sqrt (Math.Pow (u - tmpUV.u, 2) + Math.Pow (v - tmpUV.v, 2)); |
| 235 | + |
| 236 | + if (minDuv > tmpDuv) { |
| 237 | + minDuv = tmpDuv; |
| 238 | + bestTmp = t; |
| 239 | + } |
| 240 | + } |
| 241 | + |
| 242 | + return bestTmp; |
| 243 | + } |
| 244 | + |
180 | 245 | /** |
181 | 246 | * <inheritdoc /> |
182 | 247 | */ |
|
0 commit comments