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