zoukankan      html  css  js  c++  java
  • 图形学算法之NichollLeeNicholl算法

    在本学期的所学的裁剪算法中,有一个叫做Nicholl-Lee-Nicholl的算法。

    在实践中,我遇到了一个小问题,因为教程中所讲的只有起点在剪裁框内、左侧和左上的情况,并说其余情况均可以通过点的平移或旋转变换等方式变换到上述3个区域内。

    但考虑到裁剪框并不都是正方形,所以上方区域和左侧区域也不都是完全映射的,所以并不能简单的旋转平移点,而是整个屏幕都旋转,这样的话还不如为上方区域单独做算法。

    最终实现代码如下:

      1 /* Nicholl-Lee-Nicholl Line Clipping Algorithm */
      2 void NichollLeeNichollClip()
      3 {
      4     // 变量
      5     clipped_line_num = 0;
      6     float m, k;
      7     float mLT, mLB, mRB, mRT;    // 生成起点到四个剪裁窗口顶点的斜率
      8     // 针对每条线
      9     for (int i = 0; i < line_num; i++)
     10     {
     11         // 生成剪裁线
     12         line clip_line = l[i];
     13         // 区域码赋值
     14         getRegionCode(clip_line.original);
     15         getRegionCode(clip_line.terminal);
     16         // 判断框内线条(两端点区域码都为00000)
     17         if ((clip_line.original.code | clip_line.terminal.code) == 0x0)
     18         {
     19             clipped_l[clipped_line_num] = clip_line;
     20             clipped_line_num++;
     21             continue;
     22         }
     23         // 判断框外线条(两端点区域码按为与为真)
     24         if (clip_line.original.code & clip_line.terminal.code)
     25         {
     26             continue;
     27         }
     28         // 判断起点是否在已有算法区域的对称区域
     29         int before_code; // 变换之前的区域码
     30         before_code = clip_line.original.code;
     31         // 右侧变换
     32         if (clip_line.original.code == winRightBitCode)
     33         {
     34             clip_line.original.x = clip_left + clip_right - clip_line.original.x;
     35             clip_line.terminal.x = clip_left + clip_right - clip_line.terminal.x;
     36         }
     37         // 右上侧变换
     38         if (clip_line.original.code == ( winRightBitCode | winTopBitCode ) )
     39         {
     40             clip_line.original.x = clip_left + clip_right - clip_line.original.x;
     41             clip_line.terminal.x = clip_left + clip_right - clip_line.terminal.x;
     42         }
     43         // 左下侧变换
     44         if (clip_line.original.code == ( winLeftBitCode | winBottomBitCode ) )
     45         {
     46             clip_line.original.y = clip_top + clip_bottom - clip_line.original.y;
     47             clip_line.terminal.y = clip_top + clip_bottom - clip_line.terminal.y;
     48         }
     49         // 右下侧变换
     50         if (clip_line.original.code == ( winRightBitCode | winBottomBitCode ) )
     51         {
     52             clip_line.original.x = clip_left + clip_right - clip_line.original.x;
     53             clip_line.terminal.x = clip_left + clip_right - clip_line.terminal.x;
     54             clip_line.original.y = clip_top + clip_bottom - clip_line.original.y;
     55             clip_line.terminal.y = clip_top + clip_bottom - clip_line.terminal.y;
     56         }
     57         // 下侧变换
     58         if (clip_line.original.code == winBottomBitCode)
     59         {
     60             clip_line.original.y = clip_top + clip_bottom - clip_line.original.y;
     61             clip_line.terminal.y = clip_top + clip_bottom - clip_line.terminal.y;
     62         }
     63         // 重新加载区域码
     64         getRegionCode(clip_line.original);
     65         getRegionCode(clip_line.terminal);
     66         // 以下情况均要用到斜率
     67     mLT=(float)(clip_top-clip_line.original.y)/(clip_left-clip_line.original.x);
     68     mLB=(float)(clip_bottom-clip_line.original.y)/(clip_left-clip_line.original.x);
     69     mRB=(float)(clip_bottom-clip_line.original.y)/(clip_right-clip_line.original.x);
     70     mRT=(float)(clip_top-clip_line.original.y)/(clip_right-clip_line.original.x);
     71 m=(float)(clip_line.terminal.y-clip_line.original.y)/(clip_line.terminal.x-clip_line.original.x);
     72     k = 1 / m;
     73 
     74         // 判断起点位置
     75         // 情况一:在框内
     76         if (clip_line.original.code == 0x0)
     77         {
     78             // left
     79             if ((mLT <= m && m < mLB) && clip_line.terminal.code & winLeftBitCode)
     80             {
     81                 clip_line.terminal.y = clip_line.terminal.y + round(m * (clip_left - clip_line.terminal.x));
     82                 clip_line.terminal.x = clip_left;
     83             }
     84             // bottom
     85             if ((m >= mLB || m < mRB) && clip_line.terminal.code & winBottomBitCode)
     86             {
     87                 clip_line.terminal.x = clip_line.terminal.x + round(k * (clip_bottom - clip_line.terminal.y));
     88                 clip_line.terminal.y = clip_bottom;
     89             }
     90             // right
     91             if ((mRB <= m && m < mRT) && clip_line.terminal.code & winRightBitCode)
     92             {
     93                 clip_line.terminal.y = clip_line.terminal.y + round(m * (clip_right - clip_line.terminal.x));
     94                 clip_line.terminal.x = clip_right;
     95             }
     96             // top
     97             if ((m >= mRT || m < mLT) && clip_line.terminal.code & winTopBitCode)
     98             {
     99                 clip_line.terminal.x = clip_line.terminal.x + round(k * (clip_top - clip_line.terminal.y));
    100                 clip_line.terminal.y = clip_top;
    101             }
    102         }
    103         // 情况二:在框左侧
    104         elseif (clip_line.original.code == winLeftBitCode)
    105         {
    106             if (m < mLB || m >= mLT) // 区域外
    107                 continue;
    108             else
    109             {
    110                 // 起点剪裁 L
    111                 clip_line.original.y = clip_line.original.y + round(m * (clip_left - clip_line.original.x);
    112                 clip_line.original.x = clip_left;
    113                 if (clip_line.terminal.code != 0x0)
    114                 {
    115                     if (mLB <= m && m < mRB) // LB
    116                     {
    117                         clip_line.terminal.x = clip_line.terminal.x + round(k * (clip_bottom - clip_line.terminal.y));
    118                         clip_line.terminal.y = clip_bottom;
    119                     }
    120                     elseif (mRB <= m && m < mRT) // LR
    121                     {
    122                         clip_line.terminal.y = clip_line.terminal.y + round(m * (clip_right - clip_line.terminal.x));
    123                         clip_line.terminal.x = clip_right;
    124                     }
    125                     elseif (mRT <= m && m < mLT) // LT
    126                     {
    127                         clip_line.terminal.x = clip_line.terminal.x + round(k * (clip_top - clip_line.terminal.y));
    128                         clip_line.terminal.y = clip_top;
    129                     }
    130                 }
    131             }
    132         }
    133         // 情况三:在框左上侧
    134         elseif (clip_line.original.code == ( winLeftBitCode | winTopBitCode ) )
    135         {
    136             if (m < mLB || m >= mRT) // 区域外
    137                 continue;
    138             else
    139             {
    140                 // 起点靠近左裁剪线
    141                 if (clip_left - clip_line.original.x < clip_line.original.y - clip_top)
    142                 {
    143                     if (mLB <= m && m < mLT)
    144                     {
    145                         // L
    146                         clip_line.original.y = clip_line.original.y + round(m * (clip_left - clip_line.original.x));
    147                         clip_line.original.x = clip_left;
    148                         if (clip_line.terminal.code != 0x0)    // LB
    149                         {
    150                             clip_line.terminal.x = clip_line.terminal.x + round(k * (clip_bottom - clip_line.terminal.y));
    151                             clip_line.terminal.y = clip_bottom;
    152                         }
    153                     }
    154                     elseif (mLT <= m && m < mRB)
    155                     {
    156                         // T
    157                         clip_line.original.x = clip_line.original.x + round(k * (clip_top - clip_line.original.y));
    158                         clip_line.original.y = clip_top;
    159                         if (clip_line.terminal.code != 0x0)    // TB
    160                         {
    161                             clip_line.terminal.x = clip_line.terminal.x + round(k * (clip_bottom - clip_line.terminal.y));
    162                             clip_line.terminal.y = clip_bottom;
    163                         }
    164                     }
    165                     elseif (mRB <= m && m < mRT)
    166                     {
    167                         // T
    168                         clip_line.original.x = clip_line.original.x + round(k * (clip_top - clip_line.original.y));
    169                         clip_line.original.y = clip_top;
    170                         if (clip_line.terminal.code != 0x0)    // TR
    171                         {
    172                             clip_line.terminal.y = clip_line.terminal.y + round(m * (clip_right - clip_line.terminal.x));
    173                             clip_line.terminal.x = clip_right;
    174                         }
    175                     }
    176                 }
    177                 // 起点靠近上裁剪线
    178                 else
    179                 {
    180                     if (mLB <= m && m < mRB)
    181                     {
    182                         // L
    183                         clip_line.original.y = clip_line.original.y + round(m * (clip_left - clip_line.original.x));
    184                         clip_line.original.x = clip_left;
    185                         if (clip_line.terminal.code != 0x0)    // LB
    186                         {
    187                             clip_line.terminal.x = clip_line.terminal.x + round(k * (clip_bottom - clip_line.terminal.y));
    188                             clip_line.terminal.y = clip_bottom;
    189                         }
    190                     }
    191                     elseif (mRB <= m && m < mLT)
    192                     {
    193                         // L
    194                         clip_line.original.y = clip_line.original.y + round(m * (clip_left - clip_line.original.x));
    195                         clip_line.original.x = clip_left;
    196                         if (clip_line.terminal.code != 0x0)    // LR
    197                         {
    198                             clip_line.terminal.y = clip_line.terminal.y + round(m * (clip_right - clip_line.terminal.x));
    199                             clip_line.terminal.x = clip_right;
    200                         }
    201                     }
    202                     elseif (mLT <= m && m < mRT)
    203                     {
    204                         // T
    205                         clip_line.original.x = clip_line.original.x + round(k * (clip_top - clip_line.original.y));
    206                         clip_line.original.y = clip_top;
    207                         if (clip_line.terminal.code != 0x0)    // TR
    208                         {
    209                             clip_line.terminal.y = clip_line.terminal.y + round(m * (clip_right - clip_line.terminal.x));
    210                             clip_line.terminal.x = clip_right;
    211                         }
    212                     }
    213                 }
    214             }
    215 
    216         }
    217         // 情况四:在框上侧
    218         elseif (clip_line.original.code == winTopBitCode)
    219         {
    220             if ((m > 0 && m < mLT) || (m < 0 && m >= mRT)) // 区域外
    221                 continue;
    222             else
    223             {
    224                 // T
    225                 clip_line.original.x = clip_line.original.x + round(k * (clip_top - clip_line.original.y));
    226                 clip_line.original.y = clip_top;
    227                 if (clip_line.terminal.code != 0x0)
    228                 {
    229                     if (mLT <= m && m < mLB) // TL
    230                     {
    231                         clip_line.terminal.y = clip_line.terminal.y + round(m * (clip_left - clip_line.terminal.x));
    232                         clip_line.terminal.x = clip_left;
    233                     }
    234                     elseif (m >= mLB || m <= mRB) // TB
    235                     {
    236                         clip_line.terminal.x = clip_line.terminal.x + round(k * (clip_bottom - clip_line.terminal.y));
    237                         clip_line.terminal.y = clip_bottom;
    238                     }
    239                     elseif (mRB <= m && m < mRT) // TR
    240                     {
    241                         clip_line.terminal.y = clip_line.terminal.y + round(m * (clip_right - clip_line.terminal.x));
    242                         clip_line.terminal.x = clip_right;
    243                     }
    244                 }
    245             }
    246         }
    247         // 恢复对称区域的变化
    248         // 右侧变换
    249         if (before_code == winRightBitCode)
    250         {
    251             clip_line.original.x = clip_left + clip_right - clip_line.original.x;
    252             clip_line.terminal.x = clip_left + clip_right - clip_line.terminal.x;
    253         }
    254         // 右上侧变换
    255         if (before_code == ( winRightBitCode | winTopBitCode ) )
    256         {
    257             clip_line.original.x = clip_left + clip_right - clip_line.original.x;
    258             clip_line.terminal.x = clip_left + clip_right - clip_line.terminal.x;
    259         }
    260         // 左下侧变换
    261         if (before_code == ( winLeftBitCode | winBottomBitCode ) )
    262         {
    263             clip_line.original.y = clip_top + clip_bottom - clip_line.original.y;
    264             clip_line.terminal.y = clip_top + clip_bottom - clip_line.terminal.y;
    265         }
    266         // 右下侧变换
    267         if (before_code == ( winRightBitCode | winBottomBitCode ) )
    268         {
    269             clip_line.original.x = clip_left + clip_right - clip_line.original.x;
    270             clip_line.terminal.x = clip_left + clip_right - clip_line.terminal.x;
    271             clip_line.original.y = clip_top + clip_bottom - clip_line.original.y;
    272             clip_line.terminal.y = clip_top + clip_bottom - clip_line.terminal.y;
    273         }
    274         // 下侧变换
    275         if (before_code == winBottomBitCode)
    276         {
    277             clip_line.original.y = clip_top + clip_bottom - clip_line.original.y;
    278             clip_line.terminal.y = clip_top + clip_bottom - clip_line.terminal.y;
    279         }
    280         // 将剪裁好的直线存入数组
    281         clipped_l[clipped_line_num] = clip_line;
    282         clipped_line_num++;
    283     }
    284 }
  • 相关阅读:
    SQLite 版本引发的 Python 程序调用问题
    从0到10亿,微信后台架构及基础设施设计与实践!
    从Oracle到PostgreSQL:动态性能视图 vs 标准统计视图
    第一章 准备工作
    Swagger2简介
    如何查询numpy,scipy,matplotlib等的版本和安装位置
    完美解决ImportError: cannot import name '_validate_lengths'报错问题
    完美解决AttributeError: module 'scipy.misc' has no attribute 'imread'报错问题
    线上课堂:ernetes Operator开发范式
    Bomb Enemy 炸弹人
  • 原文地址:https://www.cnblogs.com/bjut13070019/p/5601388.html
Copyright © 2011-2022 走看看