00001
00002
00003 #include <iostream>
00004 #include <fstream>
00005
00006 #include "FlowGeometry.h"
00007 #include "FlowChannel.h"
00008 #include "FlowData.h"
00009 #include "reverseBytes.h"
00010
00011 using namespace std;
00012
00013
00014
00015 FlowGeometry::FlowGeometry()
00016 {
00017 geometryData = NULL;
00018 normGeometryData = NULL;
00019 }
00020
00021
00022 FlowGeometry::~FlowGeometry()
00023 {
00024 if ( geometryData )
00025 delete[] geometryData;
00026
00027 if ( normGeometryData )
00028 delete[] normGeometryData;
00029 }
00030
00031
00032 bool FlowGeometry::readFromFile(char* header, FILE* fp, bool bigEndian)
00033 {
00034 isFlipped = false;
00035
00036 std::cout << "\n\n ------- Loading grid ------- " << std::endl;
00037
00038
00039 sscanf( header, "SN4DB %d %d %d", &dim[0], &dim[1], &dim[2] );
00040 std::cout << "Dimensions: " << dim[0] << " x " << dim[1] << " x " << dim[2] << std::endl;
00041
00042 if ( dim[2]!=1 )
00043 {
00044 std::cerr << "Invalid Z dimension value." << std::endl;
00045 return false;
00046 }
00047
00048
00049 geometryData = new vec3[ dim[0] * dim[1] ];
00050
00051
00052 int result = (int) fread( geometryData, sizeof(vec3), dim[0] * dim[1], fp );
00053
00054
00055 if ( result != dim[0]*dim[1] )
00056 {
00057 std::cerr << "+ Error reading grid file." << std::endl << std::endl;
00058 return false;
00059 }
00060
00061
00062 if ( bigEndian )
00063 for (int j = 0; j < getDimX()*getDimY(); j++)
00064 for (int k = 0; k < 3; k++)
00065 geometryData[j][k] = reverseBytes<float>(geometryData[j][k]);
00066
00067
00068
00069 boundaryMin = vec3( getPos( 0 ) );
00070 boundaryMax = vec3( getPos( (dim[0]*dim[1]) - 1) );
00071 boundarySize = boundaryMax - boundaryMin;
00072
00073
00074 std::cout << "X-Boundaries : " << boundaryMin[0] << " .. " << boundaryMax[0] << std::endl;
00075 std::cout << "Y-Boundaries : " << boundaryMin[1] << " .. " << boundaryMax[1] << std::endl;
00076 std::cout << "Boundary-Size: " << boundarySize[0] << " | " << boundarySize[1] << std::endl;
00077
00078
00079
00080
00081
00082 float maxYPos = getPosY( dim[0]-1 );
00083 float avgYPos = ( boundaryMin[1] + boundaryMax[1] ) * 0.5f;
00084
00085 if ( avgYPos < maxYPos )
00086
00087
00088 {
00089 isFlipped = true;
00090 std::cout << "Flipped X and Y dimensions." << std::endl;
00091 }
00092 else isFlipped = false;
00093
00094
00095
00096
00097
00098 if ( isFlipped )
00099 {
00100
00101
00102
00103 vec3 temp;
00104
00105 for ( int i=0; i<dim[0]*dim[1]; i++ )
00106 {
00107 temp = geometryData[ i ];
00108
00109 geometryData[ i ].v[0] = temp.v[1];
00110 geometryData[ i ].v[1] = temp.v[0];
00111 }
00112
00113 int dimTemp = dim[X];
00114 dim[X] = dim[Y];
00115 dim[Y] = dimTemp;
00116 }
00117
00118
00119
00120 if ( boundaryMin.v[0] != 0.0 || boundaryMin.v[1] != 0.0 )
00121 for( int i=0; i<dim[0]*dim[1]; i++ )
00122 geometryData[i] = geometryData[i] - boundaryMin;
00123
00124
00125 boundaryMax = boundaryMax - boundaryMin;
00126 boundaryMin = getPos( 0 );
00127
00128
00129
00130
00131 normGeometryData = new vec3[ dim[0]*dim[1] ];
00132
00133 for( int i=0; i<dim[0]*dim[1]; i++ )
00134 normGeometryData[i] = normalizeCoords( geometryData[i] );
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 std::cout << "New X Boundaries: " << boundaryMin[0] << " .. " << boundaryMax[0] << std::endl;
00162 std::cout << "New Y Boundaries: " << boundaryMin[1] << " .. " << boundaryMax[1] << std::endl;
00163
00164
00165
00166
00167 std::cout << " ------- Done loading grid ------- " << std::endl;
00168
00169
00170 return true;
00171 }
00172
00173
00174 bool FlowGeometry::getIsFlipped()
00175 {
00176 return isFlipped;
00177 }
00178
00179
00180
00181
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 inline vec3 FlowGeometry::getPos(int vtxID)
00198 {
00199 return geometryData[vtxID];
00200 }
00201
00202 inline float FlowGeometry::getPosX(int vtxID)
00203 {
00204 return geometryData[vtxID][0];
00205 }
00206
00207 inline float FlowGeometry::getPosY(int vtxID)
00208 {
00209 return geometryData[vtxID][1];
00210 }
00211
00212
00213 vec3 FlowGeometry::getNormPos(int vtxID)
00214 {
00215 return normGeometryData[vtxID];
00216 }
00217
00218
00219 static int closest = 0;
00220
00221
00222
00224 int FlowGeometry::getNearestVtx(vec3 pos)
00225 {
00226
00227 float dist = pos.dist2(getPos(0));
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 return closest++;
00243 }
00244
00245
00246 bool FlowGeometry::getInterpolationAt_old(vec3 pos, int* vtxID, float* coef)
00247
00248 {
00249 std::cout << "getInterpolationAt... (old)" << std::endl;
00250
00251
00252
00253 if ((pos[0]<boundaryMin[0])||(pos[1]<boundaryMin[1])||(pos[0]>boundaryMax[0])||(pos[1]>boundaryMax[1]))
00254 return false;
00255
00256
00257 vtxID[0] = getNearestVtx(pos);
00258 vtxID[1] = 0;
00259 vtxID[2] = 0;
00260 vtxID[3] = 0;
00261 coef[0] = 1.0f;
00262 coef[1] = 0.0f;
00263 coef[2] = 0.0f;
00264 coef[3] = 0.0f;
00265 return true;
00266 }
00267
00268
00272 bool FlowGeometry::getInterpolationAt( vec3 pos, vec3* value, FlowData* data )
00273 {
00274
00275
00276
00277
00278 int xGridIdx = binarySearch( pos.v[0], 0, dim[X]-1, 0 );
00279 int yGridIdx = binarySearch( pos.v[1], 0, dim[Y]-1, 1 );
00280
00281
00282
00283
00284
00285 if ( xGridIdx == -1 || yGridIdx == -1 ) return false;
00286
00287
00288 int cell[2] = { xGridIdx, yGridIdx };
00289 vec3 interpolatedValue[1];
00290 bool retCode = interpolate( pos, cell, data, interpolatedValue );
00291
00292
00293
00294 value[0] = interpolatedValue[0];
00295
00296
00297
00298
00299
00300
00301 return retCode;
00302 }
00303
00304
00305 bool FlowGeometry::interpolate( vec3 pos, int* cell, FlowData* data, vec3 *interpolatedValue )
00306 {
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 int idxCp00 = cell[X] + cell[Y] * dim[X];
00317 int idxCp10 = idxCp00 + 1;
00318 int idxCp01 = idxCp00 + dim[X];
00319 int idxCp11 = idxCp01 + 1;
00320
00321
00322 vec3 cp00 = normGeometryData[ idxCp00 ];
00323 vec3 cp10 = normGeometryData[ idxCp10 ];
00324 vec3 cp01 = normGeometryData[ idxCp01 ];
00325 vec3 cp11 = normGeometryData[ idxCp11 ];
00326
00327
00328
00329
00330
00331
00332
00333 float coeff00 = 0.0f;
00334 float coeff10 = 0.0f;
00335 float coeff01 = 0.0f;
00336 float coeff11 = 0.0f;
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 float vx = pos[X] - cp00[X];
00352 float wx = cp10[X] - pos[X];
00353
00354 float vy = pos[Y] - cp00[Y];
00355 float wy = cp01[Y] - pos[Y];
00356
00357 float maxX = cp10[X] - cp00[X];
00358 float maxY = cp01[Y] - cp00[Y];
00359
00360 coeff00 = (wx * wy) / ( maxX * maxY );
00361 coeff10 = (vx * wy) / ( maxX * maxY );
00362 coeff01 = (wx * vy) / ( maxX * maxY );
00363 coeff11 = (vx * vy) / ( maxX * maxY );
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 FlowChannel* velX = data->getChannel( X );
00376 FlowChannel* velY = data->getChannel( Y );
00377 FlowChannel* velZ = data->getChannel( Z );
00378
00379
00380
00381
00382
00383
00384 vec3 vel00( velX->getValue( idxCp00 ), velY->getValue( idxCp00 ), velZ->getValue( idxCp00 ) );
00385 vec3 vel10( velX->getValue( idxCp10 ), velY->getValue( idxCp10 ), velZ->getValue( idxCp10 ) );
00386 vec3 vel01( velX->getValue( idxCp01 ), velY->getValue( idxCp01 ), velZ->getValue( idxCp01 ) );
00387 vec3 vel11( velX->getValue( idxCp11 ), velY->getValue( idxCp11 ), velZ->getValue( idxCp11 ) );
00388
00389
00390
00391
00392
00393
00394
00395 if ( ((vel00[X] == 0) && (vel00[Y] == 0)) ||
00396 ((vel10[X] == 0) && (vel10[Y] == 0)) ||
00397 ((vel01[X] == 0) && (vel01[Y] == 0)) ||
00398 ((vel11[X] == 0) && (vel11[Y] == 0)) )
00399 {
00400
00401
00402
00403
00404
00405
00406
00407 return false;
00408 }
00409
00410 interpolatedValue[0] = vel00 * coeff00 +
00411 vel10 * coeff10 +
00412 vel01 * coeff01 +
00413 vel11 * coeff11;
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 return true;
00449
00450 }
00451
00452
00456 int FlowGeometry::binarySearch( float searchValue, int begin, int end, int dimension )
00457 {
00458 bool found = false;
00459 int leftEnd = begin;
00460 int rightEnd = end;
00461 int mid = 0;
00462 int currentIndex = 0;
00463
00464
00465 while ( !found && leftEnd <= rightEnd )
00466 {
00467 float currentValue;
00468 mid = ( leftEnd + rightEnd ) / 2;
00469 currentIndex = mid;
00470
00471 currentValue = getCurrentSearchValue( currentIndex, dimension );
00472
00473 if ( currentValue == searchValue )
00474
00475 found = true;
00476 else
00477 {
00478
00479 if ( currentValue < searchValue )
00480 {
00481
00482 currentIndex = mid + 1;
00483 currentValue = getCurrentSearchValue( currentIndex, dimension );
00484
00485 if ( currentValue > searchValue )
00486 {
00487
00488 found = true;
00489 --currentIndex;
00490 }
00491 }
00492
00493 else
00494 {
00495
00496 currentIndex = mid - 1;
00497 currentValue = getCurrentSearchValue( currentIndex, dimension );
00498
00499 if ( currentValue < searchValue )
00500 {
00501
00502 found = true;
00503 }
00504 }
00505
00506 if ( !found )
00507 {
00508 if ( searchValue < currentValue )
00509
00510 rightEnd = mid - 1;
00511 else
00512
00513 leftEnd = mid + 1;
00514 }
00515 }
00516 }
00517
00518 if ( found )
00519
00520 return currentIndex;
00521 else
00522
00523 return -1;
00524 }
00525
00526
00530 int FlowGeometry::binarySearch2( float searchValue, int begin, int end, int dimension )
00531 {
00532 bool found = false;
00533 int leftEnd = begin;
00534 int rightEnd = end;
00535 int mid = 0;
00536 int currentIndex = 0;
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 while ( !found && leftEnd <= rightEnd )
00563 {
00564 float currentValue;
00565 mid = ( leftEnd + rightEnd ) / 2;
00566 currentIndex = mid;
00567
00568 currentValue = getCurrentSearchValue( currentIndex, dimension );
00569
00570 if ( currentValue == searchValue )
00571
00572 found = true;
00573 else
00574 {
00575
00576 currentIndex = mid + 1;
00577 currentValue = getCurrentSearchValue( currentIndex, dimension );
00578
00579 if ( currentValue == searchValue )
00580
00581 found = true;
00582 else
00583 {
00584
00585 currentIndex = mid - 1;
00586 currentValue = getCurrentSearchValue( currentIndex, dimension );
00587
00588 if ( currentValue == searchValue )
00589
00590 found = true;
00591
00592 else {
00593
00594
00595 if ( searchValue < currentValue )
00596
00597 rightEnd = mid - 1;
00598 else
00599
00600 leftEnd = mid + 1;
00601 }
00602 }
00603 }
00604 }
00605
00606 if ( found )
00607
00608 return currentIndex;
00609 else
00610
00611 return -1;
00612 }
00613
00614
00615 float FlowGeometry::getCurrentSearchValue( int index, int dimension )
00616 {
00617 float value;
00618
00619 if ( index == -1 )
00620 {
00621
00622 return 0.0f;
00623 }
00624
00625 if ( dimension == X )
00626 value = normGeometryData[ index ].v[0];
00627 else
00628 value = normGeometryData[ dim[X] * index ].v[1];
00629
00630
00631
00632
00633
00634
00635 return value;
00636 }
00637
00638
00639 void FlowGeometry::printGridPoints()
00640 {
00641 std::cout << "Writing grid-point-coords to log-file (this may take a while - please be patient!) ... ";
00642
00643 ofstream gridLogFile;
00644
00645 gridLogFile.open ("grid_points.log");
00646 gridLogFile << "Grid-Point-Positions with their corresponding indices in geometryData:\n\n";
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656 gridLogFile << "X:\n";
00657 for ( int i=0; i<dim[X]; i++ )
00658 {
00659 gridLogFile << i << ": " << normGeometryData[ i ].v[0] << "\n";
00660 }
00661
00662
00663 gridLogFile << "\n\nY:\n";
00664 for ( int i=0; i<dim[Y]; i++ )
00665 {
00666 gridLogFile << i << ": " << normGeometryData[ i * dim[X] ].v[1] << "\n";
00667 }
00668
00669
00670 gridLogFile.close();
00671
00672 std::cout << " done. " << std::endl;
00673 }
00674
00675
00676
00677 inline float FlowGeometry::getMinX()
00678 {
00679 return boundaryMin[0];
00680 }
00681
00682 inline float FlowGeometry::getMaxX()
00683 {
00684 return boundaryMax[0];
00685 }
00686
00687 inline float FlowGeometry::getMinY()
00688 {
00689 return boundaryMin[1];
00690 }
00691
00692 inline float FlowGeometry::getMaxY()
00693 {
00694 return boundaryMax[1];
00695 }
00696
00697 inline int FlowGeometry::getDimX()
00698 {
00699 return dim[0];
00700
00701 }
00702
00703 inline int FlowGeometry::getDimY()
00704 {
00705 return dim[1];
00706
00707 }
00708
00709 inline int FlowGeometry::getDimZ()
00710 {
00711 return dim[2];
00712 }
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766 vec3 FlowGeometry::normalizeCoords(vec3 pos)
00767 {
00768 vec3 u(pos - boundaryMin);
00769
00770 u[0] /= boundarySize[0];
00771 u[1] /= boundarySize[1];
00772
00773 return u;
00774 }
00775
00776 vec3 FlowGeometry::unNormalizeCoords(vec3 pos)
00777 {
00778 vec3 u(pos);
00779
00780 u[0] *= boundarySize[0];
00781 u[1] *= boundarySize[1];
00782
00783 return u += boundaryMin;
00784 }