【计算机图形学】实验一:二维图形绘制

简介: 【计算机图形学】实验一:二维图形绘制

1. 实验内容

1.绘制金刚石图案

金刚石图案的成图规则是:把一个圆周等分成n nn份,然后每两点之间连线。当n nn取奇数时,该图案可一笔连续绘成,即用MoveTo函数确定一个当前点,然后连续用LineTo函数连点成线。

请设计连线规则并编程实现。

2.绘制魔术三角形

绘制下图所示的魔术三角形图案 ,采用三种可明显区分的颜色填充。

3.绘制递归圆

应用递归的方法绘制如下所示的图案。

2. 实验环境

Visual Studio 2019

图形学实验程序框架

Windows11系统

3. 问题分析

3.1问题1


image.png

3.2问题2

对于问题2,可以预先处理出12个点位的坐标。点位标号如下:

初始时,设0点的坐标为( 400 , 800 ) (400,800)(400,800),长边长度500,短边长度100.则各个点坐标如下表所示:

点位编号 x xx坐标 y yy坐标 所属区域 点位编号 x xx坐标 y yy坐标 所属区域
0 400 800 红区 6 750 713 红区、紫区
1 900 800 红区、黄区 7 700 454 红区、黄区
2 950 713 黄区 8 500 627 紫区、黄区
3 700 281 黄区、紫区 9 700 627 紫区
4 600 281 紫区 10 650 541 红区
5 350 713 红区、紫区 11 600 627 黄区

创建三个多边形,每个多边形表示魔术三角形的一个同色区域。多边形1按顺序将点0、点1、点7、点10、点6、点5连接。多边形2按顺序将点1、点2、点3、点8、点7、点11连接。多边形3将点3、点4、点5、点6、点9、点8连接。

为了实现变色的效果,每次都需要将每一个多边形重新赋值颜色并重新上色。在选取颜色时,选择使用随机的颜色。

3.3问题3

image.png

4. 算法设计

4.1问题1


image.png

4.2问题2

正如章节3.2分析,算法的流程如下:

1.计算各个点位坐标,确定魔术三角形每个部分用到了哪些模块。

2.每隔一段时间给三个部分的颜色重新绘制上色,颜色为随机颜色。这一过程不断地循环进行。

4.3问题3

正如3.3所分析,算法的流程如下:

先创建pDC对象和画笔,然后递归地调用函数。在函数体内,先判断递归深度。若递归深度<=0,则退出,返回上一层。若递归深度>0,则找到递归圆圆心的坐标与半径,根据当前圆心与半径画出当前圆。再找到当前圆附属的8个小圆的坐标,递归地画小圆。小圆的半径为大圆的1/4,小圆的递归层数为大圆的递归层数-1。在画完所有圆后,算法结束。

5. 源代码

5.1金刚石

void CDiamondView::DrawDiamond(int nVertex, int radius,int millisecond){
  InvalidateRect(NULL);//强制清屏
  UpdateWindow();
  struct Point {
    double x, y;
  };
  Point* pnt = new Point[nVertex];
  const double PI = 3.14159265;
  CDC* pDC = GetDC();
  CRect rgn;
  GetClientRect(&rgn);
  CBrush newBrush;
  newBrush.CreateSolidBrush(RGB(255, 255, 255));
  pDC->FillRect(&rgn, &newBrush);
  CPen redPen(PS_SOLID, 1, RGB(0, 0, 255));
  CPen* OldPen = pDC->SelectObject(&redPen);
  double theta = 2 * PI / nVertex;
  for (int i = 0; i < nVertex; i++) {
    pnt[i].x = radius * cos(i * theta) + MaxX() / 2;
    pnt[i].y = radius * sin(i * theta) + MaxY() / 2;
  }
  int pos = 0;
  if (nVertex % 2 == 1) {
    for (int loop = 0; loop < nVertex; loop++) {
      for (int interv = 0; interv <= nVertex / 2 - 1; interv++) {//间隔的点的数量
        int nextpos = (pos + 1 + interv) % nVertex;
        pDC->MoveTo(round(pnt[pos].x), round(pnt[pos].y));
        pDC->LineTo(round(pnt[nextpos].x), round(pnt[nextpos].y));
        pos = nextpos;
        Sleep(millisecond);
      }
    }
  }
  else {
    for (int i = 0; i < nVertex-1; i++) {
      for (int j = i + 1; j < nVertex; j++) {
        pDC->MoveTo(round(pnt[i].x), round(pnt[i].y));
        pDC->LineTo(round(pnt[j].x), round(pnt[j].y));
        Sleep(millisecond);
      }
    }
  }
  pDC->SelectObject(OldPen);
}

