# -*- coding: utf-8 -*-
#
# $Date: 2013-03-15 17:48:48 +0900 (金, 15 3 2013) $
# $Rev: 69 $
#
from vtk.wx import wxVTKRenderWindow as vtkRender
import vtk
import wx

import math

import qspace
import define

CAMERA_VIEW_ANGLE = 45.0

class VTKPanelBase(vtkRender.wxVTKRenderWindow):
    def __init__(self, parent):
        vtkRender.wxVTKRenderWindow.__init__(self, parent, wx.ID_ANY)
        self.SetSize(parent.GetSize())
        self.Bind(wx.EVT_LEFT_DCLICK, self.LButtonDoubleClick)
        return

    def LButtonDoubleClick(self, event):
        return

class VTKPanel(VTKPanelBase):
    def __init__(self, parent):
        VTKPanelBase.__init__(self, parent)

        self.__gridData = dict()
        self.__detectorRegion = dict()
        self.__regionSurface = dict()
        self.__regionSurfaceContour = dict()
        self.__highlightingRegion = dict()
        self.__PSDsurface = dict()
        self.__PSDoutline = dict()
        self.__qPoints = dict()
        self.__etIsosurface = dict()
        self.__elasticScatteringLines = dict()
        self.__thinDetectableRegion = dict()
        self.__thinDetectableRegion['actor'] = dict()
        self.__thinDetectableRegion['grid'] = dict()

        self.__intensityGridData = dict()
        self.__intensitySurface = dict()
        self.__intensitySurfaceContour = dict()
        self.__intensityEtIsosurface = dict()

        self.__renderer = vtk.vtkRenderer()
        self.__renderer.SetViewport(0.0, 0.0, 1.0, 1.0)

        self.__colorFunc = vtk.vtkColorTransferFunction()
        self.__colorFunc.SetColorSpaceToHSV()
        self.__colorFunc.HSVWrapOff()

        self.__colorBar = vtk.vtkScalarBarActor()
        self.__renderer.AddActor2D(self.__colorBar)

        self.__createAxes()

        self.GetRenderWindow().AddRenderer(self.__renderer)

        # self.GetRenderWindow().SetAlphaBitPlanes(True)
        # self.GetRenderWindow().SetMultiSamples(0)
        # self.__renderer.SetUseDepthPeeling(True);
        # self.__renderer.SetOcclusionRatio(100)
        # self.__renderer.SetMaximumNumberOfPeels(0.1)

        self.__lastHighlightDetectorRegionName = None

        self.__mainFrame = self.GetParent()

        while not isinstance(self.__mainFrame, wx.Frame):
            self.__mainFrame = self.__mainFrame.GetParent()
            pass
        return

    def __removeActors(self, actors):
        for key in actors.keys():
            self.__renderer.RemoveActor(actors[key])
            pass
        return

    def __removeAllActors(self):
        self.__removeActors(self.__detectorRegion)
        self.__removeActors(self.__regionSurface)
        self.__removeActors(self.__regionSurfaceContour)
        self.__removeActors(self.__highlightingRegion)

        for key in self.__PSDsurface.keys():
            self.__removeActors(self.__PSDsurface[key])
            pass

        for key in self.__PSDoutline.keys():
            self.__removeActors(self.__PSDoutline[key])
            pass
        return

    def CreateDetectorRegionView(self, regionsData, scalarRange, properties):
        self.__removeAllActors()

        self.__gridData.clear()
        self.__detectorRegion.clear()
        self.__regionSurface.clear()
        self.__regionSurfaceContour.clear()
        self.__highlightingRegion.clear()
        self.__PSDsurface.clear()
        self.__PSDoutline.clear()

        for regionName in regionsData.keys():
            rawPoints = regionsData[regionName]['points']
            dimensions = regionsData[regionName]['dimensions']

            numberOfPoints = len(rawPoints) / 3

            array = vtk.vtkFloatArray()
            array.SetNumberOfComponents(3)
            array.SetNumberOfTuples(numberOfPoints)

            for i in xrange(0, len(rawPoints), 3):
                array.SetTuple3(i / 3, rawPoints[i], rawPoints[i + 1], rawPoints[i + 2])
                pass

            points = vtk.vtkPoints()
            points.SetNumberOfPoints(numberOfPoints)
            points.SetDataTypeToFloat()
            points.SetData(array)

            self.__gridData[regionName] = vtk.vtkStructuredGrid()
            self.__gridData[regionName].SetDimensions(dimensions[0], dimensions[1], dimensions[2])
            self.__gridData[regionName].SetPoints(points)

            rawPoints = regionsData[regionName]['etvals']

            array = vtk.vtkFloatArray()
            array.SetNumberOfComponents(1)
            array.SetNumberOfTuples(len(rawPoints))

            for i in xrange(0, len(rawPoints)):
                array.SetTuple1(i, rawPoints[i])
                pass

            array.SetName(define.ENERGY_TRANSFER)
            self.__gridData[regionName].GetPointData().AddArray(array)

            rawPoints = regionsData[regionName]['pxvals']

            array = vtk.vtkFloatArray()
            array.SetNumberOfComponents(1)
            array.SetNumberOfTuples(len(rawPoints))

            for i in xrange(0, len(rawPoints)):
                array.SetTuple1(i, rawPoints[i])
                pass

            array.SetName(define.PIXEL)
            self.__gridData[regionName].GetPointData().AddArray(array)

            filter = vtk.vtkStructuredGridOutlineFilter()
            filter.SetInput(self.__gridData[regionName])

            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInputConnection(filter.GetOutputPort())

            self.__detectorRegion[regionName] = vtk.vtkActor()
            self.__detectorRegion[regionName].SetMapper(mapper)
            self.__detectorRegion[regionName].VisibilityOff()

            self.__renderer.AddActor(self.__detectorRegion[regionName])

            mapper = vtk.vtkDataSetMapper()
            mapper.SetInput(self.__gridData[regionName])
            mapper.SetLookupTable(self.__colorFunc)
            mapper.SetScalarModeToUsePointFieldData()
            mapper.SelectColorArray(self.__mainFrame.GetScalarKind())

            self.__regionSurface[regionName] = vtk.vtkActor()
            self.__regionSurface[regionName].SetMapper(mapper)
            self.__regionSurface[regionName].VisibilityOff()

            self.__renderer.AddActor(self.__regionSurface[regionName])

            filter1 = vtk.vtkDataSetSurfaceFilter()
            filter1.SetInput(self.__gridData[regionName])

            filter2 = vtk.vtkBandedPolyDataContourFilter()
            filter2.SetInput(filter1.GetOutput())
            filter2.GenerateValues(11, scalarRange[0], scalarRange[1])
            filter2.GenerateContourEdgesOn()

            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInput(filter2.GetContourEdgesOutput())

            self.__regionSurfaceContour[regionName] = vtk.vtkActor()
            self.__regionSurfaceContour[regionName].SetMapper(mapper)
            self.__regionSurfaceContour[regionName].GetProperty().SetColor(0, 0, 0)
            self.__regionSurfaceContour[regionName].VisibilityOff()

            self.__renderer.AddActor(self.__regionSurfaceContour[regionName])

            mapper = vtk.vtkDataSetMapper()
            mapper.SetInput(self.__gridData[regionName])

            self.__highlightingRegion[regionName] = vtk.vtkActor()
            self.__highlightingRegion[regionName].SetMapper(mapper)
            self.__highlightingRegion[regionName].GetProperty().SetOpacity(0.5)
            self.__highlightingRegion[regionName].GetProperty().SetColor(0.0, 0.0, 1.0)
            self.__highlightingRegion[regionName].VisibilityOff()

            self.__renderer.AddActor(self.__highlightingRegion[regionName])

            self.__PSDsurface[regionName] = dict()
            self.__PSDoutline[regionName] = dict()

            self.CreatePSDShape(self.__gridData[regionName], properties[regionName], self.__PSDsurface[regionName], self.__PSDoutline[regionName])
            pass
        return

    def CreatePSDShape(self, sgrid, property, surfaceTable, outlineTable):
        dimensions = sgrid.GetDimensions()

        for i in xrange(property.nPSD):
            extractGrid = vtk.vtkExtractGrid()
            extractGrid.SetInput(sgrid)
            extractGrid.SetVOI(0, dimensions[0], 0, dimensions[1], i, i + 1)
            extractGrid.SetSampleRate(dimensions[0] - 1, 1, 1)

            mapper = vtk.vtkDataSetMapper()
            mapper.SetInputConnection(extractGrid.GetOutputPort())
            mapper.ScalarVisibilityOff()

            surfaceTable[property.PSD0 + i] = vtk.vtkActor()
            surfaceTable[property.PSD0 + i].SetMapper(mapper)
            surfaceTable[property.PSD0 + i].GetProperty().SetOpacity(0.25)
            surfaceTable[property.PSD0 + i].GetProperty().SetColor(0, 0, 1)
            surfaceTable[property.PSD0 + i].VisibilityOff()

            self.__renderer.AddActor(surfaceTable[property.PSD0 + i])

            filter = vtk.vtkStructuredGridOutlineFilter()
            filter.SetInputConnection(extractGrid.GetOutputPort())

            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInputConnection(filter.GetOutputPort())

            outlineTable[property.PSD0 + i] = vtk.vtkActor()
            outlineTable[property.PSD0 + i].SetMapper(mapper)
            outlineTable[property.PSD0 + i].GetProperty().SetColor(0.678, 0.847, 0.902)
            outlineTable[property.PSD0 + i].VisibilityOff()

            self.__renderer.AddActor(outlineTable[property.PSD0 + i])
            pass
        return

    def ShowDetectorRegion(self, regionName, isShown):
        if isShown:
            self.__detectorRegion[regionName].VisibilityOn()
            pass
        else:
            self.__detectorRegion[regionName].VisibilityOff()
            pass
        return

    def CreateIntensityRegionView(self, regionsData, scalarRange, intensityData):
        value = self.__mainFrame.GetFloatParameter(qspace.TAG_OBJ3D_ETVAL)
        width = self.__mainFrame.GetFloatParameter(qspace.TAG_OBJ3D_ETWIDTH)

        self.__removeActors(self.__intensitySurface)
        self.__removeActors(self.__intensitySurfaceContour)
        self.__removeActors(self.__intensityEtIsosurface)

        self.__intensityGridData.clear()
        self.__intensitySurface.clear()
        self.__intensitySurfaceContour.clear()
        self.__intensityEtIsosurface.clear()

        for regionName in regionsData.keys():
            if regionsData[regionName] == None:
                continue

            rawPoints = regionsData[regionName]['points']
            dimensions = regionsData[regionName]['dimensions']

            numberOfPoints = len(rawPoints) / 3

            array = vtk.vtkFloatArray()
            array.SetNumberOfComponents(3)
            array.SetNumberOfTuples(numberOfPoints)

            for i in xrange(0, len(rawPoints), 3):
                array.SetTuple3(i / 3, rawPoints[i], rawPoints[i + 1], rawPoints[i + 2])
                pass

            points = vtk.vtkPoints()
            points.SetNumberOfPoints(numberOfPoints)
            points.SetDataTypeToFloat()
            points.SetData(array)

            self.__intensityGridData[regionName] = vtk.vtkStructuredGrid()
            self.__intensityGridData[regionName].SetDimensions(dimensions[0], dimensions[1], dimensions[2])
            self.__intensityGridData[regionName].SetPoints(points)

            rawPoints = regionsData[regionName]['etvals']

            array = vtk.vtkFloatArray()
            array.SetNumberOfComponents(1)
            array.SetNumberOfTuples(len(rawPoints))
            array.SetName(define.ENERGY_TRANSFER)

            for i in xrange(0, len(rawPoints)):
                array.SetTuple1(i, rawPoints[i])
                pass

            self.__intensityGridData[regionName].GetPointData().AddArray(array)

            rawPoints = regionsData[regionName]['pxvals']

            array = vtk.vtkFloatArray()
            array.SetNumberOfComponents(1)
            array.SetNumberOfTuples(len(rawPoints))
            array.SetName(define.PIXEL)

            for i in xrange(0, len(rawPoints)):
                array.SetTuple1(i, rawPoints[i])
                pass

            self.__intensityGridData[regionName].GetPointData().AddArray(array)

            intensity = regionsData[regionName]['raw data']
            size = intensity.size
            rawData = intensity.transpose().reshape(size)

            array = vtk.vtkFloatArray()
            array.SetNumberOfComponents(1)
            array.SetNumberOfTuples(size)
            array.SetName(define.DETECT_INTENSITY)

            for i in xrange(0, len(rawData)):
                array.SetTuple1(i, rawData[i])
                pass

            self.__intensityGridData[regionName].GetCellData().AddArray(array)

            mapper = vtk.vtkDataSetMapper()
            mapper.SetInput(self.__intensityGridData[regionName])
            mapper.SetLookupTable(self.__colorFunc)
            mapper.SetScalarModeToUseCellFieldData()
            mapper.SelectColorArray(self.__mainFrame.GetScalarKind())

            self.__intensitySurface[regionName] = vtk.vtkActor()
            self.__intensitySurface[regionName].SetMapper(mapper)
            self.__intensitySurface[regionName].VisibilityOff()

            self.__renderer.AddActor(self.__intensitySurface[regionName])

            filter1 = vtk.vtkDataSetSurfaceFilter()
            filter1.SetInput(self.__intensityGridData[regionName])

            filter2 = vtk.vtkBandedPolyDataContourFilter()
            filter2.SetInput(filter1.GetOutput())
            filter2.GenerateValues(11, scalarRange[0], scalarRange[1])
            filter2.GenerateContourEdgesOn()

            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInput(filter2.GetContourEdgesOutput())

            self.__intensitySurfaceContour[regionName] = vtk.vtkActor()
            self.__intensitySurfaceContour[regionName].SetMapper(mapper)
            self.__intensitySurfaceContour[regionName].GetProperty().SetColor(0, 0, 0)
            self.__intensitySurfaceContour[regionName].VisibilityOff()

            self.__renderer.AddActor(self.__intensitySurfaceContour[regionName])

            polyData = vtk.vtkAppendPolyData()

            for et in [value - 0.5 * width - 1.0e-12,
                       value + 0.5 * width + 1.0e-12]:
                for index in xrange(len(intensityData) - 1):
                    if intensityData[index] <= et < intensityData[index + 1]:
                        break
                    pass

                voi = vtk.vtkExtractGrid()
                voi.SetVOI(index, index + 1, 0, dimensions[1], 0, dimensions[2])
                voi.SetInput(self.__intensityGridData[regionName])

                filter = vtk.vtkMarchingContourFilter()
                filter.SetInput(voi.GetOutput())
                filter.SetNumberOfContours(1)
                filter.SetValue(0, et)

                polyData.AddInputConnection(filter.GetOutputPort())
                pass

            normals = vtk.vtkPolyDataNormals()
            normals.SetInputConnection(polyData.GetOutputPort())

            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInputConnection(normals.GetOutputPort())
            mapper.SetScalarModeToUseCellFieldData()
            mapper.ColorByArrayComponent(define.DETECT_INTENSITY, 0)
            mapper.SetLookupTable(self.__colorFunc)
            mapper.InterpolateScalarsBeforeMappingOn()

            self.__intensityEtIsosurface[regionName] = vtk.vtkActor()
            self.__intensityEtIsosurface[regionName].SetMapper(mapper)
            self.__intensityEtIsosurface[regionName].VisibilityOff()

            self.__renderer.AddActor(self.__intensityEtIsosurface[regionName])
            pass
        return

    def CreateQPoints(self, points, radius):
        self.__removeActors(self.__qPoints)

        self.__qPoints.clear()

        sphere = vtk.vtkSphereSource()
        sphere.SetRadius(radius)
        sphere.SetPhiResolution(6)
        sphere.SetThetaResolution(6)

        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(sphere.GetOutputPort())

        for i in xrange(0, len(points)):
            actor = vtk.vtkActor()
            actor.SetMapper(mapper)
            actor.VisibilityOff()

            if points[i].position[0] == 0.0 and points[i].position[1] == 0.0 and points[i].position[2] == 0.0:
                actor.GetProperty().SetColor(0.0, 1.0, 0.0)
                pass
            else:
                actor.GetProperty().SetColor(1.0, 1.0, 1.0)
                pass

            actor.PickableOn()
            actor.SetPosition(points[i].position[0], points[i].position[1], points[i].position[2])

            self.__qPoints[points[i].GetIndexString()] = actor
            self.__renderer.AddActor(actor)
            pass
        return

    def SelectedQPoint(self, key, qPoint):
        if key not in self.__qPoints:
            return

        actor = self.__qPoints[key]

        if qPoint.IsInside():
            actor.GetProperty().SetColor(1.0, 0.0, 0.0)
            pass
        else:
            actor.GetProperty().SetColor(1.0, 0.647, 0.0)
            pass

        actor.VisibilityOn()
        return

    def ShowQPoint(self, isShow):
        for key in self.__qPoints.keys():
            actor = self.__qPoints[key]

            if isShow:
                actor.VisibilityOn()
                pass
            else:
                actor.VisibilityOff()
                pass
            pass
        return

    def ShowDetectorRegionHighlight(self, name):
        if self.__lastHighlightDetectorRegionName:
            self.__highlightingRegion[self.__lastHighlightDetectorRegionName].VisibilityOff()
            pass

        self.__lastHighlightDetectorRegionName = name
        self.__highlightingRegion[name].VisibilityOn()
        return

    def HideDetectorRegionHighlight(self):
        if self.__lastHighlightDetectorRegionName:
            self.__highlightingRegion[self.__lastHighlightDetectorRegionName].VisibilityOff()
            self.__lastHighlightDetectorRegionName = None
            pass
        return

    def ShowDetectorSurface(self, regionName, paintSurface, drawContour):
        if self.__mainFrame.GetScalarKind() == define.ENERGY_TRANSFER:
            gridData = self.__gridData
            surfaceActors = self.__regionSurface
            surfaceContourActors = self.__regionSurfaceContour
            pass
        else:
            if regionName not in self.__intensitySurface:
                return

            gridData = self.__intensityGridData
            surfaceActors = self.__intensitySurface
            surfaceContourActors = self.__intensitySurfaceContour
            pass

        if paintSurface:
            gridData[regionName].GetPointData().SetActiveScalars(define.ENERGY_TRANSFER)
            surfaceActors[regionName].VisibilityOn()

            if drawContour:
                surfaceContourActors[regionName].VisibilityOn()
                pass
            else:
                if surfaceContourActors[regionName].GetVisibility():
                    gridData[regionName].GetPointData().SetActiveScalars(None)
                    surfaceContourActors[regionName].VisibilityOff()
                    pass
                pass
            pass
        else:
            gridData[regionName].GetPointData().SetActiveScalars(None)
            surfaceActors[regionName].VisibilityOff()

            if surfaceContourActors[regionName].GetVisibility():
                surfaceContourActors[regionName].VisibilityOff()
                pass
            pass
        return

    def DeselectedQPoint(self, key, isShow):
        if key not in self.__qPoints:
            return

        actor = self.__qPoints[key]

        position = actor.GetPosition()
        if position[0] == 0.0 and position[1] == 0.0 and position[2] == 0.0:
            actor.GetProperty().SetColor(0.0, 1.0, 0.0)
            pass
        else:
            actor.GetProperty().SetColor(1.0, 1.0, 1.0)
            pass

        if not isShow:
            actor.VisibilityOff()
            pass
        return

    def CreateEtIsosurface(self):
        value = self.__mainFrame.GetFloatParameter(qspace.TAG_OBJ3D_ETVAL)
        width = self.__mainFrame.GetFloatParameter(qspace.TAG_OBJ3D_ETWIDTH)

        self.__removeActors(self.__etIsosurface)

        self.__etIsosurface.clear()

        for regionName in self.__gridData.keys():
            filter = vtk.vtkMarchingContourFilter()
            filter.SetInput(self.__gridData[regionName])
            filter.SetNumberOfContours(2)
            filter.SetValue(0, value - 0.5 * width - 1.0e-12)
            filter.SetValue(1, value + 0.5 * width + 1.0e-12)

            normals = vtk.vtkPolyDataNormals()
            normals.SetInputConnection(filter.GetOutputPort())

            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInputConnection(normals.GetOutputPort())
            mapper.SetScalarModeToUsePointFieldData()
            mapper.ColorByArrayComponent(define.ENERGY_TRANSFER, 0)
            mapper.SetLookupTable(self.__colorFunc)
            mapper.InterpolateScalarsBeforeMappingOn()

            self.__etIsosurface[regionName] = vtk.vtkActor()
            self.__etIsosurface[regionName].SetMapper(mapper)
            self.__etIsosurface[regionName].VisibilityOff()

            self.__renderer.AddActor(self.__etIsosurface[regionName])
            pass
        return

    def ShowEtIsosurface(self, regionName, isShow):
        if self.__mainFrame.GetScalarKind() == define.ENERGY_TRANSFER:
            gridData = self.__gridData
            etIsosurfaceActors = self.__etIsosurface
            pass
        else:
            if regionName not in self.__intensityEtIsosurface:
                return

            gridData = self.__intensityGridData
            etIsosurfaceActors = self.__intensityEtIsosurface
            pass

        if isShow:
            gridData[regionName].GetPointData().SetActiveScalars(define.ENERGY_TRANSFER)
            etIsosurfaceActors[regionName].VisibilityOn()
            pass
        else:
            gridData[regionName].GetPointData().SetActiveScalars(None)
            etIsosurfaceActors[regionName].VisibilityOff()
            pass
        return

    def CreateElasticScatteringLines(self):
        self.__removeActors(self.__elasticScatteringLines)

        self.__elasticScatteringLines.clear()

        for regionName in self.__gridData.keys():
            grid = vtk.vtkStructuredGrid()
            grid.ShallowCopy(self.__gridData[regionName])
            grid.GetPointData().SetActiveScalars(define.ENERGY_TRANSFER)

            filter1 = vtk.vtkDataSetSurfaceFilter()
            filter1.UseStripsOn()
            filter1.SetInput(grid)

            filter2 = vtk.vtkBandedPolyDataContourFilter()
            filter2.SetInput(filter1.GetOutput())
            filter2.SetNumberOfContours(1)
            filter2.SetValue(0, 1.0e-12)
            filter2.GenerateContourEdgesOn()

            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInput(filter2.GetContourEdgesOutput())

            self.__elasticScatteringLines[regionName] = vtk.vtkActor()
            self.__elasticScatteringLines[regionName].SetMapper(mapper)
            self.__elasticScatteringLines[regionName].GetProperty().SetLineWidth(3.0)
            self.__elasticScatteringLines[regionName].VisibilityOff()

            self.__renderer.AddActor(self.__elasticScatteringLines[regionName])
            pass
        return

    def ShowElasticScatteringLine(self, regionName, isShow):
        if isShow:
            self.__elasticScatteringLines[regionName].VisibilityOn()
            pass
        else:
            self.__elasticScatteringLines[regionName].VisibilityOff()
            pass
        return

    def __CreateAxis(self, point, color, label):
        # Create input point data.
        points = vtk.vtkPoints()
        points.InsertPoint(0, (0, 0, 0))

        cellArray = vtk.vtkCellArray()
        cellArray.InsertNextCell(1)
        cellArray.InsertCellPoint(0)

        polyData = vtk.vtkPolyData()
        polyData.SetPoints(points)
        polyData.SetPolys(cellArray)

        # Orient the glyphs as per vectors.
        vector = vtk.vtkFloatArray()
        vector.SetNumberOfComponents(3)
        vector.InsertTuple3(0, point[0], point[1], point[2])

        polyData.GetPointData().SetVectors(vector)
        arrow = vtk.vtkArrowSource()

        # The glyph filter.
        glyph = vtk.vtkGlyph3D()
        glyph.SetVectorModeToUseVector()
        glyph.SetScaleModeToScaleByVector()
        glyph.SetInput(polyData)
        glyph.SetSource(arrow.GetOutput())

        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(glyph.GetOutputPort())

        axisActor = vtk.vtkActor()
        axisActor.SetMapper(mapper)
        axisActor.GetProperty().SetColor(color)
        axisActor.VisibilityOff()

        self.__renderer.AddActor(axisActor)

        # Axes label
        text = vtk.vtkVectorText()
        text.SetText(label)

        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(text.GetOutputPort())

        axisLabelActor = vtk.vtkFollower()
        axisLabelActor.SetMapper(mapper)
        axisLabelActor.SetScale(0.1, 0.1, 0.1)
        axisLabelActor.SetPosition(point[0] * 1.0, point[1] * 1.0, point[2] * 1.0)
        axisLabelActor.SetCamera(self.__renderer.GetActiveCamera())
        axisLabelActor.VisibilityOff()

        self.__renderer.AddActor(axisLabelActor)
        return (axisActor, axisLabelActor)

    def CreateCell(self, ra, rb, rc):
        hexa = vtk.vtkHexahedron()
        for i in xrange(8):
            hexa.GetPointIds().SetId(i, i)
            pass

        sgrid = vtk.vtkUnstructuredGrid()
        sgrid.Allocate(1, 1)
        sgrid.InsertNextCell(hexa.GetCellType(), hexa.GetPointIds())

        self.__cellActor = vtk.vtkActor()
        self.__cellActor.VisibilityOff()

        self.__renderer.AddActor(self.__cellActor)

        points = vtk.vtkPoints()
        points.InsertPoint(0, 0, 0, 0)
        points.InsertPoint(1, ra[0], ra[1], ra[2])
        points.InsertPoint(2, ra[0] + rb[0],
                              ra[1] + rb[1],
                              ra[2] + rb[2])
        points.InsertPoint(3, rb[0], rb[1], rb[2])
        points.InsertPoint(4, rc[0], rc[1], rc[2])
        points.InsertPoint(5, ra[0] + rc[0],
                              ra[1] + rc[1],
                              ra[2] + rc[2])
        points.InsertPoint(6, ra[0] + rb[0] + rc[0],
                              ra[1] + rb[1] + rc[1],
                              ra[2] + rb[2] + rc[2])
        points.InsertPoint(7, rb[0] + rc[0],
                              rb[1] + rc[1],
                              rb[2] + rc[2])
        sgrid.SetPoints(points)

        mapper = vtk.vtkDataSetMapper()
        mapper.SetInput(sgrid)

        self.__cellActor.SetMapper(mapper)
        self.__cellActor.GetProperty().SetOpacity(0.25)

        (self.__cellAxesA, self.__cellLabelA) = self.__CreateAxis(ra, (1, 0, 0), 'a')
        (self.__cellAxesB, self.__cellLabelB) = self.__CreateAxis(rb, (0, 0, 1), 'b')
        (self.__cellAxesC, self.__cellLabelC) = self.__CreateAxis(rc, (0, 1, 0), 'c')
        return

    def __UpdateAxis(self, point, axisActor, axisLabelActor):
        mapper = axisActor.GetMapper()

        # Create input point data.
        points = vtk.vtkPoints()
        points.InsertPoint(0, (0, 0, 0))

        cellArray = vtk.vtkCellArray()
        cellArray.InsertNextCell(1)
        cellArray.InsertCellPoint(0)

        polyData = vtk.vtkPolyData()
        polyData.SetPoints(points)
        polyData.SetPolys(cellArray)

        # Orient the glyphs as per vectors.
        vector = vtk.vtkFloatArray()
        vector.SetNumberOfComponents(3)
        vector.InsertTuple3(0, point[0], point[1], point[2])

        polyData.GetPointData().SetVectors(vector)
        arrow = vtk.vtkArrowSource()

        # The glyph filter.
        glyph = vtk.vtkGlyph3D()
        glyph.SetVectorModeToUseVector()
        glyph.SetScaleModeToScaleByVector()
        glyph.SetInput(polyData)
        glyph.SetSource(arrow.GetOutput())

        mapper.SetInputConnection(glyph.GetOutputPort())

        # Axes label
        axisLabelActor.SetPosition(point[0] * 1.0, point[1] * 1.0, point[2] * 1.0)
        return

    def UpdateCell(self, ra, rb, rc):
        mapper = self.__cellActor.GetMapper()
        sgrid = mapper.GetInput()

        points = vtk.vtkPoints()
        points.InsertPoint(0, 0, 0, 0)
        points.InsertPoint(1, ra[0], ra[1], ra[2])
        points.InsertPoint(2, ra[0] + rb[0],
                              ra[1] + rb[1],
                              ra[2] + rb[2])
        points.InsertPoint(3, rb[0], rb[1], rb[2])
        points.InsertPoint(4, rc[0], rc[1], rc[2])
        points.InsertPoint(5, ra[0] + rc[0],
                              ra[1] + rc[1],
                              ra[2] + rc[2])
        points.InsertPoint(6, ra[0] + rb[0] + rc[0],
                              ra[1] + rb[1] + rc[1],
                              ra[2] + rb[2] + rc[2])
        points.InsertPoint(7, rb[0] + rc[0],
                              rb[1] + rc[1],
                              rb[2] + rc[2])
        sgrid.SetPoints(points)

        self.__UpdateAxis(ra, self.__cellAxesA, self.__cellLabelA)
        self.__UpdateAxis(rb, self.__cellAxesB, self.__cellLabelB)
        self.__UpdateAxis(rc, self.__cellAxesC, self.__cellLabelC)
        return

    def ShowCell(self, isShow):
        if isShow:
            self.__cellActor.VisibilityOn()

            self.__cellAxesA.VisibilityOn()
            self.__cellAxesB.VisibilityOn()
            self.__cellAxesC.VisibilityOn()

            self.__cellLabelA.VisibilityOn()
            self.__cellLabelB.VisibilityOn()
            self.__cellLabelC.VisibilityOn()
            pass
        else:
            self.__cellActor.VisibilityOff()

            self.__cellAxesA.VisibilityOff()
            self.__cellAxesB.VisibilityOff()
            self.__cellAxesC.VisibilityOff()

            self.__cellLabelA.VisibilityOff()
            self.__cellLabelB.VisibilityOff()
            self.__cellLabelC.VisibilityOff()
            pass
        return

    def CreateRotationGuide(self):
        self.__rotationAxisGuide = dict()
        self.__rotationAxisGuideArcSource = dict()
        self.__rotationAxisGuideMappter = dict()
        self.__rotationAxisGuideLabel = dict()

        count = 0
        for degree in xrange(-180, 180, 10):
            self.__rotationAxisGuideArcSource[degree] = vtk.vtkArcSource()

            filter = vtk.vtkTubeFilter()
            filter.SetInput(self.__rotationAxisGuideArcSource[degree].GetOutput())
            filter.SetRadius(0.02)
            filter.SetNumberOfSides(6)

            self.__rotationAxisGuideMappter[degree] = vtk.vtkPolyDataMapper()
            self.__rotationAxisGuideMappter[degree].SetInputConnection(filter.GetOutputPort())

            self.__rotationAxisGuide[degree] = vtk.vtkActor()
            self.__rotationAxisGuide[degree].VisibilityOff()
            self.__rotationAxisGuide[degree].SetMapper(self.__rotationAxisGuideMappter[degree])

            if count % 2 == 0:
                self.__rotationAxisGuide[degree].GetProperty().SetColor(1, 1, 1)
                pass
            else:
                self.__rotationAxisGuide[degree].GetProperty().SetColor(1, 0, 0)
                pass

            self.__renderer.AddActor(self.__rotationAxisGuide[degree])

            count += 1

            text = vtk.vtkVectorText()
            text.SetText(' ' + str(degree))

            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInputConnection(text.GetOutputPort())

            self.__rotationAxisGuideLabel[degree] = vtk.vtkFollower()
            self.__rotationAxisGuideLabel[degree].SetScale(0.07, 0.07, 0.07)
            self.__rotationAxisGuideLabel[degree].SetCamera(self.__renderer.GetActiveCamera())
            self.__rotationAxisGuideLabel[degree].SetMapper(mapper)
            self.__rotationAxisGuideLabel[degree].VisibilityOff()

            self.__renderer.AddActor(self.__rotationAxisGuideLabel[degree])
            pass
        return

    def SetRotationGuide(self, axisType, psi_orig, chi_orig, phi_orig, ra_orig, rb_orig, rc_orig, qPoint):
        xc = yc = zc = 0.0
        endPoints = dict()

        for degree in xrange(-180, 180, 10):
            theta = math.radians(degree)

            psi = psi_orig
            chi = chi_orig
            phi = phi_orig

            if axisType == 'psi':
                psi = theta
                pass
            elif axisType == 'chi':
                chi = theta
                pass
            elif axisType == 'phi':
                phi = theta
                pass

            matrix = GetRotationMatrix(psi, chi, phi)

            ra = matrix.TransformPoint(ra_orig)
            rb = matrix.TransformPoint(rb_orig)
            rc = matrix.TransformPoint(rc_orig)

            qx = ra[0] * qPoint.index[0] + rb[0] * qPoint.index[1] + rc[0] * qPoint.index[2]
            qy = ra[1] * qPoint.index[0] + rb[1] * qPoint.index[1] + rc[1] * qPoint.index[2]
            qz = ra[2] * qPoint.index[0] + rb[2] * qPoint.index[1] + rc[2] * qPoint.index[2]

            xc += qx / 36
            yc += qy / 36
            zc += qz / 36

            endPoints[degree] = [qx, qy, qz]
            self.__rotationAxisGuideLabel[degree].SetPosition(endPoints[degree])
            pass

        for degree1 in xrange(-180, 180, 10):
            if degree1 < 170:
                degree2 = degree1 + 10
                pass
            else:
                degree2 = -180
                pass

            self.__rotationAxisGuideArcSource[degree1].SetCenter(xc, yc, zc)
            self.__rotationAxisGuideArcSource[degree1].SetPoint1(endPoints[degree1])
            self.__rotationAxisGuideArcSource[degree1].SetPoint2(endPoints[degree2])
            self.__rotationAxisGuideArcSource[degree1].SetResolution(100)
            pass
        return
            
    def ShowRotationGuide(self, isShow):
        for degree in self.__rotationAxisGuide.keys():
            if isShow:
                self.__rotationAxisGuide[degree].VisibilityOn()
                self.__rotationAxisGuideLabel[degree].VisibilityOn()
                pass
            else:
                self.__rotationAxisGuide[degree].VisibilityOff()
                self.__rotationAxisGuideLabel[degree].VisibilityOff()
                pass
            pass
        return

    def CreatePixelIsosurface(self):
        self.__pixelIsosurface = dict()

        for regionName in self.__gridData.keys():
            self.__pixelIsosurface[regionName] = vtk.vtkActor()
            self.__renderer.AddActor(self.__pixelIsosurface[regionName])
            self.__pixelIsosurface[regionName].VisibilityOff()
            pass
        return

    def SetPixelIsosurface(self, regionName, dataType, pixel):
        grid = vtk.vtkStructuredGrid()
        grid.ShallowCopy(self.__gridData[regionName])
        grid.GetPointData().SetActiveScalars(define.PIXEL)

        dimensions = self.__gridData[regionName].GetDimensions()

        extraGrid = vtk.vtkExtractGrid()
        extraGrid.SetVOI(0, dimensions[0], pixel, pixel + 1, 0, dimensions[2])
        extraGrid.SetInput(grid)

        filter = vtk.vtkMarchingContourFilter()
        filter.SetInput(extraGrid.GetOutput())
        filter.SetNumberOfContours(1)
        filter.SetValue(0, pixel + 0.5)

        normals = vtk.vtkPolyDataNormals()
        normals.SetInputConnection(filter.GetOutputPort())

        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(normals.GetOutputPort())

        if dataType == define.ENERGY_TRANSFER:
            mapper.SetScalarModeToUsePointFieldData()
            pass
        else:
            mapper.SetScalarModeToUseCellFieldData()
            pass

        mapper.ColorByArrayComponent(dataType, 0)
        mapper.SetLookupTable(self.__colorFunc)

        self.__pixelIsosurface[regionName].SetMapper(mapper)
        self.__pixelIsosurface[regionName].VisibilityOn()
        return

    def ShowPixelIsosurface(self, regionName, isShow):
        if isShow:
            self.__pixelIsosurface[regionName].VisibilityOn()
            pass
        else:
            self.__pixelIsosurface[regionName].VisibilityOff()
            pass
        return

    def CreateLatticeAxes(self, rotates, size):
        self.__latticeAxes = [dict(), dict(), dict()]

        for i in xrange(3):
            import vector

            range = min(int(math.ceil(size / vector.GetNorm(rotates[i]))), 5)

            pos = vector.GetMultiplyVector(rotates[i], range)

            lineSource = vtk.vtkLineSource()
            lineSource.SetPoint1(vector.GetMultiplyVector(pos, -1))
            lineSource.SetPoint2(pos)

            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInputConnection(lineSource.GetOutputPort())

            axis = self.__latticeAxes[i]
            axis['line'] = vtk.vtkActor()
            axis['line'].VisibilityOff()
            axis['line'].SetMapper(mapper)

            self.__renderer.AddActor(axis['line'])

            axis['ticks'] = dict()
            axis['label'] = dict()

            for j in xrange(-range, range + 1):
                lineSource = vtk.vtkLineSource()
                lineSource.SetPoint1(0.0, 0.0, 0.0)
                lineSource.SetPoint2(0.1, 0.0, 0.0)

                mapper = vtk.vtkPolyDataMapper()
                mapper.SetInputConnection(lineSource.GetOutputPort())

                pos = vector.GetMultiplyVector(rotates[i], j)

                axis['ticks'][j] = vtk.vtkFollower()
                axis['ticks'][j].SetMapper(mapper)
                axis['ticks'][j].SetCamera(self.__renderer.GetActiveCamera())
                axis['ticks'][j].SetPosition(pos)
                axis['ticks'][j].VisibilityOff()

                self.__renderer.AddActor(axis['ticks'][j])

                text = vtk.vtkVectorText()
                text.SetText(str(j))

                mapper = vtk.vtkPolyDataMapper()
                mapper.SetInputConnection(text.GetOutputPort())

                axis['label'][j] = vtk.vtkFollower()
                axis['label'][j].SetMapper(mapper)
                axis['label'][j].SetScale(0.2, 0.2, 0.2)
                axis['label'][j].SetCamera(self.__renderer.GetActiveCamera())
                axis['label'][j].SetPosition(pos[0], pos[1], pos[2] - 0.05)
                axis['label'][j].VisibilityOff()

                self.__renderer.AddActor(axis['label'][j])
                pass
            pass
        return

    def UpdateLatticeAxes(self, rotates, size):
        for i in xrange(3):
            import vector

            range = min(int(math.ceil(size / vector.GetNorm(rotates[i]))), 5)

            pos = vector.GetMultiplyVector(rotates[i], range)

            lineSource = vtk.vtkLineSource()
            lineSource.SetPoint1(vector.GetMultiplyVector(pos, -1))
            lineSource.SetPoint2(pos)

            axis = self.__latticeAxes[i]
            axis['line'].GetMapper().SetInputConnection(lineSource.GetOutputPort())

            for j in xrange(-range, range + 1):
                pos = vector.GetMultiplyVector(rotates[i], j)

                axis['ticks'][j].SetPosition(pos)
                axis['label'][j].SetPosition(pos[0], pos[1], pos[2] - 0.05)
                pass
            pass
        return

    def ShowLatticeAxes(self, isShow):
        for i in xrange(3):
            axis = self.__latticeAxes[i]

            if isShow:
                axis['line'].VisibilityOn()

                for key in axis['ticks'].keys():
                    axis['ticks'][key].VisibilityOn()
                    axis['label'][key].VisibilityOn()
                    pass
                pass
            else:
                axis['line'].VisibilityOff()

                for key in axis['ticks'].keys():
                    axis['ticks'][key].VisibilityOff()
                    axis['label'][key].VisibilityOff()
                    pass
                pass
            pass
        return

    # def Redraw(self):
    #     self.__renderer.Render()
    #     return

    def __createAxes(self):
        self.__axes = vtk.vtkCubeAxesActor2D()

        self.__axes.PickableOff()
        self.__axes.SetCamera(self.__renderer.GetActiveCamera())
        self.__axes.SetLabelFormat('%g')
        self.__axes.SetFontFactor(1.0)
        self.__axes.SetFlyModeToOuterEdges()

        self.__axes.SetXLabel('qx[1/A]')
        self.__axes.SetYLabel('qy[1/A]')
        self.__axes.SetZLabel('qz[1/A]')

        text = vtk.vtkTextProperty()

        self.__axes.SetAxisTitleTextProperty(text)
        self.__axes.SetAxisLabelTextProperty(text)
        self.__axes.UseRangesOn()
        self.__axes.SetCornerOffset(0.0)

        self.__axes.GetXAxisActor2D().SetNumberOfMinorTicks(9)
        self.__axes.GetYAxisActor2D().SetNumberOfMinorTicks(9)
        self.__axes.GetZAxisActor2D().SetNumberOfMinorTicks(9)

        self.__axes.GetXAxisActor2D().SetTickLength(10)
        self.__axes.GetYAxisActor2D().SetTickLength(10)
        self.__axes.GetZAxisActor2D().SetTickLength(10)

        self.__axes.GetXAxisActor2D().SetMinorTickLength(5)
        self.__axes.GetYAxisActor2D().SetMinorTickLength(5)
        self.__axes.GetZAxisActor2D().SetMinorTickLength(5)

        self.__renderer.AddViewProp(self.__axes)
        return

    def SetAxesRange(self, bounds):
        self.__axes.SetBounds(bounds)
        self.__axes.SetRanges(bounds)
        return

    def CreateCameraView(self, axis, boundingSize, center, xmax, ymax, zmax):
        (xw, yw, zw) = boundingSize
        (xc, yc, zc) = center

        camera = self.__renderer.GetActiveCamera()
        camera.SetFocalPoint([xc, yc, zc])
        camera.SetViewAngle(CAMERA_VIEW_ANGLE)
        camera.SetClippingRange([0.01, 100.0])
        camera.UseHorizontalViewAngleOn()

        if axis == 'qx':
            scale = math.sqrt(yw * yw + zw * zw)
            distance = 0.7 * scale / math.tan(math.radians(CAMERA_VIEW_ANGLE / 2.0))
            camera.SetPosition([distance + xmax, yc, zc])
            camera.SetViewUp([0.0, 1.0, 0.0])
            camera.SetParallelScale(0.55 * scale)
            pass
        elif axis == 'qy':
            scale = math.sqrt(xw * xw + zw * zw)
            distance = 0.7 * scale / math.tan(math.radians(CAMERA_VIEW_ANGLE / 2.0))
            camera.SetPosition([xc, distance + ymax, zc])
            camera.SetViewUp([1.0, 0.0, 0.0])
            camera.SetParallelScale(0.55 * scale)
            pass
        elif axis == 'qz':
            scale = math.sqrt(xw * xw + yw * yw)
            distance = 0.7 * scale / math.tan(math.radians(CAMERA_VIEW_ANGLE / 2.0))
            camera.SetPosition([xc, yc, distance + zmax])
            camera.SetViewUp([0.0, 1.0, 0.0])
            camera.SetParallelScale(0.55 * scale)
            pass
        return

    def CreateLatticeView(self, axis, ra, rb, rc, scale):
        camera = self.__renderer.GetActiveCamera()
        camera.SetFocalPoint([0.0, 0.0, 0.0])
        camera.SetViewAngle(CAMERA_VIEW_ANGLE)
        camera.SetClippingRange([0.01, 100.0])
        camera.UseHorizontalViewAngleOn()

        distance = 0.7 * scale / math.tan(math.radians(CAMERA_VIEW_ANGLE / 2.0))

        import vector

        if axis == 'qa':
            fac = distance / vector.GetNorm(ra)
            camera.SetPosition([fac * ra[0], fac * ra[1], fac * ra[2]])
            camera.SetViewUp(rc)
            camera.SetParallelScale(0.55 * scale)
            pass
        elif axis == 'qb':
            fac = distance / vector.GetNorm(rb)
            camera.SetPosition([fac * rb[0], fac * rb[1], fac * rb[2]])
            camera.SetViewUp(ra)
            camera.SetParallelScale(0.55 * scale)
            pass
        elif axis == 'qc':
            fac = distance / vector.GetNorm(rc)
            camera.SetPosition([fac * rc[0], fac * rc[1], fac * rc[2]])
            camera.SetViewUp(rb)
            camera.SetParallelScale(0.55 * scale)
            pass
        return

    def CreateColorBar(self, scalarKind, scalarRange):
        self.__colorFunc.RemoveAllPoints()
        self.__colorFunc.AddHSVPoint(scalarRange[0], 0.667, 1.0, 1.0) # Blue in HSV
        self.__colorFunc.AddHSVPoint(scalarRange[1], 0.0, 1.0, 1.0) # Red in HSV

        self.__colorBar.SetLookupTable(self.__colorFunc)
        self.__colorBar.SetTitle(scalarKind)
        self.__colorBar.SetNumberOfLabels(11)
        self.__colorBar.SetLabelFormat("%g")
        self.__colorBar.SetWidth(0.4)
        self.__colorBar.SetHeight(0.1)
        self.__colorBar.SetPosition(0.55, 0.05)
        self.__colorBar.SetOrientationToHorizontal()
        self.__colorBar.SetMaximumNumberOfColors(10)
        return

    def ProjectionControl(self, isParallel):
        if isParallel:
            self.__renderer.GetActiveCamera().ParallelProjectionOn()
            pass
        else:
            self.__renderer.GetActiveCamera().ParallelProjectionOff()
            pass

        self.Render()
        return

    def ShowPSDOutline(self, regionName, psdNumber, isShow):
        if isShow:
            self.__PSDsurface[regionName][psdNumber].VisibilityOn()
            self.__PSDoutline[regionName][psdNumber].VisibilityOn()
            pass
        else:
            self.__PSDsurface[regionName][psdNumber].VisibilityOff()
            self.__PSDoutline[regionName][psdNumber].VisibilityOff()
            pass

        self.Render()
        return

    def CreateQEGraphPlane(self):
        self.__QEGraphPlane = vtk.vtkActor()
        self.__QEGraphPlane.GetProperty().SetOpacity(0.75)
        self.__QEGraphPlane.GetProperty().SetColor(0.678, 0.847, 0.902)
        self.__QEGraphPlane.SetMapper(vtk.vtkPolyDataMapper())
        self.__QEGraphPlane.VisibilityOff()

        self.__renderer.AddActor(self.__QEGraphPlane)

        self.__QEGraphRegionPlanes = dict()
        for name in self.__detectorRegion.keys():
            self.__QEGraphRegionPlanes[name] = vtk.vtkActor()
            self.__QEGraphRegionPlanes[name].GetProperty().SetOpacity(0.75)
            self.__QEGraphRegionPlanes[name].GetProperty().SetColor(0.184, 0.310, 0.310)
            self.__QEGraphRegionPlanes[name].SetMapper(vtk.vtkPolyDataMapper())
            self.__QEGraphRegionPlanes[name].VisibilityOff()

            self.__renderer.AddActor(self.__QEGraphRegionPlanes[name])
            pass
        return

    def UpdateQEGraphPlane(self, bounds, qOrigin, qNormal):
        points = vtk.vtkPoints()
        points.SetNumberOfPoints(8)
        points.InsertPoint(0, bounds[0], bounds[2], bounds[4])
        points.InsertPoint(1, bounds[1], bounds[2], bounds[4])
        points.InsertPoint(2, bounds[0], bounds[3], bounds[4])
        points.InsertPoint(3, bounds[1], bounds[3], bounds[4])
        points.InsertPoint(4, bounds[0], bounds[2], bounds[5])
        points.InsertPoint(5, bounds[1], bounds[2], bounds[5])
        points.InsertPoint(6, bounds[0], bounds[3], bounds[5])
        points.InsertPoint(7, bounds[1], bounds[3], bounds[5])

        voxel = vtk.vtkVoxel()
        for i in xrange(8):
            voxel.GetPointIds().SetId(i, i)
            pass

        grid = vtk.vtkUnstructuredGrid()
        grid.Allocate(1, 1)
        grid.InsertNextCell(voxel.GetCellType(), voxel.GetPointIds())
        grid.SetPoints(points)

        plane = vtk.vtkPlane()
        plane.SetOrigin(qOrigin)
        plane.SetNormal(qNormal)

        cutter = vtk.vtkCutter()
        cutter.SetInput(grid)
        cutter.SetCutFunction(plane)

        mapper = self.__QEGraphPlane.GetMapper()
        mapper.SetInput(cutter.GetOutput())

        for regionName in self.__detectorRegion.keys():
            grid = vtk.vtkStructuredGrid()
            grid.ShallowCopy(self.__gridData[regionName])
            grid.GetPointData().SetActiveScalars(None)

            cutter = vtk.vtkCutter()
            cutter.SetInput(grid)
            cutter.SetCutFunction(plane)

            mapper = self.__QEGraphRegionPlanes[regionName].GetMapper()
            mapper.SetInput(cutter.GetOutput())
            pass
        return

    def ShowQEGraphPlane(self, isShow):
        if isShow:
            self.__QEGraphPlane.VisibilityOn()
            pass
        else:
            self.__QEGraphPlane.VisibilityOff()
            pass
        return

    def ShowQEGraphRegionPlane(self, regionName, isShow):
        if isShow:
            self.__QEGraphRegionPlanes[regionName].VisibilityOn()
            pass
        else:
            self.__QEGraphRegionPlanes[regionName].VisibilityOff()
            pass
        return

    def GetGridData(self, regionName):
        return self.__gridData[regionName]

    def GetQPPotionOnQECutPlane(self, normal, origin):
        positions = []

        for key in self.__qPoints.keys():
            position = self.__qPoints[key].GetPosition()
            distance = vtk.vtkPlane.DistanceToPlane(position, normal, origin)
            if distance < define.GEOM_TINY_VALUE:
                positions.append(position)
                pass
            pass
        return positions

    def CreateThinDetectableRegionShape(self, regionPoints):
        self.__removeActors(self.__thinDetectableRegion['actor'])

        for regionName in regionPoints.keys():
            points = vtk.vtkPoints()
            points.SetNumberOfPoints(len(regionPoints[regionName]['ponits']))

            for i in xrange(len(regionPoints[regionName]['ponits'])):
                points.SetPoint(i, regionPoints[regionName]['ponits'][i][0],
                                regionPoints[regionName]['ponits'][i][1],
                                regionPoints[regionName]['ponits'][i][2])
                pass

            sgrid = vtk.vtkStructuredGrid()
            sgrid.SetDimensions(regionPoints[regionName]['dimensions'])
            sgrid.SetPoints(points)

            outline = vtk.vtkStructuredGridOutlineFilter()
            outline.SetInput(sgrid)

            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInputConnection(outline.GetOutputPort())

            self.__thinDetectableRegion['grid'][regionName] = sgrid
            self.__thinDetectableRegion['actor'][regionName] = vtk.vtkActor()
            self.__thinDetectableRegion['actor'][regionName].SetMapper(mapper)
            self.__thinDetectableRegion['actor'][regionName].GetProperty().SetColor(0.184, 0.310, 0.310)
            self.__thinDetectableRegion['actor'][regionName].VisibilityOff()

            self.__renderer.AddActor(self.__thinDetectableRegion['actor'][regionName])
            pass
        return

    def ShowThinDetectableRegionShape(self, regionName, isShow):
        if isShow:
            self.__thinDetectableRegion['actor'][regionName].VisibilityOn()
            pass
        else:
            self.__thinDetectableRegion['actor'][regionName].VisibilityOff()
            pass
        return

    def CreateQRegionGraphPlane(self):
        self.__QRegionGraphPlane = []
        self.__QRegionGraphCutRegions = []

        planeColors = ((0.678, 0.847, 0.902), (1.0, 0.753, 0.796))
        regionColors = ((0, 0, 1), (1, 0, 0))

        for i in xrange(2):
            actor = vtk.vtkActor()
            actor.GetProperty().SetOpacity(0.75)
            actor.GetProperty().SetColor(planeColors[i])
            actor.SetMapper(vtk.vtkPolyDataMapper())
            actor.VisibilityOff()

            self.__renderer.AddActor(actor)
            self.__QRegionGraphPlane.append(actor)

            regionActors = dict()
            self.__QRegionGraphCutRegions.append(regionActors)

            for regionName in self.__detectorRegion.keys():
                regionActors[regionName] = vtk.vtkActor()
                regionActors[regionName].GetProperty().SetOpacity(0.75)
                regionActors[regionName].GetProperty().SetColor(regionColors[i])
                regionActors[regionName].SetMapper(vtk.vtkPolyDataMapper())
                regionActors[regionName].VisibilityOff()

                self.__renderer.AddActor(regionActors[regionName])
                pass
            pass
        return

    def UpdateQRegionGraphPlane(self, bounds, qOrigin, qNormal, regionNames):
        for i in xrange(len(self.__QRegionGraphPlane)):
            points = vtk.vtkPoints()
            points.SetNumberOfPoints(8)
            points.InsertPoint(0, bounds[0], bounds[2], bounds[4])
            points.InsertPoint(1, bounds[1], bounds[2], bounds[4])
            points.InsertPoint(2, bounds[0], bounds[3], bounds[4])
            points.InsertPoint(3, bounds[1], bounds[3], bounds[4])
            points.InsertPoint(4, bounds[0], bounds[2], bounds[5])
            points.InsertPoint(5, bounds[1], bounds[2], bounds[5])
            points.InsertPoint(6, bounds[0], bounds[3], bounds[5])
            points.InsertPoint(7, bounds[1], bounds[3], bounds[5])

            voxel = vtk.vtkVoxel()
            for j in xrange(8):
                voxel.GetPointIds().SetId(j, j)
                pass

            grid = vtk.vtkUnstructuredGrid()
            grid.Allocate(1, 1)
            grid.InsertNextCell(voxel.GetCellType(), voxel.GetPointIds())
            grid.SetPoints(points)

            plane = vtk.vtkPlane()
            plane.SetOrigin(qOrigin[i])
            plane.SetNormal(qNormal[i])

            cutter = vtk.vtkCutter()
            cutter.SetInput(grid)
            cutter.SetCutFunction(plane)

            mapper = self.__QRegionGraphPlane[i].GetMapper()
            mapper.SetInput(cutter.GetOutput())

            for regionName in regionNames:
                sgrid = self.__thinDetectableRegion['grid'][regionName]

                cutter = vtk.vtkCutter()
                cutter.SetInput(sgrid)
                cutter.SetCutFunction(plane)

                mapper = self.__QRegionGraphCutRegions[i][regionName].GetMapper()
                mapper.SetInput(cutter.GetOutput())
                pass
            pass
        return

    def ShowQRegionGraphPlane(self, isShow):
        for i in xrange(2):
            if isShow:
                self.__QRegionGraphPlane[i].VisibilityOn()
                pass
            else:
                self.__QRegionGraphPlane[i].VisibilityOff()
                pass
            pass
        return

    def ShowQRegionGraphCutRegion(self, regionName, isShow):
        for i in xrange(2):
            if isShow:
                self.__QRegionGraphCutRegions[i][regionName].VisibilityOn()
                pass
            else:
                self.__QRegionGraphCutRegions[i][regionName].VisibilityOff()
                pass
            pass
        return

    def __getCheckedPSDIndices(self, regionName):
        indexes = []

        for psdNumber, actor in self.__PSDsurface[regionName].items():
            if actor.GetVisibility():
                indexes.append(psdNumber)
            pass
        return indexes

    def SetQPointColor(self, rawQPointList):
        colorMode = self.__mainFrame.GetParameter(qspace.TAG_OBJ3D_QPCOLOR)

        checkedRegions = self.__mainFrame.GetCheckedRegions()

        if colorMode == 0:
            for key in self.__qPoints.keys():
                qpoint = self.__qPoints[key]
                position = qpoint.GetPosition()

                if position[0] == 0.0 and position[1] == 0.0 and position[2] == 0.0:
                    qpoint.GetProperty().SetColor(0.0, 1.0, 0.0)
                    pass
                else:
                    qpoint.GetProperty().SetColor(1.0, 1.0, 1.0)
                    pass
                pass
            pass
        elif colorMode == 1:
            for rawQPoint in rawQPointList:
                for regionName in checkedRegions:
                    if rawQPoint.status[regionName][define.QPVAL_INSIDE]:
                        self.__qPoints[rawQPoint.GetIndexString()].GetProperty().SetColor(1.0, 0.078, 0.576) # deep pink
                        break
                    else:
                        qpoint = self.__qPoints[rawQPoint.GetIndexString()]
                        position = qpoint.GetPosition()

                        if position[0] == 0.0 and position[1] == 0.0 and position[2] == 0.0:
                            qpoint.GetProperty().SetColor(0.0, 1.0, 0.0)
                            pass
                        else:
                            qpoint.GetProperty().SetColor(1.0, 1.0, 1.0)
                            pass
                        pass
                    pass
                pass
            pass
        elif colorMode == 2:
            for rawQPoint in rawQPointList:
                for regionName in checkedRegions:
                    if rawQPoint.status[regionName][define.QPVAL_PSDID] in self.__getCheckedPSDIndices(regionName):
                        self.__qPoints[rawQPoint.GetIndexString()].GetProperty().SetColor(1.0, 0.078, 0.576) # deep pink
                        break
                    else:
                        qpoint = self.__qPoints[rawQPoint.GetIndexString()]
                        position = qpoint.GetPosition()

                        if position[0] == 0.0 and position[1] == 0.0 and position[2] == 0.0:
                            qpoint.GetProperty().SetColor(0.0, 1.0, 0.0)
                            pass
                        else:
                            qpoint.GetProperty().SetColor(1.0, 1.0, 1.0)
                            pass
                        pass
                    pass
                pass
            pass
        elif colorMode == 3:
            etValue = self.__mainFrame.GetFloatParameter(qspace.TAG_OBJ3D_ETVAL)
            etWidth = self.__mainFrame.GetFloatParameter(qspace.TAG_OBJ3D_ETWIDTH)

            for rawQPoint in rawQPointList:
                for regionName in checkedRegions:
                    et = rawQPoint.status[regionName][define.QPVAL_ET]

                    qpoint = self.__qPoints[rawQPoint.GetIndexString()]

                    if et != None and \
                            etValue - 0.5 * etWidth <= et and \
                            et <= etValue + 0.5 * etWidth:
                        qpoint.GetProperty().SetColor(self.__colorFunc.GetColor(et))
                        break
                    else:
                        position = qpoint.GetPosition()

                        if position[0] == 0.0 and position[1] == 0.0 and position[2] == 0.0:
                            qpoint.GetProperty().SetColor(0.0, 1.0, 0.0)
                            pass
                        else:
                            qpoint.GetProperty().SetColor(1.0, 1.0, 1.0)
                            pass
                        pass
                    pass
                pass
            pass
        elif colorMode == 4:
            pixelNumber = self.__mainFrame.GetParameter(qspace.TAG_OBJ3D_PXNO)
            pixelRange = self.__mainFrame.GetParameter(qspace.TAG_OBJ3D_PXRANGE)

            for rawQPoint in rawQPointList:
                for regionName in checkedRegions:
                    qpPixelNumber = rawQPoint.status[regionName][define.QPVAL_PXNO]

                    qpoint = self.__qPoints[rawQPoint.GetIndexString()]

                    if qpPixelNumber != None and abs(qpPixelNumber - pixelNumber) <= pixelRange:
                        qpoint.GetProperty().SetColor(1.0, 0.078, 0.576) # deep pink
                        break
                    else:
                        position = qpoint.GetPosition()

                        if position[0] == 0.0 and position[1] == 0.0 and position[2] == 0.0:
                            qpoint.GetProperty().SetColor(0.0, 1.0, 0.0)
                            pass
                        else:
                            qpoint.GetProperty().SetColor(1.0, 1.0, 1.0)
                            pass
                        pass
                    pass
                pass
            pass
        elif colorMode == 5:
            qOrigin, qU, qV, qNormal = self.__mainFrame.GetQEGraphAxis()

            for rawQPoint in rawQPointList:
                distance = vtk.vtkPlane.DistanceToPlane(rawQPoint.position, qNormal, qOrigin)
                qpoint = self.__qPoints[rawQPoint.GetIndexString()]

                if distance < define.GEOM_TINY_VALUE:
                    qpoint.GetProperty().SetColor(1.0, 0.078, 0.576) # deep pink
                    pass
                else:
                    position = qpoint.GetPosition()

                    if position[0] == 0.0 and position[1] == 0.0 and position[2] == 0.0:
                        qpoint.GetProperty().SetColor(0.0, 1.0, 0.0)
                        pass
                    else:
                        qpoint.GetProperty().SetColor(1.0, 1.0, 1.0)
                        pass
                    pass
                pass
            pass
        elif colorMode == 6:
            import decimal

            lattice = self.__mainFrame.GetLattice()

            for rawQPoint in rawQPointList:
                setColor = True
                for denom in lattice.ltcKindDenom:
                    sum = decimal.Decimal(0)

                    for i in xrange(3):
                        if denom[i] != None:
                            sum += decimal.Decimal(rawQPoint.index[i]) / denom[i]
                            pass
                        pass

                    if math.modf(sum)[0] != 0.0:
                        setColor = False
                        break
                    pass

                qpoint = self.__qPoints[rawQPoint.GetIndexString()]

                if setColor:
                    qpoint.GetProperty().SetColor(1.0, 0.078, 0.576) # deep pink
                    pass
                else:
                    position = qpoint.GetPosition()

                    if position[0] == 0.0 and position[1] == 0.0 and position[2] == 0.0:
                        qpoint.GetProperty().SetColor(0.0, 1.0, 0.0)
                        pass
                    else:
                        qpoint.GetProperty().SetColor(1.0, 1.0, 1.0)
                        pass
                    pass
                pass
            pass
        return

    def SetQPointOpacity(self, rawQPointList):
        opacityMode = self.__mainFrame.GetParameter(qspace.TAG_OBJ3D_QPDISPLAY)

        checkedRegions = self.__mainFrame.GetCheckedRegions()

        if opacityMode == 0:
            for key in self.__qPoints.keys():
                self.__qPoints[key].GetProperty().SetOpacity(1.0)
                pass
        elif opacityMode == 1:
            for rawQPoint in rawQPointList:
                for regionName in checkedRegions:
                    if rawQPoint.status[regionName][define.QPVAL_INSIDE]:
                        self.__qPoints[rawQPoint.GetIndexString()].GetProperty().SetOpacity(1.0)
                        break
                    else:
                        self.__qPoints[rawQPoint.GetIndexString()].GetProperty().SetOpacity(0.0)
                        pass
                    pass
                pass
            pass
        elif opacityMode == 2:
            for rawQPoint in rawQPointList:
                for regionName in checkedRegions:
                    if rawQPoint.status[regionName][define.QPVAL_INSIDE]:
                        self.__qPoints[rawQPoint.GetIndexString()].GetProperty().SetOpacity(1.0)
                        break
                    else:
                        self.__qPoints[rawQPoint.GetIndexString()].GetProperty().SetOpacity(0.25)
                        pass
                    pass
                pass
            pass
        elif opacityMode == 3:
            for rawQPoint in rawQPointList:
                for regionName in checkedRegions:
                    if rawQPoint.status[regionName][define.QPVAL_INSIDE]:
                        self.__qPoints[rawQPoint.GetIndexString()].GetProperty().SetOpacity(1.0)
                        break
                    else:
                        self.__qPoints[rawQPoint.GetIndexString()].GetProperty().SetOpacity(0.5)
                        pass
                    pass
                pass
            pass
        elif opacityMode == 4:
            pixelNumber = self.__mainFrame.GetParameter(qspace.TAG_OBJ3D_PXNO)
            pixelRange = self.__mainFrame.GetParameter(qspace.TAG_OBJ3D_PXRANGE)

            for rawQPoint in rawQPointList:
                for regionName in checkedRegions:
                    qpPixelNumber = rawQPoint.status[regionName][define.QPVAL_PXNO]

                    if qpPixelNumber != None and abs(qpPixelNumber - pixelNumber) <= pixelRange:
                        self.__qPoints[rawQPoint.GetIndexString()].GetProperty().SetOpacity(1.0)
                        break
                    else:
                        self.__qPoints[rawQPoint.GetIndexString()].GetProperty().SetOpacity(0.0)
                        pass
                    pass
                pass
            pass
        elif opacityMode == 5:
            qOrigin, qU, qV, qNormal = self.__mainFrame.GetQEGraphAxis()

            for rawQPoint in rawQPointList:
                distance = vtk.vtkPlane.DistanceToPlane(rawQPoint.position, qNormal, qOrigin)
                if distance < define.GEOM_TINY_VALUE:
                    self.__qPoints[rawQPoint.GetIndexString()].GetProperty().SetOpacity(1.0)
                    pass
                else:
                    self.__qPoints[rawQPoint.GetIndexString()].GetProperty().SetOpacity(0.0)
                    pass
                pass
            pass
        elif opacityMode == 6:
            import decimal

            lattice = self.__mainFrame.GetLattice()

            for rawQPoint in rawQPointList:
                setTransparent = False
                for denom in lattice.ltcKindDenom:
                    sum = decimal.Decimal(0)

                    for i in xrange(3):
                        if denom[i] != None:
                            sum += decimal.Decimal(rawQPoint.index[i]) / denom[i]
                            pass
                        pass

                    if math.modf(sum)[0] != 0.0:
                        setTransparent = True
                        break
                    pass

                if setTransparent:
                    self.__qPoints[rawQPoint.GetIndexString()].GetProperty().SetOpacity(0.0)
                    pass
                else:
                    self.__qPoints[rawQPoint.GetIndexString()].GetProperty().SetOpacity(1.0)
                    pass
                pass
            pass
        return

    def LButtonDoubleClick(self, event):
        size = self.GetSize()
        if self._Picker.Pick(event.GetX(), size[1] - event.GetY(), 0, self._CurrentRenderer):
            actor = self._Picker.GetActor()
            for key in self.__qPoints.keys():
                if actor == self.__qPoints[key]:
                    self.__mainFrame.QPointListSetSelected(key)
                    break
                pass
            pass
        return

