-
Notifications
You must be signed in to change notification settings - Fork 7
/
index.js
135 lines (120 loc) · 4.5 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
var colorPointsGamut_A = [[0.703, 0.296], [0.214, 0.709], [0.139, 0.081]];
var colorPointsGamut_B = [[0.674, 0.322], [0.408, 0.517], [0.168, 0.041]];
var colorPointsGamut_C = [[0.692, 0.308], [0.17, 0.7], [0.153, 0.048]];
var colorPointsDefault = [[1.0, 0.0], [0.0, 1.0], [0.0, 0.0]];
var GAMUT_A_BULBS_LIST = ["LLC001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012", "LLC014", "LLC013", "LST001"];
var GAMUT_B_BULBS_LIST = ["LCT001", "LCT002", "LCT003", "LCT004", "LLM001", "LCT005", "LCT006", "LCT007"];
var GAMUT_C_BULBS_LIST = ["LCT010", "LCT011", "LCT012", "LCT014", "LCT015", "LCT016", "LLC020", "LST002"];
var MULTI_SOURCE_LUMINAIRES = ["HBL001", "HBL002", "HBL003", "HIL001", "HIL002", "HEL001", "HEL002"];
module.exports = {
/**
* Calculate XY color points for a given RGB value.
* @param {number} red RGB red value (0-255)
* @param {number} green RGB green value (0-255)
* @param {number} blue RGB blue value (0-255)
* @param {string} model Hue bulb model
* @returns {number[]}
*/
calculateXY: function(red, green, blue, model) {
red = red / 255;
green = green / 255;
blue = blue / 255;
var r = red > 0.04045 ? Math.pow(((red + 0.055) / 1.055), 2.4000000953674316) : red / 12.92;
var g = green > 0.04045 ? Math.pow(((green + 0.055) / 1.055), 2.4000000953674316) : green / 12.92;
var b = blue > 0.04045 ? Math.pow(((blue + 0.055) / 1.055), 2.4000000953674316) : blue / 12.92;
var x = r * 0.664511 + g * 0.154324 + b * 0.162028;
var y = r * 0.283881 + g * 0.668433 + b * 0.047685;
var z = r * 8.8E-5 + g * 0.07231 + b * 0.986039;
var xy = [x / (x + y + z), y / (x + y + z)];
if (isNaN(xy[0])) {
xy[0] = 0.0;
}
if (isNaN(xy[1])) {
xy[1] = 0.0;
}
var colorPoints = colorPointsForModel(model);
var inReachOfLamps = checkPointInLampsReach(xy, colorPoints);
if (!inReachOfLamps) {
var pAB = getClosestPointToPoints(colorPoints[0], colorPoints[1], xy);
var pAC = getClosestPointToPoints(colorPoints[2], colorPoints[0], xy);
var pBC = getClosestPointToPoints(colorPoints[1], colorPoints[2], xy);
var dAB = getDistanceBetweenTwoPoints(xy, pAB);
var dAC = getDistanceBetweenTwoPoints(xy, pAC);
var dBC = getDistanceBetweenTwoPoints(xy, pBC);
var lowest = dAB;
var closestPoint = pAB;
if (dAC < dAB) {
lowest = dAC;
closestPoint = pAC;
}
if (dBC < lowest) {
closestPoint = pBC;
}
xy[0] = closestPoint[0];
xy[1] = closestPoint[1];
}
xy[0] = precision(xy[0]);
xy[1] = precision(xy[1]);
return xy;
}
};
function colorPointsForModel(model) {
if (model == null) {
model = " ";
}
if (GAMUT_B_BULBS_LIST.indexOf(model) == -1 && MULTI_SOURCE_LUMINAIRES.indexOf(model) == -1) {
if(GAMUT_A_BULBS_LIST.indexOf(model) >= 0) {
return colorPointsGamut_A;
} else if(GAMUT_C_BULBS_LIST.indexOf(model) >= 0) {
return colorPointsGamut_C;
} else {
return colorPointsDefault;
}
} else {
return colorPointsGamut_B;
}
}
function checkPointInLampsReach(point, colorPoints) {
if (point != null && colorPoints != null) {
var red = colorPoints[0];
var green = colorPoints[1];
var blue = colorPoints[2];
var v1 = [green[0] - red[0], green[1] - red[1]];
var v2 = [blue[0] - red[0], blue[1] - red[1]];
var q = [point[0] - red[0], point[1] - red[1]];
var s = crossProduct(q, v2) / crossProduct(v1, v2);
var t = crossProduct(v1, q) / crossProduct(v1, v2);
return s >= 0.0 && t >= 0.0 && s + t <= 1.0;
} else {
return false;
}
}
function crossProduct(point1, point2) {
return point1[0] * point2[1] - point1[1] * point2[0];
}
function getClosestPointToPoints(pointA, pointB, pointP) {
if (pointA != null && pointB != null && pointP != null) {
var pointAP = [pointP[0] - pointA[0], pointP[1] - pointA[1]];
var pointAB = [pointB[0] - pointA[0], pointB[1] - pointA[1]];
var ab2 = pointAB[0] * pointAB[0] + pointAB[1] * pointAB[1];
var apAb = pointAP[0] * pointAB[0] + pointAP[1] * pointAB[1];
var t = apAb / ab2;
if(t < 0.0) {
t = 0.0;
} else if(t > 1.0) {
t = 1.0;
}
return [pointA[0] + pointAB[0] * t, pointA[1] + pointAB[1] * t];
} else {
return null;
}
}
function getDistanceBetweenTwoPoints(pointA, pointB) {
var dx = pointA[0] - pointB[0];
var dy = pointA[1] - pointB[1];
var dist = Math.sqrt(dx * dx + dy * dy);
return dist;
}
function precision(d) {
return Math.round(10000.0 * d) / 10000.0;
}