/*============================================================================= Project: SharpImage Module: siVolumeProperties.cs Language: C# Author: Dan Mueller Date: $Date: 2007-07-06 10:57:00 +1000 (Fri, 06 Jul 2007) $ Revision: $Revision: 2 $ Copyright (c) Queensland University of Technology (QUT) 2007. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =============================================================================*/ using System; using System.IO; using System.Text; using System.Collections; using System.Diagnostics; using System.Drawing; using System.Drawing.Design; using System.Drawing.Imaging; using System.Drawing.Drawing2D; using System.Windows.Forms; using System.ComponentModel; using System.Xml.Serialization; using Tao.OpenGl; using Tao.FreeGlut; using Tao.Platform.Windows; using SharpImage.Main; using SharpImage.Forms; using SharpImage.SpatialObject; namespace SharpImage.Rendering { /// /// Describes the different blending options. /// public enum siVolumeBlendEnum { BackToFront, MaximumProjection, MinimumProjection, } /// /// Describes the different texture mapping geometry options. /// public enum siVolumeGeometryEnum { ViewAlignedFill, ViewAlignedSingle, ViewAlignedSlab, Orthogonal } /// /// Encapsulates properties for volume rendering. /// public class siVolumeProperties { #region Instance Variables //============================================================================ private siVolumeRenderer m_Renderer; //============================================================================ #endregion #region Construction and Disposal //============================================================================ /// /// Constructor for serialization. /// protected siVolumeProperties() { } /// /// Default constructor. /// public siVolumeProperties(siVolumeRenderer renderer) { this.m_Renderer = renderer; this.UpdateToRenderer(); } //============================================================================ #endregion #region Properties //============================================================================ #region Renderer //===================================================================== /// /// Get the renderer these properties are attached. /// [System.Xml.Serialization.XmlIgnore] protected siVolumeRenderer Renderer { get { return this.m_Renderer; } } //===================================================================== #endregion #region BackColor //===================================================================== private Color m_BackColor = Color.White; /// /// Gets/sets the background color of the Renderer window. /// [Browsable(true)] [Category("Color")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [System.Xml.Serialization.XmlIgnore] public Color BackColor { get { return this.Renderer.BackColor; } set { this.m_BackColor = value; if (this.Renderer != null) { float[] back = siColorHelper.To4fv(value); Gl.glClearColor(back[0], back[1], back[2], back[3]); this.Renderer.BackColor = value; this.Renderer.Repaint(); } } } //===================================================================== #endregion #region ViewportSize //===================================================================== private Size m_ViewportSize = new Size(350, 350); /// /// Gets/sets the viewport size. /// [Browsable(true)] [Category("Size and Transform")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public Size ViewportSize { get { return this.Renderer.ViewportSize; } set { this.m_ViewportSize = value; if (this.Renderer != null) this.Renderer.ViewportSize = value; } } //===================================================================== #endregion #region BoxOutline //===================================================================== private bool m_BoxOutlineEnabled = true; private Color m_BoxOutlineColor = Color.FromArgb(60, Color.Gray); /// /// Gets/sets the RGB color of the outline box drawn around the the volume. /// This property is used for user interaction. Use BoxOutlineColor to /// set the RGBA color. /// [Browsable(true)] [Category("BoxOutline")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public bool BoxOutlineEnabled { get { return this.m_BoxOutlineEnabled; } set { this.m_BoxOutlineEnabled = value; if (this.Renderer != null) this.Renderer.Repaint(); } } /// /// Gets/sets the color of the outline box drawn around the the volume. /// [Browsable(false)] [System.Xml.Serialization.XmlIgnore] public Color BoxOutlineColor { get { return this.m_BoxOutlineColor; } set { this.m_BoxOutlineColor = value; if (this.Renderer != null) this.Renderer.Repaint(); } } /// /// Gets/sets the RGB color of the outline box drawn around the the volume. /// This property is used for user interaction. Use BoxOutlineColor to /// set the RGBA color. /// [Browsable(true)] [Category("BoxOutline")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [System.Xml.Serialization.XmlIgnore] public Color BoxOutlineColorRGB { get { return siColorHelper.ColorFromRgb(this.BoxOutlineColor); } set { this.BoxOutlineColor = Color.FromArgb(this.BoxOutlineColor.A, value); } } /// /// Gets/sets the Alpha component of the outline box drawn around the the volume. /// This property is used for user interaction. Use BoxOutlineColor to /// set the RGBA color. /// [Browsable(true)] [Category("BoxOutline")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [System.Xml.Serialization.XmlIgnore] public int BoxOutlineColorA { get { return this.BoxOutlineColor.A; } set { this.BoxOutlineColor = Color.FromArgb(value, this.BoxOutlineColor); } } //===================================================================== #endregion #region gluLookAt //===================================================================== private double m_EyeX = 0.0; private double m_EyeY = 0.0; private double m_EyeZ = -7.5; private double m_CenterX = 0.0; private double m_CenterY = 0.0; private double m_CenterZ = 0.0; private double m_UpX = 0.0; private double m_UpY = 1.0; private double m_UpZ = 0.0; /// /// Gets/sets the x-position to look at using Glu.gluLookAt. /// [Browsable(false)] public double EyeX { get { return this.m_EyeX; } set { this.m_EyeX = value; } } /// /// Gets/sets the y-position to look at using Glu.gluLookAt. /// [Browsable(false)] public double EyeY { get { return this.m_EyeY; } set { this.m_EyeY = value; } } /// /// Gets/sets the z-position to look at using Glu.gluLookAt. /// [Browsable(false)] public double EyeZ { get { return this.m_EyeZ; } set { this.m_EyeZ = value; } } /// /// Gets/sets the Center x-position to look at using Glu.gluLookAt. /// [Browsable(false)] public double CenterX { get { return this.m_CenterX; } set { this.m_CenterX = value; } } /// /// Gets/sets the Center y-position to look at using Glu.gluLookAt. /// [Browsable(false)] public double CenterY { get { return this.m_CenterY; } set { this.m_CenterY = value; } } /// /// Gets/sets the Center z-position to look at using Glu.gluLookAt. /// [Browsable(false)] public double CenterZ { get { return this.m_CenterZ; } set { this.m_CenterZ = value; } } /// /// Gets/sets the Up x-position to look at using Glu.gluLookAt. /// [Browsable(false)] public double UpX { get { return this.m_UpX; } set { this.m_UpX = value; } } /// /// Gets/sets the Up y-position to look at using Glu.gluLookAt. /// [Browsable(false)] public double UpY { get { return this.m_UpY; } set { this.m_UpY = value; } } /// /// Gets/sets the Up z-position to look at using Glu.gluLookAt. /// [Browsable(false)] public double UpZ { get { return this.m_UpZ; } set { this.m_UpZ = value; } } //===================================================================== #endregion #region Frustrum //===================================================================== private double m_FrustrumLeft = 0.2; private double m_FrustrumRight = -0.2; private double m_FrustrumTop = 0.2; private double m_FrustrumBottom = -0.2; private double m_FrustrumFront = 1.0; private double m_FrustrumBack = 20.0; /// /// Gets/sets the left limit of the Frustrum. /// [Browsable(true)] [Category("Frustrum")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public double FrustrumLeft { get { return this.m_FrustrumLeft; } set { if (this.Renderer != null) this.Renderer.Metadata["FrustrumLeft"] = value; this.m_FrustrumLeft = value; } } /// /// Gets/sets the right limit of the Frustrum. /// [Browsable(true)] [Category("Frustrum")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public double FrustrumRight { get { return this.m_FrustrumRight; } set { if (this.Renderer != null) this.Renderer.Metadata["FrustrumRight"] = value; this.m_FrustrumRight = value; } } /// /// Gets/sets the top limit of the Frustrum. /// [Browsable(true)] [Category("Frustrum")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public double FrustrumTop { get { return this.m_FrustrumTop; } set { if (this.Renderer != null) this.Renderer.Metadata["FrustrumTop"] = value; this.m_FrustrumTop = value; } } /// /// Gets/sets the bottom limit of the Frustrum. /// [Browsable(true)] [Category("Frustrum")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public double FrustrumBottom { get { return this.m_FrustrumBottom; } set { if (this.Renderer != null) this.Renderer.Metadata["FrustrumBottom"] = value; this.m_FrustrumBottom = value; } } /// /// Gets/sets the front limit of the Frustrum. /// [Browsable(true)] [Category("Frustrum")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public double FrustrumFront { get { return this.m_FrustrumFront; } set { if (this.Renderer != null) this.Renderer.Metadata["FrustrumFront"] = value; this.m_FrustrumFront = value; } } /// /// Gets/sets the back limit of the Frustrum. /// [Browsable(true)] [Category("Frustrum")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public double FrustrumBack { get { return this.m_FrustrumBack; } set { if (this.Renderer != null) this.Renderer.Metadata["FrustrumBack"] = value; this.m_FrustrumBack = value; } } //===================================================================== #endregion #region Transforms //===================================================================== private itk.itkVector m_TransformTranslate = new itk.itkVector(0.0, 0.0, 0.0); private siTrackBall m_TrackBall = new siTrackBall(); /// /// Gets/sets the translation vector. /// [ReadOnly(true)] [Browsable(true)] [Category("Size and Transform")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [System.Xml.Serialization.XmlIgnore] public itk.itkVector TransformTranslate { get { return this.m_TransformTranslate; } set { this.m_TransformTranslate = value; } } /// /// Gets/sets the trackball. /// [Browsable(false)] [System.Xml.Serialization.XmlIgnore] public siTrackBall TrackBall { get { return this.m_TrackBall; } set { this.m_TrackBall = value; } } /// /// Gets the rotation transform. /// This property is used for user interaction. /// //[ReadOnly(true)] [Browsable(true)] [Category("Size and Transform")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [TypeConverter(typeof(itkVectorTypeConverter))] [System.Xml.Serialization.XmlIgnore] public itk.itkVector TransformRotation { get { return new itk.itkVector(this.TrackBall.GetRotationMatrixAsArray()); } set { itk.itkMatrix matrix = new itk.itkMatrix(3, 3); for (uint r = 0; r < 3; r++) for (uint c = 0; c < 3; c++) matrix[r, c] = value[(int)(r * 4 + c)]; this.TrackBall.RotationMatrix = matrix; if (this.Renderer != null) this.Renderer.Repaint(); } } //===================================================================== #endregion #region ModelSize //===================================================================== private itk.itkArray m_ModelSize = new itk.itkArray(1.0,1.0,1.0); /// /// Gets/sets the size of the model in model space. /// The model size would be [1.0, 1.0, 1.0] for an image with /// spacing equalling [1.0, 1.0, 1.0]. /// [ReadOnly(true)] [Browsable(true)] [Category("Size and Transform")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [System.Xml.Serialization.XmlIgnore] public itk.itkArray ModelSize { get { return this.m_ModelSize; } set { this.m_ModelSize = value; } } //===================================================================== #endregion #region FragmentProgramPath //===================================================================== private string m_FragmentProgramPath = String.Empty; [Browsable(true)] [Category("Rendering")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [Editor(typeof(siOpenFilenameEditor), typeof(UITypeEditor))] [TypeConverter(typeof(siOpenFilenameTypeConverter))] [siFilenameEditorFilter("Fragment Shader Program Files (*.frag)|*.frag")] [System.Xml.Serialization.XmlIgnore] public String FragmentProgramPath { get { return this.Renderer.Shader.FragmentProgramPath; } set { this.m_FragmentProgramPath = value; if (this.Renderer != null) this.Renderer.SetShader(value); } } //===================================================================== #endregion #region WireFrame //===================================================================== private bool m_WireFrame = false; /// /// Gets/sets if the texture geometry is rendered as a wire frame. /// [Browsable(true)] [Category("Rendering")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public bool WireFrame { get { return this.m_WireFrame; } set { this.m_WireFrame = value; if (this.Renderer != null) this.Renderer.Repaint(); } } //===================================================================== #endregion #region Lighting //===================================================================== private Color m_LightColorAmbient = Color.White; private Color m_LightColorDiffuse = Color.White; private Color m_LightColorSpecular = Color.White; private float m_LightColorSpecularExponent = 2.0f; private float m_NormalOffset = 0.0396f; /// /// Gets/sets the ambient color of Light0. /// [Browsable(false)] [Category("Lighting")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [System.Xml.Serialization.XmlIgnore] public Color LightColorAmbient { get { return this.m_LightColorAmbient; } set { this.m_LightColorAmbient = value; } } /// /// Gets/sets the ambient color.A of Light0. /// [Browsable(true)] [Category("Lighting")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [System.Xml.Serialization.XmlIgnore] public int LightColorAmbientA { get { return this.m_LightColorAmbient.A; } set { Color colorOld = this.m_LightColorAmbient; Color colorNew = Color.FromArgb(value, colorOld); this.m_LightColorAmbient = colorNew; if (this.Renderer != null) this.Renderer.Repaint(); } } /// /// Gets/sets the ambient color.RGB of Light0. /// [Browsable(true)] [Category("Lighting")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [System.Xml.Serialization.XmlIgnore] public Color LightColorAmbientRGB { get { return siColorHelper.ColorFromRgb(this.m_LightColorAmbient); } set { Color colorNew = Color.FromArgb(this.LightColorAmbientA, value); this.m_LightColorAmbient = colorNew; if (this.Renderer != null) this.Renderer.Repaint(); } } /// /// Gets/sets the diffuse color of Light0. /// [Browsable(false)] [Category("Lighting")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [System.Xml.Serialization.XmlIgnore] public Color LightColorDiffuse { get { return this.m_LightColorDiffuse; } set { this.m_LightColorDiffuse = value; if (this.Renderer != null) this.Renderer.Repaint(); } } /// /// Gets/sets the diffuse color.A of Light0. /// [Browsable(true)] [Category("Lighting")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [System.Xml.Serialization.XmlIgnore] public int LightColorDiffuseA { get { return this.m_LightColorDiffuse.A; } set { Color colorOld = this.m_LightColorDiffuse; Color colorNew = Color.FromArgb(value, colorOld); this.m_LightColorDiffuse = colorNew; if (this.Renderer != null) this.Renderer.Repaint(); } } /// /// Gets/sets the diffuse color.RGB of Light0. /// [Browsable(true)] [Category("Lighting")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [System.Xml.Serialization.XmlIgnore] public Color LightColorDiffuseRGB { get { return siColorHelper.ColorFromRgb(this.m_LightColorDiffuse); } set { Color colorNew = Color.FromArgb(this.LightColorDiffuseA, value); this.m_LightColorDiffuse = colorNew; if (this.Renderer != null) this.Renderer.Repaint(); } } /// /// Gets/sets the specular color of Light0. /// [Browsable(false)] [Category("Lighting")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [System.Xml.Serialization.XmlIgnore] public Color LightColorSpecular { get { return this.m_LightColorSpecular; } set { this.m_LightColorSpecular = value; if (this.Renderer != null) this.Renderer.Repaint(); } } /// /// Gets/sets the specular color.A of Light0. /// [Browsable(true)] [Category("Lighting")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [System.Xml.Serialization.XmlIgnore] public int LightColorSpecularA { get { return this.m_LightColorSpecular.A; } set { Color colorOld = this.m_LightColorSpecular; Color colorNew = Color.FromArgb(value, colorOld); this.m_LightColorSpecular = colorNew; if (this.Renderer != null) this.Renderer.Repaint(); } } /// /// Gets/sets the specular color.RGB of Light0. /// [Browsable(true)] [Category("Lighting")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [System.Xml.Serialization.XmlIgnore] public Color LightColorSpecularRGB { get { return siColorHelper.ColorFromRgb(this.m_LightColorSpecular); } set { Color colorNew = Color.FromArgb(this.LightColorSpecularA, value); this.m_LightColorSpecular = colorNew; if (this.Renderer != null) this.Renderer.Repaint(); } } /// /// Gets/sets the specular exponent. /// [Browsable(true)] [Category("Lighting")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public float LightColorSpecularExponent { get { return this.m_LightColorSpecularExponent; } set { this.m_LightColorSpecularExponent = value; if (this.Renderer != null) this.Renderer.Repaint(); } } /// /// Gets/sets the offset for computing the normal. /// [Browsable(true)] [Category("Lighting")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public float NormalOffset { get { return this.m_NormalOffset; } set { // Save the value this.m_NormalOffset = value; // Set the value in the sahder if (this.Renderer != null&& this.Renderer.ContainsMetadata("Shader")) { this.Renderer.Shader.SetUniformFloat("fNormalOffset", value); this.Renderer.RaiseModified(); this.Renderer.Repaint(); } } } //===================================================================== #endregion #region EnhanceFactor //===================================================================== private float m_EnhanceFactor1 = 0.0f; private float m_EnhanceFactor2 = 0.0f; private float m_EnhanceFactor3 = 0.0f; /// /// Gets/sets the enhancement factor. /// [Browsable(true)] [Category("Enhancement")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public float EnhanceFactor1 { get { return this.m_EnhanceFactor1; } set { // Save the value this.m_EnhanceFactor1 = value; // Set the value in the sahder if (this.Renderer != null && this.Renderer.ContainsMetadata("Shader")) { this.Renderer.Shader.SetUniformFloat("fEnhanceFactor1", value); this.Renderer.RaiseModified(); this.Renderer.Repaint(); } } } /// /// Gets/sets the enhancement factor. /// [Browsable(true)] [Category("Enhancement")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public float EnhanceFactor2 { get { return this.m_EnhanceFactor2; } set { // Save the value this.m_EnhanceFactor2 = value; // Set the value in the sahder if (this.Renderer != null && this.Renderer.ContainsMetadata("Shader")) { this.Renderer.Shader.SetUniformFloat("fEnhanceFactor2", value); this.Renderer.RaiseModified(); this.Renderer.Repaint(); } } } /// /// Gets/sets the enhancement factor. /// [Browsable(true)] [Category("Enhancement")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public float EnhanceFactor3 { get { return this.m_EnhanceFactor3; } set { // Save the value this.m_EnhanceFactor3 = value; // Set the value in the sahder if (this.Renderer != null && this.Renderer.ContainsMetadata("Shader")) { this.Renderer.Shader.SetUniformFloat("fEnhanceFactor3", value); this.Renderer.RaiseModified(); this.Renderer.Repaint(); } } } //===================================================================== #endregion #region SamplingRate //===================================================================== private siSamplingRate m_SamplingRate = new siSamplingRate(0.5F, 1.5F); /// /// Gets/sets the volume sampling rate. A value of 1.0 means that one /// texture-geometry polygon will pass through each voxel. /// [ReadOnly(true)] [Browsable(true)] [Category("Rendering")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] [TypeConverter(typeof(ExpandableObjectConverter))] public siSamplingRate SamplingRate { get { return this.m_SamplingRate; } set { this.m_SamplingRate = value; } } //===================================================================== #endregion #region Blending //===================================================================== private siVolumeBlendEnum m_Blending = siVolumeBlendEnum.BackToFront; /// /// Gets/sets the blending type. /// [Browsable(true)] [Category("Rendering")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public siVolumeBlendEnum Blending { get { return this.m_Blending; } set { // Set the value this.m_Blending = value; // Force the background colour if (value == siVolumeBlendEnum.MaximumProjection) this.BackColor = Color.Black; else if (value == siVolumeBlendEnum.MinimumProjection) this.BackColor = Color.White; // Repaint if (this.Renderer != null) this.Renderer.Repaint(); } } //===================================================================== #endregion #region Geometry //===================================================================== private siVolumeGeometryEnum m_GeometryType = siVolumeGeometryEnum.ViewAlignedFill; /// /// Gets/sets the blending type. /// [Browsable(true)] [Category("Rendering")] [ParenthesizePropertyName(false)] [RefreshProperties(RefreshProperties.All)] public siVolumeGeometryEnum GeometryType { get { if (this.Renderer.GeometryGenerator != null) return this.Renderer.GeometryGenerator.GeometryType; else return siVolumeGeometryEnum.ViewAlignedFill; } set { this.m_GeometryType = value; if (this.Renderer != null && this.Renderer.GeometryGenerator != null) { this.Renderer.GeometryGenerator.GeometryType = value; this.Renderer.Repaint(); } } } //===================================================================== #endregion //============================================================================ #endregion #region Serialization Properties //============================================================================ /// /// This method is needed for serialization. /// It is not intended for general use. /// [System.ComponentModel.Browsable(false)] public virtual string SerializableBackColor { get { return siColorHelper.SerializeColor(this.BackColor); } set { this.BackColor = siColorHelper.DeserializeColor(value); } } /// /// This method is needed for serialization. /// It is not intended for general use. /// [System.ComponentModel.Browsable(false)] public virtual string SerializableBoxOutlineColor { get { return siColorHelper.SerializeColor(this.BoxOutlineColor); } set { this.BoxOutlineColor = siColorHelper.DeserializeColor(value); } } /// /// This method is needed for serialization. /// It is not intended for general use. /// [System.ComponentModel.Browsable(false)] public virtual string SerializableLightColorAmbient { get { return siColorHelper.SerializeColor(this.LightColorAmbient); } set { this.LightColorAmbient = siColorHelper.DeserializeColor(value); } } /// /// This method is needed for serialization. /// It is not intended for general use. /// [System.ComponentModel.Browsable(false)] public virtual string SerializableLightColorDiffuse { get { return siColorHelper.SerializeColor(this.LightColorDiffuse); } set { this.LightColorDiffuse = siColorHelper.DeserializeColor(value); } } /// /// This method is needed for serialization. /// It is not intended for general use. /// [System.ComponentModel.Browsable(false)] public virtual string SerializableLightColorSpecular { get { return siColorHelper.SerializeColor(this.LightColorSpecular); } set { this.LightColorSpecular = siColorHelper.DeserializeColor(value); } } /// /// This method is needed for serialization. /// It is not intended for general use. /// [System.ComponentModel.Browsable(false)] public virtual string SerializableTransformTranslate { get { return this.SerializeVector(this.TransformTranslate); } set { this.TransformTranslate = this.DeserializeVector(value); } } /// /// This method is needed for serialization. /// It is not intended for general use. /// [System.ComponentModel.Browsable(false)] public virtual string SerializableTransformRotation { get { return this.SerializeVector(this.TransformRotation); } set { this.TransformRotation = this.DeserializeVector(value); } } /// /// This method is needed for serialization. /// It is not intended for general use. /// [System.ComponentModel.Browsable(false)] public virtual string SerializableFragmentProgramPath { get { string shortpath = this.FragmentProgramPath.Replace(Application.StartupPath, ""); return shortpath.Trim(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); } set { this.FragmentProgramPath = Path.Combine(Application.StartupPath, value); } } //============================================================================ #endregion #region Serialization Methods //===================================================================== /// /// Serializes this object to the given path. /// /// The absolute path and name of the file to create with the serialized object. public void ToXmlFile(string filePath) { // Ensure the filePath is valid if (filePath == null || filePath.Length == 0) throw new ArgumentNullException("filePath", "The file path to serialize the Volume Properties can not be null or empty."); // Ensure the directory exists if (!Directory.Exists(Path.GetDirectoryName(filePath))) Directory.CreateDirectory(Path.GetDirectoryName(filePath)); // Serialize XmlSerializer serializer = new XmlSerializer(typeof(siVolumeProperties)); FileStream stream = File.Create(filePath); serializer.Serialize(stream, this); stream.Flush(); stream.Close(); stream.Dispose(); } /// /// Deserializes this object from the given path. /// /// The absolute path and name of the file to deserialize the object from. /// public static siVolumeProperties FromXmlFile(siVolumeRenderer renderer, string filePath) { // Ensure the filePath is valid if (filePath == null || filePath.Length == 0) throw new ArgumentNullException("filePath", "The file path to serialize the Volume Properties can not be null or empty."); if (!File.Exists(filePath)) throw new FileNotFoundException("The file path to deserialize the Volume Properties was not found.", filePath); // Deserialize XmlSerializer serializer = new XmlSerializer(typeof(siVolumeProperties)); FileStream stream = File.OpenRead(filePath); siVolumeProperties result = (siVolumeProperties)serializer.Deserialize(stream); // Finish result.m_Renderer = renderer; result.UpdateToRenderer(); // Clean up stream.Flush(); stream.Close(); stream.Dispose(); // Return return result; } //===================================================================== #endregion #region Public Methods //============================================================================ /// /// Computes the size of the model from the first input object. /// /// public void ComputeModelSize() { // Create result this.m_ModelSize = new itk.itkArray(3U); // Check if the renderer has an input if (this.Renderer == null || this.Renderer.Inputs.Count == 0) { return; } // Get the input itk.itkDataObject data = this.Renderer.Inputs[0]; // Compute the model size different for images and spatial objects if (data is itk.itkImageBase) { // Input is image itk.itkImageBase dataAsImage = data as itk.itkImageBase; if (dataAsImage.Spacing[0] == dataAsImage.Spacing[1]) { m_ModelSize[0] = 1.0; m_ModelSize[1] = 1.0; m_ModelSize[2] = dataAsImage.PhysicalSize[2] / dataAsImage.PhysicalSize[0]; } else if (dataAsImage.Spacing[1] == dataAsImage.Spacing[2]) { m_ModelSize[0] = dataAsImage.PhysicalSize[0] / dataAsImage.PhysicalSize[1]; m_ModelSize[1] = 1.0; m_ModelSize[2] = 1.0; } else if (dataAsImage.Spacing[0] == dataAsImage.Spacing[2]) { m_ModelSize[0] = 1.0; m_ModelSize[1] = dataAsImage.PhysicalSize[1] / dataAsImage.PhysicalSize[0]; m_ModelSize[2] = 1.0; } else { // Assume dimension 0 is the master dimension m_ModelSize[0] = 1.0; m_ModelSize[1] = dataAsImage.PhysicalSize[1] / dataAsImage.PhysicalSize[0]; m_ModelSize[2] = dataAsImage.PhysicalSize[2] / dataAsImage.PhysicalSize[0]; } } else if (data is siSpatialObject) { // Input is spatial object siSpatialObject dataAsSpatialObject = data as siSpatialObject; if (dataAsSpatialObject.Spacing[0] == dataAsSpatialObject.Spacing[1]) { m_ModelSize[0] = 1.0; m_ModelSize[1] = 1.0; m_ModelSize[2] = dataAsSpatialObject.Spacing[0] / dataAsSpatialObject.Spacing[2]; } else if (dataAsSpatialObject.Spacing[1] == dataAsSpatialObject.Spacing[2]) { m_ModelSize[0] = dataAsSpatialObject.Spacing[1] / dataAsSpatialObject.Spacing[0]; m_ModelSize[1] = 1.0; m_ModelSize[2] = 1.0; } else if (dataAsSpatialObject.Spacing[0] == dataAsSpatialObject.Spacing[2]) { m_ModelSize[0] = 1.0; m_ModelSize[1] = dataAsSpatialObject.Spacing[0] / dataAsSpatialObject.Spacing[1]; m_ModelSize[2] = 1.0; } else { throw new NotSupportedException("The spacing of the input SpatialObject is not supported: '" + dataAsSpatialObject.Spacing.ToString() + "'."); } } } //============================================================================ #endregion #region Private Methods //============================================================================ private void UpdateToRenderer() { this.BackColor = this.m_BackColor; this.FrustrumLeft = this.m_FrustrumLeft; this.FrustrumRight = this.m_FrustrumRight; this.FrustrumTop = this.m_FrustrumTop; this.FrustrumBottom = this.m_FrustrumBottom; this.FrustrumFront = this.m_FrustrumFront; this.FrustrumBack = this.m_FrustrumBack; if (this.m_FragmentProgramPath != null && this.m_FragmentProgramPath.Length > 0) this.FragmentProgramPath = this.m_FragmentProgramPath; this.NormalOffset = this.m_NormalOffset; this.EnhanceFactor1 = this.m_EnhanceFactor1; this.EnhanceFactor2 = this.m_EnhanceFactor2; this.EnhanceFactor3 = this.m_EnhanceFactor3; this.GeometryType = this.m_GeometryType; this.ViewportSize = this.m_ViewportSize; this.SamplingRate.Changed += new siSamplingRate.siSamplingRateHandler(this.Renderer.SamplingRateChanged); this.ComputeModelSize(); this.Renderer.Repaint(); } private itk.itkVector DeserializeVector(string vector) { vector = vector.Trim('[', ']'); string[] split = vector.Split(new char[] { ',' }); itk.itkVector result = new itk.itkVector((uint)split.Length); for (int i = 0; i < split.Length; i++) result[i] = Double.Parse(split[i]); return result; } private string SerializeVector(itk.itkVector vector) { string result = string.Empty; for (int i = 0; i < vector.Length; i++) result += vector[i].ToString("0.0###") + ", "; return result.TrimEnd(' ', ','); } //============================================================================ #endregion } }