Search code examples
javascripthighchartslinestrendline

How to predict where two lines will join in Highcharts?


I have the following chart where I have a 'Scope' line and 'Total Effort Done' line and dotted trendlines for each of them. (Since Highcharts does not have support for trendlines, I am just connecting the first and last points of the data using dotted line.) I am using this plugin for the trendlines.

The objective is to extend the dotted trend lines and find the date (x-Axis value) at which these two lines will meet at the right side (if it's possible and not too far away). How can I do that?

enter image description here

Code: http://jsfiddle.net/AjJZD/6/

$(function () {
    var data1 = [
        [Date.UTC(2013, 4, 28), 40],
        [Date.UTC(2013, 5, 26), 40],
        [Date.UTC(2013, 5, 29), 48],
        [Date.UTC(2013, 7, 21), 48]
    ];
    var data2 = [
        [Date.UTC(2013, 4, 28), 0],
        [Date.UTC(2013, 5, 10), 20],
        [Date.UTC(2013, 5, 19), 22],
        [Date.UTC(2013, 5, 20), 24],
        [Date.UTC(2013, 5, 30), 26],
        [Date.UTC(2013, 6, 1), 28],
        [Date.UTC(2013, 7, 21), 30]
    ];
    var chart_linear = new Highcharts.Chart({
        chart: {
            renderTo: 'container'
        },
        colors: ['#912120', '#C00402', '#115DA9', '#115DA9'],
        xAxis: {
            type: 'datetime',
            gridLineWidth: 1,
            gridLineDashStyle: 'shortdot'
        },
        yAxis: {
            min: 0,
            gridLineDashStyle: 'shortdot'
        },
        plotOptions: {
            series: {
                marker: {
                    symbol: 'circle'
                }
            }
        },
        series: [{
            name: 'Scope',
            data: data1
        }, {
            name: 'Scope Change Trend',
            type: 'line',
            marker: {
                enabled: false
            },
            dashStyle: 'longDash',
            data: (function () {
                return fitData(data1).data;
            })()
        }, {
            name: 'Total Effort Done',
            data: data2

        }, {
            name: 'Velocity',
            type: 'line',
            marker: {
                enabled: false
            },
            dashStyle: 'longDash',
            data: (function () {
                return fitData(data2).data;
            })()
        }]
    });
});

Solution

  • Thanks to the other two answers (especially John Kiernander's), I wrote my own library called 'line_intersection.js' that provides a function to find the intersection of two straight lines and also provides a function for generating trendlines out of a chart data.

    With that library's getTrendlineData and getLineIntersectionData functions, you can do the following

    Code:

    jQuery(function () {
    var data1 = [
        [Date.UTC(2013, 0, 1), 50],
        [Date.UTC(2013, 0, 2), 58],
        [Date.UTC(2013, 0, 3), 58],
        [Date.UTC(2013, 0, 4), 58]
    ];
    var data2 = [
        [Date.UTC(2013, 0, 1), 0],
        [Date.UTC(2013, 0, 2), 12],
        [Date.UTC(2013, 0, 3), 18],
        [Date.UTC(2013, 0, 4), 22]
    ];
    var data1_t = getTrendlineData(data1).data;
    var data2_t = getTrendlineData(data2).data;
    var options = {
        icptPoint: {
            //name: 'Possible release date',
            marker: {
                enabled: true,
                fillColor: '#003300',
                lineColor: '#003300'
            }
        },
        validateIntersection: function(icptX, icptY) {
            // Don't connect the lines if the intersection point is
            // to the left of the chart
            if (icptX < data1_t[0][0] || icptX < data2_t[0][0]) {
                return false;
            }
        }
    };
    var forecast = getLineIntersectionData(data1_t, data2_t, options);
    
    var chart_linear = new Highcharts.Chart({
        chart: {
            renderTo: 'container'
        },
        colors: ['#990000', '#4679BD', '#990000', '#4679BD'],
        xAxis: {
            type: 'datetime',
            gridLineWidth: 1,
            gridLineDashStyle: 'shortdot'
        },
        yAxis: {
            min: 0,
            gridLineDashStyle: 'shortdot'
        },
        title: {
            text: 'Estimating release date'
        },
        series: [{
            name: 'Total issues',
            data: data1
        }, {
            name: 'Closed issues',
            data: data2
        }, {
            name: 'Total issues trend',
            //getLineIntersectionData() may return undefined if lines can not intersect
            data: forecast && forecast.line1_data || data1_t,
            marker: {
                enabled: false
            },
            dashStyle: 'longDash'
        }, {
            name: 'Closed issues trend',
            data: forecast && forecast.line2_data || data2_t,
            marker: {
                enabled: false
            },
            dashStyle: 'longDash',
        }]
    });
    

    Output:

    enter image description here

    Live demo: http://vigneshwaranr.github.io/line_intersection.js/demo.html

    Thanks a lot John Kiernander for the example that provided the groundwork for the library!