/* * Copyright (c) 2015 NOVA, All rights reserved. * This library is free software, licensed under GNU Lesser General Public License version 3 * * This file is part of NOVA. * * NOVA is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NOVA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NOVA. If not, see <http://www.gnu.org/licenses/>. */ package nova.core.util; import nova.core.util.math.Vector3DUtil; import org.apache.commons.math3.geometry.euclidean.threed.Rotation; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import java.util.stream.IntStream; /** * Defines basic directions in world. */ public enum Direction { DOWN(0, -1, 0), UP(0, 1, 0), NORTH(0, 0, -1), SOUTH(0, 0, 1), WEST(-1, 0, 0), EAST(1, 0, 0), UNKNOWN(0, 0, 0); /** * Contains all valid directions. */ public static final Direction[] VALID_DIRECTIONS = new Direction[] { DOWN, UP, NORTH, SOUTH, WEST, EAST }; /** * Directions in a 2 dimensional space. */ public static final Direction[] FLAT_DIRECTIONS = new Direction[] { NORTH, SOUTH, WEST, EAST }; private static final Direction[] values = Direction.values(); public final int x, y, z; public final Rotation rotation; private final Vector3D vector; Direction(int x, int y, int z) { this.x = x; this.y = y; this.z = z; this.vector = new Vector3D(x, y, z); if (vector.equals(Vector3D.ZERO)) { this.rotation = Rotation.IDENTITY; } else { this.rotation = new Rotation(Vector3DUtil.FORWARD, vector); } } /** * Turns direction number into Direction. * @param directionID Direction ID / number. * @return Resulting Direction. * @throws IllegalArgumentException if the direction ID is invalid (greater than {@code 6} or less than {@code 0}) */ public static Direction fromOrdinal(int directionID) { if (directionID < 0 || directionID >= Direction.values.length) { throw new IllegalArgumentException("Direction ID is invalid! The direction ID " + directionID + " is must be between " + (Direction.values.length - 1) + " and 0 inclusive"); } return Direction.values[directionID]; } /** * @param unitVector The unit vector representing the direction. * @return The direction based on a unit vector */ public static Direction fromVector(Vector3D unitVector) { return fromOrdinal( IntStream.range(0, 6) .boxed() .sorted((o1, o2) -> Double.compare(fromOrdinal(o2).toVector().dotProduct(unitVector), fromOrdinal(o1).toVector().dotProduct(unitVector))) .findFirst() .get() ); } /** * @return Direction opposite to this. */ public Direction opposite() { if (this == Direction.UNKNOWN) { return this; } else { return VALID_DIRECTIONS[this.ordinal() ^ 1]; } } /** * @return This Direction represented as {@link Vector3D} */ public Vector3D toVector() { return vector; } }