/*=============================================================================
Project: SharpImage
Module: siPointsSelection.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.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Diagnostics;
using SharpImage.Main;
using SharpImage.Properties;
namespace SharpImage.Rendering
{
public class siPointsSelection : siSelection
{
#region Instance Variables
//=====================================================================
//=========================================================================
#endregion
#region Construction and Disposal
//=====================================================================
///
/// Public constuctor.
///
public siPointsSelection() : base()
{
}
//=====================================================================
#endregion
#region Properties
//=====================================================================
#region Points and Indicies
//=====================================================================
private List m_Points = new List();
///
/// Gets the list of points.
///
public List Points
{
get { return this.m_Points; }
}
///
/// Get the list of indicies.
///
///
public List GetIndicies(itk.itkImageBase input)
{
List result = new List();
foreach (itk.itkPoint point in this.Points)
{
itk.itkIndex index;
input.TransformPhysicalPointToIndex(point, out index);
result.Add(index);
}
return result;
}
//=====================================================================
#endregion
#region InAdditionMode
//=====================================================================
private bool m_InAdditionMode = false;
///
/// Gets if the actor is in point addition mode,
/// allowing the user to add new points.
///
public bool InAdditionMode
{
get { return this.m_InAdditionMode; }
}
///
/// Allows the actor to add points.
///
public void EnterAdditionMode()
{
this.m_InAdditionMode = true;
}
///
/// Stops the actor from adding points.
///
public void ExitAdditionMode()
{
this.m_InAdditionMode = false;
this.RaiseExitedAdditionMode();
}
//=====================================================================
#endregion
#region GenerateMaskImageFilterType
//=====================================================================
///
/// Returns the GenerateMaskImageFilter "Point" type.
///
public override string GenerateMaskImageFilterType
{
get { return "Point"; }
}
//=====================================================================
#endregion
#region TypeName
//=====================================================================
///
/// Returns a the type name of the selection.
///
public override string TypeName
{
get { return "Points"; }
}
//=====================================================================
#endregion
//=====================================================================
#endregion
#region Events
//=====================================================================
public delegate void siPointsHandler(siPointsSelection sender, itk.itkPoint point);
private siPointsHandler m_EventStorage_PointAdded;
private siPointsHandler m_EventStorage_PointSelected;
private siActorHandler m_EventStorage_ExitedAdditionMode;
///
/// An event raised when the user adds a point.
///
public event siPointsHandler PointAdded
{
add { this.m_EventStorage_PointAdded += value; }
remove { this.m_EventStorage_PointAdded -= value; }
}
///
/// An event raised when the user selects an existing point.
///
public event siPointsHandler PointSelected
{
add { this.m_EventStorage_PointSelected += value; }
remove { this.m_EventStorage_PointSelected -= value; }
}
///
/// An event raised when the user exits addition mode.
///
public event siActorHandler ExitedAdditionMode
{
add { this.m_EventStorage_ExitedAdditionMode += value; }
remove { this.m_EventStorage_ExitedAdditionMode -= value; }
}
///
/// Raises the PointAdded event.
///
///
private void RaisePointAdded(itk.itkPoint point)
{
if (this.m_EventStorage_PointAdded != null)
{
this.m_EventStorage_PointAdded(this, point);
this.RaiseModified();
}
}
///
/// Raises the PointSelected event.
///
///
private void RaisePointSelected(itk.itkPoint point)
{
if (this.m_EventStorage_PointSelected != null)
{
this.m_EventStorage_PointSelected(this, point);
this.RaiseModified();
}
}
///
/// Raises the ExitedAdditionMode event.
///
private void RaiseExitedAdditionMode()
{
if (this.m_EventStorage_ExitedAdditionMode != null)
{
this.m_EventStorage_ExitedAdditionMode(this);
this.RaiseModified();
}
}
//=====================================================================
#endregion
#region Public Methods
//=====================================================================
///
/// Changes the currently selected point.
/// The point value can be null to unselect all point.
/// If the point is not currently included as a landmark, no points are selected.
///
///
public void SelectPoint(itk.itkPoint point)
{
this.Metadata["SelectedPoint"] = point;
this.RaiseModified();
}
///
/// Removes the given point from the list.
///
///
public void RemovePoint(itk.itkPoint point)
{
this.Points.Remove(point);
this.RaiseModified();
}
///
/// Removes all the points from the list
///
public void ClearPoints()
{
this.Points.Clear();
this.RaiseModified();
}
///
/// Returns a string representation of the selection.
///
public override string ToString()
{
return "Points: " + this.Points.Count.ToString();
}
//=====================================================================
#endregion
#region Actor Methods
//=====================================================================
///
/// Allows the actor to render itself.
///
///
protected override void OnPaint(siRenderer renderer, PaintEventArgs e)
{
if (renderer is siGdiSliceRenderer)
this.OnPaint(renderer as siGdiSliceRenderer, e);
else
this.ThrowNotSupported("The given renderer is not supported.");
}
///
/// Allows the actor to render itself to an siGdiSliceRenderer.
///
///
///
protected void OnPaint(siGdiSliceRenderer renderer, PaintEventArgs e)
{
// Set to draw smooth
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
// Setup for rendering the seed location
itk.itkImageBase input = this.GetInputAsImage(renderer);
if (input == null) return;
Pen pen = new Pen(new SolidBrush(Color.Red), 1.0F);
const float width = 9.0F;
const float widthHalf = width / 2.0F;
float crossLength = (widthHalf / (float)Math.Cos(Math.PI / 4.0)) / 2.0F;
// Enumerate the point list
foreach (itk.itkPoint point in this.Points)
{
// Pass the point through the inverse direction transform
itk.itkPoint pointT = renderer.DirectionTransformInversePoint(point);
// Convert the point to an index
itk.itkIndex indexT;
input.TransformPhysicalPointToIndex(pointT, out indexT);
// Check the point is visible at the moment
if (indexT.Dimension == 2 ||
(indexT.Dimension == 3 && renderer.Slice == indexT[2]))
{
// Get info for drawing index
PointF pointScreen = renderer.TransformImageIndexToScreenPoint(indexT, true);
// Check if the index is selected
if (this.Metadata.ContainsKey("SelectedPoint") &&
(this.Metadata["SelectedPoint"] as itk.itkPoint) == point)
{
// Draw larger circle around selected point
RectangleF rectSelected = new RectangleF(pointScreen.X - widthHalf - 2.0F, pointScreen.Y - widthHalf - 2.0F, width + 4.0F, width + 4.0F);
g.DrawArc(pen, rectSelected, 0.0F, 360.0F);
}
// Draw
RectangleF rect = new RectangleF(pointScreen.X - widthHalf, pointScreen.Y - widthHalf, width, width);
g.DrawArc(pen, rect, 0.0F, 360.0F);
g.DrawLine(pen, pointScreen.X - crossLength, pointScreen.Y - crossLength, pointScreen.X + crossLength, pointScreen.Y + crossLength);
g.DrawLine(pen, pointScreen.X - crossLength, pointScreen.Y + crossLength, pointScreen.X + crossLength, pointScreen.Y - crossLength);
}
} // End enumerate points
}
///
/// Allows the actor to consume the MouseDown event.
///
///
protected override bool OnMouseDown(siRenderer renderer, MouseEventArgs e)
{
if (renderer is siGdiSliceRenderer)
return this.OnMouseDown(renderer as siGdiSliceRenderer, e);
else
throw new NotSupportedException("The given renderer is not supported.");
}
///
/// Allows the actor to consume the MouseDown event for an siGdiSliceRenderer.
///
///
///
///
protected bool OnMouseDown(siGdiSliceRenderer renderer, MouseEventArgs e)
{
// Check the Renderer has all the required Metadata variables
if (!renderer.ContainsMetadata("IsMouseInsideImageSpace",
"LastImagePointMouseDown"))
return false;
// Only allow selections inside the image
if (!(bool)renderer.Metadata["IsMouseInsideImageSpace"])
return false;
// Check the mode
if (this.InAdditionMode && e.Button == MouseButtons.Left)
{
// Add the point
itk.itkImageBase input = this.GetInputAsImage(renderer);
itk.itkPoint pointToAdd = (itk.itkPoint)renderer.Metadata["LastImagePointMouseDown"];
itk.itkPoint pointToAddT = renderer.DirectionTransformPoint(pointToAdd);
// Check the point is not already added to the list
foreach (itk.itkPoint pointInList in this.Points)
{
if (pointToAddT == pointInList)
{
// Select this seed
this.Metadata["SelectedPoint"] = pointToAddT;
this.RaisePointSelected(pointToAddT);
return true;
}
}
// Add the point to the list, it is unique
this.Points.Add(pointToAddT);
this.Metadata["SelectedPoint"] = pointToAddT;
this.RaisePointAdded(pointToAddT);
return true;
}
else if (this.InAdditionMode && e.Button == MouseButtons.Right)
{
// Exit addition mode
this.ExitAdditionMode();
return true;
}
return false;
}
//=====================================================================
#endregion
}
}