mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-02 18:33:54 +00:00
replaced the broken calculation of distinct colors in the colormap with a HSV color schema based method
This commit is contained in:
1 parent
856aa593be
commit
3d6ea70ed6
4 files changed
+223
-42
No files matched your search
@@ -1,10 +1,13 @@
|
||||
package com.sap.sailing.domain.common;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.common.impl.Util;
|
||||
|
||||
public interface Color extends Serializable {
|
||||
Util.Triple<Integer, Integer, Integer> getAsRGB();
|
||||
|
||||
Util.Triple<Float, Float, Float> getAsHSV();
|
||||
|
||||
String getAsHtml();
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
package com.sap.sailing.domain.common.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.Color;
|
||||
import com.sap.sailing.domain.common.impl.Util.Triple;
|
||||
|
||||
/**
|
||||
* A color defined in the HSV color schema (hue, saturation, brightness) Hue is a degree between 0.0 and 360.0
|
||||
* Saturation is between 0.0 and 1.0 Brightness is between 0.0 and 1.0
|
||||
*
|
||||
* @author Frank
|
||||
*/
|
||||
public class HSVColor implements Color {
|
||||
private static final long serialVersionUID = 7602013229606352246L;
|
||||
|
||||
float hue;
|
||||
float saturation;
|
||||
float brightness;
|
||||
|
||||
HSVColor() {
|
||||
} // for GWT serializability
|
||||
|
||||
public HSVColor(float hue, float saturation, float brightness) {
|
||||
this.hue = ensureValidRange(hue, 360.0f);
|
||||
this.saturation = ensureValidRange(saturation, 1.0f);
|
||||
this.brightness = ensureValidRange(brightness, 1.0f);
|
||||
}
|
||||
|
||||
private float ensureValidRange(float value, float maxValue) {
|
||||
float result = value;
|
||||
if (value < 0.0f) {
|
||||
result = 0.0f;
|
||||
} else if (value > maxValue) {
|
||||
result = maxValue;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Triple<Integer, Integer, Integer> getAsRGB() {
|
||||
float r, b, g;
|
||||
|
||||
if (saturation == 0) {
|
||||
r = g = b = brightness;
|
||||
} else {
|
||||
float h = hue / 60.0f; // sector 0 to 5
|
||||
int i = (int) Math.floor(h);
|
||||
float f = h - i; // factorial part of h
|
||||
float p = brightness * (1 - saturation);
|
||||
float q = brightness * (1 - saturation * f);
|
||||
float t = brightness * (1 - saturation * (1 - f));
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
r = brightness;
|
||||
g = t;
|
||||
b = p;
|
||||
break;
|
||||
case 1:
|
||||
r = q;
|
||||
g = brightness;
|
||||
b = p;
|
||||
break;
|
||||
case 2:
|
||||
r = p;
|
||||
g = brightness;
|
||||
b = t;
|
||||
break;
|
||||
case 3:
|
||||
r = p;
|
||||
g = q;
|
||||
b = brightness;
|
||||
break;
|
||||
case 4:
|
||||
r = t;
|
||||
g = p;
|
||||
b = brightness;
|
||||
break;
|
||||
default: // case 5:
|
||||
r = brightness;
|
||||
g = p;
|
||||
b = q;
|
||||
}
|
||||
}
|
||||
Triple<Integer, Integer, Integer> RGBColor = new Triple<Integer, Integer, Integer>(Math.round(r * 255),
|
||||
Math.round(g * 255), Math.round(b * 255));
|
||||
return RGBColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsHtml() {
|
||||
Triple<Integer, Integer, Integer> asRGB = getAsRGB();
|
||||
return "#" + toBrowserHexValue(asRGB.getA()) + toBrowserHexValue(asRGB.getB())
|
||||
+ toBrowserHexValue(asRGB.getC());
|
||||
}
|
||||
|
||||
private static String toBrowserHexValue(int number) {
|
||||
StringBuilder builder = new StringBuilder(Integer.toHexString(number & 0xff));
|
||||
while (builder.length() < 2) {
|
||||
builder.append("0");
|
||||
}
|
||||
return builder.toString().toUpperCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Triple<Float, Float, Float> getAsHSV() {
|
||||
return new Triple<Float, Float, Float>(hue, saturation, brightness);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HSVColor [hue=" + hue + ", saturation=" + saturation + ", brightness=" + brightness + "]";
|
||||
}
|
||||
|
||||
public float getHue() {
|
||||
return hue;
|
||||
}
|
||||
|
||||
public float getSaturation() {
|
||||
return saturation;
|
||||
}
|
||||
|
||||
public float getBrightness() {
|
||||
return brightness;
|
||||
}
|
||||
}
|
||||
+62
-6
@@ -3,16 +3,20 @@ package com.sap.sailing.domain.common.impl;
|
||||
import com.sap.sailing.domain.common.Color;
|
||||
import com.sap.sailing.domain.common.impl.Util.Triple;
|
||||
|
||||
/**
|
||||
* A color defined in the RGB color schema
|
||||
* @author Frank
|
||||
*/
|
||||
public class RGBColor implements Color {
|
||||
private static final long serialVersionUID = -4091876840771631308L;
|
||||
private int red;
|
||||
private int green;
|
||||
private int blue;
|
||||
|
||||
RGBColor() {} // for GWT serializability
|
||||
|
||||
|
||||
RGBColor() {
|
||||
} // for GWT serializability
|
||||
|
||||
public RGBColor(int red, int green, int blue) {
|
||||
super();
|
||||
this.red = ensureValidRange(red);
|
||||
this.green = ensureValidRange(green);
|
||||
this.blue = ensureValidRange(blue);
|
||||
@@ -33,11 +37,52 @@ public class RGBColor implements Color {
|
||||
return new Triple<Integer, Integer, Integer>(red, green, blue);
|
||||
}
|
||||
|
||||
public Triple<Float, Float, Float> getAsHSV() {
|
||||
float hue, saturation, brightness;
|
||||
int cmax = (red > green) ? red : green;
|
||||
if (blue > cmax) {
|
||||
cmax = blue;
|
||||
}
|
||||
int cmin = (red < green) ? red : green;
|
||||
if (blue < cmin) {
|
||||
cmin = blue;
|
||||
}
|
||||
|
||||
brightness = ((float) cmax) / 255.0f;
|
||||
if (cmax != 0) {
|
||||
saturation = ((float) (cmax - cmin)) / ((float) cmax);
|
||||
} else {
|
||||
saturation = 0;
|
||||
}
|
||||
if (saturation == 0) {
|
||||
hue = 0;
|
||||
}
|
||||
else {
|
||||
float redc = ((float) (cmax - red)) / ((float) (cmax - cmin));
|
||||
float greenc = ((float) (cmax - green)) / ((float) (cmax - cmin));
|
||||
float bluec = ((float) (cmax - blue)) / ((float) (cmax - cmin));
|
||||
if (red == cmax) {
|
||||
hue = bluec - greenc;
|
||||
} else if (green == cmax) {
|
||||
hue = 2.0f + redc - bluec;
|
||||
} else {
|
||||
hue = 4.0f + greenc - redc;
|
||||
}
|
||||
hue = hue / 6.0f;
|
||||
if (hue < 0) {
|
||||
hue = hue + 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
Triple<Float, Float, Float> HSVColor = new Triple<Float, Float, Float>(hue, saturation, brightness);
|
||||
return HSVColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsHtml() {
|
||||
return "#" + toBrowserHexValue(red) + toBrowserHexValue(green) + toBrowserHexValue(blue);
|
||||
}
|
||||
|
||||
|
||||
private static String toBrowserHexValue(int number) {
|
||||
StringBuilder builder = new StringBuilder(Integer.toHexString(number & 0xff));
|
||||
while (builder.length() < 2) {
|
||||
@@ -73,10 +118,21 @@ public class RGBColor implements Color {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getAsHtml();
|
||||
}
|
||||
|
||||
public int getRed() {
|
||||
return red;
|
||||
}
|
||||
|
||||
public int getGreen() {
|
||||
return green;
|
||||
}
|
||||
|
||||
public int getBlue() {
|
||||
return blue;
|
||||
}
|
||||
}
|
||||
+33
-36
@@ -2,20 +2,34 @@ package com.sap.sailing.gwt.ui.client;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.sap.sailing.domain.common.impl.HSVColor;
|
||||
|
||||
/**
|
||||
* Manages color assignments to objects.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
* @param <T> the type of the objects to which a color is assigned
|
||||
*
|
||||
* @param <T>
|
||||
* the type of the objects to which a color is assigned
|
||||
*/
|
||||
public class ColorMap<T> {
|
||||
private final HashMap<T, String> idColor;
|
||||
|
||||
|
||||
private int colorCounter;
|
||||
|
||||
|
||||
private HSVColor[] baseColors;
|
||||
|
||||
public ColorMap() {
|
||||
baseColors = new HSVColor[8];
|
||||
baseColors[0] = new HSVColor(0.0f, 1.0f, 1.0f); // Red
|
||||
baseColors[1] = new HSVColor(30.0f, 1.0f, 1.0f); // Orange
|
||||
baseColors[2] = new HSVColor(60.f, 1.0f, 1.0f); // Yellow
|
||||
baseColors[3] = new HSVColor(120.0f, 1.0f, 1.0f); // Green
|
||||
baseColors[4] = new HSVColor(180.0f, 1.0f, 1.0f); // Cyan
|
||||
baseColors[5] = new HSVColor(240.0f, 1.0f, 1.0f); // Blue
|
||||
baseColors[6] = new HSVColor(240.0f, 1.0f, 1.0f); // Pink
|
||||
baseColors[7] = new HSVColor(300.0f, 1.0f, 1.0f); // Magenta
|
||||
|
||||
idColor = new HashMap<T, String>();
|
||||
}
|
||||
|
||||
@@ -26,15 +40,15 @@ public class ColorMap<T> {
|
||||
* An ID unique for a competitor.
|
||||
* @return A color in hex/html-format (e.g. #ff0000)
|
||||
*/
|
||||
public String getColorByID(T object){
|
||||
public String getColorByID(T object) {
|
||||
String color = idColor.get(object);
|
||||
if (color == null || color.isEmpty()){
|
||||
color = createHexColor(colorCounter++);
|
||||
idColor.put(object, color);
|
||||
if (color == null || color.isEmpty()) {
|
||||
color = createHexColor(colorCounter++);
|
||||
idColor.put(object, color);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Only use this if you don't want the color to be cached.
|
||||
*
|
||||
@@ -42,32 +56,15 @@ public class ColorMap<T> {
|
||||
* The index of e.g. a competitor. Make sure, that each competitor has a unique index.
|
||||
* @return A color computed using the {@code index}.
|
||||
*/
|
||||
private String createHexColor(int index){
|
||||
String rs, gs, bs;
|
||||
int r = 0, g = 0, b = 0;
|
||||
double factor = 1 - ((index/6)/6.0);
|
||||
if (index%6 < 2 || index%6 > 4){
|
||||
r = (int) (255*factor);
|
||||
}
|
||||
rs = Integer.toHexString(r);
|
||||
while(rs.length() < 2){
|
||||
rs = "0" + rs;
|
||||
}
|
||||
if (index%6 > 0 && index%6 < 4){
|
||||
g = (int) (220*factor);
|
||||
}
|
||||
gs = Integer.toHexString(g);
|
||||
while(gs.length() < 2){
|
||||
gs = "0" + gs;
|
||||
}
|
||||
if (index%6 > 2){
|
||||
b = (int) (255*factor);
|
||||
}
|
||||
bs = Integer.toHexString(b);
|
||||
while(bs.length() < 2){
|
||||
bs = "0" + bs;
|
||||
}
|
||||
return "#" + rs + gs + bs;
|
||||
private String createHexColor(int index) {
|
||||
int baseColorCount = baseColors.length;
|
||||
int baseColorsIndex = index % baseColorCount;
|
||||
float brightnessDecrease = Math.round(index / baseColorCount) * 0.75f;
|
||||
float saturationDecrease = Math.round(index / baseColorCount) * 0.05f;
|
||||
HSVColor hsvColor = baseColors[baseColorsIndex];
|
||||
HSVColor newColor = new HSVColor(hsvColor.getHue(), hsvColor.getSaturation() - saturationDecrease,
|
||||
hsvColor.getBrightness() - brightnessDecrease);
|
||||
return newColor.getAsHtml();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user