can someone please explain the last two params of arcTo?

This answer visually explains all arcTo parameters using four examples.

arcTo takes the following parameters:

public void arcTo(RectF oval, 
                  float startAngle, 
                  float sweepAngle, 
                  boolean forceMoveTo)

where RectF's constructor takes:

RectF(float left, float top, float right, float bottom)

ArchTo parameters explained visually

(Hopefully this visualization is less painful and less mystifying than reading the official arcTo documentation.)


odd that no one piped in with an answer, once I found it (it wasn't easy to find) it was really straight forward.

So, the way it works is this: Assuming you want to draw a rounded corner at 12 - 3 (using clock reference): you start your path and when you need the line to arc you define a rectangle whose upper left corner is the place where your line is currently terminated and whose lower right corner is the place that you want the arc to go to, so if you imagine a square whose X,Y is 12 (on the clock) and whose X+W,Y+H is 3 that's the square you need.

Now, imagine that you have an oval in that square (in this example it's a circular oval, if you want your curve to be more oval-ish, then define your square as a rectangle), you can take any slice of that circle using the last two params of the method. The first param defines the angle where you want to start cutting. If we're using a compass, 0 degrees is East (not sure why, I'm not a geometry expert... is this normal? I always think of 0 being North, but all the programming geometry examples I see have 0 as East, maybe someone will comment on why that is).

The second param defines how much of the circle you want. If you want the whole circle you put 360 if you want half the circle you put 180 etc.

So, in our case since we want to round the corner from 12 to 3, we put 270 as our starting degree and grab 90 degrees of the circle.

Lastly, when you're done with this process, the line now thinks of itself as being at 3pm so you can continue lineTo(ing) from there. So... here's my fixed code for my shape (it has a little triangle in it, but that's neither here nor there, the actual rounded parts are B-C, D-E, I-J, and K-A. All the rest are straight lines.

int arc = 25;
    public Cursor(int X, int Y, int W, int H){
        /*
         *   A            B
         * K                C 
         * J                D
         *   I   H   F    E
                   G
         */
        int Ax = X+ arc;
        int Ay = Y;
        int Bx = X + W - arc;
        int By = Y;
        int Cx = X + W;
        int Cy = Y + arc;
        int Dx = Cx;
        int Dy = (Y + arc) + (H - arc*2);
        int Ex = Bx;
        int Ey = Y + H;
        int Fx = X+W/2 +6;
        int Fy = Ey;
        int Gx = X+W/2;
        int Gy = Y+H+8;
        int Hx = X+W/2-6;
        int Hy = Ey;
        int Ix = Ax;
        int Iy = Hy;
        int Jx = X;
        int Jy = Dy;
        int Kx = X;
        int Ky = Cy;


        Path ctx = new Path();
        ctx.moveTo(Ax,Ay); //A
        ctx.lineTo(Bx,By);//B
        ctx.arcTo(new RectF(Bx, By, Cx, Cy), 270, 90); //B-C arc

        ctx.lineTo(Dx,Dy); //D
        ctx.arcTo(new RectF(Dx - arc, Dy, Ex + arc, Ey),0,90); //D-E arc

        ctx.lineTo(Fx, Fy); //E-F
        ctx.lineTo(Gx, Gy); //F-G
        ctx.lineTo(Hx, Hy); //G-H
        ctx.lineTo(Ix, Iy); //H - I
        ctx.arcTo(new RectF(Jx, Jy, Ix, Iy),90,90);// I = J arc

        ctx.lineTo(Kx, Ky); //K
        ctx.arcTo(new RectF(Ax - arc, Ay, Kx + arc, Ky),180,90); //K - A arc
        ctx.lineTo(Ax, Ay); //K



        Paint p = new Paint();
        p.setAntiAlias(true);
        p.setColor(0xffffffff);
        p.setStyle(Style.FILL);
        canvas.drawPath(ctx, p);    
        p.setColor(0xff000000);
        p.setStyle(Style.STROKE);
        p.setStrokeWidth(3);            
        canvas.drawPath(ctx, p);



    }

Thanks for this example, it makes the parameters very clear to understand. From what I read in the dev docs of Android you can probably spare yourself some of the "lineTo()" calls (except those to points F,G,H), since arcTo automatically adds a lineTo when the first point of the arc is not the last point drawn...

As for why 0 starts East, it is so because of math and trigonometry lessons generally assume that the 0 degrees mark is the point where the trigonometric circle (circle with center 0,0 and radius 1) intersects with the X-axis, which is East (these same lessons however generally count the angles counter-clockwise, so 90 degrees becomes north and 270 is south, whereas on Android it seems the angles are counted clockwise)

Tags:

Android

Path