Skip to content

vigneshwaranr/line_intersection.js

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

52 Commits
 
 
 
 
 
 
 
 

Repository files navigation

line_intersection.js

A JavaScript library to find the intersection of two straight lines (useful for charting libraries). Also includes a function that generate trendline from a chart data.

Written originally for highcharts but can work with any charting library as long as they support line data in the format [[x1, y1], [x2, y2], ... ] such as Flot, PlotKit, JS Charts etc. For other libraries, you will need to convert the data to this form and back after getting the intersection data.

Methods

  • getLineIntersectionData(line1_data, line2_data, user_options)

    Given two straight line data each of the form [[x1, y1], [x2, y2], ... [xn, yn]] this method will return an object that contains the intersection points and two "new line data" with the intersection point added. (Does not modify the input data!)

    If your data is not from a straight line but some chart data, use getTrendlineData to generate a straight trendline out of that data using Linear Regression.

  • getTrendlineData(data)

    Given any linear chart data of the form [[x1, y1], [x2, y2], ... [xn, yn]] this method will generate a straight trendline using linear regression.

Usage

getLineIntersectionData(line1_data, line2_data, user_options)

Documentation

/**
 * @param line1_data - Mandatory argument that contains the data of line1 of the form 
 *                      [[x1, y1], [x2, y2], ... [xn, yn]]
 * 
 * @param line2_data - Mandatory argument that contains the data of line2 of the form 
 *                      [[x1, y1], [x2, y2], ... [xn, yn]]
 * 
 * @param user_options - Optional argument that is an object containing custom options that overrides the default
 *                      behavior of the method. Refer the comments for each option in the opt object for the valid
 *                      values for that option.
 *
 * @returns
 * > an object with the following properties
 *     icptX - The intersection point X
 *     icptY - The intersection point Y
 *     line1_data - The new line1 data with intersection point added
 *     line2_data - The new line2 data with intersection point added
 * > or returns undefined
 *     if the lines are parallel,
 *     if any of the first two arguments are not in the form [[x1, y1], [x2, y2], ... [xn, yn]]
 *     if any of the line data has less than 2 points (it's not a line then)
 *     if the user_options argument or any of the options inside it is not in the required format
 *     if any callback set in user_options returns false
 */

Basic example

var line1 = [[0, 1], [2, 1]];
var line2 = [[1, 0], [1, 2]];
var forecast = getLineIntersectionData(line1, line2);
JSON.stringify(forecast)
>> {"icptX": 1, "icptY": 1, "line1_data": [[0,1],[1,1],[2,1]], "line2_data": [[1,0],[1,1],[1,2]]}

Example with chart

jQuery(function () {
    var data1 = [[2, 6], [12, 8]];
    var data2 = [[3, 1], [10, 5]];
    
    var forecast = getLineIntersectionData(data1, data2);
    
    var chart_linear = new Highcharts.Chart({
        chart: {
            renderTo: 'container'
        },
        series: [{
            //getLineIntersectionData() may return undefined if lines can not intersect
            data: forecast && forecast.line1_data || data1
        }, {
            data: forecast && forecast.line2_data || data2
        }]
    });
});

Output:

Basic chart example

getTrendlineData(data)

The code and this example were extracted from highcharts_trendline

Documentation

/** 
 * @param data - Mandatory argument that contains the chart data of the form 
 *                 [[x1, y1], [x2, y2], ... [xn, yn]]
 *
 * @returns an object containing the following properties
 *      data - new array containing the data for the straight trendline
 *      slope - slope of the trendline
 *      intercept - intercept of the trendline
 * 
 */

Example

jQuery(function () {
    // E.g. source data
    var sourceData = [
        [106.4, 271.8], [129.2, 213.4],
        [295.6, 432.3], [154.4, 398.1],
        [129.9, 133.2], [271.5, 432.1],
        [144.0, 134.7], [176.0, 399.2],
        [216.4, 319.2], [194.1, 542.1],
        [435.6, 665.3], [348.5, 435.9]
    ];

    var chart_linear = new Highcharts.Chart({
        chart: {
            renderTo: 'container'
        },
        series: [{
            type: 'scatter',
            data: sourceData
        }, {
            marker: {
                enabled: false
            },
            /* function returns data for trend-line */
            data: getTrendlineData(sourceData).data
        }]
    });
});

Output:

getTrendlineData screenshot 1

Example using both methods

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:

Trend forecast

See live demo for this chart here

##Tests Live unit tests available here

##Credits

About

A JavaScript library to find the intersection of two straight lines (useful for charting libraries)

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 100.0%