diff --git a/jplotter/src/main/java/hageldave/jplotter/renderables/Legend.java b/jplotter/src/main/java/hageldave/jplotter/renderables/Legend.java index c4954bac..e1d8f678 100644 --- a/jplotter/src/main/java/hageldave/jplotter/renderables/Legend.java +++ b/jplotter/src/main/java/hageldave/jplotter/renderables/Legend.java @@ -4,6 +4,7 @@ import java.awt.Font; import java.awt.geom.Rectangle2D; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.Map; @@ -12,11 +13,13 @@ import org.w3c.dom.Element; import hageldave.jplotter.canvas.FBOCanvas; +import hageldave.jplotter.color.ColorMap; import hageldave.jplotter.font.CharacterAtlas; import hageldave.jplotter.misc.Glyph; import hageldave.jplotter.renderers.CompleteRenderer; import hageldave.jplotter.renderers.Renderer; import hageldave.jplotter.util.Annotations.GLContextRequired; +import hageldave.jplotter.util.Utils; /** * The Legend class is {@link Renderable} and its own {@link Renderer} at once. @@ -37,14 +40,18 @@ */ public class Legend implements Renderable, Renderer { - protected ArrayList glyphLabels = new ArrayList<>(); + protected ArrayList glyphLabels = new ArrayList<>(0); - protected ArrayList lineLabels = new ArrayList<>(); + protected ArrayList lineLabels = new ArrayList<>(0); + + protected ArrayList colormapLabels = new ArrayList<>(0); protected Map glyph2points = new LinkedHashMap<>(); protected Map pattern2lines = new LinkedHashMap<>(); + protected LinkedList triangles = new LinkedList<>(); + protected LinkedList texts = new LinkedList<>(); protected CompleteRenderer delegate = new CompleteRenderer(); @@ -92,6 +99,34 @@ public LineLabel(String labelText, double thickness, int color, int pickColor){ } } + protected static class ColormapLabel { + public String labelText; + public ColorMap cmap; + public boolean vertical; + public int pickColor; + public double[] ticks; + public String[] ticklabels; + + public ColormapLabel(String labelText, ColorMap cmap, boolean vertical, int pickColor, double[] ticks, String[] ticklabels) { + this.labelText = labelText; + this.cmap = cmap; + this.vertical = vertical; + this.pickColor = pickColor; + this.ticks = ticks == null ? new double[0]:ticks; + this.ticklabels = ticklabels == null ? new String[0]:ticklabels; + } + + public ColormapLabel(String labelText, ColorMap cmap, boolean vertical, int pickColor, double[] ticks) { + this(labelText, cmap, vertical, pickColor, ticks, null); + } + + public ColormapLabel(String labelText, ColorMap cmap, boolean vertical, int pickColor) { + this(labelText, cmap, vertical, pickColor, null, null); + } + + + } + /** * Sets the {@link #isDirty()} state of this legend to true. * This indicates that a call to {@link #updateGL()} is necessary @@ -164,6 +199,82 @@ public Legend addLineLabel(double thickness, int color, String labeltxt){ return addLineLabel(thickness, color, labeltxt, 0); } + /** + * Adds a label for a color map to this legend. + * @param labelText text for the label + * @param cmap color map to label + * @param vertical orientation of the colormap + * @param pickColor picking color (see {@link FBOCanvas}) + * @param ticks tick marks for the map + * @param ticklabels labels for the tick marks + * @return this for chaining + */ + public Legend addColormapLabel(String labelText, ColorMap cmap, boolean vertical, int pickColor, double[] ticks, String[] ticklabels){ + colormapLabels.add(new ColormapLabel(labelText, cmap, vertical, pickColor, ticks, ticklabels)); + return setDirty(); + } + + /** + * Adds a label for a color map to this legend. + * @param labelText text for the label + * @param cmap color map to label + * @param vertical orientation of the colormap + * @param pickColor picking color (see {@link FBOCanvas}) + * @param ticks tick marks for the map + * @return this for chaining + */ + public Legend addColormapLabel(String labelText, ColorMap cmap, boolean vertical, int pickColor, double[] ticks){ + return addColormapLabel(labelText, cmap, vertical, pickColor, ticks, null); + } + + /** + * Adds a label for a color map to this legend. + * @param labelText text for the label + * @param cmap color map to label + * @param vertical orientation of the colormap + * @param pickColor picking color (see {@link FBOCanvas}) + * @return this for chaining + */ + public Legend addColormapLabel(String labelText, ColorMap cmap, boolean vertical, int pickColor){ + return addColormapLabel(labelText, cmap, vertical, pickColor, null, null); + } + + /** + * Adds a label for a color map to this legend. + * @param labelText text for the label + * @param cmap color map to label + * @param vertical orientation of the colormap + * @param ticks tick marks for the map + * @param ticklabels labels for the tick marks + * @return this for chaining + */ + public Legend addColormapLabel(String labelText, ColorMap cmap, boolean vertical, double[] ticks, String[] ticklabels){ + return addColormapLabel(labelText, cmap, vertical, 0, ticks, ticklabels); + } + + /** + * Adds a label for a color map to this legend. + * @param labelText text for the label + * @param cmap color map to label + * @param vertical orientation of the colormap + * @param ticks tick marks for the map + * @return this for chaining + */ + public Legend addColormapLabel(String labelText, ColorMap cmap, boolean vertical, double[] ticks){ + return addColormapLabel(labelText, cmap, vertical, 0, ticks, null); + } + + /** + * Adds a label for a color map to this legend. + * @param labelText text for the label + * @param cmap color map to label + * @param vertical orientation of the colormap + * @return this for chaining + */ + public Legend addColormapLabel(String labelText, ColorMap cmap, boolean vertical){ + return addColormapLabel(labelText, cmap, vertical, 0, null, null); + } + /** * NOOP */ @@ -178,7 +289,7 @@ public boolean isDirty() { } /** - * Purges all {@link Points}, {@link Lines} and {@link Text}s of this Legend. + * Purges all {@link Points}, {@link Lines}, {@link Triangles} and {@link Text}s of this Legend. * Then these Renderables are created again while laying them out according to * the available viewport size. */ @@ -256,6 +367,65 @@ public void updateGL() { currentY -= Math.max(10, fontHeight)+5; } } + // colormaps third + for(ColormapLabel cmlabel : colormapLabels) { + Text lbltxt = new Text(cmlabel.labelText, fontSize, fontStyle); + lbltxt.setPickColor(cmlabel.pickColor); + if(!lbltxt.getTextString().isEmpty()) + texts.add(lbltxt); + int pattern = 0xffff; + if(!pattern2lines.containsKey(pattern)){ + Lines lines = new Lines(); + lines + .setStrokePattern(pattern) + .setVertexRoundingEnabled(true); + pattern2lines.put(pattern, lines); + } + Lines lines = pattern2lines.get(pattern); + Triangles tris = Utils.colormap2Tris(cmlabel.cmap, cmlabel.vertical); + triangles.add(tris); + int cmapSize = 12; + if(cmlabel.vertical){ + // put label on top + int currX = currentX+4; + int currY; + if(!lbltxt.getTextString().isEmpty()){ + lbltxt.setOrigin(currentX, currentY); + currY = currentY-fontSize+2; + } else { + currY = currentY; + } + int w = cmapSize; + int h = Math.max(cmapSize*3, (fontSize+2)*cmlabel.ticklabels.length); + // stretch triangles to correct size and translate to correct location + tris.getTriangleDetails().forEach(t->{ + Arrays.asList(t.p0,t.p1,t.p2).forEach(p->{ + p.setLocation(p.getX()*w+currX, currY-h+p.getY()*h); + }); + }); + // draw frame + lines.addLineStrip(currX,currY, currX+w,currY, currX+w,currY-h, currX,currY-h, currX,currY); + // add ticks (& tick labels) + for(int i=0; i{ @@ -270,6 +440,10 @@ public void updateGL() { t.initGL(); delegate.addItemToRender(t); }); + triangles.forEach(t->{ + t.initGL(); + delegate.addItemToRender(t); + }); isDirty = false; } @@ -293,6 +467,11 @@ protected void clearGL() { l.close(); }); pattern2lines.clear(); + triangles.forEach(t->{ + t.close(); + delegate.triangles.removeItemToRender(t); + }); + triangles.clear(); texts.forEach(t->{ delegate.text.removeItemToRender(t); t.close(); diff --git a/jplotter/src/main/java/hageldave/jplotter/util/Utils.java b/jplotter/src/main/java/hageldave/jplotter/util/Utils.java index 33ef5f51..ea379a6c 100644 --- a/jplotter/src/main/java/hageldave/jplotter/util/Utils.java +++ b/jplotter/src/main/java/hageldave/jplotter/util/Utils.java @@ -17,6 +17,8 @@ import hageldave.imagingkit.core.Img; import hageldave.imagingkit.core.Pixel; +import hageldave.jplotter.color.ColorMap; +import hageldave.jplotter.renderables.Triangles; /** * Class containing utility methods @@ -281,4 +283,35 @@ public static BufferedImage remoteRGBImage(Img img) { BufferedImage bimg = new BufferedImage(cm, raster, false, null); return bimg; } + + public static Triangles colormap2Tris(ColorMap cmap, boolean vertical){ + Triangles tris = new Triangles(); + for(int i=0; i