FlowVis 1.0

FlowVis/Framework/FlowGeometry.cpp

00001 #include "FlowGeometry.h"
00002 #include "reverseBytes.h"
00003 
00004 bool FlowGeometry::readFromFile(char* header, FILE* fp, bool bigEndian)
00005 {
00006         isFlipped = false;
00007         //determine the dimensions
00008     sscanf(header,"SN4DB %d %d %d",&dim[0],&dim[1],&dim[2]);
00009     std::cout << "Dimensions: " << dim[0] << " x " << dim[1] << " x " << dim[2] << std::endl;
00010     if (dim[2]!=1)
00011     {
00012         std::cerr << "Invalid Z dimension value." << std::endl;
00013         return false;
00014     }
00015 
00016         geometryData = new vec3[dim[0]*dim[1]];
00017         //read the data and check if everything went fine
00018     int result = fread(geometryData,sizeof(vec3),dim[0]*dim[1],fp);
00019         if (result != dim[0]*dim[1])
00020         {
00021                 std::cerr << "+ Error reading grid file." << std::endl << std::endl;
00022                 return false;
00023         }
00024 
00025         if (bigEndian)
00026                 for (int j = 0; j < getDimX()*getDimY(); j++)
00027                         for (int k = 0; k < 3; k++)
00028                                 geometryData[j][k] = reverseBytes<float>(geometryData[j][k]);
00029 
00030     //first vertex
00031         boundaryMin = vec3(getPos(0));
00032         //last vertex
00033         boundaryMax = vec3(getPos((dim[0]*dim[1]) - 1));
00034         boundarySize = boundaryMax - boundaryMin;
00035 
00036     //if X and Y are swapped... meaning that going in a row the y value increases and x stays the same
00037     if (getPosY(dim[0]-1)>(boundaryMin[1] + boundaryMax[1])*0.5)
00038     {
00039                 //this flag will fix that, anywhere where it's neccerasy... watch it :)
00040         isFlipped = true;
00041         std::cout << "Flipped Y and X dimensions." << std::endl;
00042     }
00043     else isFlipped = false;        
00044 
00045     std::cout << "X Boundaries: " << boundaryMin[0] << " ... " << boundaryMax[0] << std::endl;
00046     std::cout << "Y Boundaries: " << boundaryMin[1] << " ... " << boundaryMax[1] << std::endl;
00047     
00048     return true;
00049 }
00050 
00051 FlowGeometry::FlowGeometry()
00052 {
00053     geometryData = NULL;
00054 }
00055 
00056 FlowGeometry::~FlowGeometry()
00057 {
00058     if (geometryData)
00059         delete[] geometryData;
00060 }
00061 
00063 int FlowGeometry::getXYvtx(vec3 pos)
00064 {
00065     int i;
00066         int j;
00067         //search for the column left to the vertex
00068     for (i = 0; (i < dim[0])&&(getPosX(getVtx(i,0)) < pos[0]); i++) ;
00069         //search for the row under the vertex
00070         for (j = 0; (j < dim[1])&&(getPosY(getVtx(0,j)) < pos[1]); j++) ;
00071         
00072         //return the vertex ID of the found vertex
00073         return getVtx((i<dim[0]) ? i : dim[0]-1, (j<dim[1]) ? j : dim[1]-1);
00074 }
00075 
00076 
00077 
00078 inline vec3 FlowGeometry::getPos(int vtxID)
00079 {
00080         return geometryData[vtxID];
00081 }
00082 
00083 inline float FlowGeometry::getPosX(int vtxID)
00084 {
00085         return geometryData[vtxID][0];
00086 }
00087 
00088 inline float FlowGeometry::getPosY(int vtxID)
00089 {
00090         return geometryData[vtxID][1];
00091 }
00092 
00093 //TODO students: improve this
00095 int FlowGeometry::getNearestVtx(vec3 pos)
00096 {
00097         //take the norm to the first vertex
00098         float dist = pos.dist2(getPos(0));
00099         //mark the vertex 0 as the closest one
00100         int closest = 0;
00101         float newd;
00102 
00103         //Iterate over x
00104         
00105         int last = getXYvtx(pos);
00106         
00107         
00108         //Iterate through all vertices and search for the nearest one. I know, this is so inefficient, that you'll have to rewrite it :P
00109         /*for (int i = 1; i < dim[0]*dim[1]; i++)
00110         {
00111                 newd = pos.dist2(getPos(i));
00112                 if (newd < dist)
00113                 {
00114                         dist = newd;
00115                         closest = i;
00116                 }
00117         }*/
00118         return last;
00119 }
00120 
00121 void FlowGeometry::getSurroundingVtxIDs(vec3 pos, int* vtxID, float* coef)
00122 {
00123         int xmin, xmax;
00124         int ymin, ymax;
00125         int i, j;
00126         
00127         //search for the column left to the vertex
00128     
00129         for (i = 0; (i < dim[0])&&(getPosX(getVtx(i,0)) < pos[0]); i++) ;
00130         //search for the row under the vertex
00131         for (j = 0; (j < dim[1])&&(getPosY(getVtx(0,j)) < pos[1]); j++) ;
00132         
00133         i = i>0 ? i-1 : 0; j = j>0 ? j-1 : 0;
00134         
00135         xmin = (i<dim[0]) ? i : dim[0]-1; xmax = (i+1)<dim[0] ? i+1 : dim[0]-1;
00136         ymin = (j<dim[1]) ? j : dim[1]-1; ymax = (j+1)<dim[1] ? j+1 : dim[1]-1;
00137         
00138         //define vertices sourounding pos
00139         vtxID[0] = getVtx(xmin,ymin);
00140         vtxID[1] = getVtx(xmax,ymin);
00141         vtxID[2] = getVtx(xmin,ymax);
00142         vtxID[3] = getVtx(xmax,ymax);
00143 
00144         float x0 = getPosX(getVtx(xmin,0)); 
00145         float x1 = getPosX(getVtx(xmax,0));
00146         float y0 = getPosY(getVtx(0,ymin)); 
00147         float y1 = getPosY(getVtx(0,ymax));
00148         
00149         float d = (x1-x0)*(y1-y0);      
00150         
00151         coef[0] = 0.25;
00152         coef[1] = 0.25;
00153         coef[2] = 0.25;
00154         coef[3] = 0.25;
00155         
00156         coef[0] = (x1-pos[0])*(y1-pos[1]) /d;
00157         coef[1] = (pos[0]-x0)*(y1-pos[1]) /d;
00158         coef[2] = (x1-pos[0])*(pos[1]-y0) /d;
00159         coef[3] = (pos[0]-x0)*(pos[1]-y0) /d;
00160 }
00161 
00162 
00163 
00164 bool FlowGeometry::getInterpolationAt(vec3 pos, int* vtxID, float* coef)
00165 {
00166     //if we are outside of the dataset, return false
00167         //please note, that this test is valid only for rectangular datasets (block, hurricane), but not for tube
00168     if ((pos[0]<boundaryMin[0])||(pos[1]<boundaryMin[1])||(pos[0]>boundaryMax[0])||(pos[1]>boundaryMax[1]))
00169         return false;
00170 
00171         //example of a low-quality lookup with no interpolation
00172         vtxID[0] = getNearestVtx(pos); //finds the nearest vertex to the given position and returns it's value as the dominanting one. The getNearestVtx needs to be improved to gain some speed.
00173         vtxID[1] = 0;
00174         vtxID[2] = 0;
00175         vtxID[3] = 0;        
00176         coef[0] = 1.0f;
00177         coef[1] = 0.0f;
00178         coef[2] = 0.0f;
00179         coef[3] = 0.0f; 
00180         
00181         getSurroundingVtxIDs(pos, vtxID,coef);
00182     return true;
00183 }
00184 
00185 inline float FlowGeometry::getMinX()
00186 {
00187     return boundaryMin[0];
00188 }
00189 
00190 inline float FlowGeometry::getMaxX()
00191 {
00192     return boundaryMax[0];
00193 }
00194 
00195 inline float FlowGeometry::getMinY()
00196 {
00197     return boundaryMin[1];
00198 }
00199 
00200 inline float FlowGeometry::getMaxY()
00201 {
00202     return boundaryMax[1];
00203 }
00204 
00205 inline int FlowGeometry::getDimX()
00206 {
00207         return (isFlipped) ? dim[1] : dim[0];
00208 }
00209 
00210 inline int FlowGeometry::getDimY()
00211 {
00212         return (isFlipped) ? dim[0] : dim[1];
00213 }
00214 
00215 inline int FlowGeometry::getDimZ()
00216 {
00217     return dim[2];
00218 }
00219 
00220 int FlowGeometry::getVtx(int x, int y)
00221 {
00222         //if we need to flip the rows and columns, we do it here 
00223         return (isFlipped)? (x*dim[1]) + y : (y*dim[0]) + x;
00224 }
00225 
00226 int FlowGeometry::getVtxX(int vtxID)
00227 {
00228         //if we need to flip the rows and columns, we do it here
00229         return (isFlipped)? vtxID / dim[1] : vtxID % dim[0];
00230 }
00231 
00232 int FlowGeometry::getVtxY(int vtxID)
00233 {
00234         //if we need to flip the rows and columns, we do it here
00235         return (isFlipped)? vtxID % dim[1] : vtxID / dim[0];
00236 }
00237 
00238 int FlowGeometry::getRightNeigh(int vtxID)
00239 {
00240     int x = getVtxX(vtxID);
00241     return (x+1 < dim[0]) ? getVtx(x+1,getVtxY(vtxID)) : -1;
00242 }
00243 
00244 int FlowGeometry::getTopNeigh(int vtxID)
00245 {
00246         //remember that the data is structured with (0,0) in the upper-left corner and (1,1) in the lower-right
00247         //that's why we are subtracting 1 to find the top neighbour
00248     int y = getVtxY(vtxID);
00249     return (y+1 < dim[1]) ? getVtx(getVtxX(vtxID), y-1) : -1;
00250 }
00251 
00252 int FlowGeometry::getLeftNeigh(int vtxID)
00253 {
00254     int x = getVtxX(vtxID);
00255     return (x > 1) ? getVtx(x-1,getVtxY(vtxID)) : -1;
00256 }
00257 
00258 int FlowGeometry::getBottomNeigh(int vtxID)
00259 {
00260         //remember that the data is structured with (0,0) in the upper-left corner and (1,1) in the lower-right
00261     int y = getVtxY(vtxID);
00262     return (y < 1) ? getVtx(getVtxX(vtxID), y+1) : -1;
00263 }
00264 
00265 vec3 FlowGeometry::normalizeCoords(vec3 pos)
00266 {
00267         vec3 u(pos - boundaryMin);
00268         //scale each component according to the side length
00269         u[0] /= boundarySize[0];
00270         u[1] /= boundarySize[1];
00271 
00272         return u;
00273 }
00274 
00275 vec3 FlowGeometry::unNormalizeCoords(vec3 pos)
00276 {
00277         vec3 u(pos);
00278         //multiply each component according to the side length
00279         u[0] *= boundarySize[0];
00280         u[1] *= boundarySize[1];
00281 
00282         return u += boundaryMin;
00283 }
 All Classes Functions Variables Friends