Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 23 additions & 15 deletions androidplot-core/src/main/java/com/androidplot/pie/PieRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@
*/
public class PieRenderer extends SeriesRenderer<PieChart, Segment, SegmentFormatter> {

private static final float FULL_PIE_DEGS = 360f;
private static final float HALF_PIE_DEGS = 180f;

// starting angle to use when drawing the first radial line of the first segment.
private float startDegs = 0;

// number of degrees to extend from startDegs; can be used to "shape" the pie chart.
private float extentDegs = 360;
private float extentDegs = FULL_PIE_DEGS;

// TODO: express donut in units other than px.
private float donutSize = 0.5f;
Expand Down Expand Up @@ -240,7 +243,7 @@ protected PointF calculateLineEnd(float x, float y, float rad, float deg) {

protected PointF calculateLineEnd(PointF origin, float rad, float deg) {

double radians = deg * Math.PI / 180F;
double radians = deg * Math.PI / HALF_PIE_DEGS;
double x = rad * Math.cos(radians);
double y = rad * Math.sin(radians);

Expand Down Expand Up @@ -292,11 +295,10 @@ public Segment getContainingSegment(PointF point) {
float dx = point.x - origin.x;
float dy = point.y - origin.y;
double theta = Math.atan2(dy, dx);
double angle = (theta * (180f / Math.PI));
double angle = (theta * (HALF_PIE_DEGS / Math.PI));
if (angle < 0) {
// convert angle to 0-360 range with 0 being in the
// traditional "east" orientation:
angle += 360f;
// bring into 0-360 range
angle += FULL_PIE_DEGS;
}

// find the segment whose starting and ending angle (degs) contains
Expand All @@ -310,10 +312,16 @@ public Segment getContainingSegment(PointF point) {
float lastOffset = offset;
float sweep = (float) (scale * (values[i]) * extentDegs);
offset += sweep;
offset = offset % 360;
offset = offset % FULL_PIE_DEGS;

final double dist = signedDistance(offset, angle);
if(dist > 0 && dist <= signedDistance(offset, lastOffset)) {
double endDist = signedDistance(offset, lastOffset);
if(endDist < 0) {
// segment accounts for more than 50% of the pie and wrapped around
// need to correct:
endDist = FULL_PIE_DEGS + endDist;
}
if(dist > 0 && dist <= endDist) {
return sfPair.getSeries();
}
i++;
Expand All @@ -328,10 +336,10 @@ public Segment getContainingSegment(PointF point) {
* @return
*/
protected static float degsToScreenDegs(float degs) {
degs = degs % 360;
degs = degs % FULL_PIE_DEGS;

if (degs > 0) {
return 360 - degs;
return FULL_PIE_DEGS - degs;
} else {
return degs;
}
Expand All @@ -344,12 +352,12 @@ protected static float degsToScreenDegs(float degs) {
* @return
*/
protected static double signedDistance(double angle1, double angle2) {
double d = Math.abs(angle1 - angle2) % 360;
double r = d > 180 ? 360 - d : d;
double d = Math.abs(angle1 - angle2) % FULL_PIE_DEGS;
double r = d > HALF_PIE_DEGS ? FULL_PIE_DEGS - d : d;

//calculate sign
int sign = (angle1 - angle2 >= 0 && angle1 - angle2 <= 180)
|| (angle1 - angle2 <= -180 && angle1 - angle2 >= -360) ? 1 : -1;
int sign = (angle1 - angle2 >= 0 && angle1 - angle2 <= HALF_PIE_DEGS)
|| (angle1 - angle2 <= -HALF_PIE_DEGS && angle1 - angle2 >= -FULL_PIE_DEGS) ? 1 : -1;
r *= sign;
return r;
}
Expand All @@ -359,7 +367,7 @@ protected static double signedDistance(double angle1, double angle2) {
* @param degs
*/
protected static void validateInputDegs(float degs) {
if(degs < 0 || degs > 360) {
if(degs < 0 || degs > FULL_PIE_DEGS) {
throw new IllegalArgumentException("Degrees values must be between 0.0 and 360.");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public void testOnRender() throws Exception {
}

@Test
public void testGetContainingSegment() throws Exception {
public void getContainingSegment_returnsCorrectSegment() throws Exception {
Segment segment1 = spy(new Segment("s1", 25));
Segment segment2 = spy(new Segment("s2", 25));
Segment segment3 = spy(new Segment("s3", 25));
Expand Down Expand Up @@ -150,6 +150,45 @@ public void testGetContainingSegment() throws Exception {
assertEquals(segment1, renderer.getContainingSegment(new PointF(100, 0)));
}

@Test
public void getContainingSegment_handlesSegmentsLargerThanHalfPie() throws Exception {
Segment segment1 = spy(new Segment("s1", 25));
Segment segment2 = spy(new Segment("s2", 24));
Segment segment3 = spy(new Segment("s3", 51));
SegmentFormatter formatter = spy(
new SegmentFormatter(Color.GREEN, Color.GREEN, Color.GREEN, Color.GREEN));
PieRenderer renderer = formatter.getRendererInstance(pieChart);

pieChart.addSegment(segment1, formatter);
pieChart.addSegment(segment2, formatter);
pieChart.addSegment(segment3, formatter);

// southeast
assertEquals(segment1, renderer.getContainingSegment(new PointF(100, 100)));

// southwest
assertEquals(segment2, renderer.getContainingSegment(new PointF(0, 100)));

// northwest
assertEquals(segment3, renderer.getContainingSegment(new PointF(0, 0)));

// northeast
assertEquals(segment3, renderer.getContainingSegment(new PointF(100, 0)));

renderer.setStartDegs(90);
// southeast
assertEquals(segment2, renderer.getContainingSegment(new PointF(100, 100)));

// southwest
assertEquals(segment3, renderer.getContainingSegment(new PointF(0, 100)));

// northwest
assertEquals(segment3, renderer.getContainingSegment(new PointF(0, 0)));

// northeast
assertEquals(segment1, renderer.getContainingSegment(new PointF(100, 0)));
}

@Test
public void testDegsToScreenDegs() throws Exception {
assertEquals(0f, PieRenderer.degsToScreenDegs(0));
Expand Down