/**
* Copyright (C) 2010-14 diirt developers. See COPYRIGHT.TXT
* All rights reserved. Use is subject to license terms. See LICENSE.TXT
*/
package org.diirt.graphene;
import org.diirt.util.stats.Range;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.Arrays;
import java.util.List;
import org.diirt.util.array.ListNumber;
import org.diirt.util.array.SortedListView;
import org.diirt.util.stats.Ranges;
/**
* Renderer for a line graph.
*
* @author carcassi
*/
public class LineGraph2DRenderer extends Graph2DRenderer<LineGraph2DRendererUpdate> {
public static java.util.List<InterpolationScheme> supportedInterpolationScheme = Arrays.asList(InterpolationScheme.NEAREST_NEIGHBOR, InterpolationScheme.LINEAR, InterpolationScheme.CUBIC);
public static java.util.List<ReductionScheme> supportedReductionScheme = Arrays.asList(ReductionScheme.FIRST_MAX_MIN_LAST, ReductionScheme.NONE);
@Override
public LineGraph2DRendererUpdate newUpdate() {
return new LineGraph2DRendererUpdate();
}
private NumberColorMap valueColorScheme = NumberColorMaps.GRAY;
private NumberColorMapInstance valueColorSchemeInstance;
private Range datasetRange;
private InterpolationScheme interpolation = InterpolationScheme.NEAREST_NEIGHBOR;
private ReductionScheme reduction = ReductionScheme.FIRST_MAX_MIN_LAST;
// Pixel focus
private Integer focusPixelX;
private boolean highlightFocusValue = false;
private int focusValueIndex = -1;
/**
* Creates a new line graph renderer.
*
* @param imageWidth the graph width
* @param imageHeight the graph height
*/
public LineGraph2DRenderer(int imageWidth, int imageHeight) {
super(imageWidth, imageHeight);
}
/**
* The current interpolation used for the line.
*
* @return the current interpolation
*/
public InterpolationScheme getInterpolation() {
return interpolation;
}
/**
*Current state of highlightFocusValue.
* <ul>
* <li>True - highlight and show the value the mouse is on.</li>
* <li>False - Avoid calculation involved with finding the highlighted value/ do not highlight the value.</li>
* </ul>
* @return true or false
*/
public boolean isHighlightFocusValue() {
return highlightFocusValue;
}
/**
*Current index of the value that the mouse is focused on.
* @return focused index (in the dataset).
*/
public int getFocusValueIndex() {
return focusValueIndex;
}
/**
*Current x-position(pixel) of the value that the mouse is focused on.
* @return the x position that the mouse is focused on in the graph (pixel).
*/
public Integer getFocusPixelX() {
return focusPixelX;
}
@Override
public void update(LineGraph2DRendererUpdate update) {
super.update(update);
if(update.getValueColorScheme() != null){
valueColorScheme = update.getValueColorScheme();
if (datasetRange != null) {
valueColorSchemeInstance = valueColorScheme.createInstance(datasetRange);
}
}
if (update.getInterpolation() != null) {
interpolation = update.getInterpolation();
}
if (update.getDataReduction() != null) {
reduction = update.getDataReduction();
}
if (update.getFocusPixelX()!= null) {
focusPixelX = update.getFocusPixelX();
}
if (update.getHighlightFocusValue()!= null) {
highlightFocusValue = update.getHighlightFocusValue();
}
}
/**
* Draws the graph on the given graphics context.
*
* @param g the graphics on which to display the data
* @param data the data to display
*/
public void draw(Graphics2D g, Point2DDataset data) {
this.g = g;
calculateRanges(data.getXStatistics().getRange(), data.getXDisplayRange(), data.getYStatistics().getRange(), data.getYDisplayRange());
calculateLabels();
calculateGraphArea();
drawBackground();
drawGraphArea();
SortedListView xValues = org.diirt.util.array.ListNumbers.sortedView(data.getXValues());
ListNumber yValues = org.diirt.util.array.ListNumbers.sortedView(data.getYValues(), xValues.getIndexes());
setClip(g);
g.setColor(Color.BLACK);
currentIndex = 0;
currentScaledDiff = getImageWidth();
drawValueExplicitLine(xValues, yValues, interpolation, reduction);
if (focusPixelX != null) {
focusValueIndex = xValues.getIndexes().getInt(currentIndex);
if (highlightFocusValue) {
g.setColor(new Color(0, 0, 0, 128));
int x = (int) scaledX(xValues.getDouble(currentIndex));
g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
g.drawLine(x, yAreaCoordStart, x, yAreaCoordEnd - 1);
}
} else {
focusValueIndex = -1;
}
}
public void draw(GraphBuffer buffer, Point2DDataset data) {
calculateRanges(data.getXStatistics().getRange(), data.getXDisplayRange(), data.getYStatistics().getRange(), data.getYDisplayRange());
calculateGraphArea();
// TODO: make sure this is right
GraphAreaData area = new GraphAreaData();
area.setGraphBuffer(buffer);
buffer.drawBackground(backgroundColor);
int areaRightPixel = getImageWidth() - 1 - rightMargin;
area.setGraphArea(leftMargin, getImageHeight() - 1 - bottomMargin, areaRightPixel, topMargin);
area.setGraphPadding(leftAreaMargin, bottomAreaMargin, rightAreaMargin, topAreaMargin);
area.setLabelMargin(xLabelMargin, yLabelMargin);
area.setRanges(getXPlotRange(), xValueScale, getYPlotRange(), yValueScale);
area.prepareLabels(labelFont, labelColor);
area.prepareGraphArea(false, referenceLineColor);
area.drawGraphArea();
ProcessValue pv = new ProcessValue() {
@Override
public void processScaledValue(int index, double valueX, double valueY, double scaledX, double scaledY) {
if (focusPixelX != null) {
double scaledDiff = Math.abs(scaledX - focusPixelX);
if (scaledDiff < currentScaledDiff) {
currentIndex = index;
currentScaledDiff = scaledDiff;
}
}
}
};
buffer.drawValueExplicitLine(data, interpolation, reduction, pv);
}
/**
* Draws a graph with multiple lines, each pertaining to a different set of data.
*
* @param g Graphics2D object used to perform drawing functions within draw.
* @param data can not be null
*/
public void draw(Graphics2D g, List<Point2DDataset> data) {
this.g = g;
//Calculate range, range will end up being from the lowest point to highest in all of the given data.
for(Point2DDataset dataPiece: data){
super.calculateRanges(dataPiece.getXStatistics().getRange(), dataPiece.getXDisplayRange(), dataPiece.getYStatistics().getRange(), dataPiece.getYDisplayRange());
}
calculateLabels();
calculateGraphArea();
drawBackground();
drawGraphArea();
Range datasetRangeCheck = Ranges.range(0,data.size());
//Set color scheme
if(valueColorSchemeInstance == null || datasetRange == null || datasetRange != datasetRangeCheck){
datasetRange = datasetRangeCheck;
valueColorSchemeInstance = valueColorScheme.createInstance(datasetRange);
}
//Draw a line for each set of data in the data array.
for(int datasetNumber = 0; datasetNumber < data.size(); datasetNumber++){
SortedListView xValues = org.diirt.util.array.ListNumbers.sortedView(data.get(datasetNumber).getXValues());
ListNumber yValues = org.diirt.util.array.ListNumbers.sortedView(data.get(datasetNumber).getYValues(), xValues.getIndexes());
setClip(g);
g.setColor(new Color(valueColorSchemeInstance.colorFor((double)datasetNumber)));
drawValueExplicitLine(xValues, yValues, interpolation, reduction);
}
}
@Override
protected void processScaledValue(int index, double valueX, double valueY, double scaledX, double scaledY) {
if (focusPixelX != null) {
double scaledDiff = Math.abs(scaledX - focusPixelX);
if (scaledDiff < currentScaledDiff) {
currentIndex = index;
currentScaledDiff = scaledDiff;
}
}
}
private int currentIndex;
private double currentScaledDiff;
}