package net.sf.openrocket.unit; import java.util.ArrayList; public class FixedPrecisionUnit extends Unit { private final double precision; private final String formatString; public FixedPrecisionUnit(String unit, double precision) { this(unit, precision, 1.0); } public FixedPrecisionUnit(String unit, double precision, double multiplier) { super(multiplier, unit); this.precision = precision; int decimals = 0; double p = precision; while ((p - Math.floor(p)) > 0.0000001) { p *= 10; decimals++; } formatString = "%." + decimals + "f"; } @Override public double getNextValue(double value) { return round(value + precision); } @Override public double getPreviousValue(double value) { return round(value - precision); } @Override public double round(double value) { return Math.rint(value/precision)*precision; } @Override public String toString(double value) { return String.format(formatString, this.toUnit(value)); } // TODO: LOW: This is copied from GeneralUnit, perhaps combine @Override public Tick[] getTicks(double start, double end, double minor, double major) { // Convert values start = toUnit(start); end = toUnit(end); minor = toUnit(minor); major = toUnit(major); if (minor <= 0 || major <= 0 || major < minor) { throw new IllegalArgumentException("getTicks called with minor="+minor+" major="+major); } ArrayList<Tick> ticks = new ArrayList<Tick>(); int mod2,mod3,mod4; // Moduli for minor-notable, major-nonnotable, major-notable double minstep; // Find the smallest possible step size double one=1; while (one > minor) one /= 10; while (one < minor) one *= 10; // one is the smallest round-ten that is larger than minor if (one/2 >= minor) { // smallest step is round-five minstep = one/2; mod2 = 2; // Changed later if clashes with major ticks } else { minstep = one; mod2 = 10; // Changed later if clashes with major ticks } // Find step size for major ticks one = 1; while (one > major) one /= 10; while (one < major) one *= 10; if (one/2 >= major) { // major step is round-five, major-notable is next round-ten double majorstep = one/2; mod3 = (int)Math.round(majorstep/minstep); mod4 = mod3*2; } else { // major step is round-ten, major-notable is next round-ten mod3 = (int)Math.round(one/minstep); mod4 = mod3*10; } // Check for clashes between minor-notable and major-nonnotable if (mod3 == mod2) { if (mod2==2) mod2 = 1; // Every minor tick is notable else mod2 = 5; // Every fifth minor tick is notable } // Calculate starting position int pos = (int)Math.ceil(start/minstep); // System.out.println("mod2="+mod2+" mod3="+mod3+" mod4="+mod4); while (pos*minstep <= end) { double unitValue = pos*minstep; double value = fromUnit(unitValue); if (pos%mod4 == 0) ticks.add(new Tick(value,unitValue,true,true)); else if (pos%mod3 == 0) ticks.add(new Tick(value,unitValue,true,false)); else if (pos%mod2 == 0) ticks.add(new Tick(value,unitValue,false,true)); else ticks.add(new Tick(value,unitValue,false,false)); pos++; } return ticks.toArray(new Tick[0]); } }