填充实心多边形(二)

OpenGL(二)图形绘制之多边形面的绘制 本次通过绘制一个三角形来学习相关的知识。 #include #include #include #include #include //窗口的大小 GLsizei windowWidth; GLsizei windowHeight; //旋转角度参数 static GLfloat xRot = 0.0f; static GLfloat yRot = 0.0f; //确定多边形的绕 阅读详情

 上一篇文章介绍了填充四边形及三角形,那么对于五边形,六边形呢?当然也可以把五边形分解成3个三角形,六边形分解成4个三角形进行填充。推而广之,可以把n边形分解成n-2个三角形来进行填充。这里介绍另一个方法。如图所示。

这是更为一般化的填充(光栅化?)实心多边形方法。找到多边形各顶点中y轴坐标最小的点作为起始点,按顺时针设置各顶点标号,然后从逆时针方向和顺时针方向同时出发,当一条边到达一个终点(另一个顶点)时,重新计算插值,继续下去直到完成光栅化。代码清单如下:

  1. /* 2008/9/6 
  2. 代码功能:光栅化
  3. 多边形的一般方法*/
  4. #define WIN32_LEAN_AND_MEAN   //不使用MFC
  5. #define INITGUID      //使用GUID
  6. #include <windows.h>
  7. #include <windowsx.h>
  8. #include <mmsystem.h> //多媒体API
  9. #include <iostream.h>
  10. #include <conio.h>    //控制台IO支持
  11. #include <stdlib.h>   //声明定义的一些常用标准函数库
  12. #include <malloc.h>   //声明或定义一些内存的函数
  13. #include <memory.h>   //提供了内存操作相关的一些函数及声明
  14. #include <string.h>   //字符串的一些功能
  15. #include <stdarg.h>   //defines ANSI-style macros for variable argument functions
  16. #include <stdio.h>    //efinitions/declarations for standard I/O routines
  17. #include <math.h>     //一些数学方法
  18. #include <io.h>       //declarations for low-level file handling and I/O functions
  19. #include <fcntl.h>    //file control options used by open()
  20. #include <ddraw.h>
  21. //windows类名
  22. #define  WINDOW_CLASS_NAME "WINCLASS1"
  23. //宽,高,色深(像素)
  24. #define  SCREEN_WIDTH   640
  25. #define  SCREEN_HEIGHT   480
  26. #define  SCREEN_BPP     8
  27. #define  MAX_COLORS_PALETTE   256
  28. #define  PI 3.1415926535
  29. typedef unsigned short USHORT;
  30. typedef unsigned short WORD;
  31. typedef unsigned char UCHAR;
  32. typedef unsigned char BYTE;
  33. typedef struct VERTEX2DF_TYP 
  34. {
  35.   float x,y;
  36. }VERTEX2DF,*VERTEX2DF_PTR;
  37. typedef struct POLYGON2D_TYP 
  38. {
  39.   int state;
  40.   int num_vert;
  41.   int x0,y0;
  42.   int xv,yv;
  43.   DWORD color;
  44.   VERTEX2DF* vlist;
  45. }POLYGON2D,*POLYGON2D_PTR;
  46. //GDI文字函数
  47. int Draw_Text_GDI(char* text,int x,int y,int color,LPDIRECTDRAWSURFACE7 lpdds);
  48. //填充表面
  49. int DDraw_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color);
  50. //旋转图形
  51. int Rotate_Polygon2D(POLYGON2D_PTR poly,int theta);
  52. //填充2D图形
  53. int Draw_Filled_Polygon2D(POLYGON2D_PTR poly,UCHAR* vbuffer,int mempitch);
  54. //设置调色板入口
  55. int Set_Palette_Entry(int color_index,LPPALETTEENTRY color);
  56. //键盘按键宏
  57. #define  KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code)&0x8000)?1:0)
  58. #define  KEYUP(vk_code)   ((GetAsyncKeyState(vk_code)&0x8000)?0:1)
  59. //初始化结构体
  60. #define  DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct));ddstruct.dwSize=sizeof(ddstruct); }
  61. HWND main_window_handle =NULL;
  62. int  window_closed =0;
  63. HINSTANCE hinstance_app =NULL;
  64. LPDIRECTDRAW7 lpdd =NULL;
  65. LPDIRECTDRAWSURFACE7 lpddsprimary =NULL;  //主缓存
  66. LPDIRECTDRAWSURFACE7 lpddsback =NULL;     //后备缓冲
  67. LPDIRECTDRAWPALETTE  lpddpal =NULL;       //调色板接口
  68. LPDIRECTDRAWCLIPPER  lpddclipper =NULL;   //裁剪器
  69. PALETTEENTRY         palette[256];        //调色板
  70. DDSURFACEDESC2       ddsd;
  71. DDBLTFX              ddbltfx;
  72. DDSCAPS2             ddscaps;
  73. /*裁剪区域*/
  74. int min_clip_x = 0,
  75.     max_clip_x =SCREEN_WIDTH-1, 
  76.     min_clip_y = 0,
  77.     max_clip_y = SCREEN_HEIGHT-1;
  78. char buffer[80];
  79. float cos_look[360],
  80.       sin_look[360];
  81. POLYGON2D object;
  82. int Draw_Text_GDI(char* text,int x,int y,int color,LPDIRECTDRAWSURFACE7 lpdds)
  83. {
  84.   HDC xdc;
  85.   if(FAILED(lpdds->GetDC(&xdc)))
  86.     return(0);
  87.   SetTextColor(xdc,RGB(palette[color].peRed,palette[color].peGreen,palette[color].peBlue));
  88.   SetBkMode(xdc,TRANSPARENT);
  89.   TextOut(xdc,x,y,text,strlen(text));
  90.   lpdds->ReleaseDC(xdc);
  91.   return(1);
  92. }
  93. int DDraw_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color)
  94. {
  95.   DDRAW_INIT_STRUCT(ddbltfx);
  96.   ddbltfx.dwFillColor=color;
  97.   lpdds->Blt(NULL,
  98.              NULL,
  99.              NULL,
  100.              DDBLT_COLORFILL|DDBLT_WAIT,
  101.              &ddbltfx);
  102.   return(1);
  103. }
  104. int Set_Palette_Entry(int color_index,LPPALETTEENTRY color)
  105. {
  106.   lpddpal->SetEntries(0,color_index,1,color);
  107.   memcpy(&palette[1],color,sizeof(PALETTEENTRY));
  108.   return(1);
  109. }
  110. int Rotate_Polygon2D(POLYGON2D_PTR poly, int theta)
  111. {
  112. // this function rotates the local coordinates of the polygon
  113. // test for valid pointer
  114. if (!poly)
  115.    return(0);
  116. // loop and rotate each point, very crude, no lookup!!!
  117. for (int curr_vert = 0; curr_vert < poly->num_vert; curr_vert++)
  118.     {
  119.     // perform rotation
  120.     float xr = (float)poly->vlist[curr_vert].x*cos_look[theta] - 
  121.                     (float)poly->vlist[curr_vert].y*sin_look[theta];
  122.     float yr = (float)poly->vlist[curr_vert].x*sin_look[theta] + 
  123.                     (float)poly->vlist[curr_vert].y*cos_look[theta];
  124.     // store result back
  125.     poly->vlist[curr_vert].x = xr;
  126.     poly->vlist[curr_vert].y = yr;
  127.     } // end for curr_vert
  128. // return success
  129. return(1);
  130. } // end Rotate_Polygon2D
  131. int Draw_Filled_Polygon2D(POLYGON2D_PTR poly,UCHAR *vbuffer,int mempitch)
  132. {
  133.   int ydiff1,ydiff2,
  134.       xdiff1,xdiff2,
  135.       start,
  136.       length,
  137.       errorterm1,errorterm2,
  138.       offset1,offset2,
  139.       count1,count2,
  140.       xunit1,xunit2;
  141.   int edgecount = poly->num_vert-1;
  142.   int firstvert=0;
  143.   int min_y=poly->vlist[0].y;
  144.   
  145.   for (int index=1;index<poly->num_vert;index++)
  146.   {/*找到y轴坐标最小的顶点*/
  147.     
  148.     if ((poly->vlist[index].y)<min_y)
  149.     {
  150.       firstvert=index;
  151.       min_y=poly->vlist[index].y;
  152.     }
  153.   }
  154.   int startvert1=firstvert;
  155.   int startvert2=firstvert;
  156.   int xstart1=poly->vlist[startvert1].x+poly->x0;  //逆时针移动的初始位置
  157.   int ystart1=poly->vlist[startvert1].y+poly->y0;
  158.   int xstart2=poly->vlist[startvert2].x+poly->x0;  //顺时针移动的初始位置
  159.   int ystart2=poly->vlist[startvert2].y+poly->y0;
  160.   /*取得逆时针移动遇到的第1个顶点坐标*/
  161.   int endvert1=startvert1-1;
  162.   if (endvert1<0)
  163.     endvert1=poly->num_vert-1;
  164.   int xend1=poly->vlist[endvert1].x+poly->x0;
  165.   int yend1=poly->vlist[endvert1].y+poly->y0;
  166.   
  167.   /*取得顺时针移动遇到的第1个顶点坐标*/
  168.   int endvert2=startvert2+1;
  169.   if(endvert2==(poly->num_vert))
  170.     endvert2=0;
  171.   int xend2=poly->vlist[endvert2].x+poly->x0;
  172.   int yend2=poly->vlist[endvert2].y+poly->y0;
  173.   //绘制并填充多边形
  174.   while (edgecount>0)
  175.   {
  176.     offset1=mempitch*ystart1+xstart1; //左边缘偏移量
  177.     offset2=mempitch*ystart2+xstart2; //右边缘偏移量
  178.     
  179.     //初始化误差额
  180.     errorterm1=0;
  181.     errorterm2=0;
  182.     
  183.     //初始化左边与右边x&y方向的偏移差
  184.     if ((ydiff1=yend1-ystart1)<0)
  185.       ydiff1=-ydiff1;
  186.     if ((ydiff2=yend2-ystart2)<0)
  187.       ydiff2=-ydiff2;
  188.     if ((xdiff1=xend1-xstart1)<0)
  189.     {
  190.       xunit1=-1;
  191.       xdiff1=-xdiff1;
  192.     }
  193.     else
  194.     {
  195.       xunit1=1;
  196.     }
  197.     if ((xdiff2=xend2-xstart2)<0)
  198.     {
  199.       xunit2=-1;
  200.       xdiff2=-xdiff2;
  201.     }
  202.     else
  203.     {
  204.       xunit2=1;
  205.     }
  206.     
  207.     //选择使用哪种情况
  208.     if (xdiff1>ydiff1)
  209.     {/*|k1|<1*/
  210.       if (xdiff2>ydiff2)
  211.       {/*|k2|<1*/
  212.         count1=xdiff1;    //左边X的增量
  213.         count2=xdiff2;    //右边X的增量
  214.         while (count1&&count2)
  215.         {
  216.           while ((errorterm1<xdiff1)&&(count1>0))
  217.           {
  218.             if(count1--)
  219.             {
  220.               offset1+=xunit1;
  221.               xstart1+=xunit1;
  222.             }
  223.             errorterm1+=ydiff1;
  224.             if (errorterm1<xdiff1)
  225.             {
  226.               vbuffer[offset1]=(UCHAR)poly->color;
  227.             }
  228.           }
  229.           errorterm1-=xdiff1;
  230.           while ((errorterm2<xdiff2)&&(count2>0))
  231.           {
  232.             if (count2--)
  233.             {
  234.               offset2+=xunit2;
  235.               xstart2+=xunit2;
  236.             }
  237.             errorterm2+=ydiff2;
  238.             if (errorterm2<xdiff2)
  239.             {
  240.               vbuffer[offset2]=(UCHAR)poly->color;
  241.             }
  242.           }
  243.           errorterm2-=xdiff2;
  244.           length=offset2-offset1;
  245.           if (length<0)
  246.           {
  247.             length=-length;
  248.             start=offset2;
  249.           }
  250.           else
  251.             start=offset1;
  252.           for (int index=start;index<start+length+1;index++)
  253.           {
  254.             vbuffer[index]=(UCHAR)poly->color;
  255.           }
  256.           offset1+=mempitch;
  257.           ystart1++;
  258.           offset2+=mempitch;
  259.           ystart2++;
  260.         }
  261.       }
  262.       else
  263.       {/*|k2|>1*/
  264.         count1=xdiff1;
  265.         count2=ydiff2;
  266.         while (count1&&count2)
  267.         {
  268.           while ((errorterm1<xdiff1)&&(count1>0))
  269.           {
  270.             if(count1--)
  271.             {
  272.               offset1+=xunit1;
  273.               xstart1+=xunit1;
  274.             }
  275.             errorterm1+=ydiff1;
  276.             if (errorterm1<xdiff1)
  277.             {
  278.               vbuffer[offset1]=(UCHAR)poly->color;
  279.             }
  280.           }
  281.           errorterm1-=xdiff1;
  282.           
  283.           errorterm2+=xdiff2;
  284.           if (errorterm2>=ydiff2)
  285.           {
  286.             errorterm2-=ydiff2;
  287.             offset2+=xunit2;
  288.             xstart2+=xunit2;
  289.           }
  290.           count2--;
  291.           length=offset2-offset1;
  292.           if (length<0)
  293.           {
  294.             length=-length;
  295.             start=offset2;
  296.           }
  297.           else
  298.             start=offset1;
  299.           
  300.           for (int index=start;index<start+length+1;index++)
  301.           {
  302.             vbuffer[index]=(UCHAR)poly->color;
  303.           }
  304.           offset1+=mempitch;
  305.           ystart1++;
  306.           offset2+=mempitch;
  307.           ystart2++;
  308.         }
  309.       }
  310.     }
  311.     else
  312.     {/*|k1|>1*/
  313.       if (xdiff2>ydiff2)
  314.       {/*|k2|<1*/
  315.         count1=ydiff1;
  316.         count2=xdiff2;
  317.         while (count1&&count2)
  318.         {
  319.           errorterm1+=xdiff1;
  320.           if (errorterm1>=ydiff1)
  321.           {
  322.             errorterm1-=ydiff1;
  323.             offset1+=xunit1;
  324.             xstart1+=xunit1;
  325.           }
  326.           count1--;
  327.           
  328.           while ((errorterm2<xdiff2)&&(count2>0))
  329.           {
  330.             if (count2--)
  331.             {
  332.               offset2+=xunit2;
  333.               xstart2+=xunit2;
  334.             }
  335.             errorterm2+=ydiff2;
  336.             if (errorterm2<xdiff2)
  337.             {
  338.               vbuffer[offset2]=(UCHAR)poly->color;
  339.             }
  340.         
  341.           }
  342.           errorterm2-=xdiff2;
  343.           length=offset2-offset1;
  344.           if (length<0)
  345.           {
  346.             length=-length;
  347.             start=offset2;
  348.           }
  349.           else
  350.             start=offset1;
  351.           for (int index=start;index<start+length+1;index++)
  352.           {
  353.             vbuffer[index]=(UCHAR)poly->color;
  354.           }
  355.           offset1+=mempitch;
  356.           ystart1++;
  357.           offset2+=mempitch;
  358.           ystart2++;
  359.         }
  360.       }
  361.       else
  362.       {/*|k2|>1*/
  363.         
  364.         count1=ydiff1;
  365.         count2=ydiff2;
  366.         while (count1&&count2)
  367.         {
  368.           errorterm1+=xdiff1;
  369.           if (errorterm1>=ydiff1)
  370.           {
  371.             errorterm1-=ydiff1;
  372.             offset1+=xunit1;
  373.             xstart1+=xunit1;
  374.           }
  375.           count1--;
  376.           errorterm2+=xdiff2;
  377.           if (errorterm2>=ydiff2)
  378.           {
  379.             errorterm2-=ydiff2;
  380.             offset2+=xunit2;
  381.             xstart2+=xunit2;
  382.           }
  383.           count2--;
  384.           length=offset2-offset1;
  385.           if (length<0)
  386.           {
  387.             length=-length;
  388.             start=offset2;
  389.           }
  390.           else
  391.             start=offset1;
  392.           for (int index=start;index<start+length+1;index++)
  393.           {
  394.             vbuffer[index]=(UCHAR)poly->color;
  395.           }
  396.           offset1+=mempitch;
  397.           ystart1++;
  398.           offset2+=mempitch;
  399.           ystart2++;
  400.         }
  401.       }
  402.     }
  403.     if (!count1)
  404.     {/*首先到达逆时针顶点*/
  405.       --edgecount;
  406.       startvert1=endvert1;
  407.       --endvert1;
  408.       if (endvert1<0)
  409.         endvert1=poly->num_vert-1;
  410.       xend1=poly->vlist[endvert1].x+poly->x0;
  411.       yend1=poly->vlist[endvert1].y+poly->y0;
  412.     }
  413.     if (!count2)
  414.     {/*首先到达顺时针顶点*/
  415.       --edgecount;
  416.       startvert2=endvert2;
  417.       ++endvert2;
  418.       if(endvert2==(poly->num_vert))
  419.         endvert2=0;
  420.       xend2=poly->vlist[endvert2].x+poly->x0;
  421.       yend2=poly->vlist[endvert2].y+poly->y0;
  422.     }
  423.     
  424.   }
  425.   
  426.   return(1);
  427. }
  428. LRESULT CALLBACK WindowProc(HWND hwnd,
  429.                             UINT msg,
  430.                             WPARAM wparam,
  431.                             LPARAM lparam)
  432. {
  433. PAINTSTRUCT     ps;     
  434. HDC             hdc;    
  435.        
  436. switch(msg)
  437.     {   
  438.     case WM_CREATE: 
  439.         {
  440.         return(0);
  441.         } break;
  442.    
  443.     case WM_PAINT: 
  444.         {
  445.         hdc = BeginPaint(hwnd,&ps);  
  446.         
  447.         EndPaint(hwnd,&ps);
  448.         return(0);
  449.         } break;
  450.     case WM_DESTROY: 
  451.         {
  452.         PostQuitMessage(0);
  453.         return(0);
  454.         } break;
  455.     default:break;
  456.     }
  457. return (DefWindowProc(hwnd, msg, wparam, lparam));
  458. }
  459. int Game_Init(void *parms=NULL,int num_parms=0)
  460. {
  461.   if(FAILED(DirectDrawCreateEx(NULL,(void **)&lpdd,IID_IDirectDraw7,NULL)))
  462.     return(0);
  463.   if(FAILED(lpdd->SetCooperativeLevel(main_window_handle,
  464.                                       DDSCL_FULLSCREEN|DDSCL_ALLOWMODEX|
  465.                                       DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT)))
  466.     return(0);
  467.   if(FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,0,0)))
  468.     return(0);
  469.   DDRAW_INIT_STRUCT(ddsd);
  470.   ddsd.dwFlags=DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  471.   ddsd.dwBackBufferCount=1;
  472.   ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_COMPLEX|
  473.                         DDSCAPS_FLIP;
  474.   
  475.   if(FAILED(lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL)))
  476.     return(0);
  477.   ddsd.ddsCaps.dwCaps=DDSCAPS_BACKBUFFER;
  478.   if(FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps,&lpddsback)))
  479.     return(0);
  480.   for (int color=1; color < 255; color++)
  481.     {
  482.     palette[color].peRed   = rand()%256;
  483.     palette[color].peGreen = rand()%256;
  484.     palette[color].peBlue  = rand()%256;
  485.     palette[color].peFlags = PC_NOCOLLAPSE;
  486.     } 
  487. palette[0].peRed     = 0;
  488. palette[0].peGreen   = 0;
  489. palette[0].peBlue    = 0;
  490. palette[0].peFlags   = PC_NOCOLLAPSE;
  491. palette[255].peRed   = 255;
  492. palette[255].peGreen = 255;
  493. palette[255].peBlue  = 255;
  494. palette[255].peFlags = PC_NOCOLLAPSE;
  495. palette[1].peRed     = 0;
  496. palette[1].peGreen   = 16;
  497. palette[1].peBlue    = 0;
  498. palette[1].peFlags   = PC_NOCOLLAPSE;
  499. if(FAILED(lpdd->CreatePalette(DDPCAPS_8BIT|DDPCAPS_ALLOW256|
  500.                               DDPCAPS_INITIALIZE,palette,&lpddpal,NULL)))
  501.     return(0);
  502. if(FAILED(lpddsprimary->SetPalette(lpddpal)))
  503.     return(0);
  504. DDraw_Fill_Surface(lpddsprimary,0);
  505. DDraw_Fill_Surface(lpddsback,0);
  506. //顺时针画出各点!!!
  507. VERTEX2DF object_vertices[4]={-100,-100,100,-100,100,100,-100,100};
  508. object.state=1;
  509. object.num_vert=4;
  510. object.color=1;
  511. object.xv=0;
  512. object.yv=0;
  513. object.x0=SCREEN_WIDTH/2;
  514. object.y0=SCREEN_HEIGHT/2;
  515. object.vlist=new VERTEX2DF[object.num_vert];
  516. for (int index=0;index<object.num_vert;index++)
  517.   object.vlist[index]=object_vertices[index];
  518. for (int ang=0;ang<360;ang++)
  519. {
  520.   float theta=(float)ang*PI/(float)180;
  521.   cos_look[ang]=cos(theta);
  522.   sin_look[ang]=sin(theta);
  523. }
  524. return(1);  
  525. }
  526. int Game_Main(void *parms = NULL, int num_parms = 0)
  527. {
  528.   static int green_inc=4;
  529.   if(window_closed)
  530.     return(0);
  531.   if(KEYDOWN(VK_ESCAPE))
  532.   {
  533.     PostMessage(main_window_handle,WM_CLOSE,0,0);
  534.     window_closed=1;
  535.   }
  536.   DDraw_Fill_Surface(lpddsback,0);
  537.   DDRAW_INIT_STRUCT(ddsd);
  538.   if(FAILED(lpddsback->Lock(NULL,&ddsd,DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR,NULL)))
  539.     return(0);
  540.   Draw_Filled_Polygon2D(object, (UCHAR *)ddsd.lpSurface, ddsd.lPitch);
  541.   Rotate_Polygon2D(object,5);
  542.   if (FAILED(lpddsback->Unlock(NULL)))
  543.    return(0);
  544.   Set_Palette_Entry(1, &palette[1]);
  545.   palette[1].peGreen+=green_inc;
  546.   if (palette[1].peGreen > 255 || palette[1].peGreen < 16)
  547.    {
  548.     green_inc=-green_inc;
  549.     palette[1].peGreen+=green_inc;    
  550.    } 
  551. while(FAILED(lpddsprimary->Flip(NULL,DDFLIP_WAIT)));
  552.   
  553. Sleep(33);
  554. return(1);
  555. }
  556. int Game_Shutdown(void *parms = NULL, int num_parms = 0)
  557. {/*清除资源*/
  558. if (lpddpal)
  559.    {
  560.    lpddpal->Release();
  561.    lpddpal = NULL;
  562.    }
  563. if(lpddsback)
  564.   {
  565.   lpddsback->Release();
  566.   lpddsback=NULL;
  567.   }
  568. if (lpddsprimary)
  569.    {
  570.    lpddsprimary->Release();
  571.    lpddsprimary = NULL;
  572.    } 
  573. if (lpdd)
  574.    {
  575.    lpdd->Release();
  576.    lpdd = NULL;
  577.    } 
  578. return(1);
  579. }
  580. int WINAPI WinMain( HINSTANCE hinstance,
  581.                     HINSTANCE hprevinstance,
  582.                     LPSTR lpcmdline,
  583.                     int ncmdshow)
  584. {
  585. WNDCLASSEX winclass; 
  586. HWND       hwnd;    
  587. MSG        msg;      
  588. //HDC        hdc;    
  589. winclass.cbSize         = sizeof(WNDCLASSEX);
  590. winclass.style          = CS_DBLCLKS | CS_OWNDC | 
  591.                           CS_HREDRAW | CS_VREDRAW;
  592. winclass.lpfnWndProc    = WindowProc;
  593. winclass.cbClsExtra     = 0;
  594. winclass.cbWndExtra     = 0;
  595. winclass.hInstance      = hinstance;
  596. winclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
  597. winclass.hCursor        = LoadCursor(NULL, IDC_ARROW); 
  598. winclass.hbrBackground  = (HBRUSH)GetStockObject(BLACK_BRUSH);
  599. winclass.lpszMenuName   = NULL;
  600. winclass.lpszClassName  = WINDOW_CLASS_NAME;
  601. winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);
  602. hinstance_app = hinstance;
  603. if (!RegisterClassEx(&winclass))
  604.     return(0);
  605. if (!(hwnd = CreateWindowEx(NULL,                  
  606.                             WINDOW_CLASS_NAME,    
  607.                             "DirectDraw 8-Bit Line Drawing Demo", 
  608.                             WS_POPUP | WS_VISIBLE,
  609.                             0,0,    
  610.                             SCREEN_WIDTH,SCREEN_HEIGHT,  
  611.                             NULL,     
  612.                             NULL,  
  613.                             hinstance,
  614.                             NULL))) 
  615. return(0);
  616. main_window_handle = hwnd;
  617. Game_Init();
  618. while(TRUE)
  619.     {
  620.   
  621.     if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  622.        { 
  623.        if (msg.message == WM_QUIT)
  624.            break;
  625.     
  626.        TranslateMessage(&msg);
  627.        DispatchMessage(&msg);
  628.        }
  629.      Game_Main();
  630.        
  631.     } 
  632. Game_Shutdown();
  633. return(msg.wParam);
  634. }

