// Copyright 2003, SLAC, Stanford, U.S.A.
package org.freehep.util;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
import org.geogebra.common.util.debug.Log;
/**
* 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,v 1.5 2008-10-23 19:04:04 hohenwarter Exp $
*/
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;
}
@Override
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);
Log.debug(" 0 results in " + da.getAngle(0));
Log.debug(" 1 results in " + da.getAngle(1));
Log.debug(" 5 results in " + da.getAngle(5));
Log.debug(" 80 results in " + da.getAngle(80));
Log.debug(" 90 results in " + da.getAngle(90));
Log.debug("170 results in " + da.getAngle(170));
Log.debug("185 results in " + da.getAngle(185));
Log.debug("186 results in " + da.getAngle(186));
Log.debug("231 results in " + da.getAngle(231));
Log.debug("359 results in " + da.getAngle(359));
}
}