JavaScript: Trouble with statement execution

My code is designed to classify a point as 1 if it's above the line y=x, and -1 if it's below the line y=x. I visually represent this line in a canvas by plotting y=x (although due to invertion on the y-axis, it appears like y=-x). For each point, I draw it using green color if it's 1 and red color if it's -1. The expected outcome is a straight line with one side being green and the other side being red. However, when running the code, the result turns out to be unexpected.

This is how I label my points using JavaScript:

function Point(x, y){
    this.x = x;
    this.y = y;
    this.label = 0;
    if(this.y >= this.x){
        this.label = 1;
        console.log(x, y, "UP");
    }else if(this.y < this.x){
        this.label = -1;
        console.log(x, y, "Down");
    }
}

And here is the code for painting the points in the canvas:

function draw(){
  ctx.clearRect(0, 0, can1.width, can1.height);
  ctx.strokeStyle = "yellow";
  ctx.beginPath();
  ctx.moveTo(0, 0);
  ctx.lineTo(can1.width, can1.height);
  ctx.stroke();
  ctx.closePath();
  for(var i = 0; i < points.length; i++){
    var x = points[i].x;
    var y = points[i].y;
    if(points[i].label == 1){
        var color = "Chartreuse";
    }else{
        var color = "red";
    }
    ctx.fillStyle = color;
    ctx.beginPath();
    ctx.arc(x, y, 5, 0, Math.PI * 2, false);
    ctx.fill();
    ctx.closePath();
  }
}

Upon running the code in the browser, the visual output appeared as shown in this image:

The visualization seems to only partially align with expectations. Any assistance or insights would be greatly appreciated!

Edit: Note that the x and y values are randomly assigned in other parts of the code.

Thank you for your help!

Answer №1

Feel free to extend the yellow line to where x === y, instead of just restricting it to the edge of the canvas.

ctx.lineTo(Math.min(can1.width, can1.height), Math.min(can1.width, can1.height));

Answer №2

Allow me to present the same concept in a different light.

ctx.lineTo(can1.width, can1.height);

This particular code will only function properly if the width is equal to the height. The issue lies in plotting points above and below the line y=x. As we know, y=x represents a straight line with an equation of y=mx+c where m equals 1 and c equals 0. In order to plot a line, we need two distinct points. With ctx.lineTo, it always begins at (x,y) = (0,0), which is the top left corner. When the width and height vary, errors will occur. The solution provided employs the Math.min function to ensure the line is plotted with x=y. However, I recommend utilizing the Math.max function instead so that all points fall within the maximum value of both x and y, as long as they are less than the width and height provided.

ctx.lineTo(Math.max(can1.width, can1.height), Math.max(can1.width, can1.height));

For those interested in running the complete code and observing the outcome, please refer to the link below:

https://gist.github.com/harisnp/320462ab20eafd3f36826bee6458ac8c

Take a look at the result using the Math.max approach below:

Answer №3

Utilize the cross product method.

The code snippet provided below determines whether a point lies to the left, right, or on a specific line by using the cross product calculation.

// x1, y1 represent the starting point of the line
// x2, y2 represent the end point of the line
// px1, py1 represent the point to be tested
function testPointToLine(x1, y1, x2, y2, px1, px2){
    return (x2 - x1) * (py1 - y1) - (y2 - y1) * (px1 - x1);
}

If the line always originates from 0,0, you can simplify the function as follows:

function testFromOriginPointToLine(x2, y2, px1, px2){
    return x2 * py1 - y2 * px1;
}

Both functions essentially calculate the cross product between the line vector and the vector from the line's start to the given point.

The Adjustment

To ensure that the canvas orientation does not affect the calculations, modify your point function as shown below:

function Point(x, y){
    this.x = x;
    this.y = y;
    this.label = canvas.width * y - canvas.height * x <= 0 ? 1 : -1;
}

An Illustrative Example

requestAnimationFrame(addPoints);
const ctx = canvas.getContext("2d");

 // Random number generator function
const rand = (min=1,max=min+(min=0))=>Math.random()*(max-min)+min;   

function sizeCanvas() { // Set canvas dimensions
    canvas.width = innerWidth;
    canvas.height = innerHeight;
    ctx.strokeStyle = "white";
    ctx.lineWidth = 3;
    ctx.lineTo(0,0);  
    ctx.lineTo(canvas.width, canvas.height);
    ctx.stroke();
}

function drawPoint(point){
    ctx.fillStyle = point.label > 0 ? "red" : "#0F0";
    ctx.beginPath();
    ctx.arc(point.x, point.y, 4, 0, Math.PI * 2);
    ctx.fill();
}

function Point(x, y) {
    this.x = x;
    this.y = y;
    this.label = canvas.width * y - canvas.height * x <= 0 ? 1 : -1;
}

function addPoints(){
    if (canvas.width !== innerWidth || canvas.height !== innerHeight) { sizeCanvas() }
    drawPoint(new Point(rand(canvas.width), rand(canvas.height)));
    requestAnimationFrame(addPoints);
}
canvas {position: absolute; top: 0px; left: 0px; background: black;}
<canvas id="canvas"></canvas>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Bring in a JavaScript file from Blogger without using a tag

Is there a way to retrieve blogger feeds code without using