Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 从一个范围到另一个范围的非线性插值_Javascript - Fatal编程技术网

Javascript 从一个范围到另一个范围的非线性插值

Javascript 从一个范围到另一个范围的非线性插值,javascript,Javascript,我正在努力创建一个函数,将一个范围插值到另一个范围。我已经有了一个有效的线性插值,但是得到更多的“曲线”插值,我被难住了 F.ex。我想以某种方式将范围[0100]插值到[01000],因此接近0的目标值比接近1000的目标值更有可能(反之亦然) 我采用的一种方法是使用对数插值,它有一些恼人的缺点: 我使用了一种粗糙的方法来处理负数(f.ex.[-70,50]),方法是在计算前抵消范围 “斜率”是不可调整的(例如,如果我希望目标值比线性插值更可能或更可能) 函数logPol(值s1、s2、t

我正在努力创建一个函数,将一个范围插值到另一个范围。我已经有了一个有效的线性插值,但是得到更多的“曲线”插值,我被难住了

F.ex。我想以某种方式将范围
[0100]
插值到
[01000]
,因此接近0的目标值比接近1000的目标值更有可能(反之亦然)

我采用的一种方法是使用对数插值,它有一些恼人的缺点:

  • 我使用了一种粗糙的方法来处理负数(f.ex.[-70,50]),方法是在计算前抵消范围
  • “斜率”是不可调整的(例如,如果我希望目标值比线性插值更可能或更可能)
函数logPol(值s1、s2、t1、t2){

var f=(value-s1)/(value-s1)+(s2-value));
var-add=0;

if(t1在阅读了大量不同的方法之后,我最终解决了我的问题,并最终使用Bezier曲线来处理插值。下面是我的结果函数:

    /**
 * Returns a bezier interpolated value, using the given ranges
 * @param {number} value  Value to be interpolated
 * @param {number} s1 Source range start
 * @param {number} s2  Source range end
 * @param {number} t1  Target range start
 * @param {number} t2  Target range end
 * @param {number} [slope]  Weight of the curve (0.5 = linear, 0.1 = weighted near target start, 0.9 = weighted near target end)
 * @returns {number} Interpolated value
 */
var interpolate = function (value, s1, s2, t1, t2, slope) {
    //Default to linear interpolation
    slope = slope || 0.5;

    //If the value is out of the source range, floor to min/max target values
    if(value < Math.min(s1, s2)) {
        return Math.min(s1, s2) === s1 ? t1 : t2;
    }

    if(value > Math.max(s1, s2)) {
        return Math.max(s1, s2) === s1 ? t1 : t2;
    }

    //Reverse the value, to make it correspond to the target range (this is a side-effect of the bezier calculation)
    value = s2-value;

    var C1 = {x: s1, y:t1}; //Start of bezier curve
    var C3 = {x: s2, y:t2}; //End of bezier curve
    var C2 = {              //Control point
        x: C3.x,
        y: C1.y + Math.abs(slope) * (C3.y - C1.y)
    };

    //Find out how far the value is on the curve
    var percent = value / (C3.x-C1.x);

    return C1.y*b1(percent) + C2.y*b2(percent) + C3.y*b3(percent);

    function b1(t) { return t*t }
    function b2(t) { return 2*t*(1 - t)  }
    function b3(t) { return (1 - t)*(1 - t) }
};
/**
*使用给定的范围返回贝塞尔插值
*@param{number}要插值的值
*@param{number}s1源范围开始
*@param{number}s2源范围结束
*@param{number}t1目标范围开始
*@param{number}t2目标范围结束
*@param{number}[slope]曲线的权重(0.5=线性,0.1=加权接近目标起点,0.9=加权接近目标终点)
*@返回{number}插值
*/
var插值=函数(值,s1,s2,t1,t2,斜率){
//默认为线性插值
坡度=坡度| | 0.5;
//如果该值不在源范围内,请将下限值设置为最小/最大目标值
如果(值<数学最小值(s1,s2)){
返回数学最小值(s1,s2)==s1?t1:t2;
}
如果(值>数学最大值(s1、s2)){
返回数学最大值(s1,s2)==s1?t1:t2;
}
//反转该值,使其对应于目标范围(这是贝塞尔计算的副作用)
值=s2值;
var C1={x:s1,y:t1};//贝塞尔曲线的起点
var C3={x:s2,y:t2};//贝塞尔曲线的终点
变量C2={//控制点
x:C3.x,
y:C1.y+Math.abs(斜率)*(C3.y-C1.y)
};
//找出值在曲线上的距离
风险值百分比=价值/(C3.x-C1.x);
返回C1.y*b1(百分比)+C2.y*b2(百分比)+C3.y*b3(百分比);
函数b1(t){返回t*t}
函数b2(t){返回2*t*(1-t)}
函数b3(t){返回(1-t)*(1-t)}
};

在阅读了大量不同的方法之后,我终于解决了我的问题,并最终使用贝塞尔曲线来处理插值。下面是我的结果函数:

    /**
 * Returns a bezier interpolated value, using the given ranges
 * @param {number} value  Value to be interpolated
 * @param {number} s1 Source range start
 * @param {number} s2  Source range end
 * @param {number} t1  Target range start
 * @param {number} t2  Target range end
 * @param {number} [slope]  Weight of the curve (0.5 = linear, 0.1 = weighted near target start, 0.9 = weighted near target end)
 * @returns {number} Interpolated value
 */
var interpolate = function (value, s1, s2, t1, t2, slope) {
    //Default to linear interpolation
    slope = slope || 0.5;

    //If the value is out of the source range, floor to min/max target values
    if(value < Math.min(s1, s2)) {
        return Math.min(s1, s2) === s1 ? t1 : t2;
    }

    if(value > Math.max(s1, s2)) {
        return Math.max(s1, s2) === s1 ? t1 : t2;
    }

    //Reverse the value, to make it correspond to the target range (this is a side-effect of the bezier calculation)
    value = s2-value;

    var C1 = {x: s1, y:t1}; //Start of bezier curve
    var C3 = {x: s2, y:t2}; //End of bezier curve
    var C2 = {              //Control point
        x: C3.x,
        y: C1.y + Math.abs(slope) * (C3.y - C1.y)
    };

    //Find out how far the value is on the curve
    var percent = value / (C3.x-C1.x);

    return C1.y*b1(percent) + C2.y*b2(percent) + C3.y*b3(percent);

    function b1(t) { return t*t }
    function b2(t) { return 2*t*(1 - t)  }
    function b3(t) { return (1 - t)*(1 - t) }
};
/**
*使用给定的范围返回贝塞尔插值
*@param{number}要插值的值
*@param{number}s1源范围开始
*@param{number}s2源范围结束
*@param{number}t1目标范围开始
*@param{number}t2目标范围结束
*@param{number}[slope]曲线的权重(0.5=线性,0.1=加权接近目标起点,0.9=加权接近目标终点)
*@返回{number}插值
*/
var插值=函数(值,s1,s2,t1,t2,斜率){
//默认为线性插值
坡度=坡度| | 0.5;
//如果该值不在源范围内,请将下限值设置为最小/最大目标值
如果(值<数学最小值(s1,s2)){
返回数学最小值(s1,s2)==s1?t1:t2;
}
如果(值>数学最大值(s1、s2)){
返回数学最大值(s1,s2)==s1?t1:t2;
}
//反转该值,使其对应于目标范围(这是贝塞尔计算的副作用)
值=s2值;
var C1={x:s1,y:t1};//贝塞尔曲线的起点
var C3={x:s2,y:t2};//贝塞尔曲线的终点
变量C2={//控制点
x:C3.x,
y:C1.y+Math.abs(斜率)*(C3.y-C1.y)
};
//找出值在曲线上的距离
风险值百分比=价值/(C3.x-C1.x);
返回C1.y*b1(百分比)+C2.y*b2(百分比)+C3.y*b3(百分比);
函数b1(t){返回t*t}
函数b2(t){返回2*t*(1-t)}
函数b3(t){返回(1-t)*(1-t)}
};

您不是在寻找插值,而是在寻找映射?如果您不知道如何计算,那么您就错了,因为它与JavaScript(或任何其他语言)编程完全无关。你应该看看d3,它能做你想要的一切和更多。你不是在找插值,而是在找映射?如果你不知道如何做数学,你就错了,因为它与JavaScript(或任何其他语言)编程完全无关。你应该看看d3,它能做你想要的一切和更多。