Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > Сфера


Автор: Dexter 8.11.2002, 05:03
Вот написал небольшую прогу, которая рисует "сферу"

Код

var
 s,f: integer;
begin
 for f:=0 to 30 do
 for s:=1 to 100000 do begin    
      canvas.Pixels[round(sin(s)*f*10)+width div 2,round(cos(s)*300)+height div 2]:=clBlack;
      canvas.Pixels[round(sin(s)*300)+width div 2,round(cos(s)*f*10)+height div 2]:=clBlack;
 end;
end;

Я знаю, что это полное фуфло, поэтому хочу спросить как по-людски рисуются элепсы, ну и если кто знает сферы  :D

Автор: Vit 8.11.2002, 07:05
А почему во флейм? Это тема для раздела по алгоритмам, ИМХО

Автор: Dexter 9.11.2002, 03:12
Ой, я че-то не додумался. Можешь перенести?

Автор: Vit 9.11.2002, 03:23
Нет, это к Админу и Серёге - кстати давненько он не появлялся...

Автор: podval 10.11.2002, 18:17
http://algolist.manual.ru/maths/geom/equation/sphere.php

Автор: neutrino 10.11.2002, 19:51
А не на OpenGL это делать нужно?

Автор: Dexter 10.11.2002, 21:44
Цитата
А не на OpenGL это делать нужно?


Не, я хотел спроить как это впринципе делается

Автор: neutrino 11.11.2002, 00:19
Я тебя не понял. Если тебе сферу надо нарисовать на плоском мониторе, (а других пока нет) надо нарисовать просто круг. А если 3-хмерную картинку, то это работа с тенями, светом ...
Цитата

как по-людски рисуются элепсы,

Эллепсоиды, кажись :)

Автор: Dexter 11.11.2002, 05:11
Забудем про сферу.

Как
Цитата
Эллепсоиды
рисуются.
(Не так же мазохистски как у меня). :D

Автор: MuToGeN 11.11.2002, 10:28
Код

#define pi 3.14
int xCenter=координата центра X;
int yCenter=координата центра Y;
int xRadius=радиус по X;
int yRadius=радиус по Y;
double i;
for(i=0;i<pi*2;i+=0.01)
 canvas.Pixels[ceil(cos(i)*xRadius+xCenter)][ceil(sin(i)*yRadius+yCenter)]=clBlack;
только это на С

Автор: Chingachguk 11.11.2002, 21:59
Синусы и косинусы придумали трусы ;)

Вот код на обычном Паскале:

Цитата

{$N+}
{$A-}
{$G+}
uses crt;
procedure graph256;
 begin
   asm
   mov  ax,13h; int  10h
   end;
 end;
procedure close256;
 begin
   asm
   mov  ax,03h; int  10h
   end;
 end;
procedure Ellipse256(color:byte; r,x,y:word; a,b: word);
 var
   xc,yc: word;
 begin
   asm
     push 0a000h
     pop  es
     mov  cx,r
     mov  ax,x
     sub  ax,cx
     mov  xc,ax
     mov  ax,y
     sub  ax,cx
     mov  yc,ax
     mov  ax,cx
     mul  ax
     mov  bx,ax
     shl  cx,1
     inc  cx
     mov  si,cx
@ScanY:
     push cx
     mov  cx,si
     push xc
@ScanX:
     mov  ax,xc
     sub  ax,x
     imul ax
     mul  a
     push ax
     mov  ax,yc
     sub  ax,y
     imul ax
     mul  b
     pop  dx
     add  ax,dx
     cmp  ax,bx
     ja   @NoPaint
     mov  ax,320
     mul  yc
     add  ax,xc
     mov  di,ax
     mov  al,color
     mov  es:[di],al
@NoPaint:
     inc  xc
     loop @ScanX
     pop  xc
     pop  cx
     inc  yc
     loop @ScanY
   end;
 end;
begin
 graph256;
 Ellipse256(9,10,20,20,1,1);
 Ellipse256(14,20,70,50,3,1);
 Ellipse256(31,30,170,100,1,5);
 repeat until keypressed;
 close256;
end.

Автор: MuToGeN 11.11.2002, 22:29
Цитата(Chingachguk @ 11.11.2002, 13:59)
Синусы и косинусы придумали трусы ;)
Вот код на обычном Паскале:

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

Автор: Dexter 11.11.2002, 22:59
Я тут пару дней как с asm'ом общаюсь и понял целых две процедуры: procedure graph256 и procedure close256 первая "заход" в граф. режим другая выход.

Дальше мне нужен криптограф

Автор: Chingachguk 11.11.2002, 23:03
Да я просто прикололся ;)

Хотя там действительно нету синусов: одно умножение:

// Вход: x,y - координаты центра
// color - цвет
// a и b - коэффициенты растяжения из уравнения эллипса:
// a*x^2+b*x^2=r^2
// r - радиус
// Загружаем в es адрес видеобуфера (0xA0000)
    push 0a000h
    pop  es
