/// <summary> /// Constructs a new polygonal region of interest, specifying an <see cref="IPointsGraphic"/> as the source of the definition and pixel data. /// </summary> /// <param name="polygon">The polygonal graphic that represents the region of interest.</param> public PolygonalRoi(IPointsGraphic polygon) : base(polygon.ParentPresentationImage) { if (polygon.Points.Count < 4 || !polygon.Points.IsClosed) // a valid points graphic needs 4 endpoints to define 3 sides { throw new ArgumentException("Supplied graphic must be a valid closed polygon.", "polygon"); } polygon.CoordinateSystem = CoordinateSystem.Source; try { // this list of vertices *has* the repeated start point, so we remove it here // the repeated point is an artifact of the polyline graphics system, and should not be replicated in abstract polygon models. List <PointF> vertices = new List <PointF>(polygon.Points.Count - 1); for (int n = 0; n < polygon.Points.Count - 1; n++) { vertices.Add(polygon.Points[n]); } _polygon = new PolygonF(vertices); } finally { polygon.ResetCoordinateSystem(); } }
private void InstallSnapPointGraphic(bool install) { IPointsGraphic subject = this.Graphic; CompositeGraphic parent = subject.ParentGraphic as CompositeGraphic; if (parent == null) { return; } if (install && subject.Points.Count > 0) { if (_snapPoint == null) { _snapPoint = new SnapPointGraphic(); } if (!parent.Graphics.Contains(_snapPoint)) { parent.Graphics.Add(_snapPoint); } _snapPoint.CoordinateSystem = subject.CoordinateSystem; _snapPoint.Location = subject.Points[0]; _snapPoint.ResetCoordinateSystem(); parent.Draw(); } else if (_snapPoint != null && parent.Graphics.Contains(_snapPoint)) { parent.Graphics.Remove(_snapPoint); parent.Draw(); } }
private double GetCurrentLength() { Units units = Units.Centimeters; IPointsGraphic line = LineGraphic; line.CoordinateSystem = CoordinateSystem.Source; try { double length = RoiLengthAnalyzer.CalculateLength(line.Points[0], line.Points[1], Frame.NormalizedPixelSpacing, ref units); if (units == Units.Centimeters) { return(length); } else { return(0.0); } } finally { line.ResetCoordinateSystem(); } }
public void Select(IGraphic graphic) { if (graphic != null) { Platform.CheckFalse(ReferenceEquals(graphic.ParentPresentationImage, null), "Supplied graphic must be on the same presentation image."); Platform.CheckTrue(ReferenceEquals(graphic.ParentPresentationImage, this.ParentPresentationImage), "Supplied graphic must be on the same presentation image."); } IPointsGraphic value = GetLine(graphic); if (_selectedLine != value) { if (_selectedLine != null) { _selectedLine.Points.PointAdded -= OnSelectedLinePointChanged; _selectedLine.Points.PointChanged -= OnSelectedLinePointChanged; _selectedLine.Points.PointRemoved -= OnSelectedLinePointChanged; _selectedLine.Points.PointsCleared -= OnSelectedLinePointsCleared; } _selectedLine = value; if (_selectedLine != null) { _selectedLine.Points.PointAdded += OnSelectedLinePointChanged; _selectedLine.Points.PointChanged += OnSelectedLinePointChanged; _selectedLine.Points.PointRemoved += OnSelectedLinePointChanged; _selectedLine.Points.PointsCleared += OnSelectedLinePointsCleared; } Visible = _selectedLine != null; _isDirty = true; } }
private static bool IsClosed(IPointsGraphic g) { if (g.Points.Count > 2) { return(FloatComparer.AreEqual(g.Points[0], g.Points[g.Points.Count - 1])); } return(false); }
private void OnOverlayGraphicsItemRemoved(object sender, ListEventArgs <IGraphic> e) { IPointsGraphic lineGraphic = GetLine(e.Item); if (ReferenceEquals(_selectedLine, lineGraphic)) { this.Select(null); } }
private void ResyncEndPoints() { IPointsGraphic pointsGraphic = this.Subject; if (pointsGraphic.Points.Count > 1) { pointsGraphic.Points[pointsGraphic.Points.Count - 1] = pointsGraphic.Points[0]; } }
/// <summary> /// Constructs an interactive builder for the specified graphic. /// </summary> /// <param name="maximumVertices">The maximum number of vertices to accept.</param> /// <param name="minimumVertices">The minimum number of vertices to accept.</param> /// <param name="pointsGraphic">The graphic to be interactively built.</param> public InteractivePolylineGraphicBuilder(int maximumVertices, int minimumVertices, IPointsGraphic pointsGraphic) : base(pointsGraphic) { Platform.CheckPositive(minimumVertices, "minimumVertices"); Platform.CheckTrue(maximumVertices >= minimumVertices, "max vertices >= min vertices"); Platform.CheckTrue(minimumVertices > 1, "min vertices > 1"); _maximumVertices = maximumVertices; _minimumVertices = minimumVertices; }
private static void ApplyCalibration(double lengthInMm, IPointsGraphic line, Frame frame, IDesktopWindow desktopWindow) { double aspectRatio; if (frame.PixelAspectRatio.IsNull) { // When there is no aspect ratio tag, the image is displayed with the aspect ratio // of the pixel spacing, so just keep the aspect ratio the same as // what's displayed. Otherwise, after calibration, a 2cm line drawn horizontally // would be visibly different from a 2cm line drawn vertically. if (!frame.NormalizedPixelSpacing.IsNull) { aspectRatio = frame.NormalizedPixelSpacing.AspectRatio; } else { aspectRatio = 1; } } else { aspectRatio = frame.PixelAspectRatio.Value; } line.CoordinateSystem = CoordinateSystem.Source; double widthInPixels = line.Points[1].X - line.Points[0].X; double heightInPixels = line.Points[1].Y - line.Points[0].Y; line.ResetCoordinateSystem(); if (widthInPixels == 0 && heightInPixels == 0) { desktopWindow.ShowMessageBox(SR.ErrorCannotCalibrateZeroLengthRuler, MessageBoxActions.Ok); return; } double pixelSpacingWidth, pixelSpacingHeight; CalculatePixelSpacing( lengthInMm, widthInPixels, heightInPixels, aspectRatio, out pixelSpacingWidth, out pixelSpacingHeight); frame.NormalizedPixelSpacing.Calibrate(pixelSpacingHeight, pixelSpacingWidth); line.ParentPresentationImage.Draw(); }
private IPointsGraphic GetSelectedPolyline() { RoiGraphic graphic = GetSelectedRoi(); if (graphic == null) { return(null); } IPointsGraphic line = graphic.Subject as IPointsGraphic; if (line == null) { return(null); } return(line); }
/// <summary> /// Computes the index for insertion of a new point on an existing <see cref="IPointsGraphic"/>. /// </summary> private int IndexOfNextClosestPoint(IPointsGraphic subject, PointF point) { int index = 0; double best = double.MaxValue; PointF closestPoint = this.GetClosestPoint(point); PointF temp = PointF.Empty; for (int n = 0; n < subject.Points.Count - 1; n++) { double distance = Vector.DistanceFromPointToLine(closestPoint, subject.Points[n], subject.Points[n + 1], ref temp); if (distance < best) { best = distance; index = n + 1; } } return(index); }
/// <summary> /// Called to notify the derived class of a control point change event. /// </summary> /// <param name="index">The index of the point that changed.</param> /// <param name="point">The value of the point that changed.</param> protected override void OnControlPointChanged(int index, PointF point) { base.OnControlPointChanged(index, point); IPointsGraphic pointsGraphic = this.Subject; if (pointsGraphic.Points.Count > 1) { if (index == 0) { base.OnControlPointChanged(pointsGraphic.Points.Count - 1, point); } if (index == pointsGraphic.Points.Count - 1) { base.OnControlPointChanged(0, point); } } }
/// <summary> /// Called to notify that a vertex in the subject graphic has changed. /// </summary> /// <param name="index">The index of the vertex that changed.</param> protected override void OnSubjectPointChanged(int index) { base.OnSubjectPointChanged(index); IPointsGraphic pointsGraphic = this.Subject; if (pointsGraphic.Points.Count > 1) { if (index == 0) { base.OnSubjectPointChanged(pointsGraphic.Points.Count - 1); } if (index == pointsGraphic.Points.Count - 1) { base.OnSubjectPointChanged(0); } } }
/// <summary> /// Constructs a new linear region of interest, specifying an <see cref="IPointsGraphic"/> as the source of the definition and pixel data. /// </summary> /// <param name="polyline">The linear graphic that represents the region of interest.</param> public LinearRoi(IPointsGraphic polyline) : base(polyline.ParentPresentationImage) { polyline.CoordinateSystem = CoordinateSystem.Source; try { List <PointF> points = new List <PointF>(); foreach (PointF point in polyline.Points) { points.Add(point); } _points = points.AsReadOnly(); } finally { polyline.ResetCoordinateSystem(); } Platform.CheckTrue(_points.Count >= 2, "At least 2 points must be specified."); }
/// <summary> /// Constructs a new linear region of interest, specifying an <see cref="IPointsGraphic"/> as the source of the definition and pixel data. /// </summary> /// <param name="polyline">The linear graphic that represents the region of interest.</param> public LinearRoi(IPointsGraphic polyline) : base(polyline.ParentPresentationImage) { polyline.CoordinateSystem = CoordinateSystem.Source; try { List<PointF> points = new List<PointF>(); foreach(PointF point in polyline.Points) { points.Add(point); } _points = points.AsReadOnly(); } finally { polyline.ResetCoordinateSystem(); } Platform.CheckTrue(_points.Count >= 2, "At least 2 points must be specified."); }
/// <summary> /// Called to insert a vertex at the point where the context menu was last invoked. /// </summary> protected virtual void InsertVertex() { if (!_canAddRemoveVertices) { return; } object memento = this.CreateMemento(); IPointsGraphic subject = this.Subject; subject.CoordinateSystem = CoordinateSystem.Destination; try { int index = this.HitTestControlPoint(Point.Round(_lastContextMenuPoint)); if (index < 0) { // if inserting in middle of line, find which index to insert at index = IndexOfNextClosestPoint(subject, _lastContextMenuPoint); } else if (index == subject.Points.Count - 1) { // if inserting on last point, append instead of inserting before index++; } if (index >= 0) { subject.Points.Insert(index, _lastContextMenuPoint); } } finally { subject.ResetCoordinateSystem(); } AddToCommandHistory(this, memento, this.CreateMemento()); }
/// <summary> /// Called to remove the vertex at the point where the context menu was last invoked. /// </summary> protected virtual void DeleteVertex() { if (!_canAddRemoveVertices) { return; } object memento = this.CreateMemento(); IPointsGraphic subject = this.Subject; if (subject.Points.Count > 1) { int index = this.HitTestControlPoint(Point.Round(_lastContextMenuPoint)); if (index >= 0 && index < subject.Points.Count) { subject.Points.RemoveAt(index); } } AddToCommandHistory(this, memento, this.CreateMemento()); }
/// <summary> /// Constructs a new polygonal region of interest, specifying an <see cref="IPointsGraphic"/> as the source of the definition and pixel data. /// </summary> /// <param name="polygon">The polygonal graphic that represents the region of interest.</param> public PolygonalRoi(IPointsGraphic polygon) : base(polygon.ParentPresentationImage) { if (polygon.Points.Count < 4 || !polygon.Points.IsClosed) // a valid points graphic needs 4 endpoints to define 3 sides throw new ArgumentException("Supplied graphic must be a valid closed polygon.", "polygon"); polygon.CoordinateSystem = CoordinateSystem.Source; try { // this list of vertices *has* the repeated start point, so we remove it here // the repeated point is an artifact of the polyline graphics system, and should not be replicated in abstract polygon models. List<PointF> vertices = new List<PointF>(polygon.Points.Count - 1); for (int n = 0; n < polygon.Points.Count - 1; n++) { vertices.Add(polygon.Points[n]); } _polygon = new PolygonF(vertices); } finally { polygon.ResetCoordinateSystem(); } }
/// <summary> /// Constructs an interactive builder for the specified graphic. /// </summary> /// <param name="maximumVertices">The maximum number of vertices to accept.</param> /// <param name="pointsGraphic">The graphic to be interactively built.</param> /// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="maximumVertices"/> is less than 3.</exception> public InteractivePolygonGraphicBuilder(int maximumVertices, IPointsGraphic pointsGraphic) : base(pointsGraphic) { Platform.CheckArgumentRange(maximumVertices, 3, int.MaxValue, "maximumVertices"); _maximumVertices = maximumVertices; }
public bool ComputeProfile() { IPointsGraphic line = GetSelectedPolyline(); // For now, make sure the ROI is a polyline if (line == null || line.Points.Count != 2) { this.Enabled = false; return(false); } IImageGraphicProvider imageGraphicProvider = line.ParentPresentationImage as IImageGraphicProvider; if (imageGraphicProvider == null) { this.Enabled = false; return(false); } // For now, only allow ROIs of grayscale images GrayscaleImageGraphic image = imageGraphicProvider.ImageGraphic as GrayscaleImageGraphic; if (image == null) { this.Enabled = false; return(false); } line.CoordinateSystem = CoordinateSystem.Source; Point pt1 = new Point((int)line.Points[0].X, (int)line.Points[0].Y); Point pt2 = new Point((int)line.Points[1].X, (int)line.Points[1].Y); if (pt1.X < 0 || pt1.X > image.Columns - 1 || pt2.X < 0 || pt2.X > image.Columns - 1 || pt1.Y < 0 || pt1.Y > image.Rows - 1 || pt2.Y < 0 || pt2.Y > image.Rows - 1) { this.Enabled = false; return(false); } List <Point> pixels = BresenhamLine(pt1, pt2); _pixelIndices = new int[pixels.Count]; _pixelValues = new double[pixels.Count]; int i = 0; foreach (Point pixel in pixels) { int rawPixelValue = image.PixelData.GetPixel(pixel.X, pixel.Y); _pixelIndices[i] = i; _pixelValues[i] = (int)image.ModalityLut[rawPixelValue]; i++; } this.Enabled = true; return(true); }
public static InteractivePolygonGraphicBuilder CreatePolygonalShutterBuilder(IPointsGraphic graphic) { return new InteractivePolygonalShutterBuilder(graphic); }
/// <summary> /// Constructs an interactive builder for the specified graphic. /// </summary> /// <param name="pointsGraphic">The graphic to be interactively built.</param> public InteractivePolygonGraphicBuilder(IPointsGraphic pointsGraphic) : this(int.MaxValue, pointsGraphic) { }
public InteractivePolygonalShutterBuilder(IPointsGraphic graphic) : base(graphic) { graphic.Color = _normalColor; }
public void Select(IGraphic graphic) { if (graphic != null) { Platform.CheckFalse(ReferenceEquals(graphic.ParentPresentationImage, null), "Supplied graphic must be on the same presentation image."); Platform.CheckTrue(ReferenceEquals(graphic.ParentPresentationImage, this.ParentPresentationImage), "Supplied graphic must be on the same presentation image."); } IPointsGraphic value = GetLine(graphic); if (_selectedLine != value) { if (_selectedLine != null) { _selectedLine.Points.PointAdded -= OnSelectedLinePointChanged; _selectedLine.Points.PointChanged -= OnSelectedLinePointChanged; _selectedLine.Points.PointRemoved -= OnSelectedLinePointChanged; _selectedLine.Points.PointsCleared -= OnSelectedLinePointsCleared; } _selectedLine = value; if (_selectedLine != null) { _selectedLine.Points.PointAdded += OnSelectedLinePointChanged; _selectedLine.Points.PointChanged += OnSelectedLinePointChanged; _selectedLine.Points.PointRemoved += OnSelectedLinePointChanged; _selectedLine.Points.PointsCleared += OnSelectedLinePointsCleared; } Visible = _selectedLine != null; _isDirty = true; } }
public InteractivePolygonalShutterBuilder(IPointsGraphic graphic) : base(graphic) { graphic.Color = _normalColor; }
/// <summary> /// Constructs an interactive builder for the specified graphic. /// </summary> /// <param name="maximumVertices">The maximum number of vertices to accept.</param> /// <param name="pointsGraphic">The graphic to be interactively built.</param> public InteractiveHeartRatioLineGraphicBuilder(int maximumVertices, IPointsGraphic pointsGraphic) : this(maximumVertices, 2, pointsGraphic) { }
/// <summary> /// Constructs an interactive builder for the specified graphic. /// </summary> /// <param name="maximumVertices">The maximum number of vertices to accept.</param> /// <param name="pointsGraphic">The graphic to be interactively built.</param> public InteractivePolylineGraphicBuilder(int maximumVertices, IPointsGraphic pointsGraphic) : this(maximumVertices, 2, pointsGraphic) { }
public static InteractivePolygonGraphicBuilder CreatePolygonalShutterBuilder(IPointsGraphic graphic) { return(new InteractivePolygonalShutterBuilder(graphic)); }
/// <summary> /// Constructs an interactive builder for the specified graphic. /// </summary> /// <param name="pointsGraphic">The graphic to be interactively built.</param> public InteractivePolylineGraphicBuilder(IPointsGraphic pointsGraphic) : this(int.MaxValue, pointsGraphic) {}
internal static void TestCalibration(double lengthInMm, IPointsGraphic graphic) { Frame frame = ((IImageSopProvider)graphic.ParentPresentationImage).Frame; ApplyCalibration(lengthInMm, graphic, frame, null); }
/// <summary> /// Constructs an interactive builder for the specified graphic. /// </summary> /// <param name="maximumVertices">The maximum number of vertices to accept.</param> /// <param name="minimumVertices">The minimum number of vertices to accept.</param> /// <param name="pointsGraphic">The graphic to be interactively built.</param> public InteractivePolylineGraphicBuilder(int maximumVertices, int minimumVertices, IPointsGraphic pointsGraphic) : base(pointsGraphic) { Platform.CheckPositive(minimumVertices, "minimumVertices"); Platform.CheckTrue(maximumVertices >= minimumVertices, "max vertices >= min vertices"); Platform.CheckTrue(minimumVertices > 1, "min vertices > 1"); _maximumVertices = maximumVertices; _minimumVertices = minimumVertices; }
/// <summary> /// Constructs an interactive builder for the specified graphic. /// </summary> /// <param name="pointsGraphic">The graphic to be interactively built.</param> public InteractiveHeartRatioLineGraphicBuilder(IPointsGraphic pointsGraphic) : this(int.MaxValue, pointsGraphic) { }
/// <summary> /// Constructs an interactive builder for the specified graphic. /// </summary> /// <param name="maximumVertices">The maximum number of vertices to accept.</param> /// <param name="pointsGraphic">The graphic to be interactively built.</param> /// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="maximumVertices"/> is less than 3.</exception> public InteractivePolygonGraphicBuilder(int maximumVertices, IPointsGraphic pointsGraphic) : base(pointsGraphic) { Platform.CheckArgumentRange(maximumVertices, 3, int.MaxValue, "maximumVertices"); _maximumVertices = maximumVertices; }
private static bool IsClosed(IPointsGraphic g) { if (g.Points.Count > 2) return FloatComparer.AreEqual(g.Points[0], g.Points[g.Points.Count - 1]); return false; }
/// <summary> /// Computes the index for insertion of a new point on an existing <see cref="IPointsGraphic"/>. /// </summary> private int IndexOfNextClosestPoint(IPointsGraphic subject, PointF point) { int index = 0; double best = double.MaxValue; PointF closestPoint = this.GetClosestPoint(point); PointF temp = PointF.Empty; for (int n = 0; n < subject.Points.Count - 1; n++) { double distance = Vector.DistanceFromPointToLine(closestPoint, subject.Points[n], subject.Points[n + 1], ref temp); if (distance < best) { best = distance; index = n + 1; } } return index; }
public override void OnDrawing() { base.OnDrawing(); if (!_isDirty) { return; } IOverlayGraphicsProvider overlayGraphicsProvider = this.ParentPresentationImage as IOverlayGraphicsProvider; if (overlayGraphicsProvider == null) { return; } IList <ShowAnglesToolGraphic> freeAngleGraphics = CollectionUtils.Cast <ShowAnglesToolGraphic>(this.Graphics); if (this.Visible && _selectedLine != null && _selectedLine.Points.Count == 2) { _selectedLine.CoordinateSystem = CoordinateSystem.Source; try { foreach (IGraphic otherLineGraphic in overlayGraphicsProvider.OverlayGraphics) { IPointsGraphic otherLine = GetLine(otherLineGraphic); if (otherLine != null && !ReferenceEquals(otherLine, _selectedLine) && otherLine.Points.Count == 2) { ShowAnglesToolGraphic showAnglesToolGraphic; if (freeAngleGraphics.Count > 0) { freeAngleGraphics.Remove(showAnglesToolGraphic = freeAngleGraphics[0]); } else { this.Graphics.Add(showAnglesToolGraphic = new ShowAnglesToolGraphic()); } showAnglesToolGraphic.CoordinateSystem = otherLine.CoordinateSystem = CoordinateSystem.Source; try { showAnglesToolGraphic.SetEndpoints(_selectedLine.Points[0], _selectedLine.Points[1], otherLine.Points[0], otherLine.Points[1]); } finally { showAnglesToolGraphic.ResetCoordinateSystem(); otherLine.ResetCoordinateSystem(); } } } } finally { _selectedLine.ResetCoordinateSystem(); } } foreach (IGraphic freeAngleGraphic in freeAngleGraphics) { this.Graphics.Remove(freeAngleGraphic); freeAngleGraphic.Dispose(); } }
internal static void TestCalibration(double lengthInMm, IPointsGraphic graphic) { Frame frame = ((IImageSopProvider)graphic.ParentPresentationImage).Frame; ApplyCalibration(lengthInMm, graphic, frame, null); }
/// <summary> /// Constructs an interactive builder for the specified graphic. /// </summary> /// <param name="maximumVertices">The maximum number of vertices to accept.</param> /// <param name="pointsGraphic">The graphic to be interactively built.</param> public InteractivePolylineGraphicBuilder(int maximumVertices, IPointsGraphic pointsGraphic) : this(maximumVertices, 2, pointsGraphic) { }
private static void ApplyCalibration(double lengthInMm, IPointsGraphic line, Frame frame, IDesktopWindow desktopWindow) { double aspectRatio; if (frame.PixelAspectRatio.IsNull) { // When there is no aspect ratio tag, the image is displayed with the aspect ratio // of the pixel spacing, so just keep the aspect ratio the same as // what's displayed. Otherwise, after calibration, a 2cm line drawn horizontally // would be visibly different from a 2cm line drawn vertically. if (!frame.NormalizedPixelSpacing.IsNull) aspectRatio = frame.NormalizedPixelSpacing.AspectRatio; else aspectRatio = 1; } else { aspectRatio = frame.PixelAspectRatio.Value; } line.CoordinateSystem = CoordinateSystem.Source; double widthInPixels = line.Points[1].X - line.Points[0].X; double heightInPixels = line.Points[1].Y - line.Points[0].Y; line.ResetCoordinateSystem(); if (widthInPixels == 0 && heightInPixels == 0) { desktopWindow.ShowMessageBox(SR.ErrorCannotCalibrateZeroLengthRuler, MessageBoxActions.Ok); return; } double pixelSpacingWidth, pixelSpacingHeight; CalculatePixelSpacing( lengthInMm, widthInPixels, heightInPixels, aspectRatio, out pixelSpacingWidth, out pixelSpacingHeight); frame.NormalizedPixelSpacing.Calibrate(pixelSpacingHeight, pixelSpacingWidth); line.ParentPresentationImage.Draw(); }