Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Assembler

6.4K
03 февраля 2004 года
ReichsFurherSS
3 / / 03.02.2004
Help.
Нужно нарисовать в Tasm'e 16bit круг, при наличие радиуса и координат.
перепробовал всё... есть только одна формула у меня r**2=(x-a)**2+(y-b)**2
Кто знает, прошу помощи.

А и ешё нужно нарисовать квадрат и заставить его крутиться.
Квадрат нарисовать могу, сделать Delay тоже а вот крутиться, только на 90 градусов...

Спасибо заранее =)
2.6K
05 февраля 2004 года
Hearse
89 / / 19.01.2004
Приблизительно так:

Круг можно рисовать алгоритмом Брезенхема для генерации окружностей.
Квадрат - перенести так, чтобы центр был в начале координат, потом перевести координаты вершин в полярные, добавить угол поворота, потом опять в декартовы координаты, перенести на исходную позицию и нарисовать четыре линии.
314
06 февраля 2004 года
fanto
374 / / 15.02.2003
Так в чем проблема: в круге или в графике из-под АСМа?
6.5K
07 февраля 2004 года
Retran
5 / / 01.02.2004
Окружность:

x = cos(a)*r + x0
y = sin(a)*r + y0,
где a - угол поворота (менять в цикле от 0 до 2*Pi), r - радиус, x0,y0 - координаты центра окружности.
6.4K
08 февраля 2004 года
ReichsFurherSS
3 / / 03.02.2004
Цитата:
Originally posted by Retran
Окружность:

x = cos(a)*r + x0
y = sin(a)*r + y0,
где a - угол поворота (менять в цикле от 0 до 2*Pi), r - радиус, x0,y0 - координаты центра окружности.




Проблема в том что я не знаю как в assem'e вычислить косинус и синус угла...


fanto: в круге под асм

537
13 февраля 2004 года
Cover
87 / / 14.11.2002
Цитата:
Originally posted by ReichsFurherSS



Проблема в том что я не знаю как в assem'e вычислить косинус и синус угла...


fanto: в круге под асм



Синус и косинус на ассемблере знать и не надо (в этом случае). Делается это так:
Составляется таблица синусов для углов (0-90) на Си++, например. Все остальные углы другие функции (косинус, тангес и пр.) можно посчитать, юзая учебник по Алгебре за 9 класс - формулы приведения, кажется, т.е.: sin(-PI/2) = -sin(PI/2); cos(alpha) = sin(PI/2-alpha) или че-то в этом роде.

Вобще круг можно нарисовать более простым способом (я где-то видел), но сейчас под рукой у меня этой книги (где описан простой способ) нету. Дойду до дома, может напишу. Но этого (таблицы синусов) вполне достаточно - когда я этой задачей забивал себе голову первый раз, так и делал.

537
17 февраля 2004 года
Cover
87 / / 14.11.2002
Книжку я не нашёл - видать она не моя была. Но я малость по думал и вот что придумал:

Вспомним, как рисуется прямая линия - там у нас есть dx и dy, отношение которых показывает, сколько нужно пройти точек по одной оси, чтобы по другой оси пройти всего лишь одну точку.
Так же и с кругом.
Для того, чтобы нарисовать круг, достаточно нарисовать дугу (угол дуги - 90 градусов), допустим от (x0,y0-R) до (x0+R,y0), где (x0, y0) - центр круга, а R - радиус.
Подготовка.
Бирём за начальную точку - (x0,y0-R).
Мы знаем, что двигаться мы будем вправо-вниз, рисуя точки либо справа (относительно текущей), либо снизу (точек справа-снизу мы ставить не буем).
Таким образом на каждом шаге у нас есть выбор из двух вариантов (пойти вниз или вправо). Чтобы выбрать один из вариантов, будет для каждого из них определять на сколько будующая точка будет отстаять от центра круга - соответственно, та точка, для которой это расстояние ближе к R, ту мы и рисуем.
Как определить расстояние до точки?
1) s = sqrt((X0-X)**2 + (Y0-Y)**2) - ясное дело, что для Ассемблера это не катит
2) Т.к. растояние мы сравниваем с радиусом, мы получаем первое упращение: s**2 = (X0-X)**2 + (Y0-Y)** - эту байду мы будем сравнивать не с радиусом, а с R**2 (который считается только однажды).
Возводить в квадрат всё, что двигается нам тоже не в кайф, поэтому думаем дальше.
Пусть Mx = (X-X0)**2, а Sx = (X-X0), тогда, если то же проделать и с Y-ком, то мы получим: s**2 = Mx+My - проще только "NOP". Так вот именно Mx+My для нижней и для правой точек мы и будет сравнивать с уже посчитанным (вначале программы) R**2. Как определить для точки Mx и My, и для чего у нас Sx и Sy???
Т.к. умножать и делить мы не хотим (по крайней мере я не хочу - у меня с детства боязнь к операциям умножения на асме), будем думать, как можно обойтись только сложением и вычитанием (ну и может ещё чем простым).
Зная Mx и Sx для текущей точки, как узнать их для правой и нижней точек? Очень просто.
Для правой точки: Sx = Sx+1, Mx* = (Sx+1)**2 = Sx**2 + 2*Sx + 1 = Mx + 2*Sx +1 (для тех, кто изучает ассемблер самостоятельно без книжки и компьютера: чтобы умножить число на степень двойки, нужно "сдвинуть" его влево на эту самую степень, т.е. X*2 <=> SHL X,1).
То же и для нижней точки: My* = My + 2*Sy + 1.
Мы получили два выражения, из которых нужно выбрать то, значение которого по модулю меньше:
Точка справа: (Mx + 2*Sx + 1) + My - R**2 = Mx* + My - R**2
Точка снизу: Mx + (My + 2*Sy + 1) - R**2 = Mx + My* - R**2

Реализация:
1) При инициализации мы находим Mx, My, 2*Sx, 2*Sy, R**2 для точки (X0, Y0-R)
2) На каждой итерации мы считаем:
Mx*, My* по формуле "Mi* = Mi + 2*Si + 1";
abs(sr), abs(sb) - разница между квадратом расстояния до правой или нижней точки (соответственно) и квадратом радиуса взятая по модулю.
Сравнить abs(sr) и abs(sb):
Если abs(sr) меньше, то Mx = Mx*, 2*Sx = 2*Sx+2 (для тех же самоучек, сложение с двойкой выполняется медленнее двух увеличений на 1 - на асме две команды "INC"), x = x+1.
Если abs(sb) меньше, то My = My*, 2*Sy = 2*Sy+2, y = y+1.
3) Цикл повторяется, пока x<=(x0+R) и y<=(y0) (В принципе, на том же асме, проще будет следить только за одной координатой).

Кстати, на Си рисование круга выглядет гораздо красивей, в то время, как код прогаммы не будет ни медленнее, ни длиннее.

После того, как всё это написал, ещё малость подумал и понял, что в той книжке, скорее всего так и было - там алгоритм не объяснялся - только код с комментариями был, в котором я нифига не поня, но понял, что умножений и делений нету.
Так что даже не знаю, сам я придумал этот способ или он у меня в подсознании сохранился, когда я книжку смотрел, а сейчас в сознании реализовался :D .


Что касается квадрата, то это делается с помощью матриц поворота - для каждой вершины многоугольника расчитываются новые координаты используя матрицу поворота. На асме могу только посоветовать сделать функцию рисования квадрата по вершинам (придется сделать ещё функцию рисования линии), затем для каждой вершины расчитывать координаты использую таблицу синусов: x* = cos(alpha)*L; y = sin(alpha)*L, где L - расстояние от центра поворота до текущей вершины, alpha - угол поворота. Естественно тут тоже можно всё упростить, но лучше подобным заниматься на Си.
6.4K
22 февраля 2004 года
ReichsFurherSS
3 / / 03.02.2004
Цитата:
Originally posted by Cover
Книжку я не нашёл - видать она не моя была. Но я малость по думал и вот что придумал:

