- #include "stdio.h"
- #include "graphics.h"
- #include "malloc.h"
- #include "conio.h"
- #include "math.h"
- /*******************************扫描线种子填充*********************/
- #define LEFT 200
- #define TOP 200
- #define TRUE 1
- #define FALSE 0
- #define BOUND WHITE
- #define DELAYTIME 10000
- typedef struct
- {
- int x;
- int y;
- } Data;
- typedef struct _Node
- {
- Data data;
- struct _Node *next;
- } Node, *List;
- typedef struct _Stack
- {
- Node *top;
- } Stack;
- /* 初始化栈 */
- void Init( Stack *s )
- {
- s->top = NULL;
- }
- /* 入栈 */
- void Push( Stack *s, Data d )
- {
- Node *newN = ( Node * )malloc( sizeof( Node ) );
- newN->data.x = d.x;
- newN->data.y = d.y;
- newN->next = s->top;
- s->top = newN;
- /*printf("Push %d, %d to Stack/n", s->top->data.x, s->top->data.y );*/
- }
- /* 出栈 */
- Data Pop( Stack *s )
- {
- Node *toPop = s->top;
- Data d = toPop->data;
- s->top = s->top->next;
- free (toPop);
- /*printf("Pop %d, %d from Stack/n", d.x, d.y );*/
- /*printf("p:%d,%d ", d.x-LEFT, d.y-TOP);*/
- return d;
- }
- /* 检测栈是否为空 */
- int Empty( Stack *s )
- {
- if ( s->top == NULL )
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
- Data GetTop( Stack *s )
- {
- if ( Empty( s ) != 0 )
- {
- return s->top->data;
- }
- }
- /* 扫描线种子填充 */
- void SeedFill( int seedX, int seedY, int color )
- {
- Data seed, newSeed;
- int xLeft, xRight, xCurrent, yCurrent;
- int needFill = FALSE;
- Stack seedStack;
- Init( &seedStack );
- seed.x = seedX;
- seed.y = seedY;
- /* 种子入栈 */
- Push( &seedStack, seed );
- while ( Empty( &seedStack ) == FALSE )
- {
- /* 种子出栈并给点上色 */
- seed = Pop( &seedStack );
- putpixel( seed.x, seed.y, color );
- /* 填充当前扫描线位于种子左边的部分 */
- xCurrent = seed.x - 1;
- yCurrent = seed.y;
- while ( getpixel( xCurrent, yCurrent ) != color &
- getpixel( xCurrent, yCurrent ) != BOUND )
- {
- putpixel( xCurrent, yCurrent, color );
- xCurrent -= 1;
- }
- /* 记录最左侧的内点 */
- xLeft = xCurrent + 1;
- /* 填充当前扫描线位于种子右边的部分 */
- xCurrent = seed.x + 1;
- yCurrent = seed.y;
- while ( getpixel( xCurrent, yCurrent ) != color &
- getpixel( xCurrent, yCurrent ) != BOUND )
- {
- putpixel( xCurrent, yCurrent, color );
- xCurrent += 1;
- }
- /* 记录最右侧的内点 */
- xRight = xCurrent - 1;
- /*printf("left: %d, %d 's color is %d/n", xLeft, yCurrent, getpixel(xLeft, xRight));*/
- /* 上移一条扫描线*/
- yCurrent = seed.y - 1;
- xCurrent = xLeft;
- /* 从左向右检测非边界、未填充的象素 */
- while ( xCurrent < xRight )
- {
- while ( getpixel( xCurrent, yCurrent ) != color &
- getpixel( xCurrent, yCurrent ) != BOUND )
- {
- /* 存在未填充的像素,则需要填充 */
- needFill = TRUE;
- xCurrent += 1;
- }
- /* 最右侧像素入栈 */
- if ( needFill == TRUE )
- {
- newSeed.x = xCurrent - 1;
- newSeed.y = yCurrent;
- Push( &seedStack, newSeed );
- needFill = FALSE;
- break;
- }
- xCurrent++;
- }
- delay(DELAYTIME);
- needFill = FALSE;
- /* 下移一条扫描线 */
- yCurrent = seed.y + 1;
- xCurrent = xLeft;
- /* 从左向右检测非边界、未填充的象素 */
- while ( xCurrent < xRight )
- {
- while ( getpixel( xCurrent, yCurrent ) != color &
- getpixel( xCurrent, yCurrent ) != BOUND )
- {
- /* 存在未填充的像素,则需要填充 */
- needFill = TRUE;
- xCurrent += 1;
- }
- /* 最右侧像素入栈 */
- if ( needFill == TRUE )
- {
- newSeed.x = xCurrent - 1;
- newSeed.y = yCurrent;
- Push( &seedStack, newSeed );
- needFill = FALSE;
- break;
- }
- xCurrent++;
- }
- delay(DELAYTIME);
- }
- }
- /*********************End of 扫描线种子填充*********************************/
- /**********************************剖面线种子填充******************************/
- #define BIG_PLUS_INT 65534
- #define K -1.0f
- #define DELTA_B 5.0f
- /* 顶点 */
- typedef struct _Vector
- {
- int x, y;
- } Vector;
- /* 边 */
- typedef struct _Edge
- {
- Vector v1, v2;
- } Edge;
- /******************************************************
- * summery
- * 求得剖面线的画线范围和总数,求得各条边的可相交范围
- * in
- * e[] - 边信息
- * numEdge - 图元的边数
- * k - 剖面线的斜率
- * bDelta - 相邻两条剖面线的距离
- * inout
- * bMinMax[] - 剖面线的画线范围
- * edgeMinMax[][2] - 各条边的可相交范围
- * out
- * int - 剖面线的画线总数
- *******************************************************/
- int CalcPrimitiveInfo( Edge e[], int numEdge, float k, float bDelta, float bMinMax[], float edgeMinMax[][2] )
- {
- int i;
- float tempF;
- float bMin = BIG_PLUS_INT, bMax = -BIG_PLUS_INT;
- int numHatching;
- for ( i = 0; i < numEdge; i++ )
- {
- edgeMinMax[i][0] = e[i].v1.y - k * e[i].v1.x;
- edgeMinMax[i][1] = e[i].v2.y - k * e[i].v2.x;
- if ( edgeMinMax[i][0] > edgeMinMax[i][1] )
- {
- /* 交换 */
- tempF = edgeMinMax[i][0];
- edgeMinMax[i][0] = edgeMinMax[i][1];
- edgeMinMax[i][1] = tempF;
- }
- if ( edgeMinMax[i][0] < bMin )
- {
- /* 替换Min */
- bMin = edgeMinMax[i][0];
- }
- if ( edgeMinMax[i][1] > bMax )
- {
- /* 替换Max */
- bMax = edgeMinMax[i][1];
- }
- }
- bMinMax[0] = bMin;
- bMinMax[1] = bMax;
- numHatching = ( bMax - bMin ) / bDelta;
- return numHatching;
- }
- /******************************************************
- * summery
- * 计算剖面线和边的交点
- * in
- * e - 边信息
- * k - 剖面线的斜率
- * b - 当前剖面线的b值
- * out
- * *point - 交点
- *******************************************************/
- void CalcIntersectPoint( Edge e, float k, float b, Vector *point)
- {
- float m, n, t;
- m = e.v1.x * e.v2.y - e.v1.y * e.v2.x + b * ( e.v2.x - e.v1.x );
- n = e.v2.y - e.v1.y - k * ( e.v2.x - e.v1.x );
- t = m / n;
- point->x = floor( t + 0.5f );
- point->y = floor( k * t + b + 0.5f );
- }
- /******************************************************
- * summery
- * 对交点按照交点的x值进行排序
- * inout
- * points[] - 交点数组
- * in
- * numPoints - 交点总数
- *******************************************************/
- void SortPoints( Vector points[], int numPoints )
- {
- int i, j;
- int tempX, tempY;
- for ( i = 1; i <= numPoints - 1; i++ )
- {
- for ( j = 0; j < numPoints - i; j++ )
- {
- if ( points[j].x > points[j + 1].x )
- {
- /* 交换points[j]和points[j + 1] */
- tempX = points[j].x;
- tempY = points[j].y;
- points[j].x = points[j + 1].x;
- points[j].y = points[j + 1].y;
- points[j + 1].x = tempX;
- points[j + 1].y = tempY;
- }
- }
- }
- }
- /******************************************************
- * summery
- * 画剖面线
- * in
- * e[] - 边信息
- * numEdge - 图元的边数
- * k - 剖面线的斜率
- * bDelta - 相邻两条剖面线的距离
- * edgeMinMax[][2] - 各条边的可相交范围
- * out
- * int - 剖面线的画线总数
- *******************************************************/
- void DrawHatching( Edge e[], int numEdges, float bMinMax[], float edgeMinMax[][2], float k, float b )
- {
- int i, j, n = 0, nRealSectP = 0;
- Vector *points = ( Vector* )malloc( numEdges * sizeof( Vector ) ); /* 一条剖面线与边的交点总数不可能超过边的总数 */
- Vector v[2];
- int numPoints = 0;
- if ( b <= bMinMax[0] || b >= bMinMax[1] )
- {
- return;
- }
- /* 计算剖面线与所有边的交点 */
- for ( i = 0; i < numEdges; i++ )
- {
- if ( b >= edgeMinMax[i][0] && b <= edgeMinMax[i][1] )
- {
- /* 求交点 */
- CalcIntersectPoint( e[i], k, b, &( points[numPoints] ) );
- numPoints++;
- }
- }
- /* 对这些交点进行排序 */
- SortPoints( points, numPoints );
- /* 绘制剖面线 */
- i = 0;
- nRealSectP = 0;
- while ( i < numPoints - 1 )
- {
- /*printf("i:%d, n:%d;", i, nRealSectP );*/
- /* 有重合的点 */
- if ( points[i].x == points[i + 1].x )
- {
- /* 找出共享该顶点的两条边的另外两个顶点 */
- n = 0;
- for ( j = 0; j < numEdges; j++ )
- {
- if ( e[j].v1.x == points[i].x && e[j].v1.y == points[i].y )
- {
- v[n] = e[j].v2;
- n++;
- }
- if ( e[j].v2.x == points[i].x && e[j].v2.y == points[i].y )
- {
- v[n] = e[j].v1;
- n++;
- }
- if ( n >= 2 )
- {
- break;
- }
- }
- /* 判断这两个顶点在剖面线的同侧还是异侧 */
- if ( ( v[0].y - k * v[0].x - b ) * ( v[1].y - k * v[1].x - b ) > 0 )
- {
- /* 在同侧,计两个交点,故nRealSectP需要再加一 */
- nRealSectP++;
- }
- else
- {
- /* 在异侧,计一个交点,故nRealSectP不需要改变 */
- }
- }
- else
- {
- if ( nRealSectP % 2 == 0 )
- {
- line( points[i].x, points[i].y, points[i + 1].x, points[i + 1].y );
- }
- nRealSectP++;
- }
- i++;
- }
- free( points );
- }
- /*************************End of 剖面线填充************************************/
- int main()
- {
- int gdriver = VGA , gmode = VGAHI;
- int polyPoints[6][2];
- char cmd;
- int i;
- Vector v[9];
- Edge e[9];
- float bMinMax[2];
- float edgeMinMax[9][2];
- int numHatching;
- float bCurrent;
- initgraph ( &gdriver , &gmode , "d://" );
- polyPoints[0][0] = 5 + LEFT;
- polyPoints[0][1] = 20 + TOP;
- polyPoints[1][0] = 35 + LEFT;
- polyPoints[1][1] = 0 + TOP;
- polyPoints[2][0] = 65 + LEFT;
- polyPoints[2][1] = 20 + TOP;
- polyPoints[3][0] = 85 + LEFT;
- polyPoints[3][1] = 70 + TOP;
- polyPoints[4][0] = 0 + LEFT;
- polyPoints[4][1] = 70 + TOP;
- polyPoints[5][0] = 5 + LEFT;
- polyPoints[5][1] = 20 + TOP;
- v[0].x = polyPoints[0][0];
- v[0].y = polyPoints[0][1];
- v[1].x = polyPoints[1][0];
- v[1].y = polyPoints[1][1];
- v[2].x = polyPoints[2][0];
- v[2].y = polyPoints[2][1];
- v[3].x = polyPoints[3][0];
- v[3].y = polyPoints[3][1];
- v[4].x = polyPoints[4][0];
- v[4].y = polyPoints[4][1];
- v[5].x = 15 + LEFT;
- v[5].y = 20 + TOP;
- v[6].x = 55 + LEFT;
- v[6].y = 20 + TOP;
- v[7].x = 55 + LEFT;
- v[7].y = 40 + TOP;
- v[8].x = 15 + LEFT;
- v[8].y = 40 + TOP;
- e[0].v1 = v[0];
- e[0].v2 = v[1];
- e[1].v1 = v[1];
- e[1].v2 = v[2];
- e[2].v1 = v[2];
- e[2].v2 = v[3];
- e[3].v1 = v[3];
- e[3].v2 = v[4];
- e[4].v1 = v[4];
- e[4].v2 = v[0];
- e[5].v1 = v[5];
- e[5].v2 = v[6];
- e[6].v1 = v[6];
- e[6].v2 = v[7];
- e[7].v1 = v[7];
- e[7].v2 = v[8];
- e[8].v1 = v[8];
- e[8].v2 = v[5];
- while ( TRUE )
- {
- cleardevice();
- outtext( "Enter the key:" );
- outtextxy( 20, 10, "'1': Fill with scanning line." );
- outtextxy( 20, 20, "'2': Fill with hatching." );
- outtextxy( 20, 30, "'q': Quit." );
- setcolor( BOUND );
- drawpoly( 6, *polyPoints );
- rectangle( v[5].x, v[5].y, v[7].x, v[7].y );
- cmd = getch();
- if ( cmd == '1' )
- {
- SeedFill( LEFT + 35, TOP + 60, BLUE );
- getch();
- }
- else if ( cmd == '2' )
- {
- numHatching = CalcPrimitiveInfo( e, 9, K, DELTA_B, bMinMax, edgeMinMax );
- for ( i = 1; i <= numHatching; i++ )
- {
- bCurrent = bMinMax[0] + DELTA_B * i;
- DrawHatching( e, 9, bMinMax, edgeMinMax, K, bCurrent );
- delay( DELAYTIME );
- }
- getch();
- }
- else if ( cmd == 'q' )
- {
- closegraph();
- return 1;
- }
- }
- /* should never be here */
- getch();
- closegraph () ;
- }
区域填充:扫描线种子填充和剖面线填充
最新推荐文章于 2024-01-13 12:51:34 发布