浏览代码

Add mean distance metric

Kirk Trombley 3 年之前
父节点
当前提交
a1c46f51ed
共有 2 个文件被更改,包括 18 次插入5 次删除
  1. 1 0
      nearest.html
  2. 17 5
      nearest.js

+ 1 - 0
nearest.html

@@ -30,6 +30,7 @@
                     <select type="checkbox" onchange="onMetricChanged()" id="metric">
                         <option selected>RMS/Std Dev</option>
                         <option>Mean Angle</option>
+                        <option>Mean Distance</option>
                         <option>Hue Angle</option>
                         <option>Custom Metric</option>
                     </select>

+ 17 - 5
nearest.js

@@ -27,7 +27,10 @@ const showCustomControls = () => getHideableControlNodes()
 
 // Vector Math
 const vectorDot = (u, v) => u.map((x, i) => x * v[i]).reduce((x, y) => x + y);
-const vectorMag = v => Math.sqrt(vectorDot(v, v));
+const vectorSqMag = v => vectorDot(v, v);
+const vectorMag = v => Math.sqrt(vectorSqMag(v));
+const vectorSqDist = (u, v) => vectorSqMag(u.map((x, i) => x - v[i]));
+const vectorDist = (u, v) => Math.sqrt(vectorSqDist(u, v));
 const vectorNorm = v => { const n = vectorMag(v); return [ n, v.map(c => c / n) ]; };
 
 // Angle Math
@@ -105,6 +108,10 @@ const scoringMetrics = [
     -vectorDot(yJABHat, state.targetColor.qJABHat),
     -vectorDot(yRGBHat, state.targetColor.qRGBHat),
   ],
+  ({ yJAB, yRGB }) => [
+    vectorSqDist(state.targetColor.qJAB, yJAB),
+    vectorSqDist(state.targetColor.qRGB, yRGB),
+  ],
   ({ yHueAngleJAB, yHueAngleRGB }) => [
     angleDiff(state.targetColor.qHueAngleJAB, yHueAngleJAB),
     angleDiff(state.targetColor.qHueAngleRGB, yHueAngleRGB),
@@ -122,7 +129,7 @@ const scoringMetrics = [
 ];
 
 const calcDisplayMetrics = ({
-  xJAB, xRGB, yJABHat, yJABNorm, yRGBHat, yRGBNorm, yHueAngleJAB, yHueAngleRGB,
+  xJAB, xRGB, yJAB, yRGB, yJABHat, yJABNorm, yRGBHat, yRGBNorm, yHueAngleJAB, yHueAngleRGB,
 }) => {
   // TODO - case on state.metric to avoid recalculation of subterms?
 
@@ -137,6 +144,8 @@ const calcDisplayMetrics = ({
     stdDevJAB: Math.sqrt(xJAB - 2 * yTermJAB + state.targetColor.qJABNormSq),
     angleJAB: rad2deg * Math.acos(cosAngleJAB),
     angleRGB: rad2deg * Math.acos(cosAngleRGB),
+    meanDistJAB: vectorDist(state.targetColor.qJAB, yJAB),
+    meanDistRGB: vectorDist(state.targetColor.qRGB, yRGB),
     hueAngleJAB: angleDiff(state.targetColor.qHueAngleJAB, yHueAngleJAB),
     hueAngleRGB: angleDiff(state.targetColor.qHueAngleRGB, yHueAngleRGB),
   };
@@ -157,12 +166,14 @@ const resultDefinition = TeXZilla.toMathML(String.raw`
   \left(
     \text{RMS}_P\left(q\right), 
     \angle \left(\vec{q}, \vec{Y}\left(P\right)\right), 
+    \left|\left| \vec{q} - \vec{Y}\left(P\right) \right|\right|,
     \Delta{H}
   \right)
 `);
 const metricText = [
   String.raw`\text{RMS}_{P}\left(q\right) ~ \arg\min_{P}\left[X\left(P\right) - 2\vec{q}\cdot \vec{Y}\left(P\right)\right]`,
   String.raw`\angle \left(\vec{q}, \vec{Y}\left(P\right)\right) ~ \arg\max_{P}\left[\cos\left(\angle \left(\vec{q}, \vec{Y}\left(P\right)\right)\right)\right]`,
+  String.raw`\left|\left| \vec{q} - \vec{Y}\left(P\right) \right|\right| ~ \arg\min_{P}\left[\left|\left| \vec{q} - \vec{Y}\left(P\right) \right|\right|^2\right]`,
   String.raw`\Delta{H} = \angle \left(\vec{q}_{\perp}, \vec{Y}_{\perp}\left(P\right) \right), \vec{v}_{\perp} = \text{oproj}_{\left\{\vec{J}, \vec{L}\right\}}{\vec{v}}`,
 ].map(s => TeXZilla.toMathML(s));
 
@@ -225,6 +236,7 @@ const renderPokemon = (data, classes = {}) => {
   const {
     stdDevJAB = 0, stdDevRGB = 0,
     angleJAB = 0, angleRGB = 0,
+    meanDistJAB = 0, meanDistRGB,
     hueAngleJAB = 0, hueAngleRGB = 0,
   } = displayMetrics;
 
@@ -248,10 +260,10 @@ const renderPokemon = (data, classes = {}) => {
         </div>
         <div class="pokemon_tile-score_column ${resultsClass}">
           <span class="pokemon_tile-no_flex ${jabClass}">
-            (${stdDevJAB.toFixed(2)}, ${angleJAB.toFixed(2)}&deg;, ${hueAngleJAB.toFixed(2)}&deg;)
+            (${stdDevJAB.toFixed(2)}, ${angleJAB.toFixed(2)}&deg;, ${meanDistJAB.toFixed(2)}, ${hueAngleJAB.toFixed(2)}&deg;)
           </span>
           <span class="pokemon_tile-no_flex ${rgbClass}">
-            (${stdDevRGB.toFixed(2)}, ${angleRGB.toFixed(2)}&deg;, ${hueAngleRGB.toFixed(2)}&deg;)
+            (${stdDevRGB.toFixed(2)}, ${angleRGB.toFixed(2)}&deg;, ${meanDistRGB.toFixed(2)}, ${hueAngleRGB.toFixed(2)}&deg;)
           </span>
         </div>
         <div class="pokemon_tile-hex_column">
@@ -358,7 +370,7 @@ const onMetricChanged = skipScore => {
     return;
   }
   state.metric = metric;
-  if (state.metric === 3) { // Custom
+  if (state.metric === 4) { // Custom
     showCustomControls();
     onCustomControlsChanged(skipScore); // triggers rescore
   } else {