0

On a HTML5 canvas object, I have to subtract a distance from a destination point, to give the final destination on the same line.

So, first I have calculated the distance between the source and target points, with the Pythagorean theorem, but my memories of Thales's theorem are too faulty to find the final point (on same line), with the right x and y attributes.

function getDistance (from, to){
    return Math.hypot(to.x - from.x, to.y - from.y);
}
function getFinalTo (from, to, distanceToSubstract){

    //with Pythagore we obtain the distance between the 2 points
    var originalDistance = getDistance(from, to);
    var finalDistance = originalDistance - distanceToSubstract;

    //Now, I was thinking about Thales but all my tries are wrong
    //Here some of ones, I need to get finalTo properties to draw an arrow to a node without

    var finalTo = new Object;
    finalTo.x = ((1 - finalDistance) * from.x) + (finalDistance * to.x);
    finalTo.y = ((1 - finalDistance) * from.y) + (finalDistance * to.y);

    return finalTo;
}

Indeed, the arrowhead be hidden by the round node that can be about 100 pixels of radius, so I try to get the final point.

Thanks a lot. Regards,

2 Answers2

0

You can use simple proportion by distance ratio: (I did not account for round cap)

ratio = finalDistance / originalDistance
finalTo.x = from.x + (to.x - from.x) * ratio;
finalTo.y = from.y + (to.y - from.y) * ratio;

Your approach was attempt to use linear interpolation, but you erroneously mixed distances (in pixels, meters etc) with ratios (dimensionless - is this term right?)

ratio = finalDistance / originalDistance
finalTo.x = ((1 - ratio) * from.x) + (ratio * to.x);
finalTo.y = ((1 - ratio) * from.y) + (ratio * to.y);

Note that both approaches is really the same formula.

MBo
  • 77,366
  • 5
  • 53
  • 86
0

Will depend on the line cap. For "butt" there is no change, for "round" and "square" you the line extends by half the width at each end

The following function shortens the line to fit depending on the line cap.

drawLine(x1,y1,x2,y2){
    // get vector from start to end
    var x = x2-x1;
    var y = y2-y1;
    // get length
    const len = Math.hypot(x,y) * 2;  // *2 because we want half the width
    // normalise vector
    x /= len;
    y /= len;
    if(ctx.lineCap !== "butt"){
        // shorten both ends to fit the length
        const lw = ctx.lineWidth;
        x1 += x * lw;
        y1 += y * lw;
        x2 -= x * lw;
        y2 -= y * lw;
    }
    ctx.beginPath()
    ctx.lineTo(x1,y1);
    ctx.lineTo(x2,y2);
    ctx.stroke();
 }

For miter joins the following answer will help https://stackoverflow.com/a/41184052/3877726

Blindman67
  • 51,134
  • 11
  • 73
  • 136