// Вычисляем в xc = x - r
    mov  cx,r
    mov  ax,x
    sub  ax,cx
    mov  xc,ax
// Вычисляем в yc = y - r
    mov  ax,y
    sub  ax,cx
    mov  yc,ax
// Вычисляем r^2 и будем хранить его в bx
    mov  ax,cx
    mul  ax
    mov  bx,ax
// Число проходов по X и Y равно 2*R + 1 (по обе сторны от x и y)
    shl  cx,1
    inc  cx
    mov  si,cx
// Храним его в si
@ScanY:
// Проход по yc = y - r ... y ... y + r
    push cx
    mov  cx,si
    push xc
// Проход по xc = x - r ... x ... x + r
@ScanX:
// Вычисляем xc-x
    mov  ax,xc
    sub  ax,x
// Разницу xc-x возводим в квадрат
    imul ax
// Квадрат домножаем на a
    mul  a
// Сохраняем р-т в стеке
    push ax
// Вычисляем yc-y
    mov  ax,yc
    sub  ax,y
// Разницу yc-y возводим в квадрат
    imul ax
// Квадрат домножаем на b
    mul  b
    pop  dx
// Вычисялем a*(xc-x)^2+b*(yc-y)^2
    add  ax,dx
// Если эта штука <= r^2, то рисуем пиксель цветом color
    cmp  ax,bx
    ja   @NoPaint
// Отрисовка пикселя
    mov  ax,320
    mul  yc
    add  ax,xc
    mov  di,ax
    mov  al,color
    mov  es:[di],al
@NoPaint:
// Следующий xc
    inc  xc
    loop @ScanX
    pop  xc
    pop  cx
// Следующий yc
    inc  yc
    loop @ScanY
  end;

... ;)

Автор: Dexter 11.11.2002, 23:07
Блин, как все сложно с этим асмом

Автор: Chingachguk 11.11.2002, 23:20
Цитата

Dexter Дата сообщения: 11.11.2002,15:07
Блин, как все сложно с этим асмом


Да ладно ;)

Вот вопрос на засыпку:

typedef unsigned char byte;
typedef unsigned long u32;
...

u32 x;
byte key[4] = {0x01,0x02,0x03,0x04}

...
x = key[0]  << 24 | key[1]  << 16 | key[2]  << 8 | key[3];

А теперь вопрос: что будет в результате в x ? ;)

Автор: Dexter 11.11.2002, 23:41
Че-то я нихрена не понял:

typedef unsigned char byte;
typedef unsigned long u32;

Это че-то из C++ (наверно) (я сним не в таких ладах чтобы понять это)

u32 x;
byte key[4] = {0x01,0x02,0x03,0x04}

первая строка незнаю че делает, вторая походу массив (наверно)

x = key[0]  << 24 | key[1]  << 16 | key[2]  << 8 | key[3];

Это я ваще не знаю че такое.

Автор: neutrino 12.11.2002, 00:39
Цитата(Chingachguk @ 11.11.2002, 12:20)
Вот вопрос на засыпку:

typedef unsigned char byte;
typedef unsigned long u32;
...

u32 x;
byte key[4] = {0x01,0x02,0x03,0x04}

...
x = key[0]  << 24 | key[1]  << 16 | key[2]  << 8 | key[3];

А теперь вопрос: что будет в результате в x ? ;)

Да, я тоже сначала пытался это "прочитать". А там этих строк ой-ой-ой!!! Не разобрать.
Дело в том, что << имеет больший приоритет чем |. А |, в свою очередь, берет то что справа сначала!!! Чтобы эту строку анализировать надо запустить рекурсивный алгоритм :).
В конце получится 772 (честно говоря, я проверил, но посмотрел и код).
Для особо заинтересованных: скомпилируйте это и  через td откройте файл.
2Chingachguk: Так как дела с прогой?

Автор: Chingachguk 12.11.2002, 18:54
> neutrino Дата сообщения: 11.11.2002,16:39
> Да, я тоже сначала пытался это "прочитать". А там этих строк ой-ой-ой!!!
> Не разобрать.

Не, написано как раз все понятно.

> Дело в том, что << имеет больший приоритет чем |. А |, в свою очередь,
> берет то что справа сначала!!! Чтобы эту строку анализировать надо
> запустить рекурсивный алгоритм .

Я не смотрел особо, какой-такой приоритет, я от смысла шел. А по смыслу должно быть 0x01020304.

> В конце получится 772 (честно говоря, я проверил, но посмотрел и код).

Вот видишь ! Ты чем компилил ? Я - bc.310. В ассемблерном листинге было видно, что код ОТРЕЗАЕТ старшие два байта результата промежуточных вычислений: генерит что-то вроде:

 shl ax,24 // !!! ???

