📄 tobezier.cc
字号:
}
}
/*-----------------------------------------------------------------------------
* Knotspec::showpts - print out points before transformation
*
* Client: Knotspec::select
*-----------------------------------------------------------------------------
*/
void
Knotspec::showpts( REAL *outpt )
{
if( next ) {
for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride )
next->showpts( outpt );
} else {
for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride )
dprintf( "show %g %g %g\n", outpt[0], outpt[1], outpt[2] );
}
}
/*-----------------------------------------------------------------------------
* Knotspec::factors - precompute scale factors
* - overwrites knot vector, actual new knot vector is NOT produced
*
* Client: Knotspec::select
*-----------------------------------------------------------------------------
*/
void
Knotspec::factors( void )
{
Knot *mid = (outkend - 1) - order + bend->multi;
Knot_ptr fptr = sbegin;
for( Breakpt *bpt = bend; bpt >= bbegin; bpt-- ) {
mid -= bpt->multi; // last knot less than knot to insert
int def = bpt->def - 1; // number of knots to insert
if( def <= 0 ) continue;
Knot kv = bpt->value; // knot to insert
Knot *kf = (mid-def) + (order-1);
for( Knot *kl = kf + def; kl != kf; kl-- ) {
Knot *kh, *kt;
for( kt=kl, kh=mid; kt != kf; kh--, kt-- )
*(fptr++) = (kv - *kh) / (*kt - *kh);
*kl = kv;
}
}
}
/*-----------------------------------------------------------------------------
* Knotspec::insert - convert subobject in direction of kspec into Bezier
*
* Client: Knotspec::transform
*-----------------------------------------------------------------------------
*/
void
Knotspec::insert( REAL *p )
{
Knot_ptr fptr = sbegin;
REAL *srcpt = p + prewidth - poststride;
REAL *dstpt = p + postwidth + postoffset - poststride;
Breakpt *bpt = bend;
for( REAL *pend = srcpt - poststride*bpt->def; srcpt != pend; pend +=poststride ) {
REAL *p1 = srcpt;
for( REAL *p2 = srcpt-poststride; p2 != pend; p1 = p2, p2 -= poststride ) {
pt_oo_sum( p1, p1, p2, *fptr, 1.0-*fptr );
fptr++;
}
}
for( --bpt; bpt >= bbegin; bpt-- ) {
for( int multi = bpt->multi; multi > 0; multi-- ) {
pt_oo_copy( dstpt, srcpt );
dstpt -= poststride;
srcpt -= poststride;
}
for( REAL *pend = srcpt - poststride*bpt->def; srcpt != pend; pend +=poststride, dstpt-=poststride ) {
pt_oo_copy( dstpt, srcpt );
REAL *p1 = srcpt;
for( REAL *p2 = srcpt-poststride; p2 != pend; p1=p2, p2 -= poststride ) {
pt_oo_sum( p1, p1, p2, *fptr, 1.0-*fptr );
fptr++;
}
}
}
}
/*-----------------------------------------------------------------------------
* Knotspec::preselect - initialize kspec for processing
*
* Client: Splinespec::select
*-----------------------------------------------------------------------------
*/
void
Knotspec::preselect( void )
{
Knot kval;
/* position klast after last knot of "last" breakpoint */
for( klast = inkend - order, kval = *klast; klast != inkend; klast++ )
if( ! identical( *klast, kval ) ) break;
/* position kfirst after last knot of "first" breakpoint */
for( kfirst = inkbegin+order-1, kval= *kfirst; kfirst != inkend; kfirst++ )
if( ! identical( *kfirst, kval ) ) break;
/* compute multiplicity of first breakpoint */
Knot_ptr k;
for( k = kfirst - 1; k >= inkbegin; k-- )
if( ! identical( kval, *k ) ) break;
k++;
/* allocate space for breakpoints -
use worst case estimate on number of breakpoints */
bbegin = new Breakpt[(klast - kfirst)+1];
/* record multiplicity and value of first breakpoint */
bbegin->multi = kfirst - k;
bbegin->value = kval;
bend = bbegin;
kleft = kright = kfirst;
}
/*-----------------------------------------------------------------------------
* Knotspec::select - Knotspec::select segments and precompute scale factors
*
* Client: Splinespec::select
*-----------------------------------------------------------------------------
*/
void
Knotspec::select( void )
{
breakpoints();
knots();
factors();
preoffset = kleft - (inkbegin + order);
postwidth = (int)((bend - bbegin) * order);
prewidth = (int)((outkend - outkbegin) - order);
postoffset = (bbegin->def > 1) ? (bbegin->def-1) : 0;
}
/*-----------------------------------------------------------------------------
* Knotspec::breakpoints - compute breakpoints for knotspec
*
* Client: Knotspec::select
*-----------------------------------------------------------------------------
*/
void
Knotspec::breakpoints( void )
{
Breakpt *ubpt = bbegin;
Breakpt *ubend = bend;
long nfactors = 0;
ubpt->value = ubend->value;
ubpt->multi = ubend->multi;
kleft = kright;
for( ; kright != klast; kright++ ) {
if ( identical(*kright,ubpt->value) ) {
(ubpt->multi)++;
} else {
ubpt->def = (int) (order - ubpt->multi);
nfactors += (ubpt->def * (ubpt->def - 1)) / 2;
(++ubpt)->value = *kright;
ubpt->multi = 1;
}
}
ubpt->def = (int) (order - ubpt->multi);
nfactors += (ubpt->def * (ubpt->def - 1)) / 2;
bend = ubpt;
if( nfactors ) {
sbegin = new Knot[nfactors];
} else {
sbegin = NULL;
}
}
/*-----------------------------------------------------------------------------
* Knotspec::knots - copy relevant subsequence of knots into temporary area
*
* Client: Knotspec::select
*-----------------------------------------------------------------------------
*/
void
Knotspec::knots( void )
{
Knot_ptr inkpt = kleft - order;
Knot_ptr inkend = kright + bend->def;
/* allocate space for knots and factors */
outkbegin = new Knot[inkend-inkpt];
Knot_ptr outkpt;
for( outkpt = outkbegin; inkpt != inkend; inkpt++, outkpt++ )
*outkpt = *inkpt;
outkend = outkpt;
}
/*-----------------------------------------------------------------------------
* Knotspec::transform - convert a spline along a given direction
*
* Client: Splienspec::transform
*-----------------------------------------------------------------------------
*/
void
Knotspec::transform( REAL *p )
{
if( next ) {
if( this == kspectotrans ) {
next->transform( p );
} else {
if( istransformed ) {
p += postoffset;
for( REAL *pend = p + postwidth; p != pend; p += poststride )
next->transform( p );
} else {
REAL *pend = p + prewidth;
for( ; p != pend; p += poststride )
next->transform( p );
}
}
} else {
if( this == kspectotrans ) {
insert( p );
} else {
if( istransformed ) {
p += postoffset;
for( REAL *pend = p + postwidth; p != pend; p += poststride )
kspectotrans->insert( p );
} else {
REAL *pend = p + prewidth;
for( ; p != pend; p += poststride )
kspectotrans->insert( p );
}
}
}
}
/*-----------------------------------------------------------------------------
* Knotspec::~Knotspec - free space alocated for knotspec
*-----------------------------------------------------------------------------
*/
Knotspec::~Knotspec( void )
{
if( bbegin ) delete[] bbegin;
if( sbegin ) delete[] sbegin;
if( outkbegin ) delete[] outkbegin;
}
/*-----------------------------------------------------------------------------
* pt_io_copy - make internal copy of input cntrl pt. of x coords
*-----------------------------------------------------------------------------
*/
void
Knotspec::pt_io_copy( REAL *topt, INREAL *frompt )
{
switch( ncoords ) {
case 4:
topt[3] = (REAL) frompt[3];
case 3:
topt[2] = (REAL) frompt[2];
case 2:
topt[1] = (REAL) frompt[1];
case 1:
topt[0] = (REAL) frompt[0];
break;
default: {
for( int i = 0; i < ncoords; i++ )
*topt++ = (REAL) *frompt++;
}
}
}
/*-----------------------------------------------------------------------------
* pt_oo_copy - make internal copy of internal cntrl pt. of x coords
*-----------------------------------------------------------------------------
*/
void
Knotspec::pt_oo_copy( REAL *topt, REAL *frompt )
{
switch( ncoords ) {
case 4:
topt[3] = frompt[3];
case 3:
topt[2] = frompt[2];
case 2:
topt[1] = frompt[1];
case 1:
topt[0] = frompt[0];
break;
default:
memcpy( topt, frompt, ncoords * sizeof( REAL ) );
}
}
/*-----------------------------------------------------------------------------
* pt_oo_sum - compute affine combination of internal cntrl pts
*-----------------------------------------------------------------------------
*/
void
Knotspec::pt_oo_sum( REAL *x, REAL *y, REAL *z, Knot a, Knot b )
{
switch( ncoords ) {
case 4:
x[3] = a * y[3] + b * z[3];
case 3:
x[2] = a * y[2] + b * z[2];
case 2:
x[1] = a * y[1] + b * z[1];
case 1:
x[0] = a * y[0] + b * z[0];
break;
default: {
for( int i = 0; i < ncoords; i++ )
*x++ = a * *y++ + b * *z++;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -