Логин:     Забыли пароль?
 
Пароль:   Регистрация

Форум / Программирование - Построение дуги  

Построение дуги

Фео
Фео
Посетитель
Сообщения: 5
[Сообщение #1] 15 июня 2012, 17:45
Необходимо написать собственную процедуру рисования дуги Canvas.Arc не устроил, поскольку для него нужно писать корректирующий алгоритм, чтобы заткнуть дырки в погрешностях построения, которые иногда могут возникать при округлении результатов.

Написал на посмотреть такую процедуру

procedure TForm1.FormCreate(Sender: TObject);
begin
Randomize;
Color := RGB(Random(256), Random(256), Random(256));
n := False;
end;
 
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
SetLength(Mas0, 3, 2);
SetLength(Mas1, 2, 2); // (A1, -), (X1, Y1)
 
Mas0[0, 0] := StrToFloat(Edit1.Text); // R
Mas0[0, 1] := StrToFloat(Edit2.Text); // Aльфа0
Mas0[1, 0] := ArcTan(1 / Mas0[0, 0]); // Шаг
Canvas.MoveTo(200 + Round(Mas0[0, 0]), 200);
Canvas.Pen.Color := RGB(Random(256), Random(256), Random(256));
 
Mas0[1, 1] := 0; // Начальный/текущий угол
repeat
Mas0[2, 0] := Round(200 + Mas0[0, 0] * cos(Mas0[1, 1])); // X0
Mas0[2, 1] := Round(200 + Mas0[0, 0] * sin(Mas0[1, 1])); // Y0
Canvas.LineTo(Round(Mas0[2, 0]), Round(Mas0[2, 1]));
 
Mas1[0, 0] := Mas0[1, 1] + 2 * Mas0[1, 0];
if Mas1[0, 0] <= Mas0[0, 1] then
 begin
 Mas1[1, 0] := Round(200 + Mas0[0, 0] * cos(Mas1[0, 0])); // X1
 Mas1[1, 1] := Round(200 + Mas0[0, 0] * sin(Mas1[0, 0])); // Y1
 
 if (abs(Mas0[2, 0] - Mas1[1, 0]) = 1) and
    (abs(Mas0[2, 1] - Mas1[1, 1]) = 1)
  then
   begin
   n := True;
   Canvas.Pen.Color := RGB(Random(256), Random(256), Random(256));
   Canvas.LineTo(Round(Mas1[1, 0]), Round(Mas1[1, 1]));
   end;
 end;
 
if n = False // Текущий угол
 then Mas0[1, 1] := Mas0[1, 1] + Mas0[1, 0]
 else begin Mas0[1, 1] := Mas1[0, 0]; n := False; end;
 
until Mas0[1, 1] >= Mas0[0, 1]; // Текущий угол >= Альфа0
end;

Здесь накидано только часть необходимого по минимуму, всё вроде как нормально, но результаты построения отличаются между собой (часть пикселей рисуется на один выше/ниже/левее/правее), проблема в округлении, года 3 назад слышал что программисты долго пилили этот алгоритм округления, чтоб получить то, что есть сейчас.

Собственно вопрос: где можно посмотреть исходный код стандартной процедуры построения дуги?

min@y™
min@y™
Доктор наук
Сообщения: 400
[Сообщение #2] 15 июня 2012, 21:47

Цитата (Фео):

где можно посмотреть исходный код стандартной процедуры построения дуги?

Стандартной, говоришь? Есть тут одна малоизвестная фирма... мелкософт, вроде, называется... Думаю, что исходник находится там, ибо:
procedure TCanvas.Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer);
begin
  Changing;
  RequiredState([csHandleValid, csPenValid, csBrushValid]);
  Windows.Arc(FHandle, X1, Y1, X2, Y2, X3, Y3, X4, Y4);
  Changed;
end;

Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
Фео
Фео
Посетитель
Сообщения: 5
[Сообщение #3] 16 июня 2012, 16:29
Спасибо... что находится внутри Windows.Arc я не нашёл, и сколько ещё исходников вложенных процедур придётся искать - не знаю, но думаю многовато, тем более для самостоятельного изучения второго курса программирования, единственное что наткнулся на ява код, в котором округления и не боло в принципе, может только внутри Angle где-то, хотя там скорее сглаживание применяется, что мне не надо, писать свою процедуру сглаживания для меня будет геморно, хотя что и как надо делать я представляю

Фео
Фео
Посетитель
Сообщения: 5
[Сообщение #4] 17 июня 2012, 20:17
Нашёл решение своей проблемы, но пока не писал код :-)

0) пишем все получаемые координаты в отдельный динамический массив - буфер, для круга достаточно просчитывать Пи/4 радиана, для овала Пи/2 радиана, дугу в зависимости от ситуации, остальные координаты можно посчитать сложив 2 и 2;

1) в буфере поблочно в 4 пикселя с шагом в 1 обрабатывать получаемые координаты, "выравнивая" их и выкидывая лишние, заменяя их координаты на (-65536, -65536), исключая их из видимой области формы и игнорируя при построении;

2) на следующем проходе буфера выкидываем из него избыточные данные, затирая их значением (-65536, -65536), оставляя минимум точек, находящихся в узлах (вершинах) прямых, кривые и замкнутые линии рисуются как известно из множества прямых разной длины, расположенных под углами X mod Pi/4 = 0;

3) строим дугу или чё там нам надо по оставшимся данным, игнорируя ячейки буфера со значением (-65536, -65536);

Результат будет выглядеть нормально, но будет дальше от истинного, в отличие от изначального варианта, наверно данный метод 100% опять же не будет повторять построение с помощью стандартных процедур


Всего сообщений: 4 (сейчас показаны: с 1 по 4)

Перейти в раздел:


 © 2004 - 2024, Delphi.int.ru
Версия форума: 1.10 (19.01.2010)
RSS Delphi.int.ru Expert Код
Выполнено за 0.03 сек.
Обратная связь