多边形填充 | 计算机图形学(c++版MFC)

声明:凡代码问题,欢迎私信或在评论区沟通。承蒙指正,一起成长! 

目录

实验1:绘制如下图所示扇形,并进行填充。

实验2:按下鼠标拖动绘制椭圆,然后在区域内双击鼠标,填充该椭圆区域。

实验3:绘制正六边形,并使用扫描线方式进行填充。


1. 了解并掌握圆形绘制算法;

2.掌握多边形的填充算法,已知多边形的顶点,通过绘制直线的函数或种子填充算法填充该多边形。

一、实验1:绘制如下图所示扇形,并进行填充。

(1)程序源代码

// shiyan2View.cpp : implementation of the CShiyan2View class
//

#include "stdafx.h"
#include "shiyan2.h"
#include <math.h>
#include "shiyan2Doc.h"
#include "shiyan2View.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//int x1,y1,x2,y2; //全局变量圆弧首尾两点坐标

/
// CShiyan2View

IMPLEMENT_DYNCREATE(CShiyan2View, CView)

BEGIN_MESSAGE_MAP(CShiyan2View, CView)
	//{{AFX_MSG_MAP(CShiyan2View)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDBLCLK()
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/
// CShiyan2View construction/destruction

CShiyan2View::CShiyan2View()
{
	// TODO: add construction code here

}

CShiyan2View::~CShiyan2View()
{
}

BOOL CShiyan2View::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/
// CShiyan2View drawing

void Midpointcircle_2(int radius,int color,CDC *p)
{
	int x,y,d,E=12,SE=20-8*radius;
	x=0;y=radius;
	d=3-4*radius;
	p->SetPixel(x+200,y+150,color);
	while(y>x)
	{
		if(d<=0)
		{
			d+=E;
			SE+=8;
		}
		else
		{
			d+=SE;
			SE+=16;
			y--;
		}
		E+=8;
		x++;
		p->SetPixel(x+200,y+150,color);
	}
}


/*
void Midpointcircle_1(int radius,int color,CDC *p)
{
	int x,y; float d;x=0;y=radius;
	d=3.0/4-radius;
	p->SetPixel(x+500,y+150,color);
	while(y>x)
	{
		if(d<=0)
			d+=2.0*x+3;
		else
		{
			d+=2.0*(x-y)+5;
			y--;
		}
		x++;
		p->SetPixel(-x+500,-y+150,color);
		p->SetPixel(x+500,-y+150,color);
	}
	x1=-x+500;y1=-y+150;
	x2=x+500;y2=-y+150;
}
*/


void B(int x,int y,int c1,int c2,CDC *p)
{
	long c;
	c=p->GetPixel(x,y);
	if(c!=c1 && c!=c2)
	{
		p->SetPixel(x,y,c1);
		B(x+1,y,c1,c2,p); B(x-1,y,c1,c2,p);
		B(x,y+1,c1,c2,p);  B(x,y-1,c1,c2,p);
	}
}
///
///
///

struct Edge
{
    //用来存储边的
    int yUpper;
    float xIntersect, dxPerScan;
    struct Edge * next;  //指向下一条边
} tEdge; //结构体变
///
void insertEdge(Edge *list,Edge *edge)
{
    Edge*p,*q=list;
    p=q->next;
    while(p!=NULL)
    {
        if(edge->xIntersect<p->xIntersect)
            p=NULL;
        else
        {
            q=p;
            p=p->next;
        }
    }
    edge->next=q->next;
    q->next=edge;
}
///
int yNext(int k,int cnt, CPoint * pts)
{
    int j;
    if((k+1)>(cnt-1))
        j=0;
    else
        j=k+1;
    while(pts[k].y==pts[j].y)
    {
        if((k+1)>(cnt-1))
            j=0;
        else
            j++;
    }
    return pts[j].y;
}

