00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <math.h>
00026 #include <string.h>
00027 #include "VolumetricData.h"
00028 #include "Matrix4.h"
00029 #include "utilities.h"
00030
00031 #ifndef NAN //not a number
00032 const float NAN = sqrtf(-1.f);
00033 #endif
00034
00036 VolumetricData::VolumetricData(const char *dataname, const float *o,
00037 const float *xa, const float *ya, const float *za,
00038 int xs, int ys, int zs, float *dataptr) {
00039 name = stringdup(dataname);
00040 data = dataptr;
00041 xsize = xs;
00042 ysize = ys;
00043 zsize = zs;
00044
00045 gradient = NULL;
00046 datamin = datamax = 0;
00047
00048 for (int i=0; i<3; i++) {
00049 origin[i] = (double)o[i];
00050 xaxis[i] = (double)xa[i];
00051 yaxis[i] = (double)ya[i];
00052 zaxis[i] = (double)za[i];
00053 }
00054
00055 const int ndata = xsize*ysize*zsize;
00056 if (ndata > 0) {
00057 float min, max;
00058 min = max = data[0];
00059 for (int j=1; j<ndata; j++) {
00060 if (min > data[j]) min = data[j];
00061 if (max < data[j]) max = data[j];
00062 }
00063 datamin = min;
00064 datamax = max;
00065 }
00066 }
00067
00068
00070 VolumetricData::~VolumetricData() {
00071 delete [] name;
00072 delete [] data;
00073 delete [] gradient;
00074 }
00075
00078 void VolumetricData::set_name(const char *newname) {
00079 if (name) delete[] name;
00080 name = new char[strlen(newname)+1];
00081 strcpy(name, newname);
00082 }
00083
00084
00086 void VolumetricData::cell_lengths(float *xl, float *yl, float *zl) const {
00087 float xsinv, ysinv, zsinv;
00088
00089
00090 if (xsize > 1)
00091 xsinv = 1.0f / (xsize - 1.0f);
00092 else
00093 xsinv = 1.0f;
00094
00095 if (ysize > 1)
00096 ysinv = 1.0f / (ysize - 1.0f);
00097 else
00098 ysinv = 1.0f;
00099
00100 if (zsize > 1)
00101 zsinv = 1.0f / (zsize - 1.0f);
00102 else
00103 zsinv = 1.0f;
00104
00105 *xl = sqrtf(float(dot_prod(xaxis, xaxis))) * xsinv;
00106 *yl = sqrtf(float(dot_prod(yaxis, yaxis))) * ysinv;
00107 *zl = sqrtf(float(dot_prod(zaxis, zaxis))) * zsinv;
00108 }
00109
00110
00112 void VolumetricData::cell_axes(float *xax, float *yax, float *zax) const {
00113 float xsinv, ysinv, zsinv;
00114
00115
00116 if (xsize > 1)
00117 xsinv = 1.0f / (xsize - 1.0f);
00118 else
00119 xsinv = 1.0f;
00120
00121 if (ysize > 1)
00122 ysinv = 1.0f / (ysize - 1.0f);
00123 else
00124 ysinv = 1.0f;
00125
00126 if (zsize > 1)
00127 zsinv = 1.0f / (zsize - 1.0f);
00128 else
00129 zsinv = 1.0f;
00130
00131 xax[0] = float(xaxis[0] * xsinv);
00132 xax[1] = float(xaxis[1] * xsinv);
00133 xax[2] = float(xaxis[2] * xsinv);
00134
00135 yax[0] = float(yaxis[0] * ysinv);
00136 yax[1] = float(yaxis[1] * ysinv);
00137 yax[2] = float(yaxis[2] * ysinv);
00138
00139 zax[0] = float(zaxis[0] * zsinv);
00140 zax[1] = float(zaxis[1] * zsinv);
00141 zax[2] = float(zaxis[2] * zsinv);
00142 }
00143
00144
00146 void VolumetricData::cell_dirs(float *xad, float *yad, float *zad) const {
00147 float xl, yl, zl;
00148
00149 cell_lengths(&xl, &yl, &zl);
00150 cell_axes(xad, yad, zad);
00151
00152 xad[0] /= xl;
00153 xad[1] /= xl;
00154 xad[2] /= xl;
00155
00156 yad[0] /= yl;
00157 yad[1] /= yl;
00158 yad[2] /= yl;
00159
00160 zad[0] /= zl;
00161 zad[1] /= zl;
00162 zad[2] /= zl;
00163 }
00164
00165
00168 void VolumetricData::voxel_coord_from_cartesian_coord(const float *carcoord, float *voxcoord, int shiftflag) const {
00169 float min_coord[3];
00170
00171 if (shiftflag) {
00172
00173 for (int i=0; i<3; i++)
00174 min_coord[i] = (float) origin[i] - 0.5f*float(xaxis[i]/(xsize-1) + yaxis[i]/(ysize-1) + zaxis[i]/(zsize-1));
00175 } else {
00176 for (int i=0; i<3; i++)
00177 min_coord[i] = (float) origin[i];
00178 }
00179
00180
00181 float matval[16];
00182 matval[0 ] = (float) xaxis[0]/(xsize-1);
00183 matval[1 ] = (float) yaxis[0]/(ysize-1);
00184 matval[2 ] = (float) zaxis[0]/(zsize-1);
00185 matval[3 ] = 0.f;
00186 matval[4 ] = (float) xaxis[1]/(xsize-1);
00187 matval[5 ] = (float) yaxis[1]/(ysize-1);
00188 matval[6 ] = (float) zaxis[1]/(zsize-1);
00189 matval[7 ] = 0.f;
00190 matval[8 ] = (float) xaxis[2]/(xsize-1);
00191 matval[9 ] = (float) yaxis[2]/(ysize-1);
00192 matval[10] = (float) zaxis[2]/(zsize-1);
00193 matval[11] = 0.f;
00194 matval[12] = (float) min_coord[0];
00195 matval[13] = (float) min_coord[1];
00196 matval[14] = (float) min_coord[2];
00197 matval[15] = 1.f;
00198 Matrix4 matrix(matval);
00199 matrix.inverse();
00200
00201 matrix.multpoint3d(carcoord, voxcoord);
00202 }
00203
00204
00206 int VolumetricData::voxel_index_from_coord(float xpos, float ypos, float zpos) const {
00207 float realcoord[3];
00208 float gridpoint[3];
00209 realcoord[0] = xpos;
00210 realcoord[1] = ypos;
00211 realcoord[2] = zpos;
00212
00213
00214 voxel_coord_from_cartesian_coord(realcoord, gridpoint, 1);
00215
00216 int gx = (int) gridpoint[0];
00217 int gy = (int) gridpoint[1];
00218 int gz = (int) gridpoint[2];
00219 if (gx < 0 || gx >= xsize) return -1;
00220 if (gy < 0 || gy >= ysize) return -1;
00221 if (gz < 0 || gz >= zsize) return -1;
00222 return gz*xsize*ysize + gy*xsize + gx;
00223 }
00224
00225
00227 float VolumetricData::voxel_value_safe(int x, int y, int z) const {
00228 int xx, yy, zz;
00229 xx = (x > 0) ? ((x < xsize) ? x : xsize-1) : 0;
00230 yy = (y > 0) ? ((y < ysize) ? y : ysize-1) : 0;
00231 zz = (z > 0) ? ((z < zsize) ? z : zsize-1) : 0;
00232 int index = zz*xsize*ysize + yy*xsize + xx;
00233 return data[index];
00234 }
00235
00236
00238 float VolumetricData::voxel_value_interpolate(float xv, float yv, float zv) const {
00239 int x = (int) xv;
00240 int y = (int) yv;
00241 int z = (int) zv;
00242 float xf = xv - x;
00243 float yf = yv - y;
00244 float zf = zv - z;
00245 float xlerps[4];
00246 float ylerps[2];
00247 float tmp;
00248
00249 tmp = voxel_value_safe(x, y, z);
00250 xlerps[0] = tmp + xf*(voxel_value_safe(x+1, y, z) - tmp);
00251
00252 tmp = voxel_value_safe(x, y+1, z);
00253 xlerps[1] = tmp + xf*(voxel_value_safe(x+1, y+1, z) - tmp);
00254
00255 tmp = voxel_value_safe(x, y, z+1);
00256 xlerps[2] = tmp + xf*(voxel_value_safe(x+1, y, z+1) - tmp);
00257
00258 tmp = voxel_value_safe(x, y+1, z+1);
00259 xlerps[3] = tmp + xf*(voxel_value_safe(x+1, y+1, z+1) - tmp);
00260
00261 ylerps[0] = xlerps[0] + yf*(xlerps[1] - xlerps[0]);
00262 ylerps[1] = xlerps[2] + yf*(xlerps[3] - xlerps[2]);
00263
00264 return ylerps[0] + zf*(ylerps[1] - ylerps[0]);
00265 }
00266
00267
00269 float VolumetricData::voxel_value_from_coord(float xpos, float ypos, float zpos) const {
00270 int ind = voxel_index_from_coord(xpos, ypos, zpos);
00271 if (ind > 0)
00272 return data[ind];
00273 else
00274 return NAN;
00275 }
00276
00277
00279 float VolumetricData::voxel_value_interpolate_from_coord(float xpos, float ypos, float zpos) const {;
00280 float realcoord[3];
00281 float gridpoint[3];
00282 realcoord[0] = xpos;
00283 realcoord[1] = ypos;
00284 realcoord[2] = zpos;
00285
00286
00287 voxel_coord_from_cartesian_coord(realcoord, gridpoint, 0);
00288
00289 int gx = (int) gridpoint[0];
00290 int gy = (int) gridpoint[1];
00291 int gz = (int) gridpoint[2];
00292 if (gx < 0 || gx >= xsize) return NAN;
00293 if (gy < 0 || gy >= ysize) return NAN;
00294 if (gz < 0 || gz >= zsize) return NAN;
00295 return voxel_value_interpolate(gridpoint[0], gridpoint[1], gridpoint[2]);
00296 }
00297
00298
00300 void VolumetricData::compute_volume_gradient(void) {
00301 int xi, yi, zi;
00302 float xs, ys, zs;
00303 float xl, yl, zl;
00304 int row;
00305
00306 if (!gradient) {
00307 gradient = new float[xsize * ysize * zsize * 3];
00308 }
00309
00310
00311 cell_lengths(&xl, &yl, &zl);
00312
00313
00314
00315 xs = -0.5f / xl;
00316 ys = -0.5f / yl;
00317 zs = -0.5f / zl;
00318
00319 for (zi=0; zi<zsize; zi++) {
00320 int zm, zp;
00321 zm = clamp_int(zi - 1, 0, zsize - 1);
00322 zp = clamp_int(zi + 1, 0, zsize - 1);
00323
00324 for (yi=0; yi<ysize; yi++) {
00325 int ym, yp;
00326 ym = clamp_int(yi - 1, 0, ysize - 1);
00327 yp = clamp_int(yi + 1, 0, ysize - 1);
00328
00329 row = (zi * xsize * ysize) + (yi * xsize);
00330 for (xi=0; xi<xsize; xi++) {
00331 int index = (row + xi) * 3;
00332 int xm, xp;
00333 xm = clamp_int(xi - 1, 0, xsize - 1);
00334 xp = clamp_int(xi + 1, 0, xsize - 1);
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 gradient[index ] =
00346 (voxel_value(xp, yi, zi) - voxel_value(xm, yi, zi)) * xs;
00347 gradient[index + 1] =
00348 (voxel_value(xi, yp, zi) - voxel_value(xi, ym, zi)) * ys;
00349 gradient[index + 2] =
00350 (voxel_value(xi, yi, zp) - voxel_value(xi, yi, zm)) * zs;
00351 }
00352 }
00353 }
00354 }
00355
00356
00358 void VolumetricData::voxel_gradient_safe(int x, int y, int z, float *grad) const {
00359 int xx, yy, zz;
00360 xx = (x > 0) ? ((x < xsize) ? x : xsize-1) : 0;
00361 yy = (y > 0) ? ((y < ysize) ? y : ysize-1) : 0;
00362 zz = (z > 0) ? ((z < zsize) ? z : zsize-1) : 0;
00363 int index = zz*xsize*ysize + yy*xsize + xx;
00364 grad[0] = gradient[index*3 ];
00365 grad[1] = gradient[index*3 + 1];
00366 grad[2] = gradient[index*3 + 2];
00367 }
00368
00369
00371 void VolumetricData::voxel_gradient_interpolate(const float *voxcoord, float *grad) const {
00372 float gtmpa[3], gtmpb[3];
00373 int x = (int) voxcoord[0];
00374 int y = (int) voxcoord[1];
00375 int z = (int) voxcoord[2];
00376 float xf = voxcoord[0] - x;
00377 float yf = voxcoord[1] - y;
00378 float zf = voxcoord[2] - z;
00379 float xlerpsa[3];
00380 float xlerpsb[3];
00381 float xlerpsc[3];
00382 float xlerpsd[3];
00383 float ylerpsa[3];
00384 float ylerpsb[3];
00385
00386 voxel_gradient_safe(x, y, z, gtmpa);
00387 voxel_gradient_safe(x+1, y, z, gtmpb);
00388 vec_lerp(xlerpsa, gtmpa, gtmpb, xf);
00389
00390 voxel_gradient_safe(x, y+1, z, gtmpa);
00391 voxel_gradient_safe(x+1, y+1, z, gtmpb);
00392 vec_lerp(xlerpsb, gtmpa, gtmpb, xf);
00393
00394 voxel_gradient_safe(x, y, z+1, gtmpa);
00395 voxel_gradient_safe(x+1, y, z+1, gtmpb);
00396 vec_lerp(xlerpsc, gtmpa, gtmpb, xf);
00397
00398 voxel_gradient_safe(x, y+1, z+1, gtmpa);
00399 voxel_gradient_safe(x+1, y+1, z+1, gtmpb);
00400 vec_lerp(xlerpsd, gtmpa, gtmpb, xf);
00401
00402 vec_lerp(ylerpsa, xlerpsa, xlerpsb, yf);
00403 vec_lerp(ylerpsb, xlerpsc, xlerpsd, yf);
00404
00405 vec_lerp(grad, ylerpsa, ylerpsb, zf);
00406 }
00407
00408
00410 void VolumetricData::voxel_gradient_from_coord(const float *coord, float *grad) const {
00411 int vx, vy, vz;
00412 float voxcoord[3];
00413 voxel_coord_from_cartesian_coord(coord, voxcoord, 1);
00414 vx = (int) voxcoord[0];
00415 vy = (int) voxcoord[1];
00416 vz = (int) voxcoord[2];
00417 voxel_gradient_safe(vx, vy, vz, grad);
00418 }
00419
00420
00422 void VolumetricData::voxel_gradient_interpolate_from_coord(const float *coord, float *grad) const {
00423 float voxcoord[3];
00424 voxel_coord_from_cartesian_coord(coord, voxcoord, 0);
00425
00426 if (voxcoord[0] < 0 || voxcoord[0] >= (xsize-1) ||
00427 voxcoord[1] < 0 || voxcoord[1] >= (ysize-1) ||
00428 voxcoord[2] < 0 || voxcoord[2] >= (zsize-1)) {
00429 grad[0] = NAN;
00430 grad[1] = NAN;
00431 grad[2] = NAN;
00432 return;
00433 }
00434
00435 voxel_gradient_interpolate(voxcoord, grad);
00436 }
00437
00438