www.pudn.com > V3D_Viewer_1.01_SourceCode.zip > Histogram.cs


using System; 
using System.Collections.Generic; 
using System.Text; 
 
/* **** Histogram Transfer Function Selection ***** 
 *  
 * Code which I use to initialize and create the histogram window:  
 * - HistogramObj.SetWindows(vtkFormsWindowControlHistogram.GetRenderWindow()); 
 * - HistogramObj.renderHistogram(V3Dfile.VoxelData); 
 * - ConsoleText(HistogramObj.info); 
 * - HistogramObj.starteventloop(); 
 *  
 * Code which I use to get the transfer function for the Volume rendering: 
 * - RenderVolumeObj.setTransferFunction(HistogramObj.getTransferFunction()); 
 *  
 */ 
 
namespace V3D_Viewer 
{ 
    class Histogram 
    { 
        vtk.vtkRenderWindow renHist = new vtk.vtkRenderWindow(); 
        vtk.vtkRenderer ren1 = new vtk.vtkRenderer(); 
        vtk.vtkImageCanvasSource2D canvas = new vtk.vtkImageCanvasSource2D(); 
        vtk.vtkRenderWindowInteractor iren = new vtk.vtkRenderWindowInteractor(); 
        vtk.vtkImageData data = new vtk.vtkImageData(); 
 
        int width = 0; int height = 0; // Width and height of window 
        int numBins = 0; // Number of histogram bins 
        int npoints = 0; // Number of Selected Points 
        int[] pointsx = new int[50]; // Selected Points x coordinates 
        int[] pointsy = new int[50]; // Selected Points y coordinates 
        int[] pointsc = new int[50]; // Selected color; 
        int pointsel = -1; // Point mouse select 
        double rad = 5; // Size (radius) of selected points 
        double[] inputRange; // Minimum and Maximum value input data  
        double[,] colortable=new double[14,3] {{0.00, 0.00, 0.00}, {1.00, 1.00, 1.00}, {1.00, 0.00, 0.00}, {1.00, 1.00, 0.00}, {0.00, 1.00, 0.00}, {0.00, 1.00, 1.00},{0.00, 0.00, 1.00}, {1.00, 0.00, 1.00}, {0.50, 0.00, 0.00}, {0.50, 0.50, 0.00}, {0.00, 0.50, 0.00}, {0.00, 0.50, 0.50}, {0.00, 0.00, 0.50}, {0.50, 0.00, 0.50}}; 
 
        public string info = ""; // Text for debug purposes 
 
        // Function: Get render window from main class 
        public void SetWindows(vtk.vtkRenderWindow renHistt) 
        { 
            renHist=renHistt; 
        } 
 
        // Function: Calculate en render Histogram in window 
        public void renderHistogram(vtk.vtkImageData VoxelData) 
        { 
            // Get size of histogram window 
            int[] size=renHist.GetSize(); 
            width = size[0]; height = size[1]; 
             
             
            //Setup parameters histogram Accumulate Filter 
            numBins = width / 2; 
            inputRange = VoxelData.GetScalarRange(); 
            double origin = inputRange[0]; 
            double spacing = 1.0 * (inputRange[1] - origin) / numBins; 
             
            // Setup Accumulate filter 
            vtk.vtkImageAccumulate accumulate = new vtk.vtkImageAccumulate(); 
            accumulate.SetInput(VoxelData); //Get input voxeldata  
            accumulate.SetComponentExtent(0,numBins - 1,0,0,0,0); 
            accumulate.SetComponentOrigin(origin,0.0,0.0); 
            accumulate.SetComponentSpacing(spacing,1.0,1.0); 
             
            // Make Data object from Accumulated object  
            data = accumulate.GetOutput(); 
            data.Update(); 
 
            // Initialize first and last point of the transferfunction. 
            npoints = 2; 
            pointsx[0] = 0; pointsy[0] = 0; 
            pointsx[1] = width - 1; pointsy[1] = height - 1; 
            pointsc[0] = 1; pointsc[1] = 1; 
 
            // Draw the histogram in a canvas and add the transferfunction to it  
            drawhisto(); 
            drawcurve();             
             
            // Create a color table  
            vtk.vtkColorTransferFunction colorTransferFunction = new vtk.vtkColorTransferFunction(); 
            for (int i = 0; i < 14; i++) 
            { 
                colorTransferFunction.AddRGBPoint(i, colortable[i, 0], colortable[i, 1], colortable[i, 2]); 
            } 
 
 
 
                     
            // Use the color table to color the histogram window objects 
            vtk.vtkImageMapToColors sColors = new vtk.vtkImageMapToColors(); 
            sColors.SetInputConnection(canvas.GetOutputPort()); 
            sColors.SetLookupTable(colorTransferFunction); 
 
            // Convert the histogram image to a histogram imagemap 
            vtk.vtkImageMapper histmap = new vtk.vtkImageMapper(); 
            histmap.SetInputConnection(sColors.GetOutputPort()); 
            histmap.RenderToRectangleOn(); 
            histmap.SetColorWindow(256); 
            histmap.SetColorLevel(127); 
 
            // Create the actor needed to draw the histogram image 
            vtk.vtkActor2D imageactor = new vtk.vtkActor2D(); 
            imageactor.SetMapper(histmap); 
            imageactor.SetPosition(0, 0); // Fit the histogram to the window 
            imageactor.SetPosition2(1, 1); 
 
            // Add the Histogram Image Render to the window object 
            ren1.AddActor(imageactor); 
            ren1.SetViewport(0, 0, 1, 1); // Fit the histogram to the window 
            renHist.AddRenderer(ren1); 
             
            // Add a Window (mouse) interactor to the window 
            iren.SetRenderWindow(renHist); 
 
            // Add mouse events to the window 
            iren.RemoveObserver((uint)vtk.EventIds.LeftButtonPressEvent); 
            iren.AddObserver((uint)vtk.EventIds.LeftButtonPressEvent, new vtk.vtkDotNetCallback(LeftButtonPress)); 
 
            iren.RemoveObserver((uint)vtk.EventIds.LeftButtonReleaseEvent); 
            iren.AddObserver((uint)vtk.EventIds.LeftButtonReleaseEvent, new vtk.vtkDotNetCallback(LeftButtonRelease)); 
       
            iren.RemoveObserver((uint)vtk.EventIds.MouseMoveEvent); 
            iren.AddObserver((uint)vtk.EventIds.MouseMoveEvent, new vtk.vtkDotNetCallback(MouseMove)); 
 
            iren.RemoveObserver((uint)vtk.EventIds.RightButtonPressEvent); 
            iren.AddObserver((uint)vtk.EventIds.RightButtonPressEvent, new vtk.vtkDotNetCallback(RightButtonPress)); 
 
            iren.RemoveObserver((uint)vtk.EventIds.MiddleButtonPressEvent); 
            iren.AddObserver((uint)vtk.EventIds.MiddleButtonPressEvent, new vtk.vtkDotNetCallback(MiddleButtonPress)); 
 
            // Set the (display) update rate of the histogram 
            iren.SetStillUpdateRate(5); 
            iren.SetDesiredUpdateRate(5); 
 
            // Initialize interactor and render histogram 
            iren.Initialize(); 
            renHist.Render(); 
 
            // Debug output 
            info = "Histogram is created \r\n"; 
        } 
 
        // This Function converts the selected Points to a VTK transfer function 
        public vtk.vtkPiecewiseFunction getAlphaTransferFunction() 
        { 
            vtk.vtkPiecewiseFunction TransferFunction = new vtk.vtkPiecewiseFunction(); 
            double colorindex = 0; double alpha = 0; double per=0; 
            for (int i = 0; i < npoints; i++) 
            { 
                // Calulate color index and alpha from selected points 
                per = (double)pointsx[i] / (width - 1); 
                colorindex = (1 - per) * inputRange[0] + per * inputRange[1]; 
                alpha = (double)pointsy[i]/height; 
                TransferFunction.AddPoint(colorindex, alpha); 
            } 
            return TransferFunction; 
        } 
 
        public vtk.vtkColorTransferFunction getColorTransferFunction(bool enablealpha) 
        { 
             
            vtk.vtkColorTransferFunction TransferFunction = new vtk.vtkColorTransferFunction(); 
            double colorindex = 0; double alpha = 1; double per = 0; 
             
            for (int i = 0; i < npoints; i++) 
            { 
                // Calulate color index and alpha from selected points 
                per = (double)pointsx[i] / (width - 1); 
                colorindex = (1 - per) * inputRange[0] + per * inputRange[1]; 
                if(enablealpha) alpha = (double)pointsy[i] / height; 
                TransferFunction.AddRGBPoint(colorindex, alpha * colortable[pointsc[i], 0], alpha * colortable[pointsc[i], 1], alpha * colortable[pointsc[i], 2]); 
    
            } 
            return TransferFunction; 
        } 
 
        // Function to Start the Event Interactor Loop  
        public void starteventloop() 
        { 
            iren.Start(); 
        } 
 
        public void deleterender() 
        { 
            iren.Disable(); 
        } 
 
        // Function moves a selected point during mouse movement 
        public void MouseMove(vtk.vtkObject obj, uint eventId, Object data, IntPtr clientdata) 
        { 
            if (pointsel>-1) // Point selected 
            { 
                // Get x,y mouse position 
                int[] pos = iren.GetEventPosition(); 
                int x = pos[0]; int y = pos[1]; 
 
                // Limit mouse position to histogram window 
                if (x < 0) x = 0; else if (x > width - 1) x = width - 1;  
                if (y < 0) y = 0; else if (y > height- 1) y = height - 1; 
 
                // Set the x variable of the selected point to the mouse x 
                // (only if it's not the first or last point) 
                if ((pointsel > 0) && (pointsel < npoints - 1)) 
                { 
                    if (x <= pointsx[pointsel - 1]) x = pointsx[pointsel - 1] + 1; 
                    if (x >= pointsx[pointsel + 1]) x = pointsx[pointsel + 1] - 1; 
                    pointsx[pointsel] = x; 
                } 
                 
                // Set the y variable of the selected point 
                pointsy[pointsel] = y; 
                 
                // Draw and Render the histogram and transferfunction 
                drawhisto(); drawcurve(); 
                renHist.Render(); 
            } 
        } 
 
        // This function will find or create a selectedpoint 
        // on the position of the left button click 
        public void LeftButtonPress(vtk.vtkObject obj, uint eventId, Object data, IntPtr clientdata) 
        { 
            // Get x,y mouse position 
            int[] pos = iren.GetEventPosition(); 
            int x = pos[0]; int y = pos[1]; 
             
            // Calculate the distance from mouse position to the points 
            // a point near the mousecursor will be selected 
            double dist = 0; pointsel = -1; 
            for (int i = 0; i < npoints; i++) 
            { 
                dist = Math.Sqrt(Math.Pow((double)(pointsx[i] - x), 2) + Math.Pow((double)(pointsy[i] - y), 2)); 
                if (dist < rad) pointsel = i; 
            } 
 
            // If no point beneath the mouse cursor then this code will  
            // create a point. (if the mouse is close to the curve) 
            if (pointsel == -1)   
            { 
                double mindistv = 999; int mindistx= 0; int mindisty =0; 
                int[] linevector = makevector(); // Get an array with all curve pixels 
 
                // Find pixel of the curve near the mouse position.  
                for (int i = 0; i < width; i++) 
                { 
                    dist = Math.Sqrt(Math.Pow((double)(i - x), 2) + Math.Pow((double)(linevector[i] - y), 2)); 
                    if (dist < mindistv) 
                    { 
                        mindistv = dist; 
                        mindistx = i; 
                        mindisty = linevector[i]; 
                    } 
                } 
 
                // Add a new point (if mouse is position is near the curve) 
                if (mindistv < rad)  
                { 
                    int dp = npoints - 1; 
                    // Make room for the new point in the array 
                    while (mindistx < pointsx[dp]) 
                    { 
                        pointsx[dp + 1] = pointsx[dp]; 
                        pointsy[dp + 1] = pointsy[dp]; 
                        pointsc[dp + 1] = pointsc[dp]; 
                        dp--; 
                    } 
                    pointsx[dp+1] = mindistx; 
                    pointsy[dp+1] = mindisty; 
                    pointsc[dp + 1] = 1; 
                    pointsel = dp + 1; 
                    npoints++; 
 
                    // Draw and Render the histogram and transferfunction 
                    drawhisto(); drawcurve(); 
                    renHist.Render(); 
                } 
            } 
        } 
 
