В данном приложении приведены процедуры, обеспечивающие выполнение отсечения по прямоугольному и многоугольному выпуклому окну и тестовая программа проверки работы процедур отсечения.
/*=================================================== V_CLIP.C * * Подрограммы, связанные с отсечением: * * V_SetPclip - установить размеры многоугольного окна * отсечения * V_SetRclip - установить размеры прямоугольного окна * отсечения * V_GetRclip - опросить размеры прямоугольного окна * отсечения * V_CSclip - отсечение по алгоритму Коэна-Сазерленда * прямоугольное окно, кодирование * концов отсекаемого отрезка * V_FCclip - отсечение по алгоритму быстрого отсечения * Алгоритм Собкова-Поспишила-Янга - * прямоугольное окно, кодирование * отсекаемого отрезка * V_LBclip - отсечение по алгоритму Лианга-Барски * прямоугольное окно, параметрическое * представление линий * V_CBclip - отсечение по алгоритму Кируса-Бека * окно - выпуклый многоугольник, * параметрическое представление линий */ /* Глобальные скаляры для алгоритмов отсечения по * прямоугольному окну - Коэна-Сазерленда, Fc-алгоритм, * Лианга-Барски */ static float Wxlef= 0.0, /* Координаты левого нижнего и */ Wybot= 0.0, /* правого верхнего углов окна */ Wxrig= 7.0, /* отсечения */ Wytop= 5.0; /* Глобальные скаляры для алгоритма Кируса-Бека * отсечения по многоугольному окну */ /* Координаты прямоугольного окна */ static float Wxrect[4]= {0.0, 0.0, 7.0, 7.0 }; static float Wyrect[4]= {0.0, 5.0, 5.0, 0.0 }; /* Перепендикуляры к сторонам прямоугольного окна */ static float WxNrec[4]= {1.0, 0.0, -1.0, 0.0 }; static float WyNrec[4]= {0.0, -1.0, 0.0, 1.0 }; /* Данные для многоугольного окна */ static int Windn=4; /* Кол-во вершин у окна */ static float *Windx= Wxrect, /* Координаты вершин окна */ *Windy= Wyrect; static float *Wnormx= WxNrec, /* Координаты нормалей */ *Wnormy= WyNrec;
/*------------------------------------------------- V_SetPclip * Устанавливает многоугольное окно отсечения * kv - количество вершин в окне * wx - X-координаты вершин * wy - Y-координаты вершин * nx - X-координаты нормалей к ребрам * ny - Y-координаты нормалей к ребрам * * Проверяет окно на выпуклость и невырожденность * * Если окно правильное, то * 1. Обновляет глобалы описания многоугольного окна: * Windn= kv; * Windx= wx; Windy= wy; --Координаты вершин окна * Wnormx= nx; Wnormy= ny; --Координаты перпендикуляров * * 2. Вычисляет координаты перепендикуляров к сторонам окна * * Возвращает: * 0 - норма * 1 - вершин менее трех * 2 - многоугольник вырожден в отрезок * 3 - многоугольник невыпуклый */ int V_SetPclip (kv, wx, wy, nx, ny) int kv; float *wx, *wy, *nx, *ny; { int ii, jj, sminus, splus, szero, otw; float r, vox, voy, /* Координаты (i-1)-й вершины */ vix, viy, /* Координаты i-й вершины */ vnx, vny; /* Координаты (i+1)-й вершины */ /* Проверка на выпуклость * для этого вычисляются векторные произведения * смежных сторон и определяется знак * если все знаки == 0 то многоугольник вырожден * если все знаки >= 0 то многоугольник выпуклый * если все знаки <= 0 то многоугольник невыпуклый */ otw= 0; if (--kv < 2) {++otw; goto all; } sminus= 0; splus= 0; szero= 0; vox= wx[kv]; voy= wy[kv]; vix= *wx; viy= *wy; ii= 0; do { if (++ii > kv) ii= 0; /* Следующая вершина */ vnx= wx[ii]; vny= wy[ii]; /* Координаты (i+1)-й */ r= (vix-vox)*(vny-viy) - /* Вект произв ребер */ (viy-voy)*(vnx-vix); /* смежных с i-й верш */ if (r < 0) ++sminus; else if (r > 0) ++splus; else ++szero; vox= vix; voy= viy; /* Обновлен координат */ vix= vnx; viy= vny; } while (ii); if (!splus && !sminus) /* Все векторные равны нулю */ {otw= 2; goto all; } /* Многоугольник вырожден */ if (splus && sminus) /* Знакопеременн. векторные */ {otw= 3; goto all; } /* Многоугольник невыпуклый */ /* Установление глобалов для правильного окна */ Windn= kv+1; /* Количество вершин у окна */ Windx= wx; Windy= wy; /* Координаты вершин окна */ Wnormx= nx; Wnormy= ny; /* Координ. перпендикуляров */ /* Вычисление координат перпендикуляров к сторонам */ vox= *wx; voy= *wy; ii= 0; do { if (++ii > kv) ii= 0; vix= wx[ii]; viy= wy[ii]; /* Текущая вершина */ vnx= viy-voy; vny= vox-vix; /* Поворот по часовой */ if (splus) { /* Внутр нормали влево */ vnx= -vnx; vny= -vny; } *nx++= vnx; *ny++= vny; vox= vix; voy= viy; /* Обновление координат */ } while (ii); all: return (otw); } /* V_SetPclip */
/*------------------------------------------------- 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 */
/*------------------------------------------------- V_GetRclip * Возвращает текущее прямоугольное окно отсечения */ void V_GetRclip (xleft, ybottom, xright, ytop) float *xleft, *ybottom, *xright, *ytop; { *xleft= Wxlef; *ybottom= Wybot; *xright= Wxrig; *ytop= Wytop; } /* V_GetRclip */
/*--------------------------------------------------- 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 */
/*--------------------------------------------------- V_FCclip * Реализует алгоритм отсечения FC (Fast Clipping) * Собкова-Поспишила-Янга, с кодированием линий * * int V_FCclip (float *x0, float *y0, float *x1, float *y1) * * Отсекает отрезок, заданный значениями координат его * точек (x0,y0), (x1,y1), по окну отсечения, заданному * глобальными скалярами Wxlef, Wybot, Wxrig, Wytop * * Возвращает: * -1 - ошибка в задании окна * 0 - отрезок не видим * 1 - отрезок видим */
static float FC_xn, FC_yn, FC_xk, FC_yk; static void Clip0_Top(void) {FC_xn= FC_xn + (FC_xk-FC_xn)*(Wytop-FC_yn)/(FC_yk-FC_yn); FC_yn= Wytop; } static void Clip0_Bottom(void) {FC_xn= FC_xn + (FC_xk-FC_xn)*(Wybot-FC_yn)/(FC_yk-FC_yn); FC_yn= Wybot; } static void Clip0_Right(void) {FC_yn= FC_yn + (FC_yk-FC_yn)*(Wxrig-FC_xn)/(FC_xk-FC_xn); FC_xn= Wxrig; } static void Clip0_Left(void) {FC_yn= FC_yn + (FC_yk-FC_yn)*(Wxlef-FC_xn)/(FC_xk-FC_xn); FC_xn= Wxlef; } static void Clip1_Top(void) {FC_xk= FC_xk + (FC_xn-FC_xk)*(Wytop-FC_yk)/(FC_yn-FC_yk); FC_yk= Wytop; } static void Clip1_Bottom(void) {FC_xk= FC_xk + (FC_xn-FC_xk)*(Wybot-FC_yk)/(FC_yn-FC_yk); FC_yk= Wybot; } static void Clip1_Right(void) {FC_yk= FC_yk + (FC_yn-FC_yk)*(Wxrig-FC_xk)/(FC_xn-FC_xk); FC_xk= Wxrig; } static void Clip1_Left(void) {FC_yk= FC_yk + (FC_yn-FC_yk)*(Wxlef-FC_xk)/(FC_xn-FC_xk); FC_xk= Wxlef; }
int V_FCclip (x0, y0, x1, y1) float *x0, *y0, *x1, *y1; { int Code= 0; int visible= 0; /* Отрезок невидим */ FC_xn= *x0; FC_yn= *y0; FC_xk= *x1; FC_yk= *y1; /* * Вычисление значения Code - кода отрезка * Биты 0-3 - для конечной точки, 4-7 - для начальной * */ if (FC_yk > Wytop) Code+= 8; else if (FC_yk < Wybot) Code+= 4; if (FC_xk > Wxrig) Code+= 2; else if (FC_xk < Wxlef) Code+= 1; if (FC_yn > Wytop) Code+= 128; else if (FC_yn < Wybot) Code+= 64; if (FC_xn > Wxrig) Code+= 32; else if (FC_xn < Wxlef) Code+= 16; /* Отсечение для каждого из 81-го случаев */ switch (Code) { /* Из центра */ case 0x00: ++visible; break; case 0x01: Clip1_Left() ; ++visible; break; case 0x02: Clip1_Right(); ++visible; break; case 0x04: Clip1_Bottom(); ++visible; break; case 0x05: Clip1_Left() ; if (FC_yk < Wybot) Clip1_Bottom(); ++visible; break; case 0x06: Clip1_Right(); if (FC_yk < Wybot) Clip1_Bottom(); ++visible; break; case 0x08: Clip1_Top(); ++visible; break; case 0x09: Clip1_Left() ; if (FC_yk > Wytop) Clip1_Top(); ++visible; break; case 0x0A: Clip1_Right(); if (FC_yk > Wytop) Clip1_Top(); ++visible; break;
/* Слева */ case 0x10: Clip0_Left(); ++visible; case 0x11: break; /* Отброшен */ case 0x12: Clip0_Left(); Clip1_Right(); ++visible; break; case 0x14: Clip0_Left(); if (FC_yn < Wybot) break; /* Отброшен */ Clip1_Bottom(); ++visible; case 0x15: break; /* Отброшен */ case 0x16: Clip0_Left(); if (FC_yn < Wybot) break; /* Отброшен */ Clip1_Bottom(); if (FC_xk > Wxrig) Clip1_Right(); ++visible; break; case 0x18: Clip0_Left(); if (FC_yn > Wytop) break; /* Отброшен */ Clip1_Top(); ++visible; case 0x19: break; /* Отброшен */ case 0x1A: Clip0_Left(); if (FC_yn > Wytop) break; /* Отброшен */ Clip1_Top(); if (FC_xk > Wxrig) Clip1_Right(); ++visible; break;
/* Справа */ case 0x20: Clip0_Right(); ++visible; break; case 0x21: Clip0_Right(); Clip1_Left(); ++visible; case 0x22: break; /* Отброшен */ case 0x24: Clip0_Right(); if (FC_yn < Wybot) break; /* Отброшен */ Clip1_Bottom(); ++visible; break; case 0x25: Clip0_Right(); if (FC_yn < Wybot) break; /* Отброшен */ Clip1_Bottom(); if (FC_xk < Wxlef) Clip1_Left(); ++visible; case 0x26: break; /* Отброшен */ case 0x28: Clip0_Right(); if (FC_yn > Wytop) break; /* Отброшен */ Clip1_Top(); ++visible; break; case 0x29: Clip0_Right(); if (FC_yn > Wytop) break; /* Отброшен */ Clip1_Top(); if (FC_xk < Wxlef) Clip1_Left(); ++visible; case 0x2A: break; /* Отброшен */
/* Снизу */ case 0x40: Clip0_Bottom(); ++visible; break; case 0x41: Clip0_Bottom(); if (FC_xn < Wxlef) break; /* Отброшен */ Clip1_Left() ; if (FC_yk < Wybot) Clip1_Bottom(); ++visible; break; case 0x42: Clip0_Bottom(); if (FC_xn > Wxrig) break; /* Отброшен */ Clip1_Right(); ++visible; case 0x44: case 0x45: case 0x46: break; /* Отброшен */ case 0x48: Clip0_Bottom(); Clip1_Top(); ++visible; break; case 0x49: Clip0_Bottom(); if (FC_xn < Wxlef) break; /* Отброшен */ Clip1_Left() ; if (FC_yk > Wytop) Clip1_Top(); ++visible; break; case 0x4A: Clip0_Bottom(); if (FC_xn > Wxrig) break; /* Отброшен */ Clip1_Right(); if (FC_yk > Wytop) Clip1_Top(); ++visible; break;
/* Снизу слева */ case 0x50: Clip0_Left(); if (FC_yn < Wybot) Clip0_Bottom(); ++visible; case 0x51: break; /* Отброшен */ case 0x52: Clip1_Right(); if (FC_yk < Wybot) break; /* Отброшен */ Clip0_Bottom(); if (FC_xn < Wxlef) Clip0_Left(); ++visible; case 0x54: case 0x55: case 0x56: break; /* Отброшен */ case 0x58: Clip1_Top(); if (FC_xk < Wxlef) break; /* Отброшен */ Clip0_Bottom(); if (FC_xn < Wxlef) Clip0_Left(); ++visible; case 0x59: break; /* Отброшен */ case 0x5A: Clip0_Left(); if (FC_yn > Wytop) break; /* Отброшен */ Clip1_Right(); if (FC_yk < Wybot) break; /* Отброшен */ if (FC_yn < Wybot) Clip0_Bottom(); if (FC_yk > Wytop) Clip1_Top(); ++visible; break;
/* Снизу-справа */ case 0x60: Clip0_Right(); if (FC_yn < Wybot) Clip0_Bottom(); ++visible; break; case 0x61: Clip1_Left() ; if (FC_yk < Wybot) break; /* Отброшен */ Clip0_Bottom(); if (FC_xn > Wxrig) Clip0_Right(); ++visible; case 0x62: case 0x64: case 0x65: case 0x66: break; /* Отброшен */ case 0x68: Clip1_Top(); if (FC_xk > Wxrig) break; /* Отброшен */ Clip0_Right(); if (FC_yn < Wybot) Clip0_Bottom(); ++visible; break; case 0x69: Clip1_Left() ; if (FC_yk < Wybot) break; /* Отброшен */ Clip0_Right(); if (FC_yn > Wytop) break; /* Отброшен */ if (FC_yk > Wytop) Clip1_Top(); if (FC_yn < Wybot) Clip0_Bottom(); ++visible; case 0x6A: break; /* Отброшен */
/* Сверху */ case 0x80: Clip0_Top(); ++visible; break; case 0x81: Clip0_Top(); if (FC_xn < Wxlef) break; /* Отброшен */ Clip1_Left() ; ++visible; break; case 0x82: Clip0_Top(); if (FC_xn > Wxrig) break; /* Отброшен */ Clip1_Right(); ++visible; break; case 0x84: Clip0_Top(); Clip1_Bottom(); ++visible; break; case 0x85: Clip0_Top(); if (FC_xn < Wxlef) break; /* Отброшен */ Clip1_Left() ; if (FC_yk < Wybot) Clip1_Bottom(); ++visible; break; case 0x86: Clip0_Top(); if (FC_xn > Wxrig) break; /* Отброшен */ Clip1_Right(); if (FC_yk < Wybot) Clip1_Bottom(); ++visible; case 0x88: case 0x89: case 0x8A: break; /* Отброшен */
/* Сверху-слева */ case 0x90: Clip0_Left(); if (FC_yn > Wytop) Clip0_Top(); ++visible; case 0x91: break; /* Отброшен */ case 0x92: Clip1_Right(); if (FC_yk > Wytop) break; /* Отброшен */ Clip0_Top(); if (FC_xn < Wxlef) Clip0_Left(); ++visible; break; case 0x94: Clip1_Bottom(); if (FC_xk < Wxlef) break; /* Отброшен */ Clip0_Left(); if (FC_yn > Wytop) Clip0_Top(); ++visible; case 0x95: break; /* Отброшен */ case 0x96: Clip0_Left(); if (FC_yn < Wybot) break; /* Отброшен */ Clip1_Right(); if (FC_yk > Wytop) break; /* Отброшен */ if (FC_yn > Wytop) Clip0_Top(); if (FC_yk < Wybot) Clip1_Bottom(); ++visible; case 0x98: case 0x99: case 0x9A: break; /* Отброшен */
/* Сверху-справа */ case 0xA0: Clip0_Right(); if (FC_yn > Wytop) Clip0_Top(); ++visible; break; case 0xA1: Clip1_Left() ; if (FC_yk > Wytop) break; /* Отброшен */ Clip0_Top(); if (FC_xn > Wxrig) Clip0_Right(); ++visible; case 0xA2: break; /* Отброшен */ case 0xA4: Clip1_Bottom(); if (FC_xk > Wxrig) break; /* Отброшен */ Clip0_Right(); if (FC_yn > Wytop) Clip0_Top(); ++visible; break; case 0xA5: Clip1_Left() ; if (FC_yk > Wytop) break; /* Отброшен */ Clip0_Right(); if (FC_yn < Wybot) break; /* Отброшен */ if (FC_yk < Wybot) Clip1_Bottom(); if (FC_yn > Wytop) Clip0_Top(); ++visible; case 0xA6: /* Отброшен */ case 0xA8: case 0xA9: case 0xAA: break;
/* Ошибка */ default: visible= -1; break; } /* switch */ if (visible > 0) { *x0= FC_xn; *y0= FC_yn; *x1= FC_xk; *y1= FC_yk; } return (visible); } /* V_FCclip */
/*--------------------------------------------------- V_LBclip * Реализует алгоритм отсечения Лианга-Барски * с параметрическим заданием линий * * int V_LBclip (float *x0, float *y0, float *x1, float *y1) * * Отсекает отрезок, заданный значениями координат его * точек (x0,y0), (x1,y1), по окну отсечения, заданному * глобальными скалярами Wxlef, Wybot, Wxrig, Wytop * * Возвращает: * 0 - отрезок не видим * 1 - отрезок видим */ static float LB_t0, LB_t1; static int LB_tclip (p, q) float p, q; { int accept; float r; accept= 1; /* Отрезок принят */ if (p == 0) { if (q < 0) accept= 0; /* Отбрасывание */ } else { r= q/p; if (p < 0) { if (r > LB_t1) accept= 0; /* Отбрасывание */ else if (r > LB_t0) LB_t0= r; } else { if (r < LB_t0) accept= 0; /* Отбрасывание */ else if (r < LB_t1) LB_t1= r; } } return (accept); } /* LB_tclip */
int V_LBclip (x0, y0, x1, y1) float *x0, *y0, *x1, *y1; { int visible; float dx, dy; visible= 0; LB_t0= 0; LB_t1= 1; dx= *x1 - *x0; if (LB_tclip (-dx, *x0-Wxlef)) { if (LB_tclip (dx, Wxrig-*x0)) { dy= *y1 - *y0; if (LB_tclip (-dy, *y0-Wybot)) { if (LB_tclip (dy, Wytop-*y0)) { if (LB_t1 < 1) { *x1= *x0 + LB_t1*dx; *y1= *y0 + LB_t1*dy; } if (LB_t0 > 0) { *x0= *x0 + LB_t0*dx; *y0= *y0 + LB_t0*dy; } ++visible; } } } } return (visible); } /* V_LBclip */
/*--------------------------------------------------- V_CBclip * Реализует алгоритм отсечения Кируса-Бека * по произвольному выпуклому многоугольнику * с параметрическим заданием линий * * int V_CBclip (float *x0, float *y0, float *x1, float *y1) * * Отсекает отрезок, заданный значениями координат его * точек (x0,y0), (x1,y1), по окну отсечения, заданному * глобальными скалярами: * int Windn - количество вершин в окне отсечения * float *Windx, *Windy - массивы X,Y координат вершин * float *Wnormx, *Wnormy - массивы координат нормалей * к ребрам * * Возвращает: * 0 - отрезок не видим * 1 - отрезок видим */
int V_CBclip (x0, y0, x1, y1) float *x0, *y0, *x1, *y1; { int ii, jj, visible, kw; float xn, yn, dx, dy, r; float CB_t0, CB_t1; /* Параметры концов отрезка */ float Qx, Qy; /* Положение относ ребра */ float Nx, Ny; /* Перпендикуляр к ребру */ float Pn, Qn; /**/ kw= Windn - 1; /* Ребер в окне */ visible= 1; CB_t0= 0; CB_t1= 1; dx= *x1 - (xn= *x0); dy= *y1 - (yn= *y0); for (ii=0; ii<=kw; ++ii) { /* Цикл по ребрам окна */ Qx= xn - Windx[ii]; /* Положения относ ребра */ Qy= yn - Windy[ii]; Nx= Wnormx[ii]; /* Перепендикуляр к ребру */ Ny= Wnormy[ii]; Pn= dx*Nx + dy*Ny; /* Скалярные произведения */ Qn= Qx*Nx + Qy*Ny; /* Анализ расположения */ if (Pn == 0) { /* Паралл ребру или точка */ if (Qn < 0) {visible= 0; break; } } else { r= -Qn/Pn; if (Pn < 0) { /* Поиск верхнего предела t */ if (r < CB_t0) {visible= 0; break; } if (r < CB_t1) CB_t1= r; } else { /* Поиск нижнего предела t */ if (r > CB_t1) {visible= 0; break; } if (r > CB_t0) CB_t0= r; } } } if (visible) { if (CB_t0 > CB_t1) visible= 0; else { if (CB_t0 > 0) { *x0= xn + CB_t0*dx; *y0= yn + CB_t0*dy; } if (CB_t1 < 1) { *x1= xn + CB_t1*dx; *y1= yn + CB_t1*dy; } } } return (visible); } /* V_CBclip */
/*=================================================== T_CLIP.C * * ТЕСТ ПРОЦЕДУР ОТСЕЧЕНИЯ */ #include <time.h> #include <stdio.h> /*--------------------------------------------------- V_DMclip * Пустышка для процедур отсечения */ int V_DMclip (x0, y0, x1, y1) float *x0, *y0, *x1, *y1; { int visible; visible= 1; return (visible); } /* V_DMclip */
/*---------------------------------------------------- ClipMsg * Печатает сообщение о результатах отсечения */ void ClipMsg (proc, visible, x0, y0, x1, y1, dt) char *proc; int visible; float x0, y0, x1, y1, dt; { if (visible < 0) { printf("*** ERROR (%s LineClip) - ", proc); printf("ошибка в координатах окна. "); printf("Прерывание с кодом ошибки 1."); exit (1); } else if (visible == 0) printf ("%s: Line is no visible dt=%f\n", proc, dt); else printf ("%s: ClipLine: x0=%f y0=%f x1=%f y1=%f dt=%f\n", proc, x0, y0, x1, y1, dt); } /* ClipMsg */
/*---------------------------------------------- MAIN T_CLIP.C */ void main (void) { float Wxn, Wyn, Wxk, Wyk; float Xn, Yn, Xk, Yk, x0, y0, x1, y1; int ii, numb= 1; float X_wind[100], Y_wind[100]; float X_norm[100], Y_norm[100]; int visible; float dt; time_t t1, t2; long ll, powt=10l; if (numb) goto set_win; m0:printf ("----Вершин= %d ? ", numb); scanf ("%d", &numb); for (ii=0; ii<numb; ++ii) { printf ("X_wind[%d], Y_wind[%d] ? ", ii, ii); scanf ("%f%f", &X_wind[ii], &Y_wind[ii]); } ii= V_SetPclip (numb, X_wind, Y_wind, X_norm, Y_norm); printf ("V_SetPclip= %d\n", ii); if (ii) goto m0; for (ii=0; ii<numb; ++ii) printf ("ind=%d X_norm=%f, Y_norm=%f\n", ii, X_norm[ii], Y_norm[ii]); if (ii) goto m0; /* Задание окна отсечения */ set_win: powt= 1l; V_GetRclip (&Wxn, &Wyn, &Wxk, &Wyk); for (;;) { printf ("Window: (Xn=%f Yn=%f Xk=%f Yk=%f) ? ", Wxn, Wyn, Wxk, Wyk); scanf ("%f%f%f%f", &Wxn, &Wyn, &Wxk, &Wyk); if (!V_SetRclip (Wxn, Wyn, Wxk, Wyk)) break; printf ("Error in a window boundarys\n"); } /* Ввод координат отрезка */ Xn= Wxn-1.0; Yn= Wyn-1.0; Xk= Wxk+1.0; Yk= Wyk+1.0; for (;;) { printf ("------------- "); printf ("ClipWindow: Xn=%f Yn=%f Xk=%f Yk=%f\n", Wxlef, Wybot, Wxrig, Wytop); printf ("New Line: (Xn=%f Yn=%f Xk=%f Yk=%f) ? ", Xn, Yn, Xk, Yk); scanf ("%f%f%f%f", &Xn, &Yn, &Xk, &Yk); ll= powt; t1= time(NULL); do { x0= Xn; y0= Yn; x1= Xk; y1= Yk; visible= V_DMclip (&x0, &y0, &x1, &y1); } while (--ll > 0l); t2= time (NULL); dt= ((float)(t2 - t1)); ClipMsg ("DM", visible, x0, y0, x1, y1, dt);
ll= powt; t1= time(NULL); do { x0= Xn; y0= Yn; x1= Xk; y1= Yk; visible= V_CSclip (&x0, &y0, &x1, &y1); } while (--ll > 0l); t2= time (NULL); dt= ((float)(t2 - t1)); ClipMsg ("CS", visible, x0, y0, x1, y1, dt); ll= powt; t1= time(NULL); do { x0= Xn; y0= Yn; x1= Xk; y1= Yk; visible= V_FCclip (&x0, &y0, &x1, &y1); } while (--ll > 0l); t2= time (NULL); dt= ((float)(t2 - t1)); ClipMsg ("FC", visible, x0, y0, x1, y1, dt); ll= powt; t1= time(NULL); do { x0= Xn; y0= Yn; x1= Xk; y1= Yk; visible= V_LBclip (&x0, &y0, &x1, &y1); } while (--ll > 0l); t2= time (NULL); dt= ((float)(t2 - t1)); ClipMsg ("LB", visible, x0, y0, x1, y1, dt); ll= powt; t1= time(NULL); do { x0= Xn; y0= Yn; x1= Xk; y1= Yk; visible= V_CBclip (&x0, &y0, &x1, &y1); } while (--ll > 0l); t2= time (NULL); dt= ((float)(t2 - t1)); ClipMsg ("CB", visible, x0, y0, x1, y1, dt); } }
Релятивисты и позитивисты утверждают, что "мысленный эксперимент" весьма полезный интрумент для проверки теорий (также возникающих в нашем уме) на непротиворечивость. В этом они обманывают людей, так как любая проверка может осуществляться только независимым от объекта проверки источником. Сам заявитель гипотезы не может быть проверкой своего же заявления, так как причина самого этого заявления есть отсутствие видимых для заявителя противоречий в заявлении.
Это мы видим на примере СТО и ОТО, превратившихся в своеобразный вид религии, управляющей наукой и общественным мнением. Никакое количество фактов, противоречащих им, не может преодолеть формулу Эйнштейна: "Если факт не соответствует теории - измените факт" (В другом варианте " - Факт не соответствует теории? - Тем хуже для факта").
Максимально, на что может претендовать "мысленный эксперимент" - это только на внутреннюю непротиворечивость гипотезы в рамках собственной, часто отнюдь не истинной логики заявителя. Соответсвие практике это не проверяет. Настоящая проверка может состояться только в действительном физическом эксперименте.
Эксперимент на то и эксперимент, что он есть не изощрение мысли, а проверка мысли. Непротиворечивая внутри себя мысль не может сама себя проверить. Это доказано Куртом Гёделем.
Понятие "мысленный эксперимент" придумано специально спекулянтами - релятивистами для шулерской подмены реальной проверки мысли на практике (эксперимента) своим "честным словом". Подробнее читайте в FAQ по эфирной физике.