simview 3.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. simview/__init__.py +69 -0
  2. simview/__main__.py +174 -0
  3. simview/launcher.py +109 -0
  4. simview/live.py +204 -0
  5. simview/merge.py +593 -0
  6. simview/model.py +690 -0
  7. simview/py.typed +0 -0
  8. simview/scene.py +603 -0
  9. simview/server.py +739 -0
  10. simview/state.py +190 -0
  11. simview/static/css/controls.css +36 -0
  12. simview/static/js/SimView.js +601 -0
  13. simview/static/js/components/AnimationController.js +654 -0
  14. simview/static/js/components/BatchManager.js +198 -0
  15. simview/static/js/components/InteractionController.js +446 -0
  16. simview/static/js/components/InteractionControls.js +116 -0
  17. simview/static/js/components/Scene.js +166 -0
  18. simview/static/js/components/StateStore.js +188 -0
  19. simview/static/js/config.js +233 -0
  20. simview/static/js/main.js +3 -0
  21. simview/static/js/objects/Body.js +616 -0
  22. simview/static/js/objects/StaticObject.js +181 -0
  23. simview/static/js/objects/Terrain.js +514 -0
  24. simview/static/js/objects/utils.js +378 -0
  25. simview/static/js/ui/AnalysisPanel.js +233 -0
  26. simview/static/js/ui/BatchLegend.js +207 -0
  27. simview/static/js/ui/BodyStateWindow.js +521 -0
  28. simview/static/js/ui/Controls.js +586 -0
  29. simview/static/js/ui/ErrorMetrics.js +664 -0
  30. simview/static/js/ui/Legend.js +87 -0
  31. simview/static/js/ui/PlaybackControls.js +314 -0
  32. simview/static/js/ui/ScalarPlotter.js +575 -0
  33. simview/static/js/utils/blobCodec.js +73 -0
  34. simview/static/js/utils/bodyTransforms.js +151 -0
  35. simview/static/js/utils/csv.js +46 -0
  36. simview/static/js/utils/errorMath.js +69 -0
  37. simview/static/js/utils/injectStyles.js +16 -0
  38. simview/static/js/utils/interpolate.js +65 -0
  39. simview/static/js/utils/liveFollow.js +17 -0
  40. simview/static/js/utils/loadRecordingLibs.js +34 -0
  41. simview/static/js/utils/viewState.js +226 -0
  42. simview/static/lib/chroma-js-3.1.2/index.min.js +8 -0
  43. simview/static/lib/chroma-js-3.1.2/src/Color.js +49 -0
  44. simview/static/lib/chroma-js-3.1.2/src/chroma.js +10 -0
  45. simview/static/lib/chroma-js-3.1.2/src/colors/colorbrewer.js +81 -0
  46. simview/static/lib/chroma-js-3.1.2/src/colors/w3cx11.js +164 -0
  47. simview/static/lib/chroma-js-3.1.2/src/generator/average.js +88 -0
  48. simview/static/lib/chroma-js-3.1.2/src/generator/bezier.js +86 -0
  49. simview/static/lib/chroma-js-3.1.2/src/generator/blend.js +57 -0
  50. simview/static/lib/chroma-js-3.1.2/src/generator/cubehelix.js +87 -0
  51. simview/static/lib/chroma-js-3.1.2/src/generator/mix.js +19 -0
  52. simview/static/lib/chroma-js-3.1.2/src/generator/random.js +12 -0
  53. simview/static/lib/chroma-js-3.1.2/src/generator/scale.js +394 -0
  54. simview/static/lib/chroma-js-3.1.2/src/interpolator/_hsx.js +59 -0
  55. simview/static/lib/chroma-js-3.1.2/src/interpolator/hcg.js +12 -0
  56. simview/static/lib/chroma-js-3.1.2/src/interpolator/hsi.js +12 -0
  57. simview/static/lib/chroma-js-3.1.2/src/interpolator/hsl.js +12 -0
  58. simview/static/lib/chroma-js-3.1.2/src/interpolator/hsv.js +12 -0
  59. simview/static/lib/chroma-js-3.1.2/src/interpolator/index.js +1 -0
  60. simview/static/lib/chroma-js-3.1.2/src/interpolator/lab.js +19 -0
  61. simview/static/lib/chroma-js-3.1.2/src/interpolator/lch.js +13 -0
  62. simview/static/lib/chroma-js-3.1.2/src/interpolator/lrgb.js +19 -0
  63. simview/static/lib/chroma-js-3.1.2/src/interpolator/num.js +15 -0
  64. simview/static/lib/chroma-js-3.1.2/src/interpolator/oklab.js +19 -0
  65. simview/static/lib/chroma-js-3.1.2/src/interpolator/oklch.js +12 -0
  66. simview/static/lib/chroma-js-3.1.2/src/interpolator/rgb.js +18 -0
  67. simview/static/lib/chroma-js-3.1.2/src/io/cmyk/cmyk2rgb.js +16 -0
  68. simview/static/lib/chroma-js-3.1.2/src/io/cmyk/index.js +27 -0
  69. simview/static/lib/chroma-js-3.1.2/src/io/cmyk/rgb2cmyk.js +17 -0
  70. simview/static/lib/chroma-js-3.1.2/src/io/css/css2rgb.js +238 -0
  71. simview/static/lib/chroma-js-3.1.2/src/io/css/hsl2css.js +26 -0
  72. simview/static/lib/chroma-js-3.1.2/src/io/css/index.js +27 -0
  73. simview/static/lib/chroma-js-3.1.2/src/io/css/lab2css.js +24 -0
  74. simview/static/lib/chroma-js-3.1.2/src/io/css/lch2css.js +24 -0
  75. simview/static/lib/chroma-js-3.1.2/src/io/css/oklab2css.js +16 -0
  76. simview/static/lib/chroma-js-3.1.2/src/io/css/oklch2css.js +16 -0
  77. simview/static/lib/chroma-js-3.1.2/src/io/css/rgb2css.js +61 -0
  78. simview/static/lib/chroma-js-3.1.2/src/io/gl/index.js +22 -0
  79. simview/static/lib/chroma-js-3.1.2/src/io/hcg/hcg2rgb.js +55 -0
  80. simview/static/lib/chroma-js-3.1.2/src/io/hcg/index.js +27 -0
  81. simview/static/lib/chroma-js-3.1.2/src/io/hcg/rgb2hcg.js +23 -0
  82. simview/static/lib/chroma-js-3.1.2/src/io/hex/hex2rgb.js +56 -0
  83. simview/static/lib/chroma-js-3.1.2/src/io/hex/index.js +29 -0
  84. simview/static/lib/chroma-js-3.1.2/src/io/hex/rgb2hex.js +29 -0
  85. simview/static/lib/chroma-js-3.1.2/src/io/hsi/hsi2rgb.js +45 -0
  86. simview/static/lib/chroma-js-3.1.2/src/io/hsi/index.js +27 -0
  87. simview/static/lib/chroma-js-3.1.2/src/io/hsi/rgb2hsi.js +31 -0
  88. simview/static/lib/chroma-js-3.1.2/src/io/hsl/hsl2rgb.js +35 -0
  89. simview/static/lib/chroma-js-3.1.2/src/io/hsl/index.js +27 -0
  90. simview/static/lib/chroma-js-3.1.2/src/io/hsl/rgb2hsl.js +45 -0
  91. simview/static/lib/chroma-js-3.1.2/src/io/hsv/hsv2rgb.js +47 -0
  92. simview/static/lib/chroma-js-3.1.2/src/io/hsv/index.js +27 -0
  93. simview/static/lib/chroma-js-3.1.2/src/io/hsv/rgb2hsv.js +32 -0
  94. simview/static/lib/chroma-js-3.1.2/src/io/input.js +4 -0
  95. simview/static/lib/chroma-js-3.1.2/src/io/lab/index.js +28 -0
  96. simview/static/lib/chroma-js-3.1.2/src/io/lab/lab-constants.js +120 -0
  97. simview/static/lib/chroma-js-3.1.2/src/io/lab/lab2rgb.js +101 -0
  98. simview/static/lib/chroma-js-3.1.2/src/io/lab/rgb2lab.js +67 -0
  99. simview/static/lib/chroma-js-3.1.2/src/io/lch/hcl2rgb.js +9 -0
  100. simview/static/lib/chroma-js-3.1.2/src/io/lch/index.js +35 -0
  101. simview/static/lib/chroma-js-3.1.2/src/io/lch/lab2lch.js +12 -0
  102. simview/static/lib/chroma-js-3.1.2/src/io/lch/lch2lab.js +18 -0
  103. simview/static/lib/chroma-js-3.1.2/src/io/lch/lch2rgb.js +13 -0
  104. simview/static/lib/chroma-js-3.1.2/src/io/lch/rgb2lch.js +12 -0
  105. simview/static/lib/chroma-js-3.1.2/src/io/named/index.js +30 -0
  106. simview/static/lib/chroma-js-3.1.2/src/io/num/index.js +32 -0
  107. simview/static/lib/chroma-js-3.1.2/src/io/num/num2rgb.js +13 -0
  108. simview/static/lib/chroma-js-3.1.2/src/io/num/rgb2num.js +8 -0
  109. simview/static/lib/chroma-js-3.1.2/src/io/oklab/index.js +27 -0
  110. simview/static/lib/chroma-js-3.1.2/src/io/oklab/oklab2rgb.js +34 -0
  111. simview/static/lib/chroma-js-3.1.2/src/io/oklab/rgb2oklab.js +37 -0
  112. simview/static/lib/chroma-js-3.1.2/src/io/oklch/index.js +27 -0
  113. simview/static/lib/chroma-js-3.1.2/src/io/oklch/oklch2rgb.js +13 -0
  114. simview/static/lib/chroma-js-3.1.2/src/io/oklch/rgb2oklch.js +12 -0
  115. simview/static/lib/chroma-js-3.1.2/src/io/rgb/index.js +44 -0
  116. simview/static/lib/chroma-js-3.1.2/src/io/temp/index.js +22 -0
  117. simview/static/lib/chroma-js-3.1.2/src/io/temp/rgb2temperature.js +30 -0
  118. simview/static/lib/chroma-js-3.1.2/src/io/temp/temperature2rgb.js +39 -0
  119. simview/static/lib/chroma-js-3.1.2/src/ops/alpha.js +13 -0
  120. simview/static/lib/chroma-js-3.1.2/src/ops/clipped.js +5 -0
  121. simview/static/lib/chroma-js-3.1.2/src/ops/darken.js +17 -0
  122. simview/static/lib/chroma-js-3.1.2/src/ops/get.js +13 -0
  123. simview/static/lib/chroma-js-3.1.2/src/ops/luminance.js +54 -0
  124. simview/static/lib/chroma-js-3.1.2/src/ops/mix.js +10 -0
  125. simview/static/lib/chroma-js-3.1.2/src/ops/premultiply.js +12 -0
  126. simview/static/lib/chroma-js-3.1.2/src/ops/saturate.js +15 -0
  127. simview/static/lib/chroma-js-3.1.2/src/ops/set.js +43 -0
  128. simview/static/lib/chroma-js-3.1.2/src/ops/shade.js +11 -0
  129. simview/static/lib/chroma-js-3.1.2/src/utils/analyze.js +191 -0
  130. simview/static/lib/chroma-js-3.1.2/src/utils/clip_rgb.js +15 -0
  131. simview/static/lib/chroma-js-3.1.2/src/utils/contrast.js +12 -0
  132. simview/static/lib/chroma-js-3.1.2/src/utils/contrastAPCA.js +68 -0
  133. simview/static/lib/chroma-js-3.1.2/src/utils/delta-e.js +62 -0
  134. simview/static/lib/chroma-js-3.1.2/src/utils/distance.js +17 -0
  135. simview/static/lib/chroma-js-3.1.2/src/utils/index.js +27 -0
  136. simview/static/lib/chroma-js-3.1.2/src/utils/last.js +8 -0
  137. simview/static/lib/chroma-js-3.1.2/src/utils/limit.js +5 -0
  138. simview/static/lib/chroma-js-3.1.2/src/utils/multiply-matrices.js +36 -0
  139. simview/static/lib/chroma-js-3.1.2/src/utils/scales.js +15 -0
  140. simview/static/lib/chroma-js-3.1.2/src/utils/type.js +18 -0
  141. simview/static/lib/chroma-js-3.1.2/src/utils/unpack.js +17 -0
  142. simview/static/lib/chroma-js-3.1.2/src/utils/valid.js +11 -0
  143. simview/static/lib/chroma-js-3.1.2/src/version.js +2 -0
  144. simview/static/lib/download.js +132 -0
  145. simview/static/lib/js-colormaps.js +19335 -0
  146. simview/static/lib/tar.js +334 -0
  147. simview/static/lib/three-0.174.0/addons/controls/OrbitControls.js +1556 -0
  148. simview/static/lib/three-0.174.0/addons/libs/lil-gui.module.min.js +8 -0
  149. simview/static/lib/three-0.174.0/three.core.js +48830 -0
  150. simview/static/lib/three-0.174.0/three.module.js +17313 -0
  151. simview/static/lib/uPlot.esm.js +6140 -0
  152. simview/static/lib/uPlot.min.css +2 -0
  153. simview/static/textures/contacts/red-cross0.png +0 -0
  154. simview/static/textures/points/ball0.png +0 -0
  155. simview/static/textures/points/ball1.png +0 -0
  156. simview/templates/index.html +81 -0
  157. simview/utils.py +41 -0
  158. simview-3.2.dist-info/METADATA +552 -0
  159. simview-3.2.dist-info/RECORD +163 -0
  160. simview-3.2.dist-info/WHEEL +5 -0
  161. simview-3.2.dist-info/entry_points.txt +2 -0
  162. simview-3.2.dist-info/licenses/LICENSE +28 -0
  163. simview-3.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,45 @@
1
+ import { unpack, limit, TWOPI, PITHIRD } from '../../utils/index.js';
2
+ const { cos } = Math;
3
+
4
+ /*
5
+ * hue [0..360]
6
+ * saturation [0..1]
7
+ * intensity [0..1]
8
+ */
9
+ const hsi2rgb = (...args) => {
10
+ /*
11
+ borrowed from here:
12
+ http://hummer.stanford.edu/museinfo/doc/examples/humdrum/keyscape2/hsi2rgb.cpp
13
+ */
14
+ args = unpack(args, 'hsi');
15
+ let [h, s, i] = args;
16
+ let r, g, b;
17
+
18
+ if (isNaN(h)) h = 0;
19
+ if (isNaN(s)) s = 0;
20
+ // normalize hue
21
+ if (h > 360) h -= 360;
22
+ if (h < 0) h += 360;
23
+ h /= 360;
24
+ if (h < 1 / 3) {
25
+ b = (1 - s) / 3;
26
+ r = (1 + (s * cos(TWOPI * h)) / cos(PITHIRD - TWOPI * h)) / 3;
27
+ g = 1 - (b + r);
28
+ } else if (h < 2 / 3) {
29
+ h -= 1 / 3;
30
+ r = (1 - s) / 3;
31
+ g = (1 + (s * cos(TWOPI * h)) / cos(PITHIRD - TWOPI * h)) / 3;
32
+ b = 1 - (r + g);
33
+ } else {
34
+ h -= 2 / 3;
35
+ g = (1 - s) / 3;
36
+ b = (1 + (s * cos(TWOPI * h)) / cos(PITHIRD - TWOPI * h)) / 3;
37
+ r = 1 - (g + b);
38
+ }
39
+ r = limit(i * r * 3);
40
+ g = limit(i * g * 3);
41
+ b = limit(i * b * 3);
42
+ return [r * 255, g * 255, b * 255, args.length > 3 ? args[3] : 1];
43
+ };
44
+
45
+ export default hsi2rgb;
@@ -0,0 +1,27 @@
1
+ import { unpack, type } from '../../utils/index.js';
2
+ import chroma from '../../chroma.js';
3
+ import Color from '../../Color.js';
4
+ import input from '../input.js';
5
+ import hsi2rgb from './hsi2rgb.js';
6
+ import rgb2hsi from './rgb2hsi.js';
7
+
8
+ Color.prototype.hsi = function () {
9
+ return rgb2hsi(this._rgb);
10
+ };
11
+
12
+ const hsi = (...args) => new Color(...args, 'hsi');
13
+ chroma.hsi = hsi;
14
+
15
+ input.format.hsi = hsi2rgb;
16
+
17
+ input.autodetect.push({
18
+ p: 2,
19
+ test: (...args) => {
20
+ args = unpack(args, 'hsi');
21
+ if (type(args) === 'array' && args.length === 3) {
22
+ return 'hsi';
23
+ }
24
+ }
25
+ });
26
+
27
+ export { hsi };
@@ -0,0 +1,31 @@
1
+ import { unpack, TWOPI } from '../../utils/index.js';
2
+ const { min, sqrt, acos } = Math;
3
+
4
+ const rgb2hsi = (...args) => {
5
+ /*
6
+ borrowed from here:
7
+ http://hummer.stanford.edu/museinfo/doc/examples/humdrum/keyscape2/rgb2hsi.cpp
8
+ */
9
+ let [r, g, b] = unpack(args, 'rgb');
10
+ r /= 255;
11
+ g /= 255;
12
+ b /= 255;
13
+ let h;
14
+ const min_ = min(r, g, b);
15
+ const i = (r + g + b) / 3;
16
+ const s = i > 0 ? 1 - min_ / i : 0;
17
+ if (s === 0) {
18
+ h = NaN;
19
+ } else {
20
+ h = (r - g + (r - b)) / 2;
21
+ h /= sqrt((r - g) * (r - g) + (r - b) * (g - b));
22
+ h = acos(h);
23
+ if (b > g) {
24
+ h = TWOPI - h;
25
+ }
26
+ h /= TWOPI;
27
+ }
28
+ return [h * 360, s, i];
29
+ };
30
+
31
+ export default rgb2hsi;
@@ -0,0 +1,35 @@
1
+ import { unpack } from '../../utils/index.js';
2
+
3
+ const hsl2rgb = (...args) => {
4
+ args = unpack(args, 'hsl');
5
+ const [h, s, l] = args;
6
+ let r, g, b;
7
+ if (s === 0) {
8
+ r = g = b = l * 255;
9
+ } else {
10
+ const t3 = [0, 0, 0];
11
+ const c = [0, 0, 0];
12
+ const t2 = l < 0.5 ? l * (1 + s) : l + s - l * s;
13
+ const t1 = 2 * l - t2;
14
+ const h_ = h / 360;
15
+ t3[0] = h_ + 1 / 3;
16
+ t3[1] = h_;
17
+ t3[2] = h_ - 1 / 3;
18
+ for (let i = 0; i < 3; i++) {
19
+ if (t3[i] < 0) t3[i] += 1;
20
+ if (t3[i] > 1) t3[i] -= 1;
21
+ if (6 * t3[i] < 1) c[i] = t1 + (t2 - t1) * 6 * t3[i];
22
+ else if (2 * t3[i] < 1) c[i] = t2;
23
+ else if (3 * t3[i] < 2) c[i] = t1 + (t2 - t1) * (2 / 3 - t3[i]) * 6;
24
+ else c[i] = t1;
25
+ }
26
+ [r, g, b] = [c[0] * 255, c[1] * 255, c[2] * 255];
27
+ }
28
+ if (args.length > 3) {
29
+ // keep alpha channel
30
+ return [r, g, b, args[3]];
31
+ }
32
+ return [r, g, b, 1];
33
+ };
34
+
35
+ export default hsl2rgb;
@@ -0,0 +1,27 @@
1
+ import { unpack, type } from '../../utils/index.js';
2
+ import chroma from '../../chroma.js';
3
+ import Color from '../../Color.js';
4
+ import input from '../input.js';
5
+ import hsl2rgb from './hsl2rgb.js';
6
+ import rgb2hsl from './rgb2hsl.js';
7
+
8
+ Color.prototype.hsl = function () {
9
+ return rgb2hsl(this._rgb);
10
+ };
11
+
12
+ const hsl = (...args) => new Color(...args, 'hsl');
13
+ chroma.hsl = hsl;
14
+
15
+ input.format.hsl = hsl2rgb;
16
+
17
+ input.autodetect.push({
18
+ p: 2,
19
+ test: (...args) => {
20
+ args = unpack(args, 'hsl');
21
+ if (type(args) === 'array' && args.length === 3) {
22
+ return 'hsl';
23
+ }
24
+ }
25
+ });
26
+
27
+ export { hsl };
@@ -0,0 +1,45 @@
1
+ import { unpack, min, max } from '../../utils/index.js';
2
+
3
+ /*
4
+ * supported arguments:
5
+ * - rgb2hsl(r,g,b)
6
+ * - rgb2hsl(r,g,b,a)
7
+ * - rgb2hsl([r,g,b])
8
+ * - rgb2hsl([r,g,b,a])
9
+ * - rgb2hsl({r,g,b,a})
10
+ */
11
+ const rgb2hsl = (...args) => {
12
+ args = unpack(args, 'rgba');
13
+ let [r, g, b] = args;
14
+
15
+ r /= 255;
16
+ g /= 255;
17
+ b /= 255;
18
+
19
+ const minRgb = min(r, g, b);
20
+ const maxRgb = max(r, g, b);
21
+
22
+ const l = (maxRgb + minRgb) / 2;
23
+ let s, h;
24
+
25
+ if (maxRgb === minRgb) {
26
+ s = 0;
27
+ h = Number.NaN;
28
+ } else {
29
+ s =
30
+ l < 0.5
31
+ ? (maxRgb - minRgb) / (maxRgb + minRgb)
32
+ : (maxRgb - minRgb) / (2 - maxRgb - minRgb);
33
+ }
34
+
35
+ if (r == maxRgb) h = (g - b) / (maxRgb - minRgb);
36
+ else if (g == maxRgb) h = 2 + (b - r) / (maxRgb - minRgb);
37
+ else if (b == maxRgb) h = 4 + (r - g) / (maxRgb - minRgb);
38
+
39
+ h *= 60;
40
+ if (h < 0) h += 360;
41
+ if (args.length > 3 && args[3] !== undefined) return [h, s, l, args[3]];
42
+ return [h, s, l];
43
+ };
44
+
45
+ export default rgb2hsl;
@@ -0,0 +1,47 @@
1
+ import { unpack } from '../../utils/index.js';
2
+ const { floor } = Math;
3
+
4
+ const hsv2rgb = (...args) => {
5
+ args = unpack(args, 'hsv');
6
+ let [h, s, v] = args;
7
+ let r, g, b;
8
+ v *= 255;
9
+ if (s === 0) {
10
+ r = g = b = v;
11
+ } else {
12
+ if (h === 360) h = 0;
13
+ if (h > 360) h -= 360;
14
+ if (h < 0) h += 360;
15
+ h /= 60;
16
+
17
+ const i = floor(h);
18
+ const f = h - i;
19
+ const p = v * (1 - s);
20
+ const q = v * (1 - s * f);
21
+ const t = v * (1 - s * (1 - f));
22
+
23
+ switch (i) {
24
+ case 0:
25
+ [r, g, b] = [v, t, p];
26
+ break;
27
+ case 1:
28
+ [r, g, b] = [q, v, p];
29
+ break;
30
+ case 2:
31
+ [r, g, b] = [p, v, t];
32
+ break;
33
+ case 3:
34
+ [r, g, b] = [p, q, v];
35
+ break;
36
+ case 4:
37
+ [r, g, b] = [t, p, v];
38
+ break;
39
+ case 5:
40
+ [r, g, b] = [v, p, q];
41
+ break;
42
+ }
43
+ }
44
+ return [r, g, b, args.length > 3 ? args[3] : 1];
45
+ };
46
+
47
+ export default hsv2rgb;
@@ -0,0 +1,27 @@
1
+ import { unpack, type } from '../../utils/index.js';
2
+ import chroma from '../../chroma.js';
3
+ import Color from '../../Color.js';
4
+ import input from '../input.js';
5
+ import hsv2rgb from './hsv2rgb.js';
6
+ import rgb2hsv from './rgb2hsv.js';
7
+
8
+ Color.prototype.hsv = function () {
9
+ return rgb2hsv(this._rgb);
10
+ };
11
+
12
+ const hsv = (...args) => new Color(...args, 'hsv');
13
+ chroma.hsv = hsv;
14
+
15
+ input.format.hsv = hsv2rgb;
16
+
17
+ input.autodetect.push({
18
+ p: 2,
19
+ test: (...args) => {
20
+ args = unpack(args, 'hsv');
21
+ if (type(args) === 'array' && args.length === 3) {
22
+ return 'hsv';
23
+ }
24
+ }
25
+ });
26
+
27
+ export { hsv };
@@ -0,0 +1,32 @@
1
+ import { unpack } from '../../utils/index.js';
2
+ const { min, max } = Math;
3
+
4
+ /*
5
+ * supported arguments:
6
+ * - rgb2hsv(r,g,b)
7
+ * - rgb2hsv([r,g,b])
8
+ * - rgb2hsv({r,g,b})
9
+ */
10
+ const rgb2hsl = (...args) => {
11
+ args = unpack(args, 'rgb');
12
+ let [r, g, b] = args;
13
+ const min_ = min(r, g, b);
14
+ const max_ = max(r, g, b);
15
+ const delta = max_ - min_;
16
+ let h, s, v;
17
+ v = max_ / 255.0;
18
+ if (max_ === 0) {
19
+ h = Number.NaN;
20
+ s = 0;
21
+ } else {
22
+ s = delta / max_;
23
+ if (r === max_) h = (g - b) / delta;
24
+ if (g === max_) h = 2 + (b - r) / delta;
25
+ if (b === max_) h = 4 + (r - g) / delta;
26
+ h *= 60;
27
+ if (h < 0) h += 360;
28
+ }
29
+ return [h, s, v];
30
+ };
31
+
32
+ export default rgb2hsl;
@@ -0,0 +1,4 @@
1
+ export default {
2
+ format: {},
3
+ autodetect: []
4
+ };
@@ -0,0 +1,28 @@
1
+ import { unpack, type } from '../../utils/index.js';
2
+ import chroma from '../../chroma.js';
3
+ import Color from '../../Color.js';
4
+ import input from '../input.js';
5
+ import lab2rgb from './lab2rgb.js';
6
+ import rgb2lab from './rgb2lab.js';
7
+ import { getLabWhitePoint, setLabWhitePoint } from './lab-constants.js';
8
+
9
+ Color.prototype.lab = function () {
10
+ return rgb2lab(this._rgb);
11
+ };
12
+
13
+ const lab = (...args) => new Color(...args, 'lab');
14
+ Object.assign(chroma, { lab, getLabWhitePoint, setLabWhitePoint });
15
+
16
+ input.format.lab = lab2rgb;
17
+
18
+ input.autodetect.push({
19
+ p: 2,
20
+ test: (...args) => {
21
+ args = unpack(args, 'lab');
22
+ if (type(args) === 'array' && args.length === 3) {
23
+ return 'lab';
24
+ }
25
+ }
26
+ });
27
+
28
+ export { lab, getLabWhitePoint, setLabWhitePoint };
@@ -0,0 +1,120 @@
1
+ const labConstants = {
2
+ // Corresponds roughly to RGB brighter/darker
3
+ Kn: 18,
4
+
5
+ // D65 standard referent
6
+ labWhitePoint: 'd65',
7
+ Xn: 0.95047,
8
+ Yn: 1,
9
+ Zn: 1.08883,
10
+
11
+ t0: 0.137931034, // 4 / 29
12
+ t1: 0.206896552, // 6 / 29
13
+ t2: 0.12841855, // 3 * t1 * t1
14
+ t3: 0.008856452, // t1 * t1 * t1,
15
+
16
+ kE: 216.0 / 24389.0,
17
+ kKE: 8.0,
18
+ kK: 24389.0 / 27.0,
19
+
20
+ RefWhiteRGB: {
21
+ // sRGB
22
+ X: 0.95047,
23
+ Y: 1,
24
+ Z: 1.08883
25
+ },
26
+
27
+ MtxRGB2XYZ: {
28
+ m00: 0.4124564390896922,
29
+ m01: 0.21267285140562253,
30
+ m02: 0.0193338955823293,
31
+ m10: 0.357576077643909,
32
+ m11: 0.715152155287818,
33
+ m12: 0.11919202588130297,
34
+ m20: 0.18043748326639894,
35
+ m21: 0.07217499330655958,
36
+ m22: 0.9503040785363679
37
+ },
38
+
39
+ MtxXYZ2RGB: {
40
+ m00: 3.2404541621141045,
41
+ m01: -0.9692660305051868,
42
+ m02: 0.055643430959114726,
43
+ m10: -1.5371385127977166,
44
+ m11: 1.8760108454466942,
45
+ m12: -0.2040259135167538,
46
+ m20: -0.498531409556016,
47
+ m21: 0.041556017530349834,
48
+ m22: 1.0572251882231791
49
+ },
50
+
51
+ // used in rgb2xyz
52
+ As: 0.9414285350000001,
53
+ Bs: 1.040417467,
54
+ Cs: 1.089532651,
55
+
56
+ MtxAdaptMa: {
57
+ m00: 0.8951,
58
+ m01: -0.7502,
59
+ m02: 0.0389,
60
+ m10: 0.2664,
61
+ m11: 1.7135,
62
+ m12: -0.0685,
63
+ m20: -0.1614,
64
+ m21: 0.0367,
65
+ m22: 1.0296
66
+ },
67
+
68
+ MtxAdaptMaI: {
69
+ m00: 0.9869929054667123,
70
+ m01: 0.43230526972339456,
71
+ m02: -0.008528664575177328,
72
+ m10: -0.14705425642099013,
73
+ m11: 0.5183602715367776,
74
+ m12: 0.04004282165408487,
75
+ m20: 0.15996265166373125,
76
+ m21: 0.0492912282128556,
77
+ m22: 0.9684866957875502
78
+ }
79
+ };
80
+
81
+ export default labConstants;
82
+
83
+ // taken from https://de.mathworks.com/help/images/ref/whitepoint.html
84
+ const ILLUMINANTS = new Map([
85
+ // ASTM E308-01
86
+ ['a', [1.0985, 0.35585]],
87
+ // Wyszecki & Stiles, p. 769
88
+ ['b', [1.0985, 0.35585]],
89
+ // C ASTM E308-01
90
+ ['c', [0.98074, 1.18232]],
91
+ // D50 (ASTM E308-01)
92
+ ['d50', [0.96422, 0.82521]],
93
+ // D55 (ASTM E308-01)
94
+ ['d55', [0.95682, 0.92149]],
95
+ // D65 (ASTM E308-01)
96
+ ['d65', [0.95047, 1.08883]],
97
+ // E (ASTM E308-01)
98
+ ['e', [1, 1, 1]],
99
+ // F2 (ASTM E308-01)
100
+ ['f2', [0.99186, 0.67393]],
101
+ // F7 (ASTM E308-01)
102
+ ['f7', [0.95041, 1.08747]],
103
+ // F11 (ASTM E308-01)
104
+ ['f11', [1.00962, 0.6435]],
105
+ ['icc', [0.96422, 0.82521]]
106
+ ]);
107
+
108
+ export function setLabWhitePoint(name) {
109
+ const ill = ILLUMINANTS.get(String(name).toLowerCase());
110
+ if (!ill) {
111
+ throw new Error('unknown Lab illuminant ' + name);
112
+ }
113
+ labConstants.labWhitePoint = name;
114
+ labConstants.Xn = ill[0];
115
+ labConstants.Zn = ill[1];
116
+ }
117
+
118
+ export function getLabWhitePoint() {
119
+ return labConstants.labWhitePoint;
120
+ }
@@ -0,0 +1,101 @@
1
+ import LAB_CONSTANTS from './lab-constants.js';
2
+ import { unpack } from '../../utils/index.js';
3
+
4
+ /*
5
+ * L* [0..100]
6
+ * a [-100..100]
7
+ * b [-100..100]
8
+ */
9
+ const lab2rgb = (...args) => {
10
+ args = unpack(args, 'lab');
11
+ const [L, a, b] = args;
12
+ const [x, y, z] = lab2xyz(L, a, b);
13
+ const [r, g, b_] = xyz2rgb(x, y, z);
14
+ return [r, g, b_, args.length > 3 ? args[3] : 1];
15
+ };
16
+
17
+ const lab2xyz = (L, a, b) => {
18
+ const { kE, kK, kKE, Xn, Yn, Zn } = LAB_CONSTANTS;
19
+
20
+ const fy = (L + 16.0) / 116.0;
21
+ const fx = 0.002 * a + fy;
22
+ const fz = fy - 0.005 * b;
23
+
24
+ const fx3 = fx * fx * fx;
25
+ const fz3 = fz * fz * fz;
26
+
27
+ const xr = fx3 > kE ? fx3 : (116.0 * fx - 16.0) / kK;
28
+ const yr = L > kKE ? Math.pow((L + 16.0) / 116.0, 3.0) : L / kK;
29
+ const zr = fz3 > kE ? fz3 : (116.0 * fz - 16.0) / kK;
30
+
31
+ const x = xr * Xn;
32
+ const y = yr * Yn;
33
+ const z = zr * Zn;
34
+
35
+ return [x, y, z];
36
+ };
37
+
38
+ const compand = (linear) => {
39
+ /* sRGB */
40
+ const sign = Math.sign(linear);
41
+ linear = Math.abs(linear);
42
+ return (
43
+ (linear <= 0.0031308
44
+ ? linear * 12.92
45
+ : 1.055 * Math.pow(linear, 1.0 / 2.4) - 0.055) * sign
46
+ );
47
+ };
48
+
49
+ const xyz2rgb = (x, y, z) => {
50
+ const { MtxAdaptMa, MtxAdaptMaI, MtxXYZ2RGB, RefWhiteRGB, Xn, Yn, Zn } =
51
+ LAB_CONSTANTS;
52
+
53
+ const As = Xn * MtxAdaptMa.m00 + Yn * MtxAdaptMa.m10 + Zn * MtxAdaptMa.m20;
54
+ const Bs = Xn * MtxAdaptMa.m01 + Yn * MtxAdaptMa.m11 + Zn * MtxAdaptMa.m21;
55
+ const Cs = Xn * MtxAdaptMa.m02 + Yn * MtxAdaptMa.m12 + Zn * MtxAdaptMa.m22;
56
+
57
+ const Ad =
58
+ RefWhiteRGB.X * MtxAdaptMa.m00 +
59
+ RefWhiteRGB.Y * MtxAdaptMa.m10 +
60
+ RefWhiteRGB.Z * MtxAdaptMa.m20;
61
+ const Bd =
62
+ RefWhiteRGB.X * MtxAdaptMa.m01 +
63
+ RefWhiteRGB.Y * MtxAdaptMa.m11 +
64
+ RefWhiteRGB.Z * MtxAdaptMa.m21;
65
+ const Cd =
66
+ RefWhiteRGB.X * MtxAdaptMa.m02 +
67
+ RefWhiteRGB.Y * MtxAdaptMa.m12 +
68
+ RefWhiteRGB.Z * MtxAdaptMa.m22;
69
+
70
+ const X1 =
71
+ (x * MtxAdaptMa.m00 + y * MtxAdaptMa.m10 + z * MtxAdaptMa.m20) *
72
+ (Ad / As);
73
+ const Y1 =
74
+ (x * MtxAdaptMa.m01 + y * MtxAdaptMa.m11 + z * MtxAdaptMa.m21) *
75
+ (Bd / Bs);
76
+ const Z1 =
77
+ (x * MtxAdaptMa.m02 + y * MtxAdaptMa.m12 + z * MtxAdaptMa.m22) *
78
+ (Cd / Cs);
79
+
80
+ const X2 =
81
+ X1 * MtxAdaptMaI.m00 + Y1 * MtxAdaptMaI.m10 + Z1 * MtxAdaptMaI.m20;
82
+ const Y2 =
83
+ X1 * MtxAdaptMaI.m01 + Y1 * MtxAdaptMaI.m11 + Z1 * MtxAdaptMaI.m21;
84
+ const Z2 =
85
+ X1 * MtxAdaptMaI.m02 + Y1 * MtxAdaptMaI.m12 + Z1 * MtxAdaptMaI.m22;
86
+
87
+ const r = compand(
88
+ X2 * MtxXYZ2RGB.m00 + Y2 * MtxXYZ2RGB.m10 + Z2 * MtxXYZ2RGB.m20
89
+ );
90
+ const g = compand(
91
+ X2 * MtxXYZ2RGB.m01 + Y2 * MtxXYZ2RGB.m11 + Z2 * MtxXYZ2RGB.m21
92
+ );
93
+ const b = compand(
94
+ X2 * MtxXYZ2RGB.m02 + Y2 * MtxXYZ2RGB.m12 + Z2 * MtxXYZ2RGB.m22
95
+ );
96
+
97
+ return [r * 255, g * 255, b * 255];
98
+ };
99
+
100
+ export default lab2rgb;
101
+ export { xyz2rgb };
@@ -0,0 +1,67 @@
1
+ import LAB_CONSTANTS from './lab-constants.js';
2
+ import { unpack } from '../../utils/index.js';
3
+
4
+ const rgb2lab = (...args) => {
5
+ const [r, g, b, ...rest] = unpack(args, 'rgb');
6
+ const [x, y, z] = rgb2xyz(r, g, b);
7
+ const [L, a, b_] = xyz2lab(x, y, z);
8
+ return [L, a, b_, ...(rest.length > 0 && rest[0] < 1 ? [rest[0]] : [])];
9
+ };
10
+
11
+ function xyz2lab(x, y, z) {
12
+ const { Xn, Yn, Zn, kE, kK } = LAB_CONSTANTS;
13
+ const xr = x / Xn;
14
+ const yr = y / Yn;
15
+ const zr = z / Zn;
16
+
17
+ const fx = xr > kE ? Math.pow(xr, 1.0 / 3.0) : (kK * xr + 16.0) / 116.0;
18
+ const fy = yr > kE ? Math.pow(yr, 1.0 / 3.0) : (kK * yr + 16.0) / 116.0;
19
+ const fz = zr > kE ? Math.pow(zr, 1.0 / 3.0) : (kK * zr + 16.0) / 116.0;
20
+
21
+ return [116.0 * fy - 16.0, 500.0 * (fx - fy), 200.0 * (fy - fz)];
22
+ }
23
+
24
+ function gammaAdjustSRGB(companded) {
25
+ const sign = Math.sign(companded);
26
+ companded = Math.abs(companded);
27
+ const linear =
28
+ companded <= 0.04045
29
+ ? companded / 12.92
30
+ : Math.pow((companded + 0.055) / 1.055, 2.4);
31
+ return linear * sign;
32
+ }
33
+
34
+ const rgb2xyz = (r, g, b) => {
35
+ // normalize and gamma adjust
36
+ r = gammaAdjustSRGB(r / 255);
37
+ g = gammaAdjustSRGB(g / 255);
38
+ b = gammaAdjustSRGB(b / 255);
39
+
40
+ const { MtxRGB2XYZ, MtxAdaptMa, MtxAdaptMaI, Xn, Yn, Zn, As, Bs, Cs } =
41
+ LAB_CONSTANTS;
42
+
43
+ let x = r * MtxRGB2XYZ.m00 + g * MtxRGB2XYZ.m10 + b * MtxRGB2XYZ.m20;
44
+ let y = r * MtxRGB2XYZ.m01 + g * MtxRGB2XYZ.m11 + b * MtxRGB2XYZ.m21;
45
+ let z = r * MtxRGB2XYZ.m02 + g * MtxRGB2XYZ.m12 + b * MtxRGB2XYZ.m22;
46
+
47
+ const Ad = Xn * MtxAdaptMa.m00 + Yn * MtxAdaptMa.m10 + Zn * MtxAdaptMa.m20;
48
+ const Bd = Xn * MtxAdaptMa.m01 + Yn * MtxAdaptMa.m11 + Zn * MtxAdaptMa.m21;
49
+ const Cd = Xn * MtxAdaptMa.m02 + Yn * MtxAdaptMa.m12 + Zn * MtxAdaptMa.m22;
50
+
51
+ let X = x * MtxAdaptMa.m00 + y * MtxAdaptMa.m10 + z * MtxAdaptMa.m20;
52
+ let Y = x * MtxAdaptMa.m01 + y * MtxAdaptMa.m11 + z * MtxAdaptMa.m21;
53
+ let Z = x * MtxAdaptMa.m02 + y * MtxAdaptMa.m12 + z * MtxAdaptMa.m22;
54
+
55
+ X *= Ad / As;
56
+ Y *= Bd / Bs;
57
+ Z *= Cd / Cs;
58
+
59
+ x = X * MtxAdaptMaI.m00 + Y * MtxAdaptMaI.m10 + Z * MtxAdaptMaI.m20;
60
+ y = X * MtxAdaptMaI.m01 + Y * MtxAdaptMaI.m11 + Z * MtxAdaptMaI.m21;
61
+ z = X * MtxAdaptMaI.m02 + Y * MtxAdaptMaI.m12 + Z * MtxAdaptMaI.m22;
62
+
63
+ return [x, y, z];
64
+ };
65
+
66
+ export default rgb2lab;
67
+ export { rgb2xyz };
@@ -0,0 +1,9 @@
1
+ import { unpack, reverse3 } from '../../utils/index.js';
2
+ import lch2rgb from './lch2rgb.js';
3
+
4
+ const hcl2rgb = (...args) => {
5
+ const hcl = reverse3(unpack(args, 'hcl'));
6
+ return lch2rgb(...hcl);
7
+ };
8
+
9
+ export default hcl2rgb;
@@ -0,0 +1,35 @@
1
+ import { unpack, type, reverse3 } from '../../utils/index.js';
2
+ import chroma from '../../chroma.js';
3
+ import Color from '../../Color.js';
4
+ import input from '../input.js';
5
+ import lch2rgb from './lch2rgb.js';
6
+ import hcl2rgb from './hcl2rgb.js';
7
+ import rgb2lch from './rgb2lch.js';
8
+
9
+ Color.prototype.lch = function () {
10
+ return rgb2lch(this._rgb);
11
+ };
12
+ Color.prototype.hcl = function () {
13
+ return reverse3(rgb2lch(this._rgb));
14
+ };
15
+
16
+ const lch = (...args) => new Color(...args, 'lch');
17
+ const hcl = (...args) => new Color(...args, 'hcl');
18
+
19
+ Object.assign(chroma, { lch, hcl });
20
+
21
+ input.format.lch = lch2rgb;
22
+ input.format.hcl = hcl2rgb;
23
+ ['lch', 'hcl'].forEach((m) =>
24
+ input.autodetect.push({
25
+ p: 2,
26
+ test: (...args) => {
27
+ args = unpack(args, m);
28
+ if (type(args) === 'array' && args.length === 3) {
29
+ return m;
30
+ }
31
+ }
32
+ })
33
+ );
34
+
35
+ export { lch, hcl };