一定要注意调用光栅化函数时传入的参数为顺时针在笛卡尔坐标系中设置的各多边形坐标!!!

Cadence 17.4 手把手教你画一个实心二极管Part库(附不规则形状绘制技巧) 本文详细介绍了在Cadence 17.4中使用OrCAD Capture CIS创建实心二极管Part库的全流程,包括环境准备、基本轮廓绘制、实心填充技巧以及元器件属性优化。特别分享了不规则形状绘制和填充的高级技巧,帮助工程师高效完成自定义元器件库的设计与管理。 阅读详情

相关推荐

多边形区域填充算法--扫描线种子填充算法

多边形区域填充算法--扫描线种子填充算法

ffghggf的博客 1946

图形学基础笔记II:多边形光栅化算法和显卡三角形光栅算法

为什么三角形就够了 实际对于 3D 来说肯定全是基于三角形的 geometry - OpenGL: Is it more efficient to use GL_QUADS or GL_TRIANGLES? - Stack Overflow,显卡也全部用重心坐标和 AABB 来填充三角形的。 三角形线框模式和非三角形线框模式(GUI、CAD),也很容易实现,使用 bresenham 中点算法就行了。 点就更简单了,如果没有涉及 Anti A 直接取整写显存就行了。 整理一下就是说: 线框模...

