Просмотр полной версии : Клиппирование линии
есть-ли у кого-то быстрая процедура клиппирования линии для 16 и 8 битных координат?
я использую для этих целей процедуру из исходников X-Trade, предназначенную для работы с полигонами,
но это конечно-же не оптимально. я сам писать пока даже не пытался, сделаю это наверное в ближайшие дни, но в любом случае буду признателен помощи.
Понятно что жутко поздно, но я эту проблему (для себя) только сейчас решил. Может кому ещё пригодится.
В общем метод подсказал SAM style.
Суть состоит в том, чтобы разбивая исследуемую линию на два равных куска постепенно приближатся к искомому значению (заданой границе).
Вроде-бы это называется аппроксимацией...
После долгих мучений выродил я такой вот код:
APPROX
XN EQU $+1
LD HL,0
XK EQU $+1
LD DE,0
ADD HL,DE
SRA H
RR L
LD (XM),HL
YN EQU $+1
LD HL,0
YK EQU $+1
LD DE,0
ADD HL,DE
SRA H
RR L
LD (YM),HL
LD A,H
XOR B
JP P,CPHB1
LD A,H
RLA
JP CPHB2
CPHB1 SBC HL,BC
RET Z
CPHB2 JP C,APPROX2
XM EQU $+1
LD HL,0
LD (XK),HL
LD HL,(YM)
LD (YK),HL
JP APPROX
APPROX2 LD HL,(XM)
LD (XN),HL
YM EQU $+1
LD HL,0
LD (YN),HL
JP APPROX
Это подпрограммка. Вызывать её нужно так:
Сперва в XN и YN положить координаты начала отрезка.
В YK и XK - соответственно координаты конца.
В регистровую пару BC - ограничитель (ну границу экрана например)
Потом делать CALL APPROX
На выходе в XM и YM будут откорректированые коррдинаты.
Все значения 16 бит, знаковые.
Решение о том нужно ли клиппирование вообще - принимать заранее.
Ну т.е. проверять если линия вся лежит в видимой или вся в невидимой области (тогда вызывать APPROX не нужно, даже противопоказано :) )
Да, ещё! Перед вызовом нужно отсортировать координаты по возрастанию Y (чтобы XN YN были меньше чем XK YK. Т.е. "начало" всегда "сверху" - если по спековому экрану в кодах)
P.S. Можно было-бы оформить прогу и красивше, но я стремился к максимальному быстродействию. Выжал всё что смог, может быть можно и быстрей, но я не знаю как...
denpopov
09.01.2015, 12:00
Не знаю, как переваривает ассемблер, но все же привычнее писать:
YN EQU $+1
LD HL,0
YK EQU $+1
LD DE,0
так:
YN: LD HL,0
YK: LD DE,0
YN: LD HL,0
Так ведь тогда YN будет указывать на LD HL (#21), а не на #00 #00 которые идут следом.
Не, можно конечно и по-твоему, но тогда координаты загружать нужно так:
LD HL,начальный Y
LD (YN+1),HL
denpopov
09.01.2015, 12:15
Так ведь тогда YN будет указывать на LD HL (#21), а не на #00 #00 которые идут следом
тогда
LD (YM+1),HL
Warning!
Выяснилось что приведёный мной алгоритм может давать неверные результаты (при определённом разбросе координат)
Поэтому в зависимости от размеров - процедуру нужно использовать в чуть изменённом виде.
Фрагменты:
ADD HL,DE
SRA H
RR L
Следует заменить на:
LD A,H
XOR D
ADD HL,DE
JP P,$+4
CCF
RR H
RR L
Скорректированый вариант:
APPROX
XN EQU $+1
LD HL,0
XK EQU $+1
LD DE,0
LD A,H
XOR D
ADD HL,DE
JP P,$+4
CCF
RR H
RR L
LD (XM),HL
YN EQU $+1
LD HL,0
YK EQU $+1
LD DE,0
LD A,H
XOR D
ADD HL,DE
JP P,$+4
CCF
RR H
RR L
LD (YM),HL
LD A,H
XOR B
JP P,CPHB1
LD A,H
RLA
JP CPHB2
CPHB1 SBC HL,BC
RET Z
CPHB2 JP C,APPROX2
XM EQU $+1
LD HL,0
LD (XK),HL
LD HL,(YM)
LD (YK),HL
JP APPROX
APPROX2 LD HL,(XM)
LD (XN),HL
YM EQU $+1
LD HL,0
LD (YN),HL
JP APPROX
ЫЫЫ ответ нашел своего читателя, несколько дней до 10 лет недотянули)
ЫЫЫ ответ нашел своего читателя, несколько дней до 10 лет недотянули)
Круг сужается, ещё 10 лет недотянули до следующего шага - теперь матричное клиппирование (конечно уже не для реал-тайма) ну и алгоритм Робертса для полной картины :)
Создаётся десятками лет некий шедевр, а может это просто я такой тупой что требуется на изучение всего этого столько времени. Каторжный труд, однако...
Но с другой стороны - лучший отдых от мирских забот :)
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot