1 // Copyright 2014 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.base; 6 7 /** Contains various math utilities used throughout Chrome Mobile. */ 8 public class MathUtils { 9 /** A minimum difference to use when comparing floats for equality. */ 10 public static final float EPSILON = 0.001f; 11 MathUtils()12 private MathUtils() {} 13 14 /** 15 * Returns the passed in value if it resides within the specified range (inclusive). If not, 16 * it will return the closest boundary from the range. The ordering of the boundary values does 17 * not matter. 18 * 19 * @param value The value to be compared against the range. 20 * @param a First boundary range value. 21 * @param b Second boundary range value. 22 * @return The passed in value if it is within the range, otherwise the closest boundary value. 23 */ clamp(int value, int a, int b)24 public static int clamp(int value, int a, int b) { 25 int min = (a > b) ? b : a; 26 int max = (a > b) ? a : b; 27 if (value < min) { 28 value = min; 29 } else if (value > max) { 30 value = max; 31 } 32 return value; 33 } 34 35 /** 36 * Returns the passed in value if it resides within the specified range (inclusive). If not, 37 * it will return the closest boundary from the range. The ordering of the boundary values does 38 * not matter. 39 * 40 * @param value The value to be compared against the range. 41 * @param a First boundary range value. 42 * @param b Second boundary range value. 43 * @return The passed in value if it is within the range, otherwise the closest boundary value. 44 */ clamp(long value, long a, long b)45 public static long clamp(long value, long a, long b) { 46 long min = (a > b) ? b : a; 47 long max = (a > b) ? a : b; 48 if (value < min) { 49 value = min; 50 } else if (value > max) { 51 value = max; 52 } 53 return value; 54 } 55 56 /** 57 * Returns the passed in value if it resides within the specified range (inclusive). If not, 58 * it will return the closest boundary from the range. The ordering of the boundary values does 59 * not matter. 60 * 61 * @param value The value to be compared against the range. 62 * @param a First boundary range value. 63 * @param b Second boundary range value. 64 * @return The passed in value if it is within the range, otherwise the closest boundary value. 65 */ clamp(float value, float a, float b)66 public static float clamp(float value, float a, float b) { 67 float min = (a > b) ? b : a; 68 float max = (a > b) ? a : b; 69 if (value < min) { 70 value = min; 71 } else if (value > max) { 72 value = max; 73 } 74 return value; 75 } 76 77 /** 78 * Computes a%b that is positive. Note that result of % operation is not always positive. 79 * @return a%b >= 0 ? a%b : a%b + b 80 */ positiveModulo(int a, int b)81 public static int positiveModulo(int a, int b) { 82 int mod = a % b; 83 return mod >= 0 ? mod : mod + b; 84 } 85 86 /** 87 * Moves {@code value} forward to {@code target} based on {@code speed}. 88 * @param value The current value. 89 * @param target The target value. 90 * @param speed How far to move {@code value} to {@code target}. 0 doesn't move it at all. 1 91 * moves it to {@code target}. 92 * @return The new interpolated value. 93 */ interpolate(float value, float target, float speed)94 public static float interpolate(float value, float target, float speed) { 95 return (value + (target - value) * speed); 96 } 97 98 /** 99 * Smooth a value between 0 and 1. 100 * @param t The value to smooth. 101 * @return The smoothed value between 0 and 1. 102 */ smoothstep(float t)103 public static float smoothstep(float t) { 104 return t * t * (3.0f - 2.0f * t); 105 } 106 107 /** 108 * Scales the provided dimension such that it is just large enough to fit 109 * the target width and height. 110 * 111 * @param dimensions The dimensions to scale 112 * @param targetWidth The target width 113 * @param targetHeight The target height 114 * @return The scale factor applied to dimensions 115 */ scaleToFitTargetSize(int[] dimensions, int targetWidth, int targetHeight)116 public static float scaleToFitTargetSize(int[] dimensions, int targetWidth, int targetHeight) { 117 if (dimensions.length < 2 || dimensions[0] <= 0 || dimensions[1] <= 0) { 118 throw new IllegalArgumentException( 119 "Expected dimensions to have length >= 2 && dimensions[0] > 0 && " 120 + "dimensions[1] > 0"); 121 } 122 float scale = 123 Math.max((float) targetWidth / dimensions[0], (float) targetHeight / dimensions[1]); 124 dimensions[0] = (int) (dimensions[0] * scale); 125 dimensions[1] = (int) (dimensions[1] * scale); 126 return scale; 127 } 128 129 /** 130 * Flips {@code value} iff {@code flipSign} is {@code true}. 131 * @param value The value to flip. 132 * @param flipSign Whether or not to flip the value. 133 * @return {@code value} iff {@code flipSign} is {@code false}, otherwise negative 134 * {@code value}. 135 */ flipSignIf(int value, boolean flipSign)136 public static int flipSignIf(int value, boolean flipSign) { 137 return flipSign ? -value : value; 138 } 139 140 /** 141 * Flips {@code value} iff {@code flipSign} is {@code true}. 142 * @param value The value to flip. 143 * @param flipSign Whether or not to flip the value. 144 * @return {@code value} iff {@code flipSign} is {@code false}, otherwise negative 145 * {@code value}. 146 */ flipSignIf(float value, boolean flipSign)147 public static float flipSignIf(float value, boolean flipSign) { 148 return flipSign ? -value : value; 149 } 150 151 /** 152 * Determine if two floats are equal. 153 * @param f1 The first float to compare. 154 * @param f2 The second float to compare. 155 * @return True if the floats are equal. 156 */ areFloatsEqual(float f1, float f2)157 public static boolean areFloatsEqual(float f1, float f2) { 158 return Math.abs(f1 - f2) < MathUtils.EPSILON; 159 } 160 161 /** 162 * Compute the distance between two points. 163 * @param x1 X of point 1. 164 * @param y1 Y of point 1. 165 * @param x2 X of point 2. 166 * @param y2 Y of point 2. 167 * @return The distance between the two points. 168 */ distance(float x1, float y1, float x2, float y2)169 public static float distance(float x1, float y1, float x2, float y2) { 170 float xDist = x2 - x1; 171 float yDist = y2 - y1; 172 return (float) Math.sqrt(xDist * xDist + yDist * yDist); 173 } 174 175 /** 176 * Compute the distance given two coordinate vectors 177 */ distance(float distanceX, float distanceY)178 public static float distance(float distanceX, float distanceY) { 179 return (float) Math.sqrt(distanceX * distanceX + distanceY * distanceY); 180 } 181 182 /** 183 * Maps {@code value} in [{@code fromStart}, {@code fromStop}] to 184 * [{@code toStart}, {@code toStop}]. 185 * 186 * @param value A number in [{@code fromStart}, {@code fromStop}]. 187 * @param fromStart Lower range of {@code value}. 188 * @param fromStop Upper range of {@code value}. 189 * @param toStart Lower range of mapped value. 190 * @param toStop Upper range of mapped value. 191 * @return mapped value. 192 */ map( float value, float fromStart, float fromStop, float toStart, float toStop)193 public static float map( 194 float value, float fromStart, float fromStop, float toStart, float toStop) { 195 return toStart + (toStop - toStart) * ((value - fromStart) / (fromStop - fromStart)); 196 } 197 198 /** 199 * Round the given value to two decimal places. 200 * 201 * @param value double The value to round. 202 * @return double The value rounded to two decimal places. 203 */ roundTwoDecimalPlaces(double value)204 public static double roundTwoDecimalPlaces(double value) { 205 return (double) Math.round(value * 100) / 100; 206 } 207 } 208