锐龙处理器 2407

多边形填充算法的QT实现

如果p1的y值小于p2的y值,我们将p2的y值作为边的yMax,p1的x值作为边的x,而斜率则根据(p2.x() - p1.x()) / (p2.y() - p1.y())计算得出。如果p1的y值大于p2的y值,我们交换p1和p2的角色,并使用相同的方式计算边的属性。在计算机图形学中,多边形填充算法是一种常用的技术,用于将多边形的内部区域进行填充,使其呈现出实心的效果。现在,我们可以在DrawingWidget的paintEvent函数中调用fillPolygon函数,以实现多边形的填充效果。

DevPulse的博客 410

计算机图形学 第4章 多边形填充

边缘填充算法是先求出多边形的每条边与扫描线的交点,然后将交点。

优快云_YJX的博客 1万+

Halcon实战:5分钟搞定自定义直线卡尺工具(附完整代码下载)

本文详细介绍了如何使用Halcon快速开发自定义直线卡尺工具,通过交互式ROI绘制、边缘检测和直线拟合三个核心函数,实现高效工业视觉检测。文章包含完整代码下载,帮助开发者在5分钟内掌握这一实用工具的开发技巧,提升直线检测的精度和效率。

perl8的博客 249

从问卷到结论:手把手教你用SPSS 28完成一份完整的社科数据分析报告

