All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.hansolo.steelseries.tools.TickmarkImageFactory Maven / Gradle / Ivy

package eu.hansolo.steelseries.tools;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;


/**
 * @author Gerrit Grunwald 
 */
public enum TickmarkImageFactory {
    // 
    INSTANCE;
    private final Util UTIL = Util.INSTANCE;
    private static final BasicStroke MAJOR_TICKMARK_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL);
    private static final BasicStroke MEDIUM_TICKMARK_STROKE = new BasicStroke(0.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL);
    private static final BasicStroke MINOR_TICKMARK_STROKE = new BasicStroke(0.3f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL);
    private static final int BASE = 10;
    private NumberFormat numberFormat = NumberFormat.STANDARD;
    // Buffer variables of radial gauges
    private BufferedImage imageBufferRad = UTIL.createImage(1, 1, Transparency.TRANSLUCENT);
    private int widthBufferRad = 200;
    private double minValueBufferRad = 0;
    private double maxValueBufferRad = 100;
    private int noOfMinorTicksBufferRad = 0;
    private int noOfMajorTicksBufferRad = 0;
    private double minorTickSpacingBufferRad = 10;
    private double majorTickSpacingBufferRad = 10;
    private GaugeType gaugeTypeBufferRad = GaugeType.TYPE4;
    private TickmarkType minorTickmarkTypeBufferRad = TickmarkType.LINE;
    private TickmarkType majorTickmarkTypeBufferRad = TickmarkType.LINE;
    private boolean ticksVisibleBufferRad = true;
    private boolean ticklabelsVisibleBufferRad = true;
    private boolean tickmarkSectionsVisibleBufferRad = false;
    private boolean minorTicksVisibleBufferRad = true;
    private boolean majorTicksVisibleBufferRad = true;
    private NumberFormat numberFormatBufferRad = NumberFormat.AUTO;
    private BackgroundColor backgroundColorBufferRad = BackgroundColor.DARK_GRAY;
    private Color tickmarkColorBufferRad = backgroundColorBufferRad.LABEL_COLOR;
    private boolean tickmarkColorFromThemeBufferRad = true;
    private List
