forked from Bukkit/Bukkit
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
- Loading branch information
1 parent
bd80c6e
commit ad1f1c2
Showing
2 changed files
with
277 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |