Java tutorial
//package com.ryanm.droid.rugl.util.math; /** * A numerical interval * * @author ryanm */ public class Range { /** * The lower value */ private float min = 0; /** * The upper value */ private float max = 0; /** * @param min * @param max */ public Range(float min, float max) { set(min, max); } /** * @param r * @param dest * @return <code>true</code> if the intersection exists */ public boolean intersection(Range r, Range dest) { if (intersects(r)) { dest.set(Math.max(min, r.min), Math.min(max, r.max)); return true; } return false; } /** * @param value * @return true if the value lies between the min and max values, * inclusively */ public boolean contains(float value) { return min <= value && max >= value; } /** * @param min * @param max */ public void set(float min, float max) { this.min = min; this.max = max; sort(); } /** * @param r */ public void set(Range r) { set(r.getMin(), r.getMax()); } /** * @return The difference between min and max */ public float getSpan() { return max - min; } /** * @return The lower range boundary */ public float getMin() { return min; } /** * @param min */ public void setMin(float min) { this.min = min; sort(); } /** * @return The upper range boundary */ public float getMax() { return max; } /** * @param max */ public void setMax(float max) { this.max = max; sort(); } private void sort() { if (min > max) { float t = min; min = max; max = t; } } /** * Limits a value to lie within this range * * @param v * The value to limit * @return min if v < min, max if v > max, otherwise v */ public float limit(float v) { return limit(v, min, max); } /** * Wraps a value into this range, modular arithmetic style * * @param v * @return The wrapped value */ public float wrap(float v) { return wrap(v, min, max); } /** * @param value * @return The proportion of the distance between min and max that value * lies from min */ public float toRatio(float value) { return toRatio(value, min, max); } /** * @param ratio * @return min + ratio * ( max - min ) */ public float toValue(float ratio) { return toValue(ratio, min, max); } /** * @param r * @return <code>true</code> if the ranges have values in common */ public boolean intersects(Range r) { return overlaps(min, max, r.min, r.max); } /** * Alters this range such that {@link #contains(float)} returns * <code>true</code> for f * * @param f */ public void encompass(float f) { if (f < min) { min = f; } else if (f > max) { max = f; } } /** * Alters this range such that {@link #contains(float)} returns * <code>true</code> for all values in r * * @param r */ public void encompass(Range r) { encompass(r.min); encompass(r.max); } @Override public String toString() { return "[ " + min + " : " + max + " ]"; } /** * Limits a value to lie within some range * * @param v * @param min * @param max * @return min if v < min, max if v > max, otherwise v */ public static float limit(float v, float min, float max) { if (v < min) { v = min; } else if (v > max) { v = max; } return v; } /** * Wraps a value into a range, in a modular arithmetic style (but it works * for negatives too) * * @param v * @param min * @param max * @return the wrapped value */ public static float wrap(float v, float min, float max) { v -= min; max -= min; if (v < 0) { v += max * ((int) (-v / max) + 1); } v %= max; return v + min; } /** * @param v * @param min * @param max * @return The proportion of the distance between min and max that v lies * from min */ public static float toRatio(float v, float min, float max) { float d = v - min; float e = max - min; return d / e; } /** * @param ratio * @param min * @param max * @return min + ratio * ( max - min ) */ public static float toValue(float ratio, float min, float max) { return min + ratio * (max - min); } /** * @param value * @param min * @param max * @return <code>true</code> if value lies within min and max, inclusively */ public static boolean inRange(float value, float min, float max) { return value >= min && value <= max; } /** * @param minA * @param maxA * @param minB * @param maxB * @return <code>true</code> if the ranges overlap */ public static boolean overlaps(float minA, float maxA, float minB, float maxB) { assert minA <= maxA; assert minB <= maxB; return !(minA > maxB || maxA < minB); } /** * @param a * a static range * @param b * a mobile range * @param bv * The velocity of b * @return The time period over which a and b intersect, or * <code>null</code> if they never do */ public static Range intersectionTime(Range a, Range b, float bv) { if (bv == 0) { // nobody likes division by zero if (a.intersects(b)) { // continual intersection return new Range(-Float.MAX_VALUE, Float.MAX_VALUE); } else { // no intersection return null; } } // time when low edge of a meets high edge of b float t1 = (a.getMin() - b.getMax()) / bv; // time when high edge of a meets low edge of b float t2 = (a.getMax() - b.getMin()) / bv; // constructor sorts the times into proper order return new Range(t1, t2); } /** * @param minA * @param maxA * @param minB * @param maxB * @return <code>true</code> if rangeA contains rangeB */ public static boolean contains(float minA, float maxA, float minB, float maxB) { return minA <= minB && maxA >= maxB; } /** * @param minA * @param maxA * @param minB * @param maxB * @return The size of the intersection of the two ranges */ public static float intersection(float minA, float maxA, float minB, float maxB) { float highMin = Math.max(minA, minB); float lowMax = Math.min(maxA, maxB); if (lowMax > highMin) { return lowMax - highMin; } return 0; } /** * Shifts the range * * @param d */ public void translate(float d) { min += d; max += d; } /** * Scales the range around the origin * * @param s */ public void scale(float s) { min *= s; max *= s; } /** * Smooth interpolation between min and max. Copy the following into gnuplot * to see the difference between {@link #smooth(float, float, float)} and * {@link #smooth2(float, float, float)} <br> * set xrange [0:1] <br> * set yrange [0:1] <br> * plot (x**2*(3-2*x)) title "smooth", x**3*(10+x*(-15+6*x)) title "smooth2" * * @param ratio * in range 0-1 * @param min * minimum output value * @param max * maximum output value * @return first-order continuous graduation between min and max * @see #smooth2(float, float, float) */ public static final float smooth(float ratio, float min, float max) { return toValue(ratio * ratio * (3.0f - (ratio + ratio)), min, max); } /** * Smooth interpolation between min and max * * @param ratio * in range 0-1 * @param min * minimum output value * @param max * maximum output value * @return all-derivation continuous graduation between min and max * @see Range#smooth(float, float, float) */ public static final float smooth2(float ratio, float min, float max) { float t3 = ratio * ratio * ratio; return toValue(t3 * (10.f + ratio * (-15.f + 6.f * ratio)), min, max); } }