2016-12-27 36 views
2

我想要在一系列輸入值(比如A和B之間)中進行一般插值並得到一系列輸出值(比如C和D之間)。 有時候我想鉗住這個值(所以B + 10000仍然輸出D),有時我不知道。我該怎麼做?如何將(lerp)範圍輸入線性內插到距離輸出?

例如,給定輸入設備20英里每小時80英里每小時之間的速度,我想調整17和15之間我的地圖的縮放級別:

無須裝夾

 | \ 
    | \ 
17 | \ 
    | \ 
    |  \ 
    |  \ 
    |  \ 
15 |  \ 
    |   \ 
    +----------\- 
     20 80 \ 

帶夾緊

 | 
17 |---- 
    | \ 
    |  \ 
    |  \ 
    |  \ 
15 |  ---- 
    | 
    +------------ 
     20 80  

我發現this utility function,但(一)不支持由本身夾緊,需要第二函數調用,和(b)只支持輸入0和1之間

回答

2

一般要(鬆開)方程爲:

var unclamped = (x-minX) * (maxY-minY)/(maxX-minX) + minY; 

用於夾緊,您可以鉗制輸出你計算後的結果:

x = Math.max(minX, Math.min(maxX, x)) 
var clamped = (x-minX) * (maxY-minY)/(maxX-minX) + minY; 

var clamped = Math.max(minY, Math.min(maxY, unclamped)); 

或者你使用它之前,你可以夾住輸入

如果直線的斜率不會改變,你的夾緊慾望不改,則可以通過提高性能預先計算一次,並生成功能根據您的輸入和需要:

// Generate a lerp function for a specific set of input/output, 
// with or without clamping to the output range. 
function lerp(minX, maxX, minY, maxY, clampFlag) { 
    var slope = (maxY-minY)/(maxX-minX); 
    return clampFlag ? 
    function(x){ return ((x<minX?minX:x>maxX?maxX:x) - minX) * slope + minY } 
    : 
    function(x){ return (x-minX)*slope + minY } 
} 

在行動:

prepPlotter(); // Get ready to draw a pretty graph of the results 
 

 
// Make a simple input/output function 
 
var zoomForSpeed = lerp(20, 80, 17, 15, true); 
 

 
for (var speed=0; speed<=99; speed++) { 
 
    var zoom = zoomForSpeed(speed); // Bam! Lerp'd! 
 
    plot(speed,zoom);    // Proof of the goodness 
 
} 
 

 
// Show the min/max input and output 
 
ctx.fillStyle = 'red'; 
 
plot(20,17,2); 
 
plot(80,15,2); 
 

 
function plot(speed,zoom,scale) { 
 
    ctx.fillRect(speed,zoom,0.5*(scale||1),0.03*(scale||1)); 
 
} 
 

 
function prepPlotter() { 
 
    ctx = document.querySelector('canvas').getContext('2d'); 
 
    ctx.translate(0,875); 
 
    ctx.scale(3,-50); 
 
} 
 

 
function lerp(minX, maxX, minY, maxY, clampFlag) { 
 
    var slope = (maxY-minY)/(maxX-minX); 
 
    return clampFlag ? function(x){ return ((x<minX?minX:x>maxX?maxX:x) - minX) * slope + minY } : function(x){ return (x-minX)*slope + minY } 
 
}
<canvas>Press "Run code snippet" for a graph of zoomForSpeed</canvas>