1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.cosylab.gui.components.range2;
21
22 import java.util.ArrayList;
23
24
25
26
27
28
29
30
31
32
33 public class ManualTickCalculator implements TickCalculator {
34
35 private double[] majorTicks = null;
36 private double[] labels = null;
37 private double minor = 0;
38
39
40
41
42
43 public ManualTickCalculator() {
44
45 }
46
47
48
49
50
51
52
53
54 public ManualTickCalculator(double[] majorTicks, double[] labels, double minor) {
55 this.majorTicks = majorTicks;
56 this.labels = labels;
57 this.minor = minor;
58
59 }
60
61
62
63
64
65
66
67 public void setLabels(double[] labels) {
68 this.labels = labels;
69 }
70
71
72
73
74
75
76 public void setMajorTicks(double[] majorTicks) {
77 this.majorTicks = majorTicks;
78 }
79
80
81
82
83
84
85 public void setMinor(double minor) {
86 this.minor = minor;
87 }
88
89
90
91
92
93
94 public double[] getLabels() {
95 return labels;
96 }
97
98
99
100
101
102
103 public double[] getMajorTicks() {
104 return majorTicks;
105 }
106
107
108
109
110
111 public double getMinor() {
112 return minor;
113 }
114
115 private String getLabel(double d, TickParameters measurer) {
116 if (this.labels == null) return "";
117 for (int i = 0; i < labels.length; i++) {
118 if (labels[i] == d) return measurer.formatNumber(d);
119 }
120 return "";
121 }
122
123
124
125
126
127 public Tick[] calculateTicks(int length, Range range, RangedValue rangedValue) {
128 return calculateTicks(length, new DefaultTickParameters(), range, rangedValue);
129 }
130
131 private double getMinimumMajorTick(double limit) {
132 if (majorTicks.length == 0) return Double.NaN;
133 double min = majorTicks[0];
134 for (int i = 1; i < majorTicks.length; i++) {
135 if (majorTicks[i] < limit) continue;
136 min = Math.min(min, majorTicks[i]);
137 }
138 return Math.max(min, limit);
139 }
140
141 private double getMinorStep(double min, double max, int majorCount) {
142 if (minor != 0) return minor;
143 else if (majorCount == 0) return (max-min)/2.;
144 else return (max-min)/majorCount/5.;
145 }
146
147
148
149
150
151 public Tick[] calculateTicks(int spaceLength, TickParameters measurer, Range range, RangedValue rangedValue) {
152 if (this.majorTicks == null || this.majorTicks.length == 0) return new Tick[0];
153 if (measurer == null) measurer = new DefaultTickParameters();
154 int length = majorTicks.length;
155
156
157 double rMax = rangedValue.getMaximum();
158 double rMin = rangedValue.getMinimum();
159 double mMin = getMinimumMajorTick(rMin);
160 double minor = getMinorStep(rMin, rMax, length);
161 int num = (int)((rMax - mMin)/minor);
162 int n2 = 0;
163 if (rMin < mMin) {
164 n2 = (int)((mMin-rMin)/minor);
165 }
166
167 ArrayList<Tick> ticks;
168 if (length + num + n2 < 0 || length + num + n2 > 1000000) {
169 throw new IllegalStateException("Number of minor ticks is too large. Adjust the minor step.");
170 } else {
171 ticks = new ArrayList<Tick>(length + num + n2);
172 }
173
174 for (int i = n2 -1; i >= 0 ; i--) {
175 ticks.add(new Tick(mMin - (i+1)*minor, range.toRelative(mMin - (i+1)*minor, rangedValue), false, ""));
176 }
177
178 for (int i = n2; i < n2 + num; i++) {
179 ticks.add(new Tick(mMin + (i-n2 + 1) *minor, range.toRelative(mMin + (i-n2 + 1)*minor, rangedValue), false, ""));
180 }
181
182 for (int i = n2 + num; i < length + num + n2; i++) {
183 if (majorTicks[i - num - n2] > rMax || majorTicks[i - num - n2] < rMin) continue;
184 ticks.add(new Tick(majorTicks[i - num-n2], range.toRelative(majorTicks[i - num-n2], rangedValue), true, getLabel(majorTicks[i-num-n2], measurer)));
185 }
186
187 return ticks.toArray(new Tick[ticks.size()]);
188 }
189
190 public static void main(String[] args) {
191 double[] vals = new double[]{0,5,10,15};
192 double[] lab = new double[]{5,15};
193 ManualTickCalculator pr = new ManualTickCalculator(vals,lab,4);
194 Tick[] t = pr.calculateTicks(0, new LinearRange(), new RangedValue(0,15,3));
195 for (int i = 0; i < t.length; i++) {
196 System.out.println(t[i]);
197 }
198 }
199 }