本文详细介绍了如何使用SPSS 28完成社会科学研究中的数据分析报告,从问卷数据导入、清洗到描述性和推断性统计分析,再到结果呈现与报告撰写。通过实际案例演示,帮助研究者掌握SPSS 28的核心功能,提升数据分析效率与报告质量。

weixin_28717431的博客 249

【Altium Designer21】AD里面填充fill、灌铜Polygon Pour、实心区域覆铜solid region的区别

如上图,调出管理器可以看到PCB里面有这么几项,Polygons、Regions、Fils。那么这么几项有什么区别呢。 灌铜polygon是在布线完成后进行,如下图有三种灌铜方式(Solid、Hatched、None),有智能功能,会自动避让不是同一网络、属于其它网络的焊盘、过孔、铜膜走线。可以得到任意形状的灌铜。目的是提高电路的抗干扰能力、减小辐射干扰、高频PCB电路板常常选用。 实心覆铜solid region,在覆铜区域内整片覆盖成一个整体铜膜,覆铜区域内不允许存在其它网络的焊盘、过孔、铜膜走线,.

wsq_666的博客 2万+

通俗傻瓜式理清光栅化渲染和光线追踪渲染的原理

用通俗语言傻瓜式的讲清楚光栅渲染和光线追踪渲染的原理,方便没有相关理论基础的朋友理解入门。

