Как нарисовать эллиптический сектор с помощью алгоритма Брезенхэма? - PullRequest
0 голосов
/ 24 сентября 2018

Как нарисовать заполненный эллиптический сектор с помощью алгоритма Брезенхэма и растрового объекта с помощью метода DrawPixel?

Я написал метод для рисования эллипса, но этот метод использует симметрию и пропускает только первый квадрант.Этот алгоритм не доступен для секторов.Конечно, я могу написать 8 циклов, но я думаю, что это не самое элегантное решение задачи.

1 Ответ

0 голосов
/ 27 сентября 2018

При целочисленной математике обычная параметризация - использование ограничительных линий (в направлении CW или CCW) вместо ваших углов.Так что если вы можете преобразовать эти углы в такие (вам нужно sin,cos для этого, но только один раз), то вы можете использовать для этого рендеринг с целочисленной математикой.Как я уже упоминал в комментарии, bresenham не является хорошим подходом для сектора эллипса, так как вам нужно будет вычислить состояние внутренних итераторов и счетчиков для начальной точки интерполяции, а также даст вам только точки окружности вместо заполненной формы.

Есть много подходов для этого, здесь простой:

  1. преобразовать эллипс в круг

    просто путем изменения масштабаменьшая ось радиуса

  2. проходить через bbox такого круга

    простые 2 вложенные for петли, охватывающие вписанный квадрат нашего круга

  3. проверьте, находится ли точка внутри круга

    , просто проверьте, если x^2 + y^2 <= r^2, а круг центрируется по (0,0)

  4. проверьте, находится ли точка между линиями ребер

    , поэтому она должна быть CW с одним ребром и CCW с другим.Для этого вы можете использовать перекрестное произведение (его полярность по координате z скажет вам, является ли точка CW или CCW относительно тестируемой линии края)

    , но это будет работать только до срезов 180 градусов, поэтому вам также необходимо добавить некоторыепроверка квадрантов, чтобы избежать ложных негативов.Но это всего лишь несколько ifs поверх этого.

  5. , если все условия выполнены, преобразовать точку обратно в эллипс и отобразить

Вот небольшой C ++ пример этого:

void elliptic_arc(int x0,int y0,int rx,int ry,int a0,int a1,DWORD c)    
    {
    // variables
    int  x, y, r,
        xx,yy,rr,
        xa,ya,xb,yb,                // a0,a1 edge points with radius r
        mx,my,cx,cy,sx,sy,i,a;
    // my Pixel access (you can ignore it and use your style of gfx access)
    int **Pixels=Main->pyx;         // Pixels[y][x]
    int   xs=Main->xs;              // resolution
    int   ys=Main->ys;
    // init variables
    r=rx; if (r<ry) r=ry; rr=r*r;   // r=max(rx,ry)
    mx=(rx<<10)/r;                  // scale from circle to ellipse (fixed point)
    my=(ry<<10)/r;
    xa=+double(r)*cos(double(a0)*M_PI/180.0);
    ya=+double(r)*sin(double(a0)*M_PI/180.0);
    xb=+double(r)*cos(double(a1)*M_PI/180.0);
    yb=+double(r)*sin(double(a1)*M_PI/180.0);
    // render
    for (y=-r,yy=y*y,cy=(y*my)>>10,sy=y0+cy;y<=+r;y++,yy=y*y,cy=(y*my)>>10,sy=y0+cy) if ((sy>=0)&&(sy<ys))
     for (x=-r,xx=x*x,cx=(x*mx)>>10,sx=x0+cx;x<=+r;x++,xx=x*x,cx=(x*mx)>>10,sx=x0+cx) if ((sx>=0)&&(sx<xs))
      if (xx+yy<=rr)                // inside circle
        {
        if ((cx>=0)&&(cy>=0)) a=  0;// actual quadrant
        if ((cx< 0)&&(cy>=0)) a= 90;
        if ((cx>=0)&&(cy< 0)) a=270;
        if ((cx< 0)&&(cy< 0)) a=180;
        if ((a   >=a0)||((cx*ya)-(cy*xa)<=0))           // x,y is above a0 in clockwise direction
         if ((a+90<=a1)||((cx*yb)-(cy*xb)>=0))
          Pixels[sy][sx]=c;
        }
    }

, знайте, что оба угла должны быть в диапазоне <0,360>.У моего экрана буква y направлена ​​вниз, поэтому, если a0<a1, это будет направление CW, соответствующее пути.Если вы используете a1<a0, то диапазон будет пропущен, а остальная часть эллипса будет визуализирована взамен.

Этот подход использует a0,a1 в качестве реальных углов !!!

Чтобы избежать разрывов внутрицикл Я вместо этого использовал 10-битные шкалы с фиксированной точкой.

Вы можете просто разделить это на 4 квадранта, чтобы избежать 4, если внутри циклов для повышения производительности.


x,y - точка в круговойшкала с центром в (0,0)
cx,cy - точка в эллиптической шкале с центром в (0,0)
sx,sy - точка в эллиптической шкале, переведенная в центральное положение эллипса

Осторожно мой пиксельный доступ Pixels[y][x], но большинство API-интерфейсов используют Pixels[x][y], поэтому не забудьте изменить его на API, чтобы избежать нарушений прав доступа или поворота результата на 90 градусов ...

...