Package com.bergerkiller.bukkit.common.utils

Source Code of com.bergerkiller.bukkit.common.utils.MathUtil

package com.bergerkiller.bukkit.common.utils;

import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.craftbukkit.TrigMath;
import org.bukkit.entity.Entity;
import org.bukkit.util.Vector;

import com.bergerkiller.bukkit.common.bases.LongHash;

/**
* Multiple Math utilities to compare and calculate using Vectors and raw values
*/
public class MathUtil {
  private static final int CHUNK_BITS = 4;
  private static final int CHUNK_VALUES = 16;
  public static final float DEGTORAD = 0.017453293F;
  public static final float RADTODEG = 57.29577951F;
  public static final double HALFROOTOFTWO = 0.707106781;

  public static double lengthSquared(double... values) {
    double rval = 0;
    for (double value : values) {
      rval += value * value;
    }
    return rval;
  }

  public static double length(double... values) {
    return Math.sqrt(lengthSquared(values));
  }

  public static double distance(double x1, double y1, double x2, double y2) {
    return length(x1 - x2, y1 - y2);
  }

  public static double distanceSquared(double x1, double y1, double x2, double y2) {
    return lengthSquared(x1 - x2, y1 - y2);
  }

  public static double distance(double x1, double y1, double z1, double x2, double y2, double z2) {
    return length(x1 - x2, y1 - y2, z1 - z2);
  }

  public static double distanceSquared(double x1, double y1, double z1, double x2, double y2, double z2) {
    return lengthSquared(x1 - x2, y1 - y2, z1 - z2);
  }
 
  /**
   * Gets a percentage and round it with a cusotm amound of decimals
   *
   * @param subtotal to get percentags for
   * @param total to use as 100% value
   * @param decimals to round with
   * @return Percentage for subtotal with custom decimals
   */
  public static double getPercentage(int subtotal, int total, int decimals) {
    return round(getPercentage(subtotal, total), decimals);
  }
 
  /**
   * Gets a percentags of 2 values
   *
   * @param subtotal to get percentage for
   * @param total to sue as 100% value
   * @return percentage
   */
  public static double getPercentage(int subtotal, int total) {
    return ((float) subtotal / (float) total) * 100;
  }

  /**
   * Gets the angle difference between two angles
   *
   * @param angle1
   * @param angle2
   * @return angle difference
   */
  public static int getAngleDifference(int angle1, int angle2) {
    return Math.abs(wrapAngle(angle1 - angle2));
  }

  /**
   * Gets the angle difference between two angles
   *
   * @param angle1
   * @param angle2
   * @return angle difference
   */
  public static float getAngleDifference(float angle1, float angle2) {
    return Math.abs(wrapAngle(angle1 - angle2));
  }

  /**
   * Wraps the angle to be between -180 and 180 degrees
   *
   * @param angle to wrap
   * @return [-180 > angle >= 180]
   */
  public static int wrapAngle(int angle) {
    int wrappedAngle = angle;
    while (wrappedAngle <= -180) {
      wrappedAngle += 360;
    }
    while (wrappedAngle > 180) {
      wrappedAngle -= 360;
    }
    return wrappedAngle;
  }

  /**
   * Wraps the angle to be between -180 and 180 degrees
   *
   * @param angle to wrap
   * @return [-180 > angle >= 180]
   */
  public static float wrapAngle(float angle) {
    float wrappedAngle = angle;
    while (wrappedAngle <= -180f) {
      wrappedAngle += 360f;
    }
    while (wrappedAngle > 180f) {
      wrappedAngle -= 360f;
    }
    return wrappedAngle;
  }

  /**
   * Normalizes a 2D-vector to be the length of another 2D-vector<br>
   * Calculates the normalization factor to multiply the input vector with, to get the requested length
   *
   * @param x axis of the vector
   * @param z axis of the vector
   * @param reqx axis of the length vector
   * @param reqz axis of the length vector
   * @return the normalization factor
   */
  public static double normalize(double x, double z, double reqx, double reqz) {
    return Math.sqrt(lengthSquared(reqx, reqz) / lengthSquared(x, z));
  }

  public static float getLookAtYaw(Entity loc, Entity lookat) {
    return getLookAtYaw(loc.getLocation(), lookat.getLocation());
  }