5.2魔术三角形

//绘制魔术三角
void CDiamondView::DrawTriangle(){
  InvalidateRect(NULL);//强制清屏
  UpdateWindow();
  CDC* pDC = GetDC();
  CRect rect;
  GetClientRect(&rect);
  CBrush br(RGB(0, 0, 0));
  pDC->FillRect(&rect, &br);//设置背景为黑
  CBrush newBrush, * oldBrush;
  POINT vertex[12] =
  { {400,800},
    {900,800},
    {950,713},
    {700,281},
    {600,281},
    {350,713},
    {750,713},
    {700,454},
    {500,627},
    {700,627},
    {650,541},
    {600,627} };
  POINT vertex1[6] = { vertex[0],vertex[1],vertex[7],vertex[10],vertex[6],vertex[5] };
  POINT vertex2[6] = { vertex[1],vertex[2],vertex[3],vertex[8],vertex[11],vertex[7] };
  POINT vertex3[6] = { vertex[3],vertex[4],vertex[5],vertex[6],vertex[9],vertex[8] };
  int t = 600;
  while (t--) {
    //第一个填充
    {
      CDC* pDC = GetDC();
      CBrush newBrush, * oldBrush;
      newBrush.CreateSolidBrush(RGB(rand() % 256, rand() % 256, rand() % 256));
      oldBrush = pDC->SelectObject(&newBrush);
      pDC->SetPolyFillMode(WINDING);
      pDC->Polygon(vertex1, 6);
      pDC->SelectObject(oldBrush);
      newBrush.DeleteObject();
    }
    //第二个填充
    {
      CDC* pDC = GetDC();
      CBrush newBrush, * oldBrush;
      newBrush.CreateSolidBrush(RGB(rand() % 256, rand() % 256, rand() % 256));
      oldBrush = pDC->SelectObject(&newBrush);
      pDC->SetPolyFillMode(WINDING);
      pDC->Polygon(vertex2, 6);
      pDC->SelectObject(oldBrush);
      newBrush.DeleteObject();
    }
    //第三个填充
    {
      CDC* pDC = GetDC();
      CBrush newBrush, * oldBrush;
      newBrush.CreateSolidBrush(RGB(rand() % 256, rand() % 256, rand() % 256));
      oldBrush = pDC->SelectObject(&newBrush);
      pDC->SetPolyFillMode(WINDING);
      pDC->Polygon(vertex3, 6);
      pDC->SelectObject(oldBrush);
      newBrush.DeleteObject();
    }
    Sleep(100);
  }
}

5.3 递归圆

//绘制递归圆
//nDepth:递归深度
void circle(int n, double r, double x0, double y0, CDC* pDC) {
  if (n == 0) 
    return;
  const double PI = 3.14159;
  double theta = 2*PI/8;
  double x, y;
  for (int i = 0; i < 8; i++)
  {
    x = 2 * r * cos(i * theta) + x0;
    y = 2 * r * sin(i * theta) + y0;
    CPen newPen, * oldPen;
    newPen.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
    oldPen = pDC->SelectObject(&newPen);
    CRect rect1(x - 0.25 * r, y - 0.25 * r, x + 0.25 * r, y + 0.25 * r);
    circle(n - 1, 0.25 * r, x, y, pDC);
    pDC->Ellipse(&rect1);
  }
}
//绘制递归圆主函数
//nDepth:递归深度
void CDiamondView::DrawRecursionCircle(int nDepth)
{
  InvalidateRect(NULL);//强制清屏
  UpdateWindow();
  if (nDepth == 0) 
    return;
  int x0 = MaxX()/2, y0 =MaxY()/2;//圆心
  int r = 160;//半径
  const double PI = 3.14159;
  CDC* pDC = GetDC();
  CPen newPen, * oldPen;
  newPen.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
  oldPen = pDC->SelectObject(&newPen);
  CRect rect(x0 - r, y0 - r, x0 + r, y0 + r);
  pDC->Ellipse(&rect);
  circle(nDepth, r, x0, y0, pDC);
}

6.程序运行结果

正确地绘制出了金刚石图案,且实现了一笔画的效果。在此图中,含有21个点,半径为150,图案中心在屏幕的中心。

正确地绘制出了魔术三角形。在每一秒,三角形三个部分的颜色都会随机变换一次。

正确地绘制出了递归深度为3的递归圆。


目录
相关文章
|
1月前
|
存储 算法 图形学
【计算机图形学】实验二 用扫描线算法实现多边形填充
【计算机图形学】实验二 用扫描线算法实现多边形填充
50 2
|
1月前
R语言中绘制箱形图的替代品:蜂群图和小提琴图
R语言中绘制箱形图的替代品:蜂群图和小提琴图
|
10月前
|
数据可视化 数据挖掘
热图的基础绘制(Matlab代码实现)
热图的基础绘制(Matlab代码实现)
190 0
|
算法 图形学
【计算机图形学】实验三:二维图形变换
【计算机图形学】实验三:二维图形变换
189 0
【计算机图形学】实验三:二维图形变换
|
前端开发 数据可视化 图形学
【数学篇】09 # 如何用仿射变换对几何图形进行坐标变换?
【数学篇】09 # 如何用仿射变换对几何图形进行坐标变换?
121 0
【数学篇】09 # 如何用仿射变换对几何图形进行坐标变换?
|
数据可视化
【视觉基础篇】15 # 如何用极坐标系绘制有趣图案?
【视觉基础篇】15 # 如何用极坐标系绘制有趣图案?
135 0
【视觉基础篇】15 # 如何用极坐标系绘制有趣图案?
|
传感器 JSON 数据可视化
【视觉高级篇】22 # 如何用仿射变换来移动和旋转3D物体?
【视觉高级篇】22 # 如何用仿射变换来移动和旋转3D物体?
158 0
【视觉高级篇】22 # 如何用仿射变换来移动和旋转3D物体?
|
图形学
【计算机图形学】期末复习part2:二维与三维图形变换
【计算机图形学】期末复习part2:二维与三维图形变换
135 0
【计算机图形学】期末复习part2:二维与三维图形变换
|
算法 图形学
【计算机图形学】实验四:线段裁剪
【计算机图形学】实验四:线段裁剪
88 0
【计算机图形学】实验四:线段裁剪
|
缓存 图形学
计算机图形学——实验二 几何图形变换实验
实验二 几何图形变换实验 1. 进一步掌握二维、三维变换的数学知识、变换原理、变换种类、变换方法; 2. 利用OpenGL实现二维、三维图形变换,在屏幕上显示变换过程或变换结果; 3. 掌握OpenGL常用的变换函数,利用OpenGL绘制简单的三维物体。 1、下面的代码采用GLUT库,使用了双缓存,在按下鼠标左键后,程序在空闲时一直不停地调用spinDisplay函数,实现了一个矩形在窗口中匀速转动(单击鼠标右键停止转动)。请修改代码,实现矩形在窗口内沿着水平线从左侧移动到右侧。通过实验说明glPushMa
433 0
计算机图形学——实验二 几何图形变换实验