berserk
berserk

Reputation: 2728

drawArc not drawing properly when startAngle > endAngle in android

I am trying to draw an arc between two points in a circle using touch listener. Here is my code:

public class MainActivity extends Activity implements OnTouchListener {

ImageView whiteCircle, centreCircle, slideArcFrame;
int xStart = 0, yStart = 0, xEnd = 0, yEnd = 0, centerIx = 0, centerIy = 0;
Bitmap output;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    whiteCircle = (ImageView) findViewById(R.id.centerImageWhite);
    centreCircle = (ImageView) findViewById(R.id.centerImage2);
    slideArcFrame = (ImageView) findViewById(R.id.centerImage);
    slideArcFrame.setOnTouchListener(this);
    slideArcFrame.setDrawingCacheEnabled(true);
    slideArcFrame.measure(
            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
    slideArcFrame.layout(0, 0, slideArcFrame.getMeasuredWidth(),
            slideArcFrame.getMeasuredHeight());
    slideArcFrame.buildDrawingCache(true);
    output = Bitmap.createBitmap(slideArcFrame.getDrawingCache());
    centerIx = 100;
    centerIy = 100;
}

@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
    if (arg1.getAction() == MotionEvent.ACTION_DOWN) {
        xStart = (int) arg1.getX();
        yStart = (int) arg1.getY();
    }
    if (arg1.getAction() == MotionEvent.ACTION_MOVE) {
        xEnd = (int) arg1.getX();
        yEnd = (int) arg1.getY();
        drawArc();
    }
    if (arg1.getAction() == MotionEvent.ACTION_UP) {
        xEnd = (int) arg1.getX();
        yEnd = (int) arg1.getY();
    }
    return true;
}

private void drawArc() {
    Bitmap outp = Bitmap.createBitmap(output.getWidth(),
            output.getHeight(), Config.ARGB_8888);
    Canvas can = new Canvas(outp);
    final Paint paint = new Paint();
    RectF rect = new RectF(0, 0, output.getWidth(), output.getHeight());
    can.drawARGB(0, 0, 0, 0);
    paint.setAntiAlias(true);
    paint.setColor(getResources().getColor(R.color.white));
    double quadXS, quadYS, quadXE, quadYE;
    double quadrantS = 0, quadrantE = 0;
    quadXS = xStart - centerIx;
    quadYS = yStart - centerIy;
    quadXE = xEnd - centerIx;
    quadYE = yEnd - centerIy;
    if (quadXS >= 0 && quadYS >= 0)
        quadrantS = 1;
    if (quadXS < 0 && quadYS >= 0)
        quadrantS = 2;
    if (quadXS < 0 && quadYS < 0)
        quadrantS = 3;
    if (quadXS >= 0 && quadYS < 0)
        quadrantS = 4;
    if (quadXE >= 0 && quadYE >= 0)
        quadrantE = 1;
    if (quadXE < 0 && quadYE >= 0)
        quadrantE = 2;
    if (quadXE < 0 && quadYE < 0)
        quadrantE = 3;
    if (quadXE >= 0 && quadYE < 0)
        quadrantE = 4;
    double startAngle = 0, endAngle = 0;
    if (quadrantS == 1) {
        startAngle = Math.toDegrees(Math.atan((double) (quadYS) / quadXS));
    }
    if (quadrantS == 2) {
        startAngle = 180 - Math.toDegrees(Math.atan((double) (quadYS)
                / -quadXS));
    }
    if (quadrantS == 3) {
        startAngle = 180 + Math.toDegrees(Math.atan((double) (-quadYS)
                / -quadXS));
    }
    if (quadrantS == 4) {
        startAngle = 360 - Math.toDegrees(Math.atan((double) (-quadYS)
                / quadXS));
    }
    if (quadrantE == 1) {
        endAngle = Math.toDegrees(Math.atan((double) (quadYE) / quadXE));
    }
    if (quadrantE == 2) {
        endAngle = 180 - Math.toDegrees(Math.atan((double) (quadYE)
                / -quadXE));
    }
    if (quadrantE == 3) {
        endAngle = 180 + Math.toDegrees(Math.atan((double) (-quadYE)
                / -quadXE));
    }
    if (quadrantE == 4) {
        endAngle = 360 - Math.toDegrees(Math.atan((double) (-quadYE)
                / quadXE));
    }
    can.drawArc(rect, (float) startAngle, (float) endAngle
            - (float) startAngle, true, paint);
    slideArcFrame.setImageBitmap(outp);
}
}

When the start angle is greater than end angle, the arc is drawn from end angle to start angle. Can anyone explain please?

Upvotes: 4

Views: 3148

Answers (1)

Geobits
Geobits

Reputation: 22342

For sweepAngle, you're using endAngle - startAngle. If startAngle is higher, it'll end up a negative number.

The docs say this:

If the sweep angle is negative, the sweep angle is treated as sweep angle modulo 360.

......

The arc is drawn clockwise.

The thing is, Java can return negative numbers with modulus, so -30 mod 360 = -30. For negative degrees, it will draw counter-clockwise. If you want it to always draw clockwise, you need to feed it a positive number:

float sweepAngle = endAngle - startAngle;
while(sweepAngle < 0)
    sweepAngle += 360;

Upvotes: 3

Related Questions