using CoreUnit.Common; using GUI.Properties; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Text.Json; using System.Text.Json.Serialization; using System.Windows.Forms; using System.Xml; namespace CoreUnit.Control.UserControl.Canvas { class NodePointGroupCenter : INodePoint { Group m_owner; Group 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 NodePointGroupCenter(Group owner) { m_owner = owner; m_clone = m_owner.Clone() as Group; 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.SubObjects = m_clone.SubObjects; m_owner.Selected = true; m_clone = null; } public void Cancel() { m_owner.Selected = true; } public void Undo() { m_owner.Center = m_originalPoint; } public void Redo() { m_owner.Center = m_endPoint; } 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 NodePointGroupAngle : INodePoint { protected Group m_owner; protected Group m_clone; protected float m_originalAngle; protected float m_endAngle; public NodePointGroupAngle(Group owner) { m_owner = owner; m_clone = m_owner.Clone() as Group; 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.SubObjects = m_clone.SubObjects; 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 Group : DrawObjectBase, IDrawObject, ISerialize { 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 AnglePoint { get { return HitUtil.RotatePoint(Angle, new UnitPoint(Center.X, Center.Y + AnglePointLength(P1, P3)), Center); } } public static string ObjectType { get { return "Group"; } } List m_subObjects = new List(); [Browsable(false)] public List SubObjects { get { lock (this) { return m_subObjects; } } set { lock (this) { m_subObjects = value; } } } [Browsable(false)] public UnitPoint Center { get { return new UnitPoint(MiddlePoint.X, MiddlePoint.Y); } set { MiddlePoint = value.Point; } } public Group() { } 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) { Width = layer.Width; Color = layer.Color; Selected = true; } public void Copy(Group acopy) { base.Copy(acopy); P1 = acopy.P1; P2 = acopy.P2; P3 = acopy.P3; P4 = acopy.P4; Angle = acopy.Angle; m_no = acopy.m_no; Type = acopy.Type; Selected = acopy.Selected; //마킹객체에 대한 속성 복사 Enabled = acopy.Enabled; MarkingCount = acopy.MarkingCount; foreach (IDrawObject obj in acopy.SubObjects) { SubObjects.Add(obj.Clone()); } } #region IDrawObject Members #region 1.마킹객체에 대한 속성 bool m_enabled = true; [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Enable Mark", 6, 6)] [Description("Enable Mark")] [XmlSerializable] public bool Enabled { get { return m_enabled; } set { m_enabled = value; } } bool m_lock = false; [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Lock", 5, 6)] [Description("Lock")] [XmlSerializable] public bool Lock { get { return m_lock; } set { m_lock = value; } } uint m_markingCount = 1; [Browsable(false)] [ReadOnly(false)] [Category("용접 파라미터")] [DisplayName("용접 횟수")] [Description("용접 작업 반복 횟수")] [XmlSerializable] public uint MarkingCount { get { return m_markingCount; } set { m_markingCount = value; } } //Group 은 사용 안함 /* [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Pen", 2, 6)] [CustomSortedDisplayName("Parameter", 1, 1)] [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; ChangeParam(ScannerParamID); } }*/ public enum eAlignType { XY_ANGLE, XY_OFFSET, X_OFFSET, Y_OFFSET, ABSOLUTE_XY } eAlignType m_alignType = eAlignType.ABSOLUTE_XY; [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Vision Align", 4, 6)] [CustomSortedDisplayName("Align Type", 1, 2)] [Description("Align Type")] [XmlSerializable] public eAlignType AlignType { get { return m_alignType; } set { m_alignType = value; } } int m_alignID = -1; [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Vision Align", 4, 6)] [CustomSortedDisplayName("Align ID", 2, 2)] [Description("Align ID")] [XmlSerializable] public int AlignID { get { return m_alignID; } set { m_alignID = value; } } /* ScannerParams m_selectedScanParam = null; [Browsable(true)] [ReadOnly(false)] [Category("용접 파라미터")] [DisplayName("용접 조건 변수")] [Description("용접 조건 변수(스캔속도 및 레이저 파워 값등..) 설정")] [Editor(typeof(ScannerParamEditor), typeof(UITypeEditor))] [TypeConverterAttribute(typeof(ScannerParamConverter))] public ScannerParams ScannerParam { get { return m_selectedScanParam; } set { m_selectedScanParam = value; Color = m_selectedScanParam.Color; } } * */ /* [Browsable(false)] [XmlSerializable] public string ScannerParamID { get { if (ScannerParam != null) { return ScannerParam.ID; } else { return string.Empty; } } set { for (int i = 0; i < DataModel.ScannerParamList.Count; i++) { ScannerParams param = DataModel.ScannerParamList[i]; if (param.ID == value) { ScannerParam = param; } } } } */ #endregion #region 2.드로잉 객체에 대한 속성 int m_no; [Browsable(false)] [ReadOnly(true)] [Category("객체")] [DisplayName("ID")] [Description("드로잉 객체 번호")] [XmlSerializable] public int No { get { return m_no; } set { m_no = value; } } string m_type; [Browsable(false)] [ReadOnly(true)] [Category("객체")] [DisplayName("종류")] [Description("드로잉 객체 종류")] [XmlSerializable] public virtual string Type { get { m_type = Group.ObjectType; return m_type; } set { m_type = value; } } [Browsable(false)] [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(false)] [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(false)] [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(false)] [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)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("중심점[X,Y](mm)", 1, 6)] [Description("중심점")] [TypeConverter(typeof(PointFConverter))] [JsonIgnore] 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)); } } float m_widthLength = 10; [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Width(mm)", 2, 6)] [Description("가로")] [JsonIgnore] public float ObjectWidth { get { return (float)Math.Round(P4.X - P1.X, 3); } set { m_widthLength = value; } } float m_heightLength = 10; [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Height(mm)", 3, 6)] [Description("세로")] [JsonIgnore] public float ObjectHeight { get { return (float)Math.Round(P4.Y - P1.Y, 3); } set { m_heightLength = value; } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("RotateAngle(˚)", 4, 6)] [Description("드로잉 객체의 각도")] [JsonIgnore] public float Angle { get { return (float)Math.Round(HitUtil.RadiansToDegrees(HitUtil.LineAngleR(P1, P4, 0)), 3); ; } set { float angle = value - Angle; Rotate(angle, Center); } } // 250403 Arc와 같은 경우, 초기 client와 유사성이 없으므로 새로 추가해주었음. UnitPoint clientP1, clientP2, clientP3, clientP4; [Browsable(true)] [ReadOnly(true)] [CustomSortedCategory("Boundary", 1, 6)] [CustomSortedDisplayName("Left,Bottom,Right,Top", 1, 1)] [Description("Boundary of Object")] [TypeConverter(typeof(RectangleFConverter))] [JsonIgnore] public RectangleF ClientRect { get { List points = new List { clientP1, clientP2, clientP3, clientP4 }; return ScreenUtils.GetRect(points, 0); } } /* List m_groupClass = new List();//그룹의 계층에 대한 속성을 가짐. [Browsable(false)] public List GroupClass { get { return m_groupClass; } set { m_groupClass = value; } } * */ int m_scannerParamNo = 0; [Browsable(false)] [ReadOnly(false)] [Category("용접 파라미터")] [DisplayName("용접 조건 번호")] [Description("용접 조건(스캔속도 및 레이저 파워 값등..) 번호 설정")] [XmlSerializable] public int ScannerParamNo { get { return m_scannerParamNo; } set { m_scannerParamNo = value; } } [Browsable(false)] [ReadOnly(false)] [Category("용접 파라미터")] [DisplayName("용접 조건 ID")] [Description("용접 조건(스캔속도 및 레이저 파워 값등..) ID 설정")] [XmlSerializable] public int ScannerParamID { get { return m_scannerParamNo + 1; } set { m_scannerParamNo = value - 1; } } #endregion public IDrawObject Clone() { Group a = new Group(); 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) { Pen pen; //1.Group의 subject에 대한 draw 함수 foreach (IDrawObject obj in SubObjects) { obj.Draw(canvas, unitrect); } //2. Group객체의 가장자리 bound draw 함수 if (Highlighted || Selected) { //3.Group 객체에 대한 중심 위치 점 draw 함수 pen = canvas.CreatePen(Color, Width); DrawUtils.DrawTriangleNode(canvas, new UnitPoint(MiddlePoint.X, MiddlePoint.Y)); pen = DrawUtils.SelectedPen; canvas.DrawArc(canvas, pen, new UnitPoint(MiddlePoint.X, MiddlePoint.Y), Settings.Default.GroupCenterCircleRadius, 0, 360); canvas.DrawLines(canvas, pen, new List() { P1, P2, P3, P4 }); DrawUtils.DrawNode(canvas, P1); DrawUtils.DrawNode(canvas, P2); DrawUtils.DrawNode(canvas, P3); DrawUtils.DrawNode(canvas, P4); //3.Group 객체에 회전점 draw 함수 canvas.DrawArc(canvas, pen, AnglePoint, Settings.Default.GroupCenterCircleRadius, 0, 360); //4.Group의 중심점과 회전점사이의 직선 canvas.DrawLine(canvas, pen, Center, AnglePoint); } } 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) { } public eDrawObjectMouseDown OnMouseDown(ICanvas canvas, UnitPoint point, ISnapPoint snappoint) { Selected = false; foreach (IDrawObject obj in SubObjects) { obj.Selected = Selected; obj.OnMouseDown(canvas, point, snappoint); } return eDrawObjectMouseDown.Done; } public void OnMouseUp(ICanvas canvas, UnitPoint point, ISnapPoint snappoint) { foreach (IDrawObject obj in SubObjects) { obj.OnMouseUp(canvas, point, snappoint); } } public void OnKeyDown(ICanvas canvas, KeyEventArgs e) { foreach (IDrawObject obj in SubObjects) { obj.OnKeyDown(canvas, e); } } [Browsable(false)] public UnitPoint RepeatStartingPoint { get { return UnitPoint.Empty; } } public INodePoint NodePoint(ICanvas canvas, UnitPoint point) { float thWidth = ThresholdWidth(canvas, Width); if (HitUtil.CircleHitPoint(Center, thWidth, point)) { return new NodePointGroupCenter(this); } if (HitUtil.CircleHitPoint(AnglePoint, thWidth, point)) { return new NodePointGroupAngle(this); } return null; } public ISnapPoint SnapPoint(ICanvas canvas, UnitPoint point, List otherobj, Type[] runningsnaptypes, Type usersnaptype) { return null; } public void ChangeParam(int Param) { foreach (IDrawObject obj in SubObjects) { obj.ScannerParamID = Param; } } public void Move(UnitPoint offset) { foreach (IDrawObject obj in SubObjects) { obj.Move(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) { foreach (IDrawObject obj in SubObjects) { obj.Rotate(angle, center); } CalculateClientRect(SubObjects); 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); foreach (IDrawObject subObj in SubObjects) { GetGroupObjectData(subObj, wr); } wr.WriteEndElement(); } public virtual string GetObjectData() { string jsonString = string.Empty; try { //jsonString += JsonSerializer.Serialize(this, options); foreach (IDrawObject subObj in SubObjects) { jsonString += GetGroupObjectData(subObj); } } catch { } return jsonString; } private string GetGroupObjectData(IDrawObject obj) { string jsonString = string.Empty; try { var options = new JsonSerializerOptions { WriteIndented = true, NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals, IgnoreReadOnlyFields = false, IgnoreReadOnlyProperties = false }; jsonString += JsonSerializer.Serialize(obj, options); if (obj is Group group) { //jsonString += JsonSerializer.Serialize(this, options); foreach (IDrawObject subObj in group.SubObjects) { jsonString += GetGroupObjectData(subObj); } } } catch { } return jsonString; } private void GetGroupObjectData(IDrawObject obj, XmlWriter wr) { wr.WriteStartElement(obj.Type); Common.XmlUtil.WriteProperties(obj, wr); if (obj is Group) { foreach (IDrawObject subObj in ((Group)obj).SubObjects) { GetGroupObjectData(subObj, wr); } } wr.WriteEndElement(); } public void AfterSerializedIn() { } #endregion public void CalculateClientRect(List objects) { List ptList = new List(); foreach (IDrawObject obj in objects) { if (obj is Line) { ptList.Add(((Line)obj).P1); ptList.Add(((Line)obj).P2); } else if (obj is Dot) { ptList.Add(((Dot)obj).P1); } else if (obj is Spline) { ptList.Add(((Spline)obj).Center); } else if (obj is SnowMan) { ptList.Add(((SnowMan)obj).P1); ptList.Add(((SnowMan)obj).P2); } else if (obj is Group) { ptList.Add(((Group)obj).P1); ptList.Add(((Group)obj).P2); ptList.Add(((Group)obj).P3); ptList.Add(((Group)obj).P4); } else if (obj is Arc3Point) { RectangleF tempRect = ((Arc3Point)obj).ClientRect; ptList.Add(new UnitPoint(tempRect.Left, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Left, tempRect.Top)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Top)); } else if (obj is Arc) { RectangleF tempRect = ((Arc)obj).ClientRect; ptList.Add(new UnitPoint(tempRect.Left, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Left, tempRect.Top)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Top)); } else if (obj is ZigZag) { ptList.Add(((ZigZag)obj).P1); ptList.Add(((ZigZag)obj).P2); } else if (obj is EllipseTool) { RectangleF tempRect = ((EllipseTool)obj).ClientRect; ptList.Add(new UnitPoint(tempRect.Left, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Left, tempRect.Top)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Top)); } else if (obj is RectangleTool) { RectangleF tempRect = ((RectangleTool)obj).ClientRect; ptList.Add(new UnitPoint(tempRect.Left, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Left, tempRect.Top)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Top)); } } RectangleF rect = ScreenUtils.GetRect(ptList, 0); clientP1 = new UnitPoint(rect.Left, rect.Bottom); clientP2 = new UnitPoint(rect.Left, rect.Top); clientP3 = new UnitPoint(rect.Right, rect.Top); clientP4 = new UnitPoint(rect.Right, rect.Bottom); } public void IncludeObjects(List objects) { SubObjects.Clear(); for (int i = 0; i < objects.Count; i++) { IDrawObject subObj = objects[i]; subObj.No = i; subObj.Selected = false; SubObjects.Add(subObj); } CalculateClientRect(SubObjects); Angle = 0; P1 = clientP1; P2 = clientP2; P3 = clientP3; P4 = clientP4; } private double AnglePointLength(UnitPoint p1, UnitPoint p2) { return HitUtil.Distance(p1, p2) * 0.65; } } }