規則區域填充

OpenGL

// ConsoleApplication1.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"
#include "gl/glut.h"
#include "windows.h"
const int POINTNUM=7;      //多邊形點數.

/******定義結構體用於活性邊表AET和新邊表NET***********************************/
 typedef struct XET
 {
  float x;
  float dx,ymax;
  XET* next;
 }AET,NET;

/******定義點結構體point******************************************************/
 struct point
 {
  float x;
  float y;
 }
 polypoint[POINTNUM]={250,50,550,150,550,400,250,250,100,350,100,100,120,30};//多邊形頂點

 void PolyScan()
{
/******計算最高點的y座標(掃描到此結束)****************************************/
 int MaxY=0;
 int i;
 for(i=0;i<POINTNUM;i++)
  if(polypoint[i].y>MaxY)
   MaxY=polypoint[i].y;

/*******初始化AET表***********************************************************/
  AET *pAET=new AET;
  pAET->next=NULL;

/******初始化NET表************************************************************/
  NET *pNET[1024];
  for(i=0;i<=MaxY;i++)
  {
   pNET[i]=new NET;
   pNET[i]->next=NULL;
  }
  glClear(GL_COLOR_BUFFER_BIT);        //賦值的窗口顯示.  
  glColor3f(0.0,0.0,0.0);             //設置直線的顏色紅色
  glBegin(GL_POINTS);
/******掃描並建立NET表*********************************************************/
  for(i=0;i<=MaxY;i++)
  {
   for(int j=0;j<POINTNUM;j++)
    if(polypoint[j].y==i)
    {  //一個點跟前面的一個點形成一條線段,跟後面的點也形成線段   
     if(polypoint[(j-1+POINTNUM)%POINTNUM].y>polypoint[j].y)
     {
      NET *p=new NET;
      p->x=polypoint[j].x;
      p->ymax=polypoint[(j-1+POINTNUM)%POINTNUM].y;
      p->dx=(polypoint[(j-1+POINTNUM)%POINTNUM].x-polypoint[j].x)/(polypoint[(j-1+POINTNUM)%POINTNUM].y-polypoint[j].y);
      p->next=pNET[i]->next;
      pNET[i]->next=p;

     }
     if(polypoint[(j+1+POINTNUM)%POINTNUM].y>polypoint[j].y)
     {
      NET *p=new NET;      
      p->x=polypoint[j].x;
      p->ymax=polypoint[(j+1+POINTNUM)%POINTNUM].y;
      p->dx=(polypoint[(j+1+POINTNUM)%POINTNUM].x-polypoint[j].x)/(polypoint[(j+1+POINTNUM)%POINTNUM].y-polypoint[j].y);
      p->next=pNET[i]->next;
      pNET[i]->next=p;
     }
    }
  }
/******建立並更新活性邊表AET*****************************************************/
for(i=0;i<=MaxY;i++)
  {
 //計算新的交點x,更新AET
   NET *p=pAET->next;
   while(p)
   {
    p->x=p->x + p->dx;
    p=p->next;
   }
 //更新後新AET先排序*************************************************************/
    //斷表排序,不再開闢空間
   AET *tq=pAET;
   p=pAET->next;
   tq->next=NULL;
   while(p)
   {
    while(tq->next && p->x >= tq->next->x)
     tq=tq->next;
    NET *s=p->next;
    p->next=tq->next;
    tq->next=p;
    p=s;
    tq=pAET;
   }
 //(改進算法)先從AET表中刪除ymax==i的結點****************************************/
   AET *q=pAET;
   p=q->next;
   while(p)
   {
    if(p->ymax==i)
    {
     q->next=p->next;
     delete p;
     p=q->next;
    }
    else
    {
     q=q->next;
     p=q->next;
    }
   }
 //將NET中的新點加入AET,並用插入法按X值遞增排序**********************************/
   p=pNET[i]->next;
   q=pAET;
   while(p)
   {
    while(q->next && p->x >= q->next->x)
     q=q->next;
    NET *s=p->next;
    p->next=q->next;
    q->next=p;
    p=s;
    q=pAET;
   }
/******配對填充顏色***************************************************************/

             p=pAET->next;
   while(p && p->next)
   {
    for(float j=p->x;j<=p->next->x;j++)
     glVertex2i(static_cast<int>(j),i);
    p=p->next->next;//考慮端點情況
   }


  }
   glEnd();
glFlush(); 
}
void init(void)
{glClearColor(1.0,1.0,1.0,0.0);
//窗口的背景顏色設置爲白色
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0,600.0,0.0,450.0);
}

