Skip to content

Commit

Permalink
Add spaceBetweenLabelsMin property to XAxis; fix xAsis labels overlap…
Browse files Browse the repository at this point in the history
…ping
  • Loading branch information
yaugenka committed Jan 15, 2022
1 parent 0550d3f commit de8bf0b
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 189 deletions.
Expand Up @@ -47,6 +47,11 @@ public class XAxis extends AxisBase {
*/
private boolean mAvoidFirstLastClipping = false;

/**
* minimum spacing between labels in pixels
*/
protected float mSpaceBetweenLabelsMin = 0;

/**
* the position of the x-labels relative to the chart
*/
Expand All @@ -65,6 +70,19 @@ public XAxis() {
mYOffset = Utils.convertDpToPixel(4.f); // -3
}

/**
* Returns minimum spacing between labels in pixels
*/
public float getSpaceBetweenLabelsMin() { return mSpaceBetweenLabelsMin; }

/**
* Sets minimum spacing between labels in pixels
*/
public void setSpaceBetweenLabelsMin(float space)
{
mSpaceBetweenLabelsMin = space;
}

/**
* returns the position of the x-labels
*/
Expand Down
Expand Up @@ -7,7 +7,6 @@
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;
Expand Down Expand Up @@ -115,73 +114,26 @@ public Transformer getTransformer() {
* @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) {
public abstract 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
* Compute axis interval and desired number of labels between the two given extremes
* @param min
* @param max
*/
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 || Double.isInfinite(range)) {
mAxis.mEntries = new float[]{};
mAxis.mCenteredEntries = new float[]{};
mAxis.mEntryCount = 0;
return;
}

// Find out how much spacing (in y value space) between axis values
double rawInterval = range / labelCount;
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
// if it's 0.0 after floor(), we use the old value
interval = Math.floor(10.0 * intervalMagnitude) == 0.0
? interval
: Math.floor(10.0 * intervalMagnitude);

}
protected abstract void computeAxisInterval(float min, float max);

/**
* Setup axis entries and decimals based on the previously computed interval and labels count
* @param min
* @param max
* @param labelCount
* @param range
* @param interval
*/
protected void computeAxisValues(float min, float max, int labelCount, double range, double interval) {

int n = mAxis.isCenterAxisLabelsEnabled() ? 1 : 0;

// force label count
Expand All @@ -207,12 +159,12 @@ protected void computeAxisValues(float min, float max) {
// no forced count
} else {

double first = interval == 0.0 ? 0.0 : Math.ceil(yMin / interval) * interval;
double first = interval == 0.0 ? 0.0 : Math.ceil(min / interval) * interval;
if(mAxis.isCenterAxisLabelsEnabled()) {
first -= interval;
}

double last = interval == 0.0 ? 0.0 : Utils.nextUp(Math.floor(yMax / interval) * interval);
double last = interval == 0.0 ? 0.0 : Utils.nextUp(Math.floor(max / interval) * interval);

double f;
int i;
Expand Down Expand Up @@ -262,7 +214,7 @@ else if (last == first && n == 0) {
}
}
}

/**
* Draws the axis labels to the screen.
*
Expand Down
Expand Up @@ -45,7 +45,7 @@ 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.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutX()) {
if (mViewPortHandler != null && mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutX()) {

MPPointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop());
MPPointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), mViewPortHandler.contentTop());
Expand All @@ -64,14 +64,59 @@ public void computeAxis(float min, float max, boolean inverted) {
MPPointD.recycleInstance(p2);
}

computeAxisValues(min, max);
computeAxisInterval(min, max);
}

@Override
protected void computeAxisValues(float min, float max) {
super.computeAxisValues(min, max);
protected void computeAxisInterval(float min, float max) {

// Compute the longest label width first
computeSize();

int labelCount = mXAxis.getLabelCount();
double range = Math.abs(max - min);

if (labelCount == 0 || range <= 0 || Double.isInfinite(range)) {
mXAxis.mEntries = new float[]{};
mXAxis.mCenteredEntries = new float[]{};
mXAxis.mEntryCount = 0;
return;
}

// Find out how much spacing (in x value space) between axis values
double rawInterval = range / labelCount;
double interval = Utils.roundToNextSignificant(rawInterval);

// Do not allow the interval go below the label width with spacing.
double labelMaxWidth = (mXAxis.mLabelRotatedWidth + mXAxis.getSpaceBetweenLabelsMin()) * range / mViewPortHandler.contentWidth();
if (interval < labelMaxWidth)
interval = labelMaxWidth;

// 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 (mXAxis.isGranularityEnabled())
interval = interval < mXAxis.getGranularity() ? mXAxis.getGranularity() : interval;

// Perform rounding once again after interval was probably adjusted by label width and/or granularity checks.
rawInterval = interval;
interval = Utils.roundToNextSignificant(rawInterval);

// 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
// if it's 0.0 after floor(), we use the old value
interval = Math.floor(10.0 * intervalMagnitude) == 0.0
? interval
: Math.floor(10.0 * intervalMagnitude);

// If rounded down to current significant, round up to avoid label overlapping
} else if (interval < rawInterval) {
interval = (intervalSigDigit + 1) * intervalMagnitude;
}

computeAxisValues(min, max, labelCount, range, interval);
}

protected void computeSize() {
Expand All @@ -91,7 +136,6 @@ protected void computeSize() {
labelHeight,
mXAxis.getLabelRotationAngle());


mXAxis.mLabelWidth = Math.round(labelWidth);
mXAxis.mLabelHeight = Math.round(labelHeight);
mXAxis.mLabelRotatedWidth = Math.round(labelRotatedSize.width);
Expand Down
Expand Up @@ -55,7 +55,7 @@ public void computeAxis(float min, float max, boolean inverted) {
MPPointD.recycleInstance(p2);
}

computeAxisValues(min, max);
computeAxisInterval(min, max);
}

@Override
Expand Down
Expand Up @@ -41,6 +41,69 @@ public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer t
}
}

@Override
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);
}

computeAxisInterval(min, max);
}

@Override
protected void computeAxisInterval(float min, float max) {

int labelCount = mYAxis.getLabelCount();
double range = Math.abs(max - min);

if (labelCount == 0 || range <= 0 || Double.isInfinite(range)) {
mYAxis.mEntries = new float[]{};
mYAxis.mCenteredEntries = new float[]{};
mYAxis.mEntryCount = 0;
return;
}

// Find out how much spacing (in y value space) between axis values
double rawInterval = range / labelCount;
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 (mYAxis.isGranularityEnabled())
interval = interval < mYAxis.getGranularity() ? mYAxis.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
// if it's 0.0 after floor(), we use the old value
interval = Math.floor(10.0 * intervalMagnitude) == 0.0
? interval
: Math.floor(10.0 * intervalMagnitude);
}

computeAxisValues(min, max, labelCount, range, interval);
}

/**
* draws the y-axis labels to the screen
*/
Expand Down
Expand Up @@ -57,7 +57,7 @@ public void computeAxis(float yMin, float yMax, boolean inverted) {
MPPointD.recycleInstance(p2);
}

computeAxisValues(yMin, yMax);
computeAxisInterval(yMin, yMax);
}

/**
Expand Down

0 comments on commit de8bf0b

Please sign in to comment.