#!/usr/bin/python
# -*- coding:Utf-8 -*-

#----------------------------------------------------------------------------------------------------
#	Visualization Project : 2D Spatial Data
#
# Author : Arthur COSTE
# Creation Date : October 29th, 2012
# Update Date :
# Version : 1
# Status : Working
#
# Purpose : transfert functions
#
#----------------------------------------------------------------------------------------------------

# loading libraries
import argparse
import vtk
import sys

# read input vtk file
reader = vtk.vtkGenericDataObjectReader()
reader.SetFileName(sys.argv[1])
reader.Update()

# VTK's site explanation
# The volume will be displayed by ray-cast alpha compositing.
# A ray-cast mapper is needed to do the ray-casting, and a
# compositing function is needed to do the compositing along the ray.
rayCastFunction = vtk.vtkVolumeRayCastCompositeFunction()
#rayCastFunction = vtk.vtkVolumeRayCastMIPFunction()
#rayCastFunction = vtk.vtkVolumeRayCastIsosurfaceFunction()
#rayCastFunction.SetIsoValue(120)

volumeMapper = vtk.vtkVolumeRayCastMapper()
volumeMapper.SetInputConnection(reader.GetOutputPort())
volumeMapper.SetVolumeRayCastFunction(rayCastFunction)

# VTK's site explanation
# The color transfer function maps voxel intensities to colors.
# It is modality-specific, and often anatomy-specific as well.
# The goal is to one color for flesh (between 500 and 1000)
# and another color for bone (1150 and over).
volumeColor = vtk.vtkColorTransferFunction()
volumeColor.AddRGBPoint(0,    1.0, 0.8, 0.7)
volumeColor.AddRGBPoint(10, 0, 0, 0)
volumeColor.AddRGBPoint(30,  1.0, 0.5, 0.4)
volumeColor.AddRGBPoint(60, 0, 0, 0)
volumeColor.AddRGBPoint(80, 1.0, 1.0, 0.9)

# another color transfert function
volumeColor2 = vtk.vtkColorTransferFunction()
volumeColor2.AddRGBPoint(00, 0, 0, 0)
volumeColor2.AddRGBPoint(128, 1.0, 1.0, 1.0)
volumeColor2.AddRGBPoint(255, 0.0, 0, 0)
 
# The opacity transfer function is used to control the opacity
# of different tissue types.
volumeScalarOpacity = vtk.vtkPiecewiseFunction()
volumeScalarOpacity.AddPoint(0,    0.00)
volumeScalarOpacity.AddPoint(10,  0.3)
volumeScalarOpacity.AddPoint(30,  0.25)
volumeScalarOpacity.AddPoint(60, 0.2)
volumeScalarOpacity.AddPoint(80, 1.0)
volumeScalarOpacity.AddPoint(200, 0.0)

# VTK's site explanation
# The gradient opacity function is used to decrease the opacity
# in the "flat" regions of the volume while maintaining the opacity
# at the boundaries between tissue types.  The gradient is measured
# as the amount by which the intensity changes over unit distance.
# For most medical data, the unit distance is 1mm.
volumeGradientOpacity = vtk.vtkPiecewiseFunction()
volumeGradientOpacity.AddPoint(0,   0.0)
volumeGradientOpacity.AddPoint(25,  0.5)
volumeGradientOpacity.AddPoint(0,   0.0)
volumeGradientOpacity.AddPoint(80, 1.0)

# VTK's site explanation
# The VolumeProperty attaches the color and opacity functions to the
# volume, and sets other volume properties.  The interpolation should
# be set to linear to do a high-quality rendering.  The ShadeOn option
# turns on directional lighting, which will usually enhance the
# appearance of the volume and make it look more "3D".  However,
# the quality of the shading depends on how accurately the gradient
# of the volume can be calculated, and for noisy data the gradient
# estimation will be very poor.  The impact of the shading can be
# decreased by increasing the Ambient coefficient while decreasing
# the Diffuse and Specular coefficient.  To increase the impact
# of shading, decrease the Ambient and increase the Diffuse and Specular.
volumeProperty = vtk.vtkVolumeProperty()
volumeProperty.SetColor(volumeColor)
volumeProperty.SetScalarOpacity(volumeScalarOpacity)
volumeProperty.SetGradientOpacity(volumeGradientOpacity)
# interpolation function
#volumeProperty.SetInterpolationTypeToNearest()
volumeProperty.SetInterpolationTypeToLinear()
# Phong's illumination model
volumeProperty.ShadeOn()
volumeProperty.SetAmbient(1.0)
volumeProperty.SetDiffuse(0.7)
volumeProperty.SetSpecular(0.5)

# The vtkVolume is a vtkProp3D (like a vtkActor) and controls the position
# and orientation of the volume in world coordinates.
volume = vtk.vtkVolume()
volume.SetMapper(volumeMapper)
volume.SetProperty(volumeProperty)

#create mapper
#The contour lines are mapped to the graphics library.
contMapper = vtk.vtkDataSetMapper()
contMapper.SetInputConnection(reader.GetOutputPort())
contMapper.SetScalarRange(00.0, 255)

#perform rendering
actor = vtk.vtkActor()
actor.SetMapper(contMapper)
actor.GetProperty().SetPointSize(1)
renderer = vtk.vtkRenderer()
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
#renderer.AddActor(actor)

# Finally, add the volume to the renderer
renderer.AddActor(volume)

# modify initial display parameters
renderer.ResetCamera()
renderer.GetActiveCamera().Azimuth(-00)
renderer.GetActiveCamera().Elevation(1)
renderer.GetActiveCamera().SetViewUp(0,0,1)
#renderer.SetBackground(0.2, 0.4, 0.6)
renderer.ResetCameraClippingRange()
renderWindow.SetSize(500, 500)

renderWindow.Render()
renderWindowInteractor.Start()
