1

On the 2D grid, there is a cartesian coordinate C(Cx,Cy) which is a center of square and it has 'b' of radius.

And there are two points P1(x1,y1), P2(x2,y2). When I connect P1 with P2 directly by line, there should be a straight line.

I wanna make the pseudo code that checking whether the straight line between P1 and P2 is on the square area or not.

The argument would be center point and two different points and radius.

Square center: (Cx,Cy)

Two points: P1(x1,y1), P2(x2,y2)

Radius: 'b'

function Straight ((x1,y1),(x2,y2),(Cx,Cy),b)

If the straight line is not on the square area, it should return true, if it is on the square area, it should return false.

enter image description here

Hume
  • 93
  • 7
  • 1
    What you want to know is whether the line segment (P1, P2) intersects any of the line segments (C, C(Cx-b,Cy-b)), (C, C(Cx-b,Cy+b)), (C, C(Cx+b,Cy-b)), (C, C(Cx+b,Cy+b)). You can read about detection of line segment intersection here: https://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect – hager Sep 06 '19 at 06:58

1 Answers1

1

You can convert this problem (by projecting the coordinates) to a square at (0, 0) with "radius" 1.

For determining whether the line segment (p1, p2) crosses the top side of the square, you can first test these conditions:

  • (y2 - 1) * (y2 - 1) > 0. If this is true, it means that the line segment is completely above the top of the square, or completely below it.

  • y1 = y2. If this is true, the line segment is parallel with the square.

In all other cases, the x-coordinate of the intersection point is:

          x = x1 - y1 * (x2 - x1) / (y2 - y1)

If this x is not in the range [-1, 1], the line segment does not intersect the top of the square.

A similar operation can be done for the three other sides.

If any of them gives an intersection coordinate in the range [-1, 1], the function straight should return true, and false otherwise.

Here is an interactive JavaScript implementation with which you can draw a line segment (by "dragging" the mouse) near a square. The square will highlight when the call to straight returns true:

function intersectionWithXaxis(x1, y1, x2, y2) {
    if (y1 * y2 > 0 || y1 === y2) return Infinity; // No intersection
    return x1 - y1 * (x2 - x1) / (y2 - y1); // x-coordinate of intersection
}

function straight(x1, y1, x2, y2, cx, cy, b) {
    // Project the coordinates so the square is at (0, 0) with "radius" 1
    x1 = (x1-cx)/b;
    y1 = (y1-cy)/b;
    x2 = (x2-cx)/b;
    y2 = (y2-cy)/b;
    let z;
    // Get intersections with top, bottom, left and right side of box:
    z = intersectionWithXaxis(x1, y1-1, x2, y2-1);
    if (Math.abs(z) <= 1) return true;
    z = intersectionWithXaxis(x1, y1+1, x2, y2+1);
    if (Math.abs(z) <= 1) return true;
    // We can use the same function for vertical line intersections by swapping x and y
    z = intersectionWithXaxis(y1, x1-1, y2, x2-1);
    if (Math.abs(z) <= 1) return true;
    z = intersectionWithXaxis(y1, x1+1, y2, x2+1);
    if (Math.abs(z) <= 1) return true;
    return false;
}

let cx = 100;
let cy = 60;
let b = 30;
let x1, y1, x2, y2;

// I/O handling

let canvas = document.querySelector("canvas");
let ctx = canvas.getContext("2d");
ctx.fillStyle = "yellow";
let isMouseDown = false;

function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.beginPath();
    ctx.rect(cx-b, cy-b, 2*b, 2*b);
    ctx.stroke();
    
    if (!isMouseDown) return;
    // Call the main function. If true, highlight the square
    if (straight(x1, y1, x2, y2, cx, cy, b)) ctx.fill();
    
    ctx.beginPath();
    ctx.moveTo(x1, y1);
    ctx.lineTo(x2, y2);
    ctx.stroke();
}

canvas.addEventListener("mousedown", function(e) {
    x1 = e.clientX - this.offsetLeft;
    y1 = e.clientY - this.offsetTop;
    isMouseDown = true;
});
canvas.addEventListener("mousemove", function(e) {
    if (!isMouseDown) return;
    x2 = e.clientX - this.offsetLeft;
    y2 = e.clientY - this.offsetTop;
    draw();
});
canvas.addEventListener("mouseup", function(e) {
    isMouseDown = false;
});

draw();
<canvas width="400" height="180"></canvas>
trincot
  • 317,000
  • 35
  • 244
  • 286