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