Может кто-нибудь объяснить последние два параметра arcTo?

Я пытаюсь нарисовать прямоугольник с закругленными углами. У меня есть путь javascript, который делает это, но метод javascript arcTo принимает прямоугольник (чтобы определить его овал), а затем один параметр, который устанавливает развертку.

Однако в версии Android есть три параметра. прямоугольник овал (который, я думаю, я правильно определил), а затем startAngle и sweepAngle (который я не понимаю), но мои дуги не выглядят ничем, как то, что я ожидаю, когда я лапшу с тем, как я Думаю, они должны работать.

Кто-нибудь знает хороший учебник по этому поводу?

В частности, я пытаюсь понять, как выглядят два параметра, если я попытаюсь нарисовать дугу (на циферблате) с 12 до 3, а затем предположим, что у меня была строка, которая бежала вниз от 3 и затем необходимо за углом от 3 до 6 и так далее.

Здесь мой код (не обращайте на него цифры дуги сейчас... что только последняя итерация моего угадывания о том, как это может работать, провалившись на предыдущие, более разумные попытки):

Path ctx = new Path();
        ctx.moveTo(X+5,Y); //A
        ctx.lineTo(X+W-5,Y);//B
        ctx.arcTo(new RectF(X+W, Y, X+W, Y+5), -180, 90); //B arc

        ctx.lineTo(X+W,Y+H-5); //C
        ctx.arcTo(new RectF(X+W,Y+H,X+W-5,Y+H),90,180); //C arc

        ctx.lineTo(X+W/2 +6,Y+H);
        ctx.lineTo(X+W/2,Y+H+8);
        ctx.lineTo(X+W/2-6,Y+H);
        ctx.lineTo(X+5,Y+H);
        ctx.arcTo(new RectF(X,Y+H,X,Y+H-5),180,270);

        ctx.lineTo(X,Y+5);
        ctx.arcTo(new RectF(X,Y,X+5,Y),270,0);
        Paint p = new Paint();
        p.setColor(0xffff00ff);

        canvas.drawPath(ctx, p);

очень обязан.

Ответы

Ответ 1

странно, что никто не отвечал на ответ, как только я нашел его (его было нелегко найти), это было действительно прямо.

Итак, как это работает: Предполагая, что вы хотите нарисовать закругленный угол в 12 - 3 (с использованием тактовой частоты): вы начинаете свой путь, и когда вам нужна строка для дуги, вы определяете прямоугольник, верхний левый угол которого - это место, где ваша линия в настоящее время завершена, а нижний правый угол - это место, куда вы хотите, чтобы дуга проходила, поэтому, если вы представляете квадрат, X, Y - 12 (на часах), а X + W, Y + H - 3, который вам нужен.

Теперь представьте, что у вас есть овал в этом квадрате (в этом примере это круговой овал, если вы хотите, чтобы ваша кривая была более овальной, затем определите квадрат как прямоугольник), вы можете взять любой кусочек этот круг, используя последние два параметра метода. Первый параметр определяет угол, в котором вы хотите начать резку. Если мы используем компас, 0 градусов - это Восток (не знаю, почему, я не эксперт по геометрии... это нормально? Я всегда думаю, что 0 - северный, но все примеры геометрии программирования, которые я вижу, равны 0 Восток, может быть, кто-то будет комментировать, почему это так).

Второй параметр определяет размер круга, который вы хотите. Если вы хотите, чтобы весь круг вы наложили 360, если вы хотите, чтобы половина круга вы положили 180 и т.д.

Итак, в нашем случае, поскольку мы хотим округлить угол от 12 до 3, мы ставим 270 в качестве начальной степени и получаем 90 градусов круга.

Наконец, когда вы закончите этот процесс, линия теперь думает о себе как о 3pm, чтобы вы могли продолжить lineTo (ing). Итак... вот мой фиксированный код для моей фигуры (в нем есть маленький треугольник, но ни здесь, ни там, фактические закругленные части - это BC, DE, IJ и KA. Все остальное - прямые.

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);



    }

Ответ 2

Спасибо за этот пример, он делает параметры очень понятными. Из того, что я прочитал в dev-документах Android, вы, вероятно, можете избавиться от некоторых вызовов "lineTo()" (кроме тех, что указаны в точках F, G, H), поскольку arcTo автоматически добавляет строку, когда первая точка дуги не последняя точка, нарисованная...

Что касается того, почему 0 начинается с Востока, то из-за уроков математики и тригонометрии обычно предполагается, что знак 0 градусов - это точка, где тригонометрический круг (окружность с центром 0,0 и радиус 1) пересекается с осью X, который является Востоком (эти же уроки, однако, обычно подсчитывают углы против часовой стрелки, поэтому 90 градусов становятся северными, а 270 - южными, тогда как на Android кажется, что углы подсчитываются по часовой стрелке)

Ответ 3

Вот пример кода (собранного из одного из моих классов), чтобы нарисовать заполненный прямоугольник с округлым углом, а затем добавить поглаженный прямоугольник, чтобы придать ему границу:

//Initializing some stuff
_paint = new Paint();
_rect = new RectF();
_radius = 10;
_bgColor = 0xFFFFFFFF;
_borderColor = 0xFFCCCCCC;

//Doing dimension calculations
_rect.left = 0;
_rect.top = 0;
_rect.right = this.getWidth() - 1;
_rect.bottom = this.getHeight() - 1;

//painting
//draw the background
_paint.setColor(_bgColor);
_paint.setStyle(Style.FILL_AND_STROKE);
canvas.drawRoundRect(_rect, _radius, _radius, _paint);

//draw the border
_paint.setStrokeWidth(1);
_paint.setColor(_borderColor);
_paint.setStyle(Style.STROKE);
canvas.drawRoundRect(_rect, _radius, _radius, _paint);