class QEGraphBase(VTKPanelBase):
    def __init__(self, parent):
        VTKPanelBase.__init__(self, parent)

        self._renderer = vtk.vtkRenderer()

        self.GetRenderWindow().AddRenderer(self._renderer)

        light = vtk.vtkLightKit()
        light.SetKeyLightIntensity(1.0)
        light.AddLightsToRenderer(self._renderer)

        self._bounds = [None, None, None, None, None, None]
        self.__ranges = [None, None, None, None, None, None]

        self.__getMainFrame()
        return

    def __getMainFrame(self):
        self._mainFrame = self.GetParent()

        while not isinstance(self._mainFrame, wx.Frame):
            self._mainFrame = self._mainFrame.GetParent()
            pass
        return

    def SetupTransformMatrix(self, qOrigin, qU, qV):
        thetaZ = -math.atan2(qU[1], qU[0])

        qUa = [qU[0] * math.cos(thetaZ) - qU[1] * math.sin(thetaZ),
               0.0,
               qU[2]]
        qVa = [qV[0] * math.cos(thetaZ) - qV[1] * math.sin(thetaZ),
               qV[0] * math.sin(thetaZ) + qV[1] * math.cos(thetaZ),
               qV[2]]

        thetaY = math.atan2(qUa[2], qUa[0])

        qUb = [qUa[0] * math.cos(thetaY) + qUa[2] * math.sin(thetaY),
               0.0,
               0.0]

        qVb = [qVa[0] * math.cos(thetaY) + qVa[2] * math.sin(thetaY),
               qVa[1],
               - qVa[0] * math.sin(thetaY) + qVa[2] * math.cos(thetaY)]

        thetaX = -math.atan2(qVb[2], qVb[1])

        self.__axisU = qUb
        self.__axisV = [qVb[0],
                        qVb[1] * math.cos(thetaX) - qVb[2] * math.sin(thetaX),
                        0.0]

        self._transMatrix = vtk.vtkTransform()

        self._transMatrix.RotateX(math.degrees(thetaX))
        self._transMatrix.RotateY(math.degrees(thetaY))
        self._transMatrix.RotateZ(math.degrees(thetaZ))
        self._transMatrix.Translate(-qOrigin[0], -qOrigin[1], -qOrigin[2])
        return

    def SetupRanges(self):
        if isinstance(self, QEGraphPanel):
            actors = self._warpSurfaceActors
            pass
        else:
            actors = self._contourActors
            pass

        nameList = actors.keys();

        bounds = actors[nameList[0]].GetBounds()

        for i in xrange(4):
            self.__ranges[i] = bounds[i]
            pass

        for i in xrange(1, len(nameList)):
            bounds = actors[nameList[i]].GetBounds()

            for i in (0, 2):
                self.__ranges[i] = min(self.__ranges[i], bounds[i])
                self.__ranges[i + 1] = max(self.__ranges[i + 1], bounds[i + 1])
                pass
            pass

        self.__ranges[0:2] = qspace.GetRoundingRange(self.__ranges[0:2], -1)
        self.__ranges[2:4] = qspace.GetRoundingRange(self.__ranges[2:4], -1)
        self.__ranges[4:6] = self._mainFrame.GetScalarFieldRange(define.ENERGY_TRANSFER)

        self.__zscale = max((self.__ranges[1] - self.__ranges[0]),
                            (self.__ranges[3] - self.__ranges[2])) / (self.__ranges[5] - self.__ranges[4])

        for i in xrange(6):
            self._bounds[i] = self.__ranges[i]
            pass

        self._bounds[4] *= self.__zscale
        self._bounds[5] *= self.__zscale

        for name in nameList:
            actors[name].SetScale(1.0, 1.0, self.__zscale)
            pass
        return

    def SetupQPoints(self, positions):
        self.__qPoints = []

        radius = max(self._bounds[1] - self._bounds[0],
                     self._bounds[3] - self._bounds[2],
                     self._bounds[5] - self._bounds[4]) * self._mainFrame.GetQPointSize()

        for i in xrange(len(positions)):
            x, y, dummy = self._transMatrix.TransformPoint(positions[i])

            if self._bounds[0] - define.GEOM_TINY_VALUE <= x <= self._bounds[1] + define.GEOM_TINY_VALUE and \
                    self._bounds[2] - define.GEOM_TINY_VALUE <= y <= self._bounds[3] + define.GEOM_TINY_VALUE:
                sphere = vtk.vtkSphereSource()
                sphere.SetRadius(radius)

                mapper = vtk.vtkPolyDataMapper()
                mapper.SetInputConnection(sphere.GetOutputPort())

                actor = vtk.vtkActor()
                actor.SetMapper(mapper)
                actor.PickableOn()
                if isinstance(self, QEGraphPanel):
                    actor.SetPosition(x, y, self._bounds[4])
                    pass
                else:
                    actor.SetPosition(x, y, 0.0)
                    pass

                if positions[i][0] == 0.0 and positions[i][1] == 0.0 and positions[i][2] == 0.0:
                    actor.GetProperty().SetColor(0.0, 1.0, 0.0)
                    pass

                self.__qPoints.append(actor)

                self._renderer.AddActor(actor)
                pass
            pass
        return

    def ShowQPoint(self, isShow):
        for point in self.__qPoints:
            if isShow:
                point.VisibilityOn()
                pass
            else:
                point.VisibilityOff()
                pass
            pass
        return

    def __CreateAxis(self, position, color, labelText):
        # Create input point data.
        points = vtk.vtkPoints()
        points.InsertPoint(0, (0, 0, 0))

        cellArray = vtk.vtkCellArray()
        cellArray.InsertNextCell(1)
        cellArray.InsertCellPoint(0)

        polyData = vtk.vtkPolyData()
        polyData.SetPoints(points)
        polyData.SetPolys(cellArray)

        # Orient the glyphs as per vectors.
        vec = vtk.vtkFloatArray()
        vec.SetNumberOfComponents(3)
        vec.InsertTuple3(0, position[0], position[1], position[2])

        polyData.GetPointData().SetVectors(vec)
        arrow = vtk.vtkArrowSource()

        # The glyph filter.
        glyph = vtk.vtkGlyph3D()
        glyph.SetVectorModeToUseVector()
        glyph.SetScaleModeToScaleByVector()
        glyph.SetInput(polyData)
        glyph.SetSource(arrow.GetOutput())

        glyphMapper = vtk.vtkPolyDataMapper()
        glyphMapper.SetInputConnection(glyph.GetOutputPort())

        axisActor =  vtk.vtkActor()
        axisActor.SetMapper(glyphMapper)
        axisActor.GetProperty().SetColor(color)

        pos = axisActor.GetPosition()
        if isinstance(self, QEGraphPanel):
            axisActor.SetPosition(pos[0], pos[1], self._bounds[4])
            pass
        else:
            axisActor.SetPosition(pos[0], pos[1], 0.0)
            pass

        self._renderer.AddActor(axisActor)

        # Axes axisLabelText
        text = vtk.vtkVectorText()
        text.SetText(labelText)
        textMapper = vtk.vtkPolyDataMapper()
        textMapper.SetInputConnection(text.GetOutputPort())

        axisLabelActor = vtk.vtkFollower()
        axisLabelActor.SetMapper(textMapper)
        axisLabelActor.SetScale(0.1, 0.1, 0.1)
        if isinstance(self, QEGraphPanel):
            axisLabelActor.SetPosition(1.1 * position[0], 1.1 * position[1], self._bounds[4])
            pass
        else:
            axisLabelActor.SetPosition(1.1 * position[0], 1.1 * position[1], 0.0)
            pass

        axisLabelActor.SetCamera(self._renderer.GetActiveCamera())

        self._renderer.AddActor(axisLabelActor)
        return axisActor, axisLabelActor

    def SetupUVAxis(self):
        plane = self._mainFrame.GetParameter(qspace.TAG_QEGRAPH_PLANEDEF)

        if plane == 0:
            colorU = (1, 0, 0)
            labelU = 'a'

            colorV = (0, 0, 1)
            labelV = 'b'
            pass
        elif plane == 1:
            colorU = (0, 0, 1)
            labelU = 'b'

            colorV = (0, 1, 0)
            labelV = 'c'
            pass
        elif plane == 2:
            colorU = (0, 1, 0)
            labelU = 'c'

            colorV = (1, 0, 0)
            labelV = 'a'
            pass
        else:
            colorU = (0.502, 0.0, 0.502)
            labelU = 'u'

            colorV = (0, 1, 1)
            labelV = 'v'
            pass

        self.__axisUActor, self.__axisULabelActor = self.__CreateAxis(self.__axisU, colorU, labelU)
        self.__axisVActor, self.__axisVLabelActor = self.__CreateAxis(self.__axisV, colorV, labelV)
        return

    def _setupBoundIndices(self):
        A = [[self.__axisU[0], self.__axisV[0]],
             [self.__axisU[1], self.__axisV[1]]]

        det = A[0][0] * A[1][1] - A[0][1] * A[1][0]

        M = [[A[1][1] / det, -A[0][1] / det],
             [-A[1][0] / det, A[0][0] / det]]

        phi = [ApplyMat2D(M, [self._bounds[0], self._bounds[2]]),
               ApplyMat2D(M, [self._bounds[0], self._bounds[3]]),
               ApplyMat2D(M, [self._bounds[1], self._bounds[2]]),
               ApplyMat2D(M, [self._bounds[1], self._bounds[3]])]

        imin = phi[0][0]
        imax = phi[0][0]
        jmin = phi[0][1]
        jmax = phi[0][1]

        for x in phi:
            imin = min(x[0], imin)
            imax = max(x[0], imax)
            jmin = min(x[1], jmin)
            jmax = max(x[1], jmax)
            pass

        self.__imin = int(math.floor(imin))
        self.__jmin = int(math.floor(jmin))

        self.__imax = int(math.ceil(imax))
        self.__jmax = int(math.ceil(jmax))
        return

    def SetupGridLines(self):
        self._setupBoundIndices()

        sgrid = vtk.vtkStructuredGrid()
        sgrid.SetExtent(self.__imin, self.__imax, self.__jmin, self.__jmax, 0, 0)

        size = (self.__imax - self.__imin + 1) * (self.__jmax - self.__jmin + 1)

        points = vtk.vtkPoints()
        points.SetNumberOfPoints(size)

        count = 0
        for j in xrange(self.__jmin, self.__jmax + 1):
            for i in xrange(self.__imin, self.__imax + 1):
                points.SetPoint(count,
                                self.__axisU[0] * i + self.__axisV[0] * j,
                                self.__axisU[1] * i + self.__axisV[1] * j,
                                0.0)
                count += 1
                pass
            pass

        sgrid.SetPoints(points)

        mapper = vtk.vtkDataSetMapper()
        mapper.SetInput(sgrid)

        self._gridActor = vtk.vtkActor()
        self._gridActor.SetMapper(mapper)
        self._gridActor.GetProperty().EdgeVisibilityOn()
        self._gridActor.GetProperty().SetLineWidth(2.0)
        if isinstance(self, QEGraphPanel):
            self._gridActor.GetProperty().SetOpacity(0.5)
            self._gridActor.GetProperty().SetColor(0, 0, 1)
            self._gridActor.GetProperty().SetEdgeColor(1, 1, 1)
            self._gridActor.SetPosition(0.0, 0.0, self._bounds[4])
            pass
        else:
            self._gridActor.GetProperty().SetOpacity(0.3)
            self._gridActor.SetPosition(0.0, 0.0, 0.0)
            pass

        self._renderer.AddActor(self._gridActor)
        return

    def _SetupZAxis(self):
        x0 = self.__axisU[0] * self.__imin + self.__axisV[0] * self.__jmin
        y0 = self.__axisU[1] * self.__imin + self.__axisV[1] * self.__jmin

        # Set Z-axis ticks and labels
        lineSource = vtk.vtkLineSource()
        lineSource.SetPoint1(x0, y0, self._bounds[4])
        lineSource.SetPoint2(x0, y0, self._bounds[5])

        lineMapper = vtk.vtkPolyDataMapper()
        lineMapper.SetInputConnection(lineSource.GetOutputPort())

        lineActor = vtk.vtkActor()
        lineActor.SetMapper(lineMapper)

        self._renderer.AddActor(lineActor)

        for i in xrange(11):
            tickSize = 0.1

            z = self._bounds[4] + (self._bounds[5] - self._bounds[4]) / 10 * i
            e = self.__ranges[4] + (self.__ranges[5] - self.__ranges[4]) / 10 * i

            lineSource = vtk.vtkLineSource()
            lineSource.SetPoint1(0.0, 0.0, 0.0)
            lineSource.SetPoint2(tickSize, 0.0, 0.0)
            lineMapper = vtk.vtkPolyDataMapper()
            lineMapper.SetInputConnection(lineSource.GetOutputPort())

            lineActor = vtk.vtkFollower()
            lineActor.SetCamera(self._renderer.GetActiveCamera())
            lineActor.SetMapper(lineMapper)
            lineActor.SetPosition(x0, y0, z)

            self._renderer.AddActor(lineActor)

            text = vtk.vtkVectorText()
            text.SetText('    %g' % e)
            textMapper = vtk.vtkPolyDataMapper()
            textMapper.SetInputConnection(text.GetOutputPort())

            labelActor = vtk.vtkFollower()
            labelActor.SetCamera(self._renderer.GetActiveCamera())
            labelActor.SetMapper(textMapper)
            labelActor.SetScale(0.1, 0.1, 0.1)
            labelActor.SetPosition(x0, y0, z - 0.05)

            self._renderer.AddActor(labelActor)
            pass

        # Set Z-axis title
        title = vtk.vtkVectorText()
        title.SetText('Et[meV]')
        titleMapper = vtk.vtkPolyDataMapper()
        titleMapper.SetInputConnection(title.GetOutputPort())

        titleActor = vtk.vtkFollower()
        titleActor.SetCamera(self._renderer.GetActiveCamera())
        titleActor.SetMapper(titleMapper)
        titleActor.SetScale(0.1, 0.1, 0.1)
        titleActor.SetPosition(x0, y0, 1.05 * self._bounds[5])

        self._renderer.AddActor(titleActor)
        return

    def _SetupXYAxis(self):
        plane = self._mainFrame.GetParameter(qspace.TAG_QEGRAPH_PLANEDEF)

        # Set U,V axis labels
        orig = (self._mainFrame.GetParameter(qspace.TAG_QEGRAPH_OH),
                self._mainFrame.GetParameter(qspace.TAG_QEGRAPH_OK),
                self._mainFrame.GetParameter(qspace.TAG_QEGRAPH_OL))

        if plane == 0:
            udir = (1, 0, 0)
            vdir = (0, 1, 0)
            pass
        elif plane == 1:
            udir = (0, 1, 0)
            vdir = (0, 0, 1)
            pass
        elif plane == 2:
            udir = (0, 0, 1)
            vdir = (1, 0, 0)
            pass
        else:
            udir = (self._mainFrame.GetParameter(qspace.TAG_QEGRAPH_UH),
                    self._mainFrame.GetParameter(qspace.TAG_QEGRAPH_UK),
                    self._mainFrame.GetParameter(qspace.TAG_QEGRAPH_UL))

            vdir = (self._mainFrame.GetParameter(qspace.TAG_QEGRAPH_VH),
                    self._mainFrame.GetParameter(qspace.TAG_QEGRAPH_VK),
                    self._mainFrame.GetParameter(qspace.TAG_QEGRAPH_VL))
            pass

        self.__axisULabelActors = []
        self.__axisVLabelActors = []

        labelOffset = 0.1

        y0 = self.__axisU[1] * self.__imin + self.__axisV[1] * self.__jmin

        for i in xrange(self.__imin + 1, self.__imax):
            miller = (udir[0] * i + vdir[0] * self.__jmin + orig[0],
                      udir[1] * i + vdir[1] * self.__jmin + orig[1],
                      udir[2] * i + vdir[2] * self.__jmin + orig[2])

            text = vtk.vtkVectorText()
            text.SetText(str(miller))
            textMapper = vtk.vtkPolyDataMapper()
            textMapper.SetInputConnection(text.GetOutputPort())

            x = self.__axisU[0] * i + self.__axisV[0] * self.__jmin

            labelActor = vtk.vtkFollower()
            labelActor.SetCamera(self._renderer.GetActiveCamera())
            labelActor.SetMapper(textMapper)
            labelActor.SetScale(0.075, 0.075, 0.075)
            if isinstance(self, QEGraphPanel):
                labelActor.SetPosition(x, y0, self._bounds[4] - labelOffset)
                pass
            else:
                labelActor.SetPosition(x, y0, 0.0)
                pass

            self._renderer.AddActor(labelActor)

            self.__axisULabelActors.append(labelActor)
            pass

        for j in xrange(self.__jmin + 1, self.__jmax):
            miller = (udir[0] * self.__imin + vdir[0] * j + orig[0],
                      udir[1] * self.__imin + vdir[1] * j + orig[1],
                      udir[2] * self.__imin + vdir[2] * j + orig[2])

            text = vtk.vtkVectorText()
            text.SetText(str(miller))
            textMapper = vtk.vtkPolyDataMapper()
            textMapper.SetInputConnection(text.GetOutputPort())

            x = self.__axisU[0] * self.__imin + self.__axisV[0] * j
            y = self.__axisU[1] * self.__imin + self.__axisV[1] * j

            labelActor = vtk.vtkFollower()
            labelActor.SetCamera(self._renderer.GetActiveCamera())
            labelActor.SetMapper(textMapper)
            labelActor.SetScale(0.075, 0.075, 0.075)
            if isinstance(self, QEGraphPanel):
                labelActor.SetPosition(x, y, self._bounds[4] - labelOffset)
                pass
            else:
                labelActor.SetPosition(x, y, 0.0)
                pass

            self._renderer.AddActor(labelActor)

            self.__axisVLabelActors.append(labelActor)
            pass
        return

    def SetupAxes(self):
        if isinstance(self, QEGraphPanel):
            self._SetupZAxis()
            pass
        self._SetupXYAxis()
        return

    def SetupCamera(self):
        xc = 0.5 * (self._bounds[1] + self._bounds[0])
        yc = 0.5 * (self._bounds[3] + self._bounds[2])
        zc = 0.5 * (self._bounds[5] + self._bounds[4])

        camera = self._renderer.GetActiveCamera()
        camera.SetFocalPoint([xc, yc, zc])
        camera.SetViewAngle(CAMERA_VIEW_ANGLE)
        camera.UseHorizontalViewAngleOn()

        if isinstance(self, QEGraphPanel):
            yw = self._bounds[3] - self._bounds[2]
            zw = self._bounds[5] - self._bounds[4]

            scale = math.sqrt(yw * yw + zw * zw)
            distance = 0.7 * scale / math.tan(math.radians(CAMERA_VIEW_ANGLE / 2.0))
            camera.SetPosition([distance + self._bounds[1], yc, zc])
            camera.SetViewUp([0.0, 0.0, 1.0])

            camera.Azimuth(45.0)
            camera.Elevation(10.0)

            camera.SetWindowCenter(-0.15, -0.1)
            camera.SetClippingRange([0.01, 100.0])

            camera.SetParallelScale(0.55 * scale)
            pass
        else:
            camera.SetPosition([xc, yc, zc + 1.0])
            camera.SetViewUp([0.0, 1.0, 0.0])
            camera.ParallelProjectionOn()

            xw = self._bounds[1] - self._bounds[0]
            yw = self._bounds[3] - self._bounds[2]

            scale = math.sqrt(xw * xw + yw * yw)

            camera.SetParallelScale(0.7 * scale)
            pass
        return

    def SetLegendBox(self):
        plane = self._mainFrame.GetParameter(qspace.TAG_QEGRAPH_PLANEDEF)

        if plane == 0:
            title = 'QE graph on a*b plane'
            pass
        elif plane == 1:
            title = 'QE graph on b*c plane'
            pass
        elif plane == 2:
            title = 'QE graph on c*a plane'
            pass
        else:
            title = 'QE graph on u*v plane'
            pass

        psi = self._mainFrame.GetParameter(qspace.TAG_ROTATE_PSI)
        chi = self._mainFrame.GetParameter(qspace.TAG_ROTATE_CHI)
        phi = self._mainFrame.GetParameter(qspace.TAG_ROTATE_PHI)

        labels = (title, 'psi,chi,phi=%g, %g, %g [deg.]' % (psi, chi, phi))

        legend = vtk.vtkLegendBoxActor()
        legend.SetNumberOfEntries(len(labels))
        legend.SetPosition(0.025, 0.875)
        legend.SetWidth(0.5)
        legend.SetHeight(0.1)

        for i in xrange(len(labels)):
            legend.SetEntryString(i, labels[i])
            pass

        tprop = vtk.vtkTextProperty()
        tprop.SetVerticalJustificationToCentered()

        legend.SetEntryTextProperty(tprop)
        legend.BorderOn()

        self._renderer.AddActor2D(legend)
        return

    def UpdateGridPosition(self, value):
        z = value * self.__zscale

        for point in self.__qPoints:
            pos = point.GetPosition()
            point.SetPosition(pos[0], pos[1], z)
            pass

        pos = self.__axisUActor.GetPosition()
        self.__axisUActor.SetPosition(pos[0], pos[1], z)

        pos = self.__axisVActor.GetPosition()
        self.__axisVActor.SetPosition(pos[0], pos[1], z)

        pos = self.__axisULabelActor.GetPosition()
        self.__axisULabelActor.SetPosition(pos[0], pos[1], z)

        pos = self.__axisVLabelActor.GetPosition()
        self.__axisVLabelActor.SetPosition(pos[0], pos[1], z)

        self._gridActor.SetPosition(0.0, 0.0, z)

        for actor in self.__axisULabelActors:
            pos = actor.GetPosition()
            actor.SetPosition(pos[0], pos[1], z - 0.1)
            pass

        for actor in self.__axisVLabelActors:
            pos = actor.GetPosition()
            actor.SetPosition(pos[0], pos[1], z - 0.1)
            pass
        return

class QEGraphPanel(QEGraphBase):
    def __init__(self, parent):
        QEGraphBase.__init__(self, parent)

        self.__colorFunc = vtk.vtkColorTransferFunction()
        self.__colorFunc.SetColorSpaceToHSV()
        self.__colorFunc.HSVWrapOff()

        self.__colorBar = vtk.vtkScalarBarActor()
        self._renderer.AddActor2D(self.__colorBar)
        return

    def CreateColorBar(self, scalarKind, scalarRange):
        self.__colorFunc.RemoveAllPoints()
        self.__colorFunc.AddHSVPoint(scalarRange[0], 0.667, 1.0, 1.0) # Blue in HSV
        self.__colorFunc.AddHSVPoint(scalarRange[1], 0.0, 1.0, 1.0) # Red in HSV

        self.__colorBar.SetLookupTable(self.__colorFunc)
        self.__colorBar.SetTitle(scalarKind)
        self.__colorBar.SetNumberOfLabels(11)
        self.__colorBar.SetLabelFormat("%g")
        self.__colorBar.SetWidth(0.8)
        self.__colorBar.SetHeight(0.1)
        self.__colorBar.SetPosition(0.1, 0.03)
        self.__colorBar.SetOrientationToHorizontal()
        self.__colorBar.SetMaximumNumberOfColors(10)
        return

    def CreateWarpSurface(self, qOrigin, qNormal):
        scalarKind = self._mainFrame.GetScalarKind()
        regionData = self._mainFrame.GetRegionData(scalarKind)

        self._warpSurfaceActors = {}

        for regionName in regionData.keys():
            self._warpSurfaceActors[regionName] = vtk.vtkActor()
            self._renderer.AddActor(self._warpSurfaceActors[regionName])

            if regionData[regionName] == None:
                continue

            sgrid = vtk.vtkStructuredGrid()
            sgrid.ShallowCopy(regionData[regionName])
            sgrid.GetPointData().SetActiveScalars(define.ENERGY_TRANSFER)

            plane = vtk.vtkPlane()
            plane.SetOrigin(qOrigin)
            plane.SetNormal(qNormal)

            cutter = vtk.vtkCutter()
            cutter.SetInput(sgrid)
            cutter.SetCutFunction(plane)
            cutter.Update()

            polygon = cutter.GetOutput()
            points = polygon.GetPoints()

            # Translate and rotate cut-plane
            for i in xrange(points.GetNumberOfPoints()):
                x, y, z = self._transMatrix.TransformPoint(points.GetPoint(i))
                points.SetPoint(i, x, y, 0.0)
                pass

            warp = vtk.vtkWarpScalar()
            warp.SetInput(polygon)
            warp.SetNormal(0.0, 0.0, 1.0)
            warp.UseNormalOn()

            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInput(warp.GetOutput())
            mapper.SetLookupTable(self.__colorFunc)

            if scalarKind == define.ENERGY_TRANSFER:
                mapper.SetScalarModeToUsePointFieldData()
                pass
            elif scalarKind == define.DETECT_INTENSITY:
                mapper.SetScalarModeToUseCellFieldData()
                pass

            mapper.ColorByArrayComponent(scalarKind, 0)

            self._warpSurfaceActors[regionName].SetMapper(mapper)
            pass
        return

class QEContourPanel(QEGraphBase):
    def __init__(self, parent):
        QEGraphBase.__init__(self, parent)

        self.__colorFunc = vtk.vtkColorTransferFunction()
        self.__colorFunc.SetColorSpaceToHSV()
        self.__colorFunc.HSVWrapOff()

        self.__colorBar = vtk.vtkScalarBarActor()
        self._renderer.AddActor2D(self.__colorBar)
        return

    def CreateColorBar(self, scalarKind, scalarRange):
        (etMin, etMax) = qspace.GetRoundingRange(scalarRange, math.ceil(math.log10(scalarRange[1])))

        self.__colorFunc.RemoveAllPoints()
        self.__colorFunc.AddHSVPoint(etMin, 0.667, 1.0, 1.0) # Blue in HSV
        self.__colorFunc.AddHSVPoint(etMax, 0.0, 1.0, 1.0) # Red in HSV

        self.__colorBar.SetLookupTable(self.__colorFunc)
        self.__colorBar.SetTitle(scalarKind)
        self.__colorBar.SetNumberOfLabels(11)
        self.__colorBar.SetLabelFormat("%g")
        self.__colorBar.SetWidth(0.8)
        self.__colorBar.SetHeight(0.1)
        self.__colorBar.SetPosition(0.1, 0.03)
        self.__colorBar.SetOrientationToHorizontal()
        self.__colorBar.SetMaximumNumberOfColors(10)
        return

    def CreateContour(self, qOrigin, qNormal):
        scalarKind = self._mainFrame.GetScalarKind()
        regionData = self._mainFrame.GetRegionData(scalarKind)
        etMin, etMax = self._mainFrame.GetScalarFieldRange(define.ENERGY_TRANSFER)
        (etMin, etMax) = qspace.GetRoundingRange((etMin, etMax), math.ceil(math.log10(etMax)))

        self._contourActors = {}

        for regionName in regionData.keys():
            regionAreaActor = vtk.vtkActor()
            regionAreaActor.GetProperty().SetColor(0.5, 0.5, 0.5)
            self._renderer.AddActor(regionAreaActor)

            self._contourActors[regionName] = vtk.vtkActor()
            self._renderer.AddActor(self._contourActors[regionName])

            if regionData[regionName] == None:
                continue

            sgrid = vtk.vtkStructuredGrid()
            sgrid.ShallowCopy(regionData[regionName])
            sgrid.GetPointData().SetActiveScalars(define.ENERGY_TRANSFER)

            plane = vtk.vtkPlane()
            plane.SetOrigin(qOrigin)
            plane.SetNormal(qNormal)

            cutter = vtk.vtkCutter()
            cutter.SetInput(sgrid)
            cutter.SetCutFunction(plane)
            cutter.Update()

            polygon = cutter.GetOutput()
            points = polygon.GetPoints()

            # Translate and rotate cut-plane
            for i in xrange(points.GetNumberOfPoints()):
                x, y, z = self._transMatrix.TransformPoint(points.GetPoint(i))
                points.SetPoint(i, x, y, 0.0)
                pass

            contourFilter = vtk.vtkContourFilter()
            contourFilter.SetInput(polygon)
            contourFilter.GenerateValues(11, etMin, etMax)

            mapper = vtk.vtkPolyDataMapper()
            # mapper.SetInput(polygon)
            mapper.SetInput(contourFilter.GetOutput())
            mapper.SetLookupTable(self.__colorFunc)

            if scalarKind == define.ENERGY_TRANSFER:
                mapper.SetScalarModeToUsePointFieldData()
                pass
            elif scalarKind == define.DETECT_INTENSITY:
                mapper.SetScalarModeToUseCellFieldData()
                pass

            mapper.ColorByArrayComponent(scalarKind, 0)

            self._contourActors[regionName].SetMapper(mapper)

            grid = vtk.vtkStructuredGrid()
            grid.ShallowCopy(sgrid)
            grid.GetPointData().SetActiveScalars(None)

            cutter = vtk.vtkCutter()
            cutter.SetInput(grid)
            cutter.SetCutFunction(plane)
            cutter.Update()

            polygon = cutter.GetOutput()
            points = polygon.GetPoints()

            for i in xrange(points.GetNumberOfPoints()):
                x, y, z = self._transMatrix.TransformPoint(points.GetPoint(i))
                points.SetPoint(i, x, y, 0.0)
                pass

            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInput(polygon)

            regionAreaActor.SetMapper(mapper)
            pass
        return

    def CreateImageDataFile(self, imageType, filename):
        if imageType == 'PostScript':
            writer = vtk.vtkPostScriptWriter()
            pass
        elif imageType == 'JPEG':
            writer = vtk.vtkJPEGWriter()
            pass
        elif imageType == 'PNM':
            writer = vtk.vtkPNMWriter()
            pass
        elif imageType == 'TIFF':
            writer = vtk.vtkTIFFWriter()
            pass

        filter = vtk.vtkWindowToImageFilter()
        filter.SetInput(self.GetRenderWindow())
        # filter.Update()

        writer.SetInput(filter.GetOutput())
        # writer.SetInputConnection(filter.GetOutputPort())
        writer.SetFileName(filename)
        # self.GetRenderWindow().Render()
        writer.Write()
        return

