计算机图形学中的几何知识详解

229 阅读7分钟

计算机图形学旨在通过计算机生成、处理和显示图形,而几何在其中扮演着举足轻重的角色,是构建各类图形的基础。在计算机图形学里,首要任务便是精准定义物体的形状,这就必然涉及到几何知识的运用。由于现实中物体形状丰富多样,因此图形学构建了多种几何表示方法,总体可划分为隐式几何表示和显式几何表示。

隐式几何表示

隐式几何表示并非直接刻画几何形状的顶点和边界等元素,而是借助数学关系式来描述。在这种表示法中,几何形状被定义为方程的解集,也就是满足特定条件的一组点的集合。例如,通过一个特定的关系式能够定义出圆环结构。

常用的隐式几何表示技术

  1. 代数曲面:借助一组参数方程来定义曲线和表面,适用于能用数学关系式表达的简单几何体,像常见的球体、圆柱体等规则形状,都可利用代数曲面来表示。
  1. 构造实体几何:通过布尔运算,将不同的简单几何体组合起来,从而构建出复杂的几何体。比如,一个复杂的机械零件模型,可能就是由多个立方体、圆柱体等基本几何体,经过并集、交集、差集等布尔运算组合而成。
  1. 距离函数:它描述了空间中任意一点到几何体表面的最小距离。有一种特殊的距离函数 —— 符号距离函数,当输入空间中的一个点后,依据其返回值可作如下判断:若返回值大于 0,表明该点位于几何体外部;若返回值小于 0,说明该点在几何体内部;若返回值等于 0,则表示该点处于几何体表面。
  1. 水平集:对于表面规则的几何体,距离函数较为适用;但对于表面复杂的几何体,距离函数就难以发挥作用了,此时可采用水平集。水平集的核心思想与距离函数有相似之处,不同的是,距离函数通过输入空间点来计算该点到几何体表面的距离,而水平集则存储了一系列距离值。我们可通过插值法,找到距离为 0 的位置,进而拟合出一条曲面,以此表示几何体的表面。
  1. 分形:分形具有局部与整体形状相似的特点,类似于递归。分形通常通过迭代函数系统(IFS)生成,IFS 是一个迭代过程,反复将函数应用于某个起始点或起始数据,这些函数一般包含缩放、旋转、平移等操作,并且在迭代过程中始终保持自相似性。

显式几何表示

显式几何表示是直接或通过参数映射的方式,明确地定义点、线、面等元素的集合。在这种表示中,各元素的位置常由坐标值直接给出,它们之间的关系则借助数据结构来体现。例如,通过参数映射的关系式,可间接定义点的集合。

常用的显式几何表示技术

  1. 点云:这是显式几何表示中最为简单的技术,其核心思路是利用大量的点来呈现几何体的表面。一般来说,点的密度越高,对几何体的描述精度也就越高。不过,点云存在内存占用大的明显缺点,所以在实际应用中,常常会将其转换为多边形网格。
  1. 网格模型(以多边形网格为例) :多边形网格是图形学里应用最广泛的几何表示方法,它存储点以及多边形(常见为三角形或四边形)。这种形式在处理、模拟和采样等方面都极为便捷。在 3D 建模工作中,我们常常会接触到.obj 格式的模型文件,其本质是一个文本文件,详细记录了顶点、法线、纹理坐标以及连接关系,通过这些信息便能构建出几何体的形状。例如,对于一个立方体结构,文件中会用 “v” 表示顶点,“vn” 表示法线,“vt” 表示纹理坐标,“f” 表示面。像 “f 5/1/1 1/2/1 4/3/1”,就表明这个三角形面由第 5、1、4 个顶点构成,三个顶点对应的纹理坐标分别是第 1、2、3 个纹理坐标,面的法线为第 1 条法线。

曲线在图形学中的应用

曲线在图形学领域有着极为广泛的应用,诸如相机的拍摄路径规划、物体在动画中的移动路径设定、用于控制动画节奏的动画曲线,以及矢量字体的构建等方面,都离不开曲线的运用。在众多曲线类型中,贝塞尔曲线是较为常用且重要的一种。

