0

I wanted to let my program know whether a point X is at the right or the left of a line that crosses A and B I found that solution in this forum (How to tell whether a point is to the right or left side of a line) and it was really helpful, but once I changed the angle of the line it just stopped working and started to give me the result of a line that has 0° as heading

I work with Lines that rarely have 0°

I tried also to rotate the point I have using an equation but still giving me the same result I'm trying to achieve the results I want in Unity Engine so I can visualize what I'm doing before actually jumping to the original program

    float Ax = Stop.transform.position.x;
    float Ay = Stop.transform.position.y;

    float Bx = Ref.transform.position.x;
    float By = Ref.transform.position.y;

    float X = Wheel.transform.position.x;
    float Y = Wheel.transform.position.y;

    float x = X * Cos(Gate.transform.rotation.eulerAngles.y) - Y * Sin(Gate.transform.rotation.eulerAngles.y);
    float y = Y * Cos(Gate.transform.rotation.eulerAngles.y) + X * Sin(Gate.transform.rotation.eulerAngles.y);

    float position = System.Math.Sign((Bx - Ax) * (Y - Ay) - (By - Ay) * (X - Ax));

    if (position > 0)
    {
        lg.Log("Left");
    }
    else
    {
        lg.Log("Right");
    }

I expect the program to return right or left whatever the heading of the line is and whatever is the distance between A & B & X but it just gives me results of straight 0° heading line which is weird as the B point is not aligned with the Y axes :|

  • see [Finder what point is to the left of a line/point after spinning it](https://stackoverflow.com/a/27480241/2521214) both solutions are independent on rotation. – Spektre Jul 23 '19 at 07:27

3 Answers3

0

You are calculating orientation of Wheel position (large X/Y) relative to Stop-Ref line. Coordinates of rotated point (small x/y) are ignored.

MBo
  • 77,366
  • 5
  • 53
  • 86
  • i can't understand what you mean the stop and ref are just points that are far from each other (some units) and the wheel is just a point too and the distance between the line and the wheel is not that big – BPW developer Jul 23 '19 at 02:26
  • You calculate `float x = ` but `position` formula uses `X` – MBo Jul 23 '19 at 02:31
  • I didn't notice my mistake, i corrected it but still same result here is the new code but still the same unwanted result :( `float position = System.Math.Sign((Bx - Ax) * (y - Ay) - (By - Ay) * (x - Ax));` – BPW developer Jul 23 '19 at 02:40
  • Substitute variables with specific values and check calculations. For example, Ax=0, Ay=0, Bx = 1, By=0, x = 1 and three values of `y = -1, 0, and 1` should give three values of position - `1, 0 and -1` – MBo Jul 23 '19 at 03:29
0

You can first find out the equation of the line with:

float m = (By - Ay) / (Bx - Ax);
float n = (Ay * Bx + By * Ax) / (Bx - Ax);

The equation of the line is:

y = mx + n

This is simply implementing the line equation from Wikipedia.

Now you can easily find out if a point is above or below the line. Just insert your x coordinate into the line, then you get the y coordinate of the line at that point. Now compare that y value with your y coordinate and you know if it's above or below. Depending on what you define as the direction of the line, you'll now also be able to tell if that's left or right of the line.

An exact vertical line won't work though since its slope would be approaching infinity.

Linus
  • 111
  • 4
  • I find that a clever approach, however, I do have some vertical lines or let's say that their angle is 0.1 or 0.2, will it work in that case if I have some values that are close to zero but not equal to it? – BPW developer Jul 23 '19 at 16:19
  • The only case that it won't work for is when it's exactly 0. Can you show how you implemented it? It should theoretically work in my opinion. – Linus Jul 23 '19 at 17:08
  • even if the line is vertical or not, it gives results of a vertical line `float m = (By - Ay) / (Bx / Ax); float n = (Ay * Bx + By * Ax) / (Bx / Ax); float Ey = m * Y + n; if (Ey > y) { lg.Log("Left"); } else { lg.Log("Right"); } ` – BPW developer Jul 23 '19 at 17:27
  • Damn, I just found an error in my answer. Please try it again with the updated equations for m and n in my original answer. – Linus Jul 23 '19 at 17:30
  • man, i just updated, i put the line visualy at a vertical position n it works, i rotated the line , the program reacts like the line is vertical starting from the A point to somewhere, even if B is not vertical with A :| – BPW developer Jul 23 '19 at 17:35
  • Not sure I know what you mean, are you updating m and n correctly when A or B change position? – Linus Jul 23 '19 at 17:41
  • everything is in an update method that runs every frame – BPW developer Jul 23 '19 at 17:50
  • even if i start the scene with the line rotated – BPW developer Jul 23 '19 at 17:51
0

so I found a solution first of all, it was my mistake from the beginning so after analyzing all of your answers and others from other questions on this website I finally got it First, my mistake is that I was using the Y value of a point in a left-handed 3D space plan wich uses Y as altitude and not as Longitude so I switched to Z and I started to see some results this justifies the fact that the results I always get are vertical based

I think all of your answers may work but I finally used one of mine

so here is my logic

float Ax = Stop.transform.position.x;
    float Ay = Stop.transform.position.z;

    float Bx = Ref.transform.position.x;
    float By = Ref.transform.position.y;

    float X = Wheel.transform.position.x;
    float Y = Wheel.transform.position.z;

    // set the point coordinates in a new virtual plan that has the A point as origin

    float x = X - Ax;
    float y = Y - Ay;

    // set a new B point and ignore the first one
    // it seems not logical at all but in my next program i won't be able to set a virtual point so it is needed

    Bx = 0;
    By = 5;

    //let the program know that Apoint now is the origin
    Ax = 0;
    Ay = 0;

    //get the line heading using euler angles

    float angle = Gate.transform.rotation.eulerAngles.y;
    //small log to check the values
    lg.Log(angle.ToString());

    //rotate the point coordinates arround the orgin (0 ; 0)
    var rotatedX = Cos(angle) * (x - Ax) - Sin(angle) * (y - Ay) + Ax;

    var rotatedY = Sin(angle) * (x - Ax) + Cos(angle) * (y - Ay) + Ay;

    //check the X value instead of the Y value, again my misatake

    if(rotatedX > 0)
    {
        // i created big boxed to view the left/right sign instead of logs just to not get confused :)
        left.SetActive(true);
        right.SetActive(false);
    }
    else
    {
        left.SetActive(false);
        right.SetActive(true);
    }

I'm using unity for tests cus it has a render engine that helps visualize the results before jumping to the actual program thank you all for the help :)