void makeEdgeRec (CPoint lower, CPoint upper, int yComp, Edge * edge, Edge *edges[])
{
    edge->dxPerScan=(float)(upper.x-lower.x)/(upper.y-lower.y);
    edge->xIntersect=lower.x;
    if(upper.y<yComp)
        edge->yUpper=upper.y-1;
    else
        edge->yUpper=upper.y;
    insertEdge(edges[lower.y],edge);
}
///
void buildEdgeList (int cnt, CPoint *pts, Edge *edges[])
{
    Edge * edge;
    CPoint v1,v2;
    int i,yPrev=pts[cnt-2].y;
    v1.x=pts[cnt-1].x;
    v1.y=pts[cnt-1].y;
    for(i=0; i<cnt; i++)
    {
        v2=pts[i];
        if(v1.y!=v2.y)
        {
            edge=(Edge*)malloc(sizeof(Edge));
            if(v1.y<v2.y)
                makeEdgeRec(v1,v2,yNext(i,cnt,pts),edge,edges);
            else
                makeEdgeRec(v2,v1,yPrev,edge,edges);
        }
        yPrev=v1.y;
        v1=v2;
    }
}
///
void buildActiveList (int scan, Edge * active, Edge * edges[])
{
    Edge*p,*q;
    p=edges[scan]->next;
    while(p)
    {
        q=p->next;
        insertEdge(active,p);
        p=q;
    }
}

void fillScan (int scan, Edge * active, CDC * pDC)
{
    Edge*p1,*p2;
    int i;
    p1=active->next;
    while(p1)
    {
        p2=p1->next;
        for(i=p1->xIntersect; i<p2->xIntersect; i++)
            pDC->SetPixel(i,scan,0);
        p1=p2->next;
    }
}

void deleteAfter(Edge *q)
{
    Edge * p=q-> next;
    q->next=p->next;
    free(p);
}
//
void updateActiveList (int scan, Edge * active)
{
    Edge *q=active,*p=active->next;
    while(p)
        if(scan>=p->yUpper)
        {
            p=p->next;
            deleteAfter(q);
        }
        else
        {
            p->xIntersect=p->xIntersect+p->dxPerScan;
            q=p;
            p=p->next;
        }
}
//
void resortActiveList(Edge *active)
{
    Edge*q,*p=active->next;
    active->next=NULL;
    while(p)
    {
        q=p->next;
        insertEdge(active,p);
        p=q;
    }
}
///
void scanFill(int cnt,CPoint *pts,CDC *pDC)
{
    Edge *edges[300],*active;       //edges是指针数组
    int i,scan;
    for(i=0; i<300; i++)
    {
        edges[i]=(Edge*)malloc(sizeof(Edge));//开辟内存区
        edges[i]->next=NULL;
    }
    buildEdgeList(cnt,pts,edges);
    active=(Edge*)malloc(sizeof(Edge));
    active->next=NULL;
    for(scan=0; scan<300; scan++)
    {
        buildActiveList(scan,active,edges);
        if(active->next)
        {
            fillScan(scan,active,pDC);
            updateActiveList(scan,active);
            resortActiveList(active);
        }
    }
}


///
///
///

CPoint vx[6];

//画六边形  104.7 *6
void Hexagan(CDC *p)
{
	int r=50;
	int j=0;
	p->MoveTo((int)(200+r*cos(52/100)),(int)(200+r*sin(52/100)));
	for(float i=0;i<=628;i=i+104.7)
	{
		int a=(int)(200+r*cos(i/100));
		int b=(int)(200+r*sin(i/100));
		p->LineTo(a,b);
		vx[j].x=a, vx[j].y=b;
		Sleep(500);
	}
	p->LineTo((int)(200+r*cos(52/100)),(int)(200+r*sin(52/100)));
	vx[j].x=(int)(200+r*cos(52/100));
	vx[j].y=(int)(200+r*sin(52/100));
}

