using CoreUnit.Common; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Text.Json; using System.Windows.Forms; using System.Xml; namespace CoreUnit.Control.UserControl.Canvas { public class RoiTool : DrawObjectBase, ISerialize, IDrawObject { protected UnitPoint m_startPoint = UnitPoint.Empty; protected UnitPoint m_endPoint = UnitPoint.Empty; UnitPoint m_P1; //사각형에서 Left,Top [Browsable(false)] public UnitPoint P1 { get { return m_P1; } set { m_P1 = value; } } UnitPoint m_P2; //사각형에서 Left,Bottom [Browsable(false)] public UnitPoint P2 { get { return m_P2; } set { m_P2 = value; } } UnitPoint m_P3; //사각형에서 Right,Bottom [Browsable(false)] public UnitPoint P3 { get { return m_P3; } set { m_P3 = value; } } UnitPoint m_P4;//사각형에서 Right,Top [Browsable(false)] public UnitPoint P4 { get { return m_P4; } set { m_P4 = value; } } [Browsable(false)] public UnitPoint P12 { get { UnitPoint newPoint = new UnitPoint(P1.X / 2 + P2.X / 2, P1.Y / 2 + P2.Y / 2); return newPoint; } } [Browsable(false)] public UnitPoint P23 { get { UnitPoint newPoint = new UnitPoint(P2.X / 2 + P3.X / 2, P2.Y / 2 + P3.Y / 2); return newPoint; } } [Browsable(false)] public UnitPoint P34 { get { UnitPoint newPoint = new UnitPoint(P3.X / 2 + P4.X / 2, P3.Y / 2 + P4.Y / 2); return newPoint; } } [Browsable(false)] public UnitPoint P41 { get { UnitPoint newPoint = new UnitPoint(P4.X / 2 + P1.X / 2, P4.Y / 2 + P1.Y / 2); return newPoint; } } [Browsable(true)] [ReadOnly(true)] [Category("1.Boundary")] [DisplayName("Left,Bottom,Right,Top")] [Description("Boundary of Object")] public RectangleF ClientRect { get { List points = new List { P1, P2, P3, P4 }; return ScreenUtils.GetRect(points, 0); } } [Browsable(false)] public UnitPoint Center { get { return new UnitPoint(MiddlePoint.X, MiddlePoint.Y); } set { MiddlePoint = value.Point; } } [Browsable(true)] [ReadOnly(false)] [Category("2. Geometry")] [DisplayName("Center")] [Description("Center Of ROI")] [XmlSerializable] [TypeConverter(typeof(PointFConverter))] public PointF MiddlePoint { get { return HitUtil.LineMidpoint(P2, P4).Point; } set { PointF offset = new PointF(); offset.X = (value.X - MiddlePoint.X); offset.Y = (value.Y - MiddlePoint.Y); Move(new UnitPoint(offset)); } } [Browsable(true)] [ReadOnly(false)] [Category("2. Geometry")] [DisplayName("Width")] [Description("Width Of ROI")] [XmlSerializable] public double RoiWidth { get { return Math.Round(HitUtil.Distance(P1, P4), 3); } set { double distance = value; MakeWidth(MiddlePoint, distance); } } [Browsable(true)] [ReadOnly(false)] [Category("2. Geometry")] [DisplayName("Height")] [Description("Height Of ROI")] [XmlSerializable] public double RoiHeight { get { return Math.Round(HitUtil.Distance(P1, P2), 3); } set { double distance = value; MakeHeight(MiddlePoint, distance); } } string m_visionProcessType; [Browsable(true)] [ReadOnly(true)] [Category("3. Paramter")] [DisplayName("Vision Process Type")] [Description("Vision Process Type")] [XmlSerializable] public string VisionProcessType { get { return m_visionProcessType; } set { m_visionProcessType = value; } } int m_alignId = -1; [Browsable(true)] [ReadOnly(false)] [Category("3. Parameter")] [DisplayName("Align ID")] [Description("Align ID")] [XmlSerializable] public int AlignID { get { return m_alignId; } set { m_alignId = value; } } string m_type; [Browsable(false)] public virtual string Type { get { m_type = RoiTool.ObjectType; return m_type; } set { m_type = value; } } public static string ObjectType { get { return "Roi"; } } public RoiTool() { } public RoiTool(string visionProcessType) { VisionProcessType = visionProcessType; } static int ThresholdPixel = 6; static float ThresholdWidth(ICanvas canvas, float objectwidth) { return ThresholdWidth(canvas, objectwidth, ThresholdPixel); } public static float ThresholdWidth(ICanvas canvas, float objectwidth, float pixelwidth) { double minWidth = canvas.ToUnit(pixelwidth); double width = Math.Max(objectwidth / 2, minWidth); return (float)width; } public override void InitializeFromModel(UnitPoint point, DrawingLayer layer, ISnapPoint snap) { m_startPoint = m_endPoint = P1 = P2 = P3 = P4 = point; Width = layer.Width; Color = layer.Color; Selected = true; } public void Copy(RoiTool acopy) { base.Copy(acopy); m_startPoint = acopy.P1; m_endPoint = acopy.P3; P1 = acopy.P1; P2 = acopy.P2; P3 = acopy.P3; P4 = acopy.P4; Selected = acopy.Selected; VisionProcessType = acopy.VisionProcessType; } public void SaveRoiImage(string fileName, Bitmap image) { } #region IDrawObject Members public virtual IDrawObject Clone() { RoiTool a = new RoiTool(); a.Copy(this); return a; } public RectangleF GetBoundingRect(ICanvas canvas) { float thWidth = ThresholdWidth(canvas, Width, ThresholdPixel); if (thWidth < Width) { thWidth = Width; } List points = new List { P1, P2, P3, P4 }; return ScreenUtils.GetRect(points, thWidth); } public void Draw(ICanvas canvas, RectangleF unitrect) { Color color = Color.Red; Pen pen = canvas.CreatePen(color, Width); //2. Group객체의 가장자리 bound draw 함수 if (Highlighted || Selected) { //3.Rectangle 객체에 대한 중심 위치 점 draw 함수 //pen = DrawUtils.SelectedPen; if (Locked == false) { canvas.DrawArc(canvas, pen, new UnitPoint(Center.X, Center.Y), 1, 0, 360); DrawUtils.DrawNode(canvas, P1); DrawUtils.DrawNode(canvas, P2); DrawUtils.DrawNode(canvas, P3); DrawUtils.DrawNode(canvas, P4); DrawUtils.DrawNode(canvas, P12); DrawUtils.DrawNode(canvas, P23); DrawUtils.DrawNode(canvas, P34); DrawUtils.DrawNode(canvas, P41); } } canvas.DrawLines(canvas, pen, new List() { P1, P2, P3, P4 }); } public bool PointInObject(ICanvas canvas, UnitPoint point) { RectangleF boundingrect = GetBoundingRect(canvas); return boundingrect.Contains(point.Point); } public bool ObjectInRectangle(ICanvas canvas, RectangleF rect, bool anyPoint) { RectangleF boundingrect = GetBoundingRect(canvas); if (anyPoint) { return (HitUtil.LineIntersectWithRect(P1, P2, rect) || HitUtil.LineIntersectWithRect(P3, P4, rect)); } return rect.Contains(boundingrect); } public void OnMouseMove(ICanvas canvas, UnitPoint point) { if (Locked == false) { m_endPoint = point; DrawBound(m_startPoint, m_endPoint); } } public void DrawBound(UnitPoint startPoint, UnitPoint endPoint) { P1 = new UnitPoint(Math.Min(startPoint.X, endPoint.X), Math.Max(startPoint.Y, endPoint.Y)); P2 = new UnitPoint(Math.Min(startPoint.X, endPoint.X), Math.Min(startPoint.Y, endPoint.Y)); P3 = new UnitPoint(Math.Max(startPoint.X, endPoint.X), Math.Min(startPoint.Y, endPoint.Y)); P4 = new UnitPoint(Math.Max(startPoint.X, endPoint.X), Math.Max(startPoint.Y, endPoint.Y)); } public eDrawObjectMouseDown OnMouseDown(ICanvas canvas, UnitPoint point, ISnapPoint snappoint) { Selected = false; return eDrawObjectMouseDown.Done; } public void OnMouseUp(ICanvas canvas, UnitPoint point, ISnapPoint snappoint) { } public void OnKeyDown(ICanvas canvas, KeyEventArgs e) { } [Browsable(false)] public UnitPoint RepeatStartingPoint { get { return UnitPoint.Empty; } } public INodePoint NodePoint(ICanvas canvas, UnitPoint point) { if (Locked == false) { float thWidth = ThresholdWidth(canvas, Width); #region Node Point Edge if (HitUtil.CircleHitPoint(P1, thWidth, point)) { return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P1); } if (HitUtil.CircleHitPoint(P2, thWidth, point)) { return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P2); } if (HitUtil.CircleHitPoint(P3, thWidth, point)) { return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P3); } if (HitUtil.CircleHitPoint(P4, thWidth, point)) { return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P4); } if (HitUtil.CircleHitPoint(P12, thWidth, point)) { return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P12); } if (HitUtil.CircleHitPoint(P23, thWidth, point)) { return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P23); } if (HitUtil.CircleHitPoint(P34, thWidth, point)) { return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P34); } if (HitUtil.CircleHitPoint(P41, thWidth, point)) { return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P41); } if (HitUtil.CircleHitPoint(Center, thWidth, point)) { return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.Center); } } #endregion return null; } public ISnapPoint SnapPoint(ICanvas canvas, UnitPoint point, List otherobj, Type[] runningsnaptypes, Type usersnaptype) { return null; } public void Move(UnitPoint offset) { m_P1.X += offset.X; m_P1.Y += offset.Y; m_P2.X += offset.X; m_P2.Y += offset.Y; m_P3.X += offset.X; m_P3.Y += offset.Y; m_P4.X += offset.X; m_P4.Y += offset.Y; } public void Rotate(float angle, UnitPoint center) { P1 = HitUtil.RotatePoint(angle, P1, center); P2 = HitUtil.RotatePoint(angle, P2, center); P3 = HitUtil.RotatePoint(angle, P3, center); P4 = HitUtil.RotatePoint(angle, P4, center); } public void MakeLength(float distance) { } public void MakeWidth(PointF center, double width) { P1 = new UnitPoint(center.X - width / 2, P1.Y); P2 = new UnitPoint(center.X - width / 2, P2.Y); P3 = new UnitPoint(center.X + width / 2, P3.Y); P4 = new UnitPoint(center.X + width / 2, P4.Y); } public void MakeHeight(PointF center, double height) { P1 = new UnitPoint(P1.X, center.Y + height / 2); P2 = new UnitPoint(P2.X, center.Y - height / 2); P3 = new UnitPoint(P3.X, center.Y - height / 2); P4 = new UnitPoint(P4.X, center.Y + height / 2); } public virtual string GetInfoAsString() { return string.Format("{1:D3} {0}@Boundary:{2:F3}", this.Type, No + 1, ClientRect); } #endregion #region 1.마킹객체에 대한 속성 bool m_enabled = true; [Browsable(false)] public bool Enabled { get { return m_enabled; } set { m_enabled = value; } } uint m_markingCount = 1; [Browsable(false)] public uint MarkingCount { get { return m_markingCount; } set { m_markingCount = value; } } [Browsable(false)] public PointF PF1 { get { return P1.Point; } set { P1 = new UnitPoint(value); } } [Browsable(false)] public PointF PF2 { get { return P2.Point; } set { P2 = new UnitPoint(value); } } [Browsable(false)] public PointF PF3 { get { return P3.Point; } set { P3 = new UnitPoint(value); } } [Browsable(false)] public PointF PF4 { get { return P4.Point; } set { P4 = new UnitPoint(value); } } [Browsable(false)] public float Angle { get { return (float)Math.Round(HitUtil.RadiansToDegrees(HitUtil.LineAngleR(P1, P4, 0)), 3); ; } set { float angle = value - Angle; Rotate(angle, Center); } } int m_no; [Browsable(false)] public int No { get { return m_no; } set { m_no = value; } } [Browsable(false)] public int ScannerParamID { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } #endregion #region ISerialize public virtual void GetObjectData(XmlWriter wr) { wr.WriteStartElement(Type); Common.XmlUtil.WriteProperties(this, wr); wr.WriteEndElement(); } public virtual string GetObjectData() { string jsonString = string.Empty; var options = new JsonSerializerOptions { WriteIndented = true }; try { jsonString += JsonSerializer.Serialize(this, options); } catch { } return jsonString; } private void GetRectangleObjectData(IDrawObject obj, XmlWriter wr) { wr.WriteStartElement(obj.Type); Common.XmlUtil.WriteProperties(obj, wr); wr.WriteEndElement(); } public void AfterSerializedIn() { } #endregion } public class NodePointRoiEdge : INodePoint { public enum ePoint { P1, P2, P3, P4, P12, P23, P34, P41, Center } static bool m_angleLocked = false; RoiTool m_owner; RoiTool m_clone; UnitPoint m_originalPoint; public UnitPoint OriginalPoint { get { lock (this) { return m_originalPoint; } } set { lock (this) { m_originalPoint = value; } } } UnitPoint m_endPoint; public UnitPoint EndPoint { get { lock (this) { return m_endPoint; } } set { lock (this) { m_endPoint = value; } } } ePoint m_pointId; public ePoint PointId { get { lock (this) { return m_pointId; } } set { lock (this) { m_pointId = value; } } } public NodePointRoiEdge(RoiTool owner, ePoint id) { m_owner = owner; m_clone = m_owner.Clone() as RoiTool; m_pointId = id; m_originalPoint = GetPoint(m_pointId); } #region INodePoint Members public IDrawObject GetClone() { return m_clone; } public IDrawObject GetOriginal() { return m_owner; } public void SetPosition(UnitPoint pos) //변경되는 위치의 포인터 값 { SetPoint(m_pointId, pos, m_clone); } public void Finish() { m_endPoint = GetPoint(m_pointId); m_owner.P1 = m_clone.P1; m_owner.P2 = m_clone.P2; m_owner.P3 = m_clone.P3; m_owner.P4 = m_clone.P4; m_clone = null; } public void Cancel() { } public void Undo() { SetPoint(m_pointId, m_originalPoint, m_owner); } public void Redo() { SetPoint(m_pointId, m_endPoint, m_owner); } public void OnKeyDown(ICanvas canvas, KeyEventArgs e) { if (e.KeyCode == Keys.L) { m_angleLocked = !m_angleLocked; e.Handled = true; } } #endregion protected UnitPoint GetPoint(ePoint pointid) { if (pointid == ePoint.P1) return m_clone.P1; if (pointid == ePoint.P2) return m_clone.P2; if (pointid == ePoint.P3) return m_clone.P3; if (pointid == ePoint.P4) return m_clone.P4; if (pointid == ePoint.P12) return m_clone.P12; if (pointid == ePoint.P23) return m_clone.P23; if (pointid == ePoint.P34) return m_clone.P34; if (pointid == ePoint.P41) return m_clone.P41; return m_owner.P1; } protected void SetPoint(ePoint pointid, UnitPoint point, RoiTool rect) { UnitPoint startPoint = new UnitPoint(0, 0); UnitPoint endPoint = point; if (pointid == ePoint.P1 || pointid == ePoint.P2 || pointid == ePoint.P3 || pointid == ePoint.P4) { if (pointid == ePoint.P1) { startPoint = rect.P3; } else if (pointid == ePoint.P2) { startPoint = rect.P4; } else if (pointid == ePoint.P3) { startPoint = rect.P1; } else if (pointid == ePoint.P4) { startPoint = rect.P2; } rect.P1 = new UnitPoint(Math.Min(startPoint.X, endPoint.X), Math.Max(startPoint.Y, endPoint.Y)); rect.P2 = new UnitPoint(Math.Min(startPoint.X, endPoint.X), Math.Min(startPoint.Y, endPoint.Y)); rect.P3 = new UnitPoint(Math.Max(startPoint.X, endPoint.X), Math.Min(startPoint.Y, endPoint.Y)); rect.P4 = new UnitPoint(Math.Max(startPoint.X, endPoint.X), Math.Max(startPoint.Y, endPoint.Y)); } else if (pointid == ePoint.P12 || pointid == ePoint.P23 || pointid == ePoint.P34 || pointid == ePoint.P41) { if (pointid == ePoint.P12) { startPoint = rect.P34; rect.P1 = new UnitPoint(Math.Min(startPoint.X, endPoint.X), rect.P1.Y); rect.P2 = new UnitPoint(Math.Min(startPoint.X, endPoint.X), rect.P2.Y); } else if (pointid == ePoint.P23) { startPoint = rect.P41; rect.P2 = new UnitPoint(rect.P2.X, Math.Min(startPoint.Y, endPoint.Y)); rect.P3 = new UnitPoint(rect.P3.X, Math.Min(startPoint.Y, endPoint.Y)); } else if (pointid == ePoint.P34) { startPoint = rect.P12; rect.P3 = new UnitPoint(Math.Max(startPoint.X, endPoint.X), rect.P3.Y); rect.P4 = new UnitPoint(Math.Max(startPoint.X, endPoint.X), rect.P4.Y); } else if (pointid == ePoint.P41) { startPoint = rect.P23; rect.P1 = new UnitPoint(rect.P1.X, Math.Max(startPoint.Y, endPoint.Y)); rect.P4 = new UnitPoint(rect.P4.X, Math.Max(startPoint.Y, endPoint.Y)); } } else if (pointid == ePoint.Center) { rect.Center = endPoint; } } } }