C:/Projekte/C++/FlowVIS_107/src/FlowData.cpp

Go to the documentation of this file.
00001 #include "FlowData.h"
00002 #include "reverseBytes.h"
00003 
00004 // needed for writing log-file
00005 #include <iostream>
00006 #include <fstream>
00007 
00008 
00009 FlowData::FlowData()
00010 {
00012   geometry = new FlowGeometry();
00013 
00014   //mark all the channel slots as free
00015   for(int i = 0; i < max_channels; i++)
00016   {
00017     channels[i] = NULL;
00018     freeChannel[i] = true;
00019     scalarChannel[i] = NONE;
00020   }
00021 }
00022 
00023 FlowData::~FlowData()
00024 {
00026   delete geometry;
00027 
00028   //delete all the channels
00029   for(int i = 0; i < max_channels; i++)
00030   {
00031     if (!freeChannel[i])
00032     {
00033       deleteChannel(i);
00034     }
00035   }
00036 }
00037 
00038 bool FlowData::loadDataset( string filename, bool bigEndian )
00039 {
00040   FILE* griFile = NULL;
00041   FILE* datFile = NULL; 
00042 
00043   char header[40];  // storeage for grid-file-header
00044 
00045 
00046   std::cout << "\n\n ------- READ FILE ------- " << std::endl;
00047 
00048   //localize the last dot in the filename 
00049   int lastdot = (int) filename.find_last_of(".",filename.length()-1);
00050   if (lastdot != string::npos)
00051     //if there is a dot, remove everything behind it
00052     filename = filename.substr(0,lastdot);      
00053 
00054 
00056   // GRID FILE
00058   string griName = filename + ".gri";
00059   std::cout << "- Loading grid file '" << griName << "' ... " << std::endl;
00060 
00061   //open the grid file
00062   griFile = fopen(griName.c_str(),"rb");
00063 
00064   if (!griFile)
00065   {
00066     std::cerr << "+ Error loading grid file:" << griName << std::endl << std::endl;
00067     return false;
00068   }
00069 
00070   //read the header from the grid-file
00071   fread( header, 40, 1, griFile );
00072 
00073   //pass the grid file to the geometry class to process it
00074   if ( !geometry->readFromFile( header, griFile, bigEndian ) )
00075     return false; // exit on error
00076 
00077   //close the file
00078   fclose( griFile );
00079 
00080 
00081   // --- done with grid-file
00082 
00083 
00085   // DAT FILE
00087 
00088   std::cout << "\n\n ------- Loading data file ------- " << std::endl;
00089 
00090   float DT; // gv Actually not used?
00091 
00092   //read some necessary data from the grid-file-header
00093   sscanf( header, "SN4DB %d %d %d %d %d %f", &dimX, &dimY, &dimZ, &numChannels, &timesteps, &DT );
00094   std::cout << "Dimensions: (" << dimX << ", " << dimY << ", " << dimZ << ")" << std::endl;
00095   std::cout << "Channels: " << numChannels << "\nTimesteps: " << timesteps << std::endl;         
00096 
00097   //since this framework handles only one timestep, we use only a single dat file
00098   char suffix[16];
00099   sprintf(suffix,".%.5u.dat",0); //the second dot and the following 5 specify that a minimum of 5 numbers will be written
00100   string datName = filename.append(suffix);
00101   std::cout << "- Loading grid file '" << datName << "' ... " << std::endl;    
00102 
00103 
00104   //open the dat-file
00105   datFile = fopen( datName.c_str(), "rb" );
00106   if ( !datFile )
00107   {
00108     std::cerr << "+ Error loading dat file:" << datName << std::endl << std::endl;
00109     return false;
00110   }
00111 
00112   numScalarChannels = numChannels;
00113   numChannels += 3; //add the 3 components of the velocity vector to the number of additional chanenls
00114 
00115   //because reading big chunks of data is much faster than single values, 
00116   //we read the data into a temporary array and then copy it to the channels
00117 
00118   //create temporary storage
00119   float* tmpArray = new float[ numChannels * geometry->getDimX() * geometry->getDimY() ];
00120 
00121   //read the data
00122   int result = (int) fread( tmpArray, sizeof(float), numChannels * geometry->getDimX() * geometry->getDimY(), datFile ); 
00123 
00124   //have we read the whole data file?
00125   if (result != numChannels * geometry->getDimX() * geometry->getDimY() )
00126   {
00127     std::cerr << "+ Error reading dat file:" << datName << std::endl << std::endl;
00128     return false;
00129   }
00130 
00131   // close the file
00132   fclose( datFile );
00133 
00134   // swap the byte order, if the file is encoded big-endian
00135   // (usually not necessary)
00136   if ( bigEndian )
00137     for(int j = 0; j < numChannels*geometry->getDimX()*geometry->getDimY(); j++)
00138       tmpArray[j] = reverseBytes<float>(tmpArray[j]);
00139 
00140 
00141   // --- begin processing data ---
00142 
00143   int currentChannel = -1;
00144   string channelName = "unkonwn channel data";
00145 
00146   int channelsToLoad = numChannels;  // gv Number of channels to load from file
00147   numChannels = 0;  // gv Total number of channels created in channels[]
00148 
00149   // assign the data to the appropriate channels
00150   for ( int j=0; j<channelsToLoad; j++ )
00151   {
00152    
00153     // just give the channels names for better debugging
00154     switch ( j )
00155     {
00156       case 0:
00157         channelName = "Velocity-X";
00158         break;
00159 
00160       case 1:
00161         channelName = "Velocity-Y";
00162         break;
00163 
00164       case 2:
00165         channelName = "Velocity-Z";
00166         break;
00167 
00168       case 3:
00169         channelName = "Pressure";
00170         scalarChannel[j] = ORIGINAL;
00171         break;
00172 
00173       case 4:
00174         channelName = "Vorticity";
00175         scalarChannel[j] = ORIGINAL;
00176         break;
00177 
00178       default:
00179         channelName = "unknown data";
00180         break;
00181     } // switch
00182     
00183     //create the new channel
00184     currentChannel = createChannel( channelName );
00185 
00186     //copy the values of the jth channel from tmpArray, which carries numChannels
00187     channels[ currentChannel ]->copyValues( tmpArray, channelsToLoad, j );
00188 
00189     //std::cout << "min: " << channels[ currentChannel ]->getMin() << std::endl;
00190 
00191 
00192 /* gv We do not manipulate data here -> rotations with OGL !!!
00193     // gv Not sure, but do we really need to do this??
00194     // please read comments below...!
00195 
00196     if ( j==Y ) // velocity channel y - invert y
00197     {
00198       for( int i=0; i<dimX * dimY; i++ )
00199       {
00200         float val = channels[ j ]->getValue( i );
00201         channels[ j ]->setValue( i, -val );
00202       }
00203     } // if j==Y
00204 */
00205 
00206 
00207 /*  
00208     // gv Wrong normalisazion. Correct, see below
00209     // If minimum > 1.0 => normalisation returns false results!
00210 
00211     if ( j>Z ) // scalar data in channel -> normalize to [0..1] 
00212     {
00213       float val;
00214 
00215       // normalize values
00216       for( int i=0; i<dimX * dimY; i++ )
00217       {
00218         val = channels[j]->getValue( i );
00219         val = channels[j]->normalizeValue( val );
00220         channels[j]->setValue( i, val );
00221       }
00222       // scalar data for background
00223       scalarChannel[j] = true;
00224     }
00225 */
00226 
00227   /* --- READ !! ---
00228     (gv)
00229 
00230     Not sure if this is correct now, since this time my brain seems to be overloaded! :(
00231 
00232     German now: ;)
00233 
00234     Wenn ich beim Grid de Achsen x<->y vertausche, bleiben de Indizes der Gitter-Punkte gleich. 
00235     Es ändert sich nur die Auslegung des Gitters.
00236 
00237     Wenn ich nun Skalar-Daten habe, haben die auch immer den gleichen Index im Array. Es ändert sich 
00238     für diese Daten ja nicht die Position auf dem Gitter (also der Index), sondern es ändert sich nur de Gitter-Position 
00239     auf denen diese Skalar-Werte liegen. 
00240     D.h., laut meiner Überlegung müßte es für skalare Daten egal sein, ob die Achsen geflippt werden oder nicht. 
00241     => Für Skalar-Daten keine Behandlung wenn flipped notwendig.
00242 
00243     Anders bei Vektor-Daten, da sich mit den gedrehten Achse auch die Komponenten der Vektoren vertauschen, 
00244     sonst zeigen sie in die falsche Richtung. D.h., man muß bei Vektor-Daten ebenfalls die Achsen tauschen, damit diese 
00245     in die richtige Richtung zeigen.
00246     
00247     => Dies ist bei uns nur bei den Velocity-Daten mit X u. Y der Fall. Wenn im Grid de Achsen vertauscht werden, müssen 
00248     wir de Velocity-Channels X und Y vertauschen. 
00249 
00250     Die Y-Achse invertiere ich zur Zeit nicht, da sie im Grid auch nicht mehr invertiert wird, weil somit 
00251     de Achsen von links-unten weggehen:
00252 
00253       y
00254       ^
00255       |
00256       |-------> x
00257     (0,0)
00258 
00259     Deshalb invertiere ich die Daten auch nicht mehr in Y-Richtung, weil sonst würd sich das Bild meiner Meinung
00260     nach umdrehen.
00261 
00262     Das sind meine Überlegungen dazu.
00263     Ich bin mir aber nun echt nicht sicher, ob das stimmt!!
00264 
00265     Bitte überleg dir das mal durch und sag mir Bescheid!
00266 
00267     Danke!!
00268 
00269     LG,
00270       Gü.
00271 
00272    --- */
00273 
00274 
00275 
00276   // gv If axes are flipped, flip vector-data
00277   if ( geometry->getIsFlipped() )
00278   {
00279     std::cout << "Flipping data-channel..." << std::endl;
00280 
00281 /* gv Possibily wrong idea
00282     // switching velocity x and y data
00283 
00284     // switch x and y axes
00285     // for vector-data only!
00286     // scalar-data not affected by flipped axes, since the indices for the data stay all the same!
00287     // (hope this is true!)
00288     
00289     float tempX, tempY;
00290 
00291     for ( int i=0; i<dimX*dimY; i++ ) 
00292     {
00293       tempX = channels[ 0 ]->getValue( i );
00294       tempY = channels[ 1 ]->getValue( i );
00295 
00296       channels[ 0 ]->setValue( i, tempY );
00297       channels[ 1 ]->setValue( i, tempX );
00298     }
00299 */
00300 
00301     // Generate new array and switch indices
00302     float *newArray = new float[ dimX*dimY ];
00303     int newIndex = -1;
00304     int oldIndex = -1;
00305 
00306     for ( int y=0; y<dimY; y++ )
00307       for ( int x=0; x<dimX; x++ )
00308       {
00309         newIndex = y + x * dimY;
00310         oldIndex = x + y * dimX;
00311 
00312         newArray[ newIndex ] = channels[ currentChannel ]->getValue( oldIndex );
00313 
00314         // gv TEST if indices are written correct
00315         //newArray[ newIndex ] = oldIndex;
00316       }
00317 
00318   /* gv Old version - possibly wrong
00319     for ( int x=0; x<dimX; x++ )
00320       for ( int y=0; y<dimY; y++ )
00321       {
00322         newIndex = x + y * dimX;
00323         oldIndex = y + x * dimY;
00324 
00325         //newArray[ newIndex ] = channels[ currentChannel ]->getValue( oldIndex );
00326         newArray[ newIndex ] = newIndex;
00327       }
00328     */
00329 
00330     // copy the values from the new array to the channel: channels[currentChannel] <= newArray
00331     channels[ currentChannel ]->copyValues( newArray );
00332 
00333     delete [] newArray;
00334   } // if flipped
00335 
00336 
00337   } // for channelsToLoad
00338 
00339 
00340   // gv After we processed all the channels, we need to switch the dimensions
00341   // if the axes are flipped
00342   if ( geometry->getIsFlipped() )
00343   {
00344     int temp = dimX;
00345     dimX = dimY;
00346     dimY = temp;
00347   }
00348 
00349 
00350   // Normalize data and store in new channel (so that we still have the original ones)
00351   for ( int i=3; i<(numScalarChannels+3); i++ ) // for all scalar-channels (usually there are two of them)
00352   {
00353     std::cout << "Creating a new channel for normalized data of " << channelNames[i] << "..." << std::endl;
00354 
00355     //channels[ i ]->moveMinimumToZero();  // gv Actually, not neccessary
00356 
00357     float *normArray = new float[ dimX*dimY ];
00358 
00359     for ( int j=0; j<dimX*dimY; j++ )
00360     {
00361       // normalize data
00362       float data = channels[ i ]->getValue( j );
00363 /*
00365       if(channels[i]->getMin() < 0 && data == 0.0)
00366       {
00367         normArray[ j ] = data;
00368       }
00369       else
00370       {
00371         normArray[ j ] = channels[ i ]->normalizeValue( data );
00372       }
00373 */
00374       // gv the code above is not correct -> min-values and zero-values are normalised alltogether to zero !!
00375       normArray[ j ] = channels[ i ]->normalizeValue( data );
00376     }
00377 
00378     // copy the values from the array to a new channel
00379     int newChannel = createChannel( "Normalized " + channelNames[i] );
00380     channels[ newChannel ]->copyValues( normArray );
00381 
00382     // nk - normalized scalar data for background
00383     scalarChannel[ newChannel ] = NORMALIZED;
00384 
00385     delete [] normArray;
00386   } // for normalize
00387 
00388 
00389   // create channel with magnitude of velocity-data ( gv Seems to be ok - not tested )
00390   velocityMagnitudeId = createChannelVectorLength( X, Y, Z );
00391 
00392   // normalize velocity-vectors (gv Seems to be ok - not tested )
00393   normalizeVelocityChannels( X, Y, Z );
00394 
00395   delete[] tmpArray;
00396   
00397   // gv TEST: write log-file
00398   //printData();
00399 
00400 /*
00401   // gv TEST
00402   // check, if velZ contains any data != 0
00403   // => only hurricane has velZ-data! => we need to take care of that!
00404   for ( int i=0; i<dimX*dimY; i++ )
00405   {
00406     if ( channels[2]->getValue(i) != 0 ) std::cout << " ! VelZ: " << channels[2]->getValue(i) << std::endl;
00407   }
00408 */
00409 
00410   std::cout << " ------- Done loading data file ------- \n\n" << std::endl;
00411 
00412   // hopefully everything done well
00413   return true;
00414 }
00415 
00416 
00417 
00418 void FlowData::printData() 
00419 {
00420   std::cout << "Writing log-file (this may take a while) ... please be patient!";
00421 
00422   ofstream dataLogFile;
00423 
00424   dataLogFile.open ("data.log");
00425   dataLogFile << "Channel-Data with their corresponding indices in channels:\n";
00426 
00427   // write all data in all channels 
00428   for ( int j=0; j<numChannels; j++ )
00429   {
00430     dataLogFile << "\nChannel " << j << " - " <<  channelNames[j] << ":\n";
00431 
00432     // print x/y 
00433     for ( int y=0; y<dimY; y++ )
00434     {
00435       dataLogFile << "\n\nY: " << y << ":\n";
00436 
00437       for ( int x=0; x<dimX; x++ )
00438       {
00439         dataLogFile << x << ": " << channels[j]->getValue( y*dimX + x ) << "; ";
00440         if ( (x % 10) == 9 )
00441           dataLogFile << "\n";
00442       }
00443     }
00444 
00445 
00446     /*
00447     // print array
00448     for ( int i=0; i<dimX * dimY; i++ )
00449     {
00450       dataLogFile << i << ": " << channels[j]->getValue( i ) << "\n";
00451     }
00452 */
00453 
00454   }
00455 
00456   dataLogFile.close();
00457 
00458   std::cout << " - done." << std::endl;
00459 }
00460 
00461 ScalarDataT FlowData::getIsScalar( int i )
00462 {
00463   if( i >= max_channels )
00464   {
00465     return NONE;
00466   }
00467   return scalarChannel[i];   
00468 }
00469 
00470 
00471 int FlowData::getChannelCount()
00472 {
00473   return numChannels;
00474 }
00475 
00476 
00477 //VelocityT* FlowData::getVelocity() const
00478 //{
00479 //  return velocity;
00480 //}
00481 
00482 
00483 int FlowData::createChannel( string channelName )
00484 {
00485   //find the first unused channel slot
00486   int i = 0;
00487 
00488   while ( (i<max_channels) && (!freeChannel[i]) ) i++;
00489 
00490   
00491   if ( i<max_channels ) //if there is a free slot
00492   {
00493     std::cout << "Creating channel " << channelName << " at " << i << std::endl;
00494 
00495     //create a new channel
00496     channels[i] = new FlowChannel(geometry);
00497 
00498     //remember the slot
00499     freeChannel[i] = false;
00500 
00501     // name the channel
00502     channelNames[i] = channelName;
00503 
00504     // increase numChannels
00505     ++numChannels;
00506 
00507     //return the adress of the new channel
00508     return i;
00509   }
00510   else //there is no free channel
00511   {
00512     std::cerr << "There is no free channel slot!" << std::endl;
00513     return -1;
00514   }
00515 }
00516 
00517 
00518 void FlowData::deleteChannel( int i )
00519 {
00520   if ( !freeChannel[i] ) //if the address is really occupied
00521   {
00522     std::cout << "Deleting channel at " << i << " ... ";
00523 
00524     //delete the channel instance
00525     delete channels[i];
00526 
00527     channels[i] = NULL;
00528 
00529     //free the slot
00530     freeChannel[i] = true;
00531   }
00532   else 
00533     std::cout << "Tried to delete a non-existing channel at " << i << "." << std::endl;
00534 }
00535 
00536 
00537 FlowChannel* FlowData::getChannel( int i )
00538 {
00539   return channels[i];
00540 }
00541 
00542 /* gv Obsolete?
00543 int FlowData::createChannelGeometry( int dimension )
00544 {
00545   int result = createChannel();
00546 
00547   //just take the dimension as if it was an offset to the geometryData array
00548   channels[result]->copyValues( (float*) geometry->geometryData, 3, dimension );
00549 
00550   return result;
00551 }
00552 */
00553 
00554 int FlowData::createChannelVectorLength( FlowChannel* chX, FlowChannel* chY, FlowChannel* chZ )
00555 {
00556   int newChannel = createChannel( "Velocity-Length" );
00557 
00558   //check whether we deal with 2D or 3D vectors
00559   if (chZ)
00560   {
00561     for (int i = 0; i < geometry->getDimX()*geometry->getDimY(); i++)
00562     {
00563       //save the vector length
00564       channels[newChannel]->setValue(i,sqrt(chX->getValue(i)*chX->getValue(i) + chY->getValue(i)*chY->getValue(i) + chZ->getValue(i)*chZ->getValue(i)));
00565     }
00566   }
00567   else
00568   {
00569     for (int i = 0; i < geometry->getDimX()*geometry->getDimY(); i++)
00570     {
00571       channels[newChannel]->setValue(i,sqrt(chX->getValue(i)*chX->getValue(i) + chY->getValue(i)*chY->getValue(i)));
00572     }
00573   }
00574   return newChannel;
00575 }
00576 
00577 
00578 int FlowData::createChannelVectorLength( int chX, int chY, int chZ )
00579 {
00580         //just a wrapper for the method above
00581         if (chZ >= 0)
00582   {
00583                 return createChannelVectorLength(getChannel(chX),getChannel(chY),getChannel(chZ));
00584   }
00585         else 
00586   {
00587     return createChannelVectorLength(getChannel(chX),getChannel(chY));
00588   }
00589 }
00590 
00591 
00592 void FlowData::normalizeVelocityChannels(FlowChannel* chX, FlowChannel* chY, FlowChannel* chZ)
00593 {
00594   if (chZ)
00595   {
00596     for (int i = 0; i < geometry->getDimX()*geometry->getDimY(); i++)
00597     {
00598       // create vec3 from data, normalize and save back
00599       vec3 velocity = vec3( chX->getValue(i), chY->getValue(i), chZ->getValue(i) );
00600 
00601       velocity.normalize();
00602 
00603       chX->setValue( i, velocity[X] );
00604       chY->setValue( i, velocity[Y] );
00605       chZ->setValue( i, velocity[Z] );
00606     }
00607   }
00608   else
00609   {
00610     for (int i = 0; i < geometry->getDimX()*geometry->getDimY(); i++)
00611     {
00612       // create vec3 from data, normalize and save back
00613       vec3 velocity = vec3( chX->getValue(i), chY->getValue(i) );
00614       velocity.normalize();
00615 
00616       chX->setValue( i, velocity[X] );
00617       chY->setValue( i, velocity[Y] );
00618     }
00619   }
00620 }
00621 
00622 
00623 void FlowData::normalizeVelocityChannels(int chX, int chY, int chZ)
00624 {
00625   std::cout << "Normalizing (velocity-)channels " 
00626     << chX << ", " 
00627     << chY << ", " 
00628     << chZ << "." << std::endl;
00629 
00631         if (chZ >= 0)
00632   {
00633                 normalizeVelocityChannels(getChannel(chX),getChannel(chY),getChannel(chZ));
00634   }
00635         else 
00636   {
00637     normalizeVelocityChannels(getChannel(chX),getChannel(chY));
00638   }
00639 }
00640 
00642 #if 0
00643 int FlowData::createChannelVectorLength(FlowChannel* chX, FlowChannel* chY, FlowChannel* chZ)
00644 {
00645   int result = createChannel();
00646   float mag;
00647   vec3 vel;
00648   //check whether we deal with 2D or 3D vectors
00649   if (chZ)
00650   {
00651     for (int i = 0; i < geometry->getDimX() * geometry->getDimY(); i++)
00652     {
00653       // get velocity vectors -> INVERT Y-Value due to LHS->RHS
00654       vel.v[X] = chX->getValue(i);
00655       vel.v[Y] = -chY->getValue(i);
00656       vel.v[Z] = chZ->getValue(i);
00657 
00658       // get magnitude of velocity
00659       mag = vel.length();
00660 
00661       //save the vector length to velocity struct & channel
00662       velocity[i].magnitude = mag;
00663       channels[result]->setValue(i, mag);
00664 
00665       // normalize velocity vector & save to velocity struct
00666       vel.normalize();
00667       velocity[i].normVelocity = vel;
00668     }
00669   }
00670   else
00671   {
00672     for (int i = 0; i < geometry->getDimX() * geometry->getDimY(); i++)
00673     {
00674       // get velocity vectors
00675       vel.v[X] = chX->getValue(i);
00676       vel.v[Y] = chY->getValue(i);
00677 
00678       // get magnitude of velocity
00679       mag = vel.length();
00680 
00681       //save the vector length to velocity struct & channel
00682       velocity[i].magnitude = mag;
00683       channels[result]->setValue(i, mag);
00684 
00685       // normalize velocity vector & save to velocity struct
00686       velocity[i].normVelocity = vel.normalize();
00687     }
00688   }
00689 
00690   return result;
00691 }
00692 
00693 int FlowData::createChannelVectorLength(int chX, int chY, int chZ)
00694 {
00695   //just a wrapper for the method above
00696   if (chZ >= 0)
00697   {
00698     return createChannelVectorLength(getChannel(chX),getChannel(chY),getChannel(chZ));
00699   }
00700   else 
00701   {
00702     return createChannelVectorLength(getChannel(chX),getChannel(chY));
00703   }
00704 }
00705 #endif 
00706 
00707 
00708 int FlowData::getScalarChannelCount()
00709 {
00710   return numScalarChannels;
00711 }
00712 
00713 
00714 int FlowData::getNumTimesteps()
00715 {
00716   return timesteps;
00717 }
00718 
00719 
00720 FlowGeometry* FlowData::getGeometry() const
00721 {
00722   return geometry; 
00723 }
00724 
00725 
00726 //int FlowData::getGeomID (int dim)
00727 //{
00728 //  switch(dim)
00729 //  {
00730 //  case X: return geomX;
00731 //          break;
00732 //
00733 //  case Y: return geomY;
00734 //          break;
00735 //
00736 //  default: printf("Wrong geometry dimension specified\n");
00737 //          return -1;
00738 //          break;
00739 //  }
00740 //}
00741 
00742 
00743 int FlowData::getVelMagID ()
00744 {
00745   return velocityMagnitudeId;
00746 }
00747 
00748 
00749 void FlowData::rescaleScalarData()
00750 {
00751 }
00752 

Generated on Mon Jan 21 14:50:12 2008 for VisLU by  doxygen 1.5.4