  public static float getLookAtYaw(Block loc, Block lookat) {
    return getLookAtYaw(loc.getLocation(), lookat.getLocation());
  }

  public static float getLookAtYaw(Location loc, Location lookat) {
    return getLookAtYaw(lookat.getX() - loc.getX(), lookat.getZ() - loc.getZ());
  }

  public static float getLookAtYaw(Vector motion) {
    return getLookAtYaw(motion.getX(), motion.getZ());
  }

  /**
   * Gets the horizontal look-at angle in degrees to look into the 2D-direction specified
   *
   * @param dx axis of the direction
   * @param dz axis of the direction
   * @return the angle in degrees
   */
  public static float getLookAtYaw(double dx, double dz) {
    return atan2(dz, dx) - 180f;
  }

  /**
   * Gets the pitch angle in degrees to look into the direction specified
   *
   * @param dX axis of the direction
   * @param dY axis of the direction
   * @param dZ axis of the direction
   * @return look-at angle in degrees
   */
  public static float getLookAtPitch(double dX, double dY, double dZ) {
    return getLookAtPitch(dY, length(dX, dZ));
  }

  /**
   * Gets the pitch angle in degrees to look into the direction specified
   *
   * @param dY axis of the direction
   * @param dXZ axis of the direction (length of x and z)
   * @return look-at angle in degrees
   */
  public static float getLookAtPitch(double dY, double dXZ) {
    return -atan(dY / dXZ);
  }

  /**
   * Gets the inverse tangent of the value in degrees
   *
   * @param value
   * @return inverse tangent angle in degrees
   */
  public static float atan(double value) {
    return RADTODEG * (float) TrigMath.atan(value);
  }

  /**
   * Gets the inverse tangent angle in degrees of the rectangle vector
   *
   * @param y axis
   * @param x axis
   * @return inverse tangent 2 angle in degrees
   */
  public static float atan2(double y, double x) {
    return RADTODEG * (float) TrigMath.atan2(y, x);
  }

  /**
   * Gets the floor integer value from a double value
   *
   * @param value to get the floor of
   * @return floor value
   */
  public static int floor(double value) {
    int i = (int) value;
    return value < (double) i ? i - 1 : i;
  }

  /**
   * Gets the floor integer value from a float value
   *
   * @param value to get the floor of
   * @return floor value
   */
  public static int floor(float value) {
    int i = (int) value;
    return value < (float) i ? i - 1 : i;
  }

  /**
   * Gets the ceiling integer value from a double value
   *
   * @param value to get the ceiling of
   * @return ceiling value
   */
  public static int ceil(double value) {
    return -floor(-value);
  }

  /**
   * Gets the ceiling integer value from a float value
   *
   * @param value to get the ceiling of
   * @return ceiling value
   */
  public static int ceil(float value) {
    return -floor(-value);
  }

  /**
   * Moves a Location into the yaw and pitch of the Location in the offset specified
   *
   * @param loc to move
   * @param offset vector
   * @return Translated Location
   */
  public static Location move(Location loc, Vector offset) {
    return move(loc, offset.getX(), offset.getY(), offset.getZ());
  }

  /**
   * Moves a Location into the yaw and pitch of the Location in the offset specified
   *
   * @param loc to move
   * @param dx offset
   * @param dy offset
   * @param dz offset
   * @return Translated Location
   */
  public static Location move(Location loc, double dx, double dy, double dz) {
    Vector off = rotate(loc.getYaw(), loc.getPitch(), dx, dy, dz);
    double x = loc.getX() + off.getX();
    double y = loc.getY() + off.getY();
    double z = loc.getZ() + off.getZ();
    return new Location(loc.getWorld(), x, y, z, loc.getYaw(), loc.getPitch());
  }

  /**
   * Rotates a 3D-vector using yaw and pitch
   *
   * @param yaw angle in degrees
   * @param pitch angle in degrees
   * @param vector to rotate
   * @return Vector rotated by the angle (new instance)
   */
  public static Vector rotate(float yaw, float pitch, Vector vector) {
    return rotate(yaw, pitch, vector.getX(), vector.getY(), vector.getZ());
  }

  /**
   * Rotates a 3D-vector using yaw and pitch
   *
   * @param yaw angle in degrees
   * @param pitch angle in degrees
   * @param x axis of the vector
   * @param y axis of the vector
   * @param z axis of the vector
   * @return Vector rotated by the angle
   */
  public static Vector rotate(float yaw, float pitch, double x, double y, double z) {
    // Conversions found by (a lot of) testing
    float angle;
    angle = yaw * DEGTORAD;
    double sinyaw = Math.sin(angle);
    double cosyaw = Math.cos(angle);

    angle = pitch * DEGTORAD;
    double sinpitch = Math.sin(angle);
    double cospitch = Math.cos(angle);

    Vector vector = new Vector();
    vector.setX((x * sinyaw) - (y * cosyaw * sinpitch) - (z * cosyaw * cospitch));
    vector.setY((y * cospitch) - (z * sinpitch));
    vector.setZ(-(x * cosyaw) - (y * sinyaw * sinpitch) - (z * sinyaw * cospitch));
    return vector;
  }

  /**
   * Rounds the specified value to the amount of decimals specified
   *
   * @param value to round
   * @param decimals count
   * @return value round to the decimal count specified
   */
  public static double round(double value, int decimals) {
    double p = Math.pow(10, decimals);
    return Math.round(value * p) / p;
  }

  /**
   * Returns 0 if the value is not-a-number
   *
   * @param value to check
   * @return The value, or 0 if it is NaN
   */
  public static double fixNaN(double value) {
    return fixNaN(value, 0.0);
  }

  /**
   * Returns the default if the value is not-a-number
   *
   * @param value to check
   * @param def value
   * @return The value, or the default if it is NaN
   */
  public static double fixNaN(double value, double def) {
    return Double.isNaN(value) ? def : value;
  }

  /**
   * Converts a location value into a chunk coordinate
   *
   * @param loc to convert
   * @return chunk coordinate
   */
  public static int toChunk(double loc) {
    return floor(loc / (double) CHUNK_VALUES);
  }

  /**
   * Converts a location value into a chunk coordinate
   *
   * @param loc to convert
   * @return chunk coordinate
   */
  public static int toChunk(int loc) {
    return loc >> CHUNK_BITS;
  }

  public static double useOld(double oldvalue, double newvalue, double peruseold) {
    return oldvalue + (peruseold * (newvalue - oldvalue));
  }

  public static double lerp(double d1, double d2, double stage) {
    if (Double.isNaN(stage) || stage > 1) {
      return d2;
    } else if (stage < 0) {
      return d1;
    } else {
      return d1 * (1 - stage) + d2 * stage;
    }
  }

  public static Vector lerp(Vector vec1, Vector vec2, double stage) {
    Vector newvec = new Vector();
    newvec.setX(lerp(vec1.getX(), vec2.getX(), stage));
    newvec.setY(lerp(vec1.getY(), vec2.getY(), stage));
    newvec.setZ(lerp(vec1.getZ(), vec2.getZ(), stage));
    return newvec;
  }

  public static Location lerp(Location loc1, Location loc2, double stage) {
    Location newloc = new Location(loc1.getWorld(), 0, 0, 0);
    newloc.setX(lerp(loc1.getX(), loc2.getX(), stage));
    newloc.setY(lerp(loc1.getY(), loc2.getY(), stage));
    newloc.setZ(lerp(loc1.getZ(), loc2.getZ(), stage));
    newloc.setYaw((float) lerp(loc1.getYaw(), loc2.getYaw(), stage));
    newloc.setPitch((float) lerp(loc1.getPitch(), loc2.getPitch(), stage));
    return newloc;
  }

  /**
   * Checks whether one value is negative and the other positive, or opposite
   *
   * @param value1 to check
   * @param value2 to check
   * @return True if value1 is inverted from value2
   */
  public static boolean isInverted(double value1, double value2) {
    return (value1 > 0 && value2 < 0) || (value1 < 0 && value2 > 0);
  }

  /**
   * Gets the direction of yaw and pitch angles
   *
   * @param yaw angle in degrees
   * @param pitch angle in degrees
   * @return Direction Vector
   */
  public static Vector getDirection(float yaw, float pitch) {
        Vector vector = new Vector();
        double rotX = DEGTORAD * yaw;
        double rotY = DEGTORAD * pitch;
        vector.setY(-Math.sin(rotY));
        double h = Math.cos(rotY);
        vector.setX(-h * Math.sin(rotX));
        vector.setZ(h * Math.cos(rotX));
        return vector;
  }

