многовариантный эрмитовый сплайн

Я знаю как это сделать бикубический патч от 16 контрольных точек (то есть сетка 4×4), как B-сплайн, Catmull – Rom, Besier …

Тем не менее, я хотел бы что-то вроде 2D / 3D аналогии Эрмитовый сплайн описывается 4 контрольными точками (p00,p01,p10,p11) и 4 нормали (n00,n01,n10,n11в этот момент.

Я пытался его запрограммировать (сначала делал 2х 1D интерполяцию по u и чем интерполировать результат вдоль v ).

Я застрял, когда понял, что не знаю, как использовать поверхностные нормали вместо производных, используемых в одномерном сплайне Эрмита.

Если я наивно просто включаю нормали вместо производных, я получаю бессмысленные результаты. Смотрите код C ++ здесь (я взял только соответствующие части):

// 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;
}

1

Решение

То, что вы хотите, это поверхность бикубического Эрмита, которая определяется 4 угловыми точками и dS / du, dS / dv и d2S / dudv в каждой угловой точке, где dS / du и dS / dv являются частной производной в направлении u и v и d2S / dudv — вектор кручения. Вы можете обратиться к link1 а также link2 для более подробной информации.

Наличие четырех угловых точек и четырех нормальных векторов недостаточно для однозначного определения бикубической поверхности. Однако вы можете вывести dS / du и dS / dv из векторов нормалей и 4 угловых точек. Разумеется, формула логического вывода должна обеспечить, чтобы вектор перекрестных произведений между dS / du и dS / dv находился в том же направлении, что и вектор нормали. Для вектора кручения d2S / dudv вы можете использовать нулевой вектор.

0

Другие решения


По вопросам рекламы [email protected]