Даже если делать в явном виде указание:

 (u32)key[0]<<24, то код(ассемблерный) меняется, но этого ... недостаточно !!!

> Для особо заинтересованных: скомпилируйте это и  через td откройте файл.

А самое смешное в этом СИ то, что все это в VC(винды)... работает ! А все потому, что там 32 разряда. Вообще специалист по СИ(работает рядом со мной) говорит, что скорее ВЕРНО РАБОТАЕТ именно bc - те не работает... Потому, как по правилам (?) результат должен приводиться (если явно не указано) к наименьшему типу !

> 2Chingachguk: Так как дела с прогой?

Пока особо никак ;( Работа почему-то мешает ;)

Автор: Kesh 13.11.2002, 04:48
Нашел по F1 в Делфи... :0) Или я не понял вопроса...

Draws the ellipse defined by a bounding rectangle on the canvas.

procedure Ellipse(X1, Y1, X2, Y2: Integer); overload;
procedure Ellipse(const Rect: TRect); overload;

Description

Call Ellipse to draw a circle or ellipse on the canvas. Specify the bounding rectangle either by giving

The top left point at pixel coordinates (X1, Y1) and the bottom right point at (X2, Y2).
A TRect value.

If the bounding rectangle is a square, a circle is drawn.

The ellipse is outlined using the value of Pen, and filled using the value of Brush.

Note: On Windows 95, the sums X1 + X2 and Y1 + Y2 cannot exceed 32768. Also, the sum X1 + X2 + Y1 + Y2 cannot exceed 32768.

Автор: Dexter 13.11.2002, 22:48
Не, вопрос был немного не в этом. Эти процедуры я знаю я спросил как они работают, т.е. как в принципе рисуется эллипс (да еще так быстро).

Автор: MuToGeN 13.11.2002, 23:11
насколько я понял тот алгоритм без тригонометрии, то
Код
int i,j,x,y;
int radius=радиус;
int xCenter=центр по X;
int yCenter=центр по Y;
for(i=xCenter-radius;i<xCenter+radius;i++)
 for(j=yCenter-radius;j<yCenter+radius;j++)
 {
   x=i-xCenter;
   y=j-yCenter;
   if(abs(x*x+y*y-radius*radius)<0.1)
     Canvas.Pixels[i][j]=clBlack;
 }
типа того?

еще такой вопрос появился - как нарисовать эллипс, вытянутый (сжатый) не парралельно осям, а например по прямой y=x?

Автор: Chingachguk 14.11.2002, 01:23
Цитата

MuToGeN Дата сообщения: 13.11.2002,15:11
{...}
типа того?


Ага ;)

Цитата

еще такой вопрос появился - как нарисовать эллипс, вытянутый (сжатый) не парралельно осям, а например по прямой y=x?


В смысле - повернутый на угол относительно осей ? Подумаю об этом ;)

Автор: MuToGeN 14.11.2002, 02:30
Цитата(Chingachguk @ 13.11.2002, 17:23)
В смысле - повернутый на угол относительно осей ?

во-во :) вопрос не принципиальный, просто интересно

Автор: neutrino 14.11.2002, 02:38
А нельзя использовать формулы поворота с тригонометрией?
2Chingachguk: А прогу я компилил сначала на VС а потом на ВС. Что-то я наглючился так, что потом на екзамене по SQL писал всякие сдвиги таблиц :)

Автор: MuToGeN 14.11.2002, 02:43
Цитата(neutrino @ 13.11.2002, 18:38)
А нельзя использовать формулы поворота с тригонометрией?

IMHO с целочисленными матрицами оно как-то не так будет

Автор: Dexter 14.11.2002, 23:12
2 исходника которые давал MuToGeN работают, но в первом чем больше радиус тем дальше точки друг от друга, во втором он мне рисует вообще точек 10.

Автор: MuToGeN 14.11.2002, 23:35
Цитата(Dexter @ 14.11.2002, 15:12)
в первом чем больше радиус тем дальше точки друг от друга, во втором он мне рисует вообще точек 10.

в первом тебе надо уменьшить шаг в цикле, во втором - в строке
Код
if(abs(x*x+y*y-radius*radius)<0.1)
0.1 заменяешь на нечто более убедительное, например, на 5 или 10 или 15 (чем больше, тем шире будет линия). 0.1 делать было вообще тупо (вина моя), т.к. x, y и радиус целочисленные и дробям там взяться вообще неоткуда.

Автор: Chingachguk 17.11.2002, 02:25
Цитата

neutrino Дата сообщения: 13.11.2002,18:38
А нельзя использовать формулы поворота с тригонометрией?
2Chingachguk: А прогу я компилил сначала на VС а потом на ВС. Что-то я наглючился так, что потом на екзамене по SQL писал всякие сдвиги таблиц  


Как говорят китайцы, дорога в тысячу миль начинается с 1 шага ;)))

Там есть прикольный барьер, не знаю, налетел ли ты на него ...

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