qq_37366618的博客 2万+

计算机图形学——多边形区域填充算法

计算机图形学——区域填充算法 橡皮筋效果 本次实验的环境是使用vs提供的MFC框架,在鼠标交互输入中使用橡皮筋算法来实现多边形的输入。首先定义相应变量来保存输入的数据。 int m_pNumbers; //输入点的个数 CPoint m_pAccord[N], m_mousePoint; //保存输入的顶点信息和当前的鼠标所处位置 ......

阿蓬的个人博客 9086

从晶体管到触发器:为什么芯片设计必须区分同步/异步复位?

本文深入探讨了芯片设计中同步复位与异步复位的物理本质与工程权衡。从晶体管级的CMOS结构出发,剖析了两种复位方式在物理实现、时序可靠性(如建立/保持时间、恢复/移除时间)上的根本差异,并分析了在不同应用场景下的选择策略。文章强调,理解复位信号的底层机制对于确保芯片时序收敛、系统上电确定性及整体鲁棒性至关重要。

time3的博客 221

SRC漏洞挖掘实战指南:从零入门到月入过万的网络安全副业

网络安全的核心在于识别和修复系统缺陷,其中逻辑漏洞与信息泄露是常见的安全风险。其原理在于应用程序在业务逻辑设计或数据处理过程中存在缺陷,导致未授权访问或敏感数据暴露。掌握这些技术对于构建安全的应用体系至关重要,不仅能有效防范攻击,也为安全研究人员提供了将技术能力变现的合法途径。在漏洞赏金(Bug Bounty)和SRC(安全应急响应中心)等应用场景中,白帽子通过系统化的测试方法,挖掘此类漏洞,既能获得经济回报,又能积累宝贵的实战经验。本文聚焦于逻辑漏洞与信息泄露的实战挖掘技巧,为初学者提供清晰的入门路径和效

