0

I want to get an arrow from the point with the direction to another point.

Before begin, I'm using this method to get the arrow according to the yaw:

public static String getArrow(double yaw) {
    if (22.50 < yaw && yaw < 67.50) return "⬉";
    else if (67.50 < yaw && yaw < 112.5) return "⬅";
    else if (112.50 < yaw && yaw < 157.5) return "⬋";
    else if (157.50 < yaw && yaw < 202.5) return "⬇";
    else if (202.50 < yaw && yaw < 247.5) return "⬊";
    else if (247.50 < yaw && yaw < 292.5) return "➡";
    else if (292.50 < yaw && yaw < 337.5)
        return "⬈";
    return "⬆";
}

I started by using a method like that:

public static String getArrowTo(Location position, Vector direction, Location watched) {
    Vector a = watched.clone().subtract(position).toVector().normalize();
    double angle = Math.acos(a.dot(direction));
    return getArrow(Math.toDegrees(angle));
}

But each time that the point was on left, the arrow show the forward arrow. So, I made something when it's on left, but it's not fixed even with this trick. Actually I'm using:

public static String getArrowTo(Location position, Vector direction, Location watched) {
    Vector a = watched.clone().subtract(position).toVector().normalize();
    double angle = Math.acos(a.dot(direction));
    if (isLeft(position, position.clone().add(direction), watched.toVector()))
        angle = 360 - angle;
    return getArrow(Math.toDegrees(angle));
}

public static boolean isLeft(Location a, Location b, Vector c) {
    return ((b.getX() - a.getX()) * (c.getZ() - a.getZ()) - (b.getZ() - a.getZ()) * (c.getX() - a.getX())) > 0;
}

The isLeft method comes from here.

PS: the class used are Location and Vector, here showed for spigot 1.19 but I'm using 1.8.8.

The left method seems to don't enough work in my case (I don't know why). By adding angle = angle < 0 ? (360 + angle) : angle it should works better but it never goes below 0. It's always in 0-180 range.

I tested the MBo solution: it find the right, but that's all. The front is something known as back, the right is also on the left etc..

How can I fix it ?

Elikill58
  • 4,050
  • 24
  • 23
  • 45
  • 1
    Have you tried `atan2` function? (returns range -pi..pi, so you need to correct negative values adding 2*pi) – MBo Jun 10 '22 at 09:41
  • @MBo do you mean `atan` ? Because atan2 require 2 arguments – Elikill58 Jun 10 '22 at 10:12
  • No, I mean namely atan2, two arguments are differences by x and y – MBo Jun 10 '22 at 10:13
  • So instead of `acos` I should make mulitplication of x then z to use then in atan2 ? – Elikill58 Jun 10 '22 at 10:16
  • @MBo using `double angle = Math.atan2(a.getX() * direction.getX(), a.getZ() * direction.getZ());` doesn't work properly, it seems to just inverse the issue (the left works, not the right – Elikill58 Jun 10 '22 at 10:21

2 Answers2

2

Try this:

Location playerLocation = player.getLocation();

Vector locVector = location.toVector().subtract(playerLocation.toVector());

String direction = null;

double locAngle = Math.atan2(locVector.getZ(), locVector.getX());
double playerAngle = Math.atan2(playerLocation.getDirection().getZ(), playerLocation.getDirection().getX());

double angle = playerAngle - locAngle;

while (angle > Math.PI) {
    angle = angle - 2 * Math.PI;
}

while (angle < -Math.PI) {
    angle = angle + 2 * Math.PI;
}

if (angle < -2.749 || angle >= 2.749) { // -7/8 pi
    direction = "⬇";
} else if (angle < -1.963) { // -5/8 pi
    direction = "⬊";
} else if (angle < -1.178) { // -3/8 pi
    direction = "➡";
} else if (angle < -0.393) { // -1/8 pi
    direction = "⬈";
} else if (angle < 0.393) { // 1/8 pi
    direction = "⬆";
} else if (angle < 1.178) { // 3/8 pi
    direction = "⬉";
} else if (angle < 1.963) { // 5/8 p
    direction = "⬅";
} else if (angle < 2.749) { // 7/8 pi
    direction = "⬋";
}
Funzter
  • 86
  • 5
0

For two point a and b you can find direction angle a->b as

double angle = Math.atan2(b.getZ()-a.getZ(), b.getX()-a.getX());
if (angle<0)
   angle += 2*Math.Pi;

result is in radians in range -Pi..Pi, so you can adapt result to 0..2*Pi range

Elikill58
  • 4,050
  • 24
  • 23
  • 45
MBo
  • 77,366
  • 5
  • 53
  • 86
  • @Elikill58 Is this what you want? (I'm tangled a bit with your three Location parameters, so gave the simplest variant for two points) – MBo Jun 10 '22 at 12:08
  • I'm actually checking. And it's clearly better (thanks) just now the left is actually at the oppose, like everytime I pass the left, instead of showing forward, it show backward (right: 0.01, left: 179.9) – Elikill58 Jun 10 '22 at 12:13