Package ca.eandb.jmist.framework.random

Source Code of ca.eandb.jmist.framework.random.RandomUtil

/**
* Java Modular Image Synthesis Toolkit (JMIST)
* Copyright (C) 2008-2013 Bradley W. Kimmel
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package ca.eandb.jmist.framework.random;

import ca.eandb.jmist.framework.Random;
import ca.eandb.jmist.math.Box2;
import ca.eandb.jmist.math.Box3;
import ca.eandb.jmist.math.Interval;
import ca.eandb.jmist.math.MathUtil;
import ca.eandb.jmist.math.Point2;
import ca.eandb.jmist.math.Point3;
import ca.eandb.jmist.math.PolarCoordinates;
import ca.eandb.jmist.math.SphericalCoordinates;
import ca.eandb.jmist.math.Vector2;
import ca.eandb.jmist.math.Vector3;


/**
* Static utility methods for random algorithms.
* @author Brad Kimmel
*/
public final class RandomUtil {

  public static SphericalCoordinates diffuse(Random random) {
    return diffuse(random.next(), random.next());
  }

  public static SphericalCoordinates diffuse(double ru, double rv) {

    assert(0.0 <= ru && ru <= 1.0);
    assert(0.0 <= rv && rv <= 1.0);

    return new SphericalCoordinates(
        Math.acos(Math.sqrt(1.0 - ru)),
        2.0 * Math.PI * rv
    );

  }

  public static SphericalCoordinates uniformOnUpperHemisphere(Random random) {
    return uniformOnUpperHemisphere(1.0, random.next(), random.next());
  }

  public static SphericalCoordinates uniformOnUpperHemisphere(double radius, Random random) {
    return uniformOnUpperHemisphere(radius, random.next(), random.next());
  }

  public static SphericalCoordinates uniformOnUpperHemisphere(double radius, double ru, double rv) {

    // TODO implement this directly so it's more efficient.
    SphericalCoordinates result = uniformOnSphere(radius, ru, rv);

    if (result.polar() > (Math.PI / 2.0))
      result = new SphericalCoordinates(Math.PI - result.polar(), result.azimuthal(), radius);

    return result;

  }

  public static SphericalCoordinates uniformOnSphere(Random random) {
    return uniformOnSphere(1.0, random.next(), random.next());
  }

  public static SphericalCoordinates uniformOnSphere(double radius, Random random) {
    return uniformOnSphere(radius, random.next(), random.next());
  }

  public static SphericalCoordinates uniformOnSphere(double ru, double rv) {
    return uniformOnSphere(1.0, ru, rv);
  }

  public static SphericalCoordinates uniformOnSphere(double radius, double ru, double rv) {

    assert(0.0 <= ru && ru <= 1.0);
    assert(0.0 <= rv && rv <= 1.0);

    return new SphericalCoordinates(
        Math.acos(2.0 * ru - 1.0),
        2.0 * Math.PI * rv,
        radius
    );

  }

  public static SphericalCoordinates uniformInsideSphere(Random random) {
    return uniformInsideSphere(1.0, random.next(), random.next(), random.next());
  }

  public static SphericalCoordinates uniformInsideSphere(double radius, Random random) {
    return uniformInsideSphere(radius, random.next(), random.next(), random.next());
  }

  public static SphericalCoordinates uniformInsideSphere(double ru, double rv, double rw) {
    return uniformInsideSphere(1.0, ru, rv, rw);
  }

  public static SphericalCoordinates uniformInsideSphere(double radius, double ru, double rv, double rw) {

    assert(0.0 <= ru && ru <= 1.0);
    assert(0.0 <= rv && rv <= 1.0);
    assert(0.0 <= rw && rw <= 1.0);

    return new SphericalCoordinates(
        Math.acos(2.0 * ru - 1.0),
        2.0 * Math.PI * rv,
        radius * Math.cbrt(rw)
    );

  }

  public static PolarCoordinates uniformOnDisc(Random random) {
    return uniformOnDisc(1.0, random.next(), random.next());
  }

  public static PolarCoordinates uniformOnDisc(double radius, Random random) {
    return uniformOnDisc(radius, random.next(), random.next());
  }

  public static PolarCoordinates uniformOnDisc(double ru, double rv) {
    return uniformOnDisc(1.0, ru, rv);
  }

  public static PolarCoordinates uniformOnDisc(double radius, double ru, double rv) {

    assert(0.0 <= ru && ru <= 1.0);
    assert(0.0 <= rv && rv <= 1.0);

    return new PolarCoordinates(
        2.0 * Math.PI * ru,
        radius * Math.sqrt(rv)
    );

  }

  public static Point3 uniformOnTriangle(Point3 a, Point3 b, Point3 c, Random random) {
    return uniformOnTriangle(a, b, c, random.next(), random.next());
  }

  public static Point3 uniformOnTriangle(Point3 a, Point3 b, Point3 c, double alpha, double beta) {
    if (alpha + beta > 1.0) {
      alpha = 1.0 - alpha;
      beta = 1.0 - beta;
    }
    Vector3 ab = a.vectorTo(b).times(alpha);
    Vector3 ac = a.vectorTo(c).times(beta);
    return a.plus(ab).plus(ac);
  }

  public static Point2 uniformOnTriangle(Point2 a, Point2 b, Point2 c, Random random) {
    return uniformOnTriangle(a, b, c, random.next(), random.next());
  }

  public static Point2 uniformOnTriangle(Point2 a, Point2 b, Point2 c, double alpha, double beta) {
    if (alpha + beta > 1.0) {
      alpha = 1.0 - alpha;
      beta = 1.0 - beta;
    }
    Vector2 ab = a.vectorTo(b).times(alpha);
    Vector2 ac = a.vectorTo(c).times(beta);
    return a.plus(ab).plus(ac);
  }

  public static boolean bernoulli(double probability, Random random) {
    return bernoulli(probability, random.next());
  }

  public static boolean bernoulli(double probability, double seed) {
    return seed < probability;
  }

  private static void bp() {}

  public static boolean bernoulli(double probability, SeedReference ref) {
    if (ref.seed < probability) {
      ref.seed /= probability;
      if (ref.seed < 0.0 || ref.seed > 1.0) bp();
      return true;
    } else {
      ref.seed = (ref.seed - probability) / (1.0 - probability);
      if (ref.seed < 0.0 || ref.seed > 1.0) bp();
      return false;
    }
  }

  public static boolean coin(Random random) {
    return coin(random.next());
  }

  public static boolean coin(double seed) {
    return seed < 0.5;
  }

  public static boolean coin(SeedReference ref) {
    if (ref.seed < 0.5) {
      ref.seed *= 2;
      if (ref.seed < 0.0 || ref.seed > 1.0) bp();
      return true;
    } else {
      ref.seed = (ref.seed * 2) - 1;
      if (ref.seed < 0.0 || ref.seed > 1.0) bp();
      return false;
    }
  }

  public static int categorical(double[] weights, Random random) {
    return categorical(weights, random.next());
  }

  public static int categorical(double[] weights, double seed) {

    double  x    = seed * MathUtil.sum(weights);
    double  mark  = 0.0;

    for (int i = 0; i < weights.length; i++) {
      if (x < (mark += weights[i])) {
        return i;
      }
    }

    return weights.length - 1;

  }

  public static int categorical(double[] weights, SeedReference ref) {

    ref.seed *= MathUtil.sum(weights);

    int n = weights.length - 1;
    for (int i = 0; i < n; i++) {
      if (ref.seed < weights[i]) {
        ref.seed /= weights[i];
        if (ref.seed < 0.0 || ref.seed > 1.0) bp();
        return i;
      }
      ref.seed -= weights[i];
    }

    ref.seed /= weights[n];
    if (ref.seed < 0.0 || ref.seed > 1.0) bp();
    return n;

  }

  public static int discrete(int minimum, int maximum, Random random) {
    return discrete(minimum, maximum, random.next());
  }

  public static int discrete(int minimum, int maximum, double seed) {
    return minimum + (int) Math.floor(seed * (double) (maximum - minimum + 1));
  }

  public static int discrete(int minimum, int maximum, SeedReference ref) {
    double offset;

    ref.seed *= (double) (maximum - minimum + 1);
    offset = Math.floor(ref.seed);
    ref.seed -= offset;

    if (ref.seed < 0.0 || ref.seed > 1.0) bp();
    return minimum + (int) offset;
  }

  public static double canonical(Random random) {
    return random.next();
  }

  public static Point2 canonical2(Random random) {
    return new Point2(random.next(), random.next());
  }

  public static Point3 canonical3(Random random) {
    return new Point3(random.next(), random.next(), random.next());
  }

  public static double uniform(double minimum, double maximum, double seed) {
    return minimum + seed * (maximum - minimum);
  }

  public static double uniform(double minimum, double maximum, Random random) {
    return uniform(minimum, maximum, random.next());
  }

  public static double uniform(Interval I, Random random) {
    return uniform(I, random.next());
  }

  public static double uniform(Interval I, double seed) {
    return uniform(I.minimum(), I.maximum(), seed);
  }

  public static Point2 uniform(Box2 box, Random random) {
    return uniform(box, random.next(), random.next());
  }

  public static Point2 uniform(Box2 box, double ru, double rv) {
    return new Point2(
        uniform(box.minimumX(), box.maximumX(), ru),
        uniform(box.minimumY(), box.maximumY(), rv));
  }

  public static Point3 uniform(Box3 box, Random random) {
    return uniform(box, random.next(), random.next(), random.next());
  }

  public static Point3 uniform(Box3 box, double ru, double rv, double rw) {
    return new Point3(
        uniform(box.minimumX(), box.maximumX(), ru),
        uniform(box.minimumY(), box.maximumY(), rv),
        uniform(box.minimumZ(), box.maximumZ(), rw));
  }

}
TOP

Related Classes of ca.eandb.jmist.framework.random.RandomUtil

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.