tickmarkSectionsBufferRad = new ArrayList
(10); private float radiusFactorBufferRad = 0.38f; private float textDistanceFactorBufferRad = 0.09f; private Point2D centerBufferRad = new Point2D.Double(); private Point2D offsetBufferRad = new Point2D.Double(); private Orientation orientationBufferRad = Orientation.NORTH; private TicklabelOrientation ticklabelOrientationBufferRad = TicklabelOrientation.TANGENT; private boolean niceScaleRad = true; private boolean logScaleRad = false; // Buffer variables of linear gauges private BufferedImage imageBufferLin = UTIL.createImage(1, 1, Transparency.TRANSLUCENT); private int widthBufferLin = 140; private int heightBufferLin = 0; private double minValueBufferLin = 0; private double maxValueBufferLin = 100; private int noOfMinorTicksBufferLin = 0; private int noOfMajorTicksBufferLin = 0; private double minorTickSpacingBufferLin = 10; private double majorTickSpacingBufferLin = 10; private TickmarkType minorTickmarkTypeBufferLin = TickmarkType.LINE; private TickmarkType majorTickmarkTypeBufferLin = TickmarkType.LINE; private boolean ticksVisibleBufferLin = true; private boolean ticklabelsVisibleBufferLin = true; private boolean minorTicksVisibleBufferLin = true; private boolean majorTicksVisibleBufferLin = true; private NumberFormat numberFormatBufferLin = NumberFormat.AUTO; private boolean tickmarkSectionsVisibleBufferLin = false; private BackgroundColor backgroundColorBufferLin = BackgroundColor.DARK_GRAY; private Color tickmarkColorBufferLin = backgroundColorBufferLin.LABEL_COLOR; private boolean tickmarkColorFromThemeBufferLin = true; private List
tickmarkSectionsBufferLin = new ArrayList
(10); private Point2D offsetBufferLin = new Point2D.Double(); private Orientation orientationBufferLin = Orientation.VERTICAL; private boolean niceScaleLin = true; private boolean logScaleLin = false; // // public BufferedImage create_RADIAL_TICKMARKS_Image(final int WIDTH, final double MIN_VALUE, final double MAX_VALUE, final int NO_OF_MINOR_TICKS, final int NO_OF_MAJOR_TICKS, final double MINOR_TICK_SPACING, final double MAJOR_TICK_SPACING, final GaugeType GAUGE_TYPE, final TickmarkType MINOR_TICKMARK_TYPE, final TickmarkType MAJOR_TICKMARK_TYPE, final boolean TICKS_VISIBLE, final boolean TICKLABELS_VISIBLE, final boolean MINOR_TICKS_VISIBLE, final boolean MAJOR_TICKS_VISIBLE, final NumberFormat NUMBER_FORMAT, final boolean TICKMARK_SECTIONS_VISIBLE, final BackgroundColor BACKGROUND_COLOR, final Color TICKMARK_COLOR, final boolean TICKMARK_COLOR_FROM_THEME, List
tickmarkSections, final float RADIUS_FACTOR, final float TEXT_DISTANCE_FACTOR, final Point2D CENTER, final Point2D OFFSET, final Orientation ORIENTATION, final TicklabelOrientation TICKLABEL_ORIENTATION, final boolean NICE_SCALE, final boolean LOG_SCALE, final BufferedImage BACKGROUND_IMAGE) { if (WIDTH <= 0) { return UTIL.createImage(1, 1, Transparency.TRANSLUCENT); } // Buffer check if (WIDTH == widthBufferRad && Double.compare(MIN_VALUE, minValueBufferRad) == 0 && Double.compare(MAX_VALUE, maxValueBufferRad) == 0 && NO_OF_MINOR_TICKS == noOfMinorTicksBufferRad && NO_OF_MAJOR_TICKS == noOfMajorTicksBufferRad && Double.compare(MINOR_TICK_SPACING, minorTickSpacingBufferRad) == 0 && Double.compare(MAJOR_TICK_SPACING, majorTickSpacingBufferRad) == 0 && GAUGE_TYPE == gaugeTypeBufferRad && MINOR_TICKMARK_TYPE == minorTickmarkTypeBufferRad && MAJOR_TICKMARK_TYPE == majorTickmarkTypeBufferRad && TICKS_VISIBLE == ticksVisibleBufferRad && TICKLABELS_VISIBLE == ticklabelsVisibleBufferRad && MINOR_TICKS_VISIBLE == minorTicksVisibleBufferRad && MAJOR_TICKS_VISIBLE == majorTicksVisibleBufferRad && TICKMARK_SECTIONS_VISIBLE == tickmarkSectionsVisibleBufferRad && NUMBER_FORMAT == numberFormatBufferRad && BACKGROUND_COLOR == backgroundColorBufferRad && TICKMARK_COLOR.equals(tickmarkColorBufferRad) && TICKMARK_COLOR_FROM_THEME == tickmarkColorFromThemeBufferRad && tickmarkSections.containsAll(tickmarkSectionsBufferRad) && Float.compare(RADIUS_FACTOR, radiusFactorBufferRad) == 0 && Float.compare(TEXT_DISTANCE_FACTOR, textDistanceFactorBufferRad) == 0 && CENTER.equals(centerBufferRad) && OFFSET.equals(offsetBufferRad) && orientationBufferRad == ORIENTATION && ticklabelOrientationBufferRad == TICKLABEL_ORIENTATION && niceScaleRad == NICE_SCALE && logScaleRad == LOG_SCALE) { if (BACKGROUND_IMAGE != null) { final Graphics2D G = BACKGROUND_IMAGE.createGraphics(); G.drawImage(imageBufferRad, 0, 0, null); G.dispose(); return imageBufferRad; } } // Create image if it equals null if (imageBufferRad != null) { imageBufferRad.flush(); } imageBufferRad = UTIL.createImage(WIDTH, WIDTH, Transparency.TRANSLUCENT); // Adjust the number format of the ticklabels if (NUMBER_FORMAT == NumberFormat.AUTO) { if (Math.abs(MAJOR_TICK_SPACING) > 1000) { numberFormat = NumberFormat.SCIENTIFIC; } else if (MAJOR_TICK_SPACING % 1.0 != 0) { numberFormat = NumberFormat.FRACTIONAL; } else { numberFormat = NumberFormat.STANDARD; } } else { numberFormat = NUMBER_FORMAT; } // Definitions final Font STD_FONT = new Font("Verdana", 0, (int) (0.04 * WIDTH)); final int TEXT_DISTANCE = (int) (TEXT_DISTANCE_FACTOR * WIDTH); double ticklabelRotationOffset = 0; final int MINOR_TICK_LENGTH = (int) (0.0133333333 * WIDTH); final int MEDIUM_TICK_LENGTH = (int) (0.02 * WIDTH); final int MAJOR_TICK_LENGTH = (int) (0.03 * WIDTH); final int MINOR_DIAMETER = (int) (0.0093457944 * WIDTH); //final int MEDIUM_DIAMETER = (int) (0.0186915888 * WIDTH); final int MAJOR_DIAMETER = (int) (0.03 * WIDTH); final Point2D TEXT_POINT = new Point2D.Double(0, 0); final Point2D INNER_POINT = new Point2D.Double(0, 0); final Point2D OUTER_POINT = new Point2D.Double(0, 0); final Point2D OUTER_POINT_LEFT = new Point2D.Double(0, 0); final Point2D OUTER_POINT_RIGHT = new Point2D.Double(0, 0); final Line2D TICK_LINE = new Line2D.Double(0, 0, 1, 1); final Ellipse2D TICK_CIRCLE = new Ellipse2D.Double(0, 0, 1, 1); final GeneralPath TICK_TRIANGLE = new GeneralPath(); final double ROTATION_OFFSET = GAUGE_TYPE.ROTATION_OFFSET; // Depends on GaugeType final float RADIUS = WIDTH * RADIUS_FACTOR; final double ANGLE_STEP = (GAUGE_TYPE.ANGLE_RANGE / ((MAX_VALUE - MIN_VALUE) / MINOR_TICK_SPACING)); double sinValue = 0; double cosValue = 0; double valueCounter = MIN_VALUE; int majorTickCounter = NO_OF_MINOR_TICKS - 1; // Indicator when to draw the major tickmark // Create the image final Graphics2D G2 = imageBufferRad.createGraphics(); G2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); G2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); G2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); G2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); // Set some default parameters for the graphics object if (OFFSET != null) { G2.translate(OFFSET.getX(), OFFSET.getY()); } G2.setFont(STD_FONT); G2.rotate(ROTATION_OFFSET - Math.PI, CENTER.getX(), CENTER.getY()); if (TICKMARK_COLOR_FROM_THEME) { G2.setColor(BACKGROUND_COLOR.LABEL_COLOR); } else { G2.setColor(TICKMARK_COLOR); } if (!LOG_SCALE) { for (double alpha = 0, counter = MIN_VALUE; Double.compare(counter, MAX_VALUE) <= 0; alpha -= ANGLE_STEP, counter += MINOR_TICK_SPACING) { // Set the color if (tickmarkSections != null && !tickmarkSections.isEmpty()) { if (TICKMARK_SECTIONS_VISIBLE) { for (Section section : tickmarkSections) { if (Double.compare(valueCounter, section.getStart()) >= 0 && Double.compare(valueCounter, section.getStop()) <= 0) { G2.setColor(Util.INSTANCE.setAlpha(section.getColor(), 1.0f)); break; } else if (TICKMARK_COLOR_FROM_THEME) { G2.setColor(BACKGROUND_COLOR.LABEL_COLOR); } else { G2.setColor(TICKMARK_COLOR); } } } else { if (TICKMARK_COLOR_FROM_THEME) { G2.setColor(BACKGROUND_COLOR.LABEL_COLOR); } else { G2.setColor(TICKMARK_COLOR); } } } sinValue = Math.sin(alpha); cosValue = Math.cos(alpha); majorTickCounter++; // Draw tickmark every major tickmark spacing if (majorTickCounter == NO_OF_MINOR_TICKS) { G2.setStroke(MAJOR_TICKMARK_STROKE); INNER_POINT.setLocation(CENTER.getX() + (RADIUS - MAJOR_TICK_LENGTH) * sinValue, CENTER.getY() + (RADIUS - MAJOR_TICK_LENGTH) * cosValue); OUTER_POINT.setLocation(CENTER.getX() + RADIUS * sinValue, CENTER.getY() + RADIUS * cosValue); TEXT_POINT.setLocation(CENTER.getX() + (RADIUS - TEXT_DISTANCE) * sinValue, CENTER.getY() + (RADIUS - TEXT_DISTANCE) * cosValue); // Draw the major tickmarks if (TICKS_VISIBLE && MAJOR_TICKS_VISIBLE) { drawRadialTicks(G2, INNER_POINT, OUTER_POINT, CENTER, RADIUS, MAJOR_TICKMARK_TYPE, TICK_LINE, TICK_CIRCLE, TICK_TRIANGLE, MAJOR_TICK_LENGTH, MAJOR_DIAMETER, OUTER_POINT_LEFT, OUTER_POINT_RIGHT, alpha); } // Draw the standard tickmark labels if (TICKLABELS_VISIBLE) { switch(TICKLABEL_ORIENTATION) { case NORMAL: if (Double.compare(alpha, -GAUGE_TYPE.TICKLABEL_ORIENTATION_CHANGE_ANGLE) > 0) { G2.fill(UTIL.rotateTextAroundCenter(G2, numberFormat.format(valueCounter), (int) TEXT_POINT.getX(), (int) TEXT_POINT.getY(), (-Math.PI / 2 - alpha))); } else { G2.fill(UTIL.rotateTextAroundCenter(G2, numberFormat.format(valueCounter), (int) TEXT_POINT.getX(), (int) TEXT_POINT.getY(), (Math.PI / 2 - alpha))); } break; case HORIZONTAL: G2.fill(UTIL.rotateTextAroundCenter(G2, numberFormat.format(valueCounter), (int) TEXT_POINT.getX(), (int) TEXT_POINT.getY(), Math.PI - GAUGE_TYPE.ROTATION_OFFSET)); break; case TANGENT: default: G2.fill(UTIL.rotateTextAroundCenter(G2, numberFormat.format(valueCounter), (int) TEXT_POINT.getX(), (int) TEXT_POINT.getY(), (Math.PI - alpha + ticklabelRotationOffset))); break; } } valueCounter += MAJOR_TICK_SPACING; majorTickCounter = 0; continue; } // Draw tickmark every minor tickmark spacing { INNER_POINT.setLocation(CENTER.getX() + (RADIUS - MINOR_TICK_LENGTH) * sinValue, CENTER.getY() + (RADIUS - MINOR_TICK_LENGTH) * cosValue); OUTER_POINT.setLocation(CENTER.getX() + RADIUS * sinValue, CENTER.getY() + RADIUS * cosValue); G2.setStroke(MINOR_TICKMARK_STROKE); if (NO_OF_MINOR_TICKS % 2 == 0 && majorTickCounter == (NO_OF_MINOR_TICKS / 2)) { G2.setStroke(MEDIUM_TICKMARK_STROKE); INNER_POINT.setLocation(CENTER.getX() + (RADIUS - MEDIUM_TICK_LENGTH) * sinValue, CENTER.getY() + (RADIUS - MEDIUM_TICK_LENGTH) * cosValue); OUTER_POINT.setLocation(CENTER.getX() + RADIUS * sinValue, CENTER.getY() + RADIUS * cosValue); } // Draw the minor tickmarks if (TICKS_VISIBLE && MINOR_TICKS_VISIBLE) { drawRadialTicks(G2, INNER_POINT, OUTER_POINT, CENTER, RADIUS, MINOR_TICKMARK_TYPE, TICK_LINE, TICK_CIRCLE, TICK_TRIANGLE, MINOR_TICK_LENGTH, MINOR_DIAMETER, OUTER_POINT_LEFT, OUTER_POINT_RIGHT, alpha); } } } } else { // ****************************** LOGARITHMIC SCALING ****************************************************** final double LOG_ANGLE_STEP = Math.abs(GAUGE_TYPE.ANGLE_RANGE / UTIL.logOfBase(BASE, (MAX_VALUE - MIN_VALUE))); int exponent = 0; double angle = 0; double valueStep = 1.0; for (double value = 1 ; Double.compare(value, MAX_VALUE) <= 0; value += valueStep) { if (TICKMARK_COLOR_FROM_THEME) { G2.setColor(BACKGROUND_COLOR.LABEL_COLOR); } else { G2.setColor(TICKMARK_COLOR); } angle = UTIL.logOfBase(BASE, Math.abs(value)) * LOG_ANGLE_STEP; sinValue = Math.sin(-angle); cosValue = Math.cos(-angle); INNER_POINT.setLocation(CENTER.getX() + (RADIUS - MINOR_TICK_LENGTH) * sinValue, CENTER.getY() + (RADIUS - MINOR_TICK_LENGTH) * cosValue); OUTER_POINT.setLocation(CENTER.getX() + RADIUS * sinValue, CENTER.getY() + RADIUS * cosValue); G2.setStroke(MINOR_TICKMARK_STROKE); if (Double.compare(value, Math.pow(BASE, exponent + 1)) == 0) { exponent++; valueStep = Math.pow(BASE, exponent); INNER_POINT.setLocation(CENTER.getX() + (RADIUS - MAJOR_TICK_LENGTH) * sinValue, CENTER.getY() + (RADIUS - MAJOR_TICK_LENGTH) * cosValue); OUTER_POINT.setLocation(CENTER.getX() + RADIUS * sinValue, CENTER.getY() + RADIUS * cosValue); TEXT_POINT.setLocation(CENTER.getX() + (RADIUS - TEXT_DISTANCE) * sinValue, CENTER.getY() + (RADIUS - TEXT_DISTANCE) * cosValue); if (TICKLABELS_VISIBLE) { switch(TICKLABEL_ORIENTATION) { case NORMAL: if (Double.compare(value, -GAUGE_TYPE.TICKLABEL_ORIENTATION_CHANGE_ANGLE) > 0) { G2.fill(UTIL.rotateTextAroundCenter(G2, numberFormat.format(value), (int) TEXT_POINT.getX(), (int) TEXT_POINT.getY(), (-Math.PI / 2 + angle))); } else { G2.fill(UTIL.rotateTextAroundCenter(G2, numberFormat.format(value), (int) TEXT_POINT.getX(), (int) TEXT_POINT.getY(), (Math.PI / 2 + angle))); } break; case HORIZONTAL: G2.fill(UTIL.rotateTextAroundCenter(G2, numberFormat.format(value), (int) TEXT_POINT.getX(), (int) TEXT_POINT.getY(), Math.PI - GAUGE_TYPE.ROTATION_OFFSET)); break; case TANGENT: default: G2.fill(UTIL.rotateTextAroundCenter(G2, numberFormat.format(value), (int) TEXT_POINT.getX(), (int) TEXT_POINT.getY(), (Math.PI + angle + ticklabelRotationOffset))); break; } } G2.setStroke(MAJOR_TICKMARK_STROKE); } if (TICKS_VISIBLE && MAJOR_TICKS_VISIBLE && MINOR_TICKS_VISIBLE) { TICK_LINE.setLine(INNER_POINT, OUTER_POINT); G2.draw(TICK_LINE); } } } G2.dispose(); if (BACKGROUND_IMAGE != null) { final Graphics2D G = BACKGROUND_IMAGE.createGraphics(); G.drawImage(imageBufferRad, 0, 0, null); G.dispose(); } // Buffer the current parameters widthBufferRad = WIDTH; minValueBufferRad = MIN_VALUE; maxValueBufferRad = MAX_VALUE; noOfMinorTicksBufferRad = NO_OF_MINOR_TICKS; noOfMajorTicksBufferRad = NO_OF_MAJOR_TICKS; minorTickSpacingBufferRad = MINOR_TICK_SPACING; majorTickSpacingBufferRad = MAJOR_TICK_SPACING; gaugeTypeBufferRad = GAUGE_TYPE; minorTickmarkTypeBufferRad = MINOR_TICKMARK_TYPE; majorTickmarkTypeBufferRad = MAJOR_TICKMARK_TYPE; ticksVisibleBufferRad = TICKS_VISIBLE; ticklabelsVisibleBufferRad = TICKLABELS_VISIBLE; minorTicksVisibleBufferRad = MINOR_TICKS_VISIBLE; majorTicksVisibleBufferRad = MAJOR_TICKS_VISIBLE; tickmarkSectionsVisibleBufferRad = TICKMARK_SECTIONS_VISIBLE; numberFormatBufferRad = NUMBER_FORMAT; backgroundColorBufferRad = BACKGROUND_COLOR; tickmarkColorBufferRad = TICKMARK_COLOR; tickmarkColorFromThemeBufferRad = TICKMARK_COLOR_FROM_THEME; if (tickmarkSections != null) { tickmarkSectionsBufferRad.clear(); tickmarkSectionsBufferRad.addAll(tickmarkSections); } radiusFactorBufferRad = RADIUS_FACTOR; textDistanceFactorBufferRad = TEXT_DISTANCE_FACTOR; centerBufferRad.setLocation(CENTER); if (OFFSET != null) { offsetBufferRad.setLocation(OFFSET); } orientationBufferRad = ORIENTATION; ticklabelOrientationBufferRad = TICKLABEL_ORIENTATION; niceScaleRad = NICE_SCALE; logScaleRad = LOG_SCALE; return imageBufferRad; } private void drawRadialTicks(final Graphics2D G2, final Point2D INNER_POINT, final Point2D OUTER_POINT, final Point2D CENTER, final double RADIUS, final TickmarkType TICKMARK_TYPE, final Line2D TICK_LINE, final Ellipse2D TICK_CIRCLE, final GeneralPath TICK_TRIANGLE, final double TICK_LENGTH, final double DIAMETER, final Point2D OUTER_POINT_LEFT, final Point2D OUTER_POINT_RIGHT, final double ALPHA) { // Draw tickmark every major tickmark spacing switch (TICKMARK_TYPE) { case CIRCLE: TICK_CIRCLE.setFrame(OUTER_POINT.getX() - DIAMETER / 2.0, OUTER_POINT.getY() - DIAMETER / 2.0, DIAMETER, DIAMETER); G2.fill(TICK_CIRCLE); break; case TRIANGLE: OUTER_POINT_LEFT.setLocation(CENTER.getX() + RADIUS * Math.sin(ALPHA - Math.toRadians(Math.asin(TICK_LENGTH / 16.0))), CENTER.getY() + RADIUS * Math.cos(ALPHA - Math.toRadians(Math.asin(TICK_LENGTH / 16.0)))); OUTER_POINT_RIGHT.setLocation(CENTER.getX() + RADIUS * Math.sin(ALPHA + Math.toRadians(Math.asin(TICK_LENGTH / 16.0))), CENTER.getY() + RADIUS * Math.cos(ALPHA + Math.toRadians(Math.asin(TICK_LENGTH / 16.0)))); TICK_TRIANGLE.reset(); TICK_TRIANGLE.moveTo(INNER_POINT.getX(), INNER_POINT.getY()); TICK_TRIANGLE.lineTo(OUTER_POINT_LEFT.getX(), OUTER_POINT_LEFT.getY()); TICK_TRIANGLE.lineTo(OUTER_POINT_RIGHT.getX(), OUTER_POINT_RIGHT.getY()); TICK_TRIANGLE.closePath(); G2.fill(TICK_TRIANGLE); break; case LINE: default: TICK_LINE.setLine(INNER_POINT, OUTER_POINT); G2.draw(TICK_LINE); break; } } // // public BufferedImage create_LINEAR_TICKMARKS_Image(final int WIDTH, final int HEIGHT, final double MIN_VALUE, final double MAX_VALUE, final int NO_OF_MINOR_TICKS, final int NO_OF_MAJOR_TICKS, final double MINOR_TICK_SPACING, final double MAJOR_TICK_SPACING, final TickmarkType MINOR_TICKMARK_TYPE, final TickmarkType MAJOR_TICKMARK_TYPE, final boolean TICKS_VISIBLE, final boolean TICKLABELS_VISIBLE, final boolean MINOR_TICKS_VISIBLE, final boolean MAJOR_TICKS_VISIBLE, final NumberFormat NUMBER_FORMAT, final boolean TICKMARK_SECTIONS_VISIBLE, final BackgroundColor BACKGROUND_COLOR, final Color TICKMARK_COLOR, final boolean TICKMARK_COLOR_FROM_THEME, List
tickmarkSections, final Point2D OFFSET, final Orientation ORIENTATION, final boolean NICE_SCALE, final boolean LOG_SCALE, final BufferedImage BACKGROUND_IMAGE) { if (WIDTH <= 0 || HEIGHT <= 0) { return UTIL.createImage(1, 1, Transparency.TRANSLUCENT); } // Buffer check if (WIDTH == widthBufferLin && HEIGHT == heightBufferLin && Double.compare(MIN_VALUE, minValueBufferLin) == 0 && Double.compare(MAX_VALUE, maxValueBufferLin) == 0 && NO_OF_MINOR_TICKS == noOfMinorTicksBufferLin && NO_OF_MAJOR_TICKS == noOfMajorTicksBufferLin && Double.compare(MINOR_TICK_SPACING, minorTickSpacingBufferLin) == 0 && Double.compare(MAJOR_TICK_SPACING, majorTickSpacingBufferLin) == 0 && MINOR_TICKMARK_TYPE == minorTickmarkTypeBufferLin && MAJOR_TICKMARK_TYPE == majorTickmarkTypeBufferLin && TICKS_VISIBLE == ticksVisibleBufferLin && MINOR_TICKS_VISIBLE == minorTicksVisibleBufferLin && MAJOR_TICKS_VISIBLE == majorTicksVisibleBufferLin && TICKLABELS_VISIBLE == ticklabelsVisibleBufferLin && NUMBER_FORMAT == numberFormatBufferLin && TICKMARK_SECTIONS_VISIBLE == tickmarkSectionsVisibleBufferLin && BACKGROUND_COLOR == backgroundColorBufferLin && TICKMARK_COLOR.equals(tickmarkColorBufferLin) && TICKMARK_COLOR_FROM_THEME == tickmarkColorFromThemeBufferLin && tickmarkSections.containsAll(tickmarkSectionsBufferLin) && OFFSET.equals(offsetBufferLin) && ORIENTATION == orientationBufferLin && NICE_SCALE == niceScaleLin && LOG_SCALE == logScaleLin) { if (BACKGROUND_IMAGE != null) { final Graphics2D G = BACKGROUND_IMAGE.createGraphics(); G.drawImage(imageBufferLin, 0, 0, null); G.dispose(); return imageBufferLin; } } // Create image if it equals null if (imageBufferLin != null) { imageBufferLin.flush(); } imageBufferLin = UTIL.createImage(WIDTH, HEIGHT, Transparency.TRANSLUCENT); // Adjust the number format of the ticklabels if (NUMBER_FORMAT == NumberFormat.AUTO) { if (Math.abs(MAJOR_TICK_SPACING) > 1000) { numberFormat = NumberFormat.SCIENTIFIC; } else if (MAJOR_TICK_SPACING % 1.0 != 0) { numberFormat = NumberFormat.FRACTIONAL; } } else { numberFormat = NUMBER_FORMAT; } // Definitions final Font STD_FONT; final Rectangle2D SCALE_BOUNDS; final int MINOR_DIAMETER; final int MAJOR_DIAMETER; final int MINOR_TICK_START; final int MINOR_TICK_STOP; final int MEDIUM_TICK_START; final int MEDIUM_TICK_STOP; final int MAJOR_TICK_START; final int MAJOR_TICK_STOP; double tickSpaceScaling = 1.0; if (ORIENTATION == Orientation.VERTICAL) { // Vertical orientation STD_FONT = new Font("Verdana", 0, (int) (0.062 * WIDTH)); SCALE_BOUNDS = new Rectangle2D.Double(0, HEIGHT * 0.12864077669902912, 0, (HEIGHT * 0.8567961165048543 - HEIGHT * 0.12864077669902912)); MINOR_DIAMETER = (int) (0.0186915888 * WIDTH); MAJOR_DIAMETER = (int) (0.0280373832 * WIDTH); MINOR_TICK_START = (int) (0.34 * WIDTH); MINOR_TICK_STOP = (int) (0.36 * WIDTH); MEDIUM_TICK_START = (int) (0.33 * WIDTH); MEDIUM_TICK_STOP = (int) (0.36 * WIDTH); MAJOR_TICK_START = (int) (0.32 * WIDTH); MAJOR_TICK_STOP = (int) (0.36 * WIDTH); tickSpaceScaling = SCALE_BOUNDS.getHeight() / (MAX_VALUE - MIN_VALUE); } else { // Horizontal orientation STD_FONT = new Font("Verdana", 0, (int) (0.062 * HEIGHT)); SCALE_BOUNDS = new Rectangle2D.Double(WIDTH * 0.14285714285714285, 0, (WIDTH * 0.8710124827 - WIDTH * 0.14285714285714285), 0); MINOR_DIAMETER = (int) (0.0186915888 * HEIGHT); MAJOR_DIAMETER = (int) (0.0280373832 * HEIGHT); MINOR_TICK_START = (int) (0.65 * HEIGHT); MINOR_TICK_STOP = (int) (0.63 * HEIGHT); MEDIUM_TICK_START = (int) (0.66 * HEIGHT); MEDIUM_TICK_STOP = (int) (0.63 * HEIGHT); MAJOR_TICK_START = (int) (0.67 * HEIGHT); MAJOR_TICK_STOP = (int) (0.63 * HEIGHT); tickSpaceScaling = SCALE_BOUNDS.getWidth() / (MAX_VALUE - MIN_VALUE); } final Graphics2D G2 = imageBufferLin.createGraphics(); G2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); G2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); G2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); G2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); // Set some default parameters for the graphics object if (OFFSET != null) { G2.translate(OFFSET.getX(), OFFSET.getY()); } G2.setFont(STD_FONT); if (TICKMARK_COLOR_FROM_THEME) { G2.setColor(BACKGROUND_COLOR.LABEL_COLOR); } else { G2.setColor(TICKMARK_COLOR); } final FontRenderContext RENDER_CONTEXT = new FontRenderContext(null, true, true); final TextLayout TEXT_LAYOUT = new TextLayout(numberFormat.format(MAX_VALUE), G2.getFont(), RENDER_CONTEXT); final Rectangle2D MAX_BOUNDS = TEXT_LAYOUT.getBounds(); // needed to align the numbers on the right (in vertical layout) final Line2D TICK_LINE = new Line2D.Double(0, 0, 1, 1); final Ellipse2D TICK_CIRCLE = new Ellipse2D.Double(0, 0, 1, 1); final GeneralPath TICK_TRIANGLE = new GeneralPath(); TextLayout currentLayout; Rectangle2D currentBounds; float textOffset = 0; double currentPos = 0; double valueCounter = MIN_VALUE; int majorTickCounter = NO_OF_MINOR_TICKS - 1; // Indicator when to draw the major tickmark if (!LOG_SCALE) { // Non logarithmic scaling for (double labelCounter = MIN_VALUE, tickCounter = 0; Float.compare((float) labelCounter, (float) MAX_VALUE) <= 0; labelCounter += MINOR_TICK_SPACING, tickCounter += MINOR_TICK_SPACING) { // Adjust the color for the tickmark and labels if (tickmarkSections != null && !tickmarkSections.isEmpty()) { if (TICKMARK_SECTIONS_VISIBLE) { for (Section section : tickmarkSections) { if ((Double.compare(tickCounter, section.getStart()) >= 0) && (Double.compare(tickCounter, section.getStop()) <= 0)) { G2.setColor(section.getColor()); break; } else if (TICKMARK_COLOR_FROM_THEME) { G2.setColor(BACKGROUND_COLOR.LABEL_COLOR); } else { G2.setColor(TICKMARK_COLOR); } } } else { if (TICKMARK_COLOR_FROM_THEME) { G2.setColor(BACKGROUND_COLOR.LABEL_COLOR); } else { G2.setColor(TICKMARK_COLOR); } } } else { if (TICKMARK_COLOR_FROM_THEME) { G2.setColor(BACKGROUND_COLOR.LABEL_COLOR); } else { G2.setColor(TICKMARK_COLOR); } } // Calculate the bounds of the scaling if (ORIENTATION == Orientation.VERTICAL) { currentPos = SCALE_BOUNDS.getMaxY() - tickCounter * tickSpaceScaling; } else { currentPos = SCALE_BOUNDS.getX() + tickCounter * tickSpaceScaling; } majorTickCounter++; // Draw tickmark every major tickmark spacing if (majorTickCounter == NO_OF_MINOR_TICKS) { G2.setStroke(MAJOR_TICKMARK_STROKE); // Draw the major tickmarks if (TICKS_VISIBLE && MAJOR_TICKS_VISIBLE) { drawLinearTicks(G2, WIDTH, HEIGHT, ORIENTATION, currentPos, MAJOR_TICKMARK_TYPE, TICK_LINE, TICK_CIRCLE, TICK_TRIANGLE, MAJOR_TICK_START, MAJOR_TICK_STOP, MAJOR_DIAMETER); } // Draw the standard tickmark labels if (TICKLABELS_VISIBLE) { currentLayout = new TextLayout(numberFormat.format(valueCounter), G2.getFont(), RENDER_CONTEXT); currentBounds = currentLayout.getBounds(); if (ORIENTATION == Orientation.VERTICAL) { // Vertical orientation textOffset = (float) (MAX_BOUNDS.getWidth() - currentBounds.getWidth()); G2.drawString(numberFormat.format(valueCounter), 0.18f * WIDTH + textOffset, (float) (currentPos - currentBounds.getHeight() / 2.0 + currentBounds.getHeight())); } else { // Horizontal orientation G2.drawString(numberFormat.format(valueCounter), (float) (tickCounter * tickSpaceScaling - currentBounds.getWidth() / 3.0 + SCALE_BOUNDS.getX()), (float) (HEIGHT * 0.68 + 1.5 * currentBounds.getHeight())); } } valueCounter += MAJOR_TICK_SPACING; majorTickCounter = 0; continue; } // Draw tickmark every minor tickmark spacing if (TICKS_VISIBLE && MINOR_TICKS_VISIBLE) { G2.setStroke(MINOR_TICKMARK_STROKE); if (NO_OF_MINOR_TICKS % 2 == 0 && majorTickCounter == (NO_OF_MINOR_TICKS / 2)) { G2.setStroke(MEDIUM_TICKMARK_STROKE); drawLinearTicks(G2, WIDTH, HEIGHT, ORIENTATION, currentPos, MINOR_TICKMARK_TYPE, TICK_LINE, TICK_CIRCLE, TICK_TRIANGLE, MEDIUM_TICK_START, MEDIUM_TICK_STOP, MINOR_DIAMETER); } else { drawLinearTicks(G2, WIDTH, HEIGHT, ORIENTATION, currentPos, MINOR_TICKMARK_TYPE, TICK_LINE, TICK_CIRCLE, TICK_TRIANGLE, MINOR_TICK_START, MINOR_TICK_STOP, MINOR_DIAMETER); } } } } else { // Logarithmic scaling if (TICKS_VISIBLE) { double offset; double limit; if (ORIENTATION == Orientation.VERTICAL) { offset = SCALE_BOUNDS.getMaxY(); limit = SCALE_BOUNDS.getMinY(); } else { offset = SCALE_BOUNDS.getMinX(); limit = SCALE_BOUNDS.getMaxX(); } double stepSize = 1; int exponent = 0; double factor = Math.abs(limit - offset) / (UTIL.logOfBase(BASE, MAX_VALUE)); double pos; Line2D tick = new Line2D.Double(); if (TICKMARK_COLOR_FROM_THEME) { G2.setColor(BACKGROUND_COLOR.LABEL_COLOR); } else { G2.setColor(TICKMARK_COLOR); } for (int counter = 0 ; counter <= MAX_VALUE ; counter += stepSize) { G2.setStroke(MEDIUM_TICKMARK_STROKE); if (ORIENTATION == Orientation.VERTICAL) { pos = offset - factor * UTIL.logOfBase(BASE, counter); tick.setLine(MEDIUM_TICK_START, pos, MEDIUM_TICK_STOP, pos); } else { pos = factor * UTIL.logOfBase(BASE, counter) + offset; tick.setLine(pos, MEDIUM_TICK_START, pos, MEDIUM_TICK_STOP); } if (counter == (int)Math.pow(BASE, exponent + 1)) { exponent++; stepSize = Math.pow(BASE, exponent); G2.setStroke(MAJOR_TICKMARK_STROKE); if (ORIENTATION == Orientation.VERTICAL) { tick.setLine(MAJOR_TICK_START, pos, MAJOR_TICK_STOP, pos); } else { tick.setLine(pos, MAJOR_TICK_START, pos, MAJOR_TICK_STOP); } // Ticklabels if (TICKLABELS_VISIBLE) { currentLayout = new TextLayout(numberFormat.format(counter), G2.getFont(), RENDER_CONTEXT); currentBounds = currentLayout.getBounds(); if (ORIENTATION == Orientation.VERTICAL) { // Vertical orientation textOffset = (float) (MAX_BOUNDS.getWidth() - currentBounds.getWidth()); G2.drawString(numberFormat.format(counter), 0.18f * WIDTH + textOffset, (float) (pos - currentBounds.getHeight() / 2.0 + currentBounds.getHeight())); } else { // Horizontal orientation G2.drawString(numberFormat.format(counter), (float) (pos - currentBounds.getWidth() / 3.0), (float) (HEIGHT * 0.68 + 1.5 * currentBounds.getHeight())); } } } G2.draw(tick); } } } G2.dispose(); if (BACKGROUND_IMAGE != null) { final Graphics2D G = BACKGROUND_IMAGE.createGraphics(); G.drawImage(imageBufferLin, 0, 0, null); G.dispose(); } // Buffer the current parameters widthBufferLin = WIDTH; heightBufferLin = HEIGHT; minValueBufferLin = MIN_VALUE; maxValueBufferLin = MAX_VALUE; noOfMinorTicksBufferLin = NO_OF_MINOR_TICKS; noOfMajorTicksBufferLin = NO_OF_MAJOR_TICKS; minorTickSpacingBufferLin = MINOR_TICK_SPACING; majorTickSpacingBufferLin = MAJOR_TICK_SPACING; minorTickmarkTypeBufferLin = MINOR_TICKMARK_TYPE; majorTickmarkTypeBufferLin = MAJOR_TICKMARK_TYPE; ticksVisibleBufferLin = TICKS_VISIBLE; ticklabelsVisibleBufferLin = TICKLABELS_VISIBLE; minorTicksVisibleBufferLin = MINOR_TICKS_VISIBLE; majorTicksVisibleBufferLin = MAJOR_TICKS_VISIBLE; numberFormatBufferLin = NUMBER_FORMAT; tickmarkSectionsVisibleBufferLin = TICKMARK_SECTIONS_VISIBLE; backgroundColorBufferLin = BACKGROUND_COLOR; tickmarkColorBufferLin = TICKMARK_COLOR; tickmarkColorFromThemeBufferLin = TICKMARK_COLOR_FROM_THEME; if (tickmarkSections != null) { tickmarkSectionsBufferLin.clear(); tickmarkSectionsBufferLin.addAll(tickmarkSections); } if (OFFSET != null) { offsetBufferLin.setLocation(OFFSET); } orientationBufferLin = ORIENTATION; niceScaleLin = NICE_SCALE; logScaleLin = LOG_SCALE; return imageBufferLin; } private void drawLinearTicks(final Graphics2D G2, final int WIDTH, final int HEIGHT, final Orientation ORIENTATION, final double CURRENT_POS, final TickmarkType TICKMARK_TYPE, final Line2D TICK_LINE, final Ellipse2D TICK_CIRCLE, final GeneralPath TICK_TRIANGLE, final double TICK_START, final double TICK_STOP, final double DIAMETER) { switch (TICKMARK_TYPE) { case CIRCLE: if (ORIENTATION == Orientation.VERTICAL) { TICK_CIRCLE.setFrame(TICK_START, CURRENT_POS - DIAMETER / 2.0, DIAMETER, DIAMETER); } else { TICK_CIRCLE.setFrame(CURRENT_POS - DIAMETER / 2.0, TICK_STOP, DIAMETER, DIAMETER); } G2.fill(TICK_CIRCLE); break; case TRIANGLE: TICK_TRIANGLE.reset(); if (ORIENTATION == Orientation.VERTICAL) { // Vertical orientation TICK_TRIANGLE.moveTo(TICK_START, CURRENT_POS + WIDTH * 0.005); TICK_TRIANGLE.lineTo(TICK_START, CURRENT_POS - WIDTH * 0.005); TICK_TRIANGLE.lineTo(TICK_STOP, CURRENT_POS); TICK_TRIANGLE.closePath(); } else { // Horizontal orientation TICK_TRIANGLE.moveTo(CURRENT_POS - HEIGHT * 0.005, TICK_START); TICK_TRIANGLE.lineTo(CURRENT_POS + HEIGHT * 0.005, TICK_START); TICK_TRIANGLE.lineTo(CURRENT_POS, TICK_STOP); TICK_TRIANGLE.closePath(); } G2.fill(TICK_TRIANGLE); break; case LINE: default: if (ORIENTATION == Orientation.VERTICAL) { // Vertical orientation TICK_LINE.setLine(TICK_START, CURRENT_POS, TICK_STOP, CURRENT_POS); } else { // Horizontal orientation TICK_LINE.setLine(CURRENT_POS, TICK_START, CURRENT_POS, TICK_STOP); } G2.draw(TICK_LINE); break; } } // }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy