org.esa.nest.dat.views.polarview.Axis.java Source code

Java tutorial

Introduction

Here is the source code for org.esa.nest.dat.views.polarview.Axis.java

Source

/*
 * Copyright (C) 2014 by Array Systems Computing Inc. http://www.array.ca
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU 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 General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, see http://www.gnu.org/licenses/
 */
package org.esa.nest.dat.views.polarview;

import org.apache.commons.math3.util.FastMath;

import java.awt.*;

public class Axis {
    private static final double stepValues[] = { 0.1D, 1.0D, 2D, 3D, 5D, 10D };

    private static final int TOP_X = 1;
    private static final int BOTTOM_X = 2;
    private static final int LEFT_Y = 3;
    public static final int RIGHT_Y = 4;
    public static final int RADIAL = 5;

    private AbstractAxisDisplay gr = null;
    private boolean isX = true;
    private final boolean ticksInside = false;
    private final boolean withGrid = false;
    private double minValue = 0.0;
    private double maxValue = 1.0;
    private double axisRange = maxValue - minValue;
    private double tickRange = maxValue - minValue;
    private double minData = 0.0;
    private double maxData = 1.0;
    private final double minRange = 0.0;
    private final boolean visible = true;
    private boolean autoRange = true;
    private int length = 0;
    private int breadth = 0;
    private int TouchId = 0;
    private String title = null;
    private final int tickLength = -5;
    private int tickCount = 3;
    private int bestTickCount = 3;
    private int spacing = Math.abs(tickLength);
    private String tickNames[] = { "0", "0.5", "1" };
    private double tickValues[] = { 0.0D, 0.5D, 1.0D };
    private int tickPos[] = null;
    private final Font font;
    private final Font titleFont;
    private final Color axisColor;
    private final Color labelColor;
    private final Color gridColor;
    private String unit = "";

    public Axis(int orientation) {

        font = getFont("default.font.plot.axis.tick", "SansSerif-plain-12");
        titleFont = getFont("default.font.plot.axis.title", "SansSerif-plain-12");
        axisColor = Color.black;
        labelColor = Color.black;
        gridColor = Color.darkGray;
        setLocation(orientation);
    }

    private static Font getFont(String propertyName, String defaultFont) {
        final String fontSpec = System.getProperty(propertyName, defaultFont);
        return Font.decode(fontSpec);
    }

    public void setTitle(String str) {
        title = str;
    }

    public void setUnit(String unitStr) {
        unit = unitStr;
    }

    public String getUnit() {
        return unit;
    }

    public AbstractAxisDisplay getAxisGraphics(Graphics g) {
        gr.setGraphics(g);
        return gr;
    }

    public void setSpacing(int spacing) {
        this.spacing = spacing;
    }

    public final double[] getRange() {
        return new double[] { minValue, maxValue };
    }

    public void setAutoRange(boolean autoRange) {
        if (!this.autoRange && autoRange)
            setApproximateRange(minData, maxData);
        this.autoRange = autoRange;
    }

    public void setDataRange(double range[]) {
        setDataRange(range[0], range[1]);
    }

    void setDataRange(double minValue, double maxValue) {
        minData = minValue;
        maxData = maxValue;
        if (autoRange)
            setApproximateRange(minValue, maxValue);
    }

    void setApproximateRange(double minValue, double maxValue) {
        if (minValue == maxValue) {
            minValue--;
            maxValue++;
        }
        double range = maxValue - minValue;
        if (Math.abs(range) < minRange) {
            maxValue = minValue + minRange;
            range = maxValue - minValue;
        }
        final double step = getStepValue(range / 5D, true);
        final double first = Math.floor(minValue / step + 1.0000000000000001E-005D) * step;
        final int count = (int) Math.ceil((maxValue - first) / step);
        setRange(first, first + (double) count * step, count + 1);
    }

    private static double getStepValue(double thevalue, boolean up) {
        final boolean negative = thevalue < 0.0D;
        double val = thevalue;
        if (negative)
            val = -val;
        final int exponent = (int) Math.floor(Math.log10(val));
        val *= FastMath.pow(10D, -exponent);
        int i;
        for (i = stepValues.length - 1; i > 0; i--) {
            if (val > stepValues[i])
                break;
        }
        if (up)
            val = stepValues[i + 1];
        else
            val = stepValues[i];
        val *= FastMath.pow(10D, exponent);
        if (negative)
            val = -val;
        return val;
    }

    void setRange(double rangeMin, double rangeMax) {
        if (rangeMin == minValue && rangeMax == maxValue)
            return;
        setApproximateRange(rangeMin, rangeMax);
        minValue = rangeMin;
        maxValue = rangeMax;
        if (minValue == maxValue) {
            minValue--;
            maxValue++;
        }
        axisRange = maxValue - minValue;
        if (Math.abs(axisRange) < minRange) {
            maxValue = minValue + minRange;
            axisRange = maxValue - minValue;
        }
        bestTickCount = tickCount;
        setTickCount(tickCount);
    }

    public void setRange(double minValue, double maxValue, int tickCount) {
        if (minValue == this.minValue && maxValue == this.maxValue && tickCount == bestTickCount)
            return;
        if (minValue == maxValue) {
            minValue--;
            maxValue++;
        }
        this.minValue = minValue;
        this.maxValue = maxValue;
        tickRange = axisRange = maxValue - minValue;
        if (Math.abs(axisRange) < minRange) {
            maxValue = minValue + minRange;
            tickRange = axisRange = maxValue - minValue;
        }
        bestTickCount = tickCount;
        setTickCount(tickCount);
    }

