package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d; /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures Copyright (C) 2011 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ import java.util.ArrayList; import java.util.Iterator; import org.apache.batik.util.SVGConstants; import org.w3c.dom.Element; import de.lmu.ifi.dbs.elki.data.NumberVector; import de.lmu.ifi.dbs.elki.database.datastore.DataStoreEvent; import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener; import de.lmu.ifi.dbs.elki.database.ids.DBID; import de.lmu.ifi.dbs.elki.database.ids.DBIDs; import de.lmu.ifi.dbs.elki.result.DBIDSelection; import de.lmu.ifi.dbs.elki.result.HierarchicalResult; import de.lmu.ifi.dbs.elki.result.Result; import de.lmu.ifi.dbs.elki.result.ResultUtil; import de.lmu.ifi.dbs.elki.result.SelectionResult; import de.lmu.ifi.dbs.elki.utilities.exceptions.ObjectNotFoundException; import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil; import de.lmu.ifi.dbs.elki.visualization.VisualizationTask; import de.lmu.ifi.dbs.elki.visualization.css.CSSClass; import de.lmu.ifi.dbs.elki.visualization.projector.ScatterPlotProjector; import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary; import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot; import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil; import de.lmu.ifi.dbs.elki.visualization.visualizers.AbstractVisFactory; import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization; import de.lmu.ifi.dbs.elki.visualization.visualizers.events.ContextChangeListener; import de.lmu.ifi.dbs.elki.visualization.visualizers.thumbs.ThumbnailVisualization; /** * Visualizer for generating an SVG-Element containing dots as markers * representing the selected Database's objects. * * @author Heidi Kolb * * @apiviz.has SelectionResult oneway - - visualizes * @apiviz.has DBIDSelection oneway - - visualizes * * @param Type of the NumberVector being visualized. */ public class SelectionDotVisualization> extends P2DVisualization implements ContextChangeListener, DataStoreListener { /** * A short name characterizing this Visualizer. */ private static final String NAME = "Selection"; /** * Generic tag to indicate the type of element. Used in IDs, CSS-Classes etc. */ public static final String MARKER = "selectionDotMarker"; /** * The selection result we work on */ private SelectionResult result; /** * Constructor. * * @param task Task */ public SelectionDotVisualization(VisualizationTask task) { super(task); this.result = task.getResult(); context.addContextChangeListener(this); context.addResultListener(this); context.addDataStoreListener(this); incrementalRedraw(); } @Override protected void redraw() { addCSSClasses(svgp); final double size = context.getStyleLibrary().getSize(StyleLibrary.SELECTION); DBIDSelection selContext = context.getSelection(); if(selContext != null) { DBIDs selection = selContext.getSelectedIds(); for(DBID i : selection) { try { double[] v = proj.fastProjectDataToRenderSpace(rel.get(i)); Element dot = svgp.svgCircle(v[0], v[1], size); SVGUtil.addCSSClass(dot, MARKER); layer.appendChild(dot); } catch(ObjectNotFoundException e) { // ignore } } } } /** * Adds the required CSS-Classes * * @param svgp SVG-Plot */ private void addCSSClasses(SVGPlot svgp) { // Class for the dot markers if(!svgp.getCSSClassManager().contains(MARKER)) { CSSClass cls = new CSSClass(this, MARKER); final StyleLibrary style = context.getStyleLibrary(); cls.setStatement(SVGConstants.CSS_FILL_PROPERTY, style.getColor(StyleLibrary.SELECTION)); cls.setStatement(SVGConstants.CSS_OPACITY_PROPERTY, style.getOpacity(StyleLibrary.SELECTION)); svgp.addCSSClassOrLogError(cls); } } @Override public void contentChanged(@SuppressWarnings("unused") DataStoreEvent e) { synchronizedRedraw(); } /** * Factory for visualizers to generate an SVG-Element containing dots as * markers representing the selected Database's objects. * * @author Heidi Kolb * * @apiviz.stereotype factory * @apiviz.uses SelectionDotVisualization oneway - - «create» * * @param Type of the NumberVector being visualized. */ public static class Factory> extends AbstractVisFactory { /** * Constructor */ public Factory() { super(); } @Override public Visualization makeVisualization(VisualizationTask task) { return new SelectionDotVisualization(task); } @Override public Visualization makeVisualizationOrThumbnail(VisualizationTask task) { return new ThumbnailVisualization(this, task, ThumbnailVisualization.ON_DATA | ThumbnailVisualization.ON_SELECTION); } @Override public void processNewResult(HierarchicalResult baseResult, Result result) { final ArrayList selectionResults = ResultUtil.filterResults(result, SelectionResult.class); for(SelectionResult selres : selectionResults) { Iterator> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class); for(ScatterPlotProjector p : IterableUtil.fromIterator(ps)) { final VisualizationTask task = new VisualizationTask(NAME, selres, p.getRelation(), this); task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA - 1); baseResult.getHierarchy().add(selres, task); baseResult.getHierarchy().add(p, task); } } } } }