Package de.lmu.ifi.dbs.elki.visualization.svg

Source Code of de.lmu.ifi.dbs.elki.visualization.svg.SVGSimpleLinearAxis

package de.lmu.ifi.dbs.elki.visualization.svg;

/*
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 org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;

import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClassManager;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClassManager.CSSNamingConflict;
import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;

/**
* Class to draw a simple axis with tick marks on the plot.
*
* @author Erich Schubert
*
* @apiviz.uses CSSClass
* @apiviz.uses CSSClassManager
* @apiviz.uses LinearScale
* @apiviz.uses StyleLibrary
* @apiviz.uses STYLE
* @apiviz.uses Element oneway - - «create»
*/
public class SVGSimpleLinearAxis {
  /**
   * Flag for axis label position. First char: right-hand or left-hand side of
   * line. Second char: text alignment
   *
   * @apiviz.exclude
   */
  private enum ALIGNMENT {
    LL, RL, LC, RC, LR, RR
  }

  /**
   * Labeling style: left-handed, right-handed, no ticks, labels at ends
   *
   * @author Erich Schubert
   */
  public enum LabelStyle {
    LEFTHAND, RIGHTHAND, NOLABELS, NOTHING, ENDLABEL
  }

  /**
   * CSS class name for the axes
   */
  private final static String CSS_AXIS = "axis";

  /**
   * CSS class name for the axes
   */
  private final static String CSS_AXIS_TICK = "axis-tick";

  /**
   * CSS class name for the axes
   */
  private final static String CSS_AXIS_LABEL = "axis-label";

