计算机图形学课程总结

计算机图形学是我大三上学期开设的课程。现在写个博客,做点总结,也算是没白学这么课程吧~

一、 解释图形学中名词的含义

  • 图形要素:几何要素和非几何要素。
  • 多边形扫描转换:从多边形顶点表示到点阵表示的转换。
  • 消隐:在绘制图形时,消除被遮挡的不可见的线或面。
  • 扭失:曲面片四个顶点的二阶导。
  • 引力场技术:物体延伸到空间中对另一个物体产生吸引效应的技术。
  • 灭点:指立体图形的各边延伸至同一相交点。
  • 正则形体:由几何形体内部的点集和紧紧包裹这些点集的表皮所构成。
  • 反走样:减少或消除图形因锯锯齿齿而失真的技术。
  • 显示分辨率:显示器在显示图像时的分辨率。
  • C1连接:两条相邻曲线段在相交点处,具有相同的一阶导。
  • C2连接:两条相邻曲线段在相交点处,具有相同的一阶导和二阶导。
  • 简单光照模型:由环境光放射、漫反射及镜面光反射构成。
  • 深度缓冲存储:三维图形中处理图像深度坐标的过程。
  • 捕捉技术:利用外部设备捕捉计算机能直接理解的数据,如物体尺寸测量、物体空间定位等。
  • 存储分辨率:帧缓冲区的大小
  • 法向量插值法:保留双向性插值,并对顶点采用法向量插值,其中顶点的法向矢量值由该点相邻的多边形面片的法向矢量值取平均值取得。
  • CRT:阴极射线管
  • DPU:分散处理单元
  • 象素:基本原色素及其灰度的基本编码。
  • 4连通:同一像素在上、下、左、右四个方向上连通。
  • 实体:同时具有几何要素和视觉要素的对象。
  • 型值点:位于最终得到的自由曲线上的点。
  • 控制点:不位于最终得到的自由曲线上的点。
  • 颜色位面法:每一个位面控制一种颜色或灰度,每一个象素点在每一个位面中占一位,通过几个位面中德同一位组合成一个象素。

二、概念简述

  • 图像和图形的区别:图形是无中生有,由计算机软件绘制出来的,它是面向对象的,同时具有几何属性和视觉属性。而图像是由计算机外部设备捕捉得到的,并面向计算机内传输的信息。
  • 字符的两种表示方式:点阵字符和矢量字符。
  • 实体的表示方法:边界表示、分解表示、构造实体几何表示、扫描表示和元球表示。

三、基本图形生成算法

  • 画任意斜率的直线(基于 DDA 算法)
#include <graphics.h>
#include <conio.h>

// 四舍五入
int Round(float x)
{
    return (int)(x < 0 ? x - 0.5 : x + 0.5);
}

// 使用 DDA 算法画任意斜率的直线(包括起始点,不包括终止点)
void Line_DDA(int x1, int y1, int x2, int y2, int color)
{
    float x, y;     // 当前坐标点
    float cx, cy;   // x、y 方向上的增量

    int steps = abs(x2 - x1) > abs(y2 - y1) ? abs(x2 - x1) : abs(y2 - y1);

    x = (float)x1;
    y = (float)y1;
    cx = (float)(x2 - x1) / steps;
    cy = (float)(y2 - y1) / steps;

    for(int i = 0; i < steps; i++)
    {
        putpixel(Round(x), Round(y), color);    // 在坐标 (x, y) 处画一个 color 颜色的点
        x += cx;
        y += cy;
    }
}

// 主函数
void main()
{
    initgraph(640, 480);

    // 测试画线
    Line_DDA(100, 1, 1, 478, GREEN);
    Line_DDA(1, 478, 638, 1, GREEN);

    // 按任意键退出
    getch();
    closegraph();
}
  • 画任意斜率的直线(基于直线的中点算法)
#include <graphics.h>
#include <conio.h>

