------------------------------------------
Disabler/DPL
Полярные координаты
(Всё, что Вы ещё не знаете, или
боялись знать!)
l.Введение
Для начала, сообщу вам, что если вы
продвинутый кодер, то, возможно, всё
нижеизложенное покажеться примитивным и
бессмысленным, но эта статья расчитанна в
первую очередь на новичков в демостроении,
имеющих некоторые знания o геометрии и
ассемблере.
Итак, что такое полярные координаты? Это
один из способов представления плоскости.
Для простоты будем рассматривать двумерную
плоскость. Из геометрии вы (надеюсь)
знаете, что точка, в двумерном
пространстве имеет две координаты - X и Y,
которые являются смещением от начала
координат. Но это не всегда. Так точка
представляется только в декартoвoй системе
координат. Однако существует ещё, как
минимум одна система координат - пoлярная.
B полярной системе координат точка
задаётся не двумя координатами, а длинной
вектора на котором находится точка (Q) и
углом поворота относительно оси OX (Р).
И вот тут назревает вопрос: А на..я это
надо? Дело вот в чём: например вам надо
повернуть точку A с координатами X,Y на
угол равный L.
При использовании декартoвoй системы
координат вы вычисляете:
X' = X * cos L - Y * sin L
Y' = X * sin L + Y * cos L
где X` и Y` - новые координаты, но с точки
зрения программирования этот фрагмент
можно оптимизировать:
SL = sin L
CL = cos L
X' = X * CL - Y * SL
Y' = X * SL + Y * CL
здесь мы экономим время вычисления на
однократном вычислении синуса и косинуса,
которые можно вычислять даже на обычном
калькуляторе (Маде ин Жапан) путём
двойного умножения, но это тема другой
статьи. Да, чуть не забыл, ещё можно
вычислять через "пoлинoм Чебышева" или
как бесконечный ряд, но, как говориться, в
другой раз.
Итак, вернёмся к нашему примеру. B
полярной системе координат теже действия
можно осуществить, следующим образом:
Q' = Q
P' = P + L
Ну, как, проще? А это только начало!
Например, имеем квадрат (четыре точки) с
центром в начале координат и нам надо
увеличить его на какой-либо коэффициент М
и повернуть на угол L.
B декартoвoй системе координат:
SL = sin L
CL = cos L
Xv = X + M; временные преременные
Yv = X + M
X' = Xv * CL - Yv * SL
Y' = Xv * SL + Yv * CL
Чувствуете масштаб вычислений? А теперь
берём пoлярныю систему и получаем:
Q' = Q + M
P' = P + L
Назревает oчередний вопрос: Если всё так
просто, то почему все не пользуются
полярной системой координат? А дело в том,
что многие пользуются, но не знают, как
это называется, а так-же то, что
большенство сложных объектов проще
представлять в декартoвoй системе и
выводить на экран тоже проще в декартoвoй
системе.
Но, как говориться, не всё так сложно,
как может показаться, особенно из ассм`а.
Я не буду долго распинаться и грузить
вас и себя тоже нудным выводом формул, а
сразу приведу готовые. Чтобы поставить
точку по полярным кooрдинарам есть
формула:
X = Q * cos P
Y = Q * sin P
А если надо переверсти наоборот декартoвые
координаты в полярные - поможет формула:
_______
P=/X*X+Y*Y
Q=arctg (Y/X)
Я искренне надеюсь, что вы НИКОГДА не
будете пользоваться этими формулами,
потому что использование их из ассм`а
весьма затруднительно, особенно для
перевода из декартовых в полярные
координаты.
2.Использование в ассм'е
Для начала нам (не нам, а вам!) нужно
уметь "зафoрмить" таблицу синуса, которая
по совместительству будет таблицей
косинуса. И тут нам поможет всеми
"любимый" Basic`48. Входим и набираем
следующее:
l0 Let adr=32768
20 Let atplit=64
30 For x=-Pi то Pi Step Pi/l28
40 Let sinx=l28 + atplit * Sin x
S0 Роке adr,sinx
60 Let adr=adr + l
70 Next x
80 Rand Usr lSбl9: Ret:
Save "sin" Code 32768,2S6
Данная прога зафoрмит и coxpohut на
диске файлик "sin", внутри которого лежит
один период синуса с амплитудой от -64 до
+64 и поднятый относительно оси OX на 128,
т. е. реальные значения будут от 64 до
192. Если вы не поняли: зачем это надо?
Поясняю - в ассм`е работать со знаковыми
числами неоправданно сложно, да нам это и
не надо.
B дальнейшем нам потребуется таблица
таблиц синуса, т. е. 64 таблицы синуса с
амплитудой от -1 до +1,..., от -64 до +64.
Размер каждой таблицы - 256 байт. Это
нужно для того чтобы при загрузке по
"ровному" шестнадцатиричнoму адресу (адрес
у которого младший байт равен нулю,
например: #6000, #7800 и т. д.) каждая
пoдтаблица, так же, разпoлoгалась с
ровного адреса.
Итак, есть таблица, есть ассм. Остаётся
всё это закодить :).
Грузим XAS и набираем нечто для вывода и
поворота на заданный угол четырёх точек:
;-----------------------------------------
; Поворот на угол "angle" при переменной P
; равной константе (64)
pointz equ 4; Количество точек
org #6000
sinus lcode "sin"; Грузим таблицу
ent; Вот и начало!
ld hl,#4000; Очищаем экран
ld d,h
ld e,l
inc e
ld (hl),l
ld ьс,6l44
ldir
ld (hl),7l
ld ьс,767
ldir
call view; Выводим точки
sleep хог a; Ждём нажатия любой кнопки
in a,#fe; после чего вываливаемся
cpl; отсюда!
and 3l
jr z,sleep
ret; Выход!
view ld a,(angle)
ld с,a
ld b,pointz
; c = угол поворота
; b = количество точек
ld hl,table
viewl push ьс,hl
ld a,(hl)
add a,с
ld h,sinus&h; берём старший байт
; адреса таблицы
ld l,a
ld e,(hl)
; выбераем первую координату
add a,64
; увеличиваем "a" на 64, что равнозначно
; переходу от синуса к косинусу, т.е.
; cos x = sin (x + pi/2), а в данном
; случае pi/2 = 64, или четверть таблицы
; синуса
ld l,a
ld a,(hl)
ld с,a
ld a,e
; выбераем вторую координату
call pixel; ставим точку
pop hl,ьс
inc hl
; переходим к следующей точке
djnz viewl
ret
; процедура точки, тормозная но маленькая
pixel call 8880
add a,a
add a,a
add a,a
ld b,a
ld a,#fe
sub b
ld (pixell+l),a
pixell set 0,(hl)
ret
angle db 0; угол поворота (0..255)
table db 0,64,l28,l92
; таблица углов "Q"
; ANGLEassm = (256 * ANGLEreal) / 360
А теперь прога, которая пoварачивает на
заданный угол и одновременно увеличивает
"квадрат". Файл "sin2" - набор таблиц
синуса (см. выше).
;-----------------------------------------
; Поворот на угол "angle" и
; масштабирование на заданный коэффициент
pointz equ 4; Количество точек
org #6000
sinus lcode "sin2"; Грузим таблицу
ent; Вот и начало!
ld hl,#4000; Очищаем экран
ld d,h
ld e,l
inc e
ld (hl),l
ld ьс,6l44
ldir
ld (hl),7l
ld ьс,767
ldir
call view; Выводим точки
sleep хог a; Ждём нажатия любой кнопки
in a,#fe; после чего вываливаемся
cpl; отсюда!
and 3l
jr z,sleep
ret; Выход!
view ld a,(angle)
ld с,a
ld b,pointz
; c = угол поворота
; b = количество точек
ld hl,table
viewl push ьс,hl
ld a,(hl)
add a,с
ld с,a
inc hl
ld a,(tagnif)
add a,(hl)
add a,sinus&h; берём старший байт
ld h,a; адреса таблицы
ld l,с
ld e,(hl)
; выбераем первую координату
ld a,с
add a,64
; увеличиваем "a" на 64, что равнозначно
; переходу от синуса к косинусу, т.е.
; cos x = sin (x + pi/2), а в данном
; случае pi/2 = 64, или четверть таблицы
; синуса
ld l,a
ld a,(hl)
ld с,a
ld a,e
; выбераем вторую координату
call pixel; ставим точку
pop hl,ьс
inc hl
inc hl
; переходим к следующей точке
djnz viewl
ret
; процедура точки, тормозная но маленькая
pixel call 8880
add a,a
add a,a
add a,a
ld b,a
ld a,#fe
sub b
ld (pixell+l),a
pixell set 0,(hl)
ret
angle db 0; угол поворота (0..255)
tagnif db 0; масштаб (1..64)
table db 0,l0,64,l0,l28,l0,l92,l0
; таблица углов "Q", и длинн векторов "P"
Приведённые примеры выводят на экран
четыре точки и ждут нажатия любой клавиши
для выхода. Однако, если ожидание нажатия
клавиши заменить на нижеследующее, то
получиться эффект плавного вращения.
...
loop halt
call cls_pix
call view
ld hl,angle
inc (hl)
хог a
in a,#fe
cpl
and 3l
jr z,loop
...
Где "cls_pix" - процедура стирания точек
Вот, пожалуй, и всё, что я мог поведать
вам o такой страшной вещи, как пoлярная
система координат. Если возникли вопросы
пишите на адрес редакции, ответим всем!
B следующем номере я поведаю вам o
алгоритмах быстрого вычисления функций sin
(x), cos(x), а так-же o алгоритмах
быстрого умножения, деления и возведения в
квадрат.
Other articles: