00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 #include <stdio.h>
00010 #include <stdlib.h>
00011 #include <string.h>
00012 #include <math.h>
00013 #include "Inform.h"
00014 #include "utilities.h"
00015 
00016 #define ISOCONTOUR_INTERNAL 1
00017 #include "Isocontour.h"
00018 #include "VolumetricData.h"
00019 
00020 IsoContour::IsoContour(void) {}
00021 
00022 void IsoContour::clear(void) {
00023   numtriangles=0;
00024   v.clear();
00025   f.clear();
00026 }
00027 
00028 
00029 int IsoContour::compute(const VolumetricData *data, float isovalue, int step) {
00030   int x, y, z; 
00031   int tricount=0;
00032 
00033   vol=data;
00034 
00035   xax[0] = (float) (vol->xaxis[0] / ((float) (vol->xsize - 1)));
00036   xax[1] = (float) (vol->xaxis[1] / ((float) (vol->xsize - 1)));
00037   xax[2] = (float) (vol->xaxis[2] / ((float) (vol->xsize - 1)));
00038 
00039   yax[0] = (float) (vol->yaxis[0] / ((float) (vol->ysize - 1)));
00040   yax[1] = (float) (vol->yaxis[1] / ((float) (vol->ysize - 1)));
00041   yax[2] = (float) (vol->yaxis[2] / ((float) (vol->ysize - 1)));
00042 
00043   zax[0] = (float) (vol->zaxis[0] / ((float) (vol->zsize - 1)));
00044   zax[1] = (float) (vol->zaxis[1] / ((float) (vol->zsize - 1)));
00045   zax[2] = (float) (vol->zaxis[2] / ((float) (vol->zsize - 1)));
00046 
00047   for (z=0; z<(vol->zsize - step); z+=step) {
00048     for (y=0; y<(vol->ysize - step); y+=step) {
00049       for (x=0; x<(vol->xsize - step); x+=step) {
00050         tricount += DoCell(x, y, z, isovalue, step);
00051       }
00052     }
00053   }
00054 
00055   return 1;
00056 }
00057 
00058 
00059 
00060 int IsoContour::DoCell(int x, int y, int z, float isovalue, int step) {
00061   SQUARECELL gc;
00062   int addr, row, plane, rowstep, planestep, tricount;
00063   LINE tris[5];
00064 
00065   row = vol->xsize; 
00066   plane = vol->xsize * vol->ysize;
00067   addr = z*plane + y*row + x;
00068   rowstep = row*step;
00069   planestep = plane*step;
00070   
00071   gc.val[0] = vol->data[addr                             ];
00072   gc.val[1] = vol->data[addr + step                      ];
00073   gc.val[3] = vol->data[addr +        rowstep            ];
00074   gc.val[2] = vol->data[addr + step + rowstep            ];
00075   gc.val[4] = vol->data[addr +                  planestep];
00076   gc.val[5] = vol->data[addr + step +           planestep];
00077   gc.val[7] = vol->data[addr +        rowstep + planestep];
00078   gc.val[6] = vol->data[addr + step + rowstep + planestep];
00079 
00080   
00081 
00082 
00083 
00084   int cubeindex = 0;
00085   if (gc.val[0] < isovalue) cubeindex |= 1;
00086   if (gc.val[1] < isovalue) cubeindex |= 2;
00087   if (gc.val[2] < isovalue) cubeindex |= 4;
00088   if (gc.val[3] < isovalue) cubeindex |= 8;
00089   if (gc.val[4] < isovalue) cubeindex |= 16;
00090   if (gc.val[5] < isovalue) cubeindex |= 32;
00091   if (gc.val[6] < isovalue) cubeindex |= 64;
00092   if (gc.val[7] < isovalue) cubeindex |= 128;
00093 
00094   
00095   if (edgeTable[cubeindex] == 0)
00096     return(0);
00097   gc.cubeindex = cubeindex;
00098 
00099   gc.p[0].x = (float) x;
00100   gc.p[0].y = (float) y;
00101 
00102   gc.p[1].x = (float) x + step;
00103   gc.p[1].y = (float) y;
00104 
00105   gc.p[2].x = (float) x + step;
00106   gc.p[2].y = (float) y + step;
00107   
00108   gc.p[3].x = (float) x;
00109   gc.p[3].y = (float) y + step;
00110 
00111   
00112   
00113   
00114   tricount = Polygonise(gc, isovalue, (LINE *) &tris);
00115 
00116   if (tricount > 0) {
00117     int i;
00118 
00119     for (i=0; i<tricount; i++) {
00120       float xx, yy, zz;
00121 
00122       int tritmp = numtriangles * 3;
00123       f.append3(tritmp, tritmp+1, tritmp+2);
00124       numtriangles++;
00125 
00126       
00127       xx = tris[i].p[0].x;
00128       yy = tris[i].p[0].y;
00129       v.append3((float) vol->origin[0] + xx * xax[0] + yy * yax[0] + zz * zax[0],
00130                 (float) vol->origin[1] + xx * xax[1] + yy * yax[1] + zz * zax[1],
00131                 (float) vol->origin[2] + xx * xax[2] + yy * yax[2] + zz * zax[2]);
00132       xx = tris[i].p[1].x;
00133       yy = tris[i].p[1].y;
00134       v.append3((float) vol->origin[0] + xx * xax[0] + yy * yax[0] + zz * zax[0],
00135                 (float) vol->origin[1] + xx * xax[1] + yy * yax[1] + zz * zax[1],
00136                 (float) vol->origin[2] + xx * xax[2] + yy * yax[2] + zz * zax[2]);
00137       xx = tris[i].p[2].x;
00138       yy = tris[i].p[2].y;
00139       v.append3((float) vol->origin[0] + xx * xax[0] + yy * yax[0] + zz * zax[0],
00140                 (float) vol->origin[1] + xx * xax[1] + yy * yax[1] + zz * zax[1],
00141                 (float) vol->origin[2] + xx * xax[2] + yy * yax[2] + zz * zax[2]);
00142     }
00143   }
00144 
00145   return tricount;
00146 }
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 int IsoContour::Polygonise(const SQUARECELL grid, const float isolevel, LINE *triangles) {
00159    int i,ntriang;
00160    int cubeindex = grid.cubeindex;
00161    XY vertlist[12];
00162 
00163    
00164    if (edgeTable[cubeindex] & 1)
00165       VertexInterp(isolevel, grid, 0, 1, &vertlist[0]);
00166    if (edgeTable[cubeindex] & 2)
00167       VertexInterp(isolevel, grid, 1, 2, &vertlist[1]);
00168    if (edgeTable[cubeindex] & 4)
00169       VertexInterp(isolevel, grid, 2, 3, &vertlist[2]);
00170    if (edgeTable[cubeindex] & 8)
00171       VertexInterp(isolevel, grid, 3, 0, &vertlist[3]);
00172    if (edgeTable[cubeindex] & 16)
00173       VertexInterp(isolevel, grid, 4, 5, &vertlist[4]);
00174    if (edgeTable[cubeindex] & 32)
00175       VertexInterp(isolevel, grid, 5, 6, &vertlist[5]);
00176    if (edgeTable[cubeindex] & 64)
00177       VertexInterp(isolevel, grid, 6, 7, &vertlist[6]);
00178    if (edgeTable[cubeindex] & 128)
00179       VertexInterp(isolevel, grid, 7, 4, &vertlist[7]);
00180    if (edgeTable[cubeindex] & 256)
00181       VertexInterp(isolevel, grid, 0, 4, &vertlist[8]);
00182    if (edgeTable[cubeindex] & 512)
00183       VertexInterp(isolevel, grid, 1, 5, &vertlist[9]);
00184    if (edgeTable[cubeindex] & 1024)
00185       VertexInterp(isolevel, grid, 2, 6, &vertlist[10]);
00186    if (edgeTable[cubeindex] & 2048)
00187       VertexInterp(isolevel, grid, 3, 7, &vertlist[11]);
00188 
00189    
00190    ntriang = 0;
00191    for (i=0; lineTable[cubeindex][i]!=-1;i+=3) {
00192      triangles[ntriang].p[0] = vertlist[lineTable[cubeindex][i  ]];
00193      triangles[ntriang].p[1] = vertlist[lineTable[cubeindex][i+1]];
00194      triangles[ntriang].p[2] = vertlist[lineTable[cubeindex][i+2]];
00195      ntriang++;
00196    }
00197 
00198    return ntriang;
00199 }
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 void IsoContour::VertexInterp(float isolevel, const SQUARECELL grid, int ind1, int ind2, XY * vert) {
00209   float mu;
00210 
00211   XY p1 = grid.p[ind1];
00212   XY p2 = grid.p[ind2];
00213   float valp1 = grid.val[ind1];
00214   float valp2 = grid.val[ind2];
00215 
00216   if (fabs(isolevel-valp1) < 0.00001) {
00217     *vert = grid.p[ind1];
00218     return;
00219   }
00220 
00221   if (fabs(isolevel-valp2) < 0.00001) {
00222     *vert = grid.p[ind2];
00223     return;
00224   }
00225 
00226   if (fabs(valp1-valp2) < 0.00001) {
00227     *vert = grid.p[ind1];
00228     return;
00229   }
00230 
00231   mu = (isolevel - valp1) / (valp2 - valp1);
00232 
00233   vert->x = p1.x + mu * (p2.x - p1.x);
00234   vert->y = p1.y + mu * (p2.y - p1.y);
00235 }
00236