        public void MiddleButtonPress(vtk.vtkObject obj, uint eventId, Object data, IntPtr clientdata) 
        { 
            // Get x,y mouse position 
            int[] pos = iren.GetEventPosition(); 
            int x = pos[0]; int y = pos[1]; 
 
            // Find the nearest point 
            double dist = 0; pointsel = -1; 
            for (int i = 0; i < npoints; i++) 
            { 
                dist = Math.Sqrt(Math.Pow((double)(pointsx[i] - x), 2) + Math.Pow((double)(pointsy[i] - y), 2)); 
                if (dist < rad) pointsel = i; 
            } 
 
            // When point is found 
            if (pointsel > -1) 
            { 
                pointsc[pointsel]++; if (pointsc[pointsel]>13) pointsc[pointsel]=1; 
                drawhisto(); drawcurve(); 
                renHist.Render(); 
            } 
            pointsel = -1; 
        } 
 
        // Function will delete the point nearby on right mouse press  
        public void RightButtonPress(vtk.vtkObject obj, uint eventId, Object data, IntPtr clientdata) 
        { 
            // Get x,y mouse position 
            int[] pos = iren.GetEventPosition(); 
            int x = pos[0]; int y = pos[1]; 
 
            // Find the nearest point 
            double dist = 0; pointsel = -1; 
            for (int i = 1; i < npoints-1; i++) 
            { 
                dist = Math.Sqrt(Math.Pow((double)(pointsx[i] - x), 2) + Math.Pow((double)(pointsy[i] - y), 2)); 
                if (dist < rad) pointsel = i; 
            } 
 
            // When point is found, delete it. 
            if(pointsel > 0)  
            { 
                npoints--; 
                for (int i = pointsel; i < npoints; i++) 
                { 
                    pointsx[i] = pointsx[i + 1]; 
                    pointsy[i] = pointsy[i + 1]; 
                    pointsc[i] = pointsc[i + 1]; 
                } 
                 
                // Draw and Render the histogram and transferfunction 
                drawhisto(); drawcurve(); 
                renHist.Render(); 
            } 
            pointsel = -1; 
        } 
 
        // Create a vector with all line pixels (heights) 
        // (needed for new point creation) 
        int[] makevector() 
        { 
            int[] linevector=new int[width]; 
            int dp = 0; double perc = 0; int y = 0; 
 
            for (int i=0; i < width; i++) 
            { 
                if (i > pointsx[dp + 1]) dp++; 
                perc = ((double)(i - pointsx[dp])) / ((double)(pointsx[dp + 1] - pointsx[dp])); 
                y =(int)((double)pointsy[dp]*(1-perc)+(double)pointsy[dp+1]*(perc)); 
                linevector[i] = y; 
            } 
            return linevector; 
        } 
 
        // Deselect point add mouse release 
        public void LeftButtonRelease(vtk.vtkObject obj, uint eventId, Object data, IntPtr clientdata) 
        { 
            pointsel = -1; 
        } 
 
        void drawhisto() 
        { 
            // Initialize the canvas 
            canvas.SetExtent(0, width - 1, 0, height - 1, 0, 0); 
            canvas.SetDrawColor(0); 
            canvas.FillBox(0, width - 1, 0, height - 1); 
            canvas.SetDrawColor(2); 
 
            // Scale the histogram max to fit the window 
            double[] histRange = data.GetPointData().GetScalars().GetRange(); 
            double scale = 0.9 * height / Math.Log(histRange[1]); 
 
            // Draw all histogram bins 
            for (int idx = 0; idx < numBins; idx++) 
            { 
                double y = Math.Floor(Math.Log(data.GetScalarComponentAsDouble(idx, 0, 0, 0) + 1) * scale); 
                double x = (idx * 2); 
                canvas.DrawSegment((int)x, (int)0, (int)x, (int)y); 
            } 
        } 
 
        // This function draws the lines and point circles in the histogram image 
        void drawcurve() 
        { 
            for(int i=0;i