From 3d6ea70ed6384ab001e5489d42ef10a292aef60b Mon Sep 17 00:00:00 2001 From: fmittag Date: Fri, 22 Jun 2012 11:57:44 +0200 Subject: [PATCH] replaced the broken calculation of distinct colors in the colormap with a HSV color schema based method --- .../com/sap/sailing/domain/common/Color.java | 3 + .../sailing/domain/common/impl/HSVColor.java | 125 ++++++++++++++++++ .../sailing/domain/common/impl/RGBColor.java | 68 +++++++++- .../sap/sailing/gwt/ui/client/ColorMap.java | 69 +++++----- 4 files changed, 223 insertions(+), 42 deletions(-) create mode 100644 java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/HSVColor.java diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/Color.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/Color.java index daa6015e23d..e6805416d64 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/Color.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/Color.java @@ -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 getAsRGB(); + Util.Triple getAsHSV(); + String getAsHtml(); } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/HSVColor.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/HSVColor.java new file mode 100644 index 00000000000..c3e25fc75a0 --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/HSVColor.java @@ -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 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 RGBColor = new Triple(Math.round(r * 255), + Math.round(g * 255), Math.round(b * 255)); + return RGBColor; + } + + @Override + public String getAsHtml() { + Triple 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 getAsHSV() { + return new Triple(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; + } +} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/RGBColor.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/RGBColor.java index 9817d8782a2..f5e7e10a2c1 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/RGBColor.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/RGBColor.java @@ -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(red, green, blue); } + public Triple 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 HSVColor = new Triple(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; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/ColorMap.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/ColorMap.java index 7a1c6e75351..615fa032a04 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/ColorMap.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/ColorMap.java @@ -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 the type of the objects to which a color is assigned + * + * @param + * the type of the objects to which a color is assigned */ public class ColorMap { private final HashMap 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(); } @@ -26,15 +40,15 @@ public class ColorMap { * 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 { * 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(); } - + }