geforkt von Mirrors/Paper
Add Location.setDirection(Vector). Adds BUKKIT-4862
This commit adds an additional method to Location to set the direction of facing. Included are a set of unit tests that ensure the consistency of getDirection and setDirection using a set of cardinal directions and arbituary data points. Javadocs were also added to pitch and yaw methods that explain the unit and points of origin. By: Wesley Wolfe <weswolf@aol.com>
Dieser Commit ist enthalten in:
Ursprung
6f78bf64a6
Commit
800679913f
@ -167,45 +167,79 @@ public class Location implements Cloneable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the yaw of this location
|
* Sets the yaw of this location, measured in degrees.
|
||||||
|
* <ul>
|
||||||
|
* <li>A yaw of 0 or 360 represents the positive z direction.
|
||||||
|
* <li>A yaw of 180 represents the negative z direction.
|
||||||
|
* <li>A yaw of 90 represents the negative x direction.
|
||||||
|
* <li>A yaw of 270 represents the positive x direction.
|
||||||
|
* </ul>
|
||||||
|
* Increasing yaw values are the equivalent of turning to your
|
||||||
|
* right-facing, increasing the scale of the next respective axis, and
|
||||||
|
* decreasing the scale of the previous axis.
|
||||||
*
|
*
|
||||||
* @param yaw New yaw
|
* @param yaw new rotation's yaw
|
||||||
*/
|
*/
|
||||||
public void setYaw(float yaw) {
|
public void setYaw(float yaw) {
|
||||||
this.yaw = yaw;
|
this.yaw = yaw;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the yaw of this location
|
* Gets the yaw of this location, measured in degrees.
|
||||||
|
* <ul>
|
||||||
|
* <li>A yaw of 0 or 360 represents the positive z direction.
|
||||||
|
* <li>A yaw of 180 represents the negative z direction.
|
||||||
|
* <li>A yaw of 90 represents the negative x direction.
|
||||||
|
* <li>A yaw of 270 represents the positive x direction.
|
||||||
|
* </ul>
|
||||||
|
* Increasing yaw values are the equivalent of turning to your
|
||||||
|
* right-facing, increasing the scale of the next respective axis, and
|
||||||
|
* decreasing the scale of the previous axis.
|
||||||
*
|
*
|
||||||
* @return Yaw
|
* @return the rotation's yaw
|
||||||
*/
|
*/
|
||||||
public float getYaw() {
|
public float getYaw() {
|
||||||
return yaw;
|
return yaw;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the pitch of this location
|
* Sets the pitch of this location, measured in degrees.
|
||||||
|
* <ul>
|
||||||
|
* <li>A pitch of 0 represents level forward facing.
|
||||||
|
* <li>A pitch of 90 represents downward facing, or negative y
|
||||||
|
* direction.
|
||||||
|
* <li>A pitch of -90 represents upward facing, or positive y direction.
|
||||||
|
* <ul>
|
||||||
|
* Increasing pitch values the equivalent of looking down.
|
||||||
*
|
*
|
||||||
* @param pitch New pitch
|
* @param pitch new incline's pitch
|
||||||
*/
|
*/
|
||||||
public void setPitch(float pitch) {
|
public void setPitch(float pitch) {
|
||||||
this.pitch = pitch;
|
this.pitch = pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the pitch of this location
|
* Sets the pitch of this location, measured in degrees.
|
||||||
|
* <ul>
|
||||||
|
* <li>A pitch of 0 represents level forward facing.
|
||||||
|
* <li>A pitch of 90 represents downward facing, or negative y
|
||||||
|
* direction.
|
||||||
|
* <li>A pitch of -90 represents upward facing, or positive y direction.
|
||||||
|
* <ul>
|
||||||
|
* Increasing pitch values the equivalent of looking down.
|
||||||
*
|
*
|
||||||
* @return Pitch
|
* @return the incline's pitch
|
||||||
*/
|
*/
|
||||||
public float getPitch() {
|
public float getPitch() {
|
||||||
return pitch;
|
return pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a Vector pointing in the direction that this Location is facing
|
* Gets a unit-vector pointing in the direction that this Location is
|
||||||
|
* facing.
|
||||||
*
|
*
|
||||||
* @return Vector
|
* @return a vector pointing the direction of this location's {@link
|
||||||
|
* #getPitch() pitch} and {@link #getYaw() yaw}
|
||||||
*/
|
*/
|
||||||
public Vector getDirection() {
|
public Vector getDirection() {
|
||||||
Vector vector = new Vector();
|
Vector vector = new Vector();
|
||||||
@ -215,14 +249,47 @@ public class Location implements Cloneable {
|
|||||||
|
|
||||||
vector.setY(-Math.sin(Math.toRadians(rotY)));
|
vector.setY(-Math.sin(Math.toRadians(rotY)));
|
||||||
|
|
||||||
double h = Math.cos(Math.toRadians(rotY));
|
double xz = Math.cos(Math.toRadians(rotY));
|
||||||
|
|
||||||
vector.setX(-h * Math.sin(Math.toRadians(rotX)));
|
vector.setX(-xz * Math.sin(Math.toRadians(rotX)));
|
||||||
vector.setZ(h * Math.cos(Math.toRadians(rotX)));
|
vector.setZ(xz * Math.cos(Math.toRadians(rotX)));
|
||||||
|
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link #getYaw() yaw} and {@link #getPitch() pitch} to point
|
||||||
|
* in the direction of the vector.
|
||||||
|
*/
|
||||||
|
public Location setDirection(Vector vector) {
|
||||||
|
/*
|
||||||
|
* Sin = Opp / Hyp
|
||||||
|
* Cos = Adj / Hyp
|
||||||
|
* Tan = Opp / Adj
|
||||||
|
*
|
||||||
|
* x = -Opp
|
||||||
|
* z = Adj
|
||||||
|
*/
|
||||||
|
final double _2PI = 2 * Math.PI;
|
||||||
|
final double x = vector.getX();
|
||||||
|
final double z = vector.getZ();
|
||||||
|
|
||||||
|
if (x == 0 && z == 0) {
|
||||||
|
pitch = vector.getY() > 0 ? -90 : 90;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
double theta = Math.atan2(-x, z);
|
||||||
|
yaw = (float) Math.toDegrees((theta + _2PI) % _2PI);
|
||||||
|
|
||||||
|
double x2 = NumberConversions.square(x);
|
||||||
|
double z2 = NumberConversions.square(z);
|
||||||
|
double xz = Math.sqrt(x2 + z2);
|
||||||
|
pitch = (float) Math.toDegrees(Math.atan(-vector.getY() / xz));
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the location by another.
|
* Adds the location by another.
|
||||||
*
|
*
|
||||||
|
196
paper-api/src/test/java/org/bukkit/LocationTest.java
Normale Datei
196
paper-api/src/test/java/org/bukkit/LocationTest.java
Normale Datei
@ -0,0 +1,196 @@
|
|||||||
|
package org.bukkit;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.Parameterized;
|
||||||
|
import org.junit.runners.Parameterized.Parameter;
|
||||||
|
import org.junit.runners.Parameterized.Parameters;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
@RunWith(Parameterized.class)
|
||||||
|
public class LocationTest {
|
||||||
|
private static final double δ = 1.0 / 1000000;
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* a² + b² = c², a = b
|
||||||
|
* => 2∙(a²) = 2∙(b²) = c², c = 1
|
||||||
|
* => 2∙(a²) = 1
|
||||||
|
* => a² = 1/2
|
||||||
|
* => a = √(1/2) ∎
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
private static final double HALF_UNIT = Math.sqrt(1 / 2f);
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* a² + b² = c², c = √(1/2)
|
||||||
|
* => a² + b² = √(1/2)², a = b
|
||||||
|
* => 2∙(a²) = 2∙(b²) = 1/2
|
||||||
|
* => a² = 1/4
|
||||||
|
* => a = √(1/4) ∎
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
private static final double HALF_HALF_UNIT = Math.sqrt(1 / 4f);
|
||||||
|
|
||||||
|
@Parameters(name= "{index}: {0}")
|
||||||
|
public static List<Object[]> data() {
|
||||||
|
Random RANDOM = new Random(1l); // Test is deterministic
|
||||||
|
int r = 0;
|
||||||
|
return ImmutableList.<Object[]>of(
|
||||||
|
new Object[] { "X",
|
||||||
|
1, 0, 0,
|
||||||
|
270, 0
|
||||||
|
},
|
||||||
|
new Object[] { "-X",
|
||||||
|
-1, 0, 0,
|
||||||
|
90, 0
|
||||||
|
},
|
||||||
|
new Object[] { "Z",
|
||||||
|
0, 0, 1,
|
||||||
|
0, 0
|
||||||
|
},
|
||||||
|
new Object[] { "-Z",
|
||||||
|
0, 0, -1,
|
||||||
|
180, 0
|
||||||
|
},
|
||||||
|
new Object[] { "Y",
|
||||||
|
0, 1, 0,
|
||||||
|
0, -90 // Zero is here as a "default" value
|
||||||
|
},
|
||||||
|
new Object[] { "-Y",
|
||||||
|
0, -1, 0,
|
||||||
|
0, 90 // Zero is here as a "default" value
|
||||||
|
},
|
||||||
|
new Object[] { "X Z",
|
||||||
|
HALF_UNIT, 0, HALF_UNIT,
|
||||||
|
(270 + 360) / 2, 0
|
||||||
|
},
|
||||||
|
new Object[] { "X -Z",
|
||||||
|
HALF_UNIT, 0, -HALF_UNIT,
|
||||||
|
(270 + 180) / 2, 0
|
||||||
|
},
|
||||||
|
new Object[] { "-X -Z",
|
||||||
|
-HALF_UNIT, 0, -HALF_UNIT,
|
||||||
|
(90 + 180) / 2, 0
|
||||||
|
},
|
||||||
|
new Object[] { "-X Z",
|
||||||
|
-HALF_UNIT, 0, HALF_UNIT,
|
||||||
|
(90 + 0) / 2, 0
|
||||||
|
},
|
||||||
|
new Object[] { "X Y Z",
|
||||||
|
HALF_HALF_UNIT, HALF_UNIT, HALF_HALF_UNIT,
|
||||||
|
(270 + 360) / 2, -45
|
||||||
|
},
|
||||||
|
new Object[] { "-X -Y -Z",
|
||||||
|
-HALF_HALF_UNIT, -HALF_UNIT, -HALF_HALF_UNIT,
|
||||||
|
(90 + 180) / 2, 45
|
||||||
|
},
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++),
|
||||||
|
getRandom(RANDOM, r++)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object[] getRandom(Random random, int index) {
|
||||||
|
final double YAW_FACTOR = 360;
|
||||||
|
final double YAW_OFFSET = 0;
|
||||||
|
final double PITCH_FACTOR = 180;
|
||||||
|
final double PITCH_OFFSET = -90;
|
||||||
|
final double CARTESIAN_FACTOR = 256;
|
||||||
|
final double CARTESIAN_OFFSET = -128;
|
||||||
|
|
||||||
|
Vector vector;
|
||||||
|
Location location;
|
||||||
|
if (random.nextBoolean()) {
|
||||||
|
float pitch = (float) (random.nextDouble() * PITCH_FACTOR + PITCH_OFFSET);
|
||||||
|
float yaw = (float) (random.nextDouble() * YAW_FACTOR + YAW_OFFSET);
|
||||||
|
|
||||||
|
location = getEmptyLocation();
|
||||||
|
location.setPitch(pitch);
|
||||||
|
location.setYaw(yaw);
|
||||||
|
|
||||||
|
vector = location.getDirection();
|
||||||
|
} else {
|
||||||
|
double x = random.nextDouble() * CARTESIAN_FACTOR + CARTESIAN_OFFSET;
|
||||||
|
double y = random.nextDouble() * CARTESIAN_FACTOR + CARTESIAN_OFFSET;
|
||||||
|
double z = random.nextDouble() * CARTESIAN_FACTOR + CARTESIAN_OFFSET;
|
||||||
|
|
||||||
|
location = getEmptyLocation();
|
||||||
|
vector = new Vector(x, y, z).normalize();
|
||||||
|
|
||||||
|
location.setDirection(vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Object[] { "R" + index,
|
||||||
|
vector.getX(), vector.getY(), vector.getZ(),
|
||||||
|
location.getYaw(), location.getPitch()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Parameter(0)
|
||||||
|
public String nane;
|
||||||
|
@Parameter(1)
|
||||||
|
public double x;
|
||||||
|
@Parameter(2)
|
||||||
|
public double y;
|
||||||
|
@Parameter(3)
|
||||||
|
public double z;
|
||||||
|
@Parameter(4)
|
||||||
|
public float yaw;
|
||||||
|
@Parameter(5)
|
||||||
|
public float pitch;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpectedPitchYaw() {
|
||||||
|
Location location = getEmptyLocation().setDirection(getVector());
|
||||||
|
|
||||||
|
assertThat((double) location.getYaw(), is(closeTo(yaw, δ)));
|
||||||
|
assertThat((double) location.getPitch(), is(closeTo(pitch, δ)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpectedXYZ() {
|
||||||
|
Vector vector = getLocation().getDirection();
|
||||||
|
|
||||||
|
assertThat(vector.getX(), is(closeTo(x, δ)));
|
||||||
|
assertThat(vector.getY(), is(closeTo(y, δ)));
|
||||||
|
assertThat(vector.getZ(), is(closeTo(z, δ)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector getVector() {
|
||||||
|
return new Vector(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Location getEmptyLocation() {
|
||||||
|
return new Location(null, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Location getLocation() {
|
||||||
|
Location location = getEmptyLocation();
|
||||||
|
location.setYaw(yaw);
|
||||||
|
location.setPitch(pitch);
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren