tobezier.cc revision f220fa62
1f220fa62Smrg/* 2f220fa62Smrg** License Applicability. Except to the extent portions of this file are 3f220fa62Smrg** made subject to an alternative license as permitted in the SGI Free 4f220fa62Smrg** Software License B, Version 1.1 (the "License"), the contents of this 5f220fa62Smrg** file are subject only to the provisions of the License. You may not use 6f220fa62Smrg** this file except in compliance with the License. You may obtain a copy 7f220fa62Smrg** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 8f220fa62Smrg** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: 9f220fa62Smrg** 10f220fa62Smrg** http://oss.sgi.com/projects/FreeB 11f220fa62Smrg** 12f220fa62Smrg** Note that, as provided in the License, the Software is distributed on an 13f220fa62Smrg** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS 14f220fa62Smrg** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND 15f220fa62Smrg** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A 16f220fa62Smrg** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. 17f220fa62Smrg** 18f220fa62Smrg** Original Code. The Original Code is: OpenGL Sample Implementation, 19f220fa62Smrg** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, 20f220fa62Smrg** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. 21f220fa62Smrg** Copyright in any portions created by third parties is as indicated 22f220fa62Smrg** elsewhere herein. All Rights Reserved. 23f220fa62Smrg** 24f220fa62Smrg** Additional Notice Provisions: The application programming interfaces 25f220fa62Smrg** established by SGI in conjunction with the Original Code are The 26f220fa62Smrg** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released 27f220fa62Smrg** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version 28f220fa62Smrg** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X 29f220fa62Smrg** Window System(R) (Version 1.3), released October 19, 1998. This software 30f220fa62Smrg** was created using the OpenGL(R) version 1.2.1 Sample Implementation 31f220fa62Smrg** published by SGI, but has not been independently verified as being 32f220fa62Smrg** compliant with the OpenGL(R) version 1.2.1 Specification. 33f220fa62Smrg*/ 34f220fa62Smrg 35f220fa62Smrg/* 36f220fa62Smrg * tobezier.c++ 37f220fa62Smrg * 38f220fa62Smrg */ 39f220fa62Smrg 40f220fa62Smrg#include "glimports.h" 41f220fa62Smrg#include "myassert.h" 42f220fa62Smrg#include "mystdio.h" 43f220fa62Smrg#include "mystring.h" 44f220fa62Smrg#include "quilt.h" 45f220fa62Smrg#include "knotvector.h" 46f220fa62Smrg 47f220fa62Smrg/* local type definitions */ 48f220fa62Smrgstruct Breakpt { /* breakpoints */ 49f220fa62Smrg Knot value; /* value */ 50f220fa62Smrg int multi; /* multiplicity */ 51f220fa62Smrg int def; /* deficit */ 52f220fa62Smrg}; 53f220fa62Smrg 54f220fa62Smrgstruct Knotspec { /* knotvector format */ 55f220fa62Smrg long order; /* order of spline */ 56f220fa62Smrg Knot_ptr inkbegin; /* input knot sequence */ 57f220fa62Smrg Knot_ptr inkend; /* location after last knot */ 58f220fa62Smrg Knot_ptr outkbegin; /* in-process knot subsequence */ 59f220fa62Smrg Knot_ptr outkend; /* location after last knot */ 60f220fa62Smrg Knot_ptr kleft; /* */ 61f220fa62Smrg Knot_ptr kright; /* */ 62f220fa62Smrg Knot_ptr kfirst; /* */ 63f220fa62Smrg Knot_ptr klast; /* */ 64f220fa62Smrg Knot_ptr sbegin; /* conversion factor values */ 65f220fa62Smrg Breakpt * bbegin; /* in-process breakpoints */ 66f220fa62Smrg Breakpt * bend; /* last breakpoint */ 67f220fa62Smrg int ncoords; /* coordinates per control point */ 68f220fa62Smrg int prestride; /* stride between input points */ 69f220fa62Smrg int poststride; /* stride between output points */ 70f220fa62Smrg int preoffset; /* scaled point offset */ 71f220fa62Smrg int postoffset; /* scaled point offset */ 72f220fa62Smrg int prewidth; /* width of dimension */ 73f220fa62Smrg int postwidth; /* width of dimension */ 74f220fa62Smrg int istransformed; /* was dimension transformed */ 75f220fa62Smrg Knotspec * next; /* next knotspec */ 76f220fa62Smrg Knotspec * kspectotrans; /* knotspec in transformation direction */ 77f220fa62Smrg 78f220fa62Smrg Knotspec( void ); 79f220fa62Smrg ~Knotspec( void ); 80f220fa62Smrg void factors( void ); 81f220fa62Smrg void insert( REAL * ); 82f220fa62Smrg void preselect(); 83f220fa62Smrg void select( void ); 84f220fa62Smrg void copy( INREAL *, REAL * ); 85f220fa62Smrg void breakpoints( void ); 86f220fa62Smrg void knots( void ); 87f220fa62Smrg void transform( REAL * ); 88f220fa62Smrg void showpts( REAL * ); 89f220fa62Smrg 90f220fa62Smrg void pt_io_copy( REAL *, INREAL * ); 91f220fa62Smrg void pt_oo_copy( REAL *, REAL * ); 92f220fa62Smrg void pt_oo_sum( REAL*, REAL*, REAL*, Knot, Knot ); 93f220fa62Smrg}; 94f220fa62Smrg 95f220fa62Smrgstruct Splinespec { /* a non-uniform tensor element */ 96f220fa62Smrg Splinespec( int ); 97f220fa62Smrg ~Splinespec(void); 98f220fa62Smrg Knotspec *kspec; /* format of each param. dir. */ 99f220fa62Smrg int dim; /* domain dimension */ 100f220fa62Smrg REAL * outcpts; /* Bezier control points */ 101f220fa62Smrg 102f220fa62Smrg void kspecinit( Knotvector & ); 103f220fa62Smrg void kspecinit( Knotvector &, Knotvector & ); 104f220fa62Smrg void select( void ); 105f220fa62Smrg void layout( long ); 106f220fa62Smrg void setupquilt( Quilt_ptr ); 107f220fa62Smrg void copy( INREAL * ); 108f220fa62Smrg void transform( void ); 109f220fa62Smrg}; 110f220fa62Smrg 111f220fa62Smrg/*----------------------------------------------------------------------------- 112f220fa62Smrg * Quilt::toBezier - convert from NURBS to rational Bezier 113f220fa62Smrg *----------------------------------------------------------------------------- 114f220fa62Smrg */ 115f220fa62Smrg 116f220fa62Smrgvoid 117f220fa62SmrgQuilt::toBezier( 118f220fa62Smrg Knotvector& knotvector, /* a knot vector */ 119f220fa62Smrg INREAL *ctlpts, /* input contol points */ 120f220fa62Smrg long ncoords ) /* number of coordinates per control point */ 121f220fa62Smrg{ 122f220fa62Smrg Splinespec spline( 1 ); 123f220fa62Smrg spline.kspecinit( knotvector ); 124f220fa62Smrg spline.select(); 125f220fa62Smrg spline.layout( ncoords ); 126f220fa62Smrg spline.setupquilt( this ); 127f220fa62Smrg spline.copy( ctlpts ); 128f220fa62Smrg spline.transform(); 129f220fa62Smrg} 130f220fa62Smrg 131f220fa62Smrgvoid 132f220fa62SmrgQuilt::toBezier( 133f220fa62Smrg Knotvector& sknotvector, /* a knot vector */ 134f220fa62Smrg Knotvector& tknotvector, /* a knot vector */ 135f220fa62Smrg INREAL *ctlpts, /* input contol points */ 136f220fa62Smrg long ncoords ) /* number of coordinates per control point */ 137f220fa62Smrg{ 138f220fa62Smrg Splinespec spline( 2 ); 139f220fa62Smrg spline.kspecinit( sknotvector, tknotvector ); 140f220fa62Smrg spline.select(); 141f220fa62Smrg spline.layout( ncoords ); 142f220fa62Smrg spline.setupquilt( this ); 143f220fa62Smrg spline.copy( ctlpts ); 144f220fa62Smrg spline.transform(); 145f220fa62Smrg} 146f220fa62SmrgSplinespec::Splinespec( int dimen ) 147f220fa62Smrg{ 148f220fa62Smrg dim = dimen; 149f220fa62Smrg} 150f220fa62Smrg 151f220fa62SmrgSplinespec::~Splinespec( void ) 152f220fa62Smrg{ 153f220fa62Smrg /* Note: do NOT delete 'outcpts' here since its address (not contents) 154f220fa62Smrg * is copied in 'cpts' in this file in function Splinespec::setupquilt(). 155f220fa62Smrg * This block of memory will eventually be deleted in file quilt.c++ in 156f220fa62Smrg * function Quilt::deleteMe() through 'cpts' so do NOT delete it here! 157f220fa62Smrg */ 158f220fa62Smrg Knotspec *ktrav= kspec; //start at beginning of list 159f220fa62Smrg while (ktrav != 0) { //any items to delete? 160f220fa62Smrg Knotspec *deleteThis= ktrav; //remember to delete this 161f220fa62Smrg ktrav= ktrav->next; //go to next item if any 162f220fa62Smrg delete deleteThis; //delete it 163f220fa62Smrg } 164f220fa62Smrg} /* ~Splinespec() */ 165f220fa62Smrg 166f220fa62Smrg/*----------------------------------------------------------------------------- 167f220fa62Smrg * Splinespec::kspecinit - initialize Splinespec structure 168f220fa62Smrg * 169f220fa62Smrg * Client: Quilt::toBezier 170f220fa62Smrg *----------------------------------------------------------------------------- 171f220fa62Smrg */ 172f220fa62Smrg 173f220fa62Smrgvoid 174f220fa62SmrgSplinespec::kspecinit( Knotvector& knotvector ) 175f220fa62Smrg{ 176f220fa62Smrg kspec = new Knotspec; 177f220fa62Smrg kspec->inkbegin = knotvector.knotlist; 178f220fa62Smrg kspec->inkend = knotvector.knotlist + knotvector.knotcount; 179f220fa62Smrg kspec->prestride = (int) knotvector.stride; 180f220fa62Smrg kspec->order = knotvector.order; 181f220fa62Smrg kspec->next = NULL; 182f220fa62Smrg} 183f220fa62Smrg 184f220fa62Smrgvoid 185f220fa62SmrgSplinespec::kspecinit( Knotvector& sknotvector, Knotvector& tknotvector ) 186f220fa62Smrg{ 187f220fa62Smrg kspec = new Knotspec; 188f220fa62Smrg Knotspec *tkspec = new Knotspec; 189f220fa62Smrg 190f220fa62Smrg kspec->inkbegin = sknotvector.knotlist; 191f220fa62Smrg kspec->inkend = sknotvector.knotlist + sknotvector.knotcount; 192f220fa62Smrg kspec->prestride = (int) sknotvector.stride; 193f220fa62Smrg kspec->order = sknotvector.order; 194f220fa62Smrg kspec->next = tkspec; 195f220fa62Smrg 196f220fa62Smrg tkspec->inkbegin = tknotvector.knotlist; 197f220fa62Smrg tkspec->inkend = tknotvector.knotlist + tknotvector.knotcount; 198f220fa62Smrg tkspec->prestride = (int) tknotvector.stride; 199f220fa62Smrg tkspec->order = tknotvector.order; 200f220fa62Smrg tkspec->next = NULL; 201f220fa62Smrg} 202f220fa62Smrg 203f220fa62Smrg 204f220fa62Smrg/*----------------------------------------------------------------------------- 205f220fa62Smrg * Splinespec::select - select the subsegments to copy 206f220fa62Smrg * 207f220fa62Smrg * Client: gl_quilt_to_bezier 208f220fa62Smrg *----------------------------------------------------------------------------- 209f220fa62Smrg */ 210f220fa62Smrg 211f220fa62Smrgvoid 212f220fa62SmrgSplinespec::select( ) 213f220fa62Smrg{ 214f220fa62Smrg for( Knotspec *knotspec = kspec; knotspec; knotspec = knotspec->next ) { 215f220fa62Smrg knotspec->preselect(); 216f220fa62Smrg knotspec->select(); 217f220fa62Smrg } 218f220fa62Smrg} 219f220fa62Smrg 220f220fa62Smrg/*----------------------------------------------------------------------------- 221f220fa62Smrg * Splinespec::layout - 222f220fa62Smrg * 223f220fa62Smrg * Client: gl_quilt_to_bezier 224f220fa62Smrg *----------------------------------------------------------------------------- 225f220fa62Smrg */ 226f220fa62Smrg 227f220fa62Smrgvoid 228f220fa62SmrgSplinespec::layout( long ncoords ) 229f220fa62Smrg{ 230f220fa62Smrg 231f220fa62Smrg long stride = ncoords; 232f220fa62Smrg for( Knotspec *knotspec = kspec; knotspec; knotspec=knotspec->next ) { 233f220fa62Smrg knotspec->poststride = (int) stride; 234f220fa62Smrg stride *= ((knotspec->bend-knotspec->bbegin)*knotspec->order + knotspec->postoffset); 235f220fa62Smrg knotspec->preoffset *= knotspec->prestride; 236f220fa62Smrg knotspec->prewidth *= knotspec->poststride; 237f220fa62Smrg knotspec->postwidth *= knotspec->poststride; 238f220fa62Smrg knotspec->postoffset *= knotspec->poststride; 239f220fa62Smrg knotspec->ncoords = (int) ncoords; 240f220fa62Smrg } 241f220fa62Smrg outcpts = new REAL[stride]; 242f220fa62Smrg assert( outcpts != 0 ); 243f220fa62Smrg} 244f220fa62Smrg 245f220fa62Smrg/*----------------------------------------------------------------------------- 246f220fa62Smrg * Splinespec::copy - copy the control points of current subobject 247f220fa62Smrg * 248f220fa62Smrg * Client: gl_quilt_to_bezier 249f220fa62Smrg *----------------------------------------------------------------------------- 250f220fa62Smrg */ 251f220fa62Smrg 252f220fa62Smrgvoid 253f220fa62SmrgSplinespec::copy( INREAL *incpts ) 254f220fa62Smrg{ 255f220fa62Smrg kspec->copy( incpts, outcpts ); 256f220fa62Smrg} 257f220fa62Smrg 258f220fa62Smrg/*----------------------------------------------------------------------------- 259f220fa62Smrg * Splinespec::setupquilt - assign all quilt variables from knotspec 260f220fa62Smrg * 261f220fa62Smrg * Client: gl_quilt_to_bezier 262f220fa62Smrg *----------------------------------------------------------------------------- 263f220fa62Smrg */ 264f220fa62Smrg 265f220fa62Smrgvoid 266f220fa62SmrgSplinespec::setupquilt( Quilt_ptr quilt ) 267f220fa62Smrg{ 268f220fa62Smrg Quiltspec_ptr qspec = quilt->qspec; 269f220fa62Smrg quilt->eqspec = qspec + dim; 270f220fa62Smrg for( Knotspec *knotspec = kspec; knotspec; knotspec=knotspec->next, qspec++ ) { 271f220fa62Smrg qspec->stride = knotspec->poststride; 272f220fa62Smrg qspec->width = knotspec->bend - knotspec->bbegin; 273f220fa62Smrg qspec->order = (int) knotspec->order; 274f220fa62Smrg qspec->offset = knotspec->postoffset; 275f220fa62Smrg qspec->index = 0; 276f220fa62Smrg qspec->bdry[0] = (knotspec->kleft == knotspec->kfirst) ? 1 : 0; 277f220fa62Smrg qspec->bdry[1] = (knotspec->kright == knotspec->klast) ? 1 : 0; 278f220fa62Smrg qspec->breakpoints = new Knot[qspec->width+1]; 279f220fa62Smrg Knot_ptr k = qspec->breakpoints; 280f220fa62Smrg for( Breakpt *bk = knotspec->bbegin; bk <= knotspec->bend; bk++ ) 281f220fa62Smrg *(k++) = bk->value; 282f220fa62Smrg } 283f220fa62Smrg quilt->cpts = outcpts; 284f220fa62Smrg quilt->next = 0; 285f220fa62Smrg} 286f220fa62Smrg 287f220fa62Smrg/*----------------------------------------------------------------------------- 288f220fa62Smrg * Splinespec::transform - convert a spline to Bezier format 289f220fa62Smrg * 290f220fa62Smrg * Client: gl_quilt_to_bezier 291f220fa62Smrg *----------------------------------------------------------------------------- 292f220fa62Smrg */ 293f220fa62Smrg 294f220fa62Smrgvoid 295f220fa62SmrgSplinespec::transform( void ) 296f220fa62Smrg{ 297f220fa62Smrg Knotspec *knotspec; 298f220fa62Smrg for( knotspec = kspec; knotspec; knotspec=knotspec->next ) 299f220fa62Smrg knotspec->istransformed = 0; 300f220fa62Smrg 301f220fa62Smrg for( knotspec = kspec; knotspec; knotspec=knotspec->next ) { 302f220fa62Smrg for( Knotspec *kspec2 = kspec; kspec2; kspec2=kspec2->next ) 303f220fa62Smrg kspec2->kspectotrans = knotspec; 304f220fa62Smrg kspec->transform( outcpts ); 305f220fa62Smrg knotspec->istransformed = 1; 306f220fa62Smrg } 307f220fa62Smrg} 308f220fa62Smrg 309f220fa62Smrg 310f220fa62Smrg/*----------------------------------------------------------------------------- 311f220fa62Smrg * Knotspec::Knotspec - constuct a knot spec 312f220fa62Smrg *----------------------------------------------------------------------------- 313f220fa62Smrg */ 314f220fa62Smrg 315f220fa62SmrgKnotspec::Knotspec( void ) 316f220fa62Smrg{ 317f220fa62Smrg bbegin = 0; 318f220fa62Smrg sbegin = 0; 319f220fa62Smrg outkbegin = 0; 320f220fa62Smrg} 321f220fa62Smrg 322f220fa62Smrg/*----------------------------------------------------------------------------- 323f220fa62Smrg * Knotspec::copy - copy the control points along minor direction 324f220fa62Smrg * 325f220fa62Smrg * Client: Splinespec::copy 326f220fa62Smrg *----------------------------------------------------------------------------- 327f220fa62Smrg */ 328f220fa62Smrg 329f220fa62Smrgvoid 330f220fa62SmrgKnotspec::copy( INREAL *inpt, REAL *outpt ) 331f220fa62Smrg{ 332f220fa62Smrg inpt = (INREAL *) (((char *) inpt) + preoffset); 333f220fa62Smrg 334f220fa62Smrg if( next ) { 335f220fa62Smrg for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride ) { 336f220fa62Smrg next->copy( inpt, outpt ); 337f220fa62Smrg inpt = (INREAL *) (((char *) inpt) + prestride); 338f220fa62Smrg } 339f220fa62Smrg } else { 340f220fa62Smrg for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride ) { 341f220fa62Smrg pt_io_copy( outpt, inpt ); 342f220fa62Smrg inpt = (INREAL *) (((char *) inpt) + prestride); 343f220fa62Smrg } 344f220fa62Smrg } 345f220fa62Smrg} 346f220fa62Smrg 347f220fa62Smrg/*----------------------------------------------------------------------------- 348f220fa62Smrg * Knotspec::showpts - print out points before transformation 349f220fa62Smrg * 350f220fa62Smrg * Client: Knotspec::select 351f220fa62Smrg *----------------------------------------------------------------------------- 352f220fa62Smrg */ 353f220fa62Smrgvoid 354f220fa62SmrgKnotspec::showpts( REAL *outpt ) 355f220fa62Smrg{ 356f220fa62Smrg if( next ) { 357f220fa62Smrg for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride ) 358f220fa62Smrg next->showpts( outpt ); 359f220fa62Smrg } else { 360f220fa62Smrg for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride ) 361f220fa62Smrg _glu_dprintf( "show %g %g %g\n", outpt[0], outpt[1], outpt[2] ); 362f220fa62Smrg } 363f220fa62Smrg} 364f220fa62Smrg 365f220fa62Smrg/*----------------------------------------------------------------------------- 366f220fa62Smrg * Knotspec::factors - precompute scale factors 367f220fa62Smrg * - overwrites knot vector, actual new knot vector is NOT produced 368f220fa62Smrg * 369f220fa62Smrg * Client: Knotspec::select 370f220fa62Smrg *----------------------------------------------------------------------------- 371f220fa62Smrg */ 372f220fa62Smrg 373f220fa62Smrgvoid 374f220fa62SmrgKnotspec::factors( void ) 375f220fa62Smrg{ 376f220fa62Smrg Knot *mid = (outkend - 1) - order + bend->multi; 377f220fa62Smrg Knot_ptr fptr = sbegin; 378f220fa62Smrg 379f220fa62Smrg for( Breakpt *bpt = bend; bpt >= bbegin; bpt-- ) { 380f220fa62Smrg mid -= bpt->multi; // last knot less than knot to insert 381f220fa62Smrg int def = bpt->def - 1; // number of knots to insert 382f220fa62Smrg if( def <= 0 ) continue; 383f220fa62Smrg Knot kv = bpt->value; // knot to insert 384f220fa62Smrg 385f220fa62Smrg Knot *kf = (mid-def) + (order-1); 386f220fa62Smrg for( Knot *kl = kf + def; kl != kf; kl-- ) { 387f220fa62Smrg Knot *kh, *kt; 388f220fa62Smrg for( kt=kl, kh=mid; kt != kf; kh--, kt-- ) 389f220fa62Smrg *(fptr++) = (kv - *kh) / (*kt - *kh); 390f220fa62Smrg *kl = kv; 391f220fa62Smrg } 392f220fa62Smrg } 393f220fa62Smrg} 394f220fa62Smrg 395f220fa62Smrg/*----------------------------------------------------------------------------- 396f220fa62Smrg * Knotspec::insert - convert subobject in direction of kspec into Bezier 397f220fa62Smrg * 398f220fa62Smrg * Client: Knotspec::transform 399f220fa62Smrg *----------------------------------------------------------------------------- 400f220fa62Smrg */ 401f220fa62Smrg 402f220fa62Smrgvoid 403f220fa62SmrgKnotspec::insert( REAL *p ) 404f220fa62Smrg{ 405f220fa62Smrg Knot_ptr fptr = sbegin; 406f220fa62Smrg REAL *srcpt = p + prewidth - poststride; 407f220fa62Smrg REAL *dstpt = p + postwidth + postoffset - poststride; 408f220fa62Smrg Breakpt *bpt = bend; 409f220fa62Smrg 410f220fa62Smrg for( REAL *pend = srcpt - poststride*bpt->def; srcpt != pend; pend +=poststride ) { 411f220fa62Smrg REAL *p1 = srcpt; 412f220fa62Smrg for( REAL *p2 = srcpt-poststride; p2 != pend; p1 = p2, p2 -= poststride ) { 413f220fa62Smrg pt_oo_sum( p1, p1, p2, *fptr, 1.0-*fptr ); 414f220fa62Smrg fptr++; 415f220fa62Smrg } 416f220fa62Smrg } 417f220fa62Smrg 418f220fa62Smrg for( --bpt; bpt >= bbegin; bpt-- ) { 419f220fa62Smrg 420f220fa62Smrg for( int multi = bpt->multi; multi > 0; multi-- ) { 421f220fa62Smrg pt_oo_copy( dstpt, srcpt ); 422f220fa62Smrg dstpt -= poststride; 423f220fa62Smrg srcpt -= poststride; 424f220fa62Smrg } 425f220fa62Smrg 426f220fa62Smrg for( REAL *pend = srcpt - poststride*bpt->def; srcpt != pend; pend +=poststride, dstpt-=poststride ) { 427f220fa62Smrg pt_oo_copy( dstpt, srcpt ); 428f220fa62Smrg REAL *p1 = srcpt; 429f220fa62Smrg 430f220fa62Smrg for( REAL *p2 = srcpt-poststride; p2 != pend; p1=p2, p2 -= poststride ) { 431f220fa62Smrg pt_oo_sum( p1, p1, p2, *fptr, 1.0-*fptr ); 432f220fa62Smrg fptr++; 433f220fa62Smrg } 434f220fa62Smrg } 435f220fa62Smrg } 436f220fa62Smrg} 437f220fa62Smrg 438f220fa62Smrg/*----------------------------------------------------------------------------- 439f220fa62Smrg * Knotspec::preselect - initialize kspec for processing 440f220fa62Smrg * 441f220fa62Smrg * Client: Splinespec::select 442f220fa62Smrg *----------------------------------------------------------------------------- 443f220fa62Smrg */ 444f220fa62Smrg 445f220fa62Smrgvoid 446f220fa62SmrgKnotspec::preselect( void ) 447f220fa62Smrg{ 448f220fa62Smrg Knot kval; 449f220fa62Smrg 450f220fa62Smrg /* position klast after last knot of "last" breakpoint */ 451f220fa62Smrg for( klast = inkend - order, kval = *klast; klast != inkend; klast++ ) 452f220fa62Smrg if( ! identical( *klast, kval ) ) break; 453f220fa62Smrg 454f220fa62Smrg /* position kfirst after last knot of "first" breakpoint */ 455f220fa62Smrg for( kfirst = inkbegin+order-1, kval= *kfirst; kfirst != inkend; kfirst++ ) 456f220fa62Smrg if( ! identical( *kfirst, kval ) ) break; 457f220fa62Smrg 458f220fa62Smrg /* compute multiplicity of first breakpoint */ 459f220fa62Smrg Knot_ptr k; 460f220fa62Smrg for( k = kfirst - 1; k >= inkbegin; k-- ) 461f220fa62Smrg if( ! identical( kval, *k ) ) break; 462f220fa62Smrg k++; 463f220fa62Smrg 464f220fa62Smrg /* allocate space for breakpoints - 465f220fa62Smrg use worst case estimate on number of breakpoints */ 466f220fa62Smrg 467f220fa62Smrg bbegin = new Breakpt[(klast - kfirst)+1]; 468f220fa62Smrg /* record multiplicity and value of first breakpoint */ 469f220fa62Smrg bbegin->multi = kfirst - k; 470f220fa62Smrg bbegin->value = kval; 471f220fa62Smrg bend = bbegin; 472f220fa62Smrg 473f220fa62Smrg kleft = kright = kfirst; 474f220fa62Smrg} 475f220fa62Smrg 476f220fa62Smrg 477f220fa62Smrg/*----------------------------------------------------------------------------- 478f220fa62Smrg * Knotspec::select - Knotspec::select segments and precompute scale factors 479f220fa62Smrg * 480f220fa62Smrg * Client: Splinespec::select 481f220fa62Smrg *----------------------------------------------------------------------------- 482f220fa62Smrg */ 483f220fa62Smrg 484f220fa62Smrgvoid 485f220fa62SmrgKnotspec::select( void ) 486f220fa62Smrg{ 487f220fa62Smrg breakpoints(); 488f220fa62Smrg knots(); 489f220fa62Smrg factors(); 490f220fa62Smrg 491f220fa62Smrg preoffset = kleft - (inkbegin + order); 492f220fa62Smrg postwidth = (int)((bend - bbegin) * order); 493f220fa62Smrg prewidth = (int)((outkend - outkbegin) - order); 494f220fa62Smrg postoffset = (bbegin->def > 1) ? (bbegin->def-1) : 0; 495f220fa62Smrg} 496f220fa62Smrg 497f220fa62Smrg/*----------------------------------------------------------------------------- 498f220fa62Smrg * Knotspec::breakpoints - compute breakpoints for knotspec 499f220fa62Smrg * 500f220fa62Smrg * Client: Knotspec::select 501f220fa62Smrg *----------------------------------------------------------------------------- 502f220fa62Smrg */ 503f220fa62Smrg 504f220fa62Smrgvoid 505f220fa62SmrgKnotspec::breakpoints( void ) 506f220fa62Smrg{ 507f220fa62Smrg Breakpt *ubpt = bbegin; 508f220fa62Smrg Breakpt *ubend = bend; 509f220fa62Smrg long nfactors = 0; 510f220fa62Smrg 511f220fa62Smrg ubpt->value = ubend->value; 512f220fa62Smrg ubpt->multi = ubend->multi; 513f220fa62Smrg 514f220fa62Smrg kleft = kright; 515f220fa62Smrg 516f220fa62Smrg for( ; kright != klast; kright++ ) { 517f220fa62Smrg if ( identical(*kright,ubpt->value) ) { 518f220fa62Smrg (ubpt->multi)++; 519f220fa62Smrg } else { 520f220fa62Smrg ubpt->def = (int) (order - ubpt->multi); 521f220fa62Smrg nfactors += (ubpt->def * (ubpt->def - 1)) / 2; 522f220fa62Smrg (++ubpt)->value = *kright; 523f220fa62Smrg ubpt->multi = 1; 524f220fa62Smrg } 525f220fa62Smrg } 526f220fa62Smrg ubpt->def = (int) (order - ubpt->multi); 527f220fa62Smrg nfactors += (ubpt->def * (ubpt->def - 1)) / 2; 528f220fa62Smrg 529f220fa62Smrg bend = ubpt; 530f220fa62Smrg 531f220fa62Smrg if( nfactors ) { 532f220fa62Smrg sbegin = new Knot[nfactors]; 533f220fa62Smrg } else { 534f220fa62Smrg sbegin = NULL; 535f220fa62Smrg } 536f220fa62Smrg} 537f220fa62Smrg 538f220fa62Smrg 539f220fa62Smrg/*----------------------------------------------------------------------------- 540f220fa62Smrg * Knotspec::knots - copy relevant subsequence of knots into temporary area 541f220fa62Smrg * 542f220fa62Smrg * Client: Knotspec::select 543f220fa62Smrg *----------------------------------------------------------------------------- 544f220fa62Smrg */ 545f220fa62Smrg 546f220fa62Smrgvoid 547f220fa62SmrgKnotspec::knots( void ) 548f220fa62Smrg{ 549f220fa62Smrg Knot_ptr inkpt = kleft - order; 550f220fa62Smrg Knot_ptr inkend = kright + bend->def; 551f220fa62Smrg 552f220fa62Smrg /* allocate space for knots and factors */ 553f220fa62Smrg outkbegin = new Knot[inkend-inkpt]; 554f220fa62Smrg Knot_ptr outkpt; 555f220fa62Smrg for( outkpt = outkbegin; inkpt != inkend; inkpt++, outkpt++ ) 556f220fa62Smrg *outkpt = *inkpt; 557f220fa62Smrg 558f220fa62Smrg outkend = outkpt; 559f220fa62Smrg} 560f220fa62Smrg 561f220fa62Smrg 562f220fa62Smrg/*----------------------------------------------------------------------------- 563f220fa62Smrg * Knotspec::transform - convert a spline along a given direction 564f220fa62Smrg * 565f220fa62Smrg * Client: Splienspec::transform 566f220fa62Smrg *----------------------------------------------------------------------------- 567f220fa62Smrg */ 568f220fa62Smrg 569f220fa62Smrgvoid 570f220fa62SmrgKnotspec::transform( REAL *p ) 571f220fa62Smrg{ 572f220fa62Smrg if( next ) { 573f220fa62Smrg if( this == kspectotrans ) { 574f220fa62Smrg next->transform( p ); 575f220fa62Smrg } else { 576f220fa62Smrg if( istransformed ) { 577f220fa62Smrg p += postoffset; 578f220fa62Smrg for( REAL *pend = p + postwidth; p != pend; p += poststride ) 579f220fa62Smrg next->transform( p ); 580f220fa62Smrg } else { 581f220fa62Smrg REAL *pend = p + prewidth; 582f220fa62Smrg for( ; p != pend; p += poststride ) 583f220fa62Smrg next->transform( p ); 584f220fa62Smrg } 585f220fa62Smrg } 586f220fa62Smrg } else { 587f220fa62Smrg if( this == kspectotrans ) { 588f220fa62Smrg insert( p ); 589f220fa62Smrg } else { 590f220fa62Smrg if( istransformed ) { 591f220fa62Smrg p += postoffset; 592f220fa62Smrg for( REAL *pend = p + postwidth; p != pend; p += poststride ) 593f220fa62Smrg kspectotrans->insert( p ); 594f220fa62Smrg } else { 595f220fa62Smrg REAL *pend = p + prewidth; 596f220fa62Smrg for( ; p != pend; p += poststride ) 597f220fa62Smrg kspectotrans->insert( p ); 598f220fa62Smrg } 599f220fa62Smrg } 600f220fa62Smrg } 601f220fa62Smrg} 602f220fa62Smrg 603f220fa62Smrg/*----------------------------------------------------------------------------- 604f220fa62Smrg * Knotspec::~Knotspec - free space alocated for knotspec 605f220fa62Smrg *----------------------------------------------------------------------------- 606f220fa62Smrg */ 607f220fa62Smrg 608f220fa62SmrgKnotspec::~Knotspec( void ) 609f220fa62Smrg{ 610f220fa62Smrg if( bbegin ) delete[] bbegin; 611f220fa62Smrg if( sbegin ) delete[] sbegin; 612f220fa62Smrg if( outkbegin ) delete[] outkbegin; 613f220fa62Smrg} 614f220fa62Smrg 615f220fa62Smrg 616f220fa62Smrg/*----------------------------------------------------------------------------- 617f220fa62Smrg * pt_io_copy - make internal copy of input cntrl pt. of x coords 618f220fa62Smrg *----------------------------------------------------------------------------- 619f220fa62Smrg */ 620f220fa62Smrg 621f220fa62Smrgvoid 622f220fa62SmrgKnotspec::pt_io_copy( REAL *topt, INREAL *frompt ) 623f220fa62Smrg{ 624f220fa62Smrg switch( ncoords ) { 625f220fa62Smrg case 4: 626f220fa62Smrg topt[3] = (REAL) frompt[3]; 627f220fa62Smrg case 3: 628f220fa62Smrg topt[2] = (REAL) frompt[2]; 629f220fa62Smrg case 2: 630f220fa62Smrg topt[1] = (REAL) frompt[1]; 631f220fa62Smrg case 1: 632f220fa62Smrg topt[0] = (REAL) frompt[0]; 633f220fa62Smrg break; 634f220fa62Smrg default: { 635f220fa62Smrg for( int i = 0; i < ncoords; i++ ) 636f220fa62Smrg *topt++ = (REAL) *frompt++; 637f220fa62Smrg } 638f220fa62Smrg } 639f220fa62Smrg} 640f220fa62Smrg 641f220fa62Smrg/*----------------------------------------------------------------------------- 642f220fa62Smrg * pt_oo_copy - make internal copy of internal cntrl pt. of x coords 643f220fa62Smrg *----------------------------------------------------------------------------- 644f220fa62Smrg */ 645f220fa62Smrg 646f220fa62Smrgvoid 647f220fa62SmrgKnotspec::pt_oo_copy( REAL *topt, REAL *frompt ) 648f220fa62Smrg{ 649f220fa62Smrg switch( ncoords ) { 650f220fa62Smrg case 4: 651f220fa62Smrg topt[3] = frompt[3]; 652f220fa62Smrg case 3: 653f220fa62Smrg topt[2] = frompt[2]; 654f220fa62Smrg case 2: 655f220fa62Smrg topt[1] = frompt[1]; 656f220fa62Smrg case 1: 657f220fa62Smrg topt[0] = frompt[0]; 658f220fa62Smrg break; 659f220fa62Smrg default: 660f220fa62Smrg memcpy( topt, frompt, ncoords * sizeof( REAL ) ); 661f220fa62Smrg } 662f220fa62Smrg} 663f220fa62Smrg 664f220fa62Smrg/*----------------------------------------------------------------------------- 665f220fa62Smrg * pt_oo_sum - compute affine combination of internal cntrl pts 666f220fa62Smrg *----------------------------------------------------------------------------- 667f220fa62Smrg */ 668f220fa62Smrg 669f220fa62Smrgvoid 670f220fa62SmrgKnotspec::pt_oo_sum( REAL *x, REAL *y, REAL *z, Knot a, Knot b ) 671f220fa62Smrg{ 672f220fa62Smrg switch( ncoords ) { 673f220fa62Smrg case 4: 674f220fa62Smrg x[3] = a * y[3] + b * z[3]; 675f220fa62Smrg case 3: 676f220fa62Smrg x[2] = a * y[2] + b * z[2]; 677f220fa62Smrg case 2: 678f220fa62Smrg x[1] = a * y[1] + b * z[1]; 679f220fa62Smrg case 1: 680f220fa62Smrg x[0] = a * y[0] + b * z[0]; 681f220fa62Smrg break; 682f220fa62Smrg default: { 683f220fa62Smrg for( int i = 0; i < ncoords; i++ ) 684f220fa62Smrg *x++ = a * *y++ + b * *z++; 685f220fa62Smrg } 686f220fa62Smrg } 687f220fa62Smrg} 688