class QRegionGraphPanel(VTKPanelBase):
    def __init__(self, parent):
        VTKPanelBase.__init__(self, parent)

        self.__renderer = vtk.vtkRenderer()
        self.GetRenderWindow().AddRenderer(self.__renderer)

        self.__graphActors = []
        self.__gridActors = []
        self.__labelActors = []

        self.__mainFrame = self.GetParent().GetParent().GetParent().GetParent()
        return

    def SetupGraph(self, etmin, etmax, stepNumber):
        HUGE = 1.0e+30
        self.__bounds = [HUGE, -HUGE, HUGE, -HUGE, 0.0, 0.0]

        thinDetectableRegions = self.__mainFrame.GetThinDetectableRegions(etmin, etmax)

        psi = math.radians(self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_PSI0))
        chi = math.radians(self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_CHI0))
        phi = math.radians(self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_PHI0))

        rotateAxis = self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_ROTATEAXIS)
        interval = math.radians(self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_INTERVAL))
        nstep = self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_NSTEP)

        qOrigin, qU, qV = self.__mainFrame.GetQRegionGraphAxis()

        psi2 = psi
        chi2 = chi
        phi2 = phi

        checkedRegions = self.__mainFrame.GetCheckedRegions()

        # Show loading progress bar
        progressDialog = wx.ProgressDialog('Progress status',
                                           'Please wait for construct regions',
                                           nstep)

        self.__graphActors.append([])

        for i in xrange(nstep + 1):
            if rotateAxis == 0:
                psi2 = psi + interval * i
                pass
            elif rotateAxis == 1:
                chi2 = chi + interval * i
                pass
            elif rotateAxis == 2:
                phi2 = phi + interval * i
                pass
            else:
                print 'Rotation axis error is found!'
                pass

            import vector

            vtkRotaionMatrix = GetRotationMatrix(psi2, chi2, phi2)

            qUrot = vtkRotaionMatrix.TransformPoint(qU)
            qVrot = vtkRotaionMatrix.TransformPoint(qV)
            qOrot = vtkRotaionMatrix.TransformPoint(qOrigin)
            qNrot = vector.GetCross(qUrot, qVrot)

            if i == 0:
                color = (0, 0, 1)
                offset = 1.0e-4
                pass
            elif i == nstep:
                color = (1, 0, 0)
                offset = 2.0e-4
                pass
            else:
                color = (1, 1, 1)
                offset = 0.0
                pass

            offset += stepNumber

            self.__SetupTransformMatrix(qOrot, qUrot, qVrot)

            self.SetupRegion(color, offset, qOrot, qNrot, checkedRegions, thinDetectableRegions)

            progressDialog.Update(i)
            pass
        self.SetupBoundIndices()
        self.SetupGridLines(stepNumber)
        self.__SetupXYLabels(stepNumber)

        progressDialog.Destroy()
        return

    def __SetupTransformMatrix(self, qOrigin, qU, qV):
        thetaZ = -math.atan2(qU[1], qU[0])

        qUa = (qU[0] * math.cos(thetaZ) - qU[1] * math.sin(thetaZ),
               0.0,
               qU[2])
        qVa = (qV[0] * math.cos(thetaZ) - qV[1] * math.sin(thetaZ),
               qV[0] * math.sin(thetaZ) + qV[1] * math.cos(thetaZ),
               qV[2])

        thetaY = math.atan2(qUa[2], qUa[0])

        qUb = (qUa[0] * math.cos(thetaY) + qUa[2] * math.sin(thetaY),
               0.0,
               0.0)

        qVb = (qVa[0] * math.cos(thetaY) + qVa[2] * math.sin(thetaY),
               qVa[1],
               - qVa[0] * math.sin(thetaY) + qVa[2] * math.cos(thetaY))

        thetaX = -math.atan2(qVb[2], qVb[1])

        self.__axisU = qUb
        self.__axisV = (qVb[0],
                      qVb[1] * math.cos(thetaX) - qVb[2] * math.sin(thetaX),
                      0.0)

        self.__transMatrix = vtk.vtkTransform()

        self.__transMatrix.RotateX(math.degrees(thetaX))
        self.__transMatrix.RotateY(math.degrees(thetaY))
        self.__transMatrix.RotateZ(math.degrees(thetaZ))
        self.__transMatrix.Translate(-qOrigin[0], -qOrigin[1], -qOrigin[2])
        return

    def SetupRegion(self, color, offset, qOrigin, qNormal, checkedRegions, regionPoints):
        for regionName in checkedRegions:
            points = vtk.vtkPoints()
            points.SetNumberOfPoints(len(regionPoints[regionName]['ponits']))

            for i in xrange(len(regionPoints[regionName]['ponits'])):
                points.SetPoint(i, regionPoints[regionName]['ponits'][i][0],
                                regionPoints[regionName]['ponits'][i][1],
                                regionPoints[regionName]['ponits'][i][2])
                pass

            sgrid = vtk.vtkStructuredGrid()
            sgrid.SetDimensions(regionPoints[regionName]['dimensions'])
            sgrid.SetPoints(points)

            plane = vtk.vtkPlane()
            plane.SetOrigin(qOrigin)
            plane.SetNormal(qNormal)

            cutter = vtk.vtkCutter()
            cutter.SetInput(sgrid)
            cutter.SetCutFunction(plane)
            cutter.Update()

            polyData = cutter.GetOutput()
            points = polyData.GetPoints()

            # Translate and rotate cut-plane
            for i in xrange(points.GetNumberOfPoints()):
                pos = points.GetPoint(i)
                x, y, dummy = self.__transMatrix.TransformPoint(pos)
                points.SetPoint(i, x, y, offset)
                pass

            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInput(polyData)

            actor = vtk.vtkActor()
            actor.SetMapper(mapper)
            actor.GetProperty().SetColor(color)

            self.__renderer.AddActor(actor)
            self.__graphActors[-1].append(actor)

            bounds = actor.GetBounds()

            for i in (0, 2):
                self.__bounds[i] = min(self.__bounds[i], bounds[i])
                self.__bounds[i + 1] = max(self.__bounds[i + 1], bounds[i + 1])
                pass
            pass
        return

    def SetupBoundIndices(self):
        qumin, qumax, qvmin, qvmax, dummy, dummy = self.__bounds
        u = self.__axisU
        v = self.__axisV

        A = [[u[0], v[0]],
             [u[1], v[1]]]

        det = A[0][0] * A[1][1] - A[0][1] * A[1][0]

        M = [[A[1][1] / det, -A[0][1] / det],
             [-A[1][0] / det, A[0][0] / det]]

        phi = [ApplyMat2D(M, [qumin, qvmin]),
               ApplyMat2D(M, [qumin, qvmax]),
               ApplyMat2D(M, [qumax, qvmin]),
               ApplyMat2D(M, [qumax, qvmax])]

        imin = phi[0][0]
        imax = phi[0][0]
        jmin = phi[0][1]
        jmax = phi[0][1]

        for x in phi:
            imin = min(x[0], imin)
            imax = max(x[0], imax)
            jmin = min(x[1], jmin)
            jmax = max(x[1], jmax)
            pass

        self.__imin = int(math.floor(imin))
        self.__jmin = int(math.floor(jmin))

        self.__imax = int(math.ceil(imax))
        self.__jmax = int(math.ceil(jmax))
        return

    def SetupGridLines(self, stepNumber):
        axisU = self.__axisU
        axisV = self.__axisV

        imin = self.__imin
        imax = self.__imax
        jmin = self.__jmin
        jmax = self.__jmax

        sgrid = vtk.vtkStructuredGrid()
        sgrid.SetExtent(imin, imax, jmin, jmax, 0, 0)

        size = (imax - imin + 1) * (jmax - jmin + 1)

        points = vtk.vtkPoints()
        points.SetNumberOfPoints(size)

        count = 0
        for j in xrange(jmin, jmax + 1):
            for i in xrange(imin, imax + 1):
                points.SetPoint(count,
                                axisU[0] * i + axisV[0] * j,
                                axisU[1] * i + axisV[1] * j,
                                0.0)
                count += 1
                pass
            pass

        sgrid.SetPoints(points)

        sgridMapper = vtk.vtkDataSetMapper()
        sgridMapper.SetInput(sgrid)

        actor = vtk.vtkActor()
        actor.SetMapper(sgridMapper)
        actor.GetProperty().SetRepresentationToWireframe()
        actor.GetProperty().SetColor(0.502, 0.502, 0.502)
        actor.GetProperty().SetOpacity(0.25)
        actor.SetPosition(0.0, 0.0, stepNumber - 1.0e-6)

        self.__renderer.AddActor(actor)
        self.__gridActors.append(actor)
        return

    def __SetupXYLabels(self, stepNumber):
        plane = self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_PLANEDEF)

        # Set U,V axis labels
        orig = (self.__mainFrame.GetParameter(qspace.TAG_QEGRAPH_OH),
                self.__mainFrame.GetParameter(qspace.TAG_QEGRAPH_OK),
                self.__mainFrame.GetParameter(qspace.TAG_QEGRAPH_OL))

        if plane == 0:
            udir = (1, 0, 0)
            vdir = (0, 1, 0)
            pass
        elif plane == 1:
            udir = (0, 1, 0)
            vdir = (0, 0, 1)
            pass
        elif plane == 2:
            udir = (0, 0, 1)
            vdir = (1, 0, 0)
            pass
        else:
            udir = (self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_UH),
                    self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_UK),
                    self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_UL))

            vdir = (self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_VH),
                    self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_VK),
                    self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_VL))
            pass

        self.__labelActors.append([])

        labelOffset = 0.1

        y0 = self.__axisU[1] * self.__imin + self.__axisV[1] * self.__jmin

        for i in xrange(self.__imin + 1, self.__imax):
            miller = (udir[0] * i + vdir[0] * self.__jmin + orig[0],
                      udir[1] * i + vdir[1] * self.__jmin + orig[1],
                      udir[2] * i + vdir[2] * self.__jmin + orig[2])

            text = vtk.vtkVectorText()
            text.SetText(str(miller))
            textMapper = vtk.vtkPolyDataMapper()
            textMapper.SetInputConnection(text.GetOutputPort())

            x = self.__axisU[0] * i + self.__axisV[0] * self.__jmin

            labelActor = vtk.vtkFollower()
            labelActor.SetCamera(self.__renderer.GetActiveCamera())
            labelActor.SetMapper(textMapper)
            labelActor.SetScale(0.075, 0.075, 0.075)
            labelActor.SetPosition(x, y0, stepNumber)

            self.__renderer.AddActor(labelActor)

            self.__labelActors[-1].append(labelActor)
            pass

        for j in xrange(self.__jmin + 1, self.__jmax):
            miller = (udir[0] * self.__imin + vdir[0] * j + orig[0],
                      udir[1] * self.__imin + vdir[1] * j + orig[1],
                      udir[2] * self.__imin + vdir[2] * j + orig[2])

            text = vtk.vtkVectorText()
            text.SetText(str(miller))
            textMapper = vtk.vtkPolyDataMapper()
            textMapper.SetInputConnection(text.GetOutputPort())

            x = self.__axisU[0] * self.__imin + self.__axisV[0] * j
            y = self.__axisU[1] * self.__imin + self.__axisV[1] * j

            labelActor = vtk.vtkFollower()
            labelActor.SetCamera(self.__renderer.GetActiveCamera())
            labelActor.SetMapper(textMapper)
            labelActor.SetScale(0.075, 0.075, 0.075)
            labelActor.SetPosition(x, y, stepNumber)

            self.__renderer.AddActor(labelActor)

            self.__labelActors[-1].append(labelActor)
            pass
        return

    def SetLegendBox(self):
        plane = self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_PLANEDEF)

        if plane == 0:
            title = 'QR graph on a*b plane'
            pass
        elif plane == 1:
            title = 'QR graph on b*c plane'
            pass
        elif plane == 2:
            title = 'QR graph on c*a plane'
            pass
        else:
            title = 'QR graph on u*v plane'
            pass

        psi = self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_PSI0)
        chi = self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_CHI0)
        phi = self.__mainFrame.GetParameter(qspace.TAG_QRGRAPH_PHI0)

        labels = (title, 'psi,chi,phi=%g, %g, %g [deg.]' % (psi, chi, phi))

        legend = vtk.vtkLegendBoxActor()
        legend.SetNumberOfEntries(len(labels))
        legend.SetPosition(0.025, 0.875)
        legend.SetWidth(0.5)
        legend.SetHeight(0.1)

        for i in xrange(len(labels)):
            legend.SetEntryString(i, labels[i])
            pass

        tprop = vtk.vtkTextProperty()
        tprop.SetVerticalJustificationToCentered()

        legend.SetEntryTextProperty(tprop)
        legend.BorderOn()

        self.__renderer.AddActor(legend)
        return

    def SetupLight(self):
        lightKit = vtk.vtkLightKit()
        lightKit.SetKeyLightIntensity(1.0)
        lightKit.AddLightsToRenderer(self.__renderer)
        return

    def SetupCamera(self):
        xw = self.__bounds[1] - self.__bounds[0]
        yw = self.__bounds[3] - self.__bounds[2]

        xc = 0.5 * (self.__bounds[1] + self.__bounds[0])
        yc = 0.5 * (self.__bounds[3] + self.__bounds[2])
        zc = 0.5 * (self.__bounds[5] + self.__bounds[4])

        angle = 45

        camera = self.__renderer.GetActiveCamera()
        camera.SetFocalPoint([xc, yc, zc])
        camera.SetViewAngle(angle)
        camera.SetClippingRange([0.01, 100.0])
        camera.UseHorizontalViewAngleOn()

        scale = math.sqrt(xw * xw + yw * yw)
        distance = 0.7 * scale / math.tan(math.radians(angle / 2.0))
        camera.SetPosition([xc, - distance - self.__bounds[5], distance + self.__bounds[5]])
        camera.SetViewUp([0.0, 1.0, 0.0])
        camera.SetParallelScale(0.55 * scale)
        return

    def GraphControl(self, number, isShow):
        if isShow:
            i = 0
            for actor in self.__graphActors[number]:
                actor.VisibilityOn()
                pass

            self.__gridActors[number].VisibilityOn()

            for actor in self.__labelActors[number]:
                actor.VisibilityOn()
                pass
            pass
        else:
            for actor in self.__graphActors[number]:
                actor.VisibilityOff()
                pass

            self.__gridActors[number].VisibilityOff()

            for actor in self.__labelActors[number]:
                actor.VisibilityOff()
                pass
            pass

        self.Render()
        pass

def GetRotationMatrix(psi, chi, phi):
    matrix = vtk.vtkTransform()
    matrix.Identity()

    # Y-X-Z rotation system
    matrix.RotateZ(math.degrees(phi))
    matrix.RotateX(math.degrees(chi))
    matrix.RotateY(math.degrees(psi))
    return matrix

def ApplyMat2D(M, x):
    return [M[0][0] * x[0] + M[0][1] * x[1],
            M[1][0] * x[0] + M[1][1] * x[1]]
