All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.vergne.downhill.impl.WaveDownhillCollider Maven / Gradle / Ivy

The newest version!
package fr.vergne.downhill.impl;

import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;

import fr.vergne.downhill.DownhillCollider;

/**
 * The {@link WaveDownhillCollider} aims at creating {@link Ball}s by waves: all
 * the {@link Ball}s available at an iteration t are collided (when
 * possible) to create new {@link Ball}s (the ones already known are discarded)
 * for t+1. Then all the {@link Ball}s at t+1 are used
 * to create the ones at t+2, etc. Finally, when no new
 * {@link Ball} is created, the last non-empty wave is returned.
 * 
 * @author Matthieu Vergne 
 * 
 * @param 
 */
public class WaveDownhillCollider implements DownhillCollider {

	private final boolean isOrderIndependent;

	public WaveDownhillCollider() {
		this(false);
	}

	/**
	 * The argument allows to optimize the process by reducing the number of
	 * evaluations: if evaluating two {@link Ball}s b1 and
	 * b2 gives exactly the same result independently of their
	 * order ( areColliding(b1,b2) == areColliding(b2,b1) and
	 * collides(b1,b2) == collides(b2,b1)) then you can switch the
	 * argument to true to evaluate only one order. If the order
	 * matter (or if you don't know), you can set it the argument to
	 * false to ask the evaluation of both the orders. The default
	 * case ({@link #WaveDownhillCollider()}) set the argument to
	 * false.
	 * 
	 * @param isOrderIndependent
	 *            if true, then only one couple of ball (b1, b2) is
	 *            collided, otherwise we also collide (b2, b1).
	 */
	public WaveDownhillCollider(boolean isOrderIndependent) {
		this.isOrderIndependent = isOrderIndependent;
	}

	@Override
	public Collection rolls(Collection balls,
			Collider... colliders) {
		Collection result;
		if (isOrderIndependent) {
			result = rollsIndependent(balls, colliders);
		} else {
			result = rollsDependent(balls, colliders);
		}
		return new ReductionDownhillCollider().rolls(result, colliders);
	}

	public Collection rollsDependent(Collection balls,
			Collider... colliders) {
		Collection oldBalls = null;
		Collection newBalls = new HashSet(balls);
		do {
			oldBalls = newBalls;
			newBalls = new HashSet();
			for (Ball b1 : oldBalls) {
				for (Ball b2 : oldBalls) {
					for (Collider collider : colliders) {
						if (collider.areColliding(b1, b2)) {
							Ball collided = collider.collide(b1, b2);
							newBalls.add(collided);
						} else {
							// not able to merge them
						}
					}
				}
			}
			newBalls.removeAll(oldBalls);
		} while (!newBalls.isEmpty());
		return oldBalls;
	}

	public Collection rollsIndependent(Collection balls,
			Collider... colliders) {
		Collection oldBalls = null;
		Collection newBalls = new HashSet(balls);
		do {
			oldBalls = newBalls;
			newBalls = new HashSet();

			LinkedList remaining = new LinkedList(oldBalls);
			while (!remaining.isEmpty()) {
				Ball b1 = remaining.removeFirst();
				for (Ball b2 : remaining) {
					for (Collider collider : colliders) {
						if (collider.areColliding(b1, b2)) {
							Ball collided = collider.collide(b1, b2);
							newBalls.add(collided);
						} else {
							// not able to merge them
						}
					}
				}
			}
			newBalls.removeAll(oldBalls);
		} while (!newBalls.isEmpty());
		return oldBalls;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy