mirror of
https://github.com/meteoinfo/MeteoInfo.git
synced 2025-12-08 20:36:05 +00:00
Add normalize to imshow and colorbar
This commit is contained in:
parent
4e44a4ba1e
commit
fe36eee6dd
@ -72,8 +72,8 @@
|
||||
<orderEntry type="module" module-name="meteoinfo-dataframe" />
|
||||
<orderEntry type="library" name="Maven: edu.ucar:netcdfAll:5.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.github.albfernandez:juniversalchardet:2.4.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf:2.0-rc1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf-extras:2.0-rc1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf:2.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf-extras:2.0" level="project" />
|
||||
<orderEntry type="library" scope="RUNTIME" name="Maven: com.formdev:svgSalamander:1.1.3" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.itextpdf:itextpdf:5.5.13.2" level="project" />
|
||||
<orderEntry type="module" module-name="meteoinfo-ui" />
|
||||
|
||||
@ -13,11 +13,20 @@ import java.awt.Rectangle;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.meteoinfo.common.*;
|
||||
import org.meteoinfo.common.colors.ColorMap;
|
||||
import org.meteoinfo.geo.drawing.Draw;
|
||||
import org.meteoinfo.geometry.colors.BoundaryNorm;
|
||||
import org.meteoinfo.geometry.colors.ExtendType;
|
||||
import org.meteoinfo.geometry.colors.LogNorm;
|
||||
import org.meteoinfo.geometry.colors.Normalize;
|
||||
import org.meteoinfo.geometry.legend.*;
|
||||
import org.meteoinfo.geometry.shape.ShapeTypes;
|
||||
|
||||
@ -38,6 +47,7 @@ public class ChartColorBar extends ChartLegend {
|
||||
private Color tickColor;
|
||||
private boolean drawMinLabel;
|
||||
private boolean drawMaxLabel;
|
||||
private ExtendType extendType;
|
||||
|
||||
// </editor-fold>
|
||||
// <editor-fold desc="Constructor">
|
||||
@ -59,6 +69,8 @@ public class ChartColorBar extends ChartLegend {
|
||||
this.tickColor = Color.black;
|
||||
this.drawMinLabel = false;
|
||||
this.drawMaxLabel = false;
|
||||
this.extendType = ExtendType.NEITHER;
|
||||
this.setLegendScheme(ls);
|
||||
}
|
||||
|
||||
// </editor-fold>
|
||||
@ -263,6 +275,39 @@ public class ChartColorBar extends ChartLegend {
|
||||
this.tickLabelColor = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set legend scheme
|
||||
*
|
||||
* @param value Legend scheme
|
||||
*/
|
||||
@Override
|
||||
public void setLegendScheme(LegendScheme value) {
|
||||
this.legendScheme = value;
|
||||
Normalize normalize = this.legendScheme.getNormalize();
|
||||
if (normalize != null) {
|
||||
double min = normalize.getMinValue();
|
||||
double max = normalize.getMaxValue();
|
||||
double[] tickValues;
|
||||
if (normalize instanceof LogNorm) {
|
||||
tickValues = MIMath.getIntervalValues_Log(min, max);
|
||||
} else {
|
||||
tickValues = MIMath.getIntervalValues(min, max);
|
||||
}
|
||||
this.tickLocations = Arrays.stream(tickValues).boxed().collect(Collectors.toList());
|
||||
this.tickLabels = new ArrayList<>();
|
||||
if (normalize instanceof LogNorm) {
|
||||
for (double v : this.tickLocations) {
|
||||
int e = (int) Math.floor(Math.log10(v));
|
||||
this.tickLabels.add(new ChartText("$10^{" + String.valueOf(e) + "}$"));
|
||||
}
|
||||
} else {
|
||||
for (double v : this.tickLocations) {
|
||||
this.tickLabels.add(new ChartText(DataConvert.removeTailingZeros(String.valueOf(v))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if draw minimum value label
|
||||
*
|
||||
@ -299,6 +344,30 @@ public class ChartColorBar extends ChartLegend {
|
||||
this.drawMaxLabel = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extend type
|
||||
* @return Extend type
|
||||
*/
|
||||
public ExtendType getExtendType() {
|
||||
return this.extendType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set extend type
|
||||
* @param value Extend type
|
||||
*/
|
||||
public void setExtendType(ExtendType value) {
|
||||
this.extendType = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set extend type
|
||||
* @param value Extend type string
|
||||
*/
|
||||
public void setExtendType(String value) {
|
||||
this.extendType = ExtendType.valueOf(value.toUpperCase());
|
||||
}
|
||||
|
||||
// </editor-fold>
|
||||
// <editor-fold desc="Method">
|
||||
/**
|
||||
@ -323,10 +392,16 @@ public class ChartColorBar extends ChartLegend {
|
||||
g.setStroke(new BasicStroke(1));
|
||||
switch (this.orientation) {
|
||||
case HORIZONTAL:
|
||||
this.drawHorizontalBarLegend(g, legendScheme);
|
||||
if (legendScheme.getColorMap() != null)
|
||||
this.drawHorizontal(g, legendScheme);
|
||||
else
|
||||
this.drawHorizontalBarLegend(g, legendScheme);
|
||||
break;
|
||||
case VERTICAL:
|
||||
this.drawVerticalBarLegend(g, legendScheme);
|
||||
if (legendScheme.getColorMap() != null)
|
||||
this.drawVertical(g, legendScheme);
|
||||
else
|
||||
this.drawVerticalBarLegend(g, legendScheme);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -381,6 +456,182 @@ public class ChartColorBar extends ChartLegend {
|
||||
}
|
||||
}
|
||||
|
||||
private void drawHorizontal(Graphics2D g, LegendScheme ls) {
|
||||
PointF aP = new PointF(0, 0);
|
||||
PointF sP = new PointF(0, 0);
|
||||
String caption;
|
||||
ColorMap colorMap = ls.getColorMap();
|
||||
Normalize normalize = ls.getNormalize();
|
||||
|
||||
int bNum = colorMap.getColorCount();
|
||||
if (normalize instanceof BoundaryNorm) {
|
||||
bNum = ((BoundaryNorm) normalize).getNRegions();
|
||||
}
|
||||
|
||||
this.barHeight = (float) this.legendWidth / this.aspect;
|
||||
float minMaxWidth = this.legendWidth;
|
||||
float x_shift = 0;
|
||||
switch (this.extendType) {
|
||||
case MIN:
|
||||
minMaxWidth -= barHeight;
|
||||
x_shift += barHeight;
|
||||
break;
|
||||
case MAX:
|
||||
minMaxWidth -= barHeight;
|
||||
break;
|
||||
case BOTH:
|
||||
minMaxWidth -= barHeight * 2;
|
||||
x_shift += barHeight;
|
||||
break;
|
||||
}
|
||||
barWidth = minMaxWidth / bNum;
|
||||
float y_shift = 0;
|
||||
if (this.label != null){
|
||||
switch (this.labelLocation){
|
||||
case "top":
|
||||
case "in":
|
||||
y_shift = this.label.getDimension(g).height + 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Draw color polygons
|
||||
aP.Y = y_shift;
|
||||
Color[] colors = colorMap.getColors(bNum);
|
||||
switch (this.extendType) {
|
||||
case MIN:
|
||||
case BOTH:
|
||||
g.setColor(colors[0]);
|
||||
Path2D p = new Path2D.Float();
|
||||
p.moveTo(aP.X, aP.Y + barHeight / 2);
|
||||
p.lineTo(aP.X + barHeight, aP.Y);
|
||||
p.lineTo(aP.X + barHeight, aP.Y + barHeight);
|
||||
p.lineTo(aP.X, aP.Y + barHeight / 2);
|
||||
p.closePath();
|
||||
g.fill(p);
|
||||
aP.X += barHeight;
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < bNum; i++) {
|
||||
g.setColor(colors[i]);
|
||||
Rectangle2D rect = new Rectangle2D.Float(aP.X - 1, aP.Y, barWidth + 1, barHeight);
|
||||
g.fill(rect);
|
||||
aP.X += barWidth;
|
||||
}
|
||||
switch (this.extendType) {
|
||||
case MAX:
|
||||
case BOTH:
|
||||
g.setColor(colors[bNum - 1]);
|
||||
Path2D p = new Path2D.Float();
|
||||
p.moveTo(aP.X, aP.Y);
|
||||
p.lineTo(aP.X, aP.Y + barHeight);
|
||||
p.lineTo(aP.X + barHeight, aP.Y + barHeight / 2);
|
||||
p.lineTo(aP.X, aP.Y);
|
||||
p.closePath();
|
||||
g.fill(p);
|
||||
break;
|
||||
}
|
||||
|
||||
//Draw neatline
|
||||
g.setStroke(new BasicStroke(this.neatLineSize));
|
||||
g.setColor(this.neatLineColor);
|
||||
switch (this.extendType) {
|
||||
case NEITHER:
|
||||
g.draw(new Rectangle.Double(0, y_shift, this.barWidth * bNum, this.barHeight));
|
||||
break;
|
||||
case BOTH:
|
||||
Path2D p = new Path2D.Float();
|
||||
p.moveTo(0, this.barHeight / 2 + y_shift);
|
||||
p.lineTo(this.barHeight, y_shift);
|
||||
p.lineTo(this.legendWidth - barHeight, y_shift);
|
||||
p.lineTo(this.legendWidth, this.barHeight / 2 + y_shift);
|
||||
p.lineTo(this.legendWidth - barHeight, this.barHeight + y_shift);
|
||||
p.lineTo(this.barHeight, this.barHeight + y_shift);
|
||||
p.closePath();
|
||||
g.draw(p);
|
||||
break;
|
||||
case MIN:
|
||||
p = new Path2D.Float();
|
||||
p.moveTo(0, this.barHeight / 2 + y_shift);
|
||||
p.lineTo(this.barHeight, y_shift);
|
||||
p.lineTo(this.legendWidth, y_shift);
|
||||
p.lineTo(this.legendWidth, this.barHeight + y_shift);
|
||||
p.lineTo(this.barHeight, this.barHeight + y_shift);
|
||||
p.lineTo(0, this.barHeight / 2 + y_shift);
|
||||
p.closePath();
|
||||
g.draw(p);
|
||||
break;
|
||||
case MAX:
|
||||
p = new Path2D.Float();
|
||||
p.moveTo(0, y_shift);
|
||||
p.lineTo(0, this.barHeight + y_shift);
|
||||
p.lineTo(this.legendWidth - barHeight, this.barHeight + y_shift);
|
||||
p.lineTo(this.legendWidth, this.barHeight / 2 + y_shift);
|
||||
p.lineTo(this.legendWidth - barHeight, y_shift);
|
||||
p.lineTo(0, y_shift);
|
||||
p.closePath();
|
||||
g.draw(p);
|
||||
break;
|
||||
}
|
||||
|
||||
//Draw tick and label
|
||||
float tickLen = this.tickLength;
|
||||
if (this.insideTick) {
|
||||
if (this.barHeight < tickLen) {
|
||||
tickLen = (int) this.barHeight;
|
||||
}
|
||||
}
|
||||
g.setStroke(new BasicStroke(this.tickWidth));
|
||||
g.setFont(tickLabelFont);
|
||||
g.setColor(this.tickColor);
|
||||
aP.Y = barHeight + y_shift;
|
||||
for (int i = 0; i < this.tickLocations.size(); i++) {
|
||||
sP.X = x_shift + minMaxWidth * normalize.apply(this.tickLocations.get(i)).floatValue();
|
||||
sP.Y = aP.Y;
|
||||
g.setColor(this.tickColor);
|
||||
this.drawTickLine(g, sP, tickLen, true, 0);
|
||||
String label = this.tickLabels.get(i).getText();
|
||||
g.setColor(this.tickLabelColor);
|
||||
if (this.tickLabelAngle == 0) {
|
||||
Draw.drawString(g, sP.X, sP.Y, label, XAlign.CENTER, YAlign.TOP, this.tickLabelAngle, true);
|
||||
} else if (this.tickLabelAngle < 45) {
|
||||
Draw.drawString(g, sP.X, sP.Y, label, XAlign.RIGHT, YAlign.TOP, this.tickLabelAngle, true);
|
||||
} else {
|
||||
Draw.drawString(g, sP.X, sP.Y, label, XAlign.RIGHT, YAlign.CENTER, this.tickLabelAngle, true);
|
||||
}
|
||||
}
|
||||
|
||||
//Draw label
|
||||
double sx, sy;
|
||||
if (this.label != null) {
|
||||
g.setFont(this.label.getFont());
|
||||
g.setColor(this.label.getColor());
|
||||
switch (this.labelLocation) {
|
||||
case "top":
|
||||
case "in":
|
||||
sx = this.legendWidth * 0.5;
|
||||
sy = 2;
|
||||
Draw.drawString(g, sx, sy, label.getText(), XAlign.CENTER, YAlign.TOP, label.isUseExternalFont());
|
||||
break;
|
||||
case "right":
|
||||
sx = this.legendWidth + 5;
|
||||
sy = this.barHeight * 0.5;
|
||||
Draw.drawString(g, sx, sy, label.getText(), XAlign.LEFT, YAlign.CENTER, label.isUseExternalFont());
|
||||
break;
|
||||
case "left":
|
||||
sx = -5;
|
||||
sy = this.barHeight * 0.5;
|
||||
Draw.drawString(g, sx, sy, label.getText(), XAlign.RIGHT, YAlign.CENTER, label.isUseExternalFont());
|
||||
break;
|
||||
default:
|
||||
sx = this.legendWidth * 0.5;
|
||||
sy = this.height - 2;
|
||||
Draw.drawString(g, sx, sy, label.getText(), XAlign.CENTER, YAlign.BOTTOM, label.isUseExternalFont());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawHorizontalBarLegend(Graphics2D g, LegendScheme aLS) {
|
||||
PointD aP = new PointD(0, 0);
|
||||
PointD sP = new PointD(0, 0);
|
||||
@ -426,8 +677,8 @@ public class ChartColorBar extends ChartLegend {
|
||||
}
|
||||
}
|
||||
|
||||
this._hBarHeight = (double) this.legendWidth / this.aspect;
|
||||
_vBarWidth = (double) this.legendWidth / bNum;
|
||||
this.barHeight = (float) this.legendWidth / this.aspect;
|
||||
barWidth = (float) this.legendWidth / bNum;
|
||||
float y_shift = 0;
|
||||
if (this.label != null){
|
||||
switch (this.labelLocation){
|
||||
@ -472,30 +723,30 @@ public class ChartColorBar extends ChartLegend {
|
||||
if (aLS.getShapeType() == ShapeTypes.POLYGON) {
|
||||
PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone();
|
||||
aPGB.setDrawOutline(false);
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, _vBarWidth, _hBarHeight, aPGB, g);
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, barWidth, barHeight, aPGB, g);
|
||||
} else {
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, FillColor, OutlineColor, _vBarWidth,
|
||||
_hBarHeight, DrawFill, DrawOutline, g);
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, FillColor, OutlineColor, barWidth,
|
||||
barHeight, DrawFill, DrawOutline, g);
|
||||
}
|
||||
} else {
|
||||
double extendw = _vBarWidth;
|
||||
double extendw = barWidth;
|
||||
if (this.autoExtendFrac) {
|
||||
extendw = _hBarHeight;
|
||||
extendw = barHeight;
|
||||
}
|
||||
if (i == 0) {
|
||||
PointD[] Points = new PointD[4];
|
||||
Points[0] = new PointD();
|
||||
Points[0].X = _vBarWidth - extendw;
|
||||
Points[0].Y = aP.Y + _hBarHeight * 0.5;
|
||||
Points[0].X = barWidth - extendw;
|
||||
Points[0].Y = aP.Y + barHeight * 0.5;
|
||||
Points[1] = new PointD();
|
||||
Points[1].X = _vBarWidth;
|
||||
Points[1].X = barWidth;
|
||||
Points[1].Y = aP.Y;
|
||||
Points[2] = new PointD();
|
||||
Points[2].X = _vBarWidth;
|
||||
Points[2].Y = aP.Y + _hBarHeight;
|
||||
Points[2].X = barWidth;
|
||||
Points[2].Y = aP.Y + barHeight;
|
||||
Points[3] = new PointD();
|
||||
Points[3].X = _vBarWidth - extendw;
|
||||
Points[3].Y = aP.Y + _hBarHeight * 0.5;
|
||||
Points[3].X = barWidth - extendw;
|
||||
Points[3].Y = aP.Y + barHeight * 0.5;
|
||||
if (aLS.getShapeType() == ShapeTypes.POLYGON) {
|
||||
PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone();
|
||||
aPGB.setDrawOutline(false);
|
||||
@ -506,17 +757,17 @@ public class ChartColorBar extends ChartLegend {
|
||||
} else if (i == bNum - 1) {
|
||||
PointD[] Points = new PointD[4];
|
||||
Points[0] = new PointD();
|
||||
Points[0].X = i * _vBarWidth - 1.0f;
|
||||
Points[0].Y = aP.Y + _hBarHeight;
|
||||
Points[0].X = i * barWidth - 1.0f;
|
||||
Points[0].Y = aP.Y + barHeight;
|
||||
Points[1] = new PointD();
|
||||
Points[1].X = i * _vBarWidth - 1.0f;
|
||||
Points[1].X = i * barWidth - 1.0f;
|
||||
Points[1].Y = aP.Y;
|
||||
Points[2] = new PointD();
|
||||
Points[2].X = i * _vBarWidth + extendw;
|
||||
Points[2].Y = aP.Y + _hBarHeight * 0.5;
|
||||
Points[2].X = i * barWidth + extendw;
|
||||
Points[2].Y = aP.Y + barHeight * 0.5;
|
||||
Points[3] = new PointD();
|
||||
Points[3].X = i * _vBarWidth - 1.0f;
|
||||
Points[3].Y = aP.Y + _hBarHeight;
|
||||
Points[3].X = i * barWidth - 1.0f;
|
||||
Points[3].Y = aP.Y + barHeight;
|
||||
if (aLS.getShapeType() == ShapeTypes.POLYGON) {
|
||||
PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone();
|
||||
aPGB.setDrawOutline(false);
|
||||
@ -527,41 +778,41 @@ public class ChartColorBar extends ChartLegend {
|
||||
} else if (aLS.getShapeType() == ShapeTypes.POLYGON) {
|
||||
PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone();
|
||||
aPGB.setDrawOutline(false);
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, _vBarWidth, _hBarHeight, aPGB, g);
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, barWidth, barHeight, aPGB, g);
|
||||
} else {
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, FillColor, OutlineColor, _vBarWidth,
|
||||
_hBarHeight, DrawFill, DrawOutline, g);
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, FillColor, OutlineColor, barWidth,
|
||||
barHeight, DrawFill, DrawOutline, g);
|
||||
}
|
||||
}
|
||||
}
|
||||
aP.X += _vBarWidth;
|
||||
aP.X += barWidth;
|
||||
}
|
||||
//Draw neatline
|
||||
g.setStroke(new BasicStroke(this.neatLineSize));
|
||||
g.setColor(this.neatLineColor);
|
||||
if (this.extendRect) {
|
||||
g.draw(new Rectangle.Double(0, y_shift, this._vBarWidth * bNum, this._hBarHeight));
|
||||
g.draw(new Rectangle.Double(0, y_shift, this.barWidth * bNum, this.barHeight));
|
||||
} else {
|
||||
double extendw = _vBarWidth;
|
||||
double extendw = barWidth;
|
||||
if (this.autoExtendFrac) {
|
||||
extendw = _hBarHeight;
|
||||
extendw = barHeight;
|
||||
}
|
||||
Path2D p = new Path2D.Double();
|
||||
p.moveTo(_vBarWidth - extendw, this._hBarHeight / 2 + y_shift);
|
||||
p.lineTo(this._vBarWidth, y_shift);
|
||||
p.lineTo(this._vBarWidth * (bNum - 1), y_shift);
|
||||
p.lineTo(this._vBarWidth * (bNum - 1) + extendw, this._hBarHeight / 2 + y_shift);
|
||||
p.lineTo(this._vBarWidth * (bNum - 1), this._hBarHeight + y_shift);
|
||||
p.lineTo(this._vBarWidth, this._hBarHeight + y_shift);
|
||||
p.moveTo(barWidth - extendw, this.barHeight / 2 + y_shift);
|
||||
p.lineTo(this.barWidth, y_shift);
|
||||
p.lineTo(this.barWidth * (bNum - 1), y_shift);
|
||||
p.lineTo(this.barWidth * (bNum - 1) + extendw, this.barHeight / 2 + y_shift);
|
||||
p.lineTo(this.barWidth * (bNum - 1), this.barHeight + y_shift);
|
||||
p.lineTo(this.barWidth, this.barHeight + y_shift);
|
||||
p.closePath();
|
||||
g.draw(p);
|
||||
}
|
||||
//Draw tick and label
|
||||
aP.X = -_vBarWidth / 2;
|
||||
aP.X = -barWidth / 2;
|
||||
float tickLen = this.tickLength;
|
||||
if (this.insideTick) {
|
||||
if (this._hBarHeight < tickLen) {
|
||||
tickLen = (int) this._hBarHeight;
|
||||
if (this.barHeight < tickLen) {
|
||||
tickLen = (int) this.barHeight;
|
||||
}
|
||||
}
|
||||
g.setStroke(new BasicStroke(this.tickWidth));
|
||||
@ -569,8 +820,8 @@ public class ChartColorBar extends ChartLegend {
|
||||
g.setColor(this.tickColor);
|
||||
idx = 0;
|
||||
for (int i = 0; i < bNum; i++) {
|
||||
aP.X += _vBarWidth;
|
||||
aP.Y = _hBarHeight / 2 + y_shift;
|
||||
aP.X += barWidth;
|
||||
aP.Y = barHeight / 2 + y_shift;
|
||||
if (labelIdxs.contains(i)) {
|
||||
ColorBreak cb = aLS.getLegendBreaks().get(i);
|
||||
if (this.autoTick) {
|
||||
@ -585,7 +836,7 @@ public class ChartColorBar extends ChartLegend {
|
||||
|
||||
if (aLS.getLegendType() == LegendType.UNIQUE_VALUE) {
|
||||
sP.X = aP.X;
|
||||
sP.Y = aP.Y + _hBarHeight / 2 + 5;
|
||||
sP.Y = aP.Y + barHeight / 2 + 5;
|
||||
g.setColor(this.tickLabelColor);
|
||||
if (this.tickLabelAngle == 0) {
|
||||
Draw.drawString(g, sP.X, sP.Y, caption, XAlign.CENTER, YAlign.TOP, this.tickLabelAngle, true);
|
||||
@ -595,8 +846,8 @@ public class ChartColorBar extends ChartLegend {
|
||||
Draw.drawString(g, sP.X, sP.Y, caption, XAlign.RIGHT, YAlign.CENTER, this.tickLabelAngle, true);
|
||||
}
|
||||
} else {
|
||||
sP.X = aP.X + _vBarWidth / 2;
|
||||
sP.Y = aP.Y + _hBarHeight / 2;
|
||||
sP.X = aP.X + barWidth / 2;
|
||||
sP.Y = aP.Y + barHeight / 2;
|
||||
PointD ssP = (PointD)sP.clone();
|
||||
if (this.autoTick) {
|
||||
if (i < bNum - 1) {
|
||||
@ -612,16 +863,16 @@ public class ChartColorBar extends ChartLegend {
|
||||
}
|
||||
if (this.drawMinLabel && i == 0) {
|
||||
g.setColor(this.tickColor);
|
||||
this.drawTickLine(g, ssP, tickLen, true, -this._vBarWidth);
|
||||
this.drawTickLine(g, ssP, tickLen, true, -this.barWidth);
|
||||
caption = DataConvert.removeTailingZeros(cb.getStartValue().toString());
|
||||
g.setColor(this.tickLabelColor);
|
||||
//Draw.drawString(g, ssP.X - this._vBarWidth, ssP.Y, caption, XAlign.CENTER, YAlign.TOP, this.tickLabelAngle, true);
|
||||
//Draw.drawString(g, ssP.X - this.barWidth, ssP.Y, caption, XAlign.CENTER, YAlign.TOP, this.tickLabelAngle, true);
|
||||
if (this.tickLabelAngle == 0) {
|
||||
Draw.drawString(g, ssP.X - this._vBarWidth, ssP.Y, caption, XAlign.CENTER, YAlign.TOP, this.tickLabelAngle, true);
|
||||
Draw.drawString(g, ssP.X - this.barWidth, ssP.Y, caption, XAlign.CENTER, YAlign.TOP, this.tickLabelAngle, true);
|
||||
} else if (this.tickLabelAngle < 45) {
|
||||
Draw.drawString(g, ssP.X - this._vBarWidth, ssP.Y, caption, XAlign.RIGHT, YAlign.TOP, this.tickLabelAngle, true);
|
||||
Draw.drawString(g, ssP.X - this.barWidth, ssP.Y, caption, XAlign.RIGHT, YAlign.TOP, this.tickLabelAngle, true);
|
||||
} else {
|
||||
Draw.drawString(g, ssP.X - this._vBarWidth, ssP.Y, caption, XAlign.RIGHT, YAlign.CENTER, this.tickLabelAngle, true);
|
||||
Draw.drawString(g, ssP.X - this.barWidth, ssP.Y, caption, XAlign.RIGHT, YAlign.CENTER, this.tickLabelAngle, true);
|
||||
}
|
||||
}
|
||||
} else if (this.drawMaxLabel) {
|
||||
@ -639,15 +890,15 @@ public class ChartColorBar extends ChartLegend {
|
||||
} else {
|
||||
if (i == 0 && this.tickLocations.get(idx) == Double.parseDouble(cb.getStartValue().toString())) {
|
||||
g.setColor(this.tickColor);
|
||||
this.drawTickLine(g, sP, tickLen, true, -this._vBarWidth);
|
||||
this.drawTickLine(g, sP, tickLen, true, -this.barWidth);
|
||||
g.setColor(this.tickLabelColor);
|
||||
//Draw.drawString(g, sP.X - this._vBarWidth, sP.Y, caption, XAlign.CENTER, YAlign.TOP, this.tickLabelAngle, true);
|
||||
//Draw.drawString(g, sP.X - this.barWidth, sP.Y, caption, XAlign.CENTER, YAlign.TOP, this.tickLabelAngle, true);
|
||||
if (this.tickLabelAngle == 0) {
|
||||
Draw.drawString(g, sP.X - this._vBarWidth, sP.Y, caption, XAlign.CENTER, YAlign.TOP, this.tickLabelAngle, true);
|
||||
Draw.drawString(g, sP.X - this.barWidth, sP.Y, caption, XAlign.CENTER, YAlign.TOP, this.tickLabelAngle, true);
|
||||
} else if (this.tickLabelAngle < 45) {
|
||||
Draw.drawString(g, sP.X - this._vBarWidth, sP.Y, caption, XAlign.RIGHT, YAlign.TOP, this.tickLabelAngle, true);
|
||||
Draw.drawString(g, sP.X - this.barWidth, sP.Y, caption, XAlign.RIGHT, YAlign.TOP, this.tickLabelAngle, true);
|
||||
} else {
|
||||
Draw.drawString(g, sP.X - this._vBarWidth, sP.Y, caption, XAlign.RIGHT, YAlign.CENTER, this.tickLabelAngle, true);
|
||||
Draw.drawString(g, sP.X - this.barWidth, sP.Y, caption, XAlign.RIGHT, YAlign.CENTER, this.tickLabelAngle, true);
|
||||
}
|
||||
} else {
|
||||
g.setColor(this.tickColor);
|
||||
@ -681,12 +932,12 @@ public class ChartColorBar extends ChartLegend {
|
||||
break;
|
||||
case "right":
|
||||
sx = this.legendWidth + 5;
|
||||
sy = this._hBarHeight * 0.5;
|
||||
sy = this.barHeight * 0.5;
|
||||
Draw.drawString(g, sx, sy, label.getText(), XAlign.LEFT, YAlign.CENTER, label.isUseExternalFont());
|
||||
break;
|
||||
case "left":
|
||||
sx = -5;
|
||||
sy = this._hBarHeight * 0.5;
|
||||
sy = this.barHeight * 0.5;
|
||||
Draw.drawString(g, sx, sy, label.getText(), XAlign.RIGHT, YAlign.CENTER, label.isUseExternalFont());
|
||||
break;
|
||||
default:
|
||||
@ -698,6 +949,178 @@ public class ChartColorBar extends ChartLegend {
|
||||
}
|
||||
}
|
||||
|
||||
private void drawVertical(Graphics2D g, LegendScheme ls) {
|
||||
PointF aP = new PointF(0, 0);
|
||||
PointF sP = new PointF(0, 0);
|
||||
String caption;
|
||||
ColorMap colorMap = ls.getColorMap();
|
||||
Normalize normalize = ls.getNormalize();
|
||||
|
||||
int bNum = colorMap.getColorCount();
|
||||
if (normalize instanceof BoundaryNorm) {
|
||||
bNum = ((BoundaryNorm) normalize).getNRegions();
|
||||
}
|
||||
|
||||
this.barWidth = (float) this.legendHeight / this.aspect;
|
||||
float minMaxHeight = this.legendHeight;
|
||||
float y_shift = 0;
|
||||
switch (this.extendType) {
|
||||
case MIN:
|
||||
minMaxHeight -= barWidth;
|
||||
y_shift += barWidth;
|
||||
break;
|
||||
case MAX:
|
||||
minMaxHeight -= barWidth;
|
||||
break;
|
||||
case BOTH:
|
||||
minMaxHeight -= barWidth * 2;
|
||||
y_shift += barWidth;
|
||||
break;
|
||||
}
|
||||
barHeight = minMaxHeight / bNum;
|
||||
float x_shift = 0;
|
||||
if (this.label != null){
|
||||
switch (this.labelLocation){
|
||||
case "left":
|
||||
case "in":
|
||||
x_shift = this.label.getDimension(g).height + 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Draw color polygons
|
||||
aP.X = x_shift;
|
||||
aP.Y = legendHeight;
|
||||
Color[] colors = colorMap.getColors(bNum);
|
||||
switch (this.extendType) {
|
||||
case MIN:
|
||||
case BOTH:
|
||||
g.setColor(colors[0]);
|
||||
Path2D p = new Path2D.Float();
|
||||
p.moveTo(aP.X + barWidth / 2, aP.Y);
|
||||
p.lineTo(aP.X + barWidth, aP.Y - barWidth);
|
||||
p.lineTo(aP.X, aP.Y - barWidth);
|
||||
p.lineTo(aP.X + barWidth / 2, aP.Y);
|
||||
p.closePath();
|
||||
g.fill(p);
|
||||
aP.Y -= barWidth;
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < bNum; i++) {
|
||||
aP.Y -= barHeight;
|
||||
g.setColor(colors[i]);
|
||||
Rectangle2D rect = new Rectangle2D.Float(aP.X, aP.Y, barWidth, barHeight + 1);
|
||||
g.fill(rect);
|
||||
}
|
||||
switch (this.extendType) {
|
||||
case MAX:
|
||||
case BOTH:
|
||||
g.setColor(colors[bNum - 1]);
|
||||
Path2D p = new Path2D.Float();
|
||||
p.moveTo(aP.X, aP.Y);
|
||||
p.lineTo(aP.X + barWidth, aP.Y);
|
||||
p.lineTo(aP.X + barWidth / 2, aP.Y - barWidth);
|
||||
p.lineTo(aP.X, aP.Y);
|
||||
p.closePath();
|
||||
g.fill(p);
|
||||
break;
|
||||
}
|
||||
|
||||
//Draw neatline
|
||||
g.setStroke(new BasicStroke(this.neatLineSize));
|
||||
g.setColor(this.neatLineColor);
|
||||
switch (this.extendType) {
|
||||
case NEITHER:
|
||||
g.draw(new Rectangle.Double(x_shift, 0, this.barWidth, this.legendHeight));
|
||||
break;
|
||||
case BOTH:
|
||||
Path2D p = new Path2D.Double();
|
||||
p.moveTo(this.barWidth / 2 + x_shift, 0);
|
||||
p.lineTo(x_shift, this.barWidth);
|
||||
p.lineTo(x_shift, this.legendHeight - barWidth);
|
||||
p.lineTo(this.barWidth / 2 + x_shift, legendHeight);
|
||||
p.lineTo(this.barWidth + x_shift, legendHeight - barWidth);
|
||||
p.lineTo(this.barWidth + x_shift, this.barWidth);
|
||||
p.closePath();
|
||||
g.draw(p);
|
||||
break;
|
||||
case MIN:
|
||||
p = new Path2D.Double();
|
||||
p.moveTo(x_shift, 0);
|
||||
p.lineTo(this.barWidth + x_shift, 0);
|
||||
p.lineTo(this.barWidth + x_shift, this.legendHeight - barWidth);
|
||||
p.lineTo(this.barWidth / 2 + x_shift, legendHeight);
|
||||
p.lineTo(x_shift, legendHeight - barWidth);
|
||||
p.lineTo(x_shift, 0);
|
||||
p.closePath();
|
||||
g.draw(p);
|
||||
break;
|
||||
case MAX:
|
||||
p = new Path2D.Double();
|
||||
p.moveTo(this.barWidth / 2 + x_shift, 0);
|
||||
p.lineTo(x_shift, this.barWidth);
|
||||
p.lineTo(x_shift, this.legendHeight);
|
||||
p.lineTo(this.barWidth + x_shift, legendHeight);
|
||||
p.lineTo(this.barWidth + x_shift, this.barWidth);
|
||||
p.lineTo(this.barWidth / 2 + x_shift, 0);
|
||||
p.closePath();
|
||||
g.draw(p);
|
||||
break;
|
||||
}
|
||||
|
||||
//Draw tick and label
|
||||
float tickLen = this.tickLength;
|
||||
if (this.insideTick) {
|
||||
if (this.barWidth < tickLen) {
|
||||
tickLen = (int) this.barWidth;
|
||||
}
|
||||
}
|
||||
g.setStroke(new BasicStroke(this.tickWidth));
|
||||
g.setFont(tickLabelFont);
|
||||
g.setColor(this.tickColor);
|
||||
aP.X = barWidth + x_shift;
|
||||
for (int i = 0; i < this.tickLocations.size(); i++) {
|
||||
sP.X = aP.X;
|
||||
sP.Y = this.legendHeight - y_shift - minMaxHeight * normalize.apply(this.tickLocations.get(i)).floatValue();
|
||||
g.setColor(this.tickColor);
|
||||
this.drawTickLine(g, sP, tickLen, false, 0);
|
||||
String label = this.tickLabels.get(i).getText();
|
||||
g.setColor(this.tickLabelColor);
|
||||
Draw.drawString(g, sP.X, sP.Y, label, XAlign.LEFT, YAlign.CENTER, this.tickLabelAngle, true);
|
||||
}
|
||||
|
||||
//Draw label
|
||||
double sx, sy;
|
||||
if (this.label != null) {
|
||||
g.setFont(this.label.getFont());
|
||||
g.setColor(this.label.getColor());
|
||||
Dimension dim = Draw.getStringDimension(this.label.getText(), g);
|
||||
switch (this.labelLocation) {
|
||||
case "top":
|
||||
sx = 0;
|
||||
sy = -5;
|
||||
Draw.drawString(g, sx, sy, label.getText(), XAlign.LEFT, YAlign.BOTTOM, label.isUseExternalFont());
|
||||
break;
|
||||
case "bottom":
|
||||
sx = 0;
|
||||
sy = this.legendHeight + 5;
|
||||
Draw.drawString(g, sx, sy, label.getText(), XAlign.LEFT, YAlign.TOP, label.isUseExternalFont());
|
||||
break;
|
||||
case "left":
|
||||
case "in":
|
||||
sx = 0;
|
||||
sy = this.legendHeight * 0.5;
|
||||
Draw.drawString(g, sx, sy, label.getText(), XAlign.CENTER, YAlign.TOP, 90, label.isUseExternalFont());
|
||||
break;
|
||||
default:
|
||||
sx = this.width - dim.height;
|
||||
sy = this.legendHeight * 0.5;
|
||||
Draw.drawString(g, sx, sy, label.getText(), XAlign.CENTER, YAlign.TOP, 90, label.isUseExternalFont());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawVerticalBarLegend(Graphics2D g, LegendScheme aLS) {
|
||||
PointD aP = new PointD(0, 0);
|
||||
PointD sP = new PointD(0, 0);
|
||||
@ -751,8 +1174,8 @@ public class ChartColorBar extends ChartLegend {
|
||||
}
|
||||
}
|
||||
|
||||
this._vBarWidth = (double) this.legendHeight / this.aspect;
|
||||
_hBarHeight = (double) this.legendHeight / bNum;
|
||||
this.barWidth = (float) this.legendHeight / this.aspect;
|
||||
barHeight = (float) this.legendHeight / bNum;
|
||||
aP.Y = this.legendHeight;
|
||||
float x_shift = 0;
|
||||
if (this.label != null){
|
||||
@ -793,31 +1216,31 @@ public class ChartColorBar extends ChartLegend {
|
||||
break;
|
||||
}
|
||||
|
||||
aP.Y = aP.Y - _hBarHeight;
|
||||
aP.Y = aP.Y - barHeight;
|
||||
|
||||
if (DrawShape) {
|
||||
if (this.extendRect) {
|
||||
if (aLS.getShapeType() == ShapeTypes.POLYGON) {
|
||||
PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone();
|
||||
aPGB.setDrawOutline(false);
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, _vBarWidth, _hBarHeight, aPGB, g);
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, barWidth, barHeight, aPGB, g);
|
||||
} else {
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, FillColor, OutlineColor, _vBarWidth,
|
||||
_hBarHeight, DrawFill, DrawOutline, g);
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, FillColor, OutlineColor, barWidth,
|
||||
barHeight, DrawFill, DrawOutline, g);
|
||||
}
|
||||
} else if (i == 0) {
|
||||
PointD[] Points = new PointD[4];
|
||||
Points[0] = new PointD();
|
||||
Points[0].X = aP.X + _vBarWidth * 0.5;
|
||||
Points[0].X = aP.X + barWidth * 0.5;
|
||||
Points[0].Y = this.legendHeight;
|
||||
Points[1] = new PointD();
|
||||
Points[1].X = aP.X;
|
||||
Points[1].Y = aP.Y;
|
||||
Points[2] = new PointD();
|
||||
Points[2].X = aP.X + _vBarWidth;
|
||||
Points[2].X = aP.X + barWidth;
|
||||
Points[2].Y = aP.Y;
|
||||
Points[3] = new PointD();
|
||||
Points[3].X = aP.X + _vBarWidth * 0.5;
|
||||
Points[3].X = aP.X + barWidth * 0.5;
|
||||
Points[3].Y = this.legendHeight;
|
||||
if (aLS.getShapeType() == ShapeTypes.POLYGON) {
|
||||
PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone();
|
||||
@ -830,16 +1253,16 @@ public class ChartColorBar extends ChartLegend {
|
||||
PointD[] Points = new PointD[4];
|
||||
Points[0] = new PointD();
|
||||
Points[0].X = aP.X;
|
||||
Points[0].Y = _hBarHeight;
|
||||
Points[0].Y = barHeight;
|
||||
Points[1] = new PointD();
|
||||
Points[1].X = aP.X + _vBarWidth;
|
||||
Points[1].Y = _hBarHeight;
|
||||
Points[1].X = aP.X + barWidth;
|
||||
Points[1].Y = barHeight;
|
||||
Points[2] = new PointD();
|
||||
Points[2].X = aP.X + _vBarWidth * 0.5;
|
||||
Points[2].X = aP.X + barWidth * 0.5;
|
||||
Points[2].Y = 0;
|
||||
Points[3] = new PointD();
|
||||
Points[3].X = aP.X;
|
||||
Points[3].Y = _hBarHeight;
|
||||
Points[3].Y = barHeight;
|
||||
if (aLS.getShapeType() == ShapeTypes.POLYGON) {
|
||||
PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone();
|
||||
aPGB.setDrawOutline(false);
|
||||
@ -850,10 +1273,10 @@ public class ChartColorBar extends ChartLegend {
|
||||
} else if (aLS.getShapeType() == ShapeTypes.POLYGON) {
|
||||
PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone();
|
||||
aPGB.setDrawOutline(false);
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, _vBarWidth, _hBarHeight, aPGB, g);
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, barWidth, barHeight, aPGB, g);
|
||||
} else {
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, FillColor, OutlineColor, _vBarWidth,
|
||||
_hBarHeight, DrawFill, DrawOutline, g);
|
||||
Draw.drawPolygonSymbol(aP.X, aP.Y, FillColor, OutlineColor, barWidth,
|
||||
barHeight, DrawFill, DrawOutline, g);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -861,32 +1284,32 @@ public class ChartColorBar extends ChartLegend {
|
||||
g.setStroke(new BasicStroke(this.neatLineSize));
|
||||
g.setColor(this.neatLineColor);
|
||||
if (this.extendRect) {
|
||||
g.draw(new Rectangle.Double(x_shift, 0, this._vBarWidth, this._hBarHeight * bNum));
|
||||
g.draw(new Rectangle.Double(x_shift, 0, this.barWidth, this.barHeight * bNum));
|
||||
} else {
|
||||
Path2D p = new Path2D.Double();
|
||||
p.moveTo(this._vBarWidth / 2 + x_shift, 0);
|
||||
p.lineTo(x_shift, this._hBarHeight);
|
||||
p.lineTo(x_shift, (this._hBarHeight * (bNum - 1)));
|
||||
p.lineTo(this._vBarWidth / 2 + x_shift, this._hBarHeight * bNum);
|
||||
p.lineTo(this._vBarWidth + x_shift, this._hBarHeight * (bNum - 1));
|
||||
p.lineTo(this._vBarWidth + x_shift, this._hBarHeight);
|
||||
p.moveTo(this.barWidth / 2 + x_shift, 0);
|
||||
p.lineTo(x_shift, this.barHeight);
|
||||
p.lineTo(x_shift, (this.barHeight * (bNum - 1)));
|
||||
p.lineTo(this.barWidth / 2 + x_shift, this.barHeight * bNum);
|
||||
p.lineTo(this.barWidth + x_shift, this.barHeight * (bNum - 1));
|
||||
p.lineTo(this.barWidth + x_shift, this.barHeight);
|
||||
p.closePath();
|
||||
g.draw(p);
|
||||
}
|
||||
//Draw ticks
|
||||
g.setStroke(new BasicStroke(this.tickWidth));
|
||||
aP.Y = this.legendHeight + _hBarHeight / 2;
|
||||
aP.Y = this.legendHeight + barHeight / 2;
|
||||
float tickLen = this.tickLength;
|
||||
if (this.insideTick) {
|
||||
if (this._vBarWidth < tickLen) {
|
||||
tickLen = (int) this._vBarWidth;
|
||||
if (this.barWidth < tickLen) {
|
||||
tickLen = (int) this.barWidth;
|
||||
}
|
||||
}
|
||||
g.setFont(tickLabelFont);
|
||||
idx = 0;
|
||||
for (int i = 0; i < bNum; i++) {
|
||||
aP.X = _vBarWidth / 2 + x_shift;
|
||||
aP.Y = aP.Y - _hBarHeight;
|
||||
aP.X = barWidth / 2 + x_shift;
|
||||
aP.Y = aP.Y - barHeight;
|
||||
if (labelIdxs.contains(i)) {
|
||||
ColorBreak cb = aLS.getLegendBreaks().get(i);
|
||||
if (this.autoTick) {
|
||||
@ -900,13 +1323,13 @@ public class ChartColorBar extends ChartLegend {
|
||||
}
|
||||
|
||||
if (aLS.getLegendType() == LegendType.UNIQUE_VALUE) {
|
||||
sP.X = aP.X + _vBarWidth / 2 + 5;
|
||||
sP.X = aP.X + barWidth / 2 + 5;
|
||||
sP.Y = aP.Y;
|
||||
g.setColor(this.tickLabelColor);
|
||||
Draw.drawString(g, sP.X, sP.Y, caption, XAlign.LEFT, YAlign.CENTER, this.tickLabelAngle, true);
|
||||
} else {
|
||||
sP.X = aP.X + _vBarWidth / 2;
|
||||
sP.Y = aP.Y - _hBarHeight / 2;
|
||||
sP.X = aP.X + barWidth / 2;
|
||||
sP.Y = aP.Y - barHeight / 2;
|
||||
PointD ssP = (PointD)sP.clone();
|
||||
if (this.autoTick) {
|
||||
if (i < bNum - 1) {
|
||||
@ -916,10 +1339,10 @@ public class ChartColorBar extends ChartLegend {
|
||||
Draw.drawString(g, sP.X, sP.Y, caption, XAlign.LEFT, YAlign.CENTER, this.tickLabelAngle, true);
|
||||
if (this.drawMinLabel && i == 0) {
|
||||
g.setColor(this.tickColor);
|
||||
this.drawTickLine(g, ssP, tickLen, false, this._hBarHeight);
|
||||
this.drawTickLine(g, ssP, tickLen, false, this.barHeight);
|
||||
caption = DataConvert.removeTailingZeros(cb.getStartValue().toString());
|
||||
g.setColor(this.tickLabelColor);
|
||||
Draw.drawString(g, ssP.X, ssP.Y + this._hBarHeight, caption, XAlign.LEFT, YAlign.CENTER, this.tickLabelAngle, true);
|
||||
Draw.drawString(g, ssP.X, ssP.Y + this.barHeight, caption, XAlign.LEFT, YAlign.CENTER, this.tickLabelAngle, true);
|
||||
}
|
||||
} else if (this.drawMaxLabel) {
|
||||
g.setColor(this.tickColor);
|
||||
@ -930,9 +1353,9 @@ public class ChartColorBar extends ChartLegend {
|
||||
} else {
|
||||
if (i == 0 && this.tickLocations.get(idx) == Double.parseDouble(cb.getStartValue().toString())) {
|
||||
g.setColor(this.tickColor);
|
||||
this.drawTickLine(g, sP, tickLen, false, this._hBarHeight);
|
||||
this.drawTickLine(g, sP, tickLen, false, this.barHeight);
|
||||
g.setColor(this.tickLabelColor);
|
||||
Draw.drawString(g, sP.X, sP.Y + this._hBarHeight, caption, XAlign.LEFT, YAlign.CENTER, this.tickLabelAngle, true);
|
||||
Draw.drawString(g, sP.X, sP.Y + this.barHeight, caption, XAlign.LEFT, YAlign.CENTER, this.tickLabelAngle, true);
|
||||
} else {
|
||||
g.setColor(this.tickColor);
|
||||
this.drawTickLine(g, sP, tickLen, false, 0);
|
||||
|
||||
@ -13,10 +13,7 @@
|
||||
*/
|
||||
package org.meteoinfo.chart;
|
||||
|
||||
import org.meteoinfo.common.DataConvert;
|
||||
import org.meteoinfo.common.PointF;
|
||||
import org.meteoinfo.common.XAlign;
|
||||
import org.meteoinfo.common.YAlign;
|
||||
import org.meteoinfo.common.*;
|
||||
import org.meteoinfo.geo.drawing.Draw;
|
||||
import com.l2fprod.common.beans.BaseBeanInfo;
|
||||
import com.l2fprod.common.beans.ExtendedPropertyDescriptor;
|
||||
@ -66,8 +63,8 @@ public class ChartLegend {
|
||||
private float breakSpace;
|
||||
private float topSpace;
|
||||
private float leftSpace;
|
||||
protected double _vBarWidth;
|
||||
protected double _hBarHeight;
|
||||
protected float barWidth;
|
||||
protected float barHeight;
|
||||
private int rowColNum = 1;
|
||||
private boolean autoRowColNum = true;
|
||||
private Dimension symbolDimension;
|
||||
@ -99,8 +96,8 @@ public class ChartLegend {
|
||||
breakSpace = 3;
|
||||
topSpace = 5;
|
||||
leftSpace = 5;
|
||||
_vBarWidth = 10;
|
||||
_hBarHeight = 10;
|
||||
barWidth = 10;
|
||||
barHeight = 10;
|
||||
this.labelLocation = "out";
|
||||
tickLabelFont = new Font("Arial", Font.PLAIN, 14);
|
||||
this.tickLabelColor = Color.black;
|
||||
|
||||
@ -9,6 +9,7 @@ import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.meteoinfo.chart.ChartText;
|
||||
import org.meteoinfo.chart.jogl.pipe.PipeShape;
|
||||
import org.meteoinfo.common.*;
|
||||
import org.meteoinfo.common.colors.ColorMap;
|
||||
import org.meteoinfo.data.GridArray;
|
||||
import org.meteoinfo.data.GridData;
|
||||
import org.meteoinfo.data.XYListDataset;
|
||||
@ -18,6 +19,7 @@ import org.meteoinfo.geo.drawing.Draw;
|
||||
import org.meteoinfo.geo.layer.ImageLayer;
|
||||
import org.meteoinfo.geo.layer.VectorLayer;
|
||||
import org.meteoinfo.geo.legend.LegendManage;
|
||||
import org.meteoinfo.geometry.colors.Normalize;
|
||||
import org.meteoinfo.geometry.graphic.Graphic;
|
||||
import org.meteoinfo.geometry.graphic.GraphicCollection;
|
||||
import org.meteoinfo.geometry.graphic.ImageGraphic;
|
||||
@ -3063,45 +3065,74 @@ public class GraphicFactory {
|
||||
int width, height, breakNum;
|
||||
width = gdata.getXNum();
|
||||
height = gdata.getYNum();
|
||||
breakNum = ls.getBreakNum();
|
||||
double[] breakValue = new double[breakNum];
|
||||
Color[] breakColor = new Color[breakNum];
|
||||
Color undefColor = Color.white;
|
||||
for (int i = 0; i < breakNum; i++) {
|
||||
breakValue[i] = Double.parseDouble(ls.getLegendBreaks().get(i).getEndValue().toString());
|
||||
breakColor[i] = ls.getLegendBreaks().get(i).getColor();
|
||||
if (ls.getLegendBreaks().get(i).isNoData()) {
|
||||
undefColor = ls.getLegendBreaks().get(i).getColor();
|
||||
}
|
||||
}
|
||||
Color defaultColor = breakColor[breakNum - 1]; //Last color
|
||||
BufferedImage aImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||
double oneValue;
|
||||
Color oneColor;
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
oneValue = gdata.getDoubleValue(i, j);
|
||||
if (Double.isNaN(oneValue) || MIMath.doubleEquals(oneValue, gdata.missingValue)) {
|
||||
oneColor = undefColor;
|
||||
if (ls.getColorMap() == null) {
|
||||
breakNum = ls.getValidBreakNum();
|
||||
double[] breakValue = new double[breakNum];
|
||||
Color[] breakColor = new Color[breakNum];
|
||||
Color undefColor = Color.white;
|
||||
int idx = 0;
|
||||
for (ColorBreak cb : ls.getLegendBreaks()) {
|
||||
if (cb.isNoData()) {
|
||||
undefColor = cb.getColor();
|
||||
} else {
|
||||
oneColor = defaultColor;
|
||||
if (ls.getLegendType() == LegendType.GRADUATED_COLOR) {
|
||||
for (int k = 0; k < breakNum - 1; k++) {
|
||||
if (oneValue < breakValue[k]) {
|
||||
oneColor = breakColor[k];
|
||||
break;
|
||||
}
|
||||
}
|
||||
breakValue[idx] = Double.parseDouble(cb.getEndValue().toString());
|
||||
breakColor[idx] = cb.getColor();
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
Color defaultColor = breakColor[breakNum - 1]; //Last color
|
||||
double oneValue;
|
||||
Color oneColor;
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
oneValue = gdata.getDoubleValue(i, j);
|
||||
if (Double.isNaN(oneValue) || MIMath.doubleEquals(oneValue, gdata.missingValue)) {
|
||||
oneColor = undefColor;
|
||||
} else {
|
||||
for (int k = 0; k < breakNum - 1; k++) {
|
||||
if (oneValue == breakValue[k]) {
|
||||
oneColor = breakColor[k];
|
||||
break;
|
||||
oneColor = defaultColor;
|
||||
if (ls.getLegendType() == LegendType.GRADUATED_COLOR) {
|
||||
for (int k = 0; k < breakNum - 1; k++) {
|
||||
if (oneValue < breakValue[k]) {
|
||||
oneColor = breakColor[k];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int k = 0; k < breakNum - 1; k++) {
|
||||
if (oneValue == breakValue[k]) {
|
||||
oneColor = breakColor[k];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
aImage.setRGB(j, height - i - 1, oneColor.getRGB());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ColorMap colorMap = ls.getColorMap();
|
||||
int n = colorMap.getColorCount();
|
||||
Normalize normalize = ls.getNormalize();
|
||||
double v;
|
||||
Color fillColor = colorMap.getFillColor();
|
||||
Color color;
|
||||
int idx;
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
v = gdata.getDoubleValue(i, j);
|
||||
if (Double.isNaN(v) || MIMath.doubleEquals(v, gdata.missingValue)) {
|
||||
color = fillColor;
|
||||
} else {
|
||||
idx = (int) (normalize.apply(v).floatValue() * n);
|
||||
if (idx < 0)
|
||||
idx = 0;
|
||||
else if (idx >= n)
|
||||
idx = n - 1;
|
||||
color = colorMap.getColor(idx);
|
||||
}
|
||||
aImage.setRGB(j, height - i - 1, color.getRGB());
|
||||
}
|
||||
aImage.setRGB(j, height - i - 1, oneColor.getRGB());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -29,6 +29,7 @@ public class ColorMap {
|
||||
// <editor-fold desc="Variables">
|
||||
private Color[] colors;
|
||||
private String name = "";
|
||||
private Color fillColor = Color.white;
|
||||
|
||||
final static int GRADS_RAINBOW = 0;
|
||||
// </editor-fold>
|
||||
@ -107,6 +108,22 @@ public class ColorMap {
|
||||
public void setColors(Color[] value){
|
||||
this.colors = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fill color
|
||||
* @return Fill color
|
||||
*/
|
||||
public Color getFillColor() {
|
||||
return this.fillColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set fill color
|
||||
* @param value Fill color
|
||||
*/
|
||||
public void setFillColor(Color value) {
|
||||
this.fillColor = value;
|
||||
}
|
||||
// </editor-fold>
|
||||
// <editor-fold desc="Methods">
|
||||
|
||||
@ -139,6 +156,23 @@ public class ColorMap {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* convert normalized data value from the interval [0, 1] to the RGBA color
|
||||
* @param value Normalized data value
|
||||
* @return Mapped color
|
||||
*/
|
||||
public Color map(double value) {
|
||||
if (value < 0 || value > 1) {
|
||||
return this.fillColor;
|
||||
}
|
||||
|
||||
int idx = (int)(value * this.colors.length);
|
||||
if (idx == this.colors.length) {
|
||||
idx = this.colors.length - 1;
|
||||
}
|
||||
return this.colors[idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set color
|
||||
|
||||
@ -87,8 +87,8 @@
|
||||
<orderEntry type="library" name="Maven: org.scilab.forge:jlatexmath:1.0.7" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.scilab.forge:jlatexmath-font-greek:1.0.7" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.scilab.forge:jlatexmath-font-cyrillic:1.0.7" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf:2.0-rc1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf-extras:2.0-rc1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf:2.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf-extras:2.0" level="project" />
|
||||
<orderEntry type="library" scope="RUNTIME" name="Maven: com.formdev:svgSalamander:1.1.3" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.freehep:freehep-util:2.0.2" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.netbeans:openide-lookup:1.9-patched-1.0" level="project" />
|
||||
|
||||
@ -463,7 +463,8 @@ public class Draw {
|
||||
// insert a border
|
||||
icon.setInsets(new Insets(5, 5, 5, 5));
|
||||
icon.setForeground(g.getColor());
|
||||
y = y - icon.getIconHeight() + (icon.getIconHeight() - icon.getTrueIconHeight()) * 0.6f;
|
||||
x = x - 5;
|
||||
y = y - icon.getIconHeight() + (icon.getIconHeight() - icon.getTrueIconHeight()) * 0.5f;
|
||||
//y = y - icon.getIconHeight() + size * 0.7f;
|
||||
//y = y - icon.getTrueIconHeight() * 1.f;
|
||||
Font font = g.getFont();
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
package org.meteoinfo.geometry.colors;
|
||||
|
||||
import org.meteoinfo.ndarray.Array;
|
||||
import org.meteoinfo.ndarray.math.ArrayMath;
|
||||
import org.meteoinfo.ndarray.math.ArrayUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Generate a colormap index based on discrete intervals
|
||||
*/
|
||||
public class BoundaryNorm extends Normalize {
|
||||
private Array boundaries;
|
||||
private int nColors;
|
||||
private int size;
|
||||
private int nRegions; //Number of colors needed
|
||||
private int offset;
|
||||
private ExtendType extendType;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param boundaries Boundaries
|
||||
* @param nColors Number of colors
|
||||
* @param extendType Extend type
|
||||
*/
|
||||
public BoundaryNorm(Array boundaries, int nColors, ExtendType extendType) {
|
||||
super();
|
||||
boundaries = boundaries.copyIfView();
|
||||
this.setMinValue(boundaries.getDouble(0));
|
||||
this.setMaxValue(boundaries.getDouble((int)boundaries.getSize() - 1));
|
||||
|
||||
this.boundaries = boundaries;
|
||||
this.nColors = nColors;
|
||||
this.size = (int) this.boundaries.getSize();
|
||||
this.extendType = extendType;
|
||||
this.nRegions = this.size - 1;
|
||||
this.offset = 0;
|
||||
switch (this.extendType) {
|
||||
case MIN:
|
||||
this.nRegions += 1;
|
||||
this.offset = 1;
|
||||
break;
|
||||
case MAX:
|
||||
this.nRegions += 1;
|
||||
break;
|
||||
case BOTH:
|
||||
this.nRegions += 2;
|
||||
this.offset = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of color regions
|
||||
* @return Number of color regions
|
||||
*/
|
||||
public int getNRegions() {
|
||||
return this.nRegions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number apply(double v) {
|
||||
int idx = ArrayUtil.searchSorted(this.boundaries, v, true) - 1 + this.offset;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Array apply(Array a) {
|
||||
Array r = ArrayUtil.searchSorted(this.boundaries, a, false);
|
||||
r = ArrayMath.add(r, this.offset - 1);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double inverse(double v) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Array inverse(Array a) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package org.meteoinfo.geometry.colors;
|
||||
|
||||
public enum ExtendType {
|
||||
NEITHER,
|
||||
BOTH,
|
||||
MIN,
|
||||
MAX
|
||||
}
|
||||
@ -0,0 +1,101 @@
|
||||
package org.meteoinfo.geometry.colors;
|
||||
|
||||
import org.meteoinfo.ndarray.Array;
|
||||
import org.meteoinfo.ndarray.DataType;
|
||||
import org.meteoinfo.ndarray.IndexIterator;
|
||||
import org.meteoinfo.ndarray.math.ArrayMath;
|
||||
import org.meteoinfo.ndarray.math.ArrayUtil;
|
||||
|
||||
/**
|
||||
* Normalize a given value to the 0-1 range on a log scale
|
||||
*/
|
||||
public class LogNorm extends Normalize {
|
||||
private double min;
|
||||
private double max;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param minValue Minimum value
|
||||
* @param maxValue Maximum value
|
||||
*/
|
||||
public LogNorm(double minValue, double maxValue) {
|
||||
this(minValue, maxValue, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param minValue Minimum value
|
||||
* @param maxValue Maximum value
|
||||
* @param clip Clip
|
||||
*/
|
||||
public LogNorm(double minValue, double maxValue, boolean clip) {
|
||||
this.minValue = minValue;
|
||||
this.maxValue = maxValue;
|
||||
this.clip = clip;
|
||||
this.min = Math.log10(minValue);
|
||||
this.max = Math.log10(maxValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number apply(double v) {
|
||||
double range = max - min;
|
||||
v = Math.log10(v);
|
||||
v = (v - min) / range;
|
||||
if (clip) {
|
||||
if (v < 0)
|
||||
v = 0;
|
||||
else if (v > 1)
|
||||
v = 1;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Array apply(Array a) {
|
||||
this.autoScaleNull(a);
|
||||
|
||||
Array r = Array.factory(DataType.DOUBLE, a.getShape());
|
||||
IndexIterator iterA = a.getIndexIterator();
|
||||
IndexIterator iterR = r.getIndexIterator();
|
||||
double v, range = max - min;
|
||||
if (clip) {
|
||||
while (iterA.hasNext()) {
|
||||
v = Math.log10(iterA.getDoubleNext());
|
||||
v = (v - min) / range;
|
||||
if (v < 0)
|
||||
v = 0;
|
||||
else if (v > 1)
|
||||
v = 1;
|
||||
iterR.setDoubleNext(v);
|
||||
}
|
||||
} else {
|
||||
while (iterA.hasNext()) {
|
||||
v = iterA.getDoubleNext();
|
||||
v = (v - min) / range;
|
||||
iterR.setDoubleNext(v);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double inverse(double v) {
|
||||
return Math.pow(10, min + v * (max - min));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Array inverse(Array a) {
|
||||
Array r = Array.factory(DataType.DOUBLE, a.getShape());
|
||||
IndexIterator iterA = a.getIndexIterator();
|
||||
IndexIterator iterR = r.getIndexIterator();
|
||||
double v, range = max - min;
|
||||
while (iterA.hasNext()) {
|
||||
v = iterA.getDoubleNext();
|
||||
v = Math.pow(10, min + v * range);
|
||||
iterR.setDoubleNext(v);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,200 @@
|
||||
package org.meteoinfo.geometry.colors;
|
||||
|
||||
import org.meteoinfo.ndarray.Array;
|
||||
import org.meteoinfo.ndarray.DataType;
|
||||
import org.meteoinfo.ndarray.IndexIterator;
|
||||
import org.meteoinfo.ndarray.math.ArrayMath;
|
||||
|
||||
/**
|
||||
* A class which, when called, linearly normalizes data into the [0.0, 1.0] interval.
|
||||
*/
|
||||
public class Normalize {
|
||||
protected Double minValue;
|
||||
protected Double maxValue;
|
||||
protected boolean clip;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public Normalize() {
|
||||
this.minValue = null;
|
||||
this.maxValue = null;
|
||||
this.clip = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param minValue Minimum value
|
||||
* @param maxValue Maximum value
|
||||
*/
|
||||
public Normalize(double minValue, double maxValue) {
|
||||
this.minValue = minValue;
|
||||
this.maxValue = maxValue;
|
||||
this.clip = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param minValue Minimum value
|
||||
* @param maxValue Maximum value
|
||||
* @param clip Clip
|
||||
*/
|
||||
public Normalize(double minValue, double maxValue, boolean clip) {
|
||||
this.minValue = minValue;
|
||||
this.maxValue = maxValue;
|
||||
this.clip = clip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get minimum value
|
||||
* @return Minimum value
|
||||
*/
|
||||
public double getMinValue() {
|
||||
return this.minValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set minimum value
|
||||
* @param value Minimum value
|
||||
*/
|
||||
public void setMinValue(double value) {
|
||||
this.minValue = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get maximum value
|
||||
* @return Maximum value
|
||||
*/
|
||||
public double getMaxValue() {
|
||||
return this.maxValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set maximum value
|
||||
* @param value Maximum value
|
||||
*/
|
||||
public void setMaxValue(double value) {
|
||||
this.maxValue = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get is clip or not
|
||||
* @return Clip or not
|
||||
*/
|
||||
public boolean isClip() {
|
||||
return this.clip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set clip or not
|
||||
* @param value Clip or not
|
||||
*/
|
||||
public void setClip(boolean value) {
|
||||
this.clip = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set minimum and maximum values by data array
|
||||
* @param a The data array
|
||||
*/
|
||||
public void autoScale(Array a) {
|
||||
this.minValue = ArrayMath.min(a).doubleValue();
|
||||
this.maxValue = ArrayMath.max(a).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set minimum and maximum values by data array if minValue or maxValue is not set
|
||||
* @param a The data array
|
||||
*/
|
||||
public void autoScaleNull(Array a) {
|
||||
if (this.minValue == null)
|
||||
this.minValue = ArrayMath.min(a).doubleValue();
|
||||
if (this.maxValue == null)
|
||||
this.maxValue = ArrayMath.max(a).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether minimum and maximum values are set
|
||||
* @return Boolean
|
||||
*/
|
||||
public boolean isScaled() {
|
||||
return this.minValue != null && this.maxValue != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a value
|
||||
* @param v The value
|
||||
* @return Normalized value
|
||||
*/
|
||||
public Number apply(double v) {
|
||||
double range = maxValue - minValue;
|
||||
v = (v - minValue) / range;
|
||||
if (clip) {
|
||||
if (v < 0)
|
||||
v = 0;
|
||||
else if (v > 1)
|
||||
v = 1;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the data array
|
||||
* @param a The data array
|
||||
* @return Normalized data array
|
||||
*/
|
||||
public Array apply(Array a) {
|
||||
this.autoScaleNull(a);
|
||||
|
||||
Array r = Array.factory(DataType.DOUBLE, a.getShape());
|
||||
IndexIterator iterA = a.getIndexIterator();
|
||||
IndexIterator iterR = r.getIndexIterator();
|
||||
double v, range = maxValue - minValue;
|
||||
if (clip) {
|
||||
while (iterA.hasNext()) {
|
||||
v = iterA.getDoubleNext();
|
||||
v = (v - minValue) / range;
|
||||
if (v < 0)
|
||||
v = 0;
|
||||
else if (v > 1)
|
||||
v = 1;
|
||||
iterR.setDoubleNext(v);
|
||||
}
|
||||
} else {
|
||||
while (iterA.hasNext()) {
|
||||
v = iterA.getDoubleNext();
|
||||
v = (v - minValue) / range;
|
||||
iterR.setDoubleNext(v);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse data value
|
||||
* @param v The data value
|
||||
* @return Inverse data value
|
||||
*/
|
||||
public double inverse(double v) {
|
||||
return minValue + v * (maxValue - minValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse data array
|
||||
* @param a The data array
|
||||
* @return Inverse data array
|
||||
*/
|
||||
public Array inverse(Array a) {
|
||||
Array r = Array.factory(DataType.DOUBLE, a.getShape());
|
||||
IndexIterator iterA = a.getIndexIterator();
|
||||
IndexIterator iterR = r.getIndexIterator();
|
||||
double v, range = maxValue - minValue;
|
||||
while (iterA.hasNext()) {
|
||||
v = iterA.getDoubleNext();
|
||||
v = minValue + v * range;
|
||||
iterR.setDoubleNext(v);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
@ -18,6 +18,7 @@ package org.meteoinfo.geometry.legend;
|
||||
import org.meteoinfo.common.DataConvert;
|
||||
import org.meteoinfo.common.colors.ColorMap;
|
||||
import org.meteoinfo.common.colors.ColorUtil;
|
||||
import org.meteoinfo.geometry.colors.Normalize;
|
||||
import org.meteoinfo.geometry.shape.ShapeTypes;
|
||||
import org.w3c.dom.*;
|
||||
import org.xml.sax.SAXException;
|
||||
@ -55,6 +56,8 @@ package org.meteoinfo.geometry.legend;
|
||||
private double maxValue;
|
||||
private double undef;
|
||||
private Map<Object, ColorBreak> uniqueValueMap;
|
||||
private ColorMap colorMap;
|
||||
private Normalize normalize;
|
||||
// </editor-fold>
|
||||
// <editor-fold desc="Constructor">
|
||||
/**
|
||||
@ -356,6 +359,25 @@ package org.meteoinfo.geometry.legend;
|
||||
return legendBreaks.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get valid legend breaks number
|
||||
*
|
||||
* @return The valid legend breaks number
|
||||
*/
|
||||
public int getValidBreakNum() {
|
||||
if (this.hasNoData) {
|
||||
int n = 0;
|
||||
for (ColorBreak aCB : this.legendBreaks) {
|
||||
if (!aCB.isNoData()) {
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
} else {
|
||||
return getBreakNum();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get visible legend breaks number
|
||||
*
|
||||
@ -387,6 +409,40 @@ package org.meteoinfo.geometry.legend;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get color map
|
||||
* @return Color map
|
||||
*/
|
||||
public ColorMap getColorMap() {
|
||||
return this.colorMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set color map
|
||||
* @param value Color map
|
||||
*/
|
||||
public void setColorMap(ColorMap value) {
|
||||
this.colorMap = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get normalize
|
||||
* @return Normalize
|
||||
*/
|
||||
public Normalize getNormalize() {
|
||||
return this.normalize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set normalize
|
||||
* @param value Normalize
|
||||
*/
|
||||
public void setNormalize(Normalize value) {
|
||||
this.normalize = value;
|
||||
this.minValue = normalize.getMinValue();
|
||||
this.maxValue = normalize.getMaxValue();
|
||||
}
|
||||
// </editor-fold>
|
||||
// <editor-fold desc="Methods">
|
||||
/**
|
||||
|
||||
@ -82,8 +82,8 @@
|
||||
<orderEntry type="module" module-name="meteoinfo-dataframe" />
|
||||
<orderEntry type="library" name="Maven: edu.ucar:netcdfAll:5.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.github.albfernandez:juniversalchardet:2.4.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf:2.0-rc1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf-extras:2.0-rc1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf:2.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf-extras:2.0" level="project" />
|
||||
<orderEntry type="library" scope="RUNTIME" name="Maven: com.formdev:svgSalamander:1.1.3" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.itextpdf:itextpdf:5.5.13.2" level="project" />
|
||||
<orderEntry type="module" module-name="meteoinfo-ui" />
|
||||
|
||||
@ -1,32 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<MeteoInfo File="milconfig.xml" Type="configurefile">
|
||||
<Path OpenPath="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl">
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\toolbox\miml"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\toolbox\miml\model_persistence"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map\projection"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\grads"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\satellite\calipso"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\traj"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\traj\TrajStat"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\satellite"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\satellite\modis"/>
|
||||
<Path OpenPath="D:\Working\MIScript\Jython\mis\plot_types">
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d_earth"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\scatter"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\plot"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\chart\latex"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\chart"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math\stats"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\chart\legend"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\array"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\satellite"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\contour"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
|
||||
</Path>
|
||||
<File>
|
||||
<OpenedFiles>
|
||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d_earth\streamslice_pitch.py"/>
|
||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\volumeplot_perspective.py"/>
|
||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\volumeplot_1.py"/>
|
||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\satellite\OMPS-NPP_LP-L2_2.py"/>
|
||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\scatter\scatterm_1.py"/>
|
||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\imshow.py"/>
|
||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\imshow_normalize.py"/>
|
||||
</OpenedFiles>
|
||||
<RecentFiles>
|
||||
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d_earth\streamslice_pitch.py"/>
|
||||
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\volumeplot_perspective.py"/>
|
||||
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\volumeplot_1.py"/>
|
||||
<RecentFile File="D:\Working\MIScript\Jython\mis\satellite\OMPS-NPP_LP-L2_2.py"/>
|
||||
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\scatter\scatterm_1.py"/>
|
||||
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\imshow.py"/>
|
||||
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\imshow_normalize.py"/>
|
||||
</RecentFiles>
|
||||
</File>
|
||||
<Font>
|
||||
@ -34,5 +36,5 @@
|
||||
</Font>
|
||||
<LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/>
|
||||
<Figure DoubleBuffering="true"/>
|
||||
<Startup MainFormLocation="-7,0" MainFormSize="1398,815"/>
|
||||
<Startup MainFormLocation="-7,-7" MainFormSize="1293,685"/>
|
||||
</MeteoInfo>
|
||||
|
||||
Binary file not shown.
@ -8,9 +8,11 @@ from ._figure import Figure
|
||||
from ._glfigure import GLFigure
|
||||
from .patches import *
|
||||
from .lines import *
|
||||
from .colors import *
|
||||
|
||||
|
||||
__all__ = ['Figure','GLFigure','Axes','PolarAxes','MapAxes','Axes3D','Axes3DGL']
|
||||
__all__ += miplot.__all__
|
||||
__all__ += patches.__all__
|
||||
__all__ += lines.__all__
|
||||
__all__ += lines.__all__
|
||||
__all__ += colors.__all__
|
||||
Binary file not shown.
@ -17,6 +17,7 @@ from org.meteoinfo.geometry.legend import BarBreak, PolygonBreak, PolylineBreak,
|
||||
PointBreak, LineStyles, PointStyle, LegendScheme, LegendType
|
||||
from org.meteoinfo.geometry.shape import ShapeTypes
|
||||
from org.meteoinfo.geometry.graphic import Graphic, GraphicCollection
|
||||
from org.meteoinfo.geometry.colors import ExtendType
|
||||
from org.meteoinfo.common import MIMath, Extent
|
||||
from org.meteoinfo.geo.layer import MapLayer
|
||||
|
||||
@ -32,6 +33,7 @@ import mipylib.numeric as np
|
||||
from mipylib.numeric.core import DimArray, NDArray
|
||||
from mipylib.geolib.milayer import MILayer, MIXYListData
|
||||
import plotutil
|
||||
import colors
|
||||
import mipylib.miutil as miutil
|
||||
|
||||
__all__ = ['Axes','PolarAxes']
|
||||
@ -2114,12 +2116,6 @@ class Axes(object):
|
||||
if isinstance(a, DimArray):
|
||||
y = a.dimvalue(0)
|
||||
x = a.dimvalue(1)
|
||||
# if args[0].islondim(1):
|
||||
# xaxistype = 'lon'
|
||||
# elif args[0].islatdim(1):
|
||||
# xaxistype = 'lat'
|
||||
# elif args[0].istimedim(1):
|
||||
# xaxistype = 'time'
|
||||
else:
|
||||
x = np.arange(a.shape[1])
|
||||
y = np.arange(a.shape[0])
|
||||
@ -2129,21 +2125,27 @@ class Axes(object):
|
||||
y = args[1]
|
||||
a = args[2]
|
||||
args = args[3:]
|
||||
|
||||
vmin = kwargs.pop('vmin', a.min())
|
||||
vmax = kwargs.pop('vmax', a.max())
|
||||
if ls is None:
|
||||
if len(args) > 0:
|
||||
level_arg = args[0]
|
||||
if isinstance(level_arg, int):
|
||||
cn = level_arg
|
||||
ls = LegendManage.createLegendScheme(a.min(), a.max(), cn, cmap)
|
||||
ls = LegendManage.createLegendScheme(vmin, vmax, cn, cmap)
|
||||
else:
|
||||
if isinstance(level_arg, NDArray):
|
||||
level_arg = level_arg.aslist()
|
||||
ls = LegendManage.createLegendScheme(a.min(), a.max(), level_arg, cmap)
|
||||
ls = LegendManage.createLegendScheme(vmin, vmax, level_arg, cmap)
|
||||
else:
|
||||
ls = LegendManage.createLegendScheme(a.min(), a.max(), cmap)
|
||||
ls = LegendManage.createLegendScheme(vmin, vmax, cmap)
|
||||
ls = ls.convertTo(ShapeTypes.POLYLINE)
|
||||
plotutil.setlegendscheme(ls, **kwargs)
|
||||
|
||||
|
||||
# norm = kwargs.pop('norm', colors.Normalize(vmin, vmax))
|
||||
# ls.setNormalize(norm._norm)
|
||||
# ls.setColorMap(cmap)
|
||||
smooth = kwargs.pop('smooth', True)
|
||||
if x.ndim == 2 and y.ndim == 2:
|
||||
griddata_props = kwargs.pop('griddata_props', dict(method='idw', pointnum=5, convexhull=True))
|
||||
@ -2246,12 +2248,6 @@ class Axes(object):
|
||||
if isinstance(a, DimArray):
|
||||
y = a.dimvalue(0)
|
||||
x = a.dimvalue(1)
|
||||
# if args[0].islondim(1):
|
||||
# xaxistype = 'lon'
|
||||
# elif args[0].islatdim(1):
|
||||
# xaxistype = 'lat'
|
||||
# elif args[0].istimedim(1):
|
||||
# xaxistype = 'time'
|
||||
else:
|
||||
x = np.arange(a.shape[1])
|
||||
y = np.arange(a.shape[0])
|
||||
@ -2260,24 +2256,29 @@ class Axes(object):
|
||||
x = args[0]
|
||||
y = args[1]
|
||||
a = args[2]
|
||||
#gdata = np.asgriddata(a, x, y, fill_value)
|
||||
args = args[3:]
|
||||
|
||||
vmin = kwargs.pop('vmin', a.min())
|
||||
vmax = kwargs.pop('vmax', a.max())
|
||||
if ls is None:
|
||||
if len(args) > 0:
|
||||
level_arg = args[0]
|
||||
if isinstance(level_arg, int):
|
||||
cn = level_arg
|
||||
ls = LegendManage.createLegendScheme(a.min(), a.max(), cn, cmap)
|
||||
ls = LegendManage.createLegendScheme(vmin, vmax, cn, cmap)
|
||||
else:
|
||||
if isinstance(level_arg, NDArray):
|
||||
level_arg = level_arg.aslist()
|
||||
ls = LegendManage.createLegendScheme(a.min(), a.max(), level_arg, cmap)
|
||||
ls = LegendManage.createLegendScheme(vmin, vmax, level_arg, cmap)
|
||||
else:
|
||||
ls = LegendManage.createLegendScheme(a.min(), a.max(), cmap)
|
||||
ls = LegendManage.createLegendScheme(vmin, vmax, cmap)
|
||||
ls = ls.convertTo(ShapeTypes.POLYGON)
|
||||
if not kwargs.has_key('edgecolor'):
|
||||
kwargs['edgecolor'] = None
|
||||
plotutil.setlegendscheme(ls, **kwargs)
|
||||
# norm = kwargs.pop('norm', colors.Normalize(vmin, vmax))
|
||||
# ls.setNormalize(norm._norm)
|
||||
# ls.setColorMap(cmap)
|
||||
smooth = kwargs.pop('smooth', True)
|
||||
if x.ndim == 2 and y.ndim == 2:
|
||||
griddata_props = kwargs.pop('griddata_props', dict(method='idw', pointnum=5, convexhull=True))
|
||||
@ -2333,13 +2334,6 @@ class Axes(object):
|
||||
isrgb = True
|
||||
else:
|
||||
gdata = np.asgridarray(X)
|
||||
# if isinstance(X, DimArray):
|
||||
# if X.islondim(1):
|
||||
# xaxistype = 'lon'
|
||||
# elif X.islatdim(1):
|
||||
# xaxistype = 'lat'
|
||||
# elif X.istimedim(1):
|
||||
# xaxistype = 'time'
|
||||
args = args[1:]
|
||||
|
||||
extent = kwargs.pop('extent', extent)
|
||||
@ -2359,6 +2353,8 @@ class Axes(object):
|
||||
else:
|
||||
ls = kwargs.pop('symbolspec', None)
|
||||
if ls is None:
|
||||
vmin = kwargs.pop('vmin', gdata.min())
|
||||
vmax = kwargs.pop('vmax', gdata.max())
|
||||
if len(args) > 0:
|
||||
level_arg = args[0]
|
||||
if isinstance(level_arg, int):
|
||||
@ -2369,11 +2365,14 @@ class Axes(object):
|
||||
level_arg = level_arg.aslist()
|
||||
ls = LegendManage.createImageLegend(gdata, level_arg, cmap)
|
||||
else:
|
||||
ls = plotutil.getlegendscheme(args, gdata.min(), gdata.max(), **kwargs)
|
||||
ls = plotutil.getlegendscheme(args, vmin, vmax, **kwargs)
|
||||
norm = kwargs.pop('norm', colors.Normalize(vmin, vmax))
|
||||
ls.setNormalize(norm._norm)
|
||||
ls.setColorMap(cmap)
|
||||
ls = ls.convertTo(ShapeTypes.IMAGE)
|
||||
plotutil.setlegendscheme(ls, **kwargs)
|
||||
|
||||
igraphic = GraphicFactory.createImage(gdata, ls, extent)
|
||||
|
||||
interpolation = kwargs.pop('interpolation', None)
|
||||
if not interpolation is None:
|
||||
igraphic.getShape().setInterpolation(interpolation)
|
||||
@ -3517,6 +3516,8 @@ class Axes(object):
|
||||
for lb in args[0]:
|
||||
if isinstance(lb, Graphic):
|
||||
lbs.append(lb.getLegend().clone())
|
||||
elif isinstance(lb, MILayer):
|
||||
lbs.extend(lb.legend().getLegendBreaks())
|
||||
else:
|
||||
lbs.append(lb)
|
||||
if len(args) == 2:
|
||||
@ -3744,6 +3745,8 @@ class Axes(object):
|
||||
legend.setPlotOrientation(PlotOrientation.VERTICAL)
|
||||
legend.setPosition(LegendPosition.RIGHT_OUTSIDE)
|
||||
legend.setDrawNeatLine(False)
|
||||
extend = kwargs.pop('extend', 'neither')
|
||||
legend.setExtendType(extend)
|
||||
extendrect = kwargs.pop('extendrect', True)
|
||||
legend.setExtendRect(extendrect)
|
||||
extendfrac = kwargs.pop('extendfrac', None)
|
||||
@ -3802,6 +3805,8 @@ class Axes(object):
|
||||
edgesize = kwargs.pop('edgesize')
|
||||
legend.setNeatLineSize(edgesize)
|
||||
|
||||
return legend
|
||||
|
||||
|
||||
###############################################
|
||||
class PolarAxes(Axes):
|
||||
|
||||
171
meteoinfo-lab/pylib/mipylib/plotlib/colors.py
Normal file
171
meteoinfo-lab/pylib/mipylib/plotlib/colors.py
Normal file
@ -0,0 +1,171 @@
|
||||
from org.meteoinfo.geometry.colors import Normalize as JNormalize
|
||||
from org.meteoinfo.geometry.colors import LogNorm as JLogNorm
|
||||
from org.meteoinfo.geometry.colors import BoundaryNorm as JBoundaryNorm
|
||||
from org.meteoinfo.geometry.colors import ExtendType
|
||||
from org.meteoinfo.ndarray import Array
|
||||
|
||||
import mipylib.numeric as np
|
||||
|
||||
__all__ = ['Normalize','LogNorm','BoundaryNorm']
|
||||
|
||||
class Normalize(object):
|
||||
"""
|
||||
A class which, when called, linearly normalizes data into the
|
||||
``[0.0, 1.0]`` interval.
|
||||
"""
|
||||
|
||||
def __init__(self, vmin=None, vmax=None, clip=False):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
vmin, vmax : float or None
|
||||
If *vmin* and/or *vmax* is not given, they are initialized from the
|
||||
minimum and maximum value, respectively, of the first input
|
||||
processed; i.e., ``__call__(A)`` calls ``autoscale_None(A)``.
|
||||
clip : bool, default: False
|
||||
If ``True`` values falling outside the range ``[vmin, vmax]``,
|
||||
are mapped to 0 or 1, whichever is closer, and masked values are
|
||||
set to 1. If ``False`` masked values remain masked.
|
||||
Clipping silently defeats the purpose of setting the over, under,
|
||||
and masked colors in a colormap, so it is likely to lead to
|
||||
surprises; therefore the default is ``clip=False``.
|
||||
Notes
|
||||
-----
|
||||
Returns 0 if ``vmin == vmax``.
|
||||
"""
|
||||
self._norm = JNormalize(vmin, vmax, clip)
|
||||
|
||||
@property
|
||||
def vmin(self):
|
||||
return self._norm.getMinValue()
|
||||
|
||||
@vmin.setter
|
||||
def vmin(self, value):
|
||||
if value != self._norm.getMinValue():
|
||||
self._norm.setMinValue(value)
|
||||
|
||||
@property
|
||||
def vmax(self):
|
||||
return self._norm.getMaxValue()
|
||||
|
||||
@vmax.setter
|
||||
def vmax(self, value):
|
||||
if value != self._norm.getMaxValue():
|
||||
self._norm.setMaxValue(value)
|
||||
|
||||
@property
|
||||
def clip(self):
|
||||
return self._norm.getClip()
|
||||
|
||||
@clip.setter
|
||||
def clip(self, value):
|
||||
if value != self._norm.getClip():
|
||||
self._norm.setClip(value)
|
||||
|
||||
def __call__(self, value, clip=None):
|
||||
"""
|
||||
Normalize *value* data in the ``[vmin, vmax]`` interval into the
|
||||
``[0.0, 1.0]`` interval and return it.
|
||||
Parameters
|
||||
----------
|
||||
value
|
||||
Data to normalize.
|
||||
clip : bool
|
||||
If ``None``, defaults to ``self.clip`` (which defaults to
|
||||
``False``).
|
||||
Notes
|
||||
-----
|
||||
If not already initialized, ``self.vmin`` and ``self.vmax`` are
|
||||
initialized using ``self.autoscale_None(value)``.
|
||||
"""
|
||||
if not clip is None:
|
||||
self._norm.setClip(clip)
|
||||
|
||||
if isinstance(value, (list, tuple)):
|
||||
value = np.array(value)
|
||||
|
||||
r = self._norm.apply(value._array)
|
||||
if isinstance(r, Array):
|
||||
return np.array(r)
|
||||
else:
|
||||
return r
|
||||
|
||||
def inverse(self, value):
|
||||
if isinstance(value, (list, tuple)):
|
||||
value = np.array(value)
|
||||
|
||||
r = self._norm.inverse(value._array)
|
||||
if isinstance(r, Array):
|
||||
return np.array(r)
|
||||
else:
|
||||
return r
|
||||
|
||||
class LogNorm(Normalize):
|
||||
"""Normalize a given value to the 0-1 range on a log scale."""
|
||||
|
||||
def __init__(self, vmin=None, vmax=None, clip=False):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
vmin, vmax : float or None
|
||||
If *vmin* and/or *vmax* is not given, they are initialized from the
|
||||
minimum and maximum value, respectively, of the first input
|
||||
processed; i.e., ``__call__(A)`` calls ``autoscale_None(A)``.
|
||||
clip : bool, default: False
|
||||
If ``True`` values falling outside the range ``[vmin, vmax]``,
|
||||
are mapped to 0 or 1, whichever is closer, and masked values are
|
||||
set to 1. If ``False`` masked values remain masked.
|
||||
Clipping silently defeats the purpose of setting the over, under,
|
||||
and masked colors in a colormap, so it is likely to lead to
|
||||
surprises; therefore the default is ``clip=False``.
|
||||
Notes
|
||||
-----
|
||||
Returns 0 if ``vmin == vmax``.
|
||||
"""
|
||||
self._norm = JLogNorm(vmin, vmax, clip)
|
||||
|
||||
class BoundaryNorm(Normalize):
|
||||
"""
|
||||
Generate a colormap index based on discrete intervals.
|
||||
Unlike `Normalize` or `LogNorm`, `BoundaryNorm` maps values to integers
|
||||
instead of to the interval 0-1.
|
||||
Mapping to the 0-1 interval could have been done via piece-wise linear
|
||||
interpolation, but using integers seems simpler, and reduces the number of
|
||||
conversions back and forth between integer and floating point.
|
||||
"""
|
||||
def __init__(self, boundaries, ncolors, clip=False, extend='neither'):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
boundaries : array-like
|
||||
Monotonically increasing sequence of at least 2 boundaries.
|
||||
ncolors : int
|
||||
Number of colors in the colormap to be used.
|
||||
clip : bool, optional
|
||||
If clip is ``True``, out of range values are mapped to 0 if they
|
||||
are below ``boundaries[0]`` or mapped to ``ncolors - 1`` if they
|
||||
are above ``boundaries[-1]``.
|
||||
If clip is ``False``, out of range values are mapped to -1 if
|
||||
they are below ``boundaries[0]`` or mapped to *ncolors* if they are
|
||||
above ``boundaries[-1]``.
|
||||
extend : {'neither', 'both', 'min', 'max'}, default: 'neither'
|
||||
Extend the number of bins to include one or both of the
|
||||
regions beyond the boundaries.
|
||||
Returns
|
||||
-------
|
||||
int16 scalar or array
|
||||
Notes
|
||||
-----
|
||||
*boundaries* defines the edges of bins, and data falling within a bin
|
||||
is mapped to the color with the same index.
|
||||
If the number of bins, including any extensions, is less than
|
||||
*ncolors*, the color index is chosen by linear interpolation, mapping
|
||||
the ``[0, nbins - 1]`` range onto the ``[0, ncolors - 1]`` range.
|
||||
"""
|
||||
super(BoundaryNorm, self).__init__(vmin=boundaries[0], vmax=boundaries[-1], clip=clip)
|
||||
|
||||
if isinstance(boundaries, (list, tuple)):
|
||||
boundaries = np.array(boundaries)
|
||||
|
||||
extend = ExtendType.valueOf(extend.upper())
|
||||
self._norm = JBoundaryNorm(boundaries._array, ncolors, extend)
|
||||
Binary file not shown.
@ -2096,8 +2096,9 @@ def colorbar(mappable=None, **kwargs):
|
||||
cax = kwargs.pop('cax', None)
|
||||
if cax is None:
|
||||
cax = g_axes
|
||||
cax.colorbar(mappable, **kwargs)
|
||||
cb = cax.colorbar(mappable, **kwargs)
|
||||
draw_if_interactive()
|
||||
return cb
|
||||
|
||||
# def set(obj, **kwargs):
|
||||
# '''
|
||||
|
||||
@ -73,8 +73,8 @@
|
||||
<orderEntry type="module" module-name="meteoinfo-dataframe" />
|
||||
<orderEntry type="library" name="Maven: edu.ucar:netcdfAll:5.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.github.albfernandez:juniversalchardet:2.4.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf:2.0-rc1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf-extras:2.0-rc1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf:2.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.formdev:flatlaf-extras:2.0" level="project" />
|
||||
<orderEntry type="library" scope="RUNTIME" name="Maven: com.formdev:svgSalamander:1.1.3" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.itextpdf:itextpdf:5.5.13.2" level="project" />
|
||||
<orderEntry type="module" module-name="meteoinfo-ui" />
|
||||
|
||||
@ -2263,7 +2263,7 @@ public class ArrayUtil {
|
||||
else if (idx == -(a.getSize() + 1))
|
||||
idx = (int)a.getSize();
|
||||
else {
|
||||
idx = -idx - 2;
|
||||
idx = -idx - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user