/*=============================================================================
Project: SharpImage
Module: siPolygonSelection.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.
=============================================================================*/
#define DEBUG
#define TRACE
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 IteratorType = itk.itkImageRegionIteratorWithIndex_IUC2;
namespace SharpImage.Rendering
{
public class siPolygonSelection : siShapeSelection
{
#region Instance Members
//=====================================================================
itk.itkImageBase m_Template = null;
//=====================================================================
#endregion
#region Construction and Disposal
//=====================================================================
///
/// Public constuctor.
///
/// Uses the size and spacing of the image to compute the default polygon.
public siPolygonSelection(itk.itkImageBase input, int extrusionDimension) : base()
{
// Save the template image
this.m_Template = input;
// Set the list of points
this.m_Points = new List();
// Create some default points
this.ExtrusionDimension = extrusionDimension;
int[] shape = this.GetShapeDimensions(input.Dimension);
itk.itkIndex index0 = new itk.itkIndex(input.Dimension);
itk.itkIndex index1 = new itk.itkIndex(input.Dimension);
itk.itkIndex index2 = new itk.itkIndex(input.Dimension);
itk.itkIndex index3 = new itk.itkIndex(input.Dimension);
index0[0] = (int)(input.Size[shape[0]] * 0.25);
index0[1] = (int)(input.Size[shape[1]] * 0.25);
index1[0] = (int)(input.Size[shape[0]] * 0.75);
index1[1] = (int)(input.Size[shape[1]] * 0.25);
index2[0] = (int)(input.Size[shape[0]] * 0.25);
index2[1] = (int)(input.Size[shape[1]] * 0.75);
index3[0] = (int)(input.Size[shape[0]] * 0.75);
index3[1] = (int)(input.Size[shape[1]] * 0.75);
itk.itkPoint point0;
itk.itkPoint point1;
itk.itkPoint point2;
itk.itkPoint point3;
input.TransformIndexToPhysicalPoint(index0, out point0);
input.TransformIndexToPhysicalPoint(index1, out point1);
input.TransformIndexToPhysicalPoint(index2, out point2);
input.TransformIndexToPhysicalPoint(index3, out point3);
this.Points.Add(point0);
this.Points.Add(point1);
this.Points.Add(point3);
this.Points.Add(point2);
// Set the extrusion type
this.ShapeType = ShapeTypeEnum.Extrusion;
this.ExtrusionStartPoint = 0.0;
this.ExtrusionEndPoint = input.PhysicalSize[(int)input.Dimension - 1];
// Setup the initial Metadata
this.Metadata["IsTranslating"] = false;
this.Metadata["IsMovingControlPoint"] = false;
this.Metadata["IsMouseOverControlPoint"] = false;
this.Metadata["IsMouseOverSelection"] = false;
this.Metadata["CurrentControlPointIndex"] = -1;
}
//=====================================================================
#endregion
#region Properties
//=====================================================================
private List m_Points;
///
/// Gets the list of points comprising the polygon.
///
public List Points
{
get { return this.m_Points; }
}
///
/// Gets a string describing the selection type.
///
public override string TypeName
{
get{ return "Polygon"; }
}
///
/// Gets a string indicating the "Image" type for
/// itkGenerateMaskImageFilter.
///
public override string GenerateMaskImageFilterType
{
get { return "Image"; }
}
//=====================================================================
#endregion
#region Public Methods
//=====================================================================
///
/// Return a string representing the selection.
///
///
public override string ToString()
{
String result = this.TypeName + ": ";
foreach (itk.itkPoint point in this.Points)
result += point.ToString() + " ";
return result.Trim(' ');
}
///
/// Convert this selection to an itk.itkImage with UC pixel type.
/// If size.Dimension == 2, the selection is simply rasterised.
/// If size.Dimension == 3, the selection is tiled across the extrusion dimension.
///
///
public itk.itkImageBase ToImage()
{
// Get the path in screen space
GraphicsPath pathPixel = this.GetSelectionAsPixelPath(m_Template);
// Get the output size, spacing, and origin
itk.itkSize size = m_Template.Size;
itk.itkSpacing spacing = m_Template.Spacing;
itk.itkPoint origin = m_Template.Origin;
// Create empty image
itk.itkIndex indexPath = new itk.itkIndex(0, 0);
itk.itkSize sizePath = new itk.itkSize(size[0], size[1]);
itk.itkImageRegion regionPath = new itk.itkImageRegion(sizePath, indexPath);
itk.itkImageBase imagePath = itk.itkImage_UC2.New();
imagePath.SetRegions(regionPath);
imagePath.Allocate();
imagePath.FillBuffer(0U);
imagePath.Spacing = new itk.itkSpacing(spacing[0], spacing[1]);
imagePath.Origin = new itk.itkPoint(origin[0], origin[1]);
// Convert the path to a 2D itkImage
IteratorType it = new IteratorType(imagePath, regionPath);
foreach (itk.itkPixel p in it)
{
itk.itkIndex indexIt = it.Index;
if (pathPixel.IsVisible(indexIt[0], indexIt[1]))
it.Set(255U);
}
// Clean up the path
pathPixel.Dispose();
// Check the dimension
if (size.Dimension == 2)
{
return imagePath;
}
else
{
itk.itkImageBase imageOutput = itk.itkImage_UC3.New();
// Compute the start and end indexes
itk.itkIndex indexStart;
itk.itkIndex indexEnd;
itk.itkPoint pointStart = new itk.itkPoint(0.0, 0.0, this.ExtrusionStartPoint);
itk.itkPoint pointEnd = new itk.itkPoint(0.0, 0.0, this.ExtrusionEndPoint);
m_Template.TransformPhysicalPointToIndex(pointStart, out indexStart);
m_Template.TransformPhysicalPointToIndex(pointEnd, out indexEnd);
// Create a blank image
itk.itkImageBase imageBlank = itk.itkImage_UC2.New();
imageBlank.SetRegions(regionPath);
imageBlank.Allocate();
imageBlank.FillBuffer(0U);
imageBlank.Spacing = imagePath.Spacing;
imageBlank.Origin = imagePath.Origin;
// Tile the inputs
itk.itkTileImageFilter filterTile = itk.itkTileImageFilter.New(imagePath, imageOutput);
filterTile.Layout = new uint[]{ 1U,1U,0U };
uint input = 0;
for (int i=0; i
/// 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.
///
///
protected void OnPaint(siGdiSliceRenderer renderer, PaintEventArgs e)
{
// Set to draw smooth
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
// Always painting the extrusion
this.OnPaintExtrusion(renderer, e);
}
///
/// Render the shape of the extruded object (a circle in this case).
///
///
protected override void OnPaintShape(siGdiSliceRenderer renderer, PaintEventArgs e)
{
// Get the graphics handle
Graphics g = e.Graphics;
// Get the input
itk.itkImageBase input = this.GetInputAsImage(renderer);
if (input == null) return;
// Get the selection as a path in screen space
GraphicsPath pathScreen = this.GetSelectionAsScreenPath(renderer);
// Convert the slice index to a point
itk.itkPoint pointSlice;
itk.itkIndex indexSlice = new itk.itkIndex(input.Dimension);
indexSlice[this.ExtrusionDimension] = renderer.Slice;
input.TransformIndexToPhysicalPoint(indexSlice, out pointSlice);
// Determine if the current slice is within the start and end range
if (pointSlice[this.ExtrusionDimension] < this.ExtrusionStartPoint ||
pointSlice[this.ExtrusionDimension] > this.ExtrusionEndPoint)
// The slice does not intersect with the shape, there is nothing to paint
return;
// Draw the path
SolidBrush brushFill = new SolidBrush(COLOR_FILL);
SolidBrush brushOutline = new SolidBrush(COLOR_OUTLINE);
Pen penOutline = new Pen(brushOutline, PEN_OUTLINE_WIDTH);
g.DrawPath(penOutline, pathScreen);
g.FillPath(brushFill, pathScreen);
// Draw control points
SolidBrush brushControlFill = new SolidBrush(COLOR_CONTROL_FILL);
SolidBrush brushControlOutline = new SolidBrush(COLOR_CONTROL_OUTLINE);
Pen penControlOutline = new Pen(brushControlOutline, PEN_CONTROL_OUTLINE_WIDTH);
foreach (RectangleF controlPoint in this.GetControlPoints(renderer))
{
g.FillRectangle(brushControlFill, controlPoint);
g.DrawRectangle(penControlOutline, controlPoint.X, controlPoint.Y, controlPoint.Width, controlPoint.Height);
}
}
///
/// Render the extruded object (ie. a rectangle starting at StartExtrusionIndex
/// and ending at EndExtrusionIndex, of height 2.0*this.Radius).
///
///
protected override void OnPaintExtrudedShape(siGdiSliceRenderer renderer, PaintEventArgs e)
{
// Get the graphics handle
Graphics g = e.Graphics;
// Get the rectangle
RectangleF r = this.GetExtrusionAsScreenRectangle(renderer);
if (r == RectangleF.Empty) return;
// Get the brushes and pens
SolidBrush brushFill = new SolidBrush(COLOR_FILL);
SolidBrush brushOutline = new SolidBrush(COLOR_OUTLINE);
Pen penOutline = new Pen(brushOutline, PEN_OUTLINE_WIDTH);
// Draw outline and fill
g.DrawRectangle(penOutline, r.X, r.Y, r.Width, r.Height);
g.FillRectangle(brushFill, r.X, r.Y, r.Width, r.Height);
// Draw control points
SolidBrush brushControlFill = new SolidBrush(COLOR_CONTROL_FILL);
SolidBrush brushControlOutline = new SolidBrush(COLOR_CONTROL_OUTLINE);
Pen penControlOutline = new Pen(brushControlOutline, PEN_CONTROL_OUTLINE_WIDTH);
foreach (RectangleF controlPoint in this.GetControlPoints(renderer))
{
g.FillRectangle(brushControlFill, controlPoint);
g.DrawRectangle(penControlOutline, controlPoint.X, controlPoint.Y, controlPoint.Width, controlPoint.Height);
}
}
///
/// Allows the actor to consume the MouseMove event.
///
///
///
protected override bool OnMouseMove(siRenderer renderer, MouseEventArgs e)
{
base.OnMouseMove(renderer, e);
// Check the Renderer has all the required Metadata variables
if (!renderer.ContainsMetadata("LastImagePointMouseMove"))
return false;
// Get the location as an itkPoint
itk.itkImageBase input = this.GetInputAsImage(renderer);
itk.itkPoint pointMouseMove = (itk.itkPoint)renderer.Metadata["LastImagePointMouseMove"];
itk.itkPoint pointMouseMoveT = renderer.DirectionTransformPoint(pointMouseMove);
// Check if we are translating
if ((bool)this.Metadata["IsTranslating"])
{
if (this.IsRenderingShape(renderer, input.Direction))
{
itk.itkPoint[] pointsBeforeTranslation = (itk.itkPoint[])this.Metadata["PointsBeforeTranslation"];
itk.itkPoint pointMouseDown = (itk.itkPoint)renderer.Metadata["LastImagePointMouseDown"];
itk.itkPoint pointMouseDownT = renderer.DirectionTransformPoint(pointMouseDown);
itk.itkVector offset = pointMouseMoveT - pointMouseDownT;
for (int i = 0; i < this.Points.Count; i++)
this.Points[i] = pointsBeforeTranslation[i] + offset;
this.RaiseModified();
return true;
}
else
{
// TODO:
return false;
}
}
// Check if we are editing the path
if ((bool)this.Metadata["IsMovingControlPoint"])
{
if (this.IsRenderingShape(renderer, input.Direction))
{
int indexControlPoint = (int)this.Metadata["CurrentControlPointIndex"];
this.Points[indexControlPoint] = new itk.itkPoint(pointMouseMoveT.Data);
this.RaiseModified();
return true;
}
else
{
int indexControlPoint = (int)this.Metadata["CurrentControlPointIndex"];
if (indexControlPoint == 0)
this.ExtrusionEndPoint = pointMouseMoveT[2];
else
this.ExtrusionStartPoint = pointMouseMoveT[2];
this.RaiseModified();
return true;
}
}
// Check if the mouse is over a control point
int controlPointIndex = this.IsMouseOverControlPoint(renderer as siGdiSliceRenderer, e);
if (controlPointIndex >= 0)
{
// Show the correct cursor
renderer.Metadata["Cursor"] = this.GetControlPointCursor(controlPointIndex);
this.Metadata["CurrentControlPointIndex"] = controlPointIndex;
this.Metadata["IsMouseOverControlPoint"] = true;
this.Metadata["IsMouseOverSelection"] = false;
return true;
}
// Check if the mouse is over the selection
if (this.IsMouseOverSelection(renderer as siGdiSliceRenderer, e.Location))
{
renderer.Metadata["Cursor"] = Cursors.Hand;
this.Metadata["IsMouseOverControlPoint"] = false;
this.Metadata["IsMouseOverSelection"] = true;
this.Metadata["CurrentControlPointIndex"] = -1;
return true;
}
// We did not consume this event
renderer.Metadata["Cursor"] = null;
this.Metadata["IsMouseOverControlPoint"] = false;
this.Metadata["IsMouseOverSelection"] = false;
this.Metadata["CurrentControlPointIndex"] = -1;
return false;
}
///
/// Allows the actor to consume the MouseDown event.
///
///
///
protected override bool OnMouseDown(siRenderer renderer, MouseEventArgs e)
{
base.OnMouseDown(renderer, e);
// Get the input image
itk.itkImageBase input = this.GetInputAsImage(renderer);
// Check if we are over the selection
if ((bool)this.Metadata["IsMouseOverSelection"])
{
// Check the control key
if (renderer.ContainsMetadata("KeyDown") &&
this.IsRenderingShape(renderer as siGdiSliceRenderer, input.Direction))
{
KeyEventArgs eKey = (KeyEventArgs)renderer.Metadata["KeyDown"];
if (eKey != null && eKey.Control)
{
// Check if we added a control point
if (this.AddControlPoint(renderer as siGdiSliceRenderer, e.Location))
return true;
}
}
// Override image translation
renderer.Metadata["IsTranslatingImage"] = false;
// Start selection translation
this.Metadata["IsTranslating"] = true;
// Save the point list
itk.itkPoint[] pointsBeforeTranslation = new itk.itkPoint[this.Points.Count];
for (int i = 0; i < this.Points.Count; i++)
pointsBeforeTranslation[i] = new itk.itkPoint(this.Points[i].Data);
this.Metadata["PointsBeforeTranslation"] = pointsBeforeTranslation;
return true;
}
// Check if we are over a control point
if ((bool)this.Metadata["IsMouseOverControlPoint"])
{
// Check the control key
if (renderer.ContainsMetadata("CurrentKey") &&
this.IsRenderingShape(renderer as siGdiSliceRenderer, input.Direction))
{
KeyEventArgs eKey = (KeyEventArgs)renderer.Metadata["CurrentKey"];
if (eKey.Control)
{
// Check if we deleted a control point
if (this.DeleteControlPoint((int)this.Metadata["CurrentControlPointIndex"]))
return true;
}
}
// Override other translations
renderer.Metadata["IsTranslatingImage"] = false;
this.Metadata["IsTranslating"] = false;
// Start selection resize
this.Metadata["IsMovingControlPoint"] = true;
return true;
}
// We did not consume this event
return false;
}
///
/// Allows the actor to consume the MouseUp event.
///
///
///
protected override bool OnMouseUp(siRenderer renderer, MouseEventArgs e)
{
base.OnMouseUp(renderer, e);
if ((bool)this.Metadata["IsTranslating"])
{
this.Metadata["IsTranslating"] = false;
return true;
}
else if ((bool)this.Metadata["IsMovingControlPoint"])
{
this.Metadata["IsMovingControlPoint"] = false;
return true;
}
// We did not consume this event
return false;
}
//=====================================================================
#endregion
#region Private Helper Methods
//=====================================================================
///
/// Computes the control point rectangles for the current center and radius.
///
///
private RectangleF[] GetControlPoints(siGdiSliceRenderer renderer)
{
// Get the input image
itk.itkImageBase input = this.GetInputAsImage(renderer);
// Compute some useful values
float widthControl = CONTROL_WIDTH * (renderer.ZoomFactor < 0.25 ? (float)renderer.ZoomFactor : 1.0F);
if (this.IsRenderingShape(renderer, input.Direction))
{
// Get the path
GraphicsPath pathScreen = this.GetSelectionAsScreenPath(renderer);
// Create the control points
RectangleF[] result = new RectangleF[pathScreen.PointCount];
for (int i = 0; i < pathScreen.PointCount; i++)
{
PointF point = pathScreen.PathPoints[i];
result[i] = new RectangleF(point.X - widthControl / 2.0F, point.Y - widthControl / 2.0F, widthControl, widthControl);
}
return result;
}
else
{
// Get the extrusion rectangle
RectangleF r = this.GetExtrusionAsScreenRectangle(renderer);
// Transform the test point
itk.itkPoint pointTest = new itk.itkPoint(1.0, 1.0, 0.0);
itk.itkPoint pointTestT = renderer.DirectionTransformInversePoint(pointTest);
PointF point0 = new PointF();
PointF point1 = new PointF();
if (pointTestT[1] > 0.0 && pointTestT[2] > 0.0)
{
point0 = new PointF(r.X, r.Y + r.Height / 2.0F);
point1 = new PointF(r.X + r.Width, r.Y + r.Height / 2.0F);
}
else if (pointTestT[1] > 0.0 && pointTestT[2] < 0.0)
{
point0 = new PointF(r.X, r.Y + r.Height / 2.0F);
point1 = new PointF(r.X + r.Width, r.Y + r.Height / 2.0F);
}
else if (pointTestT[0] > 0.0 && pointTestT[2] < 0.0)
{
point0 = new PointF(r.X + r.Width / 2.0F, r.Y);
point1 = new PointF(r.X + r.Width / 2.0F, r.Y - r.Height);
}
RectangleF[] result = new RectangleF[2];
result[0] = new RectangleF(point0.X - widthControl / 2.0F, point0.Y - widthControl / 2.0F, widthControl, widthControl);
result[1] = new RectangleF(point1.X - widthControl / 2.0F, point1.Y - widthControl / 2.0F, widthControl, widthControl);
return result;
}
}
///
/// Returns the index of the control point which the mouse is over.
/// Returns -1 if not over a control point.
///
///
/// The index of the control OR -1 if not over a control point.
private int IsMouseOverControlPoint(siGdiSliceRenderer renderer, MouseEventArgs e)
{
RectangleF[] controlPoints = this.GetControlPoints(renderer);
int index = 0;
foreach (RectangleF controlPoint in controlPoints)
{
if (controlPoint.Contains(e.Location))
return index;
index++;
}
return -1;
}
///
/// Returns if the mouse is inside the selection.
///
///
///
private bool IsMouseOverSelection(siGdiSliceRenderer renderer, PointF pointMouse)
{
// Get the input image
itk.itkImageBase input = this.GetInputAsImage(renderer);
if (input == null) return false;
// Convert the slice index to a point
itk.itkPoint pointSlice;
itk.itkIndex indexSlice = new itk.itkIndex(input.Dimension);
indexSlice[this.ExtrusionDimension] = renderer.Slice;
input.TransformIndexToPhysicalPoint(indexSlice, out pointSlice);
// Determine if the current slice is within the start and end range
if (pointSlice[this.ExtrusionDimension] < this.ExtrusionStartPoint ||
pointSlice[this.ExtrusionDimension] > this.ExtrusionEndPoint)
// The slice does not intersect with the shape, there is nothing to paint
return false;
// Test if the mouse is inside the path
GraphicsPath pathScreen = this.GetSelectionAsScreenPath(renderer);
bool result = pathScreen.IsVisible(pointMouse.X, pointMouse.Y);
// Clean up and return
pathScreen.Dispose();
return result;
}
///
/// Get the cursor for the given control point index.
///
///
///
private Cursor GetControlPointCursor(int controlPoint)
{
return Cursors.Hand;
}
///
/// Create a path from the list of points comprising the polygon.
///
///
private GraphicsPath GetSelectionAsScreenPath(siGdiSliceRenderer renderer)
{
// Get the input image
itk.itkImageBase input = this.GetInputAsImage(renderer);
if (input == null) return null;
// Create a path in image pixel space
GraphicsPath path = new GraphicsPath();
for (int i = 0; i < this.Points.Count; i++)
{
if (i == 0)
{
path.StartFigure();
}
else
{
PointF pointScreen0 = renderer.TransformImagePointToScreenPoint(input, this.Points[i-1]);
PointF pointScreen1 = renderer.TransformImagePointToScreenPoint(input, this.Points[i]);
path.AddLine(pointScreen0, pointScreen1);
}
}
path.CloseFigure();
return path;
}
///
/// Create a path from the list of points comprising the polygon.
///
///
private GraphicsPath GetSelectionAsPixelPath(itk.itkImageBase input)
{
// Create a path in image pixel space
GraphicsPath path = new GraphicsPath();
for (int i = 0; i < this.Points.Count; i++)
{
if (i == 0)
{
path.StartFigure();
}
else
{
itk.itkContinuousIndex cindex0;
itk.itkContinuousIndex cindex1;
input.TransformPhysicalPointToContinuousIndex(this.Points[i - 1], out cindex0);
input.TransformPhysicalPointToContinuousIndex(this.Points[i], out cindex1);
PointF pointScreen0 = new PointF((float)cindex0[0], (float)cindex0[1]);
PointF pointScreen1 = new PointF((float)cindex1[0], (float)cindex1[1]);
path.AddLine(pointScreen0, pointScreen1);
}
}
path.CloseFigure();
return path;
}
///
/// Gets the rectangle in screen coordinates which represents the slice of the
/// cylinder.
///
///
///
private RectangleF GetExtrusionAsScreenRectangle(siGdiSliceRenderer renderer)
{
RectangleF rectResult = new RectangleF();
// Get the input image
itk.itkImageBase input = this.GetInputAsImage(renderer);
if (input == null) return RectangleF.Empty;
// Get the bounds of the polygon
GraphicsPath pathScreen = this.GetSelectionAsScreenPath(renderer);
RectangleF rectPathScreenBounds = pathScreen.GetBounds();
// Get the center of the polygon in physical space
Point pointShapeScreen = new Point();
pointShapeScreen.X = (int)(rectPathScreenBounds.X);
pointShapeScreen.Y = (int)(rectPathScreenBounds.Y);
itk.itkPoint pointShape = renderer.TransformScreenPointToImagePoint(pointShapeScreen);
// Determine which path rectangle axis to show
int[] shape = this.GetShapeDimensions(input.Dimension);
itk.itkPoint pointTest = new itk.itkPoint(1.0, 1.0, 0.0);
itk.itkPoint pointStart = new itk.itkPoint(0.0, 0.0, 0.0);
itk.itkPoint pointEnd = new itk.itkPoint(0.0, 0.0, 0.0);
pointStart[shape[0]] = pointShape[shape[0]];
pointStart[shape[1]] = pointShape[shape[1]];
pointStart[this.ExtrusionDimension] = this.ExtrusionStartPoint;
pointEnd[shape[0]] = pointShape[shape[0]];
pointEnd[shape[1]] = pointShape[shape[1]];
pointEnd[this.ExtrusionDimension] = this.ExtrusionEndPoint;
itk.itkPoint pointTestT = renderer.DirectionTransformInversePoint(pointTest);
itk.itkPoint pointStartT = renderer.DirectionTransformInversePoint(pointStart);
itk.itkPoint pointEndT = renderer.DirectionTransformInversePoint(pointEnd);
PointF pointScreenStart = renderer.TransformImagePointToScreenPoint(input, pointStartT);
PointF pointScreenEnd = renderer.TransformImagePointToScreenPoint(input, pointEndT);
// This is really dodgy, but I don't know how else to work
// out which axis of the shape (width or height) to use...
if (pointTestT[1] > 0.0 && pointTestT[2] > 0.0)
{
rectResult.X = pointScreenEnd.X;
rectResult.Y = pointScreenEnd.Y;
rectResult.Height = rectPathScreenBounds.Height;
rectResult.Width = pointScreenStart.X - pointScreenEnd.X;
}
else if (pointTestT[1] > 0.0 && pointTestT[2] < 0.0)
{
rectResult.X = pointScreenEnd.X;
rectResult.Y = pointScreenEnd.Y;
rectResult.Height = rectPathScreenBounds.Width;
rectResult.Width = pointScreenStart.X - pointScreenEnd.X;
}
else if (pointTestT[0] > 0.0 && pointTestT[2] < 0.0)
{
rectResult.X = pointScreenEnd.X;
rectResult.Y = pointScreenEnd.Y;
rectResult.Height = pointScreenStart.Y - pointScreenEnd.Y;
rectResult.Width = rectPathScreenBounds.Height;
}
return rectResult;
}
///
/// Add a control point at the given screen coordinates.
///
///
///
private bool AddControlPoint(siGdiSliceRenderer renderer, PointF pointScreen)
{
// Convert the pointScreen into an itkPoint
itk.itkPoint pointScreenItk = new itk.itkPoint((double)pointScreen.X, (double)pointScreen.Y);
// Find the indexes of the lines in the path to add the point between
int index = 0;
double distance = 8000000.0;
GraphicsPath pathScreen = this.GetSelectionAsScreenPath(renderer);
for (int i=0; i
/// Delete the control point at the given index. This method does nothing
/// if the number of control points is three.
///
///
/// True if a point was deleted, false otherwise.
private bool DeleteControlPoint(int indexControlPoint)
{
int count = this.Points.Count;
// Check if there are 3 or less points
if (count <= 3)
return false;
// Remove a point
this.Points.RemoveAt(indexControlPoint);
// Get if we actually deleted a point
if (count != this.Points.Count)
{
this.RaiseModified();
return true;
}
else
return false;
}
//=====================================================================
#endregion
}
}