// Copyright 2003, SLAC, Stanford, U.S.A.
package org.freehep.util;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* Calculates a discrete angle from an arbitrary angle, based on a set of
* given angles.
*
* The class calculates the angle by dividing 360 degrees into segments
* based on the discrete angles. It then will calculate the closest discrete angle
* for a given angle. Discrete angles can be added and removed.
*
* This class can be used to constrain the mouse movement (or its result) if one
* wants to draw under certain angles only.
*
* @author Mark Donszelmann
* @version $Id: DiscreteAngle.java 8584 2006-08-10 23:06:37Z duns $
*/
public class DiscreteAngle {
private SortedSet angles;
public DiscreteAngle() {
angles = new TreeSet();
}
/**
* Returns the closest angle to any discrete angle in the set. Returns itself
* if the set is empty. Returns the only discrete angle if the set only contains
* one angle.
*/
public double getAngle(double angle) {
if (angles.isEmpty()) return angle;
Iterator i = angles.iterator();
Double prev = (Double)i.next();
if (!i.hasNext()) return prev.doubleValue();
while (i.hasNext()) {
Double cur = (Double)i.next();
double cutoff = (cur.doubleValue() - prev.doubleValue()) / 2.0 + prev.doubleValue();
if (angle <= cutoff) return prev.doubleValue();
prev = cur;
}
return prev.doubleValue();
}
/**
* Adds a discrete angle to the set.
*/
public Double addAngle(double angle) {
Double a = new Double(angle);
angles.add(a);
return a;
}
/**
* Removes a discrete angle from the set.
*/
public boolean removeAngle(double angle) {
for (Iterator i = angles.iterator(); i.hasNext(); ) {
Double r = (Double)i.next();
if (r.doubleValue() == angle) {
return removeAngle(r);
}
}
return false;
}
/**
* Removes a discrete angle from the set.
*/
public boolean removeAngle(Double angle) {
return (angle != null) ? angles.remove(angle) : false;
}
public String toString() {
StringBuffer s = new StringBuffer();
s.append("Angles: ");
for (Iterator i = angles.iterator(); i.hasNext(); ) {
Double r = (Double)i.next();
s.append(r.doubleValue());
if (i.hasNext()) s.append(", ");
}
return s.toString();
}
public static void main(String[] args) {
DiscreteAngle da = new DiscreteAngle();
da.addAngle(0);
da.addAngle(90);
da.addAngle(180);
da.addAngle(270);
da.addAngle(360);
da.addAngle(10);
da.addAngle(190);
System.out.println(" 0 results in "+da.getAngle( 0));
System.out.println(" 1 results in "+da.getAngle( 1));
System.out.println(" 5 results in "+da.getAngle( 5));
System.out.println(" 80 results in "+da.getAngle( 80));
System.out.println(" 90 results in "+da.getAngle( 90));
System.out.println("170 results in "+da.getAngle(170));
System.out.println("185 results in "+da.getAngle(185));
System.out.println("186 results in "+da.getAngle(186));
System.out.println("231 results in "+da.getAngle(231));
System.out.println("359 results in "+da.getAngle(359));
}
}