znakeeye wrote:But even if I use
SeriesBand the result is not 100% correct.
Recall your sample here:
http://stackoverflow.com/questions/1401 ... a-gradient
Try setting the maximum value to 2000. I would expect all points to be red/orange, but instead the whole gradient will be defined - including green color. If you believe this is indeed correct behavior, then please answer this:
How should I solve this?
a) Should I recalculate the gradient depending on my maximum value? That is, in your sample I would use a gradient from red to yellow since green is way above the value of ~675. If you think this is the right way to go, then please make the 3-color-gradient algorithm public. (I don't know where it resides in the code.)
b) Should TChart handle this using some kind of property? E.g. "setGradientFromValueRange(true)" or something...
Right. Even the relative gradients in the Bar series are always relative to the maximum value of the series. Right now, there's no property or method to set gradients relative to other values; in your case, relative to the axis scale. This was what I was trying to achieve
here.
And I've improved that code a bit. Take a look at it:
Code: Select all
final Color mStartColor = Color.green;
final Color mMiddleColor = Color.yellow;
final Color mEndColor = Color.red;
final int mStartValue = 100;
private void initializeChart() {
tChart1.getAspect().setView3D(false);
tChart1.getLegend().setVisible(false);
tChart1.getPanel().setMarginUnits(PanelMarginUnits.PIXELS);
tChart1.getPanel().setMarginBottom(25);
Axis bottom1 = new Axis();
Axis bottom2 = new Axis();
bottom1.setHorizontal(true);
bottom2.setHorizontal(true);
tChart1.getAxes().getCustom().add(bottom1);
tChart1.getAxes().getCustom().add(bottom2);
bottom1.setEndPosition(50);
bottom2.setStartPosition(50);
bottom1.getGrid().setVisible(false);
bottom2.getGrid().setVisible(false);
tChart1.getAxes().getLeft().getGrid().setVisible(false);
Bar bar1 = new Bar(tChart1.getChart());
bar1.setCustomHorizAxis(bottom1);
bar1.getGradient().setVisible(true);
bar1.setGradientRelative(true);
bar1.getGradient().setUseMiddle(true);
bar1.getGradient().setEndColor(mEndColor);
bar1.getMarks().setVisible(false);
Area area1 = new Area(tChart1.getChart());
area1.setCustomHorizAxis(bottom2);
area1.setOrigin(0);
area1.setUseOrigin(true);
area1.getAreaLines().setVisible(false);
area1.getLinePen().setVisible(false);
for (int i=0; i<4; i++) {
bar1.add((i+1)*20);
area1.add((i+1)*20);
}
area1.getGradient().setVisible(true);
area1.getGradient().setDirection(GradientDirection.VERTICAL);
area1.getGradient().setUseMiddle(true);
area1.getGradient().setEndColor(mEndColor);
area1.getPointer().setVisible(true);
double tmpStartValue = area1.getYValues().getValue(1);
setGradient(area1.getGradient(), tmpStartValue);
tChart1.getWalls().getBack().getGradient().setVisible(true);
tChart1.getWalls().getBack().getGradient().setDirection(GradientDirection.VERTICAL);
tChart1.getWalls().getBack().getGradient().setStartColor(mStartColor);
tChart1.getWalls().getBack().getGradient().setMiddleColor(mMiddleColor);
tChart1.getWalls().getBack().getGradient().setUseMiddle(true);
tChart1.getWalls().getBack().getGradient().setEndColor(mEndColor);
tChart1.getAxes().getLeft().setMinMax(0, mStartValue);
bar1.getPen().setVisible(false);
bar1.setBarStyleResolver(new BarStyleResolver() {
@Override
public BarStyle getStyle(ISeries series, int valueIndex, BarStyle style) {
if (series!=null) {
if (valueIndex > -1) {
double tmpValue = series.getYValues().getValue(valueIndex);
setGradient(tChart1.getGraphics3D().getGradient(), tmpValue);
}
}
return style;
}
});
area1.setPointerStyleResolver(new PointerStyleResolver() {
@Override
public PointerStyle getStyle(ISeries series, int valueIndex, PointerStyle style) {
if (series!=null) {
Gradient seriesGradient = ((Area)series).getGradient();
if (valueIndex > -1) {
double tmpValue = series.getYValues().getValue((valueIndex+2) % series.getCount());
setGradient(seriesGradient, tmpValue);
}
}
return PointerStyle.NOTHING;
}
});
}
private void setGradient(Gradient gradient, double value) {
double mMiddleValue = mStartValue/2;
if (value>mMiddleValue) {
double percent = (value-mMiddleValue)*2;
gradient.setStartColor(calcColorBlend(mStartColor, mMiddleColor, percent));
}
else {
double percent = value*2;
gradient.setStartColor(calcColorBlend(mMiddleColor, mEndColor, percent));
}
value /= 2;
if (value>mMiddleValue) {
double percent = (value-mMiddleValue)*2;
gradient.setMiddleColor(calcColorBlend(mStartColor, mMiddleColor, percent));
}
else {
double percent = value*2;
gradient.setMiddleColor(calcColorBlend(mMiddleColor, mEndColor, percent));
}
}
private Color calcColorBlend(Color end, Color start, double percentage) {
int tmpA = start.getAlpha() + Utils.round((end.getAlpha()-start.getAlpha()) * percentage / 100);
int tmpR = start.getRed() + Utils.round((end.getRed()-start.getRed()) * percentage / 100);
int tmpG = start.getGreen() + Utils.round((end.getGreen()-start.getGreen()) * percentage / 100);
int tmpB = start.getBlue() + Utils.round((end.getBlue()-start.getBlue()) * percentage / 100);
return Color.fromArgb(tmpA, tmpR, tmpG, tmpB);
}
However, I'm afraid this is still not perfect:
- device-2013-03-19-111156.png (10.4 KiB) Viewed 15622 times
When the bar/area value is below middleValue, 50 in the case above, it works fine because we just have to find the start and middle colors appropriate to the percentages, both between yellow and red.
However, when the bar/area value is above middleValue, the shape to draw isn't regular: it should be a shape from the value to 50, with a startColor according to the value percentage and a full yellow middleColor. And the second shape would be a rectangle going from yellow 50 to red 0.
znakeeye wrote:I believe there is a simple solution to get this right. This works:
Code: Select all
if (dir == GradientDirection.VERTICAL) {
g = new LinearGradient(0, /*rectangle.y*/0, 0, rectangle.getBottom(),
colors, null,
Shader.TileMode.CLAMP);
}
If you ask me, the above is the correct way to apply a gradient on any chart. Perhaps you should add another GradientDirection enum that does exactly this?
In what code example do you find this change makes a better gradient?
znakeeye wrote:Hi again. I couldn't wait, so I implemented n-color gradient. Yeray, please e-mail me (the e-mail is linked to my account) if you want my source code changes.
We'll be glad to take a look at that implementation, of course. Please, send the changes and an example to "info at steema dot com" referencing this thread.