FlowVis 1.0
|
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 }