Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Звук, графика и видео > Правильное рисование окружности


Автор: MacTep 9.10.2004, 07:34
Почему, когда я рисую окружность так
Код
var i,r:integer;
begin

 for r:=0 to 150 do
   for i:=0 to 360 do
     Canvas.Pixels[200+round(r*cos(i*2*pi/360)),200+round(r*sin(i*2*pi/360))]:=i;
у меня получается, что в окружностях имеются маленькие точечки, которые не прорисовываются? Как от этого можно избавиться? Спасибо!

Автор: p0s0l 9.10.2004, 09:59
Потому что заведомо ты установливаешь количество пикселей в окружности (360). А если радиус будет большой, то будут дыры...
Лучше рисовать по алгоритму Брезенхема - он быстрее, без sin/cos, и без дыр будет...

Автор: p0s0l 9.10.2004, 10:58
Вот, накидал рисование через Брезенхема на примере того цветого круга, который ты хотел получить в соседней теме...

Код
procedure TForm1.Button4Click(Sender: TObject);
var
 x0, y0, r : integer;
 d, x, y : integer;

function CalcColor(a : real) : TColor;
var i : integer;
const
 pi23 = pi*2/3;
 pi43 = pi*4/3;
begin
 while a < 0 do a := a + pi*2;
 
 if a < pi23 then
 begin
   i := Round(255*a/pi23);
   Result := RGB(255-i, i, 0);
 end
 else
 if a < pi43 then
 begin
   i := Round(255*(a-pi23)/pi23);
   Result := RGB(0, 255-i, i);
 end
 else
 begin
   i := Round(255*(a-pi43)/pi23);
   Result := RGB(i, 0, 255-i);
 end;
end;

procedure DrawPixels;
var
 a1 : real;
begin
 if x = 0 then a1 := pi / 2 else a1 := ArcTan (y / x);
 Canvas.Pixels[x0 + x, y0 + y] := CalcColor(a1);
 Canvas.Pixels[x0 - x, y0 + y] := CalcColor(pi - a1);
 Canvas.Pixels[x0 + x, y0 - y] := CalcColor(-a1);
 Canvas.Pixels[x0 - x, y0 - y] := CalcColor(-pi + a1);
 Canvas.Pixels[x0 + y, y0 + x] := CalcColor(pi/2 - a1);
 Canvas.Pixels[x0 - y, y0 + x] := CalcColor(pi/2 + a1);
 Canvas.Pixels[x0 + y, y0 - x] := CalcColor(-pi/2 + a1);
 Canvas.Pixels[x0 - y, y0 - x] := CalcColor(-pi/2 - a1);
end;

begin
// центр окружности
 x0 := 200;
 y0 := 200;

 for r := 0 to 150 do
 begin
   x := 0;
   y := r;
   d := 3 - 2*r;
   repeat
     DrawPixels;
     if d < 0 then Inc(d, x*4 + 6)
     else
     begin
       Inc(d, 4*(x-y)+10);
       Dec(y);
       DrawPixels;
     end;
     Inc(x);
   until x > y;
 end;  
end;

Автор: MacTep 10.10.2004, 23:02
А знаешь, в соседней теме, да и в этой я тоже пытался сделать так, чтобы к центру окружности, цвета становились темнее и в конце-концов стали черными, а к краям все было белее и белее и вдруг стало белым. Как это сделать?

Автор: p0s0l 10.10.2004, 23:23
Так ?
Код
procedure TForm1.Button1Click(Sender: TObject);
var
 x0, y0, rmin, rmax : integer;
 d, x, y, r : integer;
 k, k1 : real;

function CalcColor(a : real) : TColor;
var
 r, g, b : real;
const
 pi23 = pi*2/3;
 pi43 = pi*4/3;
begin
 if a < 0 then a := a + pi*2;

 if a < pi23 then
 begin
   g := 255*a/pi23;
   r := 255-g;
   b := 0;
 end
 else
 if a < pi43 then
 begin
   r := 0;
   b := 255*(a-pi23)/pi23;
   g := 255-b;
 end
 else
 begin
   r := 255*(a-pi43)/pi23;
   g := 0;
   b := 255-r;
 end;

 if k <= 1 then
 begin
   r := r*k;
   g := g*k;
   b := b*k;
 end
 else
 begin
   r := 255 -(255-r)*k1;
   g := 255 -(255-g)*k1;
   b := 255 -(255-b)*k1;
 end;
 Result := RGB(Trunc(r), Trunc(g), Trunc(b));
end;

procedure DrawPixels;
var
 a1 : real;
