Search code examples
highchartsregressionseriesinterception

Highcharts - Get crossing point of crossing series


I am currently trying to extract the points of multiple crossings of series (a,b,c,d) of a specific series (x). I can't seem to find any function that can aid me in this task.

My best bet is to measure the distance of every single point in x with every single point in a,b,c,d... and assume when the distance reaches under some threshold, the point must be a crossing point. I think this approach is far too computational heavy and seems "dirty". I believe there must be easier or better ways, even perhaps functions within highcharts own API.

I have searched various sources and sites, but I can't really find any solutions to this. A few people have used regression as a part of their solution. I don't know much about regression, but perhaps regression is the only way?

Also due to the "complex" nature of our series, I also believe regression is rather difficult to utilize.


Solution

  • This is a well studied problem. Before optimizing, though, I'd try the "computational heavy" brute-force approach. Borrowing from the excellent answers here, I've coded up a quick integration with highcharts (fiddle here):

    get_line_intersection = function(p0,p1,p2,p3)
    {        
        var p0_x = p0.x;
        var p0_y = p0.y;
        var p1_x = p1.x;
        var p1_y = p1.y;
        var p2_x = p2.x;
        var p2_y = p2.y;
        var p3_x = p3.x;
        var p3_y = p3.y;  
    
        var s1_x, s1_y, s2_x, s2_y;
        s1_x = p1_x - p0_x;     s1_y = p1_y - p0_y;
        s2_x = p3_x - p2_x;     s2_y = p3_y - p2_y;
    
        var s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
        var t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
    
        if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
        {
            return [p0_x + (t * s1_x),p0_y + (t * s1_y)];
        }
    
        return false;
    }
    
    $(function () {
        $('#container').highcharts({
            series: [{
                name: 'line1',
                data: $.map(new Array(10), function(){return Math.random() * 10;})
            }, {
                name: 'line2',
                data: $.map(new Array(10), function(){return Math.random() * 10;})
            }, {
                name: 'intersect',
                data: [],
                type: 'scatter'
                }
            ]
        }, function(chart){
            var s0 = chart.series[0].points;
            var s1 = chart.series[1].points;
            var s2 = chart.series[2];
            var n0 = s0.length;
            var n1 = s1.length;
            var i,j,isect;
            for (i = 1; i < n0; i++){
               for (j = 1; j < n1; j++){
                   if (isect = get_line_intersection(s0[i-1],s0[i],
                                       s1[j-1],s1[j])){
                       s2.addPoint(isect, false, false);
    
                   }
               } 
            }
            chart.redraw();
        });
    }); 
    

    enter image description here