Draw line to the canvas edges from origin through click

I think I understand the issue I am having but need some other smart people to help. How do I continue the line that is drawn to the edge of the canvas depending on where I have clicked on the stage. I need to know the point the line should end when it hits the canvas edge.

// Given F, S, W, H or frame, stage, stageW, stageH
let circle = new Circle(20,red).center();

let line;
new Rectangle(W,H,faint).addTo().tap(()=>{
    let x1 = Math.floor(S.mouseX),
        y1 = Math.floor(S.mouseY),
        x2 = circle.x,
        y2 = circle.y,
        m = (y2 - y1) / (x2 - x1),
        b = y2 - (x2*m);
    line = new Line({points: [[x2,y2],[x1,y1]],color:black}).reg(x2,y2).addTo().loc(x2,y2);
    //zog([x1,y1,],[x2,y2],m,b);
    zog(line.x,line.y);
    S.update();
});

There is probably a better way... but here is a way :wink:

1 Like

I am avoiding work lol

const Intersection = {
    ofLines: function (ptA, ptB, ptC, ptD, lineSegmentOnly) {
        if ((ptA.x === ptB.x && ptA.y === ptB.y) || (ptC.x === ptD.x && ptC.y === ptD.y)) {
            return null;
        }

        const denominator = ((ptD.y - ptC.y) * (ptB.x - ptA.x) - (ptD.x - ptC.x) * (ptB.y - ptA.y));

        // Lines are parallel
        if (denominator === 0) {
            return null;
        }

        const ua = ((ptD.x - ptC.x) * (ptA.y - ptC.y) - (ptD.y - ptC.y) * (ptA.x - ptC.x)) / denominator;

        // Check if the intersection point is within the bounds of the line segments if required
        if (lineSegmentOnly) {
            const ub = ((ptB.x - ptA.x) * (ptA.y - ptC.y) - (ptB.y - ptA.y) * (ptA.x - ptC.x)) / denominator;
            if (ua < 0 || ua > 1 || ub < 0 || ub > 1) {
                return null;
            }
        }

        // Return an object with the x and y coordinates of the intersection
        const x = ptA.x + ua * (ptB.x - ptA.x);
        const y = ptA.y + ua * (ptB.y - ptA.y);

        return {x, y};
    },

    ofRectAndExitingRay: function (ptA, ptB, rect) {
        const lineLen = Math.sqrt((ptB.x - ptA.x) ** 2 + (ptB.y - ptA.y) ** 2);
        // 1.42 ensures the minimum value necessary to reach outside the rect (just exceeds hypotenuse)
        const rayLen = Math.max(rect.width, rect.height) * 1.42;
        const extendX = (ptB.x - ptA.x) / lineLen * rayLen;
        const extendY = (ptB.y - ptA.y) / lineLen * rayLen;
        const farPt = {x: ptA.x + extendX, y: ptA.y + extendY};

        // Define the bounding box to test
        const rectCornerPts = [
            {x: 0, y: 0},
            {x: rect.width, y: 0},
            {x: rect.width, y: rect.height},
            {x: 0, y: rect.height}
        ];

        let intersectionPt = null;
        for (let i = 1; i <= rectCornerPts.length && intersectionPt == null; ++i) {
            const edgePtA = rectCornerPts[i - 1];
            const edgePtB = rectCornerPts[i % rectCornerPts.length];
            intersectionPt = this.ofLines(ptA, farPt, edgePtA, edgePtB, true);
        }
        return intersectionPt;
    }
}

const rect = {x: 0, y: 0, width: 100, height: 100};
const ptA = {x: 50, y: 50};
const ptB = {x: 30, y: 57};
const edgePt = Intersection.ofRectAndExitingRay(ptA, ptB, rect);

console.log(edgePt);

The ofLines() function is based on this: https://paulbourke.net/geometry/pointlineplane/javascript.txt
I wrote the ofRectAndExitingRay() function to apply your use case to it

Of course, the other answer would be to use a library such as: math.js | an extensive math library for JavaScript and Node.js

2 Likes

I appreciate you both. I have been thinking about touching Math.js. @josephd me too but this is good exercise for the brain; which means we do better for work? Right!

2 Likes