// 使用中点算法画任意斜率的直线(包括起始点,不包括终止点)
void Line_Midpoint(int x1, int y1, int x2, int y2, int color)
{
    int x = x1, y = y1;
    int a = y1 - y2, b = x2 - x1;
    int cx = (b >= 0 ? 1 : (b = -b, -1));
    int cy = (a <= 0 ? 1 : (a = -a, -1));

    putpixel(x, y, color);

    int d, d1, d2;
    if (-a <= b)        // 斜率绝对值 <= 1
    {
        d = 2 * a + b;
        d1 = 2 * a;
        d2 = 2 * (a + b);
        while(x != x2)
        {
            if (d < 0)
                y += cy, d += d2;
            else
                d += d1;
            x += cx;
            putpixel(x, y, color);
        }
    }
    else                // 斜率绝对值 > 1
    {
        d = 2 * b + a; 
        d1 = 2 * b;
        d2 = 2 * (a + b);
        while(y != y2) 
        { 
            if(d < 0)
                d += d1; 
            else 
                x += cx, d += d2; 
            y += cy; 
            putpixel(x, y, color);
        } 
    }
}

// 主函数
void main()
{
    initgraph(640, 480);

    // 测试画线
    Line_Midpoint(100, 1, 1, 478, GREEN);
    Line_Midpoint(1, 478, 638, 1, GREEN);

    // 按任意键退出
    getch();
    closegraph();
}
  • 画任意斜率的直线(基于 Bresenham 算法)
#include <graphics.h>
#include <conio.h>

// 使用 Bresenham 算法画任意斜率的直线(包括起始点,不包括终止点)
void Line_Bresenham(int x1, int y1, int x2, int y2, int color)
{
    int x = x1;
    int y = y1;
    int dx = abs(x2 - x1);
    int dy = abs(y2 - y1);
    int s1 = x2 > x1 ? 1 : -1;
    int s2 = y2 > y1 ? 1 : -1;

    bool interchange = false;   // 默认不互换 dx、dy
    if (dy > dx)                // 当斜率大于 1 时,dx、dy 互换
    {
        int temp = dx;
        dx = dy;
        dy = temp;
        interchange = true;
    }

    int p = 2 * dy - dx;
    for(int i = 0; i < dx; i++)
    {
        putpixel(x, y, color);
        if (p >= 0)
        {
            if (!interchange)       // 当斜率 < 1 时,选取上下象素点
                y += s2;
            else                    // 当斜率 > 1 时,选取左右象素点
                x += s1;
            p -= 2 * dx;
        }
        if (!interchange)
            x += s1;                // 当斜率 < 1 时,选取 x 为步长
        else
            y += s2;                // 当斜率 > 1 时,选取 y 为步长
        p += 2 * dy;
    }
}

// 主函数
void main()
{
    initgraph(640, 480);

    // 测试画线
    Line_Bresenham(100, 1, 1, 478, GREEN);
    Line_Bresenham(1, 478, 638, 1, GREEN);

    // 按任意键退出
    getch();
    closegraph();
}
  • 画圆(基于中点算法)
#include <graphics.h>
#include <conio.h>

// 中点画圆法
void Circle_Midpoint(int x, int y, int r, int color)
{
    int tx = 0, ty = r, d = 1 - r;

    while(tx <= ty)
    {
        // 利用圆的八分对称性画点
        putpixel(x + tx, y + ty, color);
        putpixel(x + tx, y - ty, color);
        putpixel(x - tx, y + ty, color);
        putpixel(x - tx, y - ty, color);
        putpixel(x + ty, y + tx, color);
        putpixel(x + ty, y - tx, color);
        putpixel(x - ty, y + tx, color);
        putpixel(x - ty, y - tx, color);

        if(d < 0)
            d += 2 * tx + 3;
        else
            d += 2 * (tx - ty) + 5, ty--;

        tx++;
    }
}

// 主函数
void main()
{
    initgraph(640, 480);

    // 测试画圆
    Circle_Midpoint(320, 240, 200, RED);
    Circle_Midpoint(320, 240, 101, RED);

    // 按任意键退出
    getch();
    closegraph();
}
  • 画圆(基于正负算法)
#include <graphics.h>
#include <conio.h>

// 正负画圆法
void Circle_PN(int x, int y, int r, int color)
{
    int tx = 0, ty = r, f = 0;

    while(tx <= ty)
    {
        // 利用圆的八分对称性画点
        putpixel(x + tx, y + ty, color);
        putpixel(x + tx, y - ty, color);
        putpixel(x - tx, y + ty, color);
        putpixel(x - tx, y - ty, color);
        putpixel(x + ty, y + tx, color);
        putpixel(x + ty, y - tx, color);
        putpixel(x - ty, y + tx, color);
        putpixel(x - ty, y - tx, color);

        if(f <= 0)
            f = f + 2 * tx + 1, tx++;
        else
            f = f - 2 * ty + 1, ty--;
    }
}

// 主函数
void main()
{
    initgraph(640, 480);

    // 测试画圆
    Circle_PN(320, 240, 200, RED);
    Circle_PN(320, 240, 101, RED);

    // 按任意键退出
    getch();
    closegraph();
}
  • 画圆(基于 Bresenham 算法)
#include <graphics.h>
#include <conio.h>

// 使用 Bresenham 画圆法
void Circle_Bresenham(int x, int y, int r, int color)
{
    int tx = 0, ty = r, d = 3 - 2 * r;

    while( tx <= ty)
    {
        // 利用圆的八分对称性画点
        putpixel(x + tx, y + ty, color);
        putpixel(x + tx, y - ty, color);
        putpixel(x - tx, y + ty, color);
        putpixel(x - tx, y - ty, color);
        putpixel(x + ty, y + tx, color);
        putpixel(x + ty, y - tx, color);
        putpixel(x - ty, y + tx, color);
        putpixel(x - ty, y - tx, color);

        if (d < 0)      // 取上面的点
            d += 4 * tx + 6;
        else            // 取下面的点
            d += 4 * (tx - ty) + 10, ty--;

        tx++;
    }
}

// 主函数
void main()
{
    initgraph(640, 480);

    // 测试画圆
    Circle_Bresenham(320, 240, 200, RED);
    Circle_Bresenham(320, 240, 101, RED);

    // 按任意键退出
    getch();
    closegraph();
}
  • 画填充圆(基于 Bresenham 算法)
#include <graphics.h>
#include <conio.h>

// 基于 Bresenham 算法画填充圆
void FillCircle_Bresenham(int x, int y, int r, COLORREF color)
{
    int tx = 0, ty = r, d = 3 - 2 * r, i;

    while( tx < ty)
    {
        // 画水平两点连线(<45度)
        for (i = x - ty; i <= x + ty; i++)
        {
            putpixel(i, y - tx, color);
            if (tx != 0)    // 防止水平线重复绘制
                putpixel(i, y + tx, color);
        }

        if (d < 0)          // 取上面的点
            d += 4 * tx + 6;
        else                // 取下面的点
        {
            // 画水平两点连线(>45度)
            for (i = x - tx; i <= x + tx; i++)
            {
                putpixel(i, y - ty, color);
                putpixel(i, y + ty, color);
            }

            d += 4 * (tx - ty) + 10, ty--;
        }

        tx++;
    }

    if (tx == ty)           // 画水平两点连线(=45度)
        for (i = x - ty; i <= x + ty; i++)
        {
            putpixel(i, y - tx, color);
            putpixel(i, y + tx, color);
        }
}

// 主函数
void main()
{
    // 创建绘图窗口
    initgraph(640, 480);

    // 测试画填充圆
    FillCircle_Bresenham(320, 240, 100, GREEN);

    // 按任意键退出
    getch();
    closegraph();
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值