From 99abeb27dac0fe4c84a50d2215b04aede97a3e2e Mon Sep 17 00:00:00 2001 From: biss Date: Tue, 12 May 2026 22:07:06 +0800 Subject: [PATCH] 222 --- lab1/4.cpp | 6 +- lab2/lab2.cpp | 112 ++++++++++++++++++------------------ lab2/lab2.exe | Bin 68330 -> 67922 bytes lab4/lab4.cpp | 155 ++++++++++++++++++++++++++------------------------ lab4/lab4.exe | Bin 67770 -> 68001 bytes 5 files changed, 141 insertions(+), 132 deletions(-) diff --git a/lab1/4.cpp b/lab1/4.cpp index bb9aefe..2e3bf12 100644 --- a/lab1/4.cpp +++ b/lab1/4.cpp @@ -52,7 +52,7 @@ void init() { // 定义 OpenGL 初始化函数。 glMatrixMode(GL_PROJECTION); // 切换到投影矩阵模式。 glLoadIdentity(); // 将当前投影矩阵重置为单位矩阵。 gluOrtho2D(0.0, WIDTH, 0.0, HEIGHT); // 设置二维正交投影范围。 -} // 初始化函数结束。 +} int main(int argc, char** argv) { // 程序入口函数。 glutInit(&argc, argv); // 初始化 GLUT。 @@ -63,5 +63,5 @@ int main(int argc, char** argv) { // 程序入口函数。 init(); // 调用初始化函数。 glutDisplayFunc(display); // 注册显示回调函数。 glutMainLoop(); // 进入 GLUT 事件循环。 - return 0; // 程序正常结束。 -} // 主函数结束。 \ No newline at end of file + return 0; +} \ No newline at end of file diff --git a/lab2/lab2.cpp b/lab2/lab2.cpp index 2667da2..804d9c6 100644 --- a/lab2/lab2.cpp +++ b/lab2/lab2.cpp @@ -1,5 +1,4 @@ -#include // 引入 OpenGL 头文件,提供窗口和绘图函数。 -#include // 引入输入输出流库,便于需要时输出调试信息。 +#include // 引入 OpenGL 头文件,提供窗口和绘图函数。 // 定义区域编码 #define INSIDE 0 // 0000,表示点在裁剪窗口内部。 @@ -12,21 +11,44 @@ struct ClipWindow { // 定义用于保存裁剪窗口边界的结构体。 float xmin, xmax, ymin, ymax; // 保存裁剪窗口的左、右、下、上边界。 }; // 结构体定义结束。 -ClipWindow rect; // 定义全局裁剪窗口对象。 -int x_0, y_0, x_1, y_1; // 定义线段端点坐标变量。 +struct Point { // 定义二维点结构体。 + float x, y; // 保存点的横坐标和纵坐标。 +}; // 点结构体定义结束。 -int computeCode(float x, float y, ClipWindow rect) { // 根据点坐标和裁剪窗口计算区域编码。 +ClipWindow rect; // 定义全局裁剪窗口对象。 +Point lineStart = {60, 80}; // 定义原始线段起点。 +Point lineEnd = {520, 360}; // 定义原始线段终点。 + +int computeCode(Point p, ClipWindow rect) { // 根据点坐标和裁剪窗口计算区域编码。 int code = INSIDE; // 初始认为点在窗口内部。 - if (x < rect.xmin) code |= LEFT; // 如果点在左边界外,则添加 LEFT 标记。 - else if (x > rect.xmax) code |= RIGHT; // 如果点在右边界外,则添加 RIGHT 标记。 - if (y < rect.ymin) code |= BOTTOM; // 如果点在下边界外,则添加 BOTTOM 标记。 - else if (y > rect.ymax) code |= TOP; // 如果点在上边界外,则添加 TOP 标记。 + if (p.x < rect.xmin) code |= LEFT; // 如果点在左边界外,则添加 LEFT 标记。 + else if (p.x > rect.xmax) code |= RIGHT; // 如果点在右边界外,则添加 RIGHT 标记。 + if (p.y < rect.ymin) code |= BOTTOM; // 如果点在下边界外,则添加 BOTTOM 标记。 + else if (p.y > rect.ymax) code |= TOP; // 如果点在上边界外,则添加 TOP 标记。 return code; // 返回最终区域编码。 } -void cohenSutherlandClip(float& x_0, float& y_0, float& x_1, float& y_1, ClipWindow rect) { // 定义 Cohen-Sutherland 线段裁剪函数。 - int code1 = computeCode(x_0, y_0, rect); // 计算第一个端点的区域编码。 - int code2 = computeCode(x_1, y_1, rect); // 计算第二个端点的区域编码。 +void drawLine(Point p1, Point p2, float r, float g, float b) { // 按指定颜色绘制一条线段。 + glColor3f(r, g, b); // 设置线段颜色。 + glBegin(GL_LINES); // 开始绘制线段。 + glVertex2f(p1.x, p1.y); // 提交第一个端点。 + glVertex2f(p2.x, p2.y); // 提交第二个端点。 + glEnd(); // 结束绘制。 +} + +void drawClipWindow(ClipWindow rect) { // 绘制裁剪窗口。 + glColor3f(1.0f, 0.0f, 0.0f); // 设置绘制颜色为红色。 + glBegin(GL_LINE_LOOP); // 开始绘制闭合线框。 + glVertex2f(rect.xmin, rect.ymin); // 提交裁剪窗口左下角顶点。 + glVertex2f(rect.xmax, rect.ymin); // 提交裁剪窗口右下角顶点。 + glVertex2f(rect.xmax, rect.ymax); // 提交裁剪窗口右上角顶点。 + glVertex2f(rect.xmin, rect.ymax); // 提交裁剪窗口左上角顶点。 + glEnd(); // 结束闭合线框顶点提交。 +} + +void cohenSutherlandClip(Point p1, Point p2, ClipWindow rect) { // 定义 Cohen-Sutherland 线段裁剪函数。 + int code1 = computeCode(p1, rect); // 计算第一个端点的区域编码。 + int code2 = computeCode(p2, rect); // 计算第二个端点的区域编码。 bool accept = false; // 定义是否接受裁剪结果的标志,初始为 false。 while (true) { // 不断处理线段,直到确定接受或舍弃。 @@ -42,7 +64,7 @@ void cohenSutherlandClip(float& x_0, float& y_0, float& x_1, float& y_1, ClipWin // 3. 线段部分在窗口内,需要求交点。 else { // 线段部分可见,需要把窗口外端点裁到边界上。 int code_out; // 保存当前选中的窗口外端点区域编码。 - float x, y; // 保存线段与裁剪边界的交点坐标。 + Point crossPoint; // 保存线段与裁剪边界的交点坐标。 // 选择窗口外的一个端点。 if (code1 != 0) // 如果第一个端点在窗口外。 code_out = code1; // 选择第一个端点作为待裁剪端点。 @@ -50,70 +72,48 @@ void cohenSutherlandClip(float& x_0, float& y_0, float& x_1, float& y_1, ClipWin code_out = code2; // 选择第二个端点作为待裁剪端点。 // 计算交点。 if (code_out & TOP) { // 如果端点在上边界外,则与上边界求交。 - x = x_0 + (x_1 - x_0) * (rect.ymax - y_0) / (y_1 - y_0); // 根据直线参数方程计算交点 x 坐标。 - y = rect.ymax; // 交点 y 坐标等于上边界。 + crossPoint.x = p1.x + (p2.x - p1.x) * (rect.ymax - p1.y) / (p2.y - p1.y); // 根据直线参数方程计算交点 x 坐标。 + crossPoint.y = rect.ymax; // 交点 y 坐标等于上边界。 } // 上边界求交结束。 else if (code_out & BOTTOM) { // 如果端点在下边界外,则与下边界求交。 - x = x_0 + (x_1 - x_0) * (rect.ymin - y_0) / (y_1 - y_0); // 根据直线参数方程计算交点 x 坐标。 - y = rect.ymin; // 交点 y 坐标等于下边界。 + crossPoint.x = p1.x + (p2.x - p1.x) * (rect.ymin - p1.y) / (p2.y - p1.y); // 根据直线参数方程计算交点 x 坐标。 + crossPoint.y = rect.ymin; // 交点 y 坐标等于下边界。 } // 下边界求交结束。 else if (code_out & RIGHT) { // 如果端点在右边界外,则与右边界求交。 - y = y_0 + (y_1 - y_0) * (rect.xmax - x_0) / (x_1 - x_0); // 根据直线参数方程计算交点 y 坐标。 - x = rect.xmax; // 交点 x 坐标等于右边界。 + crossPoint.y = p1.y + (p2.y - p1.y) * (rect.xmax - p1.x) / (p2.x - p1.x); // 根据直线参数方程计算交点 y 坐标。 + crossPoint.x = rect.xmax; // 交点 x 坐标等于右边界。 } // 右边界求交结束。 else if (code_out & LEFT) { // 如果端点在左边界外,则与左边界求交。 - y = y_0 + (y_1 - y_0) * (rect.xmin - x_0) / (x_1 - x_0); // 根据直线参数方程计算交点 y 坐标。 - x = rect.xmin; // 交点 x 坐标等于左边界。 + crossPoint.y = p1.y + (p2.y - p1.y) * (rect.xmin - p1.x) / (p2.x - p1.x); // 根据直线参数方程计算交点 y 坐标。 + crossPoint.x = rect.xmin; // 交点 x 坐标等于左边界。 } // 左边界求交结束。 // 用交点替换原来的外部端点。 if (code_out == code1) { // 如果被裁剪的是第一个端点。 - x_0 = x; y_0 = y; // 用交点更新第一个端点坐标。 - code1 = computeCode(x_0, y_0, rect); // 重新计算第一个端点的区域编码。 + p1 = crossPoint; // 用交点更新第一个端点坐标。 + code1 = computeCode(p1, rect); // 重新计算第一个端点的区域编码。 } // 第一个端点更新结束。 else { // 否则被裁剪的是第二个端点。 - x_1 = x; y_1 = y; // 用交点更新第二个端点坐标。 - code2 = computeCode(x_1, y_1, rect); // 重新计算第二个端点的区域编码。 + p2 = crossPoint; // 用交点更新第二个端点坐标。 + code2 = computeCode(p2, rect); // 重新计算第二个端点的区域编码。 } } } // 如果接受,则绘制裁剪后的线段(蓝色)。 if (accept) { // 如果线段最终被接受。 - glBegin(GL_LINES); // 开始按线段方式提交顶点。 - glColor3f(0.0f, 0.0f, 1.0f); // 设置绘制颜色为蓝色。 - glVertex2f(x_0, y_0); // 提交裁剪后线段的起点。 - glVertex2f(x_1, y_1); // 提交裁剪后线段的终点。 - glEnd(); // 结束线段顶点提交。 + drawLine(p1, p2, 0.0f, 0.0f, 1.0f); // 绘制裁剪后的蓝色线段。 } // 接受线段绘制结束。 } // 显示回调函数 void myDisplay() { // 定义窗口重绘时调用的显示函数。 glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区。 -// 空行:分隔清屏和裁剪窗口绘制。 - // 1. 绘制裁剪窗口 (红色线框)。 - glColor3f(1.0f, 0.0f, 0.0f); // 设置绘制颜色为红色。 - glBegin(GL_LINE_LOOP); // 开始绘制闭合线框。 - glVertex2f(rect.xmin, rect.ymin); // 提交裁剪窗口左下角顶点。 - glVertex2f(rect.xmax, rect.ymin); // 提交裁剪窗口右下角顶点。 - glVertex2f(rect.xmax, rect.ymax); // 提交裁剪窗口右上角顶点。 - glVertex2f(rect.xmin, rect.ymax); // 提交裁剪窗口左上角顶点。 - glEnd(); // 结束闭合线框顶点提交。 - // 2. 绘制原始线段 (绿色)。 - int orig_x_0 = 50, orig_y_0 = 350; // 定义原始线段的第一个端点坐标。 - int orig_x_1 = 550, orig_y_1 = 50; // 定义原始线段的第二个端点坐标。 + drawClipWindow(rect); // 绘制红色裁剪窗口。 + drawLine(lineStart, lineEnd, 0.0f, 1.0f, 0.0f); // 绘制绿色原始线段。 - glBegin(GL_LINES); // 开始按线段方式提交顶点。 - glColor3f(0.0f, 1.0f, 0.0f); // 设置绘制颜色为绿色。 - glVertex2f(orig_x_0, orig_y_0); // 提交原始线段起点。 - glVertex2f(orig_x_1, orig_y_1); // 提交原始线段终点。 - glEnd(); // 结束原始线段顶点提交。 - - // 3. 执行裁剪并绘制结果 (蓝色)。 - float cx_0 = orig_x_0, cy_0 = orig_y_0; // 将原始起点复制为浮点变量。 - float cx_1 = orig_x_1, cy_1 = orig_y_1; // 将原始终点复制为浮点变量。 + // 执行裁剪并绘制结果 (蓝色)。 glLineWidth(3.0); // 设置线宽为 3 像素。 - cohenSutherlandClip(cx_0, cy_0, cx_1, cy_1, rect); // 执行裁剪算法并绘制裁剪后的线段。 + cohenSutherlandClip(lineStart, lineEnd, rect); // 执行裁剪算法并绘制裁剪后的线段。 glLineWidth(1.0); // 恢复线宽。 glFlush(); // 强制执行所有尚未执行的 OpenGL 绘图命令。 @@ -122,10 +122,10 @@ void myDisplay() { // 定义窗口重绘时调用的显示函数。 // 初始化设置 void Init() { // 定义初始化函数。 glShadeModel(GL_FLAT); // 设置平面着色模式。 - rect.xmin = 100; // 设置裁剪窗口左边界。 - rect.xmax = 400; // 设置裁剪窗口右边界。 - rect.ymin = 100; // 设置裁剪窗口下边界。 - rect.ymax = 300; // 设置裁剪窗口上边界。 + rect.xmin = 150; // 设置裁剪窗口左边界。 + rect.xmax = 450; // 设置裁剪窗口右边界。 + rect.ymin = 120; // 设置裁剪窗口下边界。 + rect.ymax = 320; // 设置裁剪窗口上边界。 } // 窗口大小调整 diff --git a/lab2/lab2.exe b/lab2/lab2.exe index 0746bc10fcbce2840e364529d196e6aba51e1ae5..40ccffb5c771cb62e81a4a41833e32516750ad21 100644 GIT binary patch delta 13685 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 SnTFpBbnH8Ob?J}yTmBDSgXtLn delta 14160 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 // 引入 GLUT/OpenGL 头文件,提供窗口和绘图函数。 +#include // 引入 GLUT 和 OpenGL 相关函数。 -// 定义窗口宽度和高度。 -const int WIDTH = 800; // 定义窗口宽度为 800 像素。 -const int HEIGHT = 600; // 定义窗口高度为 600 像素。 +const int WINDOW_WIDTH = 800; // 设置窗口宽度。 +const int WINDOW_HEIGHT = 600; // 设置窗口高度。 +const int CURVE_SEGMENTS = 10000; // 设置曲线分段数量,数量越大曲线越平滑。 -struct Point { // 定义用于保存坐标点的结构体。 +struct Vec2 { // 定义二维坐标点结构体。 double x; // 保存点的 x 坐标。 double y; // 保存点的 y 坐标。 -}; // 结构体定义结束。 +}; -// 定义三次 Bezier 曲线的四个控制点。 -Point p0 = { -300.0, -100.0 }; // 定义第一个控制点。 -Point p1 = { 0.0, 200.0 }; // 定义第二个控制点。 -Point p2 = { 200.0, 300.0 }; // 定义第三个控制点。 -Point p3 = { 300.0, 100.0 }; // 定义第四个控制点。 +Vec2 controlStart = { -300.0, -100.0 }; // Bezier 曲线的起点。 +Vec2 controlHandleA = { 0.0, 200.0 }; // 第一个控制点,用来影响曲线起始方向。 +Vec2 controlHandleB = { 200.0, 300.0 }; // 第二个控制点,用来影响曲线结束方向。 +Vec2 controlEnd = { 300.0, 100.0 }; // Bezier 曲线的终点。 -Point bezier(double t) { // 根据参数 t 计算三次 Bezier 曲线上的点。 - double u = 1.0 - t; // 计算 1-t,便于代入 Bezier 曲线公式。 +Vec2 calculateBezierPoint(double t) { // 根据参数 t 计算三次 Bezier 曲线上的点。 + double inverseT = 1.0 - t; // 计算 1 - t,方便套用 Bezier 公式。 + double startWeight = inverseT * inverseT * inverseT; // 起点对应的权重。 + double handleAWeight = 3.0 * t * inverseT * inverseT; // 第一个控制点对应的权重。 + double handleBWeight = 3.0 * t * t * inverseT; // 第二个控制点对应的权重。 + double endWeight = t * t * t; // 终点对应的权重。 - Point p; // 定义曲线上的当前点。 - p.x = u * u * u * p0.x + 3 * t * u * u * p1.x + 3 * t * t * u * p2.x + t * t * t * p3.x; // 根据三次 Bezier 公式计算 x 坐标。 + Vec2 curvePoint; // 保存当前计算出的曲线点。 + curvePoint.x = startWeight * controlStart.x // 按权重累加起点的 x 坐标。 + + handleAWeight * controlHandleA.x // 按权重累加第一个控制点的 x 坐标。 + + handleBWeight * controlHandleB.x // 按权重累加第二个控制点的 x 坐标。 + + endWeight * controlEnd.x; // 按权重累加终点的 x 坐标。 + curvePoint.y = startWeight * controlStart.y // 按权重累加起点的 y 坐标。 + + handleAWeight * controlHandleA.y // 按权重累加第一个控制点的 y 坐标。 + + handleBWeight * controlHandleB.y // 按权重累加第二个控制点的 y 坐标。 + + endWeight * controlEnd.y; // 按权重累加终点的 y 坐标。 - p.y = u * u * u * p0.y + 3 * t * u * u * p1.y + 3 * t * t * u * p2.y + t * t * t * p3.y; // 根据三次 Bezier 公式计算 y 坐标。 - - return p; // 返回计算得到的曲线点。 + return curvePoint; // 返回曲线上当前参数 t 对应的点。 } -void drawAxis() { // 定义绘制坐标轴的函数,便于观察控制点和曲线位置。 - glColor3f(0.5f, 0.5f, 0.5f); // 设置绘制颜色为灰色。 - glLineWidth(1.0f); // 设置线宽为 1 像素。 - - glBegin(GL_LINES); // 开始按线段方式提交顶点。 - glVertex2d(-400.0, 0.0); // 提交 x 轴左端点。 - glVertex2d( 400.0, 0.0); // 提交 x 轴右端点。 - glVertex2d(0.0, -200.0); // 提交 y 轴下端点。 - glVertex2d(0.0, 400.0); // 提交 y 轴上端点。 - glEnd(); // 结束坐标轴顶点提交。 +void submitControlVertices() { // 将四个控制点提交给当前 OpenGL 绘制命令。 + glVertex2d(controlStart.x, controlStart.y); // 提交起点坐标。 + glVertex2d(controlHandleA.x, controlHandleA.y); // 提交第一个控制点坐标。 + glVertex2d(controlHandleB.x, controlHandleB.y); // 提交第二个控制点坐标。 + glVertex2d(controlEnd.x, controlEnd.y); // 提交终点坐标。 } -void drawControlPolygon() { // 定义绘制控制多边形的函数。 - glColor3f(0.0f, 0.0f, 1.0f); // 设置绘制颜色为蓝色。 - glLineWidth(2.0f); // 设置线宽为 2 像素。 +void renderCoordinateAxes() { // 绘制坐标轴。 + glColor3f(0.5f, 0.5f, 0.5f); // 设置坐标轴颜色为灰色。 + glLineWidth(1.0f); // 设置坐标轴线宽。 - glBegin(GL_LINE_STRIP); // 开始按连续折线方式提交顶点。 - glVertex2d(p0.x, p0.y); // 提交第一个控制点。 - glVertex2d(p1.x, p1.y); // 提交第二个控制点。 - glVertex2d(p2.x, p2.y); // 提交第三个控制点。 - glVertex2d(p3.x, p3.y); // 提交第四个控制点。 - glEnd(); // 结束控制多边形顶点提交。 + glBegin(GL_LINES); // 开始绘制独立线段。 + glVertex2d(-400.0, 0.0); // x 轴左端点。 + glVertex2d(400.0, 0.0); // x 轴右端点。 + glVertex2d(0.0, -200.0); // y 轴下端点。 + glVertex2d(0.0, 400.0); // y 轴上端点。 + glEnd(); // 结束坐标轴绘制。 } -void drawBezierCurve() { // 定义绘制三次 Bezier 曲线的函数。 - glColor3f(1.0f, 1.0f, 0.0f); // 设置绘制颜色为黄色。 - glLineWidth(3.0f); // 设置线宽为 3 像素。 +void renderControlPolygon() { // 绘制连接控制点的折线。 + glColor3f(0.0f, 0.0f, 1.0f); // 设置控制多边形颜色为蓝色。 + glLineWidth(2.0f); // 设置控制多边形线宽。 - double dt = 1.0 / 10000.0; // 定义参数 t 每次增加的步长,步长越小曲线越平滑。 + glBegin(GL_LINE_STRIP); // 开始绘制连续折线。 + submitControlVertices(); // 按顺序提交四个控制点。 + glEnd(); // 结束控制多边形绘制。 +} - glBegin(GL_LINE_STRIP); // 开始按连续折线方式绘制曲线。 - for (double t = 0.0; t <= 1.0; t += dt) { // 从 0 到 1 逐步取点。 - Point p = bezier(t); // 计算当前参数对应的曲线点。 - glVertex2d(p.x, p.y); // 提交当前曲线点。 +void renderBezierCurve() { // 绘制三次 Bezier 曲线。 + glColor3f(1.0f, 1.0f, 0.0f); // 设置曲线颜色为黄色。 + glLineWidth(3.0f); // 设置曲线线宽。 + + double step = 1.0 / CURVE_SEGMENTS; // 计算每次增加的 t 步长。 + + glBegin(GL_LINE_STRIP); // 开始用连续折线近似绘制曲线。 + for (double t = 0.0; t <= 1.0; t += step) { // 从 t=0 到 t=1 依次取点。 + Vec2 curvePoint = calculateBezierPoint(t); // 计算当前 t 对应的曲线点。 + glVertex2d(curvePoint.x, curvePoint.y); // 提交当前曲线点坐标。 } - glEnd(); // 结束曲线顶点提交。 + glEnd(); // 结束曲线绘制。 } -void drawControlPoints() { // 定义绘制控制点的函数。 - glColor3f(1.0f, 0.0f, 0.0f); // 设置绘制颜色为红色。 - glPointSize(8.0f); // 设置控制点大小为 8 像素。 +void renderControlPoints() { // 绘制四个控制点。 + glColor3f(1.0f, 0.0f, 0.0f); // 设置控制点颜色为红色。 + glPointSize(8.0f); // 设置控制点大小。 - glBegin(GL_POINTS); // 开始按点方式提交顶点。 - glVertex2d(p0.x, p0.y); // 提交第一个控制点。 - glVertex2d(p1.x, p1.y); // 提交第二个控制点。 - glVertex2d(p2.x, p2.y); // 提交第三个控制点。 - glVertex2d(p3.x, p3.y); // 提交第四个控制点。 - glEnd(); // 结束控制点顶点提交。 + glBegin(GL_POINTS); // 开始绘制点。 + submitControlVertices(); // 提交四个控制点的位置。 + glEnd(); // 结束控制点绘制。 } -void myDisplay() { // 定义窗口重绘时调用的显示函数。 - glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区。 +void displayScene() { // GLUT 显示回调函数,负责绘制整个画面。 + glClear(GL_COLOR_BUFFER_BIT); // 清空颜色缓冲区,准备重新绘制。 - drawAxis(); // 绘制坐标轴。 - drawControlPolygon(); // 绘制控制多边形。 - drawBezierCurve(); // 绘制三次 Bezier 曲线。 - drawControlPoints(); // 绘制控制点。 + renderCoordinateAxes(); // 绘制坐标轴。 + renderControlPolygon(); // 绘制控制多边形。 + renderBezierCurve(); // 绘制 Bezier 曲线。 + renderControlPoints(); // 绘制控制点。 - glFlush(); // 强制执行所有尚未执行的 OpenGL 绘图命令。 + glFlush(); // 强制执行前面的 OpenGL 绘图命令。 } -void Init() { // 定义初始化函数。 +void initializeOpenGL() { // 初始化 OpenGL 绘图环境。 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // 设置背景颜色为黑色。 glMatrixMode(GL_PROJECTION); // 切换到投影矩阵模式。 - glLoadIdentity(); // 将当前投影矩阵重置为单位矩阵。 + glLoadIdentity(); // 重置当前投影矩阵。 gluOrtho2D(-400.0, 400.0, -200.0, 400.0); // 设置二维正交投影范围。 } -int main(int argc, char** argv) { // 程序入口函数,接收命令行参数。 +int main(int argc, char** argv) { // 程序入口函数。 glutInit(&argc, argv); // 初始化 GLUT。 - glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // 设置显示模式为 RGB 颜色和单缓冲。 - glutInitWindowSize(WIDTH, HEIGHT); // 设置窗口大小为 WIDTH x HEIGHT。 - glutInitWindowPosition(100, 100); // 设置窗口初始显示位置。 - glutCreateWindow("实验4_03毕爽爽 三次Bezier曲线"); // 创建窗口并设置标题。 + glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // 使用单缓冲和 RGB 颜色模式。 + glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); // 设置窗口大小。 + glutInitWindowPosition(100, 100); // 设置窗口初始位置。 + glutCreateWindow("实验4_01毕爽爽三次 Bezier 曲线"); // 创建窗口并设置标题。 - Init(); // 调用初始化函数。 - glutDisplayFunc(myDisplay); // 注册显示回调函数。 + initializeOpenGL(); // 初始化 OpenGL 参数。 + glutDisplayFunc(displayScene); // 注册显示回调函数。 + glutMainLoop(); // 进入 GLUT 主事件循环。 - glutMainLoop(); // 进入 GLUT 事件处理主循环。 - return 0; + return 0; // 程序正常结束。 } diff --git a/lab4/lab4.exe b/lab4/lab4.exe index b0b1f93bad84b66d8280e4b5afdc05b8dd0f4c31..10b96bc61b6cf962e4a9d71459a0c077ed523cea 100644 GIT binary patch delta 12270 zcmbW7d0Z9c{>NtqMmFIb6=V$#95%@e+_#^ihK{DjwM?>-O;C0MG&A*}XiCQg{aUWK z$kg0L(OgO|E?udt(5%SphW@m;SxII$vXtNFdFF7&$9wY`3_I+K&!bG$Do->|qIquqZm;8VbA~@{bc^ed&Gcb( z)-60U2I_UsBQk88gBd;^4KKT2%m_)ccdj%yZ`Iqs4R^GUca)^cq^lKkuSzd?9&u-W zJENG3x_KB(q>5H~h6$|>2*9$}`%|)e*QgGNjj$^a1{Y^Bfs5M^d{JGQ=Mhg9X9C&X zhxsKV+Ih4z1Y$^t(Y(rwtR8vt5L)386Z1Q&LIk@yaSjVV z!_%I06^2C!Y*&+XrZ$^vzxL=OD+?mY*K4#ql%{ya%09H%D?`b%(si#Ca{dcbikp}H7=QgM z2El61)=Y(Un8Q9xC8@1}8GNc6oW9S%cd2A^Se(=?YVWi7#oiubpKh?}K7;ezpb9lv zjGBHinf>1HD@l;vCm`+WJNV4jtD4R|?CLI#Y`oF}&iH+Tx*z5(D9gFYjrZF-l-+(| z(R~-j@e8b{rTj{4J-kzx>KKadPJ=OqK|iRrb_=ie*ymqnUH%U}y3>dC;l}%R)t|@U zm2c$McGcZLZ*X+Pg>4XaHIuiRlkc{*p*7?F;A1g|iHLfhjnzhEu&b}~JUsePNA$f0 zdW0j^)lGo>erQkiJ5A{nE-$C@P64q#?Pl!8NMZMkem|+d_GZ0!IH|RCKk7L|b)7;7 zU*e2sTvW+=Z&y_#<0g*y-UpAdywyD54)4#DN?O-B*w#&lZvZyuqo>WM*~i>AZquD# z{PzKU;4z-|#(8~Evy39HEMY|)k^T7yx^jP{{)J<7-LD&LA-x^arUnAQLg6uDFXApZ z=e!e|uVNr&*ay&FAX8g|woD!03jjOei?``S7hl^fZVQVQTsaJLNxx01oJU(!2`*MuwMAt( zDb;unKx!xgPcF5Tdnd^{~ z9de9A4&<^uLHn+AJro@q8o@>YGX=dD(<|!SwMsRXV;40%fh5Q;*nVqkW0Q2x)`o54IsS+-ol$pFzTZI8-!Z@J zA*hsj!}Bm5^oy6jp>O?q$+Z;J^?Y(eJevXp9*6n3(%wi!<6rHKUTAnEILxBah-_~J zqA|3+(GiX52{hP$s4^gd=K9Z+f2UjiW0k>0R2~>gX#wtvFH?g%XaQsG>P;FJ;7^+Z z!sJtQG9b=u;pt8`*Yn%ndp<4)n3nm<#3B;_nr(EME?~SEJt$Z;y@qyF4+Qm zn7$}y%b$(YP}rRS3!%n9A7$jj)ExMX+#eu-o(=MmJ2B0yhiybyGt9rwM^%BeJ18jO zppC^rm>>*R8gH;=t}g1qx__eivp?I~?CP3)Nvf!mE7j%s)EX3_WbgncJD%;Pg{TBm z>^+b(_ebn3Lm+DeQ+cqe{FVo`EB!S%$o$?smh8G*Rgv_kY*&xho(WErl||iaJs#*U zD-{pYh|q0{$Ak1^=rQX*rm<-?Ey5bce%F8&FW?N6=5R0edhsW<1^CgGu$b^tz%%M| z_+$stFNkBp&(4LqI*#Hj!xhUkDzx;Kn`w(BR{mS<$Ch_oeXJQU#QRSdSo>$tny5I% znn9_@rM4ggORnbvOzjQhjo#^#mT6;~8)3E4(QFgT+ zgw4SMJ=994!Hp8VXmt-qSneZP$##i%DO^ufiG^lYFHm|+Kd(rq>wbDO=IKG-rt;gW z3ks}-st?5g9`%g+9*B&T*XK4jWA)-T17Po+`G|Lb2E_IXp98{`VN9C>bTioNygfJTW;8uAD{qkTxr6iQPcP~_w(AtgNKa@LP z!?-+q3VS2pWbmvEp%;2Y$$RMa9&g%8uu9oJ*)HQ8?fCyx?sMqraENfo&JL+KH9IG(#B%2LC*RP_-kEf{cZ_RGsFX|PI)KD%-Odi5{2|AODgRt8` zXYwk}ThN)@6f8;7d|mzly(4rc`-DhR0CXm6aYjOCa^wS&6c1erm879K2SaD_5Ke7A zUa*<+4bCTUp$YOj&NS#KSy~z zO!_=5NoMF~$bC3Npfg#5hg&RkCOhGQ*&8~O-aRELk=a8A;v5UzVuP{~=M!i!*#~b) zY0#Pc17|*TCLhJ4eHL^kH{fL39+RW+;!p*h$ro{MgwEs-IJZG(@*})_AAoM|CrN+7 zSqD80@+i(BXVIvG@)6EP=vc}Umao(VoymaySO?H8kn3>XV){Tyioz*X)F!z4$g751 z`X&$1x5c4mNt%e04G@za?k=kP1XmY183X9BDFk20ZRpA2Ho7ySBaIv3PP>PP)c!vF z4`u&Ib7zl+zWRdgxiZ|pHa_LDtTgnk?J_yem&u`pdOM;x(i?9Sqvmdr%jn0s!Ey6k zF_Nf@eYs$#B&`HVakO-@1>`$7YMAM3p22S6a-U3|g$t~wN zp^u82Lx=O6FbZ&!7q={T!Xbcv=nwbJ0Y zihiE$M;W#Waup>k52TO5t6&yMf7$7$VuU3Z+H3P)8ShG+%VXta8dUz2oIf0 zRYWS)-c(Z+K|Pj^qCpEsE8S&WjWDQ2zKinFWZrKt(v)q`<|sA1z5gXmIn1^A#hOyb zwLQ@4xz>G&rZjME2ed}6#a3!c6W6vvYew~zb7)|>7kRw&AZ>bCQwFm1LA3mo2bt_v z`l;N5zO2Zk*X)|2@ycY0&Q;{njHLz9Q)EfH+a^iVz4<^P+?<~uc2UE;)E4Eo1h0ux@-Q;X4 zLc0mct@QSCO)jK1XM5xdO`bz5R#=rL79fI&#ud408j^IN^f>{PTIELb$dhJm50V#> zy~--L@JP2;^jNhrNZv)kD@SywMR_f}JkwHVc_#rID1BL2hcBTmHSy)N+pD_FVQ=%vZ46q)jatsJ-UYJMQie8mA+aNrrtsY7HV7L*Xw&; zRoV2c)Y7cX(k29QW5ICZ6LFg%4PpXW#Qe-ZIC~QXmg&1{t*`kfCmRYj$d9oWCmRp8 zfU}!UHU&%y#7G3;M)9A8)(=9y3J^0TtP4iH*f{B-busA2#C0pYHX{aec9AvKZMmF0 z)?4MS^w9dSfXlehBE-1?QWMCh!Bb(O*rB3dK|y>PaBbK6TrbusJ!k+AT2F&ESmjVk z-C(61>#-8n451G;M9Mwr#)dE@#EsI{2bd$A0sA80jt~}*TTk7X;pK{p_eN~u5tGRD z*Ra9kU~WN12*-dw4OJ6JAxN@7=75;Pcvt#3Gp_^Or^9|ucm%M-!X{yWlbr|a6wXSN z&Gh?U^SnZw1;+C(w^HS6R@{2K@oA=WujR?l(to|q^z_&LOn>2lvWrWyO0&u^Ghh^N z^TE~auji>_S*-S3M~{7la|SvJ@P#>}No_5#?bD6-7+ zGdWo$*o#p-%kxgS74U~BK4@5coATr*=)@+g+?%d#vMTEow)ye(Sx?>GwBjZmhtDhY z+?z2_|}JLPj%3$Ef%?+ z!nd#}N%*`=IrzLn%kcRV?c4IGe30%yXAXII+%DV7^nLvEv#ohFc$+4lqsq6eavGyv zX)*e%fQvktzS){iW43$Jn74wcaC@Y=3H>u>X1E8f-WH)oc}P+nb5-hMsA*fS+6XJ> zoYL|gkx?y9ztq&?)YR0R!kn_K!kNx}JR2bz5F!}2v|5HnGHzh2(h#$1N3P0}8sYZr zjErJSUoT@uW=UCUdO_*5)T~)KW$p0@5t?{KO)>Q6j^*^yu3>C*j}CD}$6 zNTmsR_A5<#4%Wz_VFwC;sph~OrCImOIH)Nty4nP_Rad9Hjs1d#)%2lD(A>E;`H+T1 z!B``-017`m7k3sQbab6#93Kc0g`~jD5Q=1)b64 zS9y$iXS&PPJYUy(P2S1#v34%~SYJR}VO#aSCLiIp?9J=X_ao&RZol*cO+LfzSv!|9 zKP-@Y(zy@A@B2pZ#eh9X%CEXFp4%_(g8yabdJFUZvvGBRMKR z=}uQJ(Iu$TxiPY zp{kE3UNC4r-~-U=J5bB>U1@irJDvW#N{RENC%=fW^~aSuJVMzk2{sQLlR#>);bK>I zkmr~UsxZi0km)!LvW|HPHakID5!SFd4#EzWN6+<<4X9B_e+h(rF)`e{@IzojH+`qo z-C{tBk<2K1G>BP9|0GC@K&FAz3mu#7^%VLc7};S|?tO2vtsv}RxgZ8!ZGx9PfCLL}#?rOtw3t^jPNA9&H?K8ilGRfu!Nhr429p zdR0Xr625C1WXWV8_KnLJ%hk*X2i^)CZaX-!+~al{ggtPLKusX-a4|Z3lWu%z_4PqX zmtbkc5BH|%ixHzo;zA3o4Tony*v}0p*^xL0giWI1Jev_=6qnP=i+;9xaKo<}tp-OF zz32Nt#PUvnBs<3x#?qG{?9gYiAgds=_yv4lc4os1*UXF=*;1o0?pIlyr}1H={~4_` zVN6|o^ieiC>kDEL(hmeNBZxlk1?l57N7wd$vNd=kC1|1daeJlZC zhcR*GAgqsu%?1`nxS5VKFJVo54$>-k-Le6#Me#-;HxuedAB`RbgRB+Y5#k2_BEN3>tMTi95y%*dK_FG|GRP!7w*yrAT@$b zGsqIS7?ryCVQYge=Fl<8CL2(V6P4ynD@@PF4+X;72x2xuvN(_`rxz4ym?N~&jbxB! zXE#dAN(wUziluEroD4rK&22)B&%;fegO@;(k;3T50g!m1uNOcXKn$D9Ak&3~_$$a^ zVZJ+e#UCaP2%!_Z;_ekfr-M`rCC&mlEQDSRA_-m_Ko&ahIb4;_f@~AK8bNFULPghr z$_4T-5R1?=7k`QG^u}t40I3(cF&KnRv9aMj#t05$gt9@*82@{gUMWzG&{twc!fMzL z(k!gxvmo_CiC=(J3&~sq^j+LY?+@ZCO}n?o?m#Ugh3n40tqEf0!b70h53vK zUTf*at9{0A0k0Q)&wwluESo@Dgznt{5nt2qfZ(_FyH`U8dk5mVFN{wJ2;16?p2mWR zOL{a&Q#VSv7HXRUHBlJ686a$%H|B0Rh`8}qgCNH}HhVy3IeU_tT~IVN3kJ^DE*A3y zY#N2qKD7a*3H4tEF=Gj`@a%4uq+darg%aKI7s4e12?CjeZ!bo#9|NfplBI)G3yXVp zkQDIOI(tI`oXA9xSvOZxMO&YaY_d{AdJC^U|R59gl!8hScKa5 zG9nDcF%b4BHNu?*X%cF`0>TbsW!(NZ;)OrPHbme1lnk%|t%aMh?e_pVEDZY~km*7} z$soo==wHmRRE2J2z=jQ?QP4aPNr+<)VS5Y?!{|*IRSP{k43gq><3G~D!(B-Bci1F? zvV{7~odaRJzA9Y6q&rT%ub+Y#)4^@1t!E!T^ke9b0QgSDpb8_ndr?dgnl9mtm=5!l{QYbdXbI Wli)X8qWO3H=&L)PYaVr%i~a|mK9oiP delta 12405 zcmbVSeOy%4);{OR@TD*#ABvzbFnmdAsEFqEP14YVW|3)Pb_G8`1jJF%u&lwr0>_V` zWrb-;sikIxV&z94qh^|V6*0S3rdWEVw8U<|z0jMd;6rtWCXA3IXHb=;d8F39G2GLh5+F%c=@-kN zxhO62-|frn#>6ud)5iNjk;+@;1!lCo;ed^vA4ZwJ-QwQT+^m8dbe1xKP8H}Y%sS(58spR3 z2)|acDB=5qN^0pE;V9$n<_(y8bMY;Fr2mPJKk)%hIq&?>(&_d302cYRM%*Z$oxH`9 za4)ymEqCYfPi`MY7&{A+A13c1U$_Id<9^pO`zeV0p>bY!d^C4!!`xSxPO}tL;aD)8c)^phe{f|NtR-zXx!U3yfw>^}d*lv}eA6Re^vLHt za-K&{)1)JA$WrFO996;GN^NmNJcJ~V4EIQXkNo%Z+JHZMz4b~6X!}!Wd5G0|{*Sgcwp7W+A>%Yf%;gV1^C43J9Sa#^j)xcacveaRU>QcC zp~>)RV$&^Vk- z>$(k7)+E#S-4@D|Xngkvm376`6c$PD?!HP1QzLxTum_!{aZK+F}%3FO&?eTs6M4+;nm?-%M|p5Q1P`EozY z8m!(;m-?{q_BEfzzIB>z6iQOLTdp$wT1Z*pG0Ofz=D_U4i-)-av0ya=UgenY15P%= zBG!nYrf`!ok*VG2R(QB2j{CnNyUNpV%1%>ceL_TZ(@A`?3&a1=n~BgX zT$q0EP0ON&D`k0fJStUI$z)BGqw4!w_j(1EPX!S#XTe}UIhAh2CMo4p$rd-#5zKn{ z_MAJPC)*jC%phlat6G(bIWlSL#h?|Yf8?~2OE|fG3mdhXjAO;gdF)+{_y4qx1-rtu zMK|`*Mmm(m_E&+mbf_Ol^p6GpH>j3GwbKEnC>u))07AjTbAdThZUyl+3le{ z%x$pDf!qx?!ALd>r^IKuMC+|W^*K!`v@d>8=L+34h&m-q{>wSB$Qbg2|K>^->%{z7O?!hq$di1VAN@Fitepj(FtylfcyN=31=}6UI54c<| ze)Kp^rz7Z_K5=p&we{KHXhh+%)3aSJ^R)lB@`nP={{JZ*asOAt$2|kK%OSkoe!8~B zh2PfxVU{PrJ4#Di+z#H+?%>5_Yff9-I1hQaNA~x~7>^9{NW~+6%l8c8k&Pa?pUa=# z`3@(uan<+pN|!0L|2xt4!BQHliT11Pwzj+eLjNb_$Ri(|{3#_ndBFA)N4Fi_W<7js z=kejWPtD4mcj(_I&P()c%Jk~KzH}ia!OImTrO{kxaDCLkXs>>w`-tvcR& zG4Zg0&SY(GNjeOj$p?}glJpfCnMwF|jk^gtlNWJch28>*#7nKvnS2k=F)y4ob&!wX z;b?)*WKcgz>It36?YI-6Gx;uFg;E$FayRZY=x)fN12B8&Lmf~~;~tL&lWXxv&wec^P*FbS5M4#li)h$>q4$L1%I{zEEw3UI%#{_fF{2U`cu$w;Os6 zv6gk3HZyNF6N_BFV9V0D4e)d6Hh4!zG z?p~jqbwO6_gX)7HPYPjjSh3cQvBw6WqDMWmNuE!?JQEST&yH%gQGJln&v z0B!AB4#qS;YFHRzezF~t)&T5J`<@N8EYh*Z~ zW>gQZ?8j3wif5H9JjXB#Dh1c_4(oDMkR4COr#!>&W zAaXDEHM>AH;qD|?;4_*otm)>@njBhO9UV$)S)$xRbIT^lt#q_(k|G6C{E{riH;~F8 zEP?bbL|7oDJeQ?d18F5hVjwj`BnML63n{d)T$PX0XXT^hG`fFz0nM$*kb6_K6Ynh_ z`*N(1MlUT=(lq+jrK+N8YQgiWlBuc9P_r~O?*&!KVd`QfUqhxXa%~ zDbv)mP%Aa{@nx#w($q7{RCy2r870^9z)m?cv?bPKfeoMw5L(->$*a$7o4%af7a?}l0i2rB}M>}+kNCenrK zP_n)rh#;=7D3p`wuPbeG2ra?qblSAirj(hfsUn81u2khh8n{Xa7Ozs}MRahLO)hKq z!MK600@HYm?@dz|htaCdKFVO3?6ooS658joDK5=hva2tpR)@=5=#lCXrojl!#hh5G z^vFj6Yv7T4Pl0;3g;%Ik?=JwDVPQoEpY=&E=E?FCR82No=kljzD}(7IJuGjh=+zk0 z!e@}|ilybNW95CcT?BJp?nU>$^oo3vPQJw1+^L1aUtTFMrY$eqlzeRp-_Uh5++98H z{OS2s;l!+0J?$f3pe3*9o$sxQMTbA1qe5M4q9PU{UUyfv8?2~ytbu-ArZF`Uj!N`5 z1Jjm=b*=^y7j!3!pLF}J;B*ST6X%M~`5c_@?#TH?=bY*dQcSlyIl88kegvns2T~qh zo$M8S3$3d{z`itWjm>l~HoBF%ZnfdSa;{k=*HFZ(Hado6sIP_(4o1QL*@mM)UNAp* z-t4I*`MLAv^_|Y<%db3Gw?H$}Py!?~oUgtQt9E`Z1Gp!gtvV@(_DN;&`WD=N=rCjHV|H17c1XIaqFVI-(aI@zN2*CdjXE_#eC!7sa{uz zgNOP0iu)Q)>90i%Z3M-Nyckh70Z|3ypFlDNLtp4|Y5scN!Or`K zxU)R_yxjS@B@)`97%uH z#>SWF-FEnzUeaMj`Fc4JEa+^|JbeZ)0vu}NV7?B%0r0d27U!Lv%9NpEjRQ0xiRupti*>OmWAayd=jXj5MFrLv7N z%4@!~abvu^m5!pPj;?K-311U8+3=&n)A%f>_4u4g2k<$cE^itm@1Oy1Y0N(StZ}`k zoi%Pc!13#wS#RgJ3+0`(?;V@Gx_!Oa6Yp)CA|+xfHaU@eHy6;tw^hscn5nUhhkWVC z<{0m-m`M&}#wZZowiL+6*y_{En`7l)=*um51c6~^47T%?fB912)_4U#>ed46izQn| zDYq2*d26J1m>(W8+?Ba3k<~BD4c?|ayL0?IMe{q+7)9~9@w-2-XJyDE*|n@YRhRpkVd-y21ikBeyMd#ap`7JIyx(DL_- z$o)ww^{rFszE4wW8{|%RDkW`K<$UgC^LCYz4y0224plDY$VOHfTgN_PS|m`dRvs1*4{D%C))gY5R9O5ul6X*FciAwT+NcOMG+NR>Bpuda_& z8hT7a19zzu|FpG^oPj*E7&uTsv0vhiE{QVt45UL}j*>ql z^N~?Xrbga(Bt!n3lR5CUd=L2?iwa9exw-TMyKhNuX$k6)Q|_jMWB19KRNXj`&K*K#mp;dA%vq6-guepMlD!^KfYeAyzfWL{~qJ`gxTYH$KFJ>v-B*GI=msULsF6K+6${> z@$_q)KbRGQ(m3dn6pWLP+d$aJbpj_DNGk?1I3pZ@xH)sdwQ)es2mwt6Qi?vq%mu`r zq#aV4)i#D;Fk>3Wfmnp$zXQ@DAXokIb?C4@S2lhdNcjTEf*&)jfgK0C3kbWA1W(XI zfUtZR!%qUz&|7;C&_XN)GPq0oG_tcxi?XLm)Z-hoV>NnelRA#@2J;=pO}c-1_oIsl3Bjs%ja zryXpG{p$g{w8fvDJA1kv-^g3_g~0pR!f6Zgq*5JW>{+mC!EH=qAzC>?jw=IDjV$fP z?AL%~6^8!|h{bc%DfrG_R5WKg>Pnw|_K0!gv&W8?To}|?<1=h9A&VD*K<9yk z37nsSl!0T+wGBwAFxM_-5K!dC@I!#4={ZBMGzv(L1Fnta=K%T`U0Oc!@^}qNc41u? zF-O8GE(ek&48ImgBK#P`9|z(VtS$o??1TIp!`}duiMbdhqh2Z4wcFojv^YiaKXIxZ`2BOgUU*x9Yv@J1;)V0K0~ zVNJo{9JGe#TR>_APGqnoQA$&+IbT?}RGQgjbBsbKvo@j~ z55!k+Fb#+ph@EkSU@L$Og)3vJ>VPx>F+6_`Bt+nx3kFmpgmo>LdR~Ze{5LvSF&Ngt zFg2bj=#p$eSa}%h^8k<>y`~xGVIXw^XEu;Zm>7{(0DT0 zD+sRFgOe#B?*nn^R?N{CK$`Uj;rx<$#nWfoB~`FG1I}h4pkG2zuVTh;vccfch&l;B zOeG658x5oZh{2f%#8=n~g+O)*t6K?Vr{MX+Q1(X_!S&xksug1V6-bug`W6sLun{#;1co6{!8RF4qQJ}m;u5Bp1w{N3kO#z~TjA|_ z7T%t3+m8#u*(D@yX>UO6ls9rv4MZ&M9YD&GXz``UhYmqa6ViGP2s`nOHM{{tJcIpu zXmwz4x&y&qHkvO*I+CEC5h550MB>x6^1MsZSRfXmn5F<}76O?Iq*6f2fh_j#IJaFu zT*6pKQUTQpMerk#G9gR90ufUZKzsjTbHw0}s)q$;UmzAl?}wX}41Tc#(ku-55RlD6 zpi_X@Jr^teSMkd@(hsN`tG$4U?7$Uw^6M-!12Z70}*%v zIs#;;kd@YOT75aj!Tv1l7G@I$#46+_9teAy8tw)HX%c2L1_-;1)t>$zNC^;oLdQL{ z!~v)VX2v1^3Xm)zpp8KCg@ASgF_uRA(uaTqtE1qsj2Ho31|kW5evi=J?K_aV;7{PS z!px$9Wa(zvp3yc7gWUrTJL8QE-3O#b=im`jlv|8t(h-CrP3VaeJxy5N9GJO~MhKu2{!5_&Jgu%m(CV9;pPg5K>E}Ez$H0jh4~$pw=iUcX)%1)}>UgNB)A;{x z%z!$0#=NOd-d{Rv{z5eR@z#hr#U=CR6lKmSS~PP`F~