Package nodebox.function

Source Code of nodebox.function.MathFunctions$RangeIterator

package nodebox.function;

import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import nodebox.graphics.Point;
import nodebox.util.Geometry;
import nodebox.util.MathUtils;
import nodebox.util.waves.*;

import java.util.*;

import static com.google.common.base.Preconditions.checkArgument;
import static nodebox.util.MathUtils.clamp;

/**
* Basic math function library.
*/
public class MathFunctions {

    public static final FunctionLibrary LIBRARY;
    public static final String OVERFLOW_WRAP = "wrap";
    public static final String OVERFLOW_MIRROR = "mirror";
    public static final String OVERFLOW_CLAMP = "clamp";
    public static final String OVERFLOW_IGNORE = "ignore";
    public static final String WAVE_SINE = "sine";
    public static final String WAVE_SQUARE = "square";
    public static final String WAVE_TRIANGLE = "triangle";
    public static final String WAVE_SAWTOOTH = "sawtooth";

    static {
        LIBRARY = JavaLibrary.ofClass("math", MathFunctions.class,
                "number", "integer", "makeBoolean",
                "negate", "abs", "add", "subtract", "multiply", "divide", "mod", "sqrt", "pow",
                "log", "sum", "average", "compare", "logicOperator", "min", "max", "ceil", "floor", "runningTotal",
                "even", "odd",
                "makeNumbers", "randomNumbers", "round",
                "sample", "range",
                "radians", "degrees", "angle", "distance", "coordinates", "reflect", "sin", "cos", "pi", "e",
                "convertRange", "wave");
    }

    public static double number(double n) {
        return n;
    }

    public static long integer(long value) {
        return value;
    }

    public static boolean makeBoolean(boolean value) {
        return value;
    }

    public static double add(double n1, double n2) {
        return n1 + n2;
    }

    public static double subtract(double n1, double n2) {
        return n1 - n2;
    }

    public static double multiply(double n1, double n2) {
        return n1 * n2;
    }

    public static double divide(double n1, double n2) {
        checkArgument(n2 != 0, "Divider cannot be zero.");
        return n1 / n2;
    }

    public static double mod(double n1, double n2) {
        checkArgument(n2 != 0, "Divider cannot be zero.");
        return n1 % n2;
    }

    public static double sqrt(double n) {
        return Math.sqrt(n);
    }

    public static double pow(double n1, double n2) {
        return Math.pow(n1, n2);
    }

    public static double log(double n) {
        checkArgument(n != 0, "Value cannot be zero.");
        return Math.log(n);
    }

    /**
     * Return true if the given number is even.
     *
     * @param n The number to check.
     * @return true if even
     */
    public static boolean even(double n) {
        return n % 2 == 0;
    }

    /**
     * Return true if the given number is not even.
     *
     * @param n The number to check.
     * @return true if odd
     */
    public static boolean odd(double n) {
        return n % 2 != 0;
    }

    public static double negate(double n) {
        return -n;
    }

    public static double abs(double n) {
        return Math.abs(n);
    }

    private static boolean noValues(Iterable<?> values) {
        return values == null || Iterables.isEmpty(values);
    }

    public static double sum(Iterable<Double> numbers) {
        if (noValues(numbers)) return 0.0;
        double sum = 0;
        for (Double d : numbers) {
            sum += d;
        }
        return sum;
    }

    public static double average(Iterable<Double> numbers) {
        if (noValues(numbers)) return 0.0;
        double sum = 0;
        double counter = 0;
        for (Double d : numbers) {
            sum += d;
            counter++;
        }
        return sum / counter;
    }

    public static double max(Iterable<Double> numbers) {
        if (noValues(numbers)) return 0.0;
        double max = Iterables.getFirst(numbers, 0.0);
        for (Double d : numbers) {
            max = Math.max(max, d);
        }
        return max;
    }

    public static double min(Iterable<Double> numbers) {
        if (noValues(numbers)) return 0.0;
        double min = Iterables.getFirst(numbers, 0.0);
        for (Double d : numbers) {
            min = Math.min(min, d);
        }
        return min;
    }

    public static double ceil(double n) {
        return Math.ceil(n);
    }

    public static double floor(double n) {
        return Math.floor(n);
    }

    @SuppressWarnings("unchecked")
    public static boolean compare(Comparable o1, Comparable o2, String comparator) {
        int comparison = o1.compareTo(o2);
        if (comparator.equals("<")) {
            return comparison < 0;
        } else if (comparator.equals(">")) {
            return comparison > 0;
        } else if (comparator.equals("<=")) {
            return comparison <= 0;
        } else if (comparator.equals(">=")) {
            return comparison >= 0;
        } else if (comparator.equals("==")) {
            return comparison == 0;
        } else if (comparator.equals("!=")) {
            return comparison != 0;
        } else {
            throw new IllegalArgumentException("unknown comparison operation " + comparator);
        }
    }


    public static boolean logicOperator(Boolean b1, Boolean b2, String comparator){
        if (comparator.equals("or")) {
            return b1 || b2;
        } else if (comparator.equals("and")) {
            return b1 && b2;
        }
        else if (comparator.equals("xor")) {
            return b1 ^ b2;
        }
        else {
            throw new IllegalArgumentException("unknown logical operation " );
        }
    }

    public static List<Double> makeNumbers(String s, String separator) {
        if (s == null || s.length() == 0) {
            return ImmutableList.of();
        }
        Iterable<String> parts;
        if (separator == null || separator.isEmpty())
            parts = Splitter.fixedLength(1).split(s);
        else
            parts = Splitter.on(separator).split(s);

        ArrayList<Double> numbers = new ArrayList<Double>();
        for (String part : parts) {
            numbers.add(Double.parseDouble(part));
        }
        return ImmutableList.copyOf(numbers);
    }

    public static List<Double> randomNumbers(long amount, double start, double end, long seed) {
        Random r = MathUtils.randomFromSeed(seed);
        ImmutableList.Builder<Double> numbers = ImmutableList.builder();
        for (int i = 0; i < amount; i++) {
            double v = start + (r.nextDouble() * (end - start));
            numbers.add(v);
        }
        return numbers.build();
    }

    public static long round(double a) {
        return Math.round(a);
    }

    public static List<Double> sample(final long amount, final double start, final double end) {
        if (amount == 0) return ImmutableList.of();
        if (amount == 1) return ImmutableList.of(start + (end - start) / 2);

        // The step is the range divided by amount - 1, because we also want the end value.
        // If I wouldn't use amount - 1, we fall one value short of the end.
        // E.g. if amount = 3 between 0-100, I want 0.0, 50.0, 100.0.
        final double step = (end - start) / (amount - 1);
        ImmutableList.Builder<Double> b = ImmutableList.builder();
        for (long i = 0; i < amount; i++) {
            b.add(start + step * i);
        }
        return b.build();
    }

    public static List<Double> range(final double start, final double end, final double step) {
        if (step == 0 || start == end || (start < end && step < 0) || (start > end && step > 0))
            return ImmutableList.of();
        else {
            return ImmutableList.copyOf(new Iterable<Double>() {
                public Iterator<Double> iterator() {
                    return new RangeIterator(start, end, step);
                }
            });
        }
    }

    public static List<Double> runningTotal(Iterable<Double> numbers) {
        if (noValues(numbers)) return ImmutableList.of(0.0);
        double currentTotal = 0;
        ImmutableList.Builder<Double> b = ImmutableList.builder();
        for (Double d : numbers) {
            b.add(currentTotal);
            currentTotal += d;
        }
        return b.build();
    }

    private static final class RangeIterator implements Iterator<Double> {
        private final double start;
        private final double end;
        private final double step;
        private double next;

        private RangeIterator(double start, double end, double step) {
            this.start = start;
            this.end = end;
            this.step = step;
            this.next = this.start;
        }

        public boolean hasNext() {
            if (step > 0)
                return next < end;
            else
                return next > end;
        }

        public Double next() {
            if (Thread.currentThread().isInterrupted()) throw new RuntimeException("interrupt");
            //if (Thread.interrupted()) throw new RuntimeException("interrupt");
            if (!hasNext())
                throw new NoSuchElementException();
            double result = next;
            next += step;
            return result;
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    public static double radians(double degrees) {
        return Geometry.radians(degrees);
    }

    public static double degrees(double radians) {
        return Geometry.degrees(radians);
    }

    /**
     * Calculate the angle between two points.
     *
     * @param p1 The first point.
     * @param p2 The second point.
     * @return The angle in radians.
     */
    public static double angle(Point p1, Point p2) {
        return Geometry.angle(p1.x, p1.y, p2.x, p2.y);
    }

    /**
     * The distance between two points.
     */
    public static double distance(Point p1, Point p2) {
        return Geometry.distance(p1.x, p1.y, p2.x, p2.y);
    }

    /**
     * The location of a point based on angle and distance.
     */
    public static Point coordinates(Point p, double angle, double distance) {
        double x = p.x + Math.cos(radians(angle)) * distance;
        double y = p.y + Math.sin(radians(angle)) * distance;
        return new Point(x, y);
    }

    /**
     * The reflection of a point through an origin point.
     */
    public static Point reflect(Point p1, Point p2, double angle, double distance) {
        distance *= distance(p1, p2);
        angle += angle(p1, p2);
        return coordinates(p1, angle, distance);
    }

    public static double sin(double n) {
        return Math.sin(n);
    }

    public static double cos(double n) {
        return Math.cos(n);
    }

    public static double pi() {
        return Math.PI;
    }

    public static double e() {
        return Math.E;
    }

    public static double convertRange(double value, double srcMin, double srcMax, double targetMin, double targetMax, String overflowMethod) {
        if (overflowMethod.equals(OVERFLOW_WRAP)) {
            value = srcMin + value % (srcMax - srcMin);
        } else if (overflowMethod.equals(OVERFLOW_MIRROR)) {
            double rest = value % (srcMax - srcMin);
            if ((int) (value / (srcMax - srcMin)) % 2 == 1)
                value = srcMax - rest;
            else
                value = srcMin + rest;
        } else if (overflowMethod.equals(OVERFLOW_CLAMP)) {
            value = clamp(value, srcMin, srcMax);

        }

        // Convert value to 0.0-1.0 range.
        try {
            value = (value - srcMin) / (srcMax - srcMin);
        } catch (ArithmeticException e) {
            value = srcMin;
        }

        // Convert value to target range.
        return targetMin + value * (targetMax - targetMin);
    }

    public static double wave(double min, double max, double period, double offset, String waveType) {
        float fmin = (float) min;
        float fmax = (float) max;
        float fperiod = (float) period;

        AbstractWave wave;
        if (waveType.equals(WAVE_TRIANGLE))
            wave = TriangleWave.from(fmin, fmax, fperiod);
        else if (waveType.equals(WAVE_SQUARE))
            wave = SquareWave.from(fmin, fmax, fperiod);
        else if (waveType.equals(WAVE_SAWTOOTH))
            wave = SawtoothWave.from(fmin, fmax, fperiod);
        else
            wave = SineWave.from(fmin, fmax, fperiod);
        return wave.getValueAt((float) offset);
    }

}
TOP

Related Classes of nodebox.function.MathFunctions$RangeIterator

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.