  /**
   * Register CSS classes with a {@link CSSClassManager}
   *
   * @param owner Owner of the CSS classes
   * @param manager Manager to register the classes with
   * @throws CSSNamingConflict when a name clash occurs
   */
  private static void setupCSSClasses(Object owner, CSSClassManager manager, StyleLibrary style) throws CSSNamingConflict {
    if(!manager.contains(CSS_AXIS)) {
      CSSClass axis = new CSSClass(owner, CSS_AXIS);
      axis.setStatement(SVGConstants.CSS_STROKE_PROPERTY, style.getColor(StyleLibrary.AXIS));
      axis.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, style.getLineWidth(StyleLibrary.AXIS));
      manager.addClass(axis);
    }
    if(!manager.contains(CSS_AXIS_TICK)) {
      CSSClass tick = new CSSClass(owner, CSS_AXIS_TICK);
      tick.setStatement(SVGConstants.CSS_STROKE_PROPERTY, style.getColor(StyleLibrary.AXIS_TICK));
      tick.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, style.getLineWidth(StyleLibrary.AXIS_TICK));
      manager.addClass(tick);
    }
    if(!manager.contains(CSS_AXIS_LABEL)) {
      CSSClass label = new CSSClass(owner, CSS_AXIS_LABEL);
      label.setStatement(SVGConstants.CSS_FILL_PROPERTY, style.getTextColor(StyleLibrary.AXIS_LABEL));
      label.setStatement(SVGConstants.CSS_FONT_FAMILY_PROPERTY, style.getFontFamily(StyleLibrary.AXIS_LABEL));
      label.setStatement(SVGConstants.CSS_FONT_SIZE_PROPERTY, style.getTextSize(StyleLibrary.AXIS_LABEL));
      manager.addClass(label);
    }
  }

  /**
   * Plot an axis with appropriate scales
   *
   * @param plot Plot object
   * @param parent Containing element
   * @param scale axis scale information
   * @param x1 starting coordinate
   * @param y1 starting coordinate
   * @param x2 ending coordinate
   * @param y2 ending coordinate
   * @param labelstyle Style for placing the labels
   * @param style Style library
   * @throws CSSNamingConflict when a conflict occurs in CSS
   */
  public static void drawAxis(SVGPlot plot, Element parent, LinearScale scale, double x1, double y1, double x2, double y2, LabelStyle labelstyle, StyleLibrary style) throws CSSNamingConflict {
    assert (parent != null);
    Element line = plot.svgLine(x1, y1, x2, y2);
    SVGUtil.setCSSClass(line, CSS_AXIS);
    parent.appendChild(line);

    double tx = x2 - x1;
    double ty = y2 - y1;
    // ticks are orthogonal
    double tw = ty * 0.01;
    double th = -tx * 0.01;

    // choose where to print labels.
    final boolean labels, ticks;
    switch(labelstyle){
    case LEFTHAND:
    case RIGHTHAND:
      labels = true;
      ticks = true;
      break;
    case NOLABELS:
      labels = false;
      ticks = true;
      break;
    case ENDLABEL: // end labels are handle specially
    case NOTHING:
    default:
      labels = false;
      ticks = false;
    }
    ALIGNMENT pos = ALIGNMENT.LL;
    if(labels) {
      double angle = Math.atan2(ty, tx);
      // System.err.println(tx + " " + (-ty) + " " + angle);
      if(angle > 2.6) { // pi .. 2.6 = 180 .. 150
        pos = labelstyle == LabelStyle.RIGHTHAND ? ALIGNMENT.RC : ALIGNMENT.LC;
      }
      else if(angle > 0.5) { // 2.3 .. 0.7 = 130 .. 40
        pos = labelstyle == LabelStyle.RIGHTHAND ? ALIGNMENT.RR : ALIGNMENT.LL;
      }
      else if(angle > -0.5) { // 0.5 .. -0.5 = 30 .. -30
        pos = labelstyle == LabelStyle.RIGHTHAND ? ALIGNMENT.RC : ALIGNMENT.LC;
      }
      else if(angle > -2.6) { // -0.5 .. -2.6 = -30 .. -150
        pos = labelstyle == LabelStyle.RIGHTHAND ? ALIGNMENT.RL : ALIGNMENT.LR;
      }
      else { // -2.6 .. -pi = -150 .. -180
        pos = labelstyle == LabelStyle.RIGHTHAND ? ALIGNMENT.RC : ALIGNMENT.LC;
      }
    }
    // vertical text offset; align approximately with middle instead of
    // baseline.
    double textvoff = style.getTextSize(StyleLibrary.AXIS_LABEL) * .35;

    // draw ticks on x axis
    if(ticks || labels) {
      for(double tick = scale.getMin(); tick <= scale.getMax() + scale.getRes() / 10; tick += scale.getRes()) {
        double x = x1 + tx * scale.getScaled(tick);
        double y = y1 + ty * scale.getScaled(tick);
        if(ticks) {
          // This is correct. Vectors: (vec - tvec) to (vec + tvec)
          Element tickline = plot.svgLine(x - tw, y - th, x + tw, y + th);
          SVGUtil.setAtt(tickline, SVGConstants.SVG_CLASS_ATTRIBUTE, CSS_AXIS_TICK);
          parent.appendChild(tickline);
        }
        // draw labels
        if(labels) {
          double tex = x;
          double tey = y;
          switch(pos){
          case LL:
          case LC:
          case LR:
            tex = x + tw * 2.5;
            tey = y + th * 2.5 + textvoff;
            break;
          case RL:
          case RC:
          case RR:
            tex = x - tw * 2.5;
            tey = y - th * 2.5 + textvoff;
          }
          Element text = plot.svgText(tex, tey, scale.formatValue(tick));
          text.setAttribute(SVGConstants.SVG_CLASS_ATTRIBUTE, CSS_AXIS_LABEL);
          switch(pos){
          case LL:
          case RL:
            text.setAttribute(SVGConstants.SVG_TEXT_ANCHOR_ATTRIBUTE, SVGConstants.SVG_START_VALUE);
            break;
          case LC:
          case RC:
            text.setAttribute(SVGConstants.SVG_TEXT_ANCHOR_ATTRIBUTE, SVGConstants.SVG_MIDDLE_VALUE);
            break;
          case LR:
          case RR:
            text.setAttribute(SVGConstants.SVG_TEXT_ANCHOR_ATTRIBUTE, SVGConstants.SVG_END_VALUE);
            break;
          }
          parent.appendChild(text);
        }
      }
    }
    if(labelstyle == LabelStyle.ENDLABEL) {
      {
        Element text = plot.svgText(x1 - tx * 0.02, y1 - ty * 0.02 + textvoff, scale.formatValue(scale.getMin()));
        text.setAttribute(SVGConstants.SVG_CLASS_ATTRIBUTE, CSS_AXIS_LABEL);
        text.setAttribute(SVGConstants.SVG_TEXT_ANCHOR_ATTRIBUTE, SVGConstants.SVG_MIDDLE_VALUE);
        parent.appendChild(text);
      }
      {
        Element text = plot.svgText(x2 + tx * 0.02, y2 + ty * 0.02 + textvoff, scale.formatValue(scale.getMax()));
        text.setAttribute(SVGConstants.SVG_CLASS_ATTRIBUTE, CSS_AXIS_LABEL);
        text.setAttribute(SVGConstants.SVG_TEXT_ANCHOR_ATTRIBUTE, SVGConstants.SVG_MIDDLE_VALUE);
        parent.appendChild(text);
      }
    }
    setupCSSClasses(plot, plot.getCSSClassManager(), style);
  }
}
TOP

Related Classes of de.lmu.ifi.dbs.elki.visualization.svg.SVGSimpleLinearAxis

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.