Новосибирский Государственный Технический Университет. Факультет автоматики и вычислительной техники Кафедра вычислительной техники (специальность 220100). учебное пособие

Вид материалаУчебное пособие
0.18.2  V_SetRclip - установить прямоугольник отсечения
0.18.3  V_GetRclip - опросить прямоугольник отсечения
0.18.4  V_CSclip - отсечение Коэна-Сазерленда
Подобный материал:
1   ...   36   37   38   39   40   41   42   43   44

0.18.2  V_SetRclip - установить прямоугольник отсечения


/*------------------------------------------------- V_SetRclip

* Устанавливает прямоугольное окно отсечения

* Возвращает 0/1 - нет/есть ошибки в задании окна

*/

int V_SetRclip (xleft, ybottom, xright, ytop)

float xleft, ybottom, xright, ytop;

{ int otw;

otw= 0;

if (xleft >= xright || ybottom >= ytop) ++otw; else {

Windn= 4;

Windx= Wxrect; Windy= Wyrect; /* Вершины */

Wxlef= Wxrect[0]= Wxrect[1]= xleft;

Wybot= Wyrect[0]= Wyrect[3]= ybottom;

Wxrig= Wxrect[2]= Wxrect[3]= xright;

Wytop= Wyrect[1]= Wyrect[2]= ytop;

Wnormx= WxNrec; Wnormy= WyNrec; /* Нормали */

WxNrec[0]= 1; WyNrec[0]= 0;

WxNrec[1]= 0; WyNrec[1]= -1;

WxNrec[2]= -1; WyNrec[2]= 0;

WxNrec[3]= 0; WyNrec[3]= 1;

}

return (otw);

} /* V_SetRclip */


0.18.3  V_GetRclip - опросить прямоугольник отсечения


/*------------------------------------------------- V_GetRclip

* Возвращает текущее прямоугольное окно отсечения

*/

void V_GetRclip (xleft, ybottom, xright, ytop)

float *xleft, *ybottom, *xright, *ytop;

{

*xleft= Wxlef; *ybottom= Wybot;

*xright= Wxrig; *ytop= Wytop;

} /* V_GetRclip */


0.18.4  V_CSclip - отсечение Коэна-Сазерленда


/*--------------------------------------------------- V_CSclip

* Реализует алгоритм отсечения Коэна-Сазерленда с

* кодированием концов отсекаемого отрезка

*

* int V_CSclip (float *x0, float *y0, float *x1, float *y1)

*

* Отсекает отрезок, заданный значениями координат его

* точек (x0,y0), (x1,y1), по окну отсечения, заданному

* глобальными скалярами Wxlef, Wybot, Wxrig, Wytop

*

* Конечным точкам отрезка приписываются коды,

* характеризующие его положение относительно окна отсечения

* по правилу:

*

* 1001 | 1000 | 1010

* -----|------|-----

* | Окно |

* 0001 | 0000 | 0010

* -----|------|-----

* 0101 | 0100 | 0110

*

* Отрезок целиком видим если оба его конца имеют коды 0000

* Если логическое И кодов концов не равно 0, то отрезок

* целиком вне окна и он просто отбрасывается.

* Если же результат этой операции = 0, то отрезок

* подозрительный. Он может быть и вне и пересекать окно.

* Для подозрительных отрезков определяются координаты их

* пересечений с теми сторонами, с которыми они могли бы

* пересечься в соответствии с кодами концов.

* При этом используется горизонтальность и вертикальность

* сторон окна, что позволяет определить одну из координат

* без вычислений.

* Часть отрезка, оставшаяся за окном отбрасывается.

* Оставшаяся часть отрезка проверяется на возможность его

* принятия или отбрасывания целиком. Если это невозможно,

* то процесс повторяется для другой стороны окна.

* На каждом цикле вычислений конечная точка отрезка,

* выходившая за окно, заменяется на точку, лежащую или на

* стороне окна или его продолжении.

*

* Вспомогательная процедура Code вычисляет код положения

* для конца отрезка.

*

*/


static float CSxn, CSyn; /* Координаты начала отрезка */


static int CScode (void) /* Определяет код точки xn, yn */

{ register int i;

i= 0;

if (CSxn < Wxlef) ++i; else

if (CSxn > Wxrig) i+= 2;

if (CSyn < Wybot) i+= 4; else

if (CSyn > Wytop) i+= 8;

return (i);

} /* CScode */


int V_CSclip (x0, y0, x1, y1)

float *x0, *y0, *x1, *y1;

{

float CSxk, CSyk; /* Координаты конца отрезка */

int cn, ck, /* Коды концов отрезка */

visible, /* 0/1 - не видим/видим*/

ii, s; /* Рабочие переменные */

float dx, dy, /* Приращения координат*/

dxdy,dydx, /* Наклоны отрезка к сторонам */

r; /* Рабочая переменная */


CSxk= *x1; CSyk= *y1;

CSxn= *x1; CSyn= *y1; ck= CScode ();

CSxn= *x0; CSyn= *y0; cn= CScode ();


/* Определение приращений координат и наклонов отрезка

* к осям. Заодно сразу на построение передается отрезок,

* состоящий из единственной точки, попавшей в окно

*/

dx= CSxk - CSxn;

dy= CSyk - CSyn;

if (dx != 0) dydx= dy / dx; else {

if (dy == 0) {

if (cn==0 && ck==0) goto out; else goto all;

}

}

if (dy != 0) dxdy= dx / dy;


/* Основной цикл отсечения */

visible= 0; ii= 4;

do {

if (cn & ck) break; /* Целиком вне окна */

if (cn == 0 && ck == 0) { /* Целиком внутри окна */

++visible; break;

}

if (!cn) { /* Если Pn внутри окна, то */

s= cn; cn= ck; ck= s; /* перестить точки Pn,Pk и */

r=CSxn; CSxn=CSxk; CSxk=r; /* их коды, чтобы Pn */

r=CSyn; CSyn=CSyk; CSyk=r; /* оказалась вне окна */

}

/* Теперь отрезок разделяется. Pn помещается в точку

* пересечения отрезка со стороной окна.

*/

if (cn & 1) { /* Пересечение с левой стороной */

CSyn= CSyn + dydx * (Wxlef-CSxn);

CSxn= Wxlef;

} else if (cn & 2) { /* Пересечение с правой стороной*/

CSyn= CSyn + dydx * (Wxrig-CSxn);

CSxn= Wxrig;

} else if (cn & 4) { /* Пересечение в нижней стороной*/

CSxn= CSxn + dxdy * (Wybot-CSyn);

CSyn= Wybot;

} else if (cn & 8) { /*Пересечение с верхней стороной*/

CSxn= CSxn + dxdy * (Wytop-CSyn);

CSyn= Wytop;

}

cn= CScode (); /* Перевычисление кода точки Pn */

} while (--ii >= 0);

if (visible) {

out: *x0= CSxn; *y0= CSyn;

*x1= CSxk; *y1= CSyk;

}

all:

return (visible);

} /* V_CSclip */