I am writing a browser application which attempts to discover points of interest in an image.
Once I have computed these points I draw a line between them.
My application needs to extrapolate these lines to the edges of my canvas.
Does anyone have any experience with linear graph calculation in javascript?
I have knocked up a demonstration
(function(){
function drawLine(points){
context.beginPath();
points.forEach(function(point){
context.lineTo(point.x, point.y);
});
context.stroke();
}
var canvas = document.createElement('canvas');
canvas.setAttribute('width', 500);
canvas.setAttribute('height', 300);
document.body.appendChild(canvas);
context = canvas.getContext("2d");
// top
drawLine([{x: 100, y: 40}, {x: 400, y: 10}]);
// bottom
drawLine([{x: 50, y: 220}, {x: 300, y: 290}]);
// left
drawLine([{x: 40, y: 20}, {x: 80, y: 260}]);
// right
drawLine([{x: 490, y: 60}, {x: 440, y: 290}]);
})();
https://jsfiddle.net/y87a0dec/
Many thanks.
The line segment between p = (p.x, p.y)
and q = (q.x, q.y)
can be extended to the line y - p.y = a * (x - p.x)
, where a
is the slope (p.y - q.y) / (p.x - q.x)
. (If p.x = q.x
, this is invalid, but this is a special case we can handle separately.)
By solving for y
and for x
, we get the equivalent formulations: y = a * (x - p.x) + p.y
and x = (y - p.y) / a + p.x
. Inserting our canvas edges into these equations gives us the points where the extended line intersects the canvas.
With a suitable case analysis, we can determine which two of the four canvas edges the extended line intersects. Here is an implementation for the general case of the line segment between p
and q
extended into the canvas [x0, x1]
× [y0, y1]
:
function extend(p, q, x0, x1, y0, y1) {
var dx = q.x - p.x;
var dy = q.y - p.y;
if (dx === 0) return [{x: p.x, y: y0}, {x: p.x, y: y1}];
var slope = dy / dx;
var y_at_x0 = slope * (x0 - p.x) + p.y;
var y_at_x1 = slope * (x1 - p.x) + p.y;
var x_at_y0 = (y0 - p.y) / slope + p.x;
var x_at_y1 = (y1 - p.y) / slope + p.x;
var r, s;
if (y_at_x0 < y0) r = {x: x_at_y0, y: y0};
else if (y_at_x0 <= y1) r = {x: x0, y: y_at_x0};
else r = {x: x_at_y1, y: y1};
if (y_at_x1 < y0) s = {x: x_at_y0, y: y0};
else if (y_at_x1 <= y1) s = {x: x1, y: y_at_x1};
else s = {x: x_at_y1, y: y1};
return [r, s];
}
In the following jsfiddle, drawExtended
passes the result from extend
into your drawLine
. The top and left segments have been extended into the canvas edges:
https://jsfiddle.net/y87a0dec/1/
©2020 All rights reserved.