void CShiyan2View::OnDraw(CDC* pDC)
{
	CShiyan2Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
/*
	Midpointcircle_1(145,0,pDC);
	pDC->MoveTo(x1,y1);
	pDC->LineTo(500,150);
	pDC->LineTo(x2,y2);
	B(500,1,255,0,pDC);

*/
//	Hexagan(pDC);

	int cnt=6;
	CPoint he[6];
	he[0].x=200,he[0].y=100;
	he[1].x=300,he[1].y=100;
	he[2].x=350,he[2].y=187;
	he[3].x=300,he[3].y=274;
	he[4].x=200,he[4].y=274;
	he[5].x=150,he[5].y=187;
	pDC->MoveTo(he[0].x,he[0].y);
	pDC->LineTo(he[1].x,he[1].y);
	pDC->LineTo(he[2].x,he[2].y);
	pDC->LineTo(he[3].x,he[3].y);
	pDC->LineTo(he[4].x,he[4].y);
	pDC->LineTo(he[5].x,he[5].y);
	pDC->LineTo(he[0].x,he[0].y);
	scanFill(cnt,he,pDC);

	// TODO: add draw code for native data here
}

/
// CShiyan2View printing

BOOL CShiyan2View::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CShiyan2View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CShiyan2View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/
// CShiyan2View diagnostics

#ifdef _DEBUG
void CShiyan2View::AssertValid() const
{
	CView::AssertValid();
}

void CShiyan2View::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CShiyan2Doc* CShiyan2View::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CShiyan2Doc)));
	return (CShiyan2Doc*)m_pDocument;
}
#endif //_DEBUG

/
// CShiyan2View message handlers

CPoint DownPoint;
//全局变量

void CShiyan2View::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	DownPoint=point;
	CView::OnLButtonDown(nFlags, point);
}

void CShiyan2View::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	CDC *p=GetDC();
	p->Ellipse(DownPoint.x,DownPoint.y,point.x,point.y);
//	p->Rectangle(DownPoint.x,DownPoint.y,point.x,point.y);
	CView::OnLButtonUp(nFlags, point);
}

void CShiyan2View::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	CDC *pDC=GetDC();
	B(point.x,point.y,90000,0,pDC);
//	scanFill(4,&point,pDC);
	CView::OnLButtonDblClk(nFlags, point);
}

(2)运行结果

 

半径R=145;圆心坐标(500,150);

二、实验2:编写程序,运行后按下鼠标拖动绘制椭圆,然后在区域内双击鼠标,填充该椭圆区域。

(1)程序源代码

CPoint DownPoint;
//全局变量
void CShiyan2View::OnLButtonDown(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default
    DownPoint=point;
    CView::OnLButtonDown(nFlags, point);
}
void CShiyan2View::OnLButtonUp(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default
    CDC *p=GetDC();
    p->Ellipse(DownPoint.x,DownPoint.y,point.x,point.y);
    CView::OnLButtonUp(nFlags, point);
}
void CShiyan2View::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default
    CDC *pDC=GetDC();
    B(point.x,point.y,90000,0,pDC);
    CView::OnLButtonDblClk(nFlags, point);
}

(2)运行结果

       

 

 三、实验3:绘制正六边形,并使用扫描线方式进行填充。

(1)程序源代码


///    扫描线填充函数    /
struct Edge
{
    //用来存储边的
    int yUpper;
    float xIntersect, dxPerScan;
    struct Edge * next;  //指向下一条边
} tEdge; //结构体变
///
void insertEdge(Edge *list,Edge *edge)
{
    Edge*p,*q=list;
    p=q->next;
    while(p!=NULL)
    {
        if(edge->xIntersect<p->xIntersect)
            p=NULL;
        else
        {
            q=p;
            p=p->next;
        }
    }
    edge->next=q->next;
    q->next=edge;
}
///
int yNext(int k,int cnt, CPoint * pts)
{
    int j;
    if((k+1)>(cnt-1))
        j=0;
    else
        j=k+1;
    while(pts[k].y==pts[j].y)
    {
        if((k+1)>(cnt-1))
            j=0;
        else
            j++;
    }
    return pts[j].y;
}

