package com.github.mikephil.charting.renderer; import android.graphics.Canvas; import android.graphics.Paint.Style; import android.graphics.Path; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.buffer.ScatterBuffer; import com.github.mikephil.charting.charts.ScatterChart.ScatterShape; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; import com.github.mikephil.charting.interfaces.ScatterDataProvider; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.List; public class ScatterChartRenderer extends DataRenderer { protected ScatterDataProvider mChart; protected ScatterBuffer[] mScatterBuffers; public ScatterChartRenderer(ScatterDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = chart; mRenderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); } @Override public void initBuffers() { ScatterData scatterData = mChart.getScatterData(); mScatterBuffers = new ScatterBuffer[scatterData.getDataSetCount()]; for (int i = 0; i < mScatterBuffers.length; i++) { ScatterDataSet set = scatterData.getDataSetByIndex(i); mScatterBuffers[i] = new ScatterBuffer(set.getEntryCount() * 2); } } @Override public void drawData(Canvas c) { ScatterData scatterData = mChart.getScatterData(); for (ScatterDataSet set : scatterData.getDataSets()) { if (set.isVisible()) drawDataSet(c, set); } } protected void drawDataSet(Canvas c, ScatterDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); calcXBounds(trans); float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); List<Entry> entries = dataSet.getYVals(); float shapeHalf = dataSet.getScatterShapeSize() / 2f; ScatterShape shape = dataSet.getScatterShape(); ScatterBuffer buffer = mScatterBuffers[mChart.getScatterData().getIndexOfDataSet( dataSet)]; buffer.setPhases(phaseX, phaseY); buffer.feed(entries); trans.pointValuesToPixel(buffer.buffer); switch (shape) { case SQUARE: mRenderPaint.setStyle(Style.FILL); for (int i = 0; i < buffer.size(); i += 2) { if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) break; if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) continue; mRenderPaint.setColor(dataSet.getColor(i / 2)); c.drawRect(buffer.buffer[i] - shapeHalf, buffer.buffer[i + 1] - shapeHalf, buffer.buffer[i] + shapeHalf, buffer.buffer[i + 1] + shapeHalf, mRenderPaint); } break; case CIRCLE: mRenderPaint.setStyle(Style.FILL); for (int i = 0; i < buffer.size(); i += 2) { if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) break; if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) continue; mRenderPaint.setColor(dataSet.getColor(i / 2)); c.drawCircle(buffer.buffer[i], buffer.buffer[i + 1], shapeHalf, mRenderPaint); } break; case TRIANGLE: mRenderPaint.setStyle(Style.FILL); // create a triangle path Path tri = new Path(); for (int i = 0; i < buffer.size(); i += 2) { if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) break; if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) continue; mRenderPaint.setColor(dataSet.getColor(i / 2)); tri.moveTo(buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf); tri.lineTo(buffer.buffer[i] + shapeHalf, buffer.buffer[i + 1] + shapeHalf); tri.lineTo(buffer.buffer[i] - shapeHalf, buffer.buffer[i + 1] + shapeHalf); tri.close(); c.drawPath(tri, mRenderPaint); tri.reset(); } break; case CROSS: mRenderPaint.setStyle(Style.STROKE); for (int i = 0; i < buffer.size(); i += 2) { if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) break; if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) continue; mRenderPaint.setColor(dataSet.getColor(i / 2)); c.drawLine(buffer.buffer[i] - shapeHalf, buffer.buffer[i + 1], buffer.buffer[i] + shapeHalf, buffer.buffer[i + 1], mRenderPaint); c.drawLine(buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf, buffer.buffer[i], buffer.buffer[i + 1] + shapeHalf, mRenderPaint); } break; default: break; } // else { // draw the custom-shape // // Path customShape = dataSet.getCustomScatterShape(); // // for (int j = 0; j < entries.size() * mAnimator.getPhaseX(); j += 2) { // // Entry e = entries.get(j / 2); // // if (!fitsBounds(e.getXIndex(), mMinX, mMaxX)) // continue; // // if (customShape == null) // return; // // mRenderPaint.setColor(dataSet.getColor(j)); // // Path newPath = new Path(customShape); // newPath.offset(e.getXIndex(), e.getVal()); // // // transform the provided custom path // trans.pathValueToPixel(newPath); // c.drawPath(newPath, mRenderPaint); // } // } } @Override public void drawValues(Canvas c) { // if values are drawn if (mChart.getScatterData().getYValCount() < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleX()) { List<ScatterDataSet> dataSets = mChart.getScatterData().getDataSets(); for (int i = 0; i < mChart.getScatterData().getDataSetCount(); i++) { ScatterDataSet dataSet = dataSets.get(i); if (!dataSet.isDrawValuesEnabled()) continue; // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); List<Entry> entries = dataSet.getYVals(); float[] positions = mChart.getTransformer(dataSet.getAxisDependency()) .generateTransformedValuesScatter(entries, mAnimator.getPhaseY()); float shapeSize = dataSet.getScatterShapeSize(); for (int j = 0; j < positions.length * mAnimator.getPhaseX(); j += 2) { if (!mViewPortHandler.isInBoundsRight(positions[j])) break; // make sure the lines don't do shitty things outside bounds if (j != 0 && (!mViewPortHandler.isInBoundsLeft(positions[j]) || !mViewPortHandler.isInBoundsY(positions[j + 1]))) continue; float val = entries.get(j / 2).getVal(); c.drawText(dataSet.getValueFormatter().getFormattedValue(val), positions[j], positions[j + 1] - shapeSize, mValuePaint); } } } } @Override public void drawExtras(Canvas c) { } @Override public void drawHighlighted(Canvas c, Highlight[] indices) { for (int i = 0; i < indices.length; i++) { ScatterDataSet set = mChart.getScatterData().getDataSetByIndex(indices[i] .getDataSetIndex()); if (set == null) continue; mHighlightPaint.setColor(set.getHighLightColor()); int xIndex = indices[i].getXIndex(); // get the // x-position if (xIndex > mChart.getXChartMax() * mAnimator.getPhaseX()) continue; float y = set.getYValForXIndex(xIndex) * mAnimator.getPhaseY(); // get // the // y-position float[] pts = new float[] { xIndex, mChart.getYChartMax(), xIndex, mChart.getYChartMin(), 0, y, mChart.getXChartMax(), y }; mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); // draw the highlight lines c.drawLines(pts, mHighlightPaint); } } }