int main(int argc,char* argv)
{
    glutInit(&argc,&argv);                //I初始化 GLUT.
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);    //設置顯示模式:單個緩存和使用RGB模型
    glutInitWindowPosition(50,100);        //設置窗口的頂部和左邊位置
    glutInitWindowSize(400,300);        //設置窗口的高度和寬度
    glutCreateWindow("An Example OpenGL Program");    //創建顯示窗口

    init();                                //調用初始化過程
    glutDisplayFunc(PolyScan);        //圖形的定義傳遞給我window.
    glutMainLoop();                        //顯示所有的圖形並等待
    return 0;
}

這裏寫圖片描述


Win32應用程序

// Win32Project1.cpp : 定義應用程序的入口點。
//

#include "stdafx.h"
#include "Win32Project1.h"

// altwind.c

#include <windows.h>

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );

int WINAPI WinMain(
    HINSTANCE   hInstance,
    HINSTANCE   hPrevInstance,
    LPSTR       lpszCmdLine,
    int         nCmdShow
    )
{
    static TCHAR    szAppName[] = TEXT("altwind");

    WNDCLASS    wndclass;
    HWND        hWnd;
    MSG         msg;

    wndclass.style          = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc    = WndProc;
    wndclass.cbClsExtra     = 0;
    wndclass.cbWndExtra     = 0;
    wndclass.hInstance      = hInstance;
    wndclass.hIcon          = LoadIcon( NULL, IDI_APPLICATION );
    wndclass.hCursor        = LoadCursor( NULL, IDC_ARROW );
    wndclass.hbrBackground  = (HBRUSH)GetStockObject( WHITE_BRUSH );
    wndclass.lpszMenuName   = NULL;
    wndclass.lpszClassName  = szAppName;

    RegisterClass( &wndclass );

    hWnd = CreateWindow(
        szAppName, TEXT("Alternate and Winding Fill Modes"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL
    );

    ShowWindow( hWnd, nCmdShow );
    UpdateWindow( hWnd );

    while ( GetMessage( &msg, NULL, 0, 0 ) )
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }

    return msg.wParam;
}


LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    static POINT aptFigure[10] = { 10,70, 50,70, 50,10, 90,10, 90,50,
        30,50, 30,90, 70,90, 70,30, 10,30 };

    static int      cxClient, cyClient;

    POINT       apt[10];

    HDC             hdc;
    PAINTSTRUCT     ps;

    int     i;

    switch ( message )
    {
    case WM_SIZE:
        cxClient = LOWORD( lParam );
        cyClient = HIWORD( lParam );    

        return 0;

    case WM_PAINT:
        hdc = BeginPaint( hWnd, &ps );

        SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
        for ( i = 0; i < 10; i++ ) // 注意不能將其放在WM_SIZE的響應中
        { // 因爲ShowWindow和UpdateWindow並不產生WM_SIZE消息,而後者直接產生WM_PAINT消息
            apt[i].x = aptFigure[i].x * cxClient / 200;
            apt[i].y = aptFigure[i].y * cyClient / 100;
        } // 如果將其放在WM_SIZE響應中則剛開始ShowWindow並Update的時候使用的是未初始化的apt
        // 將什麼都顯示不出來!

        SetPolyFillMode( hdc, ALTERNATE );
        Polygon( hdc, apt, 10 );

        for ( i = 0; i < 10; i++ ) // 右邊的Winding填充方式
        {
            apt[i].x += cxClient / 2;
        }

        SetPolyFillMode( hdc, WINDING );
        Polygon( hdc, apt, 10 );

        EndPaint( hWnd, &ps );
        return 0;

    case WM_DESTROY:
        PostQuitMessage( 0 );
        return 0;
    }

    return DefWindowProc( hWnd, message, wParam, lParam );
}

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章