using CoreUnit.Common; using GUI.Properties; 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 NodePointRectangleEdge : INodePoint { public enum ePoint { P1, P2, P3, P4, P12, P23, P34, P41 } static bool m_angleLocked = false; RectangleTool m_owner; RectangleTool 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 NodePointRectangleEdge(RectangleTool owner, ePoint id) { m_owner = owner; m_clone = m_owner.Clone() as RectangleTool; 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, RectangleTool rect) { var rotationAngle = rect.Angle; var center = rect.Center; var startPoint = new UnitPoint(0, 0); UnitPoint endPoint; rect.P1 = HitUtil.RotatePoint(-rotationAngle, rect.P1, center); rect.P2 = HitUtil.RotatePoint(-rotationAngle, rect.P2, center); rect.P3 = HitUtil.RotatePoint(-rotationAngle, rect.P3, center); rect.P4 = HitUtil.RotatePoint(-rotationAngle, rect.P4, center); endPoint = HitUtil.RotatePoint(-rotationAngle, point, center); if (pointid == ePoint.P1 || pointid == ePoint.P2 || pointid == ePoint.P3 || pointid == ePoint.P4) { // Logic for updating corners 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) { // Logic for updating edges 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)); } } //// 새로운 회전 각도를 적용하여 사각형의 포인트를 업데이트합니다. rect.P1 = HitUtil.RotatePoint(rotationAngle, rect.P1, center); rect.P2 = HitUtil.RotatePoint(rotationAngle, rect.P2, center); rect.P3 = HitUtil.RotatePoint(rotationAngle, rect.P3, center); rect.P4 = HitUtil.RotatePoint(rotationAngle, rect.P4, center); } } class NodePointRectangleCenter : INodePoint { RectangleTool m_owner; RectangleTool 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; } } } public NodePointRectangleCenter(RectangleTool owner) { m_owner = owner; m_clone = m_owner.Clone() as RectangleTool; m_owner.Selected = false; m_originalPoint = GetPoint(); } #region INodePoint Members public IDrawObject GetClone() { return m_clone; } public IDrawObject GetOriginal() { return m_owner; } public void SetPosition(UnitPoint pos) { SetPoint(pos); } public void Finish() { m_endPoint = GetPoint(); 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_owner.Selected = true; m_clone = null; } public void Cancel() { m_owner.Selected = true; } public void Undo() { m_originalPoint = m_owner.Center; } public void Redo() { m_endPoint = m_owner.Center; } public void OnKeyDown(ICanvas canvas, KeyEventArgs e) { } #endregion protected UnitPoint GetPoint() { return m_clone.Center; } protected void SetPoint(UnitPoint point) { m_clone.Center = point; } } class NodePointRectangleAngle : INodePoint { protected RectangleTool m_owner; protected RectangleTool m_clone; protected float m_originalAngle; protected float m_endAngle; public NodePointRectangleAngle(RectangleTool owner) { m_owner = owner; m_clone = m_owner.Clone() as RectangleTool; m_clone.Angle = m_owner.Angle; m_originalAngle = m_owner.Angle; m_owner.Selected = false; } #region INodePoint Members public IDrawObject GetClone() { return m_clone; } public IDrawObject GetOriginal() { return m_owner; } public virtual void SetPosition(UnitPoint pos) { m_clone.Angle = (float)HitUtil.RadiansToDegrees(HitUtil.LineAngleR(m_clone.Center, pos, 0)) - 90; } public virtual void Finish() { m_endAngle = m_clone.Angle; 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_owner.Selected = true; m_clone = null; } public void Cancel() { m_owner.Selected = true; } public virtual void Undo() { m_owner.Angle = m_originalAngle; } public virtual void Redo() { m_owner.Angle = m_endAngle; } public void OnKeyDown(ICanvas canvas, KeyEventArgs e) { } #endregion } public class RectangleTool : DrawObjectBase, IDrawObject, ISerialize { protected UnitPoint m_startPoint = UnitPoint.Empty; protected UnitPoint m_endPoint = UnitPoint.Empty; UnitPoint m_originalCenter; public UnitPoint OriginalCenter { get { lock (this) { return m_originalCenter; } } set { lock (this) { m_originalCenter = value; } } } 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 => (P1 + P2) / 2; } [Browsable(false)] public UnitPoint P23 { get => (P2 + P3) / 2; } [Browsable(false)] public UnitPoint P34 { get => (P3 + P4) / 2; } [Browsable(false)] public UnitPoint P41 { get => (P4 + P1) / 2; } [Browsable(false)] public UnitPoint AnglePoint { get { return HitUtil.RotatePoint(Angle, new UnitPoint(Center.X, Center.Y + 10), Center); } } public static string ObjectType { get { return "Rectangle"; } } [Browsable(false)] public UnitPoint Center { get { return new UnitPoint(MiddlePoint.X, MiddlePoint.Y); } set { MiddlePoint = value.Point; } } [Browsable(false)] public double DiagonalLine { get { return HitUtil.Distance(P1, P4); } } public RectangleTool() { } 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; m_originalCenter = Center; Width = layer.Width; Color = layer.Color; Selected = true; } public void Copy(RectangleTool acopy) { base.Copy(acopy); m_startPoint = acopy.P1; m_endPoint = acopy.P3; m_originalCenter = acopy.m_originalCenter; P1 = acopy.P1; P2 = acopy.P2; P3 = acopy.P3; P4 = acopy.P4; Angle = acopy.Angle; m_no = acopy.No; Type = acopy.Type; Selected = acopy.Selected; //마킹객체에 대한 속성 복사 Enabled = acopy.Enabled; MarkingCount = acopy.MarkingCount; WeldingParameterID = acopy.WeldingParameterID; ScannerParamNo = acopy.ScannerParamNo; ScannerParamID = acopy.ScannerParamID; } #region IDrawObject Members #region 1.마킹객체에 대한 속성 bool m_enabled = true; [Browsable(true)] [ReadOnly(false)] [Category("용접 파라미터")] [DisplayName("용접 작업 유무")] [Description("용접 작업 진행 여부")] [XmlSerializable] public bool Enabled { get { return m_enabled; } set { m_enabled = value; } } uint m_markingCount = 1; [Browsable(true)] [ReadOnly(false)] [Category("용접 파라미터")] [DisplayName("용접 횟수")] [Description("용접 작업 반복 횟수")] [XmlSerializable] public uint MarkingCount { get { return m_markingCount; } set { m_markingCount = value; } } #endregion #region 2.드로잉 객체에 대한 속성 int m_no; [Browsable(true)] [ReadOnly(true)] [Category("객체")] [DisplayName("ID")] [Description("드로잉 객체 번호")] [XmlSerializable] public int No { get { return m_no; } set { m_no = value; } } string m_type; [Browsable(true)] [ReadOnly(true)] [Category("객체")] [DisplayName("종류")] [Description("드로잉 객체 종류")] [XmlSerializable] public virtual string Type { get { m_type = RectangleTool.ObjectType; return m_type; } set { m_type = value; } } [Browsable(true)] [ReadOnly(true)] [Category("GEOMETRY")] [DisplayName("1.왼쪽 상위점[X,Y](mm)")] [Description("↖그룹 객체 영역의 왼쪽 상위점")] [TypeConverter(typeof(PointFConverter))] [XmlSerializable] public PointF PF1 { get { return P1.Point; } set { P1 = new UnitPoint(value); } } [Browsable(true)] [ReadOnly(true)] [Category("GEOMETRY")] [DisplayName("2.왼쪽 하위점[X,Y](mm)")] [Description("↙그룹 객체 영역의 왼쪽 하위점")] [TypeConverter(typeof(PointFConverter))] [XmlSerializable] public PointF PF2 { get { return P2.Point; } set { P2 = new UnitPoint(value); } } [Browsable(true)] [ReadOnly(true)] [Category("GEOMETRY")] [DisplayName("3.오른쪽 하위점[X,Y](mm)")] [Description("↘그룹 객체 영역의 오른쪽 하위점")] [TypeConverter(typeof(PointFConverter))] [XmlSerializable] public PointF PF3 { get { return P3.Point; } set { P3 = new UnitPoint(value); } } [Browsable(true)] [ReadOnly(true)] [Category("GEOMETRY")] [DisplayName("4.오른쪽 상위점[X,Y](mm)")] [Description("↗그룹 객체 영역의 오른쪽 상위점")] [TypeConverter(typeof(PointFConverter))] [XmlSerializable] public PointF PF4 { get { return P4.Point; } set { P4 = new UnitPoint(value); } } [Browsable(true)] [ReadOnly(false)] [Category("GEOMETRY")] [DisplayName("5.중심점[X,Y](mm)")] [Description("중심점")] [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("GEOMETRY")] [DisplayName("6.각도(˚)")] [Description("드로잉 객체의 각도")] public float Angle { get { return (float)Math.Round(HitUtil.RadiansToDegrees(HitUtil.LineAngleR(P1, P4, 0)), 3); ; } set { float angle = value - Angle; Rotate(angle, Center); } } [Browsable(true)] [ReadOnly(true)] [Category("Boundary")] [DisplayName("Left,Bottom,Right,Top")] [Description("Boundary of Object")] [TypeConverter(typeof(RectangleFConverter))] public RectangleF ClientRect { get { List points = new List { P1, P2, P3, P4 }; return ScreenUtils.GetRect(points, 0); } } int m_scannerParamNo = 0; [Browsable(false)] [ReadOnly(false)] [Category("3. Marking Parameter")] [DisplayName("용접 조건 번호")] [Description("용접 조건(스캔속도 및 레이저 파워 값등..) 번호 설정")] [XmlSerializable] public int ScannerParamNo { get { return m_scannerParamNo; } set { m_scannerParamNo = value; } } [Browsable(false)] [ReadOnly(false)] [Category("3. Marking Parameter")] [DisplayName("용접 조건 ID")] [Description("용접 조건(스캔속도 및 레이저 파워 값등..) ID 설정")] [XmlSerializable] public int ScannerParamID { get { return m_scannerParamNo + 1; } set { m_scannerParamNo = value - 1; } } [Browsable(true)] [ReadOnly(false)] [Category("Pen")] [DisplayName("Parameter ID")] [Description("Welding Paramter ID")] [Editor(typeof(WeldingParameterIDEditor.WeldingParamterNoUITypeEditor), typeof(System.Drawing.Design.UITypeEditor))] [XmlSerializable] public WeldingParameterIDEditor.eWeldingParamterID WeldingParameterID { get { return (WeldingParameterIDEditor.eWeldingParamterID)ScannerParamID; } set { ScannerParamID = (int)value; } } #endregion public IDrawObject Clone() { RectangleTool a = new RectangleTool(); 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; color = WeldingParameterIDEditor.weldingColorList[(int)WeldingParameterID - 1]; Pen pen = canvas.CreatePen(color, Width); //2.Rectangle 객체의 가장자리 bound draw 함수 if (Highlighted || Selected) { pen = DrawUtils.SelectedPen; if (Locked == false) { //3.Rectangle 객체에 대한 중심 위치 점 draw 함수 canvas.DrawArc(canvas, pen, new UnitPoint(MiddlePoint.X, MiddlePoint.Y), Settings.Default.GroupCenterCircleRadius, 0, 360); DrawUtils.DrawNode(canvas, P1); DrawUtils.DrawNode(canvas, P2); DrawUtils.DrawNode(canvas, P3); DrawUtils.DrawNode(canvas, P4); DrawUtils.DrawNode(canvas, P41); DrawUtils.DrawNode(canvas, P12); DrawUtils.DrawNode(canvas, P23); DrawUtils.DrawNode(canvas, P34); //3.Rectangle 객체에 회전점 draw 함수 canvas.DrawArc(canvas, pen, AnglePoint, Settings.Default.GroupCenterCircleRadius, 0, 360); //4.Rectangle 의 중심점과 회전점 사이의 직선 canvas.DrawLine(canvas, pen, Center, AnglePoint); } } 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); if (HitUtil.CircleHitPoint(Center, thWidth, point)) { return new NodePointRectangleCenter(this); } if (HitUtil.CircleHitPoint(AnglePoint, thWidth, point)) { return new NodePointRectangleAngle(this); } OriginalCenter = Center; #region Node Point Edge if (HitUtil.CircleHitPoint(P1, thWidth, point)) { return new NodePointRectangleEdge(this, NodePointRectangleEdge.ePoint.P1); } if (HitUtil.CircleHitPoint(P2, thWidth, point)) { return new NodePointRectangleEdge(this, NodePointRectangleEdge.ePoint.P2); } if (HitUtil.CircleHitPoint(P3, thWidth, point)) { return new NodePointRectangleEdge(this, NodePointRectangleEdge.ePoint.P3); } if (HitUtil.CircleHitPoint(P4, thWidth, point)) { return new NodePointRectangleEdge(this, NodePointRectangleEdge.ePoint.P4); } if (HitUtil.CircleHitPoint(P12, thWidth, point)) { return new NodePointRectangleEdge(this, NodePointRectangleEdge.ePoint.P12); } if (HitUtil.CircleHitPoint(P23, thWidth, point)) { return new NodePointRectangleEdge(this, NodePointRectangleEdge.ePoint.P23); } if (HitUtil.CircleHitPoint(P34, thWidth, point)) { return new NodePointRectangleEdge(this, NodePointRectangleEdge.ePoint.P34); } if (HitUtil.CircleHitPoint(P41, thWidth, point)) { return new NodePointRectangleEdge(this, NodePointRectangleEdge.ePoint.P41); } #endregion } return null; } public ISnapPoint SnapPoint(ICanvas canvas, UnitPoint point, List otherobj, Type[] runningsnaptypes, Type usersnaptype) { return null; } public void Move(UnitPoint offset) { P1 += offset; P2 += offset; P3 += offset; P4 += offset; } 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 virtual string GetInfoAsString() { return string.Format("{1:D3} {0}@Boundary:{2:F3}", this.Type, No + 1, ClientRect); } #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 } }