void makeEdgeRec (CPoint lower, CPoint upper, int yComp, Edge * edge, Edge *edges[])
{
    edge->dxPerScan=(float)(upper.x-lower.x)/(upper.y-lower.y);
    edge->xIntersect=lower.x;
    if(upper.y<yComp)
        edge->yUpper=upper.y-1;
    else
        edge->yUpper=upper.y;
    insertEdge(edges[lower.y],edge);
}
///
void buildEdgeList (int cnt, CPoint *pts, Edge *edges[])
{
    Edge * edge;
    CPoint v1,v2;
    int i,yPrev=pts[cnt-2].y;
    v1.x=pts[cnt-1].x;
    v1.y=pts[cnt-1].y;
    for(i=0; i<cnt; i++)
    {
        v2=pts[i];
        if(v1.y!=v2.y)
        {
            edge=(Edge*)malloc(sizeof(Edge));
            if(v1.y<v2.y)
                makeEdgeRec(v1,v2,yNext(i,cnt,pts),edge,edges);
            else
                makeEdgeRec(v2,v1,yPrev,edge,edges);
        }
        yPrev=v1.y;
        v1=v2;
    }
}
///
void buildActiveList (int scan, Edge * active, Edge * edges[])
{
    Edge*p,*q;
    p=edges[scan]->next;
    while(p)
    {
        q=p->next;
        insertEdge(active,p);
        p=q;
    }
}

void fillScan (int scan, Edge * active, CDC * pDC)
{
    Edge*p1,*p2;
    int i;
    p1=active->next;
    while(p1)
    {
        p2=p1->next;
        for(i=p1->xIntersect; i<p2->xIntersect; i++)
            pDC->SetPixel(i,scan,0);
        p1=p2->next;
    }
}

void deleteAfter(Edge *q)
{
    Edge * p=q-> next;
    q->next=p->next;
    free(p);
}
//
void updateActiveList (int scan, Edge * active)
{
    Edge *q=active,*p=active->next;
    while(p)
        if(scan>=p->yUpper)
        {
            p=p->next;
            deleteAfter(q);
        }
        else
        {
            p->xIntersect=p->xIntersect+p->dxPerScan;
            q=p;
            p=p->next;
        }
}
//
void resortActiveList(Edge *active)
{
    Edge*q,*p=active->next;
    active->next=NULL;
    while(p)
    {
        q=p->next;
        insertEdge(active,p);
        p=q;
    }
}
///
void scanFill(int cnt,CPoint *pts,CDC *pDC)
{
    Edge *edges[300],*active;       //edges是指针数组
    int i,scan;
    for(i=0; i<300; i++)
    {
        edges[i]=(Edge*)malloc(sizeof(Edge));//开辟内存区
        edges[i]->next=NULL;
    }
    buildEdgeList(cnt,pts,edges);
    active=(Edge*)malloc(sizeof(Edge));
    active->next=NULL;
    for(scan=0; scan<300; scan++)
    {
        buildActiveList(scan,active,edges);
        if(active->next)
        {
            fillScan(scan,active,pDC);
            updateActiveList(scan,active);
            resortActiveList(active);
        }
    }
}
///    扫描线填充函数    /

void CShiyan2View::OnDraw(CDC* pDC)
{
    CShiyan2Doc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    int cnt=6;
    CPoint he[6];
    he[0].x=200,he[0].y=100;
    he[1].x=300,he[1].y=100;
    he[2].x=350,he[2].y=187;
    he[3].x=300,he[3].y=274;
    he[4].x=200,he[4].y=274;
    he[5].x=150,he[5].y=187;
    pDC->MoveTo(he[0].x,he[0].y);
    pDC->LineTo(he[1].x,he[1].y);
    pDC->LineTo(he[2].x,he[2].y);
    pDC->LineTo(he[3].x,he[3].y);
    pDC->LineTo(he[4].x,he[4].y);
    pDC->LineTo(he[5].x,he[5].y);
    pDC->LineTo(he[0].x,he[0].y);
    scanFill(cnt,he,pDC);

    // TODO: add draw code for native data here
}

(2)运行结果

 

  • 4
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尘封的CPU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值