C++ 多变量hermite样条

C++ 多变量hermite样条,c++,3d,interpolation,spline,hermite,C++,3d,Interpolation,Spline,Hermite,我知道如何做从(即4x4网格)像B样条曲线,卡特穆尔-Rom,贝塞尔 然而,我更希望类似2D/3D的类比由4个控制点(p00、p01、p10、p11)和4个法线(n00、n01、n10、n11)在该点进行描述 我试着编程(首先沿u进行2x1d插值,然后沿v插值结果) 当我意识到我不知道如何使用曲面法线来代替1D Hermite样条曲线中使用的导数时,我陷入了困境 如果我天真地只插入法线而不是导数,我会得到无意义的结果。在这里看到C++代码(我只使用相关部分): //基函数 模板 内联空心样条曲线

我知道如何做从(即4x4网格)像B样条曲线,卡特穆尔-Rom,贝塞尔

然而,我更希望类似2D/3D的类比由4个控制点(
p00、p01、p10、p11
)和4个法线(
n00、n01、n10、n11
)在该点进行描述

我试着编程(首先沿
u
进行2x1d插值,然后沿
v
插值结果)

当我意识到我不知道如何使用曲面法线来代替1D Hermite样条曲线中使用的导数时,我陷入了困境

如果我天真地只插入法线而不是导数,我会得到无意义的结果。在这里看到C++代码(我只使用相关部分):

//基函数
模板
内联空心样条曲线\u hermite\u基准(x型、c0型、c1型、d0型、d1型){
x2型=x*x;
x3型=x*x2;
c0=2*x3-3*x2+1;
c1=-2*x3+3*x2;
d0=x3-2*x2+x;
d1=x3-x2;
};
//基函数的导数
模板
内联空心样条线(x型、c0型、c1型、d0型、d1型){
x2型=x*x;
c0=6*x2-6*x;
c1=-6*x2+6*x;
d0=3*x2-4*x+1;
d1=3*x2-2*x;
};
无效立方体匹配点(双u、双v、,
const Vec3d和p00,const Vec3d和p01,const Vec3d和p10,const Vec3d和p11,
const Vec3d&n00、const Vec3d&n01、const Vec3d&n10、const Vec3d&n11、,
Vec3d&p、Vec3d&n
){
双cc0,cc1,cd0,cd1;
双dc0,dc1,dd0,dd1;
//沿u轴插值
样条hermite基(u,cc0,cc1,cd0,cd1);
dspline_hermite_基(u,dc0,dc1,dd0,dd1);
Vec3d p0u、p1u、n0u、n1u;
p0u.set_mul(p00,cc0);p0u.add_mul(p01,cc1);p0u.add_mul(n00,cd0);p0u.add_mul(n01,cd1);//p0u=cc0*p00+cc1*p01+cd0*n00+cd1*n01;
n0u.set_mul(p00,dc0);n0u.add_mul(p01,dc1);n0u.add_mul(n00,dd0);n0u.add_mul(n01,dd1);//n0u=dc0*p00+dc1*p01+dd0*n00+dd1*n01;
p1u.set_mul(p10,cc0);p1u.add_mul(p11,cc1);p1u.add_mul(n10,cd0);p1u.add_mul(n11,cd1);//p1u=cc0*p10+cc1*p11+cd0*n10+cd1*n11;
n1u.set_mul(p10,dc0);n1u.add_mul(p11,dc1);n1u.add_mul(n10,dd0);n1u.add_mul(n11,dd1);//n1u=dc0*p10+dc1*p11+dd0*n10+dd1*n11;
//沿v的插值
样条hermite基(v,cc0,cc1,cd0,cd1);
dspline_hermite_基(v,dc0,dc1,dd0,dd1);
p、 设置_mul(p0u,cc0);p.add_mul(p1u,cc1);p.add_mul(n0u,cd0);p.add_mul(n1u,cd1);//p=cc0*p0u+cc1*p1u+cd0*n0u+cd1*n1u;
n、 设置多个(p0u,dc0);n.add多个(p1u,dc1);n.add多个(n0u,dd0);n.add多个(n1u,dd1);//n=dc0*p0u+dc1*p1u+dd0*n0u+dd1*n1u;
}   

您想要的是双三次Hermite曲面,它由4个角点和每个角点处的dS/du、dS/dv和d2S/dudv定义,其中dS/du和dS/dv是u和v方向上的偏导数,d2S/dudv是扭曲向量。有关更多详细信息,请参阅和


仅具有4个角点和4个法向量不足以唯一定义双三次曲面。但是,可以从法向量和4个角点推断dS/du和dS/dv。当然,推断公式需要确保dS/du和dS/dv之间的叉积向量与法向量方向相同。对于扭曲向量d2S/dudv,可以使用零向量。

谢谢。与此同时,我发现这可能是问题所在(点和法线根本没有足够的自由度)。我有点失望,因为要扩展到更高的维度,任何三次插值都需要内存中4^N的数字,而不是2*(2^N)。。。如果我在trinagle(单纯形)而不是矩形上进行插值,会有什么变化吗?我的意思是:如果在trinagle上有类似hermite样条的东西,或者如果在三角形网格上有一个二维插值,并且有连续的导数,你只提供点和法线?
// basis function
template <class TYPE>  
inline void spline_hermite_basis( TYPE x, TYPE& c0, TYPE& c1, TYPE& d0, TYPE& d1 ){
    TYPE x2   = x*x;
    TYPE x3   = x*x2;
    c0        =  2*x3 - 3*x2 + 1;
    c1        = -2*x3 + 3*x2    ;
    d0        =    x3 - 2*x2 + x; 
    d1        =    x3 -   x2    ;
};

// derivative of basis functions
template <class TYPE>  
inline void dspline_hermite_basis( TYPE x, TYPE& c0, TYPE& c1, TYPE& d0, TYPE& d1 ){
    TYPE x2   = x*x;
    c0        =   6*x2 - 6*x    ;
    c1        =  -6*x2 + 6*x    ;
    d0        =   3*x2 - 4*x + 1; 
    d1        =   3*x2 - 2*x    ;
};

void cubicPatch_point( double u, double v, 
    const Vec3d& p00, const Vec3d& p01, const Vec3d& p10, const Vec3d& p11,  
    const Vec3d& n00, const Vec3d& n01, const Vec3d& n10, const Vec3d& n11, 
    Vec3d& p, Vec3d& n  
){
    double cc0,cc1,cd0,cd1;
    double dc0,dc1,dd0,dd1;
    // interpolation along u
     spline_hermite_basis<double>( u,  cc0, cc1, cd0, cd1 );
    dspline_hermite_basis<double>( u,  dc0, dc1, dd0, dd1 );
    Vec3d p0u,p1u,n0u,n1u;
    p0u.set_mul( p00, cc0 ); p0u.add_mul( p01, cc1 ); p0u.add_mul( n00, cd0 ); p0u.add_mul( n01, cd1 );   // p0u =  cc0*p00 + cc1*p01 + cd0*n00 + cd1*n01; 
    n0u.set_mul( p00, dc0 ); n0u.add_mul( p01, dc1 ); n0u.add_mul( n00, dd0 ); n0u.add_mul( n01, dd1 );   // n0u =  dc0*p00 + dc1*p01 + dd0*n00 + dd1*n01; 
    p1u.set_mul( p10, cc0 ); p1u.add_mul( p11, cc1 ); p1u.add_mul( n10, cd0 ); p1u.add_mul( n11, cd1 );   // p1u =  cc0*p10 + cc1*p11 + cd0*n10 + cd1*n11; 
    n1u.set_mul( p10, dc0 ); n1u.add_mul( p11, dc1 ); n1u.add_mul( n10, dd0 ); n1u.add_mul( n11, dd1 );   // n1u =  dc0*p10 + dc1*p11 + dd0*n10 + dd1*n11; 
    // interpolation along v
     spline_hermite_basis<double>( v,  cc0, cc1, cd0, cd1 );
    dspline_hermite_basis<double>( v,  dc0, dc1, dd0, dd1 );
    p.set_mul( p0u, cc0 );  p.add_mul( p1u, cc1 );  p.add_mul( n0u, cd0 );  p.add_mul( n1u, cd1 );        // p =  cc0*p0u + cc1*p1u + cd0*n0u + cd1*n1u; 
    n.set_mul( p0u, dc0 );  n.add_mul( p1u, dc1 );  n.add_mul( n0u, dd0 );  n.add_mul( n1u, dd1 );        // n =  dc0*p0u + dc1*p1u + dd0*n0u + dd1*n1u; 
}