к оглавлению

Основные алгоритмы компьютерной графики

Процедуры отсечения отрезка

    0.18.1  V_SetPclip - установить многоугольник отсечения
    0.18.2  V_SetRclip - установить прямоугольник отсечения
    0.18.3  V_GetRclip - опросить прямоугольник отсечения
    0.18.4  V_CSclip - отсечение Коэна-Сазерленда
    0.18.5  V_FCclip - Fast Clipping-алгоритм
    0.18.6  V_LBclip - алгоритм Лианга-Барски
    0.18.7  V_CBclip - алгоритм Кируса-Бека
    0.18.8  Тест процедур отсечения

В данном приложении приведены процедуры, обеспечивающие выполнение отсечения по прямоугольному и многоугольному выпуклому окну и тестовая программа проверки работы процедур отсечения.

/*=================================================== 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;

0.18.1  V_SetPclip - установить многоугольник отсечения

/*------------------------------------------------- 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 */

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 */


0.18.5  V_FCclip - Fast Clipping-алгоритм

/*--------------------------------------------------- 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 */


0.18.6  V_LBclip - алгоритм Лианга-Барски

/*--------------------------------------------------- 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 */


0.18.7  V_CBclip - алгоритм Кируса-Бека

/*--------------------------------------------------- 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 */


0.18.8  Тест процедур отсечения

/*=================================================== 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);
   }
}
к оглавлению

Знаете ли Вы, что только в 1990-х доплеровские измерения радиотелескопами показали скорость Маринова для CMB (космического микроволнового излучения), которую он открыл в 1974. Естественно, о Маринове никто не хотел вспоминать. Подробнее читайте в FAQ по эфирной физике.

НОВОСТИ ФОРУМА

Форум Рыцари теории эфира


Рыцари теории эфира
 10.11.2021 - 12:37: ПЕРСОНАЛИИ - Personalias -> WHO IS WHO - КТО ЕСТЬ КТО - Карим_Хайдаров.
10.11.2021 - 12:36: СОВЕСТЬ - Conscience -> РАСЧЕЛОВЕЧИВАНИЕ ЧЕЛОВЕКА. КОМУ ЭТО НАДО? - Карим_Хайдаров.
10.11.2021 - 12:36: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от д.м.н. Александра Алексеевича Редько - Карим_Хайдаров.
10.11.2021 - 12:35: ЭКОЛОГИЯ - Ecology -> Биологическая безопасность населения - Карим_Хайдаров.
10.11.2021 - 12:34: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> Проблема государственного терроризма - Карим_Хайдаров.
10.11.2021 - 12:34: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> ПРАВОСУДИЯ.НЕТ - Карим_Хайдаров.
10.11.2021 - 12:34: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Вадима Глогера, США - Карим_Хайдаров.
10.11.2021 - 09:18: НОВЫЕ ТЕХНОЛОГИИ - New Technologies -> Волновая генетика Петра Гаряева, 5G-контроль и управление - Карим_Хайдаров.
10.11.2021 - 09:18: ЭКОЛОГИЯ - Ecology -> ЭКОЛОГИЯ ДЛЯ ВСЕХ - Карим_Хайдаров.
10.11.2021 - 09:16: ЭКОЛОГИЯ - Ecology -> ПРОБЛЕМЫ МЕДИЦИНЫ - Карим_Хайдаров.
10.11.2021 - 09:15: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Екатерины Коваленко - Карим_Хайдаров.
10.11.2021 - 09:13: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Вильгельма Варкентина - Карим_Хайдаров.
Bourabai Research - Технологии XXI века Bourabai Research Institution