【作业】计算机图形学——de Boor算法绘制平面三次B样条曲线

程序功能:给定平面上15个不同的点(数据文件输入) ,用de Boor分割算法编程生成平面三次B样条曲线。

程序语言:c++

程序说明
这段程序是一个用于绘制B样条曲线的图形应用程序。下面是对程序各部分的功能进行说明:

  1. 头文件引入:程序使用了一些头文件,包括iostream、fstream、vector、cmath和graphics.h等。
  2. Point类:这个类表示一个点,具有x和y坐标属性。
  3. BSplineCurve类:这个类表示B样条曲线,包括控制点、结点向量和曲线次数等属性。
    • control_points:控制点的向量,存储了所有控制点的坐标。
    • knot_vector:结点向量,根据控制点数量和曲线次数生成。
    • degree:曲线的次数。 构造函数:初始化控制点和结点向量。
    • BasisFunction()函数:计算基函数的值。
    • CalculatePoint()函数:计算B样条曲线上的点。
  4. drawLine()函数:绘制一条直线。
  5. main()函数:程序的主函数,包含了读取控制点、初始化图形窗口、绘制控制多边形和B样条曲线等过程。
    • 从文件中读取控制点的坐标。
    • 初始化图形窗口。
    • 绘制控制多边形。
    • 创建BSplineCurve对象。
    • 根据步长循环计算并绘制B样条曲线上的点,并连接相邻点。
    • 按下任意键关闭图形窗口。

程序代码

#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <graphics.h>
#include <conio.h>

using namespace std;

class Point 
{
public:
    float x, y;
    Point(float x = 0, float y = 0) : x(x), y(y) {}
};

class BSplineCurve 
{
public:
    vector<pair<float, float>> control_points; // 控制点
    vector<float> knot_vector; // 结点向量
    int degree; // 曲线次数

    //Constructor
    BSplineCurve(vector<pair<float, float>> points, int k)
    {
        control_points = points;
        degree = k;
        // 初始化结点向量, m = n + k + 1   ,m节点数量, n控制点数量 ,k 次数
        for (int i = 0; i <= control_points.size() + degree; i++)
        {
            if (i < degree)
            {
                knot_vector.push_back(0);
            }
            else if (i < control_points.size())
            {
                knot_vector.push_back((i - degree) / (float)(control_points.size() - degree));
            }
            else
            {
                knot_vector.push_back(1);
            }
        }
    }

    // 计算基函数值
    float BasisFunction(int i, int k, float u)
    {
        if (k == 0)
        {
            if (u >= knot_vector[i] && u < knot_vector[i + 1])
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }
        float a = 0, b = 0;
        if (knot_vector[i + k] - knot_vector[i] != 0)
        {
            a = (u - knot_vector[i]) / float(knot_vector[i + k] - knot_vector[i]);
        }
        if (knot_vector[i + k + 1] - knot_vector[i + 1] != 0)
        {
            b = (knot_vector[i + k + 1] - u) / float(knot_vector[i + k + 1] - knot_vector[i + 1]);
        }
        return a * BasisFunction(i, k - 1, u) + b * BasisFunction(i + 1, k - 1, u);
    }

    // 计算B 样条曲线上的点
    Point CalculatePoint(float u) 
    {
        Point res(0,0);
        for (int i = 0; i < control_points.size(); ++i) 
        {
            float basis = BasisFunction(i, degree, u);
            res.x += control_points[i].first * basis;
            res.y += control_points[i].second * basis;
        }
        return res;
    }
};

void drawLine(int x1, int y1, int x2, int y2, int color)
{
    setcolor(color);
    line(x1, y1, x2, y2);
}

int main()
{
    ifstream infile("F:/Program/CG_HM6/points.txt");
    if (!infile)
    {
        cout << "无法打开文件!" << endl;
        return 1;
    }

    vector<pair<float, float>> control_points; // 存储控制点

    float x, y;
    while (infile >> x >> y)
    {
        control_points.push_back(make_pair(x, y));
    }
    infile.close();

    initgraph(800, 800);

    // 绘制控制多边形
    for (size_t i = 0; i < control_points.size() - 1; ++i)
    {
        drawLine(control_points[i].first, control_points[i].second, control_points[i + 1].first, control_points[i + 1].second, GREEN);
    }

    int degree = 3; // 曲线次数

    BSplineCurve curve(control_points, degree);

    const float step = 0.005; // 步长
    Point p0 = curve.CalculatePoint(0);
    for (float u = 0; u <= 1; u += step)
    {
        Point p1 = curve.CalculatePoint(u);
        if (p0.x != 0 || p0.y != 0)
        {
            drawLine(p0.x, p0.y, p1.x, p1.y, WHITE);
            //cout << p0.x << '\t' << p0.y << endl;
        }
        p0 = p1;

        // 判断是否为最后一个控制点
        if (u + step > 1 && u < 1)
        {
            Point p2 = curve.CalculatePoint(1-0.001);
            drawLine(p1.x, p1.y, p2.x, p2.y, WHITE);
        }
    }

    cout << "按下任意键关闭图形窗口…";
    _getch();
    closegraph();

    return 0;
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值