weixin_28568819的博客 349

算法系列之十二:多边形区域填充算法--扫描线填充算法(有序边表法)

二、扫描线算法(Scan-Line Filling) 扫描线算法适合对矢量图形进行区域填充,只需要直到多边形区域的几何位置,不需要指定种子点,适合计算机自动进行图形处理的场合使用,比如电脑游戏和三维CAD软件的渲染等等。 对矢量多边形区域填充,算法核心还是求交。《计算几何与图形学有关的几种常用算法》一文给出了判断点与多边形关系的算法――扫描交点的奇偶数判断算法,利用此算法可以判断一个点是否在多...

java开发指南博客 【转载】 7033

应用商店评论分析实战:Python逆向工程破解Google Play加密接口与NLP建模

在移动互联网时代,应用商店中的用户评论成为了开发者优化应用、提升用户体验的重要依据。然而,Google Play等应用商店对评论数据进行了加密处理,直接爬取难度较大。本文将介绍如何使用Python逆向工程破解Google Play的加密接口,实现对应用商店评论的实时采集,并结合NLP(自然语言处理)技术进行情感分析和主题建模,为开发者提供有价值的数据支持。

u014481728的博客 1348

MFC之学习多边形绘制、阴影模式、多边形填充模式与绘制实心五角星

1.笔记 1.1绘制多边形函数 BOOL CDC::Polygon(LPPOINT lpPoints,int nCount); lpPoints是多边形顶点数组名,数组中每个点是CPoint对象(或称POINT结构体),nCount是数组中顶点个数。调用成功返回非零,否则返回零。 1.2阴影画刷 1.2.1创建阴影画刷函数 BOOL CreateHatchBrush(int nIndex,COLORREF crColor); 参数为阴影模式、阴影颜色。调用成功返回非零,否则返回零。 1.