  /**
   * Clamps the value between -limit and limit
   *
   * @param value to clamp
   * @param limit
   * @return value, -limit or limit
   */
  public static double clamp(double value, double limit) {
    return clamp(value, -limit, limit);
  }

  /**
   * Clamps the value between the min and max values
   * @param value to clamp
   * @param min
   * @param max
   * @return value, min or max
   */
  public static double clamp(double value, double min, double max) {
    return value < min ? min : (value > max ? max : value);
  }

  /**
   * Clamps the value between -limit and limit
   *
   * @param value to clamp
   * @param limit
   * @return value, -limit or limit
   */
  public static float clamp(float value, float limit) {
    return clamp(value, -limit, limit);
  }

  /**
   * Clamps the value between the min and max values
   * @param value to clamp
   * @param min
   * @param max
   * @return value, min or max
   */
  public static float clamp(float value, float min, float max) {
    return value < min ? min : (value > max ? max : value);
  }

  /**
   * Clamps the value between -limit and limit
   *
   * @param value to clamp
   * @param limit
   * @return value, -limit or limit
   */
  public static int clamp(int value, int limit) {
    return clamp(value, -limit, limit);
  }

  /**
   * Clamps the value between the min and max values
   * @param value to clamp
   * @param min
   * @param max
   * @return value, min or max
   */
  public static int clamp(int value, int min, int max) {
    return value < min ? min : (value > max ? max : value);
  }

  /**
   * Turns a value negative or keeps it positive based on a boolean input
   *
   * @param value to work with
   * @param negative - True to invert, False to keep the old value
   * @return the value or inverted (-value)
   */
  public static int invert(int value, boolean negative) {
    return negative ? -value : value;
  }

  /**
   * Turns a value negative or keeps it positive based on a boolean input
   *
   * @param value to work with
   * @param negative - True to invert, False to keep the old value
   * @return the value or inverted (-value)
   */
  public static float invert(float value, boolean negative) {
    return negative ? -value : value;
  }

  /**
   * Turns a value negative or keeps it positive based on a boolean input
   *
   * @param value to work with
   * @param negative - True to invert, False to keep the old value
   * @return the value or inverted (-value)
   */
  public static double invert(double value, boolean negative) {
    return negative ? -value : value;
  }

  /**
   * Merges two ints into a long
   *
   * @param msw integer
   * @param lsw integer
   * @return merged long value
   */
  public static long toLong(int msw, int lsw) {
    return longHashToLong(msw, lsw);
  }

  public static long longHashToLong(int msw, int lsw) {
    return LongHash.toLong(msw, lsw);
  }

  public static int longHashMsw(long key) {
    return LongHash.msw(key);
  }

  public static int longHashLsw(long key) {
    return LongHash.lsw(key);
  }

  public static void setVectorLength(Vector vector, double length) {
    setVectorLengthSquared(vector, Math.signum(length) * length * length);
  }

  public static void setVectorLengthSquared(Vector vector, double lengthsquared) {
    double vlength = vector.lengthSquared();
    if (Math.abs(vlength) > 0.0001) {
      if (lengthsquared < 0) {
        vector.multiply(-Math.sqrt(-lengthsquared / vlength));
      } else {
        vector.multiply(Math.sqrt(lengthsquared / vlength));
      }
    }
  }

  public static boolean isHeadingTo(BlockFace direction, Vector velocity) {
    return isHeadingTo(FaceUtil.faceToVector(direction), velocity);
  }

  public static boolean isHeadingTo(Location from, Location to, Vector velocity) {
    return isHeadingTo(new Vector(to.getX() - from.getX(), to.getY() - from.getY(), to.getZ() - from.getZ()), velocity);
  }

  public static boolean isHeadingTo(Vector offset, Vector velocity) {
    double dbefore = offset.lengthSquared();
    if (dbefore < 0.0001) {
      return true;
    }
    Vector clonedVelocity = velocity.clone();
    setVectorLengthSquared(clonedVelocity, dbefore);
    return dbefore > clonedVelocity.subtract(offset).lengthSquared();
  }
}
TOP

Related Classes of com.bergerkiller.bukkit.common.utils.MathUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.