Package de.lmu.ifi.dbs.elki.visualization.visualizers.pairsegments

Source Code of de.lmu.ifi.dbs.elki.visualization.visualizers.pairsegments.SegmentsStylingPolicy

package de.lmu.ifi.dbs.elki.visualization.visualizers.pairsegments;

/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures

Copyright (C) 2012
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 <http://www.gnu.org/licenses/>.
*/

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.TreeMap;

import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
import de.lmu.ifi.dbs.elki.evaluation.clustering.pairsegments.Segment;
import de.lmu.ifi.dbs.elki.evaluation.clustering.pairsegments.Segments;
import de.lmu.ifi.dbs.elki.visualization.colors.ColorLibrary;
import de.lmu.ifi.dbs.elki.visualization.style.ClassStylingPolicy;
import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;

/**
* Styling policy to communicate the segment selection to other visualizers.
*
* @author Sascha Goldhofer
* @author Erich Schubert
*/
public class SegmentsStylingPolicy implements ClassStylingPolicy {
  /**
   * The segments we use for visualization
   */
  protected final Segments segments;

  /**
   * Selected segments
   */
  protected ArrayList<Segment> selectedSegments = new ArrayList<Segment>();

  /**
   * Segments indirectly selected
   */
  protected TreeMap<Segment, Segment> indirectSelections = new TreeMap<Segment, Segment>();

  /**
   * Not selected IDs that will be drawn in default colors.
   */
  protected ModifiableDBIDs unselectedObjects = DBIDUtil.newHashSet();

  /**
   * Color library (only used in compatibility mode)
   */
  // TODO: move to abstract super class?
  ColorLibrary colorset;

  /**
   * Constructor.
   *
   * @param segments Segments
   */
  public SegmentsStylingPolicy(Segments segments, StyleLibrary style) {
    super();
    this.segments = segments;
    this.colorset = style.getColorSet(StyleLibrary.PLOT);

    // get all selectable segments
    for(Segment segment : segments) {
      // store segmentID
      if(!segment.isUnpaired()) {
        // and store their get all objects
        if(segment.getDBIDs() != null) {
          unselectedObjects.addDBIDs(segment.getDBIDs());
        }
      }
    }
  }

  /**
   * Test whether a segment is selected.
   *
   * @param segment Segment to test
   * @return true when selected
   */
  public boolean isSelected(Segment segment) {
    return selectedSegments.contains(segment) || indirectSelections.containsValue(segment);
  }

  @Override
  public int getStyleForDBID(DBID id) {
    Iterator<Segment> s = selectedSegments.iterator();
    for(int i = 0; s.hasNext(); i++) {
      Segment seg = s.next();
      DBIDs ids = seg.getDBIDs();
      if(ids != null && ids.contains(id)) {
        return i;
      }
    }
    return -2;
  }

  @Override
  public int getColorForDBID(DBID id) {
    int style = getStyleForDBID(id);
    // FIXME: slow
    return SVGUtil.stringToColor(colorset.getColor(style)).getRGB();
  }

  @Override
  // -2=grau, -1=schwarz, 0+=farben
  public int getMinStyle() {
    return -2;
  }

  @Override
  public int getMaxStyle() {
    return selectedSegments.size();
  }

  @Override
  public Iterator<DBID> iterateClass(int cnum) {
    // unselected
    if(cnum == -2) {
      return unselectedObjects.iterator();
    }
    else if(cnum == -1) {
      return DBIDUtil.EMPTYDBIDS.iterator();
    }
    // colors
    DBIDs ids = selectedSegments.get(cnum).getDBIDs();
    return (ids != null) ? ids.iterator() : DBIDUtil.EMPTYDBIDS.iterator();
  }

  /**
   * Adds or removes the given segment to the selection. Depending on the
   * clustering and cluster selected and the addToSelection option given, the
   * current selection will be modified. This method is called by clicking on a
   * segment and ring and the CTRL-button status.
   *
   * Adding selections does only work on the same clustering and cluster, else a
   * new selection will be added.
   *
   * @param segment the selected element representing a segment ring (specific
   *        clustering)
   * @param addToSelection flag for adding segment to current selection
   */
  public void select(Segment segment, boolean addToSelection) {
    // abort if segment represents pairs inNone. Would select all segments...
    if(segment.isNone()) {
      return;
    }
    if(!addToSelection) {
      deselectAllSegments();
    }

    // get selected segments
    if(segment.isUnpaired()) {
      // check if all segments are selected
      if(addToSelection) {
        boolean allSegmentsSelected = true;
        for(Segment other : segments.getPairedSegments(segment)) {
          if(!isSelected(other)) {
            allSegmentsSelected = false;
            break;
          }
        }

        // if all are selected, deselect all
        if(allSegmentsSelected) {
          deselectSegment(segment);
          return;
        }
      }
      if(isSelected(segment)) {
        deselectSegment(segment);
      }
      else {
        selectSegment(segment);
      }
    }
    else {
      // an object segment was selected
      if(isSelected(segment)) {
        deselectSegment(segment);
      }
      else {
        selectSegment(segment);
      }
    }
  }

  /**
   * Deselect all currently selected segments
   */
  public void deselectAllSegments() {
    while(selectedSegments.size() > 0) {
      deselectSegment(selectedSegments.get(selectedSegments.size() - 1));
    }
  }

  /**
   * Deselect a segment
   *
   * @param segment Segment to deselect
   */
  protected void deselectSegment(Segment segment) {
    if(segment.isUnpaired()) {
      ArrayList<Segment> remove = new ArrayList<Segment>();
      // remove all object segments associated with unpaired segment from
      // selection list
      for(Entry<Segment, Segment> entry : indirectSelections.entrySet()) {
        if(entry.getValue() == segment) {
          remove.add(entry.getKey());
        }
      }

      for(Segment other : remove) {
        indirectSelections.remove(other);
        deselectSegment(other);
      }
    }
    else {
      // check if deselected object Segment has a unpaired segment highlighted
      Segment unpaired = indirectSelections.get(segment);
      if(unpaired != null) {
        // remove highlight
        deselectSegment(unpaired);
      }
      if(selectedSegments.remove(segment)) {
        if(segment.getDBIDs() != null) {
          unselectedObjects.addDBIDs(segment.getDBIDs());
        }
      }
    }
  }

  /**
   * Select a segment
   *
   * @param segment Segment to select
   */
  protected void selectSegment(Segment segment) {
    if(segment.isUnpaired()) {
      // remember selected unpaired segment
      for(Segment other : segments.getPairedSegments(segment)) {
        indirectSelections.put(other, segment);
        selectSegment(other);
      }
    }
    else {
      if(!selectedSegments.contains(segment)) {
        selectedSegments.add(segment);
        if(segment.getDBIDs() != null) {
          unselectedObjects.removeDBIDs(segment.getDBIDs());
        }
      }
    }
  }

  /**
   * Get the index of a selected segment.
   *
   * @param segment Segment to find
   * @return Index, or -1
   */
  public int indexOfSegment(Segment segment) {
    return selectedSegments.indexOf(segment);
  }
}
TOP

Related Classes of de.lmu.ifi.dbs.elki.visualization.visualizers.pairsegments.SegmentsStylingPolicy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.