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 Spline : DrawObjectBase, IDrawObject, ISerialize { //토네이도 중심 protected UnitPoint m_center; [Browsable(false)] public UnitPoint Center { get { return m_center; } set { m_center = value; } } //Spline의 경우 PointList 1개 protected List m_p1 = new List(); [Browsable(false)] public List P1 { get { return m_p1; } set { m_p1 = value; } } //Tornado의 경우 PointList 2개 protected List m_p2 = new List(); [Browsable(false)] public List P2 { get { return m_p2; } set { m_p2 = value; } } protected double m_wholeLength = 10; [Browsable(true)] public double WholeLength { get { return m_wholeLength; } set { m_wholeLength = value; } } protected float m_startAngle = 0; protected float m_radius = 5; protected double m_innerRadius = 0.2; protected double m_increaseFactor = 1; public static string ObjectType { get { return "Spline"; } } protected bool m_splineDirection = false; protected bool m_splineTornado = true; protected DrawWayType m_drawWay = DrawWayType.OUT_OUT; public enum DrawWayType { OUT_OUT, IN_OUT, OUT_IN, IN_IN } public Spline() { } public Spline(UnitPoint center, float width, Color color) { Center = center; Width = width; Color = color; Selected = false; } public override void InitializeFromModel(UnitPoint center, DrawingLayer layer, ISnapPoint snap) { Center = center; Width = layer.Width; Color = layer.Color; Selected = true; } 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 virtual void Copy(Spline acopy) { base.Copy(acopy); P1 = acopy.P1; P2 = acopy.P2; Center = acopy.Center; m_startAngle = acopy.m_startAngle; m_radius = acopy.m_radius; m_innerRadius = acopy.m_innerRadius; m_increaseFactor = acopy.m_increaseFactor; m_splineDirection = acopy.m_splineDirection; m_splineTornado = acopy.m_splineTornado; Type = acopy.Type; m_no = acopy.m_no; m_drawWay = acopy.m_drawWay; //마킹객체에 대한 속성 복사 ScannerParamNo = acopy.ScannerParamNo; Enabled = acopy.Enabled; Selected = acopy.Selected; WeldingParameterID = acopy.WeldingParameterID; } public RectangleF GetBoundingRect(ICanvas canvas) { float thWidth = ThresholdWidth(canvas, m_radius); UnitPoint newPoint1 = new UnitPoint(m_center.X - thWidth / 2, m_center.Y - thWidth / 2); UnitPoint newPoint2 = new UnitPoint(m_center.X + thWidth / 2, m_center.Y + thWidth / 2); return ScreenUtils.GetRect(newPoint1, newPoint2, thWidth); } #region IDrawObject Members public virtual IDrawObject Clone() { Spline l = new Spline(); l.Copy(this); return l; } #region IObjectEditInstance public IDrawObject GetDrawObject() { return new Spline(Center, Width, Color); } #endregion public bool PointInObject(ICanvas canvas, UnitPoint point) { RectangleF boundingrect = GetBoundingRect(canvas); if (boundingrect.Contains(point.Point) == false) return false; float thWidth = Line.ThresholdWidth(canvas, Width, ThresholdPixel); if (HitUtil.PointInPoint(m_center, point, m_radius)) return true; return HitUtil.IsPointInCircle(m_center, m_radius, point, thWidth / 2); } public bool ObjectInRectangle(ICanvas canvas, RectangleF rect, bool anyPoint) { RectangleF boundingrect = GetBoundingRect(canvas); UnitPoint newPoint1 = new UnitPoint(boundingrect.X, boundingrect.Y); UnitPoint newPoint2 = new UnitPoint(boundingrect.X + boundingrect.Width, boundingrect.Y + boundingrect.Height); if (anyPoint) return HitUtil.LineIntersectWithRect(newPoint1, newPoint2, rect); return rect.Contains(boundingrect); } #region 마킹객체에 대한 속성 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; } } 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; } } [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; } } #endregion #region 드로잉 객체에 대한 속성 int m_no; [Browsable(false)] [XmlSerializable] public int No { get { return m_no; } set { m_no = value; } } string m_type; [Browsable(false)] [ReadOnly(true)] [Category("객체")] [DisplayName("종류")] [Description("드로잉 객체 종류")] [XmlSerializable] public string Type { get { m_type = Spline.ObjectType; return m_type; } set { m_type = value; } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Center", 1, 6)] [Description("Starting Point Of Drawing Object")] [TypeConverter(typeof(PointFConverter))] [XmlSerializable] public PointF PF1 { get { lock (this) { return Center.Point; } } set { lock (this) { Center = new UnitPoint(value); } } } [Browsable(false)] [ReadOnly(false)] [Category("GEOMETRY")] [DisplayName("2.End[X,Y](mm)")] [Description("Starting Point Of Drawing Object")] [TypeConverter(typeof(PointFConverter))] [XmlSerializable] public PointF PF2 { get { lock (this) { return Center.Point; } } set { lock (this) { Center = new UnitPoint(value); } } } [Browsable(false)] [ReadOnly(false)] [Category("GEOMETRY")] [DisplayName("3.중심점[X,Y](mm)")] [Description("드로잉 객체의 중심점")] [TypeConverter(typeof(PointFConverter))] public PointF MiddlePoint { get { return Center.Point; } set { Center = new UnitPoint(value); } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Spiral Parameter", 4, 6)] [CustomSortedDisplayName("Start Angle[˚]", 3, 6)] [Description("Spline Start Angle(˚)")] [XmlSerializable] public float Angle { get { return m_startAngle; } set { m_startAngle = value; CreateSplinePointList(); } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Radius[mm]", 2, 6)] [Description("Spline Outer Radius(mm)")] [XmlSerializable] public float Radius { get { return m_radius; } set { m_radius = value; CreateSplinePointList(); } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Inner Radius", 3, 6)] [Description("Spline Inner Radius(mm)")] [XmlSerializable] public double InnerRadius { get { return m_innerRadius; } set { m_innerRadius = value; CreateSplinePointList(); } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Reverse", 4, 6)] [Description("Spline Direction")] [XmlSerializable] public bool SplineDirection { get { return m_splineDirection; } set { m_splineDirection = value; CreateSplinePointList(); } } 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; } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Spiral Parameter", 4, 6)] [CustomSortedDisplayName("Increase Factor[mm]", 1, 6)] [Description("Spline Increase Factor(mm)")] [XmlSerializable] public double IncreaseFactor { get { return m_increaseFactor; } set { m_increaseFactor = value; CreateSplinePointList(); } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Spiral Parameter", 4, 6)] [CustomSortedDisplayName("Tornado Mode", 5, 6)] [Description("Tornado Mode (True : Use, False : No Use)")] [XmlSerializable] public bool SplineTornado { get { return m_splineTornado; } set { m_splineTornado = value; CreateSplinePointList(); } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Spiral Parameter", 4, 6)] [CustomSortedDisplayName("Draw Way", 4, 6)] [Description("Draw Way (OUT_OUT,IN_OUT, OUT_IN, IN_IN)")] [XmlSerializable] public DrawWayType DrawWay { get { return m_drawWay; } set { m_drawWay = value; } } 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", 5, 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", 5, 6)] [CustomSortedDisplayName("Align ID", 2, 2)] [Description("Align ID")] [XmlSerializable] public int AlignID { get { return m_alignID; } set { m_alignID = value; } } [Browsable(true)] [ReadOnly(true)] [CustomSortedCategory("Boundary", 1, 6)] [CustomSortedDisplayName("Left,Bottom,Right,Top", 1, 1)] [Description("Boundary of Object")] [TypeConverter(typeof(RectangleFConverter))] public RectangleF ClientRect { get; } public void Move(UnitPoint offset) { m_center.X += offset.X; m_center.Y += offset.Y; } public void Rotate(float angle, UnitPoint center) { Angle = Angle + angle; } public void MakeLength(float distance) { } #endregion public virtual void Draw(ICanvas canvas, RectangleF unitrect) { Color color = Color; color = WeldingParameterIDEditor.weldingColorList[(int)WeldingParameterID - 1]; Pen pen = canvas.CreatePen(color, Width); pen.EndCap = System.Drawing.Drawing2D.LineCap.Round; pen.StartCap = System.Drawing.Drawing2D.LineCap.Round; //PointList 생성 CreateSplinePointList(); if (Selected) { DrawSpline(canvas, DrawUtils.SelectedPen); } else { //Spline 그리기 DrawSpline(canvas, pen); } } private void CreateSplinePointList() { double distance = 0; int index = 0; m_p1.Clear(); m_p2.Clear(); while (true) { UnitPoint p1 = new UnitPoint(); UnitPoint p2 = new UnitPoint(); double radianAngle = (m_startAngle + index) * Math.PI / 180; p1.X = (m_innerRadius + index * m_increaseFactor / 360) * Math.Cos(radianAngle); p1.Y = (m_innerRadius + index * m_increaseFactor / 360) * Math.Sin(radianAngle); p2.X = (-1) * p1.X; p2.Y = (-1) * p1.Y; //Reverse 인 경우 대칭 if (m_splineDirection == true) { radianAngle = radianAngle * (-1); p1.X = p1.X * (-1); //p1.Y = p1.Y * (-1); p2.X = p2.X * (-1); //p2.Y = p2.Y * (-1); } distance = Math.Sqrt(Math.Pow(p1.X, 2) + Math.Pow(p1.Y, 2)); if (distance < m_radius) { m_p1.Add(new UnitPoint(p1.X + Center.X, p1.Y + Center.Y)); m_p2.Add(new UnitPoint(p2.X + Center.X, p2.Y + Center.Y)); index++; } else { break; } } m_wholeLength = 0; for (int i = 0; i < m_p1.Count - 1; i++) { m_wholeLength += HitUtil.Distance(m_p1[i], m_p1[i + 1]); } for (int i = 0; i < m_p2.Count - 1; i++) { m_wholeLength += HitUtil.Distance(m_p2[i], m_p2[i + 1]); } } private void DrawSpline(ICanvas canvas, Pen pen) { //일반 Spline 은 P1만 그림 for (int i = 0; i < m_p1.Count - 1; i++) { canvas.DrawLine(canvas, pen, m_p1[i], m_p1[i + 1]); } // Tornado의 경우 P2까지 그려줌 if (m_splineTornado) { for (int i = 0; i < m_p1.Count - 1; i++) { canvas.DrawLine(canvas, pen, m_p2[i], m_p2[i + 1]); } } } public virtual void OnMouseMove(ICanvas canvas, UnitPoint point) { } public virtual eDrawObjectMouseDown OnMouseDown(ICanvas canvas, UnitPoint point, ISnapPoint snappoint) { Selected = false; m_center = point; return eDrawObjectMouseDown.Done; } public void OnMouseUp(ICanvas canvas, UnitPoint point, ISnapPoint snappoint) { } public virtual void OnKeyDown(ICanvas canvas, KeyEventArgs e) { } [Browsable(false)] public UnitPoint RepeatStartingPoint { get { return m_center; } } public INodePoint NodePoint(ICanvas canvas, UnitPoint point) { return null; } public ISnapPoint SnapPoint(ICanvas canvas, UnitPoint point, List otherobjs, Type[] runningsnaptypes, Type usersnaptype) { return null; } public virtual string GetInfoAsString() { return string.Format("{1:D3} {0}@{2} - Type={3},", this.Type, No + 1, Center.PosAsString(), m_startAngle.ToString()); } #endregion #region ISerialize public void GetObjectData(XmlWriter wr) { wr.WriteStartElement("Spline"); 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; } public void AfterSerializedIn() { } #endregion } }