create changelog entry
[debian/openrocket] / core / src / net / sf / openrocket / unit / FixedPrecisionUnit.java
1 package net.sf.openrocket.unit;
2
3 import java.util.ArrayList;
4
5 public class FixedPrecisionUnit extends Unit {
6         
7         private final double precision;
8         private final String formatString;
9
10         public FixedPrecisionUnit(String unit, double precision) {
11                 this(unit, precision, 1.0);
12         }
13         
14         public FixedPrecisionUnit(String unit, double precision, double multiplier) {
15                 super(multiplier, unit);
16                 
17                 this.precision = precision;
18                 
19                 int decimals = 0;
20                 double p = precision;
21                 while ((p - Math.floor(p)) > 0.0000001) {
22                         p *= 10;
23                         decimals++;
24                 }
25                 formatString = "%." + decimals + "f";
26         }
27         
28
29         @Override
30         public double getNextValue(double value) {
31                 return round(value + precision);
32         }
33
34         @Override
35         public double getPreviousValue(double value) {
36                 return round(value - precision);
37         }
38
39
40         @Override
41         public double round(double value) {
42                 return Math.rint(value/precision)*precision;
43         }
44
45         
46         
47
48         @Override
49         public String toString(double value) {
50                 return String.format(formatString, this.toUnit(value));
51         }
52         
53         
54         
55         // TODO: LOW: This is copied from GeneralUnit, perhaps combine
56         @Override
57         public Tick[] getTicks(double start, double end, double minor, double major) {
58                 // Convert values
59                 start = toUnit(start);
60                 end = toUnit(end);
61                 minor = toUnit(minor);
62                 major = toUnit(major);
63                 
64                 if (minor <= 0 || major <= 0 || major < minor) {
65                         throw new IllegalArgumentException("getTicks called with minor="+minor+" major="+major);
66                 }
67                 
68                 ArrayList<Tick> ticks = new ArrayList<Tick>();
69                 
70                 int mod2,mod3,mod4;  // Moduli for minor-notable, major-nonnotable, major-notable
71                 double minstep;
72
73                 // Find the smallest possible step size
74                 double one=1;
75                 while (one > minor)
76                         one /= 10;
77                 while (one < minor)
78                         one *= 10;
79                 // one is the smallest round-ten that is larger than minor
80                 if (one/2 >= minor) {
81                         // smallest step is round-five
82                         minstep = one/2;
83                         mod2 = 2;  // Changed later if clashes with major ticks
84                 } else {
85                         minstep = one;
86                         mod2 = 10;  // Changed later if clashes with major ticks
87                 }
88                 
89                 // Find step size for major ticks
90                 one = 1;
91                 while (one > major)
92                         one /= 10;
93                 while (one < major)
94                         one *= 10;
95                 if (one/2 >= major) {
96                         // major step is round-five, major-notable is next round-ten
97                         double majorstep = one/2;
98                         mod3 = (int)Math.round(majorstep/minstep);
99                         mod4 = mod3*2;
100                 } else {
101                         // major step is round-ten, major-notable is next round-ten
102                         mod3 = (int)Math.round(one/minstep);
103                         mod4 = mod3*10;
104                 }
105                 // Check for clashes between minor-notable and major-nonnotable
106                 if (mod3 == mod2) {
107                         if (mod2==2)
108                                 mod2 = 1;  // Every minor tick is notable
109                         else
110                                 mod2 = 5;  // Every fifth minor tick is notable
111                 }
112
113
114                 // Calculate starting position
115                 int pos = (int)Math.ceil(start/minstep);
116 //              System.out.println("mod2="+mod2+" mod3="+mod3+" mod4="+mod4);
117                 while (pos*minstep <= end) {
118                         double unitValue = pos*minstep;
119                         double value = fromUnit(unitValue);
120                         
121                         if (pos%mod4 == 0)
122                                 ticks.add(new Tick(value,unitValue,true,true));
123                         else if (pos%mod3 == 0)
124                                 ticks.add(new Tick(value,unitValue,true,false));
125                         else if (pos%mod2 == 0)
126                                 ticks.add(new Tick(value,unitValue,false,true));
127                         else
128                                 ticks.add(new Tick(value,unitValue,false,false));
129                         
130                         pos++;
131                 }
132                 
133                 return ticks.toArray(new Tick[0]);
134         }
135         
136         
137 }