Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
современный фортран , Бортеньев.pdf
Скачиваний:
272
Добавлен:
26.03.2015
Размер:
2.34 Mб
Скачать

6. Встроенные процедуры

выполняется начиная с самого правого бита, номер которого равен нулю. Параметры from, frompos, len и topos имеют целый тип и вид связи IN: to - параметр целого типа с видом связи INOUT. Параметры должны удовлетворять условиям: len 0, frompos + len BIT_SIZE(from), frompos 0, topos 0, topos + len BIT_SIZE(to). Параметры from и to должны иметь одну разновидность типа. В качестве from и to можно использовать одну и ту же переменную.

Пример:

integer(1) :: iso = 13 integer(1) :: tar = 6

call mvbits(iso, 2, 2, tar, 0)

!2#00001101

!2#00000110

!Возвращает tar = 00000111

6.14.4. Пример использования битовых функций

Достаточно часто поразрядные операции находят применение в программах машинной графики. Рассмотрим в качестве примера применяемый в машинной графике для решения задачи отсечения алгоритм Сазерленда - Кохена. Задача отсечения заключается в удалении элементов изображения, лежащих вне заданной границы (рис. 6.2). Возьмем задачу, в которой границей области является прямоугольник, который далее мы будем называть окном вывода. Задача отсечения многократно решается при работе с изображением для большого числа отрезков, поэтому важно, чтобы алгоритм ее решения обладал высоким быстродействием.

В машинной графике экран монитора отображается на растровую плоскость, размеры которой зависят от возможностей видеоадаптера и монитора. Координаты на растровой плоскости целочисленные. Учитывая обеспечиваемое видеоадаптерами разрешение, например 800 * 600 или 1024 * 768 пикселей, для координат используется тип INTEGER(2).

В алгоритме Сазерленда - Кохена взаимное расположение отрезка и окна вывода определяется так. Окно вывода разбивает своими сторонами и их продолжениями растровую плоскость на 9 областей.

Установим для каждой области 4-битовый код (рис. 6.2), в котором:

единица в бите 0 означает, что точка лежит ниже окна вывода;

единица в бите 1 означает, что точка лежит правее окна вывода;

единица в бите 2 означает, что точка лежит выше окна вывода;

единица в бите 3 означает, что точка лежит левее окна вывода.

Пусть 1 и 2 - номера вершин отрезка; c1 и c2 - коды областей

расположения соответственно первой и второй вершины. XL, XR, YB, YT - координаты границ окна вывода. Очевидно, что

отрезок расположен внутри окна, если IOR(c1, c2) возвращает 0;

отрезок не пересекает окно, если IAND(c1, c2) > 0;

отрезок может пересекать окно, если IAND(c1, c2) возвращает 0

и IOR(c1, c2) > 0.

195

О. В. Бартеньев. Современный ФОРТРАН

y

 

 

1100

0100

0110

YT

 

 

1000

0000

0010

 

 

YB

 

 

1001

0001

0011

 

 

x

 

XL

XR

 

а

б

Рис. 6.2. Задача отсечения: а - коды областей; б - решение задачи отсечения

Для сокращения кода программы сначала выполним все отсечения для вершины 1, а затем поменяем вершины 1 и 2 местами (вершине 2 дадим номер 1; вершине 1 - номер 2) и вновь продолжим исследование вершины 1.

Алгоритм: Интерфейс:

Входные данные:

XL, XR - x-координаты правой и левой границ окна вывода; YB, YT - y-координаты нижней и верхней границ окна вывода; x1, y1 и x2, y2 - координаты вершин отрезка.

Выходные данные:

x1, y1 и x2, y2 - координаты вершин усеченного отрезка (или исходного, если отрезок целиком принадлежит окну вывода) после решения задачи отсечения. В случае расположения отрезка вне окна вывода выведем сообщение "Отрезок вне окна".

Промежуточные данные:

c1, c2 - коды областей расположения первой и второй вершин отрезка; x1, y1 и x2, y2 - координаты вершин отрезка на линиях отсечения;

fl - есть истина, если выполнен обмен вершинами 1 и 2.

Алгоритм:

1°. Начало.

2°. Вычислить c1, c2.

3°. Если отрезок может пересекать окно вывода, то перейти к п. 4°, иначе перейти к п. 6° (все отсечения для c1 выполнены).

4°. Если c1 равен нулю, то поменять местами вершины 1 и 2. 5°. Найти линию отсечения, с которой пересекается отрезок 1, и перенести вершину 1 в точку пересечения отрезка и линии

отсечения; вычислить c1 и перейти к п. 3°.

196

6. Встроенные процедуры

6°. Если IOR(c1, C2) = 0, то отрезок внутри окна; вывести x1, y1, x2, y2, иначе отрезок вне окна.

7°. Конец.

Программа содержит две процедуры: подпрограмму swap - обмена значениями переменных - и функцию code, возвращающую код области расположения вершины отрезка.

program clip

! Текст программы отсечения

integer(2) :: XL = 15, XR = 60, YB = 15, YT = 60

integer(2) :: x1 = 10, y1 = 10, x2 = 65, y2 = 65

integer(2) c1, c2, code

 

logical :: fl = .false.

 

c1 = code(x1, y1, XL, XR, YB, YT)

 

c2 = code(x2, y2, XL, XR, YB, YT)

 

do while(iand(c1, c2) == 0 .and. ior(c1, c2) > 0)

if(c1 == 0) then

 

fl = .not. fl

! Обмен вершин отрезка

call swap(x1, x2); call swap(y1, y2);

call swap(c1, c2)

end if

 

if(x1 < XL) then

! Отсечение слева

y1

= y1 + dfloat(y2 - y1) * dfloat(XL - x1) / dfloat(x2 - x1)

x1

= XL

 

else if(y1 < YB) then

! Отсечение снизу

x1

= x1 + dfloat(x2 - x1) * dfloat(YB - y1) / dfloat(y2 - y1)

y1

= YB

 

else if(x1 > XR) then

! Отсечение справа

y1

= y1 + dfloat(y2 - y1) * dfloat(XR - x1) / dfloat(x2 - x1)

x1

= XR

 

else if(y1 > YT) then

! Отсечение сверху

x1

= x1 + dfloat(x2 - x1) * dfloat(YT - y1) / dfloat(y2 - y1)

y1

= YT

 

end if

 

c1 = code(x1, y1, XL, XR, YB, YT)

! Код вершины 2 не изменился

end do

 

if(fl) then

! Обмен вершин отрезка

call swap(x1, x2)

! Восстанавливаем прежний порядок

call swap(y1, y2)

! вершин

call swap(c1, c2)

 

end if

 

if(ior(c1, c2) == 0) then

! x1, y1: 15, 15; x2, y2: 60, 60

write(*, 1) x1, y1, x2, y2

else

write(*, *) 'Отрезок вне окна вывода' end if

1 format(' x1, y1:', i4, ',', i4, '; x2, y2:', i4, ',', i4) end program clip

197