PDA

Просмотр полной версии : Клиппирование линии



elfh
24.01.2005, 17:51
есть-ли у кого-то быстрая процедура клиппирования линии для 16 и 8 битных координат?
я использую для этих целей процедуру из исходников X-Trade, предназначенную для работы с полигонами,
но это конечно-же не оптимально. я сам писать пока даже не пытался, сделаю это наверное в ближайшие дни, но в любом случае буду признателен помощи.

Destr
09.01.2015, 11:53
Понятно что жутко поздно, но я эту проблему (для себя) только сейчас решил. Может кому ещё пригодится.
В общем метод подсказал 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

Destr
09.01.2015, 12:09
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

Destr
12.01.2015, 19:57
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

kotsoft
12.01.2015, 23:14
ЫЫЫ ответ нашел своего читателя, несколько дней до 10 лет недотянули)

Destr
18.10.2024, 23:25
ЫЫЫ ответ нашел своего читателя, несколько дней до 10 лет недотянули)
Круг сужается, ещё 10 лет недотянули до следующего шага - теперь матричное клиппирование (конечно уже не для реал-тайма) ну и алгоритм Робертса для полной картины :)
Создаётся десятками лет некий шедевр, а может это просто я такой тупой что требуется на изучение всего этого столько времени. Каторжный труд, однако...
Но с другой стороны - лучший отдых от мирских забот :)