星辰大海的博客 4684

用C#+Avalonia写跨平台串口工具:Windows/macOS/Linux通吃,还能解析Modbus+画实时曲线

不管是串口还是蓝牙,核心操作都是“打开连接、发数据、收数据、关连接”,先定义一个// 通信设备接口:统一串口/蓝牙的操作// 连接状态变化事件(UI层订阅)// 接收数据事件(收到数据后触发)// 通信配置(不同设备配置不同,用泛型)// 通信设备接口:统一串口/蓝牙的操作 public interface ICommDevice : IDisposable {// 连接状态变化事件(UI层订阅) event Action < bool > OnConnectionChanged;

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 997

【STK】手把手教你利用STK进行关联分析仿真01-STK/CAT模块介绍

今天主要介绍接近分析工具CAT。

weixin_44184852的博客 1106

使用openGL,利用多边形填充的扫描线算法画出实心五边形

具体内容参考博客:https://blog.youkuaiyun.com/qq_38345598/article/details/84553043 实心五边形 任意给定5个顶点坐标,利用多边形填充的扫描线算法编写程序,生成一个实心五边形。 运行截图 代码(转载) #include <GL/glut.h> #include <windows.h> const int POINTNUM = 5; typedef struct XET{ float x; float dx, ymax; XET

小` pi孩 1881

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

五边形顶点坐标_任意给定五边形的5个顶点坐标,利用多边形填充的扫描算法,编写程序生成一个实心五边形...

//////////////////////////////////////////////////////////////////////////////////////////////////// 功能: 填充多边形//// 参数: lpPoints: 指向顶点坐标数组的指针,数组类型为POINT,多边形由它们顺次封闭连接得到// nCount: 顶点的个数// nColor: 填充的颜色 默...

weixin_39861823的博客 1416

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

OpenCV画椭圆、实心圆、凹多边形、线段、矩形

OpenCV画椭圆、实心圆、凹多边形、线段、矩形author@jason_ql http://blog.youkuaiyun.com/lql07161、 实例代码#include <QCoreApplication> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc

aibotlab的博客 2万+

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

OpenCV学习笔记4-绘制图形和填充多边形(附代码实现)

通过OpenCV绘制图形和填充多边形

Aaron的博客 3380

填充实心多边形(一)

可以利用前一篇文章中的Cohen-Sutherland裁剪算法对缓冲区的任意图形画出经裁剪的该图形,那么接下来该如何填充这些图形(一般是多边形)。若是四边形,我们可以把它分解成2个三角形。而对于任意三角形,又可以分解成一个平底三角形和一个平顶三角形。接下来给出填充任意三角形的代码,摘自《windows游戏编程大师技巧》。/* 2008/9/4代码功能:填充任意三角形并经过矩形裁

天之痕 1473

matlab 画实心矩形,graphics画实心矩形

C程序设计(根据用户的输入画矩形) 指导老师:赵亚娟 学生:陈文川 学号:06 ? ...? ? #include "graphics.h" #include "conio.h" #include"stdio.h" int ......ATmega128的_LCD12864_绘图(画点_画线_画矩形等)_物理_自然科学_专业资料。w .. . .. 基于 ATmega128 的 LCD12864 ...

weixin_39538962的博客 1802

直线,贝塞尔,椭圆,多边形,圆(空心的与实心的)

 Dim g As Graphics = Me.CreateGraphics        Dim mypen As New Pen(Color.Red)        mypen.Width = 5         g.DrawLine(mypen, 1, 1, 45, 45)         g.DrawBezier(mypen, 15, 15, 30, 30,

keenweiwei的专栏 2156

OpenGL学习05-绘制实心物体

使用三角形或者多边形结合在一起,我们可以绘制实心物体(3D物体)。本篇中使用三角形绘制圆锥形。 下面测试第一个OpenGL程序: void renderScene(void) { float angle; float x, y; static int triangleNum = 1; //清除颜色缓冲区和深度缓冲区 glClear(GL_COLOR_BUFFER_BIT | GL_D

997

OpenCV-Python官方教程-02-绘图工具(线、矩阵、圆、椭圆、多边形,添加文字,填充多边形)

Opencv中绘图工具(线、矩形、圆、椭圆、多边形、添加文字、填充多边形): 这里用到了三个函数:cv2.line();cv2.rectangle();cv2.circle();cv2.ellipse();cv2.putText(); cv2.polylines(); cv2.fillConvexPoly();cv2.fillPoly() cv2.line(img,dot1,dot2,color,thickness) cv2.rectangle(img,dot1,dot2,color,thickness

Galen_xia的博客 949
上一篇: 填充实心多边形(一)
下一篇: 迷途指针
lingang_
博客等级 码龄19年 76粉丝 123原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值