2

I am trying to extend a line (from to points(X,Y)) to the end of the drawing area. so far i found a couple of instructions on how to calculate the extension end point.

however i don't really get it done it works in one direction and breaks as soon as you reach over the middle point.

see attached code sample (the real product i am working on is in swift, but as it is not a programming language related issue, i ported it to javascript)

on the right side it seems to work, black line is the one the user selects, red one is the extension to the edge of canvas, going to the left side produces garbage.

var canvas = document.getElementById("myCanvas");
var endPoint = {
  x: 200,
  y: 200
};

function draw() {
  //Demo only in final product user also can select the startpoint
  startPoint = {
    x: 150,
    y: 150
  }
  screenMax = {
    x: canvas.height,
    y: canvas.width
  }

  var ctx = canvas.getContext("2d");
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.beginPath();
  ctx.moveTo(startPoint.x, startPoint.y);
  ctx.lineTo(endPoint.x, endPoint.y);
  ctx.strokeStyle = "#000000";
  ctx.stroke();

  //Extend line to end of canvas according to slope
  var slope = 1.0
  var extendedPoint = {
    x: 0,
    y: 0
  }
  if (endPoint.x != startPoint.x) {
    slope = (endPoint.y - startPoint.y) / (endPoint.x - startPoint.x);
    extendedPoint = {
      x: screenMax.x,
      y: slope * (screenMax.x - endPoint.x) + endPoint.y
    }

  } else {
    slope = 0
    extendedPoint.x = endPoint.x;
    extendedPoint.y = screenMax.y;
  }
  console.log(endPoint);

  //Draw the Extension
  ctx.beginPath();
  ctx.moveTo(endPoint.x, endPoint.y);
  ctx.lineTo(extendedPoint.x, extendedPoint.y);
  ctx.strokeStyle = "#FF0000";
  ctx.stroke();




}
//initial draw
draw();

//handle Mouse dOwn
canvas.onmousedown = function(e) {
  handleMouseDown(e);
}



// handle the mousedown event
//Set new endpoint
function handleMouseDown(e) {
  mouseX = parseInt(e.clientX);
  mouseY = parseInt(e.clientY);
  endPoint = {
    x: mouseX,
    y: mouseY
  }
  draw();
}
<!DOCTYPE html>
<html>

<body>

  <canvas id="myCanvas" width="300" height="300" style="border:1px solid #d3d3d3;">
      Your browser does not support the HTML5 canvas tag.</canvas>


</body>

</html>
Helmut Januschka
  • 1,578
  • 3
  • 16
  • 34

2 Answers2

2

This function may help, takes the line x1,y1 to x2,y2 and extends it to the border defined by left,top,right,bottom returning the intercept point as {x:?,y:?}

function toBorder(x1, y1, x2, y2, left, top, right, bottom){
    var dx, dy, py, vx, vy;
    vx = x2 - x1;
    vy = y2 - y1;
    dx = vx < 0 ? left : right;
    dy = py = vy < 0 ? top : bottom;
    if(vx === 0){
        dx = x1;
    }else if(vy === 0){
        dy = y1;
    }else{
        dy = y1 + (vy / vx) * (dx - x1);
        if(dy < top || dy > bottom){
            dx = x1 + (vx / vy) * (py - y1);
            dy = py;
        }
    }
    return {x : dx, y : dy}
}
Blindman67
  • 51,134
  • 11
  • 73
  • 136
  • awesome! works like a charm! many thx, for the reference here is a updated fiddle with your function (just changed the input params) https://jsfiddle.net/tp9e2vaw/3/ – Helmut Januschka Jul 12 '17 at 11:39
  • Nice dude, this works perfect. I dont understand how the code works but it works xD. Thanks. – jojemapa Jun 24 '21 at 07:35
1

Slope approach is not universal - it cannot work with vertical lines (x0=x1).

I'd use parametric representation of ray (line)

 x0 = startPoint.x 
 x1 = endPoint.x
 y0 = startPoint.y 
 y1 = endPoint.y

dx = x1 - x0
dy = y1 - y0
x = x0 + dx * t
y = y0 + dy * t

Now check what border will be intersected first (with smaller t value)

//prerequisites: potential border positions
if dx > 0 then
   bx = width
else
   bx = 0

if dy > 0 then
   by = height
else
   bx = 0

//first check for horizontal/vertical lines 
if dx = 0 then
    return ix = x0,  iy = by

if dy = 0 then
    return iy = y0,  ix = bx


//in general case find parameters of intersection with horizontal and vertical edge
tx = (bx - x0) / dx
ty = (by - y0) / dy

//and get intersection for smaller parameter value
if tx <= ty then
   ix = bx
   iy = y0 + tx * dy
else
   iy = by
   ix = x0 + ty * dx

return ix, iy
MBo
  • 77,366
  • 5
  • 53
  • 86
  • many thx for your answer, my mind is blown. what is `t`? could you adopt your variable's to more readable once, as i seem way to stupid to understand it and adopt my sample above to this :( – Helmut Januschka Jul 12 '17 at 08:54
  • t is parameter varying from 0 to 1 along the start-end of segment (and bigger value outside it) – MBo Jul 12 '17 at 10:20