00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "HilbertCoordinateMapper.h"
00012 #include <iostream>
00013
00021 void HilbertCoordinateMapper::makeVec( const double x, const double y, vector< double >* where ) {
00022 (*where)[ 0 ] = x;
00023 (*where)[ 1 ] = y;
00024 }
00025
00034 void HilbertCoordinateMapper::makeVec( const double x, const double y, const double z, vector< double >* where ) {
00035 (*where)[ 0 ] = x;
00036 (*where)[ 1 ] = y;
00037 (*where)[ 2 ] = z;
00038 }
00039
00048 double HilbertCoordinateMapper::dist( const vector< double > *vx, const vector< double > *vy, const unsigned int dim ) {
00049
00050 double ret = ( (*vx)[ 0 ] - (*vy)[ 0 ] ); ret *= ret;
00051 for ( unsigned int i=1; i<dim; i++ ) {
00052 const double cur = ( (*vx)[ i ] - (*vy)[ i ] );
00053 ret += cur*cur;
00054 }
00055
00056 return sqrt( ret );
00057 }
00058
00068 unsigned int HilbertCoordinateMapper::closestTo( const vector< double > *coor, const vector< vector< double > > *corners, const unsigned int dim ) {
00069
00070 if (corners->size() == 0 )
00071 cerr << "Empty corners vector passed to HilbertCoordinateMapper::closestTo()!" << endl;
00072
00073 unsigned int ret = 0;
00074 double min = dist( coor, &( corners->at( 0 ) ), dim );
00075
00076
00077 for ( unsigned int i=1 ; i<corners->size(); i++ ) {
00078 const double curcost = dist( coor, & ( corners->at( i ) ), dim );
00079 if ( curcost < min ) {
00080 min = curcost;
00081 ret = i;
00082 }
00083 }
00084
00085 return ret;
00086 }
00087
00096 void HilbertCoordinateMapper::mid( const vector< double > *x, const vector< double > *y, vector< double > *to ) {
00097
00098 double* toArr = & ( (*to)[ 0 ] );
00099 for( unsigned int i=0; i<x->size(); i++ )
00100 toArr[ i ] = ( (*x)[ i ] + (*y)[ i ] ) / 2;
00101
00102 }
00103
00112 inline
00113 void HilbertCoordinateMapper::mid3D( unsigned int pos, unsigned int i, unsigned int j ) {
00114
00115 for( unsigned int d=0; d<3; d++ )
00116 Box_3Dtemp[ pos ][ d ] = ( Box_3D[ i ][ d ] + Box_3D[ j ][ d ] ) / 2.0;
00117
00118 }
00119
00126 void HilbertCoordinateMapper::refineCoors2D( vector< vector< double > > *corners, const unsigned int cell ) {
00127
00128 vector< double > a( 2 );
00129 vector< double > b( 2 );
00130 vector< double > c( 2 );
00131 vector< double > d( 2 );
00132
00133 vector< double > *in = &( ( *corners )[ 0 ] );
00134
00135
00136 switch( cell ) {
00137 case 1:
00138 a = in[ 0 ];
00139 mid( &in[ 0 ], &in[ 3 ], &b );
00140 mid( &in[ 0 ], &in[ 2 ], &c );
00141 mid( &in[ 0 ], &in[ 1 ], &d );
00142 break;
00143 case 2:
00144 mid( &in[ 0 ], &in[ 1 ], &a );
00145 b = in[ 1 ];
00146 mid( &in[ 1 ], &in[ 2 ], &c );
00147 mid( &in[ 1 ], &in[ 3 ], &d );
00148 break;
00149 case 3:
00150 mid( &in[ 0 ], &in[ 2 ], &a );
00151 mid( &in[ 1 ], &in[ 2 ], &b );
00152 c = in[ 2 ];
00153 mid( &in[ 2 ], &in[ 3 ], &d );
00154 break;
00155 case 4:
00156 mid( &in[ 3 ], &in[ 2 ], &a );
00157 mid( &in[ 1 ], &in[ 3 ], &b );
00158 mid( &in[ 3 ], &in[ 0 ], &c );
00159 d = in[ 3 ];
00160 break;
00161 default:
00162 cerr << "Invalid cell no. given in refineHilbert2D!" << endl;
00163 exit( 1 );
00164 }
00165
00166
00167
00168
00169
00170
00171 (*corners)[ 0 ] = a;
00172 (*corners)[ 1 ] = b;
00173 (*corners)[ 2 ] = c;
00174 (*corners)[ 3 ] = d;
00175
00176 }
00177
00184 void HilbertCoordinateMapper::refineCoors3D( const unsigned int cell ) {
00185
00186
00187 switch( cell ) {
00188 case 1:
00189 Box_3Dtemp[ 0 ] = Box_3D[ 0 ];
00190 mid3D( 1, 0, 3 );
00191 mid3D( 2, 0, 4 );
00192 mid3D( 3, 0, 7 );
00193 mid3D( 4, 0, 6 );
00194 mid3D( 5, 0, 5 );
00195 mid3D( 6, 0, 2 );
00196 mid3D( 7, 0, 1 );
00197 break;
00198 case 2:
00199 mid3D( 0, 0, 1 );
00200 mid3D( 1, 0, 6 );
00201 mid3D( 2, 1, 6 );
00202 Box_3Dtemp[ 3 ] = Box_3D[ 1 ];
00203 mid3D( 4, 1, 2 );
00204 mid3D( 5, 1, 5 );
00205 mid3D( 6, 0, 5 );
00206 mid3D( 7, 0, 2 );
00207 break;
00208 case 3:
00209 mid3D( 0, 0, 2 );
00210 mid3D( 1, 0, 5 );
00211 mid3D( 2, 1, 5 );
00212 mid3D( 3, 1, 2 );
00213 Box_3Dtemp[ 4 ] = Box_3D[ 2 ];
00214 mid3D( 5, 2, 5 );
00215 mid3D( 6, 3, 5 );
00216 mid3D( 7, 3, 2 );
00217 break;
00218 case 4:
00219 mid3D( 0, 3, 2 );
00220 Box_3Dtemp[ 1 ] = Box_3D[ 3 ];
00221 mid3D( 2, 0, 3 );
00222 mid3D( 3, 0, 2 );
00223 mid3D( 4, 0, 5 );
00224 mid3D( 5, 0, 4 );
00225 mid3D( 6, 3, 4 );
00226 mid3D( 7, 3, 5 );
00227 break;
00228 case 5:
00229 mid3D( 0, 3, 5 );
00230 mid3D( 1, 3, 4 );
00231 mid3D( 2, 0, 4 );
00232 mid3D( 3, 0, 5 );
00233 mid3D( 4, 7, 5 );
00234 mid3D( 5, 4, 7 );
00235 Box_3Dtemp[ 6 ] = Box_3D[ 4 ];
00236 mid3D( 7, 4, 5 );
00237 break;
00238 case 6:
00239 mid3D( 0, 4, 5 );
00240 mid3D( 1, 3, 5 );
00241 mid3D( 2, 2, 5 );
00242 Box_3Dtemp[ 3 ] = Box_3D[ 5 ];
00243 mid3D( 4, 6, 5 );
00244 mid3D( 5, 1, 5 );
00245 mid3D( 6, 0, 5 );
00246 mid3D( 7, 7, 5 );
00247 break;
00248 case 7:
00249 mid3D( 0, 7, 5 );
00250 mid3D( 1, 0, 5 );
00251 mid3D( 2, 2, 5 );
00252 mid3D( 3, 6, 5 );
00253 Box_3Dtemp[ 4 ] = Box_3D[ 6 ];
00254 mid3D( 5, 1, 6 );
00255 mid3D( 6, 0, 6 );
00256 mid3D( 7, 7, 6 );
00257 break;
00258 case 8:
00259 mid3D( 0, 7, 6 );
00260 mid3D( 1, 7, 5 );
00261 mid3D( 2, 0, 5 );
00262 mid3D( 3, 6, 0 );
00263 mid3D( 4, 0, 7 );
00264 mid3D( 5, 0, 5 );
00265 mid3D( 6, 7, 5 );
00266 Box_3Dtemp[ 7 ] = Box_3D[ 7 ];
00267 break;
00268 default:
00269 cerr << "Invalid cell no. given in refineHilbert3D!" << endl;
00270 exit( 1 );
00271 }
00272
00273 Box_3D = Box_3Dtemp;
00274 }
00275
00289 double HilbertCoordinateMapper::toHilbert2D( const vector< double > *coordinates ) {
00290 vector< unsigned int > digits;
00291 vector< vector< double > > Box;
00292
00293
00294 vector< double > a( 2 ); makeVec( 0, 0, &a); Box.push_back( a );
00295 vector< double > b( 2 ); makeVec( 0, 1, &b); Box.push_back( b );
00296 vector< double > c( 2 ); makeVec( 1, 1, &c); Box.push_back( c );
00297 vector< double > d( 2 ); makeVec( 1, 0, &d); Box.push_back( d );
00298
00299 double curDist;
00300 unsigned int closest = closestTo( coordinates, &Box, 2 );
00301 digits.push_back( closest );
00302
00303 for ( unsigned int i=0; i<RECURSE_LEVEL; i++ ) {
00304
00305 refineCoors2D( &Box, closest+1 );
00306
00307 closest = closestTo( coordinates, &Box, 2 );
00308
00309 digits.push_back( closest );
00310
00311 curDist = dist( coordinates, &Box.at( closest ), 2 );
00312
00313 }
00314
00315
00316
00317 return base4_to_base10( &digits );
00318 }
00319
00333 double HilbertCoordinateMapper::toHilbert3D( const vector< double > *coordinates ) {
00334 vector< unsigned int > digits;
00335 Box_3D = pattern;
00336
00337 unsigned int closest = closestTo3D( coordinates );
00338 digits.push_back( closest );
00339
00340 for ( unsigned int i=0; i<RECURSE_LEVEL; i++ ) {
00341
00342 refineCoors3D( closest + 1 );
00343
00344 closest = closestTo3D( coordinates );
00345
00346 digits.push_back( closest );
00347
00348 }
00349
00350
00351 #ifdef _DEBUG
00352
00353
00354
00355
00356
00357
00358 #endif
00359
00360 return base8_to_base10( &digits );
00361 }
00362
00372 unsigned int HilbertCoordinateMapper::closestTo3D( const vector< double > *coor ) {
00373
00374 unsigned int ret = 0;
00375 double min = dist3D( coor, 0 );
00376
00377 for ( unsigned int i=1; i<8; i++ ) {
00378 const double curcost = dist3D( coor, i );
00379 if ( curcost < min ) {
00380 min = curcost;
00381 ret = i;
00382 }
00383 }
00384
00385 return ret;
00386 }
00387
00396 inline double HilbertCoordinateMapper::dist3D( const vector< double > *vx, const unsigned int num ) {
00397
00398 double ret = ( (*vx)[ 0 ] - Box_3D[ num ][ 0 ] ); ret *= ret;
00399 for ( unsigned int i=1; i<3; i++ ) {
00400 const double cur = ( (*vx)[ i ] - Box_3D[ num ][ i ] );
00401 ret += cur*cur;
00402 }
00403
00404
00405 return ret;
00406 }
00407
00408 typedef boost::multi_array<double, 2 > array_type;
00409
00410 array_type HilbertCoordinateMapper::pattern = HilbertCoordinateMapper::makePattern();
00411
00412 array_type HilbertCoordinateMapper::Box_3D = HilbertCoordinateMapper::pattern;
00413
00414 array_type HilbertCoordinateMapper::Box_3Dtemp = HilbertCoordinateMapper::pattern;