1 package org.opentrafficsim.graphs;
2
3 import java.awt.Color;
4 import java.awt.Paint;
5
6 import org.jfree.chart.renderer.PaintScale;
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 public class ContinuousColorPaintScale implements PaintScale
22 {
23
24 private double[] bounds;
25
26
27 private Color[] boundColors;
28
29
30 private final String format;
31
32
33
34
35
36
37
38 ContinuousColorPaintScale(final String format, final double[] bounds, final Color[] boundColors)
39 {
40 this.format = format;
41 if (bounds.length < 2)
42 {
43 throw new Error("bounds must have >= 2 entries");
44 }
45 if (bounds.length != boundColors.length)
46 {
47 throw new Error("bounds must have same length as boundColors");
48 }
49 this.bounds = new double[bounds.length];
50 this.boundColors = new Color[bounds.length];
51
52
53 for (int nextBound = 0; nextBound < bounds.length; nextBound++)
54 {
55
56 double currentLowest = Double.POSITIVE_INFINITY;
57 int bestIndex = -1;
58 int index;
59 for (index = 0; index < bounds.length; index++)
60 {
61 if (bounds[index] < currentLowest && (nextBound == 0 || bounds[index] > this.bounds[nextBound - 1]))
62 {
63 bestIndex = index;
64 currentLowest = bounds[index];
65 }
66 }
67 if (bestIndex < 0)
68 {
69 throw new Error("duplicate value in bounds");
70 }
71 this.bounds[nextBound] = bounds[bestIndex];
72 this.boundColors[nextBound] = boundColors[bestIndex];
73 }
74 }
75
76
77 @Override
78 public final double getLowerBound()
79 {
80 return this.bounds[0];
81 }
82
83
84
85
86
87
88
89
90
91
92 private static int mixComponent(final double ratio, final int low, final int high)
93 {
94 final double mix = low * (1 - ratio) + high * ratio;
95 int result = (int) mix;
96 if (result < 0)
97 {
98 result = 0;
99 }
100 if (result > 255)
101 {
102 result = 255;
103 }
104 return result;
105 }
106
107
108 @Override
109 public final Paint getPaint(final double value)
110 {
111 int bucket;
112 for (bucket = 0; bucket < this.bounds.length - 1; bucket++)
113 {
114 if (value < this.bounds[bucket + 1])
115 {
116 break;
117 }
118 }
119 if (bucket >= this.bounds.length - 1)
120 {
121 bucket = this.bounds.length - 2;
122 }
123 final double ratio = (value - this.bounds[bucket]) / (this.bounds[bucket + 1] - this.bounds[bucket]);
124 Color mix =
125 new Color(mixComponent(ratio, this.boundColors[bucket].getRed(), this.boundColors[bucket + 1].getRed()),
126 mixComponent(ratio, this.boundColors[bucket].getGreen(), this.boundColors[bucket + 1].getGreen()),
127 mixComponent(ratio, this.boundColors[bucket].getBlue(), this.boundColors[bucket + 1].getBlue()));
128 return mix;
129 }
130
131
132 @Override
133 public final double getUpperBound()
134 {
135 return this.bounds[this.bounds.length - 1];
136 }
137
138
139
140
141
142 public final String getFormat()
143 {
144 return this.format;
145 }
146
147 }