多边形的裁剪

实现了两种二维图形裁剪算法:Sutherland-Hodgeman单边裁剪法和Weiler-Atherton边界裁剪法,关于这两个算法的具体可以参看这个网址:http://course.cug.edu.cn/cugFirst/computer_graphics/class/start.asp

 

  1. #include <stdio.h>
  2. #include <alloc.h>
  3. #include <graphics.h>
  4. #include <math.h>
  5. typedef enum 
  6. {
  7.     FALSE  = 0,
  8.     TRUE = 1
  9. BOOL;
  10. typedef enum
  11. {
  12.     INSIDE,
  13.     EDGE_IN,
  14.     EDGE_OUT,
  15.     EDGE_CORNER,
  16.     OUTSIDE,
  17.     UNKNOWN
  18. } VectorType;
  19. typedef struct
  20. {
  21.     int x;
  22.     int y;
  23.     VectorType type;
  24. } Vector;
  25. typedef struct
  26. {
  27.     Vector v1;
  28.     Vector v2;
  29. } Edge;
  30. typedef struct _Node
  31. {
  32.     Vector v;
  33.     struct _Node *next;
  34. } Node, *VectorList;
  35. const Vector AREA_LEFT_TOP = { 145, 125 };
  36. const Vector AREA_RIGHT_BOTTOM = { 260, 190 };
  37. typedef enum
  38. {
  39.     LEFT,
  40.     TOP,
  41.     RIGHT,
  42.     BOTTOM,
  43.     AROUND
  44. } EdgeType;
  45. #define VECTOR_NUM 7
  46. const Vector PRIMITIVE_LEFT_TOP = { 100, 100 };
  47. BOOL Clockwise( Vector v1, Vector v2 )
  48. {
  49.     int n = v1.x * v2.y - v1.y * v2.x;
  50.     if ( n > 0 )
  51.     {
  52.         return TRUE;
  53.     }
  54.     else
  55.     {
  56.         return FALSE;
  57.     }
  58. }
  59. void Push( VectorList *vList, Node *frontNode, Node *pushingNode )
  60. {
  61.     Node *n;
  62.     if ( *vList == NULL || frontNode == NULL )
  63.     {
  64.         printf( "error in Push;" );
  65.         return;
  66.     }
  67.     pushingNode->next = frontNode->next;
  68.     frontNode->next = pushingNode;
  69. }
  70. void PushBack( VectorList *vList, Node *pushingNode )
  71. {
  72.     Node *n;
  73.     pushingNode->next = NULL;
  74.     if ( *vList == NULL )
  75.     {
  76.         *vList = pushingNode;
  77.     }
  78.     else
  79.     {
  80.         for ( n = *vList; n->next != NULL; n = n->next );
  81.         n->next = pushingNode;
  82.     }
  83. }
  84. void Erase( VectorList *vList, Node **erasingNode )
  85. {
  86.     Node *n;
  87.     if ( *vList == NULL )
  88.     {
  89.         printf( "error in Erase" );
  90.         return;
  91.     }
  92.     if ( *erasingNode == *vList )
  93.     {
  94.         *vList = ( *vList )->next;
  95.         free( *erasingNode );
  96.         return;
  97.     }
  98.     for ( n = *vList; n->next != *erasingNode && n->next != NULL; n = n->next );
  99.     if ( n->next == NULL )
  100.     {
  101.         printf( "can not find node in Erase" );
  102.         return;
  103.     }
  104.     n->next = ( *erasingNode )->next;
  105.     free( *erasingNode );
  106. }
  107. /* 获得顶点列表的索引为i的元素, 0 <= i < numVector */
  108. Node* GetVector( VectorList vList, int i )
  109. {
  110.     int j;
  111.     Node *n;
  112.     for ( j = 0, n = vList; j < i && n->next != NULL; i++, n = n->next );
  113.     return n;
  114. }
  115. BOOL InsideEdge( Vector v, EdgeType type )
  116. {
  117.     switch ( type )
  118.     {
  119.     case ( LEFT ) :
  120.         return v.x >= AREA_LEFT_TOP.x;
  121.     case ( RIGHT ) :
  122.         return v.x <= AREA_RIGHT_BOTTOM.x;
  123.     case ( TOP ) :
  124.         return v.y >= AREA_LEFT_TOP.y;
  125.     case ( BOTTOM ) :
  126.         return v.y <= AREA_RIGHT_BOTTOM.y;
  127.     case ( AROUND ):
  128.         return v.x >= AREA_LEFT_TOP.x &
  129.             v.x <= AREA_RIGHT_BOTTOM.x &
  130.             v.y >= AREA_LEFT_TOP.y &
  131.             v.y <= AREA_RIGHT_BOTTOM.y;
  132.     default :
  133.         return FALSE;
  134.     }
  135. }
  136. /* 检测一条边与某个边界的交点 */
  137. Vector CalcIntersectPoint( Edge e, EdgeType type )
  138. {
  139.     Vector res = { -1, -1 };
  140.     float x0, x1, y0, y1;
  141.     x0 = e.v1.x;
  142.     x1 = e.v2.x;
  143.     y0 = e.v1.y;
  144.     y1 = e.v2.y;
  145.     switch ( type )
  146.     {
  147.     case ( LEFT ) :
  148.         if ( x1 - x0 != 0 )
  149.         {
  150.             res.x = AREA_LEFT_TOP.x;
  151.             res.y = floor( res.x * ( y1 - y0 ) / ( x1 - x0 ) + ( x1 * y0 - x0 * y1 ) / ( x1 - x0 ) + 0.5f );
  152.             return res;
  153.         }
  154.         else
  155.         {
  156.             printf( "error LEFT" );
  157.             return res;
  158.         }
  159.     case ( RIGHT ) :
  160.         if ( x1 - x0 != 0 )
  161.         {
  162.             res.x = AREA_RIGHT_BOTTOM.x;
  163.             res.y = floor( res.x * ( y1 - y0 ) / ( x1 - x0 ) + ( x1 * y0 - x0 * y1 ) / ( x1 - x0 ) + 0.5f );
  164.             return res;
  165.         }
  166.         else
  167.         {
  168.             printf( "error RIGHT" );
  169.             return res;
  170.         }
  171.     case ( TOP ) :
  172.         if ( y1 - y0 != 0 )
  173.         {
  174.             res.y = AREA_LEFT_TOP.y;
  175.             res.x = floor( res.y * ( x1 - x0 ) / ( y1 - y0 ) + ( x0 * y1 - x1 * y0 ) / ( y1 - y0 ) + 0.5f );
  176.             return res;
  177.         }
  178.         else
  179.         {
  180.             printf( "error TOP" );
  181.             return res;
  182.         }
  183.     case ( BOTTOM ) :
  184.         if ( y1 - y0 != 0 )
  185.         {
  186.             res.y = AREA_RIGHT_BOTTOM.y;
  187.             res.x = floor( res.y * ( x1 - x0 ) / ( y1 - y0 ) + ( x0 * y1 - x1 * y0 ) / ( y1 - y0 ) + 0.5f );
  188.             return res;
  189.         }
  190.         else
  191.         {
  192.             printf( "error BOTTOM" );
  193.             return res;
  194.         }
  195.     default :
  196.         printf( "unknown type" );
  197.     }
  198.     /* should never be here */
  199.     return res;
  200. }
  201. /* 单边裁剪 */
  202. void SingleEdgeClipping( Vector primitive[], int numVector )
  203. {
  204.     int i;
  205.     VectorList vList = NULL;
  206.     Node *n = NULL, *m = NULL;
  207.     Vector vTemp, vNext;
  208.     Vector v1, v2;
  209.     Edge eTemp;
  210.     BOOL in1, in2;
  211.     EdgeType type;
  212.     /* 顺时针序列转为逆时针序列 */
  213.     for ( i = numVector - 1; i >= 0; i-- )
  214.     {
  215.         n = ( Node* )malloc( sizeof( Node ) );
  216.         n->v = primitive[i];
  217.         n->next = NULL;
  218.         PushBack( &vList, n );
  219.     }
  220.     /* 分别对左右上下四个边界作单边裁剪 */
  221.     for ( type = LEFT; type <= BOTTOM; type++ )
  222.     {
  223.         n = vList;
  224.         /* 遍历顶点列表 */
  225.         while ( n != NULL )
  226.         {
  227.             /*printf( "cur(%d,%d) ", n->v.x - PRIMITIVE_LEFT_TOP.x, n->v.y - PRIMITIVE_LEFT_TOP.y );*/
  228.             in1 = InsideEdge( n->v, type );
  229.             if ( n->next == NULL )
  230.             {
  231.                 vNext = vList->v;
  232.             }
  233.             else
  234.             {
  235.                 vNext = n->next->v;
  236.             } 
  237.             in2 = InsideEdge( vNext, type );
  238.             if ( in1 == TRUE ) /* 当前遍历的顶点在边界以内 */
  239.             {
  240.                 if ( in2 == TRUE ) /* 下一个顶点在边界以内 */
  241.                 {
  242.                     n = n->next;;
  243.                 }
  244.                 else
  245.                 {
  246.                     /* 求与边界的交点 */
  247.                     eTemp.v1 = n->v;
  248.                     eTemp.v2 = vNext;
  249.                     vTemp = CalcIntersectPoint( eTemp, type );
  250.                     /* 将交点添加到List,添加到当前遍历顶点的后面 */
  251.                     m = ( Node* )malloc( sizeof( Node ) );
  252.                     m->v = vTemp;
  253.                     m->next = NULL;
  254.                     Push( &vList, n, m); 
  255.                     /*printf("add(%d,%d) ", m->v.x - PRIMITIVE_LEFT_TOP.x, m->v.y - PRIMITIVE_LEFT_TOP.y );*/
  256.                     /* 跳过当前新添加的节点 */
  257.                     n = m->next;
  258.                 }
  259.             }
  260.             else
  261.             {
  262.                 if ( in2 == TRUE )
  263.                 {
  264.                     /* 求与边界的交点 */
  265.                     eTemp.v1 = n->v;
  266.                     eTemp.v2 = vNext;
  267.                     vTemp = CalcIntersectPoint( eTemp, type );
  268.                     /* 将交点添加到List,添加到当前遍历顶点的后面 */
  269.                     m = ( Node* )malloc( sizeof( Node ) );
  270.                     m->v = vTemp;
  271.                     m->next = NULL;
  272.                     Push( &vList, n, m);
  273.                     /*printf("add(%d,%d) ", m->v.x - PRIMITIVE_LEFT_TOP.x, m->v.y - PRIMITIVE_LEFT_TOP.y );*/
  274.                     m = n;
  275.                     /* 跳过当前新添加的节点 */
  276.                     n = n->next->next;
  277.                     /* 从顶点列表中删除当前节点 */
  278.                     /*printf("del(%d,%d) ", m->v.x - PRIMITIVE_LEFT_TOP.x, m->v.y - PRIMITIVE_LEFT_TOP.y );*/
  279.                     Erase( &vList, &m );
  280.                 }
  281.                 else
  282.                 {
  283.                     m = n;
  284.                     n = n->next;
  285.                     /* 从顶点列表中删除当前节点 */
  286.                     /*printf("del(%d,%d) ", m->v.x - PRIMITIVE_LEFT_TOP.x, m->v.y - PRIMITIVE_LEFT_TOP.y );*/
  287.                     Erase( &vList, &m );
  288.                 }
  289.             }
  290.         }
  291.         /*
  292.         n = vList;
  293.         while ( n != NULL )
  294.         {
  295.             printf("(%d,%d)", n->v.x - PRIMITIVE_LEFT_TOP.x, n->v.y - PRIMITIVE_LEFT_TOP.y);
  296.             n = n->next;
  297.         }
  298.         printf("/n");
  299.         */
  300.     }
  301.     n = vList;
  302.     setlinestyle( SOLID_LINE, 0, 3 );
  303.     setcolor( RED );
  304.     while ( n->next != NULL )
  305.     {
  306.         line( n->v.x, n->v.y, n->next->v.x, n->next->v.y );
  307.         n = n->next;
  308.     }
  309.     line( n->v.x - PRIMITIVE_LEFT_TOP.x, n->v.y - PRIMITIVE_LEFT_TOP.y, vList->v.x - PRIMITIVE_LEFT_TOP.x, vList->v.y - PRIMITIVE_LEFT_TOP.y );
  310. }
  311. /* 检测一条边与所有边界的交点,交点可能有1个或两个,函数返回交点数目 */
  312. int CalcIntersectPoints( Edge e, Vector vRes[] )
  313. {
  314.     int n = 0;
  315.     EdgeType type;
  316.     BOOL b1, b2;
  317.     Vector v;
  318.     float t1, t2;
  319.     for ( type = LEFT; type <= BOTTOM; type++ )
  320.     {
  321.         b1 = InsideEdge( e.v1, type );
  322.         b2 = InsideEdge( e.v2, type );
  323.         if ( b1 ^ b2 == 1 ) /* 在边缘的两侧才有可能有交点 */
  324.         {
  325.             v = CalcIntersectPoint( e, type );
  326.             /* 必须保证交点在区域内 */
  327.             if ( InsideEdge( v, AROUND ) == TRUE )
  328.             {
  329.                 vRes[n] = v;
  330.                 n++;
  331.             }
  332.         }
  333.     }
  334.     if ( n == 2 )
  335.     {
  336.         t1 = fabs( vRes[0].x - e.v1.x );
  337.         t2 = fabs( vRes[1].x - e.v1.x );
  338.         /*printf("e.v1(%d,%d)", e.v1.x - PRIMITIVE_LEFT_TOP.x, e.v1.y - PRIMITIVE_LEFT_TOP.y );
  339.         printf("sec1(%d,%d)", vRes[0].x - PRIMITIVE_LEFT_TOP.x, vRes[0].y - PRIMITIVE_LEFT_TOP.y );
  340.         printf("(t1:%f, t2:%f)", t1, t2 );*/
  341.         /* 必须保证第一个交点比第二个交点更接近起点(即e的第一个顶点)*/
  342.         if ( t1 > t2 )
  343.         {
  344.             v = vRes[0];
  345.             vRes[0] = vRes[1];
  346.             vRes[1] = v;
  347.         }
  348.     }
  349.     if ( n > 2 )
  350.     {
  351.         printf( "(%d,%d)num wrong(%d)", e.v1.x, e.v1.y, n );
  352.     }
  353.     return n;
  354. }
  355. /* 对一边的顶点进行排序 */
  356. void SortEdgeVectors( Vector vList[], int numVector, EdgeType type )
  357. {
  358.     int i, j;
  359.     Vector vTemp;
  360.     switch ( type )
  361.     {
  362.         case LEFT:
  363.             for ( i = 1; i <= numVector - 1; i++ )
  364.             {
  365.                 for ( j = 0; j < numVector - i; j++ )
  366.                 {
  367.                     if ( vList[j].y > vList[j + 1].y )
  368.                     {
  369.                         /* 交换vList[j]和vList[j + 1] */
  370.                         vTemp = vList[j];
  371.                         vList[j] = vList[j + 1];
  372.                         vList[j + 1] = vTemp;
  373.                     }
  374.                 }
  375.             }
  376.             break;
  377.         case TOP:
  378.             for ( i = 1; i <= numVector - 1; i++ )
  379.             {
  380.                 for ( j = 0; j < numVector - i; j++ )
  381.                 {
  382.                     if ( vList[j].x < vList[j + 1].x )
  383.                     {
  384.                         /* 交换vList[j]和vList[j + 1] */
  385.                         vTemp = vList[j];
  386.                         vList[j] = vList[j + 1];
  387.                         vList[j + 1] = vTemp;
  388.                     }
  389.                 }
  390.             }
  391.             break;
  392.         case RIGHT:
  393.             for ( i = 1; i <= numVector - 1; i++ )
  394.             {
  395.                 for ( j = 0; j < numVector - i; j++ )
  396.                 {
  397.                     if ( vList[j].y < vList[j + 1].y )
  398.                     {
  399.                         /* 交换vList[j]和vList[j + 1] */
  400.                         vTemp = vList[j];
  401.                         vList[j] = vList[j + 1];
  402.                         vList[j + 1] = vTemp;
  403.                     }
  404.                 }
  405.             }
  406.             break;
  407.         case BOTTOM:
  408.             for ( i = 1; i <= numVector - 1; i++ )
  409.             {
  410.                 for ( j = 0; j < numVector - i; j++ )
  411.                 {
  412.                     if ( vList[j].x > vList[j + 1].x )
  413.                     {
  414.                         /* 交换vList[j]和vList[j + 1] */
  415.                         vTemp = vList[j];
  416.                         vList[j] = vList[j + 1];
  417.                         vList[j + 1] = vTemp;
  418.                     }
  419.                 }
  420.             }
  421.             break;
  422.         default:
  423.             printf( "error in Sort" );
  424.             break;
  425.     }
  426. }
  427. /* 边界裁剪 */
  428. void EdgeClipping( Vector primitive[], int numVector )
  429. {
  430.     int i = 0, j = 0, k = 0, l = 0;
  431.     /* vList是多边形顶点及插入交点的序列
  432.        vEdgeList是区域ABCD四个点及插入交点的序列 */
  433.     VectorList vList = NULL;
  434.     Node *n = NULL, *m = NULL;
  435.     Vector vTemp, vNext;
  436.     Vector vIntersect[2];
  437.     int num = 0, numIntersect = 0, numEdge = 0;
  438.     Vector v1, v2;
  439.     Edge eTemp;
  440.     VectorType vType;
  441.     EdgeType eType;
  442.     Vector *polyList = NULL, *edgeList = NULL, *tempList = NULL;
  443.     Vector curStart;
  444.     Vector *clippedList = NULL;
  445.     int numClipped = 0;
  446.     /* 顺时针序列转为逆时针序列 */
  447.     for ( i = numVector - 1; i >= 0; i-- )
  448.     {
  449.         n = ( Node* )malloc( sizeof( Node ) );
  450.         n->v = primitive[i];
  451.         n->next = NULL;
  452.         if ( InsideEdge( n->v, AROUND ) )
  453.         {
  454.             n->v.type = INSIDE;
  455.         }
  456.         else
  457.         {
  458.             n->v.type = OUTSIDE;
  459.         }
  460.         PushBack( &vList, n );
  461.     }
  462.     /* 求各个交点,初始化vList */
  463.     n = vList;
  464.     while ( n != NULL )
  465.     {
  466.         if ( n->next == NULL )
  467.         {
  468.             vNext = vList->v;
  469.         }
  470.         else
  471.         {
  472.             vNext = n->next->v;
  473.         }
  474.         eTemp.v1 = n->v;
  475.         eTemp.v2 = vNext;
  476.         num = CalcIntersectPoints( eTemp, vIntersect );
  477.         numIntersect += num;
  478.         if ( num == 0 )
  479.         {
  480.             n = n->next;
  481.         }
  482.         if ( num == 1 )
  483.         {
  484.             if ( n->v.type == OUTSIDE )
  485.             {
  486.                 /* 交点是入点 */
  487.                 vType = EDGE_IN;
  488.             }
  489.             else
  490.             {
  491.                 /* 交点是出点 */
  492.                 vType = EDGE_OUT;
  493.             }
  494.             /* 添加到vList */
  495.             m = ( Node* )malloc( sizeof( Node ) );
  496.             m->v = vIntersect[0];
  497.             m->v.type = vType;
  498.             m->next = NULL;
  499.             Push( &vList, n, m );
  500.             n = n->next->next;
  501.         }
  502.         else if ( num == 2 )
  503.         {
  504.             /* 必定第一个交点是入点,第二个交点是出点 */
  505.             /* 添加第一个交点到vList */
  506.             m = ( Node* )malloc( sizeof( Node ) );
  507.             m->v = vIntersect[0];
  508.             m->v.type = EDGE_IN;
  509.             m->next = NULL;
  510.             Push( &vList, n, m );
  511.             n = m;
  512.             
  513.             /* 添加第二个交点到vList */
  514.             m = ( Node* )malloc( sizeof( Node ) );
  515.             m->v = vIntersect[1];
  516.             m->v.type = EDGE_OUT;
  517.             m->next = NULL;
  518.             Push( &vList, n, m );
  519.             n = m;
  520.             n = n->next;
  521.         }
  522.     }
  523.     polyList = ( Vector* )malloc( sizeof( Vector ) * ( numVector + numIntersect ) );
  524.     edgeList = ( Vector* )malloc( sizeof( Vector ) * ( 4 + numIntersect ) );
  525.     tempList = ( Vector* )malloc( sizeof( Vector ) * numIntersect );
  526.     /* 初始化polyList */
  527.     i = 0;
  528.     n = vList;
  529.     while ( n != NULL )
  530.     {
  531.         polyList[i].x = n->v.x;
  532.         polyList[i].y = n->v.y;
  533.         polyList[i].type = n->v.type;
  534.         n = n->next;
  535.         i++;
  536.     }
  537.     /*
  538.     for ( i = 0; i < numVector + numIntersect; i++)
  539.     {
  540.         printf("[%d](%d,%d) ", polyList[i].type, polyList[i].x - PRIMITIVE_LEFT_TOP.x, polyList[i].y - PRIMITIVE_LEFT_TOP.y );
  541.     }
  542.     printf("/n");
  543.     */
  544.     /* 初始化edgeList */
  545.     numEdge = 0;
  546.     /*
  547.       按逆时针DCBA
  548.       A----------B
  549.       |          |
  550.       |          |
  551.       |          |
  552.       D----------C
  553.     */
  554.     /* 插入D点 */
  555.     edgeList[numEdge].x = AREA_LEFT_TOP.x;
  556.     edgeList[numEdge].y = AREA_RIGHT_BOTTOM.y;
  557.     edgeList[numEdge].type = EDGE_CORNER;
  558.     numEdge++;
  559.     /* 寻找DC边上的点并排序 */
  560.     num = 0;
  561.     for ( i = 0; i < numVector + numIntersect; i++ )
  562.     {
  563.         if ( polyList[i].y == AREA_RIGHT_BOTTOM.y )
  564.         {
  565.             tempList[num] = polyList[i];
  566.             num++;
  567.         }
  568.     }
  569.     SortEdgeVectors( tempList, num, BOTTOM );
  570.     /* 插入DC上的点 */
  571.     for ( i = 0; i < num; i++ )
  572.     {
  573.         edgeList[numEdge] = tempList[i];
  574.         numEdge++;
  575.     }
  576.     /* 插入C点 */
  577.     edgeList[numEdge].x = AREA_RIGHT_BOTTOM.x;
  578.     edgeList[numEdge].y = AREA_RIGHT_BOTTOM.y;
  579.     edgeList[numEdge].type = EDGE_CORNER;
  580.     numEdge++;
  581.     /* 寻找CB边上的点并排序 */
  582.     num = 0;
  583.     for ( i = 0; i < numVector + numIntersect; i++ )
  584.     {
  585.         if ( polyList[i].x == AREA_RIGHT_BOTTOM.x )
  586.         {
  587.             tempList[num] = polyList[i];
  588.             num++;
  589.         }
  590.     }
  591.     SortEdgeVectors( tempList, num, RIGHT );
  592.     /* 插入CB上的点 */
  593.     for ( i = 0; i < num; i++ )
  594.     {
  595.         edgeList[numEdge] = tempList[i];
  596.         numEdge++;
  597.     }
  598.     /* 插入B点 */
  599.     edgeList[numEdge].x = AREA_RIGHT_BOTTOM.x;
  600.     edgeList[numEdge].y = AREA_LEFT_TOP.y;
  601.     edgeList[numEdge].type = EDGE_CORNER;
  602.     numEdge++;
  603.     /* 寻找BA边上的点并排序 */
  604.     num = 0;
  605.     for ( i = 0; i < numVector + numIntersect; i++ )
  606.     {
  607.         if ( polyList[i].y == AREA_LEFT_TOP.y )
  608.         {
  609.             tempList[num] = polyList[i];
  610.             num++;
  611.         }
  612.     }
  613.     SortEdgeVectors( tempList, num, TOP );
  614.     /* 插入BA上的点 */
  615.     for ( i = 0; i < num; i++ )
  616.     {
  617.         edgeList[numEdge] = tempList[i];
  618.         numEdge++;
  619.     }
  620.     /* 插入A点 */
  621.     edgeList[numEdge].x = AREA_LEFT_TOP.x;
  622.     edgeList[numEdge].y = AREA_LEFT_TOP.y;
  623.     edgeList[numEdge].type = EDGE_CORNER;
  624.     numEdge++;
  625.     /* 寻找AD边上的点并排序 */
  626.     num = 0;
  627.     for ( i = 0; i < numVector + numIntersect; i++ )
  628.     {
  629.         if ( polyList[i].x == AREA_LEFT_TOP.x )
  630.         {
  631.             tempList[num] = polyList[i];
  632.             num++;
  633.         }
  634.     }
  635.     SortEdgeVectors( tempList, num, LEFT );
  636.     /* 插入AD上的点 */
  637.     for ( i = 0; i < num; i++ )
  638.     {
  639.         edgeList[numEdge] = tempList[i];
  640.         numEdge++;
  641.     }
  642.     /*
  643.     for ( i = 0; i < numEdge; i++)
  644.     {
  645.         printf("[%d](%d,%d) ", edgeList[i].type, edgeList[i].x - PRIMITIVE_LEFT_TOP.x, edgeList[i].y - PRIMITIVE_LEFT_TOP.y );
  646.     }
  647.     printf("/n");
  648.     */
  649.     /* 边界裁剪算法开始进行 */
  650.     while ( TRUE )
  651.     {
  652.         /* 初始化输出数组 */
  653.         clippedList = ( Vector* )malloc( sizeof( Vector ) * ( numVector + numIntersect ) );
  654.         numClipped = 0;
  655.         /* 从polyList中找入点 */
  656.         for ( i = 0; polyList[i].type != EDGE_IN && i < numVector + numIntersect; i++ );
  657.         if ( i == numVector + numIntersect ) /* 没有找到入点,算法终止 */
  658.         {
  659.             /*printf( "End" );*/
  660.             break;
  661.         }
  662.         /* 将入点记为起始点 */
  663.         curStart = polyList[i];
  664.         while ( TRUE )
  665.         {
  666.             /* 入点进clippedList,并将该入点的入点标记删去 */
  667.             clippedList[numClipped++] = polyList[i];
  668.             /*printf("in(%d, %d)",clippedList[numClipped-1].x- PRIMITIVE_LEFT_TOP.x,clippedList[numClipped-1].y - PRIMITIVE_LEFT_TOP.y );*/
  669.             polyList[i].type = UNKNOWN;
  670.             /* 寻找出点 */
  671.             if ( i == numVector + numIntersect - 1 )
  672.             {
  673.                 j = 0;
  674.             }
  675.             else
  676.             {
  677.                 j = i + 1;
  678.             }
  679.             while ( TRUE )
  680.             {
  681.                 if ( polyList[j].type != EDGE_OUT )
  682.                 {
  683.                     /* 非出点进clippedList */
  684.                     clippedList[numClipped++] = polyList[j];
  685.                     /*printf("in(%d, %d)",clippedList[numClipped-1].x- PRIMITIVE_LEFT_TOP.x,clippedList[numClipped-1].y - PRIMITIVE_LEFT_TOP.y );*/
  686.                 }
  687.                 else
  688.                 {
  689.                     /* 找到了出点, 先把出点也进clippedList */
  690.                     clippedList[numClipped++] = polyList[j];
  691.                     /*printf("in(%d, %d)",clippedList[numClipped-1].x- PRIMITIVE_LEFT_TOP.x,clippedList[numClipped-1].y - PRIMITIVE_LEFT_TOP.y );*/
  692.                     break;
  693.                 }
  694.                 if ( j == numVector + numIntersect - 1 )
  695.                 {
  696.                     /* 到了polyList的末尾则调到开始继续寻找 */
  697.                     j = 0;
  698.                 }
  699.                 else if ( j == i )
  700.                 {
  701.                     /* 错误——没有找到出点!*/
  702.                     printf( "error-can not find out point" );
  703.                     return;
  704.                 }
  705.                 else
  706.                 {
  707.                     j++;
  708.                 }
  709.             }
  710.             /* 从polyList中找到了出点,接着从edgeList中找入点 */
  711.             /* 先从edgeList中找到与当前出点相同的点 */
  712.             for ( k = 0; edgeList[k].x != polyList[j].x || edgeList[k].y != polyList[j].y && k < numEdge; k++ );
  713.             /*printf("eOut(%d,%d)", edgeList[k].x- PRIMITIVE_LEFT_TOP.x,edgeList[k].y - PRIMITIVE_LEFT_TOP.y );*/
  714.             if ( k == numEdge )
  715.             {
  716.                 /* 错误——没有找到与polyList中出点相对应的边缘点! */
  717.                 printf( "error-can not find out point in edgeList/n" );
  718.                 return;
  719.             }
  720.             /* 接着寻找入点 */
  721.             if ( k == numEdge - 1 )
  722.             {
  723.                 l = 0;
  724.             }
  725.             else
  726.             {
  727.                 l = k + 1;
  728.             }
  729.             while ( TRUE )
  730.             {
  731.                 if ( edgeList[l].type != EDGE_IN )
  732.                 {
  733.                     /* 非入点进clippedList */
  734.                     clippedList[numClipped++] = edgeList[l];
  735.                     /*printf("in(%d, %d)",clippedList[numClipped-1].x- PRIMITIVE_LEFT_TOP.x,clippedList[numClipped-1].y - PRIMITIVE_LEFT_TOP.y );*/
  736.                 }
  737.                 else
  738.                 {
  739.                     /* 找到了入点 */
  740.                     break;
  741.                 }
  742.                 if ( l == numEdge - 1 )
  743.                 {
  744.                     /* 到了edgeList的末尾则调到开始继续寻找 */
  745.                     l = 0;
  746.                 }
  747.                 else if ( l == k )
  748.                 {
  749.                     /* 错误——没有找到入点! */
  750.                     printf( "error-can not find in point in edgeList/n" );
  751.                 }
  752.                 else
  753.                 {
  754.                     l++;
  755.                 }
  756.             }
  757.             /* 从edgeList中找到了入点, 判断是否与起点相等 */
  758.             if ( edgeList[l].x == curStart.x && edgeList[l].y == curStart.y )
  759.             {
  760.                 /* 与起点相等,哈哈~一个多边形区域被确定了! */
  761.                 clippedList[numClipped++] = edgeList[l];
  762.                 /*printf(" DONE " );*/
  763.                 break;
  764.             }
  765.             else
  766.             {
  767.                 clippedList[numClipped++] = edgeList[l];
  768.                 /* 与起点不相等 */
  769.                 /* 从polyList中找到与当前入点相同的点 */
  770.                 for ( i = 0; polyList[i].x != edgeList[l].x || polyList[i].y != edgeList[l].y && i < numVector + numIntersect; i++ );
  771.                 if ( i == numVector + numIntersect )
  772.                 {
  773.                     /* 错误——没有找到与edgeList中出点相对应的边缘点! */
  774.                     printf( "error-can not find out point in edgeList/n" );
  775.                     return;
  776.                 }
  777.                 continue;
  778.             }
  779.         }
  780.         /* 上面这个while循环确定一个多边形区域,接着绘制这份多边形区域 */
  781.         setcolor( RED );
  782.         setlinestyle( SOLID_LINE, 0, 3 );
  783.         for ( i = 0; i < numClipped - 1; i++ )
  784.         {
  785.             line( clippedList[i].x, clippedList[i].y, clippedList[i + 1].x, clippedList[i + 1].y );
  786.         }
  787.         /*
  788.         for ( i = 0; i < numClipped; i++ )
  789.         {
  790.             printf( "(%d,%d)", clippedList[i].x - PRIMITIVE_LEFT_TOP.x,clippedList[i].y - PRIMITIVE_LEFT_TOP.x );
  791.         }
  792.         printf("/n");
  793.         */
  794.         free( clippedList );
  795.     }
  796.     free( polyList );
  797.     free( edgeList );
  798. }
  799. int main()
  800. {
  801.     int gdriver = VGA , gmode = VGAHI;
  802.     Vector primitive[VECTOR_NUM + 1];
  803.     int i = 0;
  804.     char cmd = ' ';
  805.     primitive[0].x = PRIMITIVE_LEFT_TOP.x + 35;
  806.     primitive[0].y = PRIMITIVE_LEFT_TOP.y;
  807.     primitive[1].x = PRIMITIVE_LEFT_TOP.x + 200;
  808.     primitive[1].y = PRIMITIVE_LEFT_TOP.y + 60;
  809.     primitive[2].x = PRIMITIVE_LEFT_TOP.x + 130;
  810.     primitive[2].y = PRIMITIVE_LEFT_TOP.y + 140;
  811.     primitive[3].x = PRIMITIVE_LEFT_TOP.x;
  812.     primitive[3].y = PRIMITIVE_LEFT_TOP.y + 80;
  813.     primitive[4].x = PRIMITIVE_LEFT_TOP.x + 60;
  814.     primitive[4].y = PRIMITIVE_LEFT_TOP.y + 60;
  815.     primitive[5].x = PRIMITIVE_LEFT_TOP.x + 60;
  816.     primitive[5].y = PRIMITIVE_LEFT_TOP.y + 20;
  817.     primitive[6].x = PRIMITIVE_LEFT_TOP.x + 40;
  818.     primitive[6].y = PRIMITIVE_LEFT_TOP.y + 40;
  819.     primitive[7] = primitive[0];
  820.     initgraph (&gdriver , &gmode , "d://");
  821.     while ( TRUE )
  822.     {
  823.         cleardevice();
  824.         setcolor( WHITE );
  825.         setlinestyle( SOLID_LINE, 0, 1 );
  826.         for ( i = 0; i < VECTOR_NUM; i++ )
  827.         {
  828.             line( primitive[i].x, primitive[i].y, primitive[i + 1].x, primitive[i + 1].y );
  829.         }
  830.         setlinestyle( DOTTED_LINE, 0, 1 );
  831.         rectangle( AREA_LEFT_TOP.x, AREA_LEFT_TOP.y, AREA_RIGHT_BOTTOM.x, AREA_RIGHT_BOTTOM.y );
  832.         outtext( "Enter the key:" );
  833.         outtextxy( 20, 10, "'1': Sutherland - Hodgeman Clipping." );
  834.         outtextxy( 20, 20, "'2': Weiler - Atherton Clipping." );
  835.         outtextxy( 20, 30, "'q': Quit." );
  836.         cmd = getch();
  837.         if ( cmd == '1' )
  838.         {
  839.             SingleEdgeClipping( primitive, VECTOR_NUM );
  840.             getch();
  841.         }
  842.         else if ( cmd == '2' )
  843.         {
  844.             EdgeClipping( primitive, VECTOR_NUM );
  845.             getch();
  846.         }
  847.         else if ( cmd == 'q' )
  848.         {
  849.             closegraph();
  850.             return 0;
  851.         }
  852.     }
  853.     /* should never be here */
  854.     closegraph();
  855.     return 0;
  856. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值