package com.github.mikephil.charting.renderer;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.drawable.Drawable;
import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.charts.RadarChart;
import com.github.mikephil.charting.data.RadarData;
import com.github.mikephil.charting.data.RadarEntry;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet;
import com.github.mikephil.charting.utils.ColorTemplate;
import com.github.mikephil.charting.utils.MPPointF;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ViewPortHandler;
public class RadarChartRenderer extends LineRadarRenderer {
protected RadarChart mChart;
/**
* paint for drawing the web
*/
protected Paint mWebPaint;
protected Paint mHighlightCirclePaint;
public RadarChartRenderer(RadarChart chart, ChartAnimator animator,
ViewPortHandler viewPortHandler) {
super(animator, viewPortHandler);
mChart = chart;
mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mHighlightPaint.setStyle(Paint.Style.STROKE);
mHighlightPaint.setStrokeWidth(2f);
mHighlightPaint.setColor(Color.rgb(255, 187, 115));
mWebPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mWebPaint.setStyle(Paint.Style.STROKE);
mHighlightCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
public Paint getWebPaint() {
return mWebPaint;
}
@Override
public void initBuffers() {
// TODO Auto-generated method stub
}
@Override
public void drawData(Canvas c) {
RadarData radarData = mChart.getData();
int mostEntries = radarData.getMaxEntryCountSet().getEntryCount();
for (IRadarDataSet set : radarData.getDataSets()) {
if (set.isVisible()) {
drawDataSet(c, set, mostEntries);
}
}
}
protected Path mDrawDataSetSurfacePathBuffer = new Path();
/**
* Draws the RadarDataSet
*
* @param c
* @param dataSet
* @param mostEntries the entry count of the dataset with the most entries
*/
protected void drawDataSet(Canvas c, IRadarDataSet dataSet, int mostEntries) {
float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();
float sliceangle = mChart.getSliceAngle();
// calculate the factor that is needed for transforming the value to
// pixels
float factor = mChart.getFactor();
MPPointF center = mChart.getCenterOffsets();
MPPointF pOut = MPPointF.getInstance(0,0);
Path surface = mDrawDataSetSurfacePathBuffer;
surface.reset();
boolean hasMovedToPoint = false;
for (int j = 0; j < dataSet.getEntryCount(); j++) {
mRenderPaint.setColor(dataSet.getColor(j));
RadarEntry e = dataSet.getEntryForIndex(j);
Utils.getPosition(
center,
(e.getY() - mChart.getYChartMin()) * factor * phaseY,
sliceangle * j * phaseX + mChart.getRotationAngle(), pOut);
if (Float.isNaN(pOut.x))
continue;
if (!hasMovedToPoint) {
surface.moveTo(pOut.x, pOut.y);
hasMovedToPoint = true;
} else
surface.lineTo(pOut.x, pOut.y);
}
if (dataSet.getEntryCount() > mostEntries) {
// if this is not the largest set, draw a line to the center before closing
surface.lineTo(center.x, center.y);
}
surface.close();
if (dataSet.isDrawFilledEnabled()) {
final Drawable drawable = dataSet.getFillDrawable();
if (drawable != null) {
drawFilledPath(c, surface, drawable);
} else {
drawFilledPath(c, surface, dataSet.getFillColor(), dataSet.getFillAlpha());
}
}
mRenderPaint.setStrokeWidth(dataSet.getLineWidth());
mRenderPaint.setStyle(Paint.Style.STROKE);
// draw the line (only if filled is disabled or alpha is below 255)
if (!dataSet.isDrawFilledEnabled() || dataSet.getFillAlpha() < 255)
c.drawPath(surface, mRenderPaint);
MPPointF.recycleInstance(center);
MPPointF.recycleInstance(pOut);
}
@Override
public void drawValues(Canvas c) {
float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();
float sliceangle = mChart.getSliceAngle();
// calculate the factor that is needed for transforming the value to
// pixels
float factor = mChart.getFactor();
MPPointF center = mChart.getCenterOffsets();
MPPointF pOut = MPPointF.getInstance(0,0);
MPPointF pIcon = MPPointF.getInstance(0,0);
float yoffset = Utils.convertDpToPixel(5f);
for (int i = 0; i < mChart.getData().getDataSetCount(); i++) {
IRadarDataSet dataSet = mChart.getData().getDataSetByIndex(i);
if (!shouldDrawValues(dataSet))
continue;
// apply the text-styling defined by the DataSet
applyValueTextStyle(dataSet);
MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset());
iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x);
iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y);
for (int j = 0; j < dataSet.getEntryCount(); j++) {
RadarEntry entry = dataSet.getEntryForIndex(j);
Utils.getPosition(
center,
(entry.getY() - mChart.getYChartMin()) * factor * phaseY,
sliceangle * j * phaseX + mChart.getRotationAngle(),
pOut);
if (dataSet.isDrawValuesEnabled()) {
drawValue(c,
dataSet.getValueFormatter(),
entry.getY(),
entry,
i,
pOut.x,
pOut.y - yoffset,
dataSet.getValueTextColor
(j));
}
if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
Drawable icon = entry.getIcon();
Utils.getPosition(
center,
(entry.getY()) * factor * phaseY + iconsOffset.y,
sliceangle * j * phaseX + mChart.getRotationAngle(),
pIcon);
//noinspection SuspiciousNameCombination
pIcon.y += iconsOffset.x;
Utils.drawImage(
c,
icon,
(int)pIcon.x,
(int)pIcon.y,
icon.getIntrinsicWidth(),
icon.getIntrinsicHeight());
}
}
MPPointF.recycleInstance(iconsOffset);
}
MPPointF.recycleInstance(center);
MPPointF.recycleInstance(pOut);
MPPointF.recycleInstance(pIcon);
}
@Override
public void drawExtras(Canvas c) {
drawWeb(c);
}
protected void drawWeb(Canvas c) {
float sliceangle = mChart.getSliceAngle();
// calculate the factor that is needed for transforming the value to
// pixels
float factor = mChart.getFactor();
float rotationangle = mChart.getRotationAngle();
MPPointF center = mChart.getCenterOffsets();
// draw the web lines that come from the center
mWebPaint.setStrokeWidth(mChart.getWebLineWidth());
mWebPaint.setColor(mChart.getWebColor());
mWebPaint.setAlpha(mChart.getWebAlpha());
final int xIncrements = 1 + mChart.getSkipWebLineCount();
int maxEntryCount = mChart.getData().getMaxEntryCountSet().getEntryCount();
MPPointF p = MPPointF.getInstance(0,0);
for (int i = 0; i < maxEntryCount; i += xIncrements) {
Utils.getPosition(
center,
mChart.getYRange() * factor,
sliceangle * i + rotationangle,
p);
c.drawLine(center.x, center.y, p.x, p.y, mWebPaint);
}
MPPointF.recycleInstance(p);
// draw the inner-web
mWebPaint.setStrokeWidth(mChart.getWebLineWidthInner());
mWebPaint.setColor(mChart.getWebColorInner());
mWebPaint.setAlpha(mChart.getWebAlpha());
int labelCount = mChart.getYAxis().mEntryCount;
MPPointF p1out = MPPointF.getInstance(0,0);
MPPointF p2out = MPPointF.getInstance(0,0);
for (int j = 0; j < labelCount; j++) {
for (int i = 0; i < mChart.getData().getEntryCount(); i++) {
float r = (mChart.getYAxis().mEntries[j] - mChart.getYChartMin()) * factor;
Utils.getPosition(center, r, sliceangle * i + rotationangle, p1out);
Utils.getPosition(center, r, sliceangle * (i + 1) + rotationangle, p2out);
c.drawLine(p1out.x, p1out.y, p2out.x, p2out.y, mWebPaint);
}
}
MPPointF.recycleInstance(p1out);
MPPointF.recycleInstance(p2out);
}
@Override
public void drawHighlighted(Canvas c, Highlight[] indices) {
float sliceangle = mChart.getSliceAngle();
// calculate the factor that is needed for transforming the value to
// pixels
float factor = mChart.getFactor();
MPPointF center = mChart.getCenterOffsets();
MPPointF pOut = MPPointF.getInstance(0,0);
RadarData radarData = mChart.getData();
for (Highlight high : indices) {
IRadarDataSet set = radarData.getDataSetByIndex(high.getDataSetIndex());
if (set == null || !set.isHighlightEnabled())
continue;
RadarEntry e = set.getEntryForIndex((int) high.getX());
if (!isInBoundsX(e, set))
continue;
float y = (e.getY() - mChart.getYChartMin());
Utils.getPosition(center,
y * factor * mAnimator.getPhaseY(),
sliceangle * high.getX() * mAnimator.getPhaseX() + mChart.getRotationAngle(),
pOut);
high.setDraw(pOut.x, pOut.y);
// draw the lines
drawHighlightLines(c, pOut.x, pOut.y, set);
if (set.isDrawHighlightCircleEnabled()) {
if (!Float.isNaN(pOut.x) && !Float.isNaN(pOut.y)) {
int strokeColor = set.getHighlightCircleStrokeColor();
if (strokeColor == ColorTemplate.COLOR_NONE) {
strokeColor = set.getColor(0);
}
if (set.getHighlightCircleStrokeAlpha() < 255) {
strokeColor = ColorTemplate.colorWithAlpha(strokeColor, set.getHighlightCircleStrokeAlpha());
}
drawHighlightCircle(c,
pOut,
set.getHighlightCircleInnerRadius(),
set.getHighlightCircleOuterRadius(),
set.getHighlightCircleFillColor(),
strokeColor,
set.getHighlightCircleStrokeWidth());
}
}
}
MPPointF.recycleInstance(center);
MPPointF.recycleInstance(pOut);
}
protected Path mDrawHighlightCirclePathBuffer = new Path();
public void drawHighlightCircle(Canvas c,
MPPointF point,
float innerRadius,
float outerRadius,
int fillColor,
int strokeColor,
float strokeWidth) {
c.save();
outerRadius = Utils.convertDpToPixel(outerRadius);
innerRadius = Utils.convertDpToPixel(innerRadius);
if (fillColor != ColorTemplate.COLOR_NONE) {
Path p = mDrawHighlightCirclePathBuffer;
p.reset();
p.addCircle(point.x, point.y, outerRadius, Path.Direction.CW);
if (innerRadius > 0.f) {
p.addCircle(point.x, point.y, innerRadius, Path.Direction.CCW);
}
mHighlightCirclePaint.setColor(fillColor);
mHighlightCirclePaint.setStyle(Paint.Style.FILL);
c.drawPath(p, mHighlightCirclePaint);
}
if (strokeColor != ColorTemplate.COLOR_NONE) {
mHighlightCirclePaint.setColor(strokeColor);
mHighlightCirclePaint.setStyle(Paint.Style.STROKE);
mHighlightCirclePaint.setStrokeWidth(Utils.convertDpToPixel(strokeWidth));
c.drawCircle(point.x, point.y, outerRadius, mHighlightCirclePaint);
}
c.restore();
}
}