begin
 if x = 0 then a1 := pi / 2 else a1 := ArcTan (y / x);
 Canvas.Pixels[x0 + x, y0 + y] := CalcColor(a1);
 Canvas.Pixels[x0 - x, y0 + y] := CalcColor(pi - a1);
 Canvas.Pixels[x0 + x, y0 - y] := CalcColor(-a1);
 Canvas.Pixels[x0 - x, y0 - y] := CalcColor(-pi + a1);
 Canvas.Pixels[x0 + y, y0 + x] := CalcColor(pi/2 - a1);
 Canvas.Pixels[x0 - y, y0 + x] := CalcColor(pi/2 + a1);
 Canvas.Pixels[x0 + y, y0 - x] := CalcColor(-pi/2 + a1);
 Canvas.Pixels[x0 - y, y0 - x] := CalcColor(-pi/2 - a1);
end;

begin
// центр окружности
 x0 := 200;
 y0 := 200;
// начальные и конечные радиусы
 rmin := 0;
 rmax := 150;

 for r := rmin to rmax do
 begin
   k := (r-rmin)*2/(rmax - rmin);
   k1 := 2-k;
   x := 0;
   y := r;
   d := 3 - 2*r;
   repeat
     DrawPixels;
     if d < 0 then Inc(d, x*4 + 6)
     else
     begin
       Inc(d, 4*(x-y)+10);
       Dec(y);
       DrawPixels;
     end;
     Inc(x);
   until x > y;
 end;
end;

PS: изменил позже процедуру CalcColor, там из-за целочисленных вычислений/округлений была четкая граница между переходами R-G-B, теперь получше стало...

Автор: Kesh 10.10.2004, 23:28
Код
procedure TForm1.FormClick(Sender: TObject);
const
 N = 300;
var
 i,j: integer;
 c: byte;
begin
 form1.Canvas.Brush.Style := bsSolid;
 for i := N downto 0 do
   begin
     c := Round(i/N*255);
     form1.Canvas.Pen.Color := RGB(c,c,c);
     form1.Canvas.Brush.Color := RGB(c,c,c);
     form1.Canvas.Ellipse(N-i,N-i,N+i,N+i);
   end;
end;

Автор: MacTep 11.10.2004, 08:20
Kesh, мне надо, чтобы круг был не черно-белым, а полноцветным. Т.е. там должны быть все цвета радуги, плавно переходящие друг из друга в другие цвета. Мне надо такую окружность, как показал p0s0l, но с таким затемнением, как у тебя. Понятно?

Добавлено @ 08:30
p0s0l, все замечательно. Ты все сделал просто класс. Только теперь можно узнать, в чем состоит алгоритм Брозенхейма и парут-тройку комментаривев к твое программе. А то мне ее надо еще объянять преподу, да и отчет писать как-никак.

Автор: Alex 11.10.2004, 08:39
Цитата(MacTep @ 11.10.2004, 09:20)
p0s0l, все замечательно. Ты все сделал просто класс. Только теперь можно узнать, в чем состоит алгоритм Брозенхейма и парут-тройку комментаривев к твое программе. А то мне ее надо еще объянять преподу, да и отчет писать как-никак.

http://www.yandex.ru/yandsearch?text=%C1%F0%E5%E7%E5%ED%F5%E5%EC%E0&tb=1

Автор: p0s0l 11.10.2004, 10:39
Comments:

CalcColor - вычисляет цвет точки в зависимости от угла (вх. параметр a), и от радиуса окружности.
Вначале выясняется, к какой трети окружности принадлежит данная точка, и в зависимости от этого вычисляется её цвет. Например, во второй трети (if a < pi43) вычисляется так:
красная компонента = 0
зеленая компонента -> чем больше угол, тем меньше зелености
синяя компонента - наоборот, чем больше угол, тем больше синевы
Далее (if k <= 1) - если радиус текущей окружности ® меньше половины радиуса внешней окружности (rmax), то идёт затемнение цвета путём умножения составляющих цвета на коэффициент k, где k=[0..1]
Если же (k > 1), то наоборот происходит осветление...

DrawPixels - выводит 8 симметрично расположенных пикселей. Почему 8 ? В данном коде окружность разбивается на 8 частей, и алгоритмом Брезенхема вычисляется только одна часть, остальные части получаются путём зеркального отражения.

А там дальше уже идёт сам Брезенхем - о нём можешь почитать в данных выше ссылках...

Автор: MacTep 11.10.2004, 10:42
Вот спасибо! Очень помогло!

Автор: posleg 22.1.2010, 00:42
хороший пример))))
не подскажете как на его основе сделать 4- х связанный эллипс ??????????
плиз

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)