1 /* 2 Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho 3 All rights reserved. 4 5 Redistribution and use in source and binary forms, with or without modification, 6 are permitted provided that the following conditions are met: 7 8 Redistributions of source code must retain the above copyright notice, this list of 9 conditions and the following disclaimer. Redistributions in binary form must reproduce 10 the above copyright notice, this list of conditions and the following disclaimer 11 in the documentation and/or other materials provided with the distribution. 12 13 Neither the name of the Johns Hopkins University nor the names of its contributors 14 may be used to endorse or promote products derived from this software without specific 15 prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 DAMAGE. 27 */ 28 29 #ifndef BSPLINE_DATA_INCLUDED 30 #define BSPLINE_DATA_INCLUDED 31 32 #define NEW_BSPLINE_CODE 1 33 34 #include "BinaryNode.h" 35 #include "PPolynomial.h" 36 #include "Array.h" 37 38 // This class represents a function that is a linear combination of B-spline elements, 39 // with the coeff member indicating how much of each element is present. 40 // [WARNING] The ordering of B-spline elements is in the opposite order from that returned by Polynomial::BSplineComponent 41 template< int Degree > 42 struct BSplineElementCoefficients 43 { 44 int coeffs[Degree+1]; BSplineElementCoefficientsBSplineElementCoefficients45 BSplineElementCoefficients( void ){ memset( coeffs , 0 , sizeof( int ) * ( Degree+1 ) ); } 46 int& operator[]( int idx ){ return coeffs[idx]; } 47 const int& operator[]( int idx ) const { return coeffs[idx]; } 48 }; 49 50 // This class represents a function on the the interval, partitioned into "res" blocks. 51 // On each block, the function is a degree-Degree polynomial, represented by the coefficients 52 // in the associated BSplineElementCoefficients. 53 // [NOTE] This representation of a function is agnostic to the type of boundary conditions (though the constructor is not). 54 template< int Degree > 55 struct BSplineElements : public std::vector< BSplineElementCoefficients< Degree > > 56 { 57 static const bool _Primal = (Degree&1)==1; 58 static const int _Off = (Degree+1)/2; 59 static int _ReflectLeft ( int offset , int res ); 60 static int _ReflectRight( int offset , int res ); 61 static int _RotateLeft ( int offset , int res ); 62 static int _RotateRight ( int offset , int res ); 63 template< bool Left > void _addPeriodic( int offset , bool negate ); 64 public: 65 // Coefficients are ordered as "/" "-" "\" 66 // [WARNING] This is the opposite of the order in Polynomial::BSplineComponent 67 int denominator; 68 BSplineElementsBSplineElements69 BSplineElements( void ) { denominator = 1; } 70 BSplineElements( int res , int offset , bool dirichlet ); 71 72 void upSample( BSplineElements& high ) const; 73 void differentiate( BSplineElements< Degree-1 >& d ) const; 74 75 void print( FILE* fp=stdout ) const 76 { 77 for( int i=0 ; i<std::vector< BSplineElementCoefficients< Degree > >::size() ; i++ ) 78 { 79 printf( "%d]" , i ); 80 for( int j=0 ; j<=Degree ; j++ ) printf( " %d" , (*this)[i][j] ); 81 printf( " (%d)\n" , denominator ); 82 } 83 } 84 }; 85 #define BSPLINE_SET_BOUNDS( name , s , e ) \ 86 static const int name ## Start = (s); \ 87 static const int name ## End = (e); \ 88 static const int name ## Size = (e)-(s)+1 89 90 // Assumes that x is non-negative 91 #define _FLOOR_OF_HALF( x ) ( (x) >>1 ) 92 #define _CEIL_OF_HALF( x ) ( ( (x)+1 )>>1 ) 93 // Done with the assumption 94 #define FLOOR_OF_HALF( x ) ( (x)<0 ? - _CEIL_OF_HALF( -(x) ) : _FLOOR_OF_HALF( x ) ) 95 #define CEIL_OF_HALF( x ) ( (x)<0 ? - _FLOOR_OF_HALF( -(x) ) : _CEIL_OF_HALF( x ) ) 96 #define SMALLEST_INTEGER_LARGER_THAN_HALF( x ) ( CEIL_OF_HALF( (x)+1 ) ) 97 #define LARGEST_INTEGER_SMALLER_THAN_HALF( x ) ( FLOOR_OF_HALF( (x)-1 ) ) 98 #define SMALLEST_INTEGER_LARGER_THAN_OR_EQUAL_TO_HALF( x ) ( CEIL_OF_HALF( x ) ) 99 #define LARGEST_INTEGER_SMALLER_THAN_OR_EQUAL_TO_HALF( x ) ( FLOOR_OF_HALF( x ) ) 100 101 template< int Degree > 102 class BSplineEvaluationData 103 { 104 public: 105 BSplineEvaluationData( void ); 106 static double Value( int depth , int off , double s , bool dirichlet , bool derivative ); 107 Dimension(int depth)108 static int Dimension( int depth ){ return ( 1<<depth ) + ( Degree&1 ); } 109 // An index is interiorly supported if its support is in the range [0,1<<depth) InteriorSupportedSpan(int depth,int & begin,int & end)110 inline static void InteriorSupportedSpan( int depth , int& begin , int& end ){ begin = -SupportStart , end = (1<<depth)-SupportEnd; } 111 112 // If the degree is even, we use a dual basis and functions are centered at the center of the interval 113 // It the degree is odd, we use a primal basis and functions are centered at the left end of the interval 114 // The function at index I is supported in: 115 // Support( I ) = [ I - (Degree+1-Inset)/2 , I + (Degree+1+Inset)/2 ] 116 // [NOTE] The value of ( Degree + 1 +/- Inset ) is always even 117 static const int Inset = (Degree&1) ? 0 : 1; 118 BSPLINE_SET_BOUNDS( Support , -( (Degree+1)/2 ) , Degree/2 ); 119 BSPLINE_SET_BOUNDS( ChildSupport , 2*SupportStart , 2*(SupportEnd+1)-1 ); 120 BSPLINE_SET_BOUNDS( Corner , SupportStart+1 , SupportEnd ); 121 BSPLINE_SET_BOUNDS( ChildCorner , 2*SupportStart+1 , 2*SupportEnd + 1 ); 122 123 // Setting I=0, we are looking for the smallest/largest integers J such that: 124 // Support( 0 ) CONTAINS Support( J ) 125 // <=> [-(Degree+1-Inset) , (Degree+1+Inset) ] CONTAINS [ J-(Degree+1-Inset)/2 , J+(Degree+1+Inset)/2 ] 126 // Which is the same as the smallest/largest integers J such that: 127 // J - (Degree+1-Inset)/2 >= -(Degree+1-Inset) | J + (Degree+1+Inset)/2 <= (Degree+1+Inset) 128 // <=> J >= -(Degree+1-Inset)/2 | J <= (Degree+1+Inset)/2 129 BSPLINE_SET_BOUNDS( UpSample , - ( Degree + 1 - Inset ) / 2 , ( Degree + 1 + Inset ) /2 ); 130 131 // Setting I=0/1, we are looking for the smallest/largest integers J such that: 132 // Support( J ) CONTAINS Support( 0/1 ) 133 // <=> [ 2*J - (Degree+1-Inset) , 2*J + (Degree+1+Inset) ] CONTAINS [ 0/1 - (Degree+1-Inset)/2 , 0/1 + (Degree+1+Inset)/2 ] 134 // Which is the same as the smallest/largest integers J such that: 135 // 2*J + (Degree+1+Inset) >= 0/1 + (Degree+1+Inset)/2 | 2*J - (Degree+1-Inset) <= 0/1 - (Degree+1-Inset)/2 136 // <=> 2*J >= 0/1 - (Degree+1+Inset)/2 | 2*J <= 0/1 + (Degree+1-Inset)/2 137 BSPLINE_SET_BOUNDS( DownSample0 , SMALLEST_INTEGER_LARGER_THAN_OR_EQUAL_TO_HALF( 0 - ( Degree + 1 + Inset ) / 2 ) , LARGEST_INTEGER_SMALLER_THAN_OR_EQUAL_TO_HALF( 0 + ( Degree + 1 - Inset ) / 2 ) ); 138 BSPLINE_SET_BOUNDS( DownSample1 , SMALLEST_INTEGER_LARGER_THAN_OR_EQUAL_TO_HALF( 1 - ( Degree + 1 + Inset ) / 2 ) , LARGEST_INTEGER_SMALLER_THAN_OR_EQUAL_TO_HALF( 1 + ( Degree + 1 - Inset ) / 2 ) ); 139 static const int DownSampleStart[] , DownSampleEnd[] , DownSampleSize[]; 140 141 // Note that this struct stores the components in left-to-right order 142 struct BSplineComponents 143 { 144 protected: 145 Polynomial< Degree > _polys[Degree+1]; 146 public: BSplineComponentsBSplineComponents147 BSplineComponents( void ){ ; } 148 BSplineComponents( int depth , int offset , bool dirichlet ); 149 const Polynomial< Degree >& operator[] ( int idx ) const { return _polys[idx]; } printnlBSplineComponents150 void printnl( void ) const { for( int d=0 ; d<=Degree ; d++ ) printf( "[%d] " , d ) , _polys[d].printnl(); } 151 }; 152 struct BSplineUpSamplingCoefficients 153 { 154 protected: 155 int _coefficients[ UpSampleSize ]; 156 public: BSplineUpSamplingCoefficientsBSplineUpSamplingCoefficients157 BSplineUpSamplingCoefficients( void ){ ; } 158 BSplineUpSamplingCoefficients( int depth , int offset , bool dirichlet ); 159 double operator[] ( int idx ){ return (double)_coefficients[idx] / (1<<Degree); } 160 }; 161 162 struct CenterEvaluator 163 { 164 static const int Start = -SupportStart , Stop = SupportEnd , Size = Start + Stop + 1; 165 IndexCenterEvaluator166 static const int Index( int depth , int offset ) 167 { 168 int dim = BSplineEvaluationData< Degree >::Dimension( depth ); 169 if ( offset<Start ) return offset; 170 else if( offset>=dim-Stop ) return Start + 1 + offset - ( dim-Stop ); 171 else return Start; 172 } 173 struct Evaluator 174 { 175 protected: 176 friend BSplineEvaluationData; 177 int _depth; 178 double _ccValues[2][Size][SupportSize]; 179 public: 180 double value( int fIdx , int cIdx , bool d ) const; depthCenterEvaluator::Evaluator181 int depth( void ) const { return _depth; } 182 }; 183 struct ChildEvaluator 184 { 185 protected: 186 friend BSplineEvaluationData; 187 int _parentDepth; 188 double _pcValues[2][Size][ChildSupportSize]; 189 public: 190 double value( int fIdx , int cIdx , bool d ) const; parentDepthCenterEvaluator::ChildEvaluator191 int parentDepth( void ) const { return _parentDepth; } childDepthCenterEvaluator::ChildEvaluator192 int childDepth( void ) const { return _parentDepth+1; } 193 }; 194 }; 195 static void SetCenterEvaluator( typename CenterEvaluator::Evaluator& evaluator , int depth , bool dirichlet ); 196 static void SetChildCenterEvaluator( typename CenterEvaluator::ChildEvaluator& evaluator , int parentDepth , bool dirichlet ); 197 198 struct CornerEvaluator 199 { 200 static const int Start = -SupportStart , Stop = SupportEnd , Size = Start + Stop + 1; 201 IndexCornerEvaluator202 static const int Index( int depth , int offset ) 203 { 204 int dim = BSplineEvaluationData< Degree >::Dimension( depth ); 205 if ( offset<Start ) return offset; 206 else if( offset>=dim-Stop ) return Start + 1 + offset - ( dim-Stop ); 207 else return Start; 208 } 209 struct Evaluator 210 { 211 protected: 212 friend BSplineEvaluationData; 213 int _depth; 214 double _ccValues[2][Size][CornerSize]; 215 public: 216 double value( int fIdx , int cIdx , bool d ) const; depthCornerEvaluator::Evaluator217 int depth( void ) const { return _depth; } 218 }; 219 struct ChildEvaluator 220 { 221 protected: 222 friend BSplineEvaluationData; 223 int _parentDepth; 224 double _pcValues[2][Size][ChildCornerSize]; 225 public: 226 double value( int fIdx , int cIdx , bool d ) const; parentDepthCornerEvaluator::ChildEvaluator227 int parentDepth( void ) const { return _parentDepth; } childDepthCornerEvaluator::ChildEvaluator228 int childDepth( void ) const { return _parentDepth+1; } 229 }; 230 }; 231 static void SetCornerEvaluator( typename CornerEvaluator::Evaluator& evaluator , int depth , bool dirichlet ); 232 static void SetChildCornerEvaluator( typename CornerEvaluator::ChildEvaluator& evaluator , int parentDepth , bool dirichlet ); 233 234 struct Evaluator 235 { 236 typename CenterEvaluator::Evaluator centerEvaluator; 237 typename CornerEvaluator::Evaluator cornerEvaluator; centerValueEvaluator238 double centerValue( int fIdx , int cIdx , bool d ) const { return centerEvaluator.value( fIdx , cIdx , d ); } cornerValueEvaluator239 double cornerValue( int fIdx , int cIdx , bool d ) const { return cornerEvaluator.value( fIdx , cIdx , d ); } 240 }; SetEvaluator(Evaluator & evaluator,int depth,bool dirichlet)241 static void SetEvaluator( Evaluator& evaluator , int depth , bool dirichlet ){ SetCenterEvaluator( evaluator.centerEvaluator , depth , dirichlet ) , SetCornerEvaluator( evaluator.cornerEvaluator , depth , dirichlet ); } 242 struct ChildEvaluator 243 { 244 typename CenterEvaluator::ChildEvaluator centerEvaluator; 245 typename CornerEvaluator::ChildEvaluator cornerEvaluator; centerValueChildEvaluator246 double centerValue( int fIdx , int cIdx , bool d ) const { return centerEvaluator.value( fIdx , cIdx , d ); } cornerValueChildEvaluator247 double cornerValue( int fIdx , int cIdx , bool d ) const { return cornerEvaluator.value( fIdx , cIdx , d ); } 248 }; SetChildEvaluator(ChildEvaluator & evaluator,int depth,bool dirichlet)249 static void SetChildEvaluator( ChildEvaluator& evaluator , int depth , bool dirichlet ){ SetChildCenterEvaluator( evaluator.centerEvaluator , depth , dirichlet ) , SetChildCornerEvaluator( evaluator.cornerEvaluator , depth , dirichlet ); } 250 251 struct UpSampleEvaluator 252 { 253 static const int Start = - SupportStart , Stop = SupportEnd , Size = Start + Stop + 1; IndexUpSampleEvaluator254 static const int Index( int depth , int offset ) 255 { 256 int dim = BSplineEvaluationData< Degree >::Dimension( depth ); 257 if ( offset<Start ) return offset; 258 else if( offset>=dim-Stop ) return Start + 1 + offset - ( dim-Stop ); 259 else return Start; 260 } 261 protected: 262 friend BSplineEvaluationData; 263 int _lowDepth; 264 double _pcValues[Size][UpSampleSize]; 265 public: 266 double value( int pIdx , int cIdx ) const; lowDepthUpSampleEvaluator267 int lowDepth( void ) const { return _lowDepth; } 268 }; 269 static void SetUpSampleEvaluator( UpSampleEvaluator& evaluator , int lowDepth , bool dirichlet ); 270 }; 271 template< int Degree > const int BSplineEvaluationData< Degree >::DownSampleStart[] = { DownSample0Start , DownSample1Start }; 272 template< int Degree > const int BSplineEvaluationData< Degree >::DownSampleEnd [] = { DownSample0End , DownSample1End }; 273 template< int Degree > const int BSplineEvaluationData< Degree >::DownSampleSize [] = { DownSample0Size , DownSample1Size }; 274 275 template< int Degree1 , int Degree2 > 276 class BSplineIntegrationData 277 { 278 public: 279 static double Dot( int depth1 , int off1 , bool dirichlet1 , bool d1 , int depth2 , int off2 , bool dirichlet2 , bool d2 ); 280 // An index is interiorly overlapped if the support of its overlapping neighbors is in the range [0,1<<depth) InteriorOverlappedSpan(int depth,int & begin,int & end)281 inline static void InteriorOverlappedSpan( int depth , int& begin , int& end ){ begin = -OverlapStart-BSplineEvaluationData< Degree2 >::SupportStart , end = (1<<depth)-OverlapEnd-BSplineEvaluationData< Degree2 >::SupportEnd; } 282 283 typedef BSplineEvaluationData< Degree1 > EData1; 284 typedef BSplineEvaluationData< Degree2 > EData2; 285 BSPLINE_SET_BOUNDS( Overlap , EData1:: SupportStart - EData2::SupportEnd , EData1:: SupportEnd - EData2::SupportStart ); 286 BSPLINE_SET_BOUNDS( ChildOverlap , EData1::ChildSupportStart - EData2::SupportEnd , EData1::ChildSupportEnd - EData2::SupportStart ); 287 BSPLINE_SET_BOUNDS( OverlapSupport , OverlapStart + EData2::SupportStart , OverlapEnd + EData2::SupportEnd ); 288 BSPLINE_SET_BOUNDS( ChildOverlapSupport , ChildOverlapStart + EData2::SupportStart , ChildOverlapEnd + EData2::SupportEnd ); 289 290 // Setting I=0/1, we are looking for the smallest/largest integers J such that: 291 // Support( 2*J ) * 2 INTERSECTION Support( 0/1 ) NON-EMPTY 292 // <=> [ 2*J - (Degree2+1-Inset2) , 2*J + (Degree2+1+Inset2) ] INTERSECTION [ 0/1 - (Degree1+1-Inset1)/2 , 0/1 + (Degree1+1+Inset1)/2 ] NON-EMPTY 293 // Which is the same as the smallest/largest integers J such that: 294 // 0/1 - (Degree1+1-Inset1)/2 < 2*J + (Degree2+1+Inset2) | 0/1 + (Degree1+1+Inset1)/2 > 2*J - (Degree2+1-Inset2) 295 // <=> 2*J > 0/1 - ( 2*Degree2 + Degree1 + 3 + 2*Inset2 - Inset1 ) / 2 | 2*J < 0/1 + ( 2*Degree2 + Degree1 + 3 - 2*Inset2 + Inset1 ) / 2 296 BSPLINE_SET_BOUNDS( ParentOverlap0 , SMALLEST_INTEGER_LARGER_THAN_HALF( 0 - ( 2*Degree2 + Degree1 + 3 + 2*EData2::Inset - EData1::Inset ) / 2 ) , LARGEST_INTEGER_SMALLER_THAN_HALF( 0 + ( 2*Degree2 + Degree1 + 3 - 2*EData2::Inset + EData1::Inset ) / 2 ) ); 297 BSPLINE_SET_BOUNDS( ParentOverlap1 , SMALLEST_INTEGER_LARGER_THAN_HALF( 1 - ( 2*Degree2 + Degree1 + 3 + 2*EData2::Inset - EData1::Inset ) / 2 ) , LARGEST_INTEGER_SMALLER_THAN_HALF( 1 + ( 2*Degree2 + Degree1 + 3 - 2*EData2::Inset + EData1::Inset ) / 2 ) ); 298 static const int ParentOverlapStart[] , ParentOverlapEnd[] , ParentOverlapSize[]; 299 300 struct FunctionIntegrator 301 { 302 static const int Start = - OverlapSupportStart , Stop = OverlapSupportEnd , Size = Start + Stop + 1; IndexFunctionIntegrator303 static const int Index( int depth , int offset ) 304 { 305 int dim = BSplineEvaluationData< Degree2 >::Dimension( depth ); 306 if ( offset<Start ) return offset; 307 else if( offset>=dim-Stop ) return Start + 1 + offset - ( dim-Stop ); 308 else return Start; 309 } 310 struct Integrator 311 { 312 protected: 313 friend BSplineIntegrationData; 314 int _depth; 315 double _ccIntegrals[2][2][Size][OverlapSize]; 316 public: 317 double dot( int fIdx1 , int fidx2 , bool d1 , bool d2 ) const; depthFunctionIntegrator::Integrator318 int depth( void ) const { return _depth; } 319 }; 320 struct ChildIntegrator 321 { 322 protected: 323 friend BSplineIntegrationData; 324 int _parentDepth; 325 double _pcIntegrals[2][2][Size][ChildOverlapSize]; 326 public: 327 double dot( int fIdx1 , int fidx2 , bool d1 , bool d2 ) const; parentDepthFunctionIntegrator::ChildIntegrator328 int parentDepth( void ) const { return _parentDepth; } childDepthFunctionIntegrator::ChildIntegrator329 int childDepth( void ) const { return _parentDepth+1; } 330 }; 331 }; 332 static void SetIntegrator( typename FunctionIntegrator::Integrator& integrator , int depth , bool dirichlet1 , bool dirichlet2 ); 333 static void SetChildIntegrator( typename FunctionIntegrator::ChildIntegrator& integrator , int parentDepth , bool dirichlet1 , bool dirichlet2 ); 334 }; 335 template< int Degree1 , int Degree2 > const int BSplineIntegrationData< Degree1 , Degree2 >::ParentOverlapStart[] = { ParentOverlap0Start , ParentOverlap1Start }; 336 template< int Degree1 , int Degree2 > const int BSplineIntegrationData< Degree1 , Degree2 >::ParentOverlapEnd [] = { ParentOverlap0End , ParentOverlap1End }; 337 template< int Degree1 , int Degree2 > const int BSplineIntegrationData< Degree1 , Degree2 >::ParentOverlapSize [] = { ParentOverlap0Size , ParentOverlap1Size }; 338 #undef BSPLINE_SET_BOUNDS 339 #undef _FLOOR_OF_HALF 340 #undef _CEIL_OF_HALF 341 #undef FLOOR_OF_HALF 342 #undef CEIL_OF_HALF 343 #undef SMALLEST_INTEGER_LARGER_THAN_HALF 344 #undef LARGEST_INTEGER_SMALLER_THAN_HALF 345 #undef SMALLEST_INTEGER_LARGER_THAN_OR_EQUAL_TO_HALF 346 #undef LARGEST_INTEGER_SMALLER_THAN_OR_EQUAL_TO_HALF 347 348 template< int Degree > 349 class BSplineData 350 { 351 bool _dirichlet; 352 public: 353 Centers(int depth)354 inline static int Centers ( int depth ){ return (1<<depth); } Corners(int depth)355 inline static int Corners ( int depth ){ return (1<<depth) + 1; } Dimension(int depth)356 inline static int Dimension( int depth ){ return (1<<depth) + (Degree&1); } FunctionIndex(int depth,int offset)357 inline static int FunctionIndex( int depth , int offset ){ return (Degree&1) ? BinaryNode::CornerIndex( depth , offset ) : BinaryNode::CenterIndex( depth , offset ); } FactorFunctionIndex(int idx,int & depth,int & offset)358 inline static void FactorFunctionIndex( int idx , int& depth , int& offset ){ return (Degree&1) ? BinaryNode::CornerDepthAndOffset( idx , depth , offset ) : BinaryNode::CenterDepthAndOffset( idx , depth , offset ); } TotalFunctionCount(int depth)359 inline static int TotalFunctionCount( int depth ){ return (Degree&1) ? BinaryNode::CumulativeCornerCount( depth ) : BinaryNode::CumulativeCenterCount( depth ); } TotalSampleCount(int depth)360 inline static int TotalSampleCount( int depth ){ return BinaryNode::CenterCount( depth ) + BinaryNode::CornerCount( depth ); } FunctionSpan(int depth,int & fStart,int & fEnd)361 inline static void FunctionSpan( int depth , int& fStart , int& fEnd ){ fStart = (depth>0) ? TotalFunctionCount(depth-1) : 0 , fEnd = TotalFunctionCount(depth); } SampleSpan(int depth,int & sStart,int & sEnd)362 inline static void SampleSpan( int depth , int& sStart , int& sEnd ){ sStart = (depth>0) ? TotalSampleCount(depth-1) : 0 , sEnd = TotalSampleCount(depth); } 363 364 inline static int RemapOffset( int depth , int idx , bool& reflect ); 365 366 int depth; 367 size_t functionCount , sampleCount; 368 Pointer( typename BSplineEvaluationData< Degree >::BSplineComponents ) baseBSplines; 369 370 BSplineData( void ); 371 372 void set( int maxDepth , bool dirichlet=false ); 373 }; 374 375 template< int Degree1 , int Degree2 > void SetBSplineElementIntegrals( double integrals[Degree1+1][Degree2+1] ); 376 377 378 #include "BSplineData.inl" 379 #endif // BSPLINE_DATA_INCLUDED