Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/380.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_Math_Trigonometry_Intervals - Fatal编程技术网

Javascript 计算不在一组范围之间的最小值

Javascript 计算不在一组范围之间的最小值,javascript,math,trigonometry,intervals,Javascript,Math,Trigonometry,Intervals,给定一组圆(x、y、r值),我想放置一个新点,使其具有固定/已知的y坐标(显示为水平线),并且尽可能靠近中心,但不在任何现有圆内。在示例图像中,红色的点就是结果 圆具有已知半径和Y轴属性,因此很容易计算它们在已知Y值处与水平线相交的点。效率很重要,我不想尝试一堆X坐标,并针对圆圈数组中的每个项目对它们进行测试。有没有办法从数学上计算出这个最优的X坐标?非常感谢您的帮助。顺便说一下,我正在使用Raphael.js库用javascript编写它(因为它是唯一一个支持IE8的库),但这更像是一个逻辑问

给定一组圆(x、y、r值),我想放置一个新点,使其具有固定/已知的y坐标(显示为水平线),并且尽可能靠近中心,但不在任何现有圆内。在示例图像中,红色的点就是结果

圆具有已知半径和Y轴属性,因此很容易计算它们在已知Y值处与水平线相交的点。效率很重要,我不想尝试一堆X坐标,并针对圆圈数组中的每个项目对它们进行测试。有没有办法从数学上计算出这个最优的X坐标?非常感谢您的帮助。顺便说一下,我正在使用Raphael.js库用javascript编写它(因为它是唯一一个支持IE8的库),但这更像是一个逻辑问题,所以语言并不重要。

我将按如下方式处理您的问题:

  • 将一组间隔S(按间隔的X坐标排序)初始化为空集
  • 对于每个圆c,计算c与X轴的交点Ic。如果c不相交,则转到下一个圆。否则,测试Ic是否与s中的任何间隔重叠(这很快,因为s已排序);如果是这样,从S中删除所有相交间隔,将Ic和所有删除的间隔折叠为新间隔I'c,并将I'c添加到S。如果没有交点,则将Ic添加到S
  • 检查S中的任何间隔是否包括中心(同样,快,因为S已排序)。如果是,请选择距离中心最近的间隔端点;如果不是,请选择中心作为最近点
  • 创建intersect_segments数组(在x=0 y=0时进行规格化)

  • 按上限对相交线段进行排序,并删除上限为0的线段

  • 初始化点2=0和段=0

  • 点2位于相交段内时循环[段]

    7.1。按段下限递减点2

    7.2。减量段

  • 该点是p1和p2的最小绝对值


  • 基本上,圆的方程是(x-cx)2+(y-cy)2=r2。因此,通过用0替换y,可以轻松找到圆和X轴之间的交点。在这之后,你就有了一个简单的解决方法:x2-2cxx+cx2+cy2-r2=0。对于it,您有3种可能的结果:

    • 无交叉-行列式将是无理数(JavaScript中为NaN),忽略此结果
    • 一个交点-两个解决方案匹配,使用[值,值]
    • 两个交点-两种解决方案不同,请使用[value1,value2]
    对新计算的交叉点间隔进行排序,然后在可能的情况下尝试合并它们。但是请记住,在每种程序语言中都有近似值,因此需要为点近似值定义增量值,并在合并区间时将其考虑在内

    合并间隔时,可以通过在每个间隔的开始/结束处减去/添加相同的增量值来生成x坐标。最后,从各点来看,最接近零的一点就是你的答案

    下面是一个O(n logn)复杂度的示例,它更倾向于可读性。我使用了1*10-10表示增量:

    var circles = [
        {x:0, y:0, r:1},
        {x:2.5, y:0, r:1},
        {x:-1, y:0.5, r:1},
        {x:2, y:-0.5, r:1},
        {x:-2, y:0, r:1},
        {x:10, y:10, r:1}
    ];
    
    console.log(getClosestPoint(circles, 1e-10));
    
    
    
    function getClosestPoint(circles, delta)
    {
        var intervals = [],
            len = circles.length, 
            i, result;
        for (i = 0; i < len; i++)
        {
            result = getXIntersection(circles[i])
            if (result)
            {
                intervals.push(result);
            }
        }
    
        intervals = intervals.sort(function(a, b){
            return a.from - b.from;
        });
        if (intervals.length <= 0) return 0;
        intervals = mergeIntervals(intervals, delta);
    
        var points = getClosestPoints(intervals, delta);
        points = points.sort(function(a, b){
            return Math.abs(a) - Math.abs(b);
        });
        return points[0];
    }
    
    function getXIntersection(circle)
    {
        var d = Math.sqrt(circle.r * circle.r - circle.y * circle.y);
        return isNaN(d) ? null : {from: circle.x - d, to: circle.x + d};
    }
    
    function mergeIntervals(intervals, delta)
    {
        var curr = intervals[0],
            result = [],
            len = intervals.length, i;
        for (i = 1 ; i < len ; i++)
        {
            if (intervals[i].from <= curr.to + delta)
            {
                curr.to = Math.max(curr.to, intervals[i].to);
            } else {
                result.push(curr);
                curr = intervals[i];
            }
        }
        result.push(curr);
        return result;
    }
    
    function getClosestPoints(intervals, delta)
    {
        var result = [], 
            len = intervals.length, i;
        for (i = 0 ; i < len ; i++)
        {
            result.push( intervals[i].from - delta );
            result.push( intervals[i].to + delta );
        }
        return result;
    }
    
    var圆=[
    {x:0,y:0,r:1},
    {x:2.5,y:0,r:1},
    {x:-1,y:0.5,r:1},
    {x:2,y:-0.5,r:1},
    {x:-2,y:0,r:1},
    {x:10,y:10,r:1}
    ];
    console.log(getClosestPoint(圆圈,1e-10));
    函数GetClosesPoint(圆、三角形)
    {
    var区间=[],
    len=圆。长度,
    i、 结果;
    对于(i=0;i如果(左图中的interval.length,为什么红点不在第四个圆的两个交点之一(从左边算起)?在我看来,这些点比指示点更靠近右圆的中心。或者“中心”是指其他东西吗?如果是,什么?对不起-我指的是图表中的垂直线(为了简单起见,将其视为X=0)你说的“尝试一堆X坐标”是什么意思?您只需尝试交叉点。+1用于折叠间隔,这似乎是OP没有想到的。顺便说一句,您可以在计算所有交叉点的过程中检查任何间隔是否包括中心,甚至在对它们进行排序之前。@Bergi-关于边走边跟踪哪个间隔(如果有的话)的极好观点包含中心。由于合并,最多只能有一个这样的间隔。谢谢Ted,这看起来很有希望&明天将在JS中尝试。请原谅我的无知,但当您提到“一组间隔”时,您是指一个Xstart和Xend值数组(即沿x轴的范围)吗?通过“折叠Ic…”你的意思是,例如,如果一个是1delta
    是否合适(实际上,扩大间隔)也不清楚