001/*
002 * This file is part of Baritone.
003 *
004 * Baritone is free software: you can redistribute it and/or modify
005 * it under the terms of the GNU Lesser General Public License as published by
006 * the Free Software Foundation, either version 3 of the License, or
007 * (at your option) any later version.
008 *
009 * Baritone is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012 * GNU Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public License
015 * along with Baritone.  If not, see <https://www.gnu.org/licenses/>.
016 */
017
018package baritone.api.utils;
019
020/**
021 * @author Brady
022 * @since 9/25/2018
023 */
024public class Rotation {
025
026    /**
027     * The yaw angle of this Rotation
028     */
029    private final float yaw;
030
031    /**
032     * The pitch angle of this Rotation
033     */
034    private final float pitch;
035
036    public Rotation(float yaw, float pitch) {
037        this.yaw = yaw;
038        this.pitch = pitch;
039        if (Float.isInfinite(yaw) || Float.isNaN(yaw) || Float.isInfinite(pitch) || Float.isNaN(pitch)) {
040            throw new IllegalStateException(yaw + " " + pitch);
041        }
042    }
043
044    /**
045     * @return The yaw of this rotation
046     */
047    public float getYaw() {
048        return this.yaw;
049    }
050
051    /**
052     * @return The pitch of this rotation
053     */
054    public float getPitch() {
055        return this.pitch;
056    }
057
058    /**
059     * Adds the yaw/pitch of the specified rotations to this
060     * rotation's yaw/pitch, and returns the result.
061     *
062     * @param other Another rotation
063     * @return The result from adding the other rotation to this rotation
064     */
065    public Rotation add(Rotation other) {
066        return new Rotation(
067                this.yaw + other.yaw,
068                this.pitch + other.pitch
069        );
070    }
071
072    /**
073     * Subtracts the yaw/pitch of the specified rotations from this
074     * rotation's yaw/pitch, and returns the result.
075     *
076     * @param other Another rotation
077     * @return The result from subtracting the other rotation from this rotation
078     */
079    public Rotation subtract(Rotation other) {
080        return new Rotation(
081                this.yaw - other.yaw,
082                this.pitch - other.pitch
083        );
084    }
085
086    /**
087     * @return A copy of this rotation with the pitch clamped
088     */
089    public Rotation clamp() {
090        return new Rotation(
091                this.yaw,
092                clampPitch(this.pitch)
093        );
094    }
095
096    /**
097     * @return A copy of this rotation with the yaw normalized
098     */
099    public Rotation normalize() {
100        return new Rotation(
101                normalizeYaw(this.yaw),
102                this.pitch
103        );
104    }
105
106    /**
107     * @return A copy of this rotation with the pitch clamped and the yaw normalized
108     */
109    public Rotation normalizeAndClamp() {
110        return new Rotation(
111                normalizeYaw(this.yaw),
112                clampPitch(this.pitch)
113        );
114    }
115
116    public Rotation withPitch(float pitch) {
117        return new Rotation(this.yaw, pitch);
118    }
119
120    /**
121     * Is really close to
122     *
123     * @param other another rotation
124     * @return are they really close
125     */
126    public boolean isReallyCloseTo(Rotation other) {
127        return yawIsReallyClose(other) && Math.abs(this.pitch - other.pitch) < 0.01;
128    }
129
130    public boolean yawIsReallyClose(Rotation other) {
131        float yawDiff = Math.abs(normalizeYaw(yaw) - normalizeYaw(other.yaw)); // you cant fool me
132        return (yawDiff < 0.01 || yawDiff > 359.99);
133    }
134
135    /**
136     * Clamps the specified pitch value between -90 and 90.
137     *
138     * @param pitch The input pitch
139     * @return The clamped pitch
140     */
141    public static float clampPitch(float pitch) {
142        return Math.max(-90, Math.min(90, pitch));
143    }
144
145    /**
146     * Normalizes the specified yaw value between -180 and 180.
147     *
148     * @param yaw The input yaw
149     * @return The normalized yaw
150     */
151    public static float normalizeYaw(float yaw) {
152        float newYaw = yaw % 360F;
153        if (newYaw < -180F) {
154            newYaw += 360F;
155        }
156        if (newYaw > 180F) {
157            newYaw -= 360F;
158        }
159        return newYaw;
160    }
161
162    @Override
163    public String toString() {
164        return "Yaw: " + yaw + ", Pitch: " + pitch;
165    }
166}