2016-06-16 13 views
1

Ich versuche, eine 3D-Darstellung eines Bildes zu schneiden. Folgende Faktoren ist bekannt:Slicing ein 3D-Bild

  • DimensionX
  • DimensionY
  • DimensionZ
  • Voxel []

Voxel [] ist ein Array von ushorts die Graustufen der Pixel darstellt.

Presentation of image

Jetzt muss ich es in alle möglichen Richtungen schneiden. Mit sagen wir x, y oder z.

Z-SliceY-SliceX-Slice

I Baum-Implementierungen für diese haben, aber sie haben ein Problem, sie arbeiten nicht mit Dimensionen, die nicht gleich sind. (Außer Get Z Slice, das funktioniert perfekt).

Dies sind die Methoden:

private ushort[] GetZSlice(int z, ushort[] voxels, int DimensionX, int DimensionY) 
{ 
    var res = new ushort[DimensionX * DimensionY]; 
    for(int j = 0; j < DimensionY; j++) 
    { 
     for(int i = 0; i < DimensionX; i++) 
     { 
      res[j*DimensionX + i] = voxels[z*DimensionX*DimensionY + j*DimensionX + i]; 
     } 
    } 
    return res; 
} 

Diese Methode einwandfrei funktioniert, ist es nicht mather wat i als die Dimension wählen.

Die nächsten beiden Methoden mit x oder y als Tiefe sind ein schwierigeres Problem.

private ushort[] GetYSlice(int y, ushort[] voxels, int DimensionX, int DimensionY, int DimensionZ) 
{ 
    var res = new ushort[DimensionX * DimensionZ]; 
    for(int i = 0; i < DimensionX; i++) 
    { 
     for(int j = 0; j < DimensionX; j++) 
     { 
      res[j + i*DimensionX] = voxels[j * DimensionZ * DimensionY + Y*DimensionZ + i] 
     } 
    } 
    return res; 
} 

private ushort[] GetXSlice(int x, ushort[voxels], int DimensionX, int DimensionY, int DimensionZ) 
{ 
    var res = new short[DimensionY * DimensionZ]; 
    for(int i = 0; i < DimensionY; i++) 
    { 
     for(int j = 0; j < DimensionZ; j++) 
     { 
      res[j + i*DimensionZ] = voxels[i*DimensionY + j*DimensionZ*DimensionX + x] 
     } 
    } 
    return res; 
} 

Wie könnte ich die letzten 2 Methoden verbessern, so dass es mit Dimensionen funktioniert, die nicht gleich sind?

Antwort

1

Warum nicht universelle Slice-Funktion mit Basisvektoren? Es wird weit weniger Code sein, den man verwalten kann.

Grundsätzlich haben Sie U,V Achsen je zugeordnet in X,Y oder Z. Und das Slice W ist die dritte ungenutzte Achse. So schlingen Sie einfach die U, V und lassen W wie es ist. Jeder U,V hat einen Basisvektor (ux,uy,uz), (vx,vy,vz), der die Inkrementänderung in x,y,z Koordinaten beschreibt.

I kodiert sie in meine LED Würfelclass in C++ ...

//--------------------------------------------------------------------------- 
class LED_cube 
    { 
public: 
    int xs,ys,zs,***map; 

    LED_cube()    { xs=0; ys=0; zs=0; map=NULL; } 
    LED_cube(LED_cube& a) { xs=0; ys=0; zs=0; map=NULL; *this=a; } 
    ~LED_cube()    { _free(); } 
    LED_cube* operator = (const LED_cube *a) { *this=*a; return this; } 
    LED_cube* operator = (const LED_cube &a); 
    void _free(); 
    void resize(int _xs,int _ys,int _zs); 
    void cls(int col);         // clear cube with col 0x00BBGGRR 
    void sphere(int x0,int y0,int z0,int r,int col); // draws sphere surface with col 0x00BBGGRR 
    void slice (char *uv,int slice,int col);   // draws (XY,XZ,YZ) slice with col 0x00BBGGRR 
    void glDraw();          // render cube by OpenGL as 1x1x1 cube at 0,0,0 
    }; 
//--------------------------------------------------------------------------- 
void LED_cube::slice(char *uv,int slice,int col) 
    { 
    // detect basis vectors from uv string 
    int ux=0,uy=0,uz=0,us=0; 
    int vx=0,vy=0,vz=0,vs=0; 
    int x=slice,y=slice,z=slice,u,v,x0,y0,z0; 
    if (uv[0]=='X') { x=0; ux=1; us=xs; } 
    if (uv[0]=='Y') { y=0; uy=1; us=ys; } 
    if (uv[0]=='Z') { z=0; uz=1; us=zs; } 
    if (uv[1]=='X') { x=0; vx=1; vs=xs; } 
    if (uv[1]=='Y') { y=0; vy=1; vs=ys; } 
    if (uv[1]=='Z') { z=0; vz=1; vs=zs; } 
    // render slice 
    if ((x>=0)&&(x<xs)&&(y>=0)&&(y<ys)&&(z>=0)&&(z<zs)) 
    for (u=0;u<us;u++,x+=ux,y+=uy,z+=uz) 
     { 
     x0=x; y0=y; z0=z; 
     for (v=0;v<vs;v++,x+=vx,y+=vy,z+=vz) 
      map[x][y][z]=col; 
     x=x0; y=y0; z=z0; 
     } 
    } 
//--------------------------------------------------------------------------- 

Wie Sie es ist sehr schön und einfach sehen kann ... und noch viel mehr optimiert werden. hier Nutzung und Ausgabebeispiel:

cube.resize(32,16,20); 
cube.cls(0x00202020); 
cube.slice("XY",5,0x000000FF); 
cube.slice("XZ",5,0x0000FF00); 
cube.slice("YZ",5,0x00FF0000); 
cube.glDraw(); 

example

Wie Sie bekam Ihre Voxel in 1D-Array gespeichert dann berechnen nur die Adresse von x,y,z. so map[x][y][z] wird Ihre voxels[(x*ys*zs)+(y*zs)+z] oder was auch immer Kombination von Achsenreihenfolge Sie haben. Dies kann vollständig in die Basisvektoren kodiert werden, so dass Sie du=(ux*ys*zs)+(uy*zs)+uz und dv=... haben und die Adresse direkt erhöhen können, ohne dass eine Multiplikation benötigt wird.

+0

Vielen Dank, das hat viel geholfen! – Gulpener