blob: c96a4d45febaec0b1ad1aaf30eb9ba34991870e7 [file] [log] [blame]
package com.github.mikephil.charting.renderer;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.utils.MPPointD;
import com.github.mikephil.charting.utils.Transformer;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ViewPortHandler;
/**
* Baseclass of all axis renderers.
*
* @author Philipp Jahoda
*/
public abstract class AxisRenderer extends Renderer {
/** base axis this axis renderer works with */
protected AxisBase mAxis;
/** transformer to transform values to screen pixels and return */
protected Transformer mTrans;
/**
* paint object for the grid lines
*/
protected Paint mGridPaint;
/**
* paint for the x-label values
*/
protected Paint mAxisLabelPaint;
/**
* paint for the line surrounding the chart
*/
protected Paint mAxisLinePaint;
/**
* paint used for the limit lines
*/
protected Paint mLimitLinePaint;
public AxisRenderer(ViewPortHandler viewPortHandler, Transformer trans, AxisBase axis) {
super(viewPortHandler);
this.mTrans = trans;
this.mAxis = axis;
if(mViewPortHandler != null) {
mAxisLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mGridPaint = new Paint();
mGridPaint.setColor(Color.GRAY);
mGridPaint.setStrokeWidth(1f);
mGridPaint.setStyle(Style.STROKE);
mGridPaint.setAlpha(90);
mAxisLinePaint = new Paint();
mAxisLinePaint.setColor(Color.BLACK);
mAxisLinePaint.setStrokeWidth(1f);
mAxisLinePaint.setStyle(Style.STROKE);
mLimitLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mLimitLinePaint.setStyle(Paint.Style.STROKE);
}
}
/**
* Returns the Paint object used for drawing the axis (labels).
*
* @return
*/
public Paint getPaintAxisLabels() {
return mAxisLabelPaint;
}
/**
* Returns the Paint object that is used for drawing the grid-lines of the
* axis.
*
* @return
*/
public Paint getPaintGrid() {
return mGridPaint;
}
/**
* Returns the Paint object that is used for drawing the axis-line that goes
* alongside the axis.
*
* @return
*/
public Paint getPaintAxisLine() {
return mAxisLinePaint;
}
/**
* Returns the Transformer object used for transforming the axis values.
*
* @return
*/
public Transformer getTransformer() {
return mTrans;
}
/**
* Computes the axis values.
*
* @param min - the minimum value in the data object for this axis
* @param max - the maximum value in the data object for this axis
*/
public void computeAxis(float min, float max, boolean inverted) {
// calculate the starting and entry point of the y-labels (depending on
// zoom / contentrect bounds)
if (mViewPortHandler != null && mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) {
MPPointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop());
MPPointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom());
if (!inverted) {
min = (float) p2.y;
max = (float) p1.y;
} else {
min = (float) p1.y;
max = (float) p2.y;
}
MPPointD.recycleInstance(p1);
MPPointD.recycleInstance(p2);
}
computeAxisValues(min, max);
}
/**
* Sets up the axis values. Computes the desired number of labels between the two given extremes.
*
* @return
*/
protected void computeAxisValues(float min, float max) {
float yMin = min;
float yMax = max;
int labelCount = mAxis.getLabelCount();
double range = Math.abs(yMax - yMin);
if (labelCount == 0 || range <= 0) {
mAxis.mEntries = new float[]{};
mAxis.mEntryCount = 0;
return;
}
// Find out how much spacing (in y value space) between axis values
double rawInterval = range / labelCount;
if (Double.isInfinite(rawInterval))
{
rawInterval = range > 0.0 && !Double.isInfinite(range) ? range : 1.0;
}
double interval = Utils.roundToNextSignificant(rawInterval);
// If granularity is enabled, then do not allow the interval to go below specified granularity.
// This is used to avoid repeated values when rounding values for display.
if (mAxis.isGranularityEnabled())
interval = interval < mAxis.getGranularity() ? mAxis.getGranularity() : interval;
// Normalize interval
double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10(interval)));
int intervalSigDigit = (int) (interval / intervalMagnitude);
if (intervalSigDigit > 5) {
// Use one order of magnitude higher, to avoid intervals like 0.9 or
// 90
interval = Math.floor(10 * intervalMagnitude);
}
boolean centeringEnabled = mAxis.isCenterAxisLabelsEnabled();
int n = centeringEnabled ? 1 : 0;
// force label count
if (mAxis.isForceLabelsEnabled()) {
float step = (float) range / (float) (labelCount - 1);
mAxis.mEntryCount = labelCount;
if (mAxis.mEntries.length < labelCount) {
// Ensure stops contains at least numStops elements.
mAxis.mEntries = new float[labelCount];
}
float v = min;
for (int i = 0; i < labelCount; i++) {
mAxis.mEntries[i] = v;
v += step;
}
n = labelCount;
// no forced count
} else {
double first = interval == 0.0 ? 0.0 : Math.ceil(yMin / interval) * interval;
if(centeringEnabled) {
first -= interval;
}
double last = interval == 0.0 ? 0.0 : Utils.nextUp(Math.floor(yMax / interval) * interval);
double f;
int i;
if (interval != 0.0) {
for (f = first; f <= last; f += interval) {
++n;
}
}
mAxis.mEntryCount = n;
if (mAxis.mEntries.length < n) {
// Ensure stops contains at least numStops elements.
mAxis.mEntries = new float[n];
}
for (f = first, i = 0; i < n; f += interval, ++i) {
if (f == 0.0) // Fix for negative zero case (Where value == -0.0, and 0.0 == -0.0)
f = 0.0;
mAxis.mEntries[i] = (float) f;
}
}
// set decimals
if (interval < 1) {
mAxis.mDecimals = (int) Math.ceil(-Math.log10(interval));
} else {
mAxis.mDecimals = 0;
}
if (centeringEnabled) {
if (mAxis.mCenteredEntries.length < n) {
mAxis.mCenteredEntries = new float[n];
}
float offset = (mAxis.mEntries[1] - mAxis.mEntries[0]) / 2f;
for (int i = 0; i < n; i++) {
mAxis.mCenteredEntries[i] = mAxis.mEntries[i] + offset;
}
}
}
/**
* Draws the axis labels to the screen.
*
* @param c
*/
public abstract void renderAxisLabels(Canvas c);
/**
* Draws the grid lines belonging to the axis.
*
* @param c
*/
public abstract void renderGridLines(Canvas c);
/**
* Draws the line that goes alongside the axis.
*
* @param c
*/
public abstract void renderAxisLine(Canvas c);
/**
* Draws the LimitLines associated with this axis to the screen.
*
* @param c
*/
public abstract void renderLimitLines(Canvas c);
}