gismo中NURBS的相关函数的使用---待完善

本文详细介绍了如何使用G+Smo库进行B样条和NURBS的计算,包括节点向量生成、基函数的调用及求值、导数计算,以及控制点坐标处理。同时,讨论了gsVector和gsMatrix的数据输入方法。在计算过程中,强调了节点向量顺序与控制点矩阵的关系,以及gsAsMatrix函数在数据转换中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

只是为方便学习,不做其他用途,参考网址G+Smo的Nurbs module部分

一、B样条的求值

1.1 节点向量的生成

有几个具有类似名称的函数,下表可以帮助你找到适合的函数:

在这里插入图片描述

#include<iostream>
#include <gismo.h>
#include <Eigen/Dense>
using namespace Eigen;
using namespace gismo;
using namespace std;

int main()
{
    // Nurbs module   网址: https://gismo.github.io/group__Nurbs.html
    // 该模块包含b样条和NURBS基函数
    // G+Smo在处理张量积型B样条方面非常强大:
    // 例1:
    // 建立一个二元二次张量积基,并计算了几个点上的基函数  首先,我们需要节点向量:
    gsKnotVector<> kv0(0, 1, 3, 3);    //节点的左端点  右端点  内部节点个数  左/右端点的节点重数   
    gsKnotVector<> kv1(0, 1, 1, 3);    //start,end,interior knots, start/end multiplicites of knots
    // kv0 = { 0,0,0,0.25,0.5,0.75,1,1,1}  内部节点均匀划分
    // kv1 = { 0,0,0,0.5,,1,1,1}

    for (int i = 0; i < kv0.size(); i++)
    {
        cout << " kv0_" << i << " = " << kv0[i] << endl;
    }
}

运行结果:

在这里插入图片描述

1.2 基函数的调用

现在我们有16个基函数,下图显示了它们和我们要求值的点:
在这里插入图片描述

网格中,数字对应格列维尔横坐标的基函数,红点对应评价点。

gsMatrix< unsigned > actRes;

在这里插入图片描述

我们准备6个评估点(0,0)、(0.1,0),(1,0)、(0.5,0.5),(0.6,0.6),(1,1)

gsMatrix< double > uVals(2,6);
uVals << 0,0.1,1,0.5,0.6,1, 0,0,0,0.5,0.6,1;

// 和矩阵的结果

    gsMatrix< unsigned > actRes;
    gsMatrix< double > valRes;

Tipp:请注意,actRes需要一个unsigned矩阵,否则你会得到一个难以理解的错误。在类似的情况下,最好记住这种情况。

现在我们要求评估和打印结果

 tbas.active_into(uVals, actRes);
 tbas.eval_into(uVals, valRes);
 std::cout << "Active functions:\n" << actRes << "\n\nResults of evaluation:\n" << valRes << "\n";
    //  actRes:9*6矩阵    valRes:9*6矩阵 

在这里插入图片描述

从第一个矩阵我们可以读到(0,0)中的活动函数是函数号0、1、2、4、5、6、8、9、10(与图核对)。类似地,第二列显示了活跃在(0.1,0)等中的基函数。
在0-0.5区间 u方向只有前三个基函数影响函数值

在这里插入图片描述

在第二个矩阵中,我们看到了实际的值。第一列告诉我们在(0,0)中只有一个张量基函数在这里等于1。在(0.1,0)中我们有更多的非零基函数;第0个值等于0.64,第1个值等于0.34,第2个值等于0.02,其他值等于0(不用担心,评估点位于它们的支持边界)。有趣的是第四列:我们可以看到在定义域的中间有四个非零函数,它们的下标是5、6、9和10,所有的值都等于0.25。

注: 你可以观察到统一的部分。每列中所有项的和应该等于1。

下面给出一些函数类

  1. gsBSpline< T >:具有任意维数的单参数b样条函数
  2. gsBSplineBasis< T >:单变量b样条基
  3. gsNurbs< T > :一个只有一个参数的NURBS函数,具有任意目标维数
  4. gsNurbsBasis< T > : 单变量NURBS基
  5. gsNurbsCreator: 类gsNurbsCreator提供了Nurbs几何的一些简单示例
  6. gsNurbsCreatorExtended< T > :类gsnurbscreatoreextended提供了对现有gsNurbsCreator类的扩展
  7. gsNurthbs< d, T >:一种目标维数任意,参数维数d的张量积非均匀有理thb样条函数
  8. gsTensorBSpline< d, T >:具有任意目标维数的d个b样条函数的张量积。
  9. gsTensorBSplineBasis< d, T >:张量积b样条基
  10. gsTensorBSplineBasis< 1, T >: 单变量b样条基
  11. gsTensorNurbs< d, T >: 一种目标维数任意,参数维数d的张量积非均匀有理b样条函数
  12. gsTensorNurbsBasis< d, T >: 张量积非均匀有理b样条基。
    在这里插入图片描述

1.3 函数里面的T指的是系数类型

例如:
在这里插入图片描述

T = int 或者 double…(数据类型)

gsKnotVector<> kv0(0, 1, 1, 3);  
gsKnotVector<> kv1(0, 1, 1, 3); 
gsTensorBSplineBasis<2, double> tbas(new gsBSplineBasis< double >(kv0), new gsBSplineBasis< double >(kv1));     

二、输出B样条基函数的值和调用B样条基函数的导数

代码:
#include<iostream>
#include <gismo.h>
#include <Eigen/Dense>
using namespace Eigen;
using namespace gismo;
using namespace std;
#include <vector>
#include "IGA_Plate.h"


int main()
{
	gsKnotVector<> kv1(0, 1, 1, 3);    // kv1 = { 0,0,0,0.5,,1,1,1}    对应生成4个B样条基函数
	int i = 0;
	gsKnotVector<> U = kv1;        // gismo 中生成的向量类型为 gsKnotVector<>
	gsBSplineBasis< double > basis(U);
	gsInfo << "\n basis = \n" << basis << endl;

	cout << "---------分割线1----------" << endl;

	gsKnotVector<> kv(0, 1, 0, 3);
	gsBSplineBasis<double>base(kv);     // 生成单参数B样条基函数
	cout << "kv = " << kv << endl;
	gsMatrix< double > u(1, 1);
	u << 0;

	gsMatrix<double> result = base.evalSingle(0, u);    // 求B样条第一个基函数在u点的值
	cout << "result = " << result << endl;
	gsMatrix<double> val = base.derivSingle(0, u);      // 求B样条第一个基函数在u点的导数值
	double a = val(0, 0);
	cout << "val = " << a << endl;
	gsMatrix<double> va2 = base.derivSingle(1, u);      // 求B样条第2个基函数在u点的导数值
	
	
	cout << "va2 = " << va2 << endl;
	cout << "---------分割线1----------" << endl;

}
结果:

在这里插入图片描述

三、以等几何两个单元12个控制点为例

#include<iostream>
#include <gismo.h>
#include <Eigen/Dense>
using namespace Eigen;
using namespace gismo;
using namespace std;
#include <vector>

// 输出矩阵的各个值
void Print_MatrixXd(MatrixXd K)
{
    for (int j = 0; j < K.rows(); j++)
    {
        for (int i = 0; i < K.cols(); i++)
        {
            cout << K(j, i) << "  ";
        }
        cout << endl;
    }
}

// 输出向量的各个值
void Print_Vector(vector<double> U)
{
    for (int i = 0; i < U.size(); i++)
    {
        cout << " U_ " << i << " = " << U[i] << endl;
    }
}

int main()
{
    // Nurbs module   网址: https://gismo.github.io/group__Nurbs.html
    // 该模块包含b样条和NURBS基函数
    // G+Smo在处理张量积型B样条方面非常强大:
    // 例1:
    // 建立一个二元二次张量积基,并计算了几个点上的基函数  首先,我们需要节点向量:
    gsKnotVector<> kv0(0, 1, 1, 3);    //节点的左端点  右端点  内部节点个数  左/右端点的节点重数   
    gsKnotVector<> kv1(0, 1, 0, 3);    //start,end,interior knots, start/end multiplicites of knots
    // gsKnotVector<> kv0(0, 1, 3, 3);  kv0 = { 0,0,0,0.25,0.5,0.75,1,1,1}  内部节点均匀划分
    // kv1 = { 0,0,0,0.5,,1,1,1}    对应生成4个B样条基函数
    Print_Vector(kv0);

    MatrixXd Node(12, 2);
    Node << 0, 0,
        0, 1,
        0, 2,
        0.5, 0,
        0.5, 1,
        0.5, 2,
        1.5, 0,
        1.5, 1,
        1.5, 2,
        2, 0,
        2, 1,
        2, 2;
    // 生成张量基型Nurbs曲面
    gsTensorNurbs<2, double> nurbs(kv0, kv1, Node);
    // 调用细化函数
    nurbs.uniformRefine();
    
    //  细化后调用节点向量
    vector<double> U = nurbs.knots(0);
    gsInfo << nurbs.knots(1);   // 细化后V方向节点向量
    cout << endl;
    gsInfo << nurbs.knots(0);   // 细化后U方向节点向量
    cout << endl;

    //  细化后调用节点坐标
    cout << "控制点坐标为" << endl;
    gsInfo << nurbs.coefs();

}

输出的控制点坐标有误

gsTensorNurbs<2, double> nurbs(kv0, kv1, Node); 变成gsTensorNurbs<2, double> nurbs(kv1, kv0, Node); 即两个节点向量换一下位置

我感觉和控制点坐标的矩阵输入有关,如果坐标矩阵输入是先v方向一列列输入,则调用函数时需要先输入相同方向(v)的节点向量

#include<iostream>
#include <gismo.h>
#include <Eigen/Dense>
using namespace Eigen;
using namespace gismo;
using namespace std;
#include <vector>

int main()
{
    // Nurbs module   网址: https://gismo.github.io/group__Nurbs.html
    // 该模块包含b样条和NURBS基函数
    // G+Smo在处理张量积型B样条方面非常强大:
    // 例1:
    // 建立一个二元二次张量积基,并计算了几个点上的基函数  首先,我们需要节点向量:
    gsKnotVector<> kv0(0, 1, 1, 3);    //节点的左端点  右端点  内部节点个数  左/右端点的节点重数   
    gsKnotVector<> kv1(0, 1, 0, 3);    //start,end,interior knots, start/end multiplicites of knots

    MatrixXd Node(12, 2);
    Node << 0, 0,
        0, 1,
        0, 2,
        0.5, 0,
        0.5, 1,
        0.5, 2,
        1.5, 0,
        1.5, 1,
        1.5, 2,
        2, 0,
        2, 1,
        2, 2;

    // 生成张量基型Nurbs曲面
    gsTensorNurbs<2, double> nurbs(kv1, kv0, Node);
    // 调用细化函数
    nurbs.uniformRefine();
    
    //  细化后调用节点向量
    vector<double> U = nurbs.knots(0);
    gsInfo << nurbs.knots(1);   // 细化后V方向节点向量
    cout << endl;
    gsInfo << nurbs.knots(0);   // 细化后U方向节点向量
    cout << endl;

    //  细化后调用节点坐标
    cout << "控制点坐标为" << endl;
    gsInfo << nurbs.coefs();

}

结果正确

在这里插入图片描述

在这里插入图片描述

四、gsVector和gsMatrix

4.1 gsVector输入 :vec函数

只能输入2维三维向量

gsVector u3 = gsVector::vec(0, 0.1, 0.3);

vector<double>  nums = { 2,7,8,8,9,10 };

	gsVector<double> u;

	gsVector<double> u3 = gsVector<double>::vec(0, 0.1, 0.3);
	gsInfo << "u3 = \n" << u3 << "\n";

在这里插入图片描述

4.2 gsVector输入 :用gsAsMatrix函数

先输入一个vector,然后用gsAsMatrix将生成的vector转化成向量或者矩阵:

    vector<double>  nums = { 2,7,8,8,9,10 };

	gsVector<double> u;
	u = gsAsMatrix<double>(nums, 5, 1);
	gsInfo << "u = \n" << u << "\n";
	
	gsMatrix<double> u1;
	u1 = gsAsMatrix<double>(nums, 6, 1);
	gsInfo << "u1 = \n" << u1 << "\n";

u = gsAsMatrix(nums, 5, 1):
(nums, 5, 1)表示将nums向量生成 5行1列的向量或者矩阵

4.3 gsMatrix生成

用gsAsMatrix函数生成:

    vector<double>  nums = { 2,7,8,8,9,10 };
    
	gsMatrix<double> u1;
	u1 = gsAsMatrix<double>(nums, 6, 1);
	gsInfo << "u1 = \n" << u1 << "\n";

	gsMatrix<double> u2;
	u2 = gsAsMatrix<double>(nums, 2, 3);
	gsInfo << "u2 = \n" << u2 << "\n";

4.4 汇总

#include <gismo.h>
#include <vector>

using std::vector;
using namespace gismo;

int main(int argc, char* argv[]) {

	
	vector<double>  nums = { 2,7,8,8,9,10 };

	gsVector<double> u;
	u = gsAsMatrix<double>(nums, 5, 1);
	gsInfo << "u = \n" << u << "\n";

	gsMatrix<double> u1;
	u1 = gsAsMatrix<double>(nums, 5, 1);
	gsInfo << "u1 = \n" << u1 << "\n";

	gsMatrix<double> u2;
	u2 = gsAsMatrix<double>(nums, 2, 3);
	gsInfo << "u2 = \n" << u2 << "\n";

	gsVector<double> u3 = gsVector<double>::vec(0, 0.1, 0.3);
	gsInfo << "u3 = \n" << u3 << "\n";

	return 0;
}

在这里插入图片描述

结果;

u =
2
7
8
8
9
u1 =
2
7
8
8
9
u2 =
 2  8  9
 7  8 10
u3 =
  0
0.1
0.3

三、

3.1

3.2

3.3

3.4

四、

4.1

4.2

4.3

4.4

总结

二维数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值