package org.andork.unit;
import java.util.HashMap;
import java.util.Map;
import java.util.function.DoubleUnaryOperator;
public class Angle extends UnitType<Angle> {
private static class AngleUnit extends Unit<Angle> {
private final DoubleUnaryOperator toRadians;
private final DoubleUnaryOperator fromRadians;
public AngleUnit(Angle type, String id, DoubleUnaryOperator toRadians, DoubleUnaryOperator fromRadians) {
super(type, id);
this.toRadians = toRadians;
this.fromRadians = fromRadians;
}
}
public static final Angle type;
public static final AngleUnit degrees;
public static final AngleUnit radians;
public static final AngleUnit gradians;
public static final AngleUnit percentGrade;
public static final AngleUnit milsNATO;
private static final Map<Unit<Angle>, Map<Unit<Angle>, Double>> doubleConversions = new HashMap<>();
static {
type = new Angle();
type.addUnit(degrees = new AngleUnit(type, "deg",
angle -> Math.PI * angle / 180.0,
angle -> angle * 180.0 / Math.PI));
type.addUnit(radians = new AngleUnit(type, "rad",
DoubleUnaryOperator.identity(),
DoubleUnaryOperator.identity()));
type.addUnit(gradians = new AngleUnit(type, "grad",
angle -> Math.PI * angle / 200.0,
angle -> angle * 200.0 / Math.PI));
type.addUnit(percentGrade = new AngleUnit(type, "% grade",
angle -> Math.atan(angle / 100.0),
angle -> Math.tan(angle) * 100));
type.addUnit(milsNATO = new AngleUnit(type, "mil",
angle -> Math.PI * angle / 3200.0,
angle -> 3200.0 * angle / Math.PI));
Map<Unit<Angle>, Double> degreeConversions = new HashMap<>();
degreeConversions.put(radians, Math.PI / 180.0);
degreeConversions.put(gradians, 400.0 / 360.0);
doubleConversions.put(degrees, degreeConversions);
Map<Unit<Angle>, Double> radianConversions = new HashMap<>();
radianConversions.put(degrees, 180.0 / Math.PI);
radianConversions.put(gradians, 200.0 / Math.PI);
doubleConversions.put(radians, radianConversions);
Map<Unit<Angle>, Double> gradianConversions = new HashMap<>();
gradianConversions.put(degrees, 360.0 / 400.0);
gradianConversions.put(radians, Math.PI / 200.0);
doubleConversions.put(gradians, gradianConversions);
/**
* Add identity conversions
*/
for (Unit<Angle> unit : type.units()) {
Map<Unit<Angle>, Double> conv = doubleConversions.get(unit);
if (conv != null) {
conv.put(unit, 1.0);
}
}
}
public static void main(String[] args) {
System.out.println(type.convert(360.0, degrees, radians));
System.out.println(type.convert(Math.PI * 2, radians, degrees));
System.out.println(type.convert(400.0, gradians, degrees));
System.out.println(type.convert(400.0, gradians, radians));
}
private Angle() {
}
@Override
public double convert(double d, Unit<Angle> from, Unit<Angle> to) {
Map<Unit<Angle>, Double> subMap = doubleConversions.get(from);
if (subMap != null) {
Double ratio = subMap.get(to);
if (ratio != null) {
return d * ratio;
}
}
return ((AngleUnit) to).fromRadians.applyAsDouble(((AngleUnit) from).toRadians.applyAsDouble(d));
}
}