贝塞尔曲线

  1. 定义与特点:贝塞尔曲线由一系列控制点来定义。例如,4 个控制点能够确定一条贝塞尔曲线,曲线的起始方向沿着第一个控制点和第二个控制点的连线方向,结束方向沿着第三个控制点和第四个控制点的连线方向。需要注意的是,曲线并不一定会经过所有的控制点,但必定会经过起始点和结束点。
  1. 绘制算法(De Casteljau's Algorithm) :该算法的基本原理是运用线性插值,将高阶贝塞尔曲线转化为一阶贝塞尔曲线的组合。以 3 个控制点绘制二阶贝塞尔曲线为例:
    • 首先,定义 3 个控制点,依次连接相邻的控制点。
    • 引入一个变量 t,其取值范围为 (0, 1)。当 t = 0 时,对应贝塞尔曲线的起始点输入值;当 t = 1 时,对应贝塞尔曲线的结束点输入值。在控制点构成的连线上,依据 t 的值确定新的点。比如,在连接第一个控制点和第二个控制点的线段上确定一个点,在连接第二个控制点和第三个控制点的线段上也确定一个点。
    • 接着,连接这两个新确定的点,并按照同样的规则,在这条新连线上再确定一个点。
    • 当只剩下一个新定义的点时,让 t 的值从 0 逐步变化到 1。在此过程中,前面确定的各个点的位置都会随 t 的改变而变化。最终得到的贝塞尔曲线,实际上就是最后确定的那个点在 t 从 0 变到 1 的过程中所经过的路径。当控制点数量增多时,依然遵循上述规则,将高阶贝塞尔曲线转化为一阶贝塞尔曲线的组合,进而完成曲线的绘制。

用 JavaScript 实现简单贝塞尔曲线绘制示例

以下是一段使用 JavaScript 和 HTML5 Canvas 绘制二阶贝塞尔曲线的简单代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Bezier Curve</title>
    <style>
        canvas {
            border: 1px solid black;
        }
    </style>
</head>
<body>
    <canvas id="myCanvas" width="400" height="400"></canvas>
    <script>
        const canvas = document.getElementById('myCanvas');
        const ctx = canvas.getContext('2d');
        // 定义三个控制点
        const controlPoint1 = { x: 50, y: 350 };
        const controlPoint2 = { x: 200, y: 50 };
        const controlPoint3 = { x: 350, y: 350 };
        // 绘制控制点
        function drawPoints() {
            ctx.beginPath();
            ctx.arc(controlPoint1.x, controlPoint1.y, 5, 0, 2 * Math.PI);
            ctx.fillStyle ='red';
            ctx.fill();
            ctx.arc(controlPoint2.x, controlPoint2.y, 5, 0, 2 * Math.PI);
            ctx.fillStyle = 'green';
            ctx.fill();
            ctx.arc(controlPoint3.x, controlPoint3.y, 5, 0, 2 * Math.PI);
            ctx.fillStyle = 'blue';
            ctx.fill();
        }
        // 绘制贝塞尔曲线
        function drawBezierCurve() {
            ctx.beginPath();
            ctx.moveTo(controlPoint1.x, controlPoint1.y);
            for (let t = 0; t <= 1; t += 0.01) {
                const x = Math.pow(1 - t, 2) * controlPoint1.x + 2 * t * (1 - t) * controlPoint2.x + Math.pow(t, 2) * controlPoint3.x;
                const y = Math.pow(1 - t, 2) * controlPoint1.y + 2 * t * (1 - t) * controlPoint2.y + Math.pow(t, 2) * controlPoint3.y;
                if (t === 0) {
                    ctx.moveTo(x, y);
                } else {
                    ctx.lineTo(x, y);
                }
            }
            ctx.strokeStyle = 'black';
            ctx.stroke();
        }
        drawPoints();
        drawBezierCurve();
    </script>
</body>
</html>

在上述代码中:

  1. 首先获取 HTML5 Canvas 元素及其绘图上下文。
  1. 定义了三个控制点,分别用红色、绿色和蓝色的小圆点在 Canvas 上绘制出来。
  1. 在绘制贝塞尔曲线的函数中,通过一个循环,让 t 从 0 以 0.01 的步长逐渐增加到 1。在每次循环中,根据二阶贝塞尔曲线的代数公式计算出对应的 x 和 y 坐标值。当 t 为 0 时,使用moveTo方法将画笔移动到起始点;从 t 大于 0 开始,使用lineTo方法依次连接计算出的点,最终绘制出贝塞尔曲线。

通过运行这段代码,在 Canvas 上就可以直观地看到由三个控制点确定的二阶贝塞尔曲线及其控制点的显示效果 。