文章目录
前言
只是为方便学习,不做其他用途,参考网址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。
下面给出一些函数类
- gsBSpline< T >:具有任意维数的单参数b样条函数
- gsBSplineBasis< T >:单变量b样条基
- gsNurbs< T > :一个只有一个参数的NURBS函数,具有任意目标维数
- gsNurbsBasis< T > : 单变量NURBS基
- gsNurbsCreator: 类gsNurbsCreator提供了Nurbs几何的一些简单示例
- gsNurbsCreatorExtended< T > :类gsnurbscreatoreextended提供了对现有gsNurbsCreator类的扩展
- gsNurthbs< d, T >:一种目标维数任意,参数维数d的张量积非均匀有理thb样条函数
- gsTensorBSpline< d, T >:具有任意目标维数的d个b样条函数的张量积。
- gsTensorBSplineBasis< d, T >:张量积b样条基
- gsTensorBSplineBasis< 1, T >: 单变量b样条基
- gsTensorNurbs< d, T >: 一种目标维数任意,参数维数d的张量积非均匀有理b样条函数
- 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
:
总结
:
二维数 |