    private void setTickCount(int newTickCount) {
        tickCount = Math.abs(newTickCount);
        final double absMin = Math.abs(minValue);
        final double absMax = Math.abs(maxValue);
        final double largestValue = absMin <= absMax ? absMax : absMin;
        int exponent = (int) Math.floor(Math.log10(largestValue));
        if (Math.abs(exponent) < 5)
            exponent = 0;
        double first = minValue;
        int lastTickIndex = tickCount - 1;
        double step = tickRange / (double) lastTickIndex;
        if (Math.abs((first + step) - minValue) < Math.abs(step * 0.15D)) {
            tickCount = lastTickIndex--;
            first += step;
            tickRange -= step;
        }
        if (Math.abs((first + tickRange) - maxValue) > Math.abs(step * 0.85D)) {
            tickCount = lastTickIndex--;
            tickRange -= step;
        }
        if (tickCount < 3) {
            lastTickIndex = 2;
            tickCount = 3;
            first = minValue;
            tickRange = axisRange;
            step = tickRange / (double) lastTickIndex;
        }
        if (tickValues == null || tickValues.length != tickCount) {
            tickValues = new double[tickCount];
            tickNames = new String[tickCount];
        }
        for (int i = 1; i < lastTickIndex; i++) {
            double v = first + (double) i * step;
            tickValues[i] = v;
            tickNames[i] = valueToString(v, exponent);
        }

        tickValues[0] = minValue;
        tickNames[0] = valueToString(minValue, exponent);
        tickValues[lastTickIndex] = maxValue;
        tickNames[lastTickIndex] = valueToString(maxValue, exponent);
        getTickPositions();
    }

    final void setLocation(int orientation) {
        switch (orientation) {
        case TOP_X:
        default:
            isX = true;
            gr = new AbstractAxisDisplay.XAxisDisplay(false);
            break;
        case BOTTOM_X:
            isX = true;
            gr = new AbstractAxisDisplay.XAxisDisplay(true);
            break;
        case LEFT_Y:
            isX = false;
            gr = new AbstractAxisDisplay.YAxisDisplay(true);
            break;
        case RIGHT_Y:
            isX = false;
            gr = new AbstractAxisDisplay.YAxisDisplay(false);
            break;
        case RADIAL:
            isX = true;
            gr = new AbstractAxisDisplay.XAxisDisplay(false);
            break;
        }
    }

    public int getTouchId() {
        return TouchId;
    }

    public void setSize(Dimension graphSize) {
        int length;
        int breadth;
        if (isX) {
            length = graphSize.width - 2 * spacing;
            breadth = graphSize.height - 2 * spacing;
        } else {
            length = graphSize.height - 2 * spacing;
            breadth = graphSize.width - 2 * spacing;
        }
        this.breadth = breadth;
        if (length != this.length) {
            this.length = length;
            getTickPositions();
        }
    }

    public void draw(Graphics g, Dimension graphSize) {
        setSize(graphSize);
        draw(g);
    }

    public void draw(Graphics g) {
        if (!visible)
            return;
        gr.setGraphics(g);
        final FontMetrics fm = g.getFontMetrics(font);
        g.setColor(axisColor);
        gr.drawLine(0, 0, length + 2 * spacing, 0);
        int tickLength = this.tickLength;
        if (ticksInside)
            tickLength = -tickLength;
        final int maxTickCount = (int) (((float) length + 0.5F)
                / (float) gr.maxTickSize(tickNames, tickCount, font));
        final int minTickCount = Math.min(maxTickCount, bestTickCount);
        if (tickCount > maxTickCount)
            setTickCount(maxTickCount);
        else if (tickCount < minTickCount)
            setTickCount(minTickCount);
        for (int i = 0; i < tickCount; i++) {
            gr.drawTick(tickPos[i], tickLength);
        }
        g.setColor(labelColor);
        g.setFont(font);
        for (int i = 0; i < tickCount; i++) {
            gr.drawMultiLineTickName(tickNames[i], tickPos[i], tickLength, fm);
        }

        g.setFont(titleFont);
        gr.drawTitle(title, titleFont, length);
        if (!withGrid)
            return;
        g.setColor(gridColor);
        for (int i = 0; i < tickCount; i++) {
            gr.drawTick(tickPos[i], breadth);
        }
    }

    private static String valueToString(double v, int exponent) {
        if (exponent != 0) {
            final float vm = (float) (v * FastMath.pow(10D, -exponent));
            if (vm != 0.0F)
                return Float.toString(vm) + 'e' + exponent;
        }
        return Float.toString((float) v);
    }

    public final int getScreenPoint(double value) {
        final int p = spacing + (int) (((double) length * (value - minValue)) / axisRange);
        if (isX)
            return p;
        return -p;
    }

    private void getTickPositions() {
        if (tickPos == null || tickPos.length != tickCount)
            tickPos = new int[tickCount];
        for (int i = 0; i < tickCount; i++) {
            if (isX)
                tickPos[i] = getScreenPoint(tickValues[i]);
            else
                tickPos[i] = -getScreenPoint(tickValues[i]);
        }
        TouchId++;
    }

}