Вспомним, как рисуется прямая линия - там у нас есть dx и dy, отношение которых показывает, сколько нужно пройти точек по одной оси, чтобы по другой оси пройти всего лишь одну точку.
Так же и с кругом.
Для того, чтобы нарисовать круг, достаточно нарисовать дугу (угол дуги - 90 градусов), допустим от (x0,y0-R) до (x0+R,y0), где (x0, y0) - центр круга, а R - радиус.
Подготовка.
Бирём за начальную точку - (x0,y0-R).
Мы знаем, что двигаться мы будем вправо-вниз, рисуя точки либо справа (относительно текущей), либо снизу (точек справа-снизу мы ставить не буем).
Таким образом на каждом шаге у нас есть выбор из двух вариантов (пойти вниз или вправо). Чтобы выбрать один из вариантов, будет для каждого из них определять на сколько будующая точка будет отстаять от центра круга - соответственно, та точка, для которой это расстояние ближе к R, ту мы и рисуем.
Как определить расстояние до точки?
1) s = sqrt((X0-X)**2 + (Y0-Y)**2) - ясное дело, что для Ассемблера это не катит
2) Т.к. растояние мы сравниваем с радиусом, мы получаем первое упращение: s**2 = (X0-X)**2 + (Y0-Y)** - эту байду мы будем сравнивать не с радиусом, а с R**2 (который считается только однажды).
Возводить в квадрат всё, что двигается нам тоже не в кайф, поэтому думаем дальше.
Пусть Mx = (X-X0)**2, а Sx = (X-X0), тогда, если то же проделать и с Y-ком, то мы получим: s**2 = Mx+My - проще только "NOP". Так вот именно Mx+My для нижней и для правой точек мы и будет сравнивать с уже посчитанным (вначале программы) R**2. Как определить для точки Mx и My, и для чего у нас Sx и Sy???
Т.к. умножать и делить мы не хотим (по крайней мере я не хочу - у меня с детства боязнь к операциям умножения на асме), будем думать, как можно обойтись только сложением и вычитанием (ну и может ещё чем простым).
Зная Mx и Sx для текущей точки, как узнать их для правой и нижней точек? Очень просто.
Для правой точки: Sx = Sx+1, Mx* = (Sx+1)**2 = Sx**2 + 2*Sx + 1 = Mx + 2*Sx +1 (для тех, кто изучает ассемблер самостоятельно без книжки и компьютера: чтобы умножить число на степень двойки, нужно "сдвинуть" его влево на эту самую степень, т.е. X*2 <=> SHL X,1).
То же и для нижней точки: My* = My + 2*Sy + 1.
Мы получили два выражения, из которых нужно выбрать то, значение которого по модулю меньше:
Точка справа: (Mx + 2*Sx + 1) + My - R**2 = Mx* + My - R**2
Точка снизу: Mx + (My + 2*Sy + 1) - R**2 = Mx + My* - R**2

Реализация:
1) При инициализации мы находим Mx, My, 2*Sx, 2*Sy, R**2 для точки (X0, Y0-R)
2) На каждой итерации мы считаем:
Mx*, My* по формуле "Mi* = Mi + 2*Si + 1";
abs(sr), abs(sb) - разница между квадратом расстояния до правой или нижней точки (соответственно) и квадратом радиуса взятая по модулю.
Сравнить abs(sr) и abs(sb):
Если abs(sr) меньше, то Mx = Mx*, 2*Sx = 2*Sx+2 (для тех же самоучек, сложение с двойкой выполняется медленнее двух увеличений на 1 - на асме две команды "INC"), x = x+1.
Если abs(sb) меньше, то My = My*, 2*Sy = 2*Sy+2, y = y+1.
3) Цикл повторяется, пока x<=(x0+R) и y<=(y0) (В принципе, на том же асме, проще будет следить только за одной координатой).

Кстати, на Си рисование круга выглядет гораздо красивей, в то время, как код прогаммы не будет ни медленнее, ни длиннее.

После того, как всё это написал, ещё малость подумал и понял, что в той книжке, скорее всего так и было - там алгоритм не объяснялся - только код с комментариями был, в котором я нифига не поня, но понял, что умножений и делений нету.
Так что даже не знаю, сам я придумал этот способ или он у меня в подсознании сохранился, когда я книжку смотрел, а сейчас в сознании реализовался :D .


Что касается квадрата, то это делается с помощью матриц поворота - для каждой вершины многоугольника расчитываются новые координаты используя матрицу поворота. На асме могу только посоветовать сделать функцию рисования квадрата по вершинам (придется сделать ещё функцию рисования линии), затем для каждой вершины расчитывать координаты использую таблицу синусов: x* = cos(alpha)*L; y = sin(alpha)*L, где L - расстояние от центра поворота до текущей вершины, alpha - угол поворота. Естественно тут тоже можно всё упростить, но лучше подобным заниматься на Си.





спасибо!

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог