diff options
author | Andrej Shadura <andrewsh@debian.org> | 2019-03-09 22:30:34 +0000 |
---|---|---|
committer | Andrej Shadura <andrewsh@debian.org> | 2019-03-09 22:30:34 +0000 |
commit | b7b404fd7a726774d442562d11659d7b5368cdb9 (patch) | |
tree | 6f510ddbf80c1a51e333f80411541565ac71c9e9 /src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java | |
parent | ace5fa7f57d49756c0e1b111a30f3b6a9436c1cb (diff) |
Import Upstream version 0.5.5
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java')
-rw-r--r-- | src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java | 249 |
1 files changed, 142 insertions, 107 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java index 62a4fb5c..f21e4df6 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java @@ -52,147 +52,182 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization; /** * Visualizer, displaying the key for a clustering. - * + * * @author Erich Schubert * - * @apiviz.has Clustering oneway - - visualizes + * @apiviz.stereotype factory + * @apiviz.uses Instance oneway - - «create» */ -public class KeyVisualization extends AbstractVisualization { +public class KeyVisualization extends AbstractVisFactory { /** * Name for this visualizer. */ private static final String NAME = "Cluster Key"; - /** - * Clustering to display - */ - private Clustering<Model> clustering; + @Override + public void processNewResult(HierarchicalResult baseResult, Result newResult) { + // Find clusterings we can visualize: + Collection<Clustering<?>> clusterings = ResultUtil.filterResults(newResult, Clustering.class); + for(Clustering<?> c : clusterings) { + final int numc = c.getAllClusters().size(); + if(numc > 0) { + // FIXME: compute from labels? + final double maxwidth = 10.; + final VisualizationTask task = new VisualizationTask(NAME, c, null, this); + final int cols = getPreferredColumns(1.0, 1.0, numc, maxwidth); + final int rows = (int) Math.ceil(numc / (double) cols); + final double div = Math.max(2. + rows, cols * maxwidth); + task.width = cols * maxwidth / div; + task.height = (2. + rows) / div; + task.level = VisualizationTask.LEVEL_STATIC; + task.nodetail = true; + baseResult.getHierarchy().add(c, task); + } + } + } /** - * Constructor. + * Compute the preferred number of columns. * - * @param task Visualization task + * @param width Target width + * @param height Target height + * @param numc Number of clusters + * @param maxwidth Max width of entries + * @return Preferred number of columns */ - public KeyVisualization(VisualizationTask task) { - super(task); - this.clustering = task.getResult(); - context.addResultListener(this); + public static int getPreferredColumns(double width, double height, int numc, double maxwidth) { + // Maximum width (compared to height) of labels - guess. + // FIXME: do we really need to do this three-step computation? + // Number of rows we'd use in a squared layout: + final double rows = Math.ceil(Math.pow(numc * maxwidth, height / (width + height))); + // Given this number of rows (plus two for header), use this many columns: + return (int) Math.ceil(numc / (rows + 2)); } @Override - public void destroy() { - context.removeResultListener(this); - super.destroy(); + public Visualization makeVisualization(VisualizationTask task) { + return new Instance(task); } @Override - public void resultChanged(Result current) { - super.resultChanged(current); - if(current == context.getStyleResult()) { - incrementalRedraw(); - } + public boolean allowThumbnails(VisualizationTask task) { + return false; } - @Override - protected void redraw() { - SVGPlot svgp = task.getPlot(); - final List<Cluster<Model>> allcs = clustering.getAllClusters(); - - StyleLibrary style = context.getStyleLibrary(); - MarkerLibrary ml = style.markers(); - layer = svgp.svgElement(SVGConstants.SVG_G_TAG); - - // Add a label for the clustering. - { - Element label = svgp.svgText(0.1, 0.7, clustering.getLongName()); - label.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.4; fill: "+style.getTextColor(StyleLibrary.DEFAULT)); - layer.appendChild(label); + /** + * Instance + * + * @author Erich Schubert + * + * @apiviz.has Clustering oneway - - visualizes + */ + public class Instance extends AbstractVisualization { + /** + * Clustering to display + */ + private Clustering<Model> clustering; + + /** + * Constructor. + * + * @param task Visualization task + */ + public Instance(VisualizationTask task) { + super(task); + this.clustering = task.getResult(); + context.addResultListener(this); } - // TODO: multi-column layout! - int i = 0; - for(Cluster<Model> c : allcs) { - ml.useMarker(svgp, layer, 0.3, i + 1.5, i, 0.3); - Element label = svgp.svgText(0.7, i + 1.7, c.getNameAutomatic()); - label.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.6; fill: "+style.getTextColor(StyleLibrary.DEFAULT)); - layer.appendChild(label); - i++; + @Override + public void destroy() { + context.removeResultListener(this); + super.destroy(); } - // Add a button to set style policy - { - StylingPolicy sp = context.getStyleResult().getStylingPolicy(); - if(sp instanceof ClusterStylingPolicy && ((ClusterStylingPolicy) sp).getClustering() == clustering) { - // Don't show the button when active. May confuse people more than the disappearing button - - // SVGButton button = new SVGButton(.1, i + 1.1, 3.8, .7, .2); - // button.setTitle("Active style", "darkgray"); - // layer.appendChild(button.render(svgp)); - } - else { - SVGButton button = new SVGButton(.1, i + 1.1, 3.8, .7, .2); - button.setTitle("Set style", "black"); - Element elem = button.render(svgp); - // Attach listener - EventTarget etr = (EventTarget) elem; - etr.addEventListener(SVGConstants.SVG_CLICK_EVENT_TYPE, new EventListener() { - @Override - public void handleEvent(Event evt) { - setStylePolicy(); - } - }, false); - layer.appendChild(elem); + @Override + public void resultChanged(Result current) { + super.resultChanged(current); + if(current == context.getStyleResult()) { + incrementalRedraw(); } } - int rows = i + 2; - int cols = Math.max(6, (int) (rows * task.getHeight() / task.getWidth())); - final double margin = style.getSize(StyleLibrary.MARGIN); - final String transform = SVGUtil.makeMarginTransform(task.getWidth(), task.getHeight(), cols, rows, margin / StyleLibrary.SCALE); - SVGUtil.setAtt(layer, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, transform); - } + @Override + protected void redraw() { + SVGPlot svgp = task.getPlot(); + StyleLibrary style = context.getStyleResult().getStyleLibrary(); + MarkerLibrary ml = style.markers(); + + // Maximum width (compared to height) of labels - guess. + // FIXME: compute from labels? + final double maxwidth = 10.; + + final List<Cluster<Model>> allcs = clustering.getAllClusters(); + final int numc = allcs.size(); + final int cols = getPreferredColumns(task.getWidth(), task.getHeight(), numc, maxwidth); + final int rows = 2 + (int) Math.ceil(numc / (double) cols); + // We use a coordinate system based on rows, so columns are at c*maxwidth + + layer = svgp.svgElement(SVGConstants.SVG_G_TAG); + // Add a label for the clustering. + { + Element label = svgp.svgText(0.1, 0.7, clustering.getLongName()); + label.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.4; fill: " + style.getTextColor(StyleLibrary.DEFAULT)); + layer.appendChild(label); + } - /** - * Trigger a style change. - */ - protected void setStylePolicy() { - context.getStyleResult().setStylingPolicy(new ClusterStylingPolicy(clustering, context.getStyleLibrary())); - context.getHierarchy().resultChanged(context.getStyleResult()); - } + int i = 0; + for(Cluster<Model> c : allcs) { + final int col = i / rows; + final int row = i % rows; + ml.useMarker(svgp, layer, 0.3 + maxwidth * col, row + 1.5, i, 0.3); + Element label = svgp.svgText(0.7 + maxwidth * col, row + 1.7, c.getNameAutomatic()); + label.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.6; fill: " + style.getTextColor(StyleLibrary.DEFAULT)); + layer.appendChild(label); + i++; + } - /** - * Visualization factory - * - * @author Erich Schubert - * - * @apiviz.stereotype factory - * @apiviz.uses KeyVisualization oneway - - «create» - */ - public static class Factory extends AbstractVisFactory { - @Override - public void processNewResult(HierarchicalResult baseResult, Result newResult) { - // Find clusterings we can visualize: - Collection<Clustering<?>> clusterings = ResultUtil.filterResults(newResult, Clustering.class); - for (Clustering<?> c : clusterings) { - if(c.getAllClusters().size() > 0) { - final VisualizationTask task = new VisualizationTask(NAME, c, null, this); - task.width = 1.0; - task.height = 1.0; - task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_STATIC); - task.put(VisualizationTask.META_NODETAIL, true); - baseResult.getHierarchy().add(c, task); + // Add a button to set style policy + { + StylingPolicy sp = context.getStyleResult().getStylingPolicy(); + if(sp instanceof ClusterStylingPolicy && ((ClusterStylingPolicy) sp).getClustering() == clustering) { + // Don't show the button when active. May confuse people more than the + // disappearing button? + + // SVGButton button = new SVGButton(.1, rows + 1.1, 3.8, .7, .2); + // button.setTitle("Active style", "darkgray"); + // layer.appendChild(button.render(svgp)); + } + else { + SVGButton button = new SVGButton(.1, rows + 1.1, 3.8, .7, .2); + button.setTitle("Set style", "black"); + Element elem = button.render(svgp); + // Attach listener + EventTarget etr = (EventTarget) elem; + etr.addEventListener(SVGConstants.SVG_CLICK_EVENT_TYPE, new EventListener() { + @Override + public void handleEvent(Event evt) { + setStylePolicy(); + } + }, false); + layer.appendChild(elem); } } - } - @Override - public Visualization makeVisualization(VisualizationTask task) { - return new KeyVisualization(task); + // int rows = i + 2; + // int cols = Math.max(6, (int) (rows * task.getHeight() / + // task.getWidth())); + final double margin = style.getSize(StyleLibrary.MARGIN); + final String transform = SVGUtil.makeMarginTransform(task.getWidth(), task.getHeight(), cols * maxwidth, rows, margin / StyleLibrary.SCALE); + SVGUtil.setAtt(layer, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, transform); } - @Override - public boolean allowThumbnails(VisualizationTask task) { - return false; + /** + * Trigger a style change. + */ + protected void setStylePolicy() { + context.getStyleResult().setStylingPolicy(new ClusterStylingPolicy(clustering, context.getStyleResult().getStyleLibrary())); + context.getHierarchy().resultChanged(context.getStyleResult()); } } }
\ No newline at end of file |