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 { class NodePointArc3PointPoint : INodePoint { protected Arc3Point m_owner; protected Arc3Point m_clone; protected UnitPoint[] m_originalPoints = new UnitPoint[3]; protected UnitPoint[] m_endPoints = new UnitPoint[3]; protected Arc3Point.eCurrentPoint m_curPoint; public NodePointArc3PointPoint(Arc3Point owner, Arc3Point.eCurrentPoint curpoint) { m_owner = owner; m_clone = m_owner.Clone() as Arc3Point; m_owner.Selected = false; m_clone.Selected = true; m_originalPoints[0] = m_owner.P1; m_originalPoints[1] = m_owner.P2; m_originalPoints[2] = m_owner.P3; m_curPoint = curpoint; } #region INodePoint Members public IDrawObject GetClone() { return m_clone; } public IDrawObject GetOriginal() { return m_owner; } public virtual void SetPosition(UnitPoint pos) { SetPoint(m_clone, pos); } /* UnitPoint GetPoint() { if (m_curPoint == Arc3Point.eCurrentPoint.p1) return m_clone.P1; if (m_curPoint == Arc3Point.eCurrentPoint.p2) return m_clone.P2; if (m_curPoint == Arc3Point.eCurrentPoint.p3) return m_clone.P3; if (m_curPoint == Arc3Point.eCurrentPoint.startangle) return m_clone.P1; if (m_curPoint == Arc3Point.eCurrentPoint.endangle) return m_clone.P3; if (m_curPoint == Arc3Point.eCurrentPoint.radius) return m_clone.P2; return UnitPoint.Empty; } * */ void SetPoint(Arc3Point arc, UnitPoint pos) { if (m_curPoint == Arc3Point.eCurrentPoint.p1) arc.P1 = pos; if (m_curPoint == Arc3Point.eCurrentPoint.p2) arc.P2 = pos; if (m_curPoint == Arc3Point.eCurrentPoint.p3) arc.P3 = pos; double angleToRound = 0; if (System.Windows.Forms.Control.ModifierKeys == Keys.Control) angleToRound = HitUtil.DegressToRadians(45); double angleR = HitUtil.LineAngleR(arc.Center, pos, angleToRound); if (m_curPoint == Arc3Point.eCurrentPoint.startangle) arc.P1 = HitUtil.PointOncircle(arc.Center, arc.Radius, angleR); if (m_curPoint == Arc3Point.eCurrentPoint.endangle) arc.P3 = HitUtil.PointOncircle(arc.Center, arc.Radius, angleR); if (m_curPoint == Arc3Point.eCurrentPoint.radius) { double radius = HitUtil.Distance(arc.Center, pos); arc.P1 = HitUtil.PointOncircle(arc.Center, radius, HitUtil.DegressToRadians(arc.StartAngle)); arc.P2 = pos; arc.P3 = HitUtil.PointOncircle(arc.Center, radius, HitUtil.DegressToRadians(arc.EndAngle)); } arc.UpdateArcFrom3Points(); if ((m_curPoint == Arc3Point.eCurrentPoint.startangle) || (m_curPoint == Arc3Point.eCurrentPoint.endangle)) arc.UpdateCenterNodeFromAngles(); } public virtual void Finish() { m_endPoints[0] = m_clone.P1; m_endPoints[1] = m_clone.P2; m_endPoints[2] = m_clone.P3; m_owner.Copy(m_clone); m_owner.Selected = true; m_clone = null; } public void Cancel() { m_owner.Selected = true; } public virtual void Undo() { m_owner.P1 = m_originalPoints[0]; m_owner.P2 = m_originalPoints[1]; m_owner.P3 = m_originalPoints[2]; m_owner.UpdateArcFrom3Points(); } public virtual void Redo() { m_owner.P1 = m_endPoints[0]; m_owner.P2 = m_endPoints[1]; m_owner.P3 = m_endPoints[2]; m_owner.UpdateArcFrom3Points(); } public void OnKeyDown(ICanvas canvas, KeyEventArgs e) { } #endregion } public class Arc3Point : DrawObjectBase, IArc, IDrawObject, ISerialize { public enum eArcType { kArc3P132, kArc3P123, } eArcType m_type = eArcType.kArc3P132; public enum eDirection { CW, CCW, } UnitPoint m_p1 = UnitPoint.Empty; UnitPoint m_p2 = UnitPoint.Empty; UnitPoint m_p3 = UnitPoint.Empty; [Browsable(false)] public UnitPoint P1 { get { return m_p1; } set { m_p1 = value; } } [Browsable(false)] public UnitPoint P2 { get { return m_p2; } set { m_p2 = value; } } [Browsable(false)] public UnitPoint P3 { get { return m_p3; } set { m_p3 = value; } } UnitPoint m_center; float m_radius; float m_startAngle = 0; float m_endAngle = 0; [Browsable(false)] public UnitPoint Center { get { return m_center; } set { UnitPoint origin = m_center; m_center = value; m_p1 = m_p1 + value - origin; m_p2 = m_p2 + value - origin; m_p3 = m_p3 + value - origin; } } public Arc3Point() { } public Arc3Point(eArcType type) { m_type = type; m_curPoint = eCurrentPoint.p1; } public override void InitializeFromModel(UnitPoint point, DrawingLayer layer, ISnapPoint snap) { P1 = P3 = point; Width = layer.Width; Color = layer.Color; Selected = true; OnMouseDown(null, point, snap); } public void Copy(Arc3Point acopy) { base.Copy(acopy); m_p1 = acopy.m_p1; m_p2 = acopy.m_p2; m_p3 = acopy.m_p3; m_center = acopy.m_center; m_radius = acopy.m_radius; m_startAngle = acopy.m_startAngle; m_endAngle = acopy.m_endAngle; m_direction = acopy.m_direction; m_curPoint = acopy.m_curPoint; m_RCCArc = acopy.m_RCCArc; } double GetSweep(double start, double end, eDirection direction) { double sweep = 360; if (start == end) return sweep; if (direction == eDirection.CCW) { if (end >= start) sweep = end - start; else sweep = 360 - (start - end); } if (direction == eDirection.CW) { if (end >= start) sweep = -(360 - (end - start)); else sweep = -(start - end); } return sweep; } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Sweep Angle[deg]", 4, 7)] [Description("unit : degree")] public float SweepAngle { get { return (float)GetSweep(StartAngle, EndAngle, Direction); } set { float sweep = value; bool isPositive = sweep >= 0 ? true : false; if (isPositive && Direction == eDirection.CCW) { if (sweep <= 2160) EndAngle = StartAngle + sweep; else EndAngle = StartAngle + 2160; } if (!isPositive && Direction == eDirection.CW) { if (-2160 <= sweep) EndAngle = StartAngle + sweep; else EndAngle = StartAngle - 2160; } } } #region IDrawObject Members #region 마킹객체에 대한 속성 [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 { //lock (this) { return ScreenUtils.GetRect(Center, Radius, 0); } List RectanglePoint = new List(); RectanglePoint.Add(P1); if (m_type == eArcType.kArc3P132) RectanglePoint.Add(P3); else RectanglePoint.Add(P2); int[] dx = new int[] { 0, -1, 0, 1 }; int[] dy = new int[] { 1, 0, -1, 0 }; int startQuad = (int)StartAngle / 90; int endQuad = (int)EndAngle / 90; int standardQuad = 0; int iter = 0; if (Direction == eDirection.CW) { if (endQuad < 0) standardQuad = endQuad + 4 * ((int)(endQuad / 4) + 1) - 1; else standardQuad = endQuad; iter = -endQuad + startQuad; } else if (Direction == eDirection.CCW) { if (startQuad < 0) standardQuad = startQuad + 4 * ((int)(startQuad / 4) + 1) - 1; else standardQuad = startQuad; iter = endQuad - startQuad; } //else; if (startQuad != endQuad) { if (iter < 0) iter = iter + 4; for (int i = 0; i < iter; i++) { int index = (standardQuad + i) % 4; if (index < 0) index += 4; // 음수 값을 양수로 변환 float xAxis = (float)(Center.X) + Radius * dx[index]; float yAxis = (float)(Center.Y) + Radius * dy[index]; RectanglePoint.Add(new UnitPoint(xAxis, yAxis)); } } return ScreenUtils.GetRect(RectanglePoint, 0); //else lock (this) { return ScreenUtils.GetRect(Center, Radius, 0); } } } bool m_enabled = true; [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] // 용접 파라미터 [CustomSortedDisplayName("Enable Mark", 7, 7)] // 용접 작업 유무 [Description("Enable Mark")] // 용접 작업 진행 여부 public bool Enabled { get { return m_enabled; } set { m_enabled = value; } } int m_scannerParamNo = 0; [Browsable(false)] [ReadOnly(false)] [Category("용접 파라미터")] [DisplayName("용접 조건 번호")] [Description("용접 조건(스캔속도 및 레이저 파워 값등..) 번호 설정")] public int ScannerParamNo { get { return m_scannerParamNo; } set { m_scannerParamNo = value; } } [Browsable(false)] [ReadOnly(false)] [Category("용접 파라미터")] [DisplayName("용접 조건 ID")] [Description("용접 조건(스캔속도 및 레이저 파워 값등..) ID 설정")] public int ScannerParamID { get { return m_scannerParamNo + 1; } set { m_scannerParamNo = value - 1; } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Pen", 2, 6)] [CustomSortedDisplayName("Parameter ID", 2, 2)] [Description("Welding Paramter ID")] [Editor(typeof(WeldingParameterIDEditor.WeldingParamterNoUITypeEditor), typeof(System.Drawing.Design.UITypeEditor))] public WeldingParameterIDEditor.eWeldingParamterID WeldingParameterID { get { return (WeldingParameterIDEditor.eWeldingParamterID)ScannerParamID; } set { ScannerParamID = (int)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")] 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")] public int AlignID { get { return m_alignID; } set { m_alignID = value; } } #endregion #region 드로잉 객체에 대한 속성 int m_no; [Browsable(false)] public int No { get { return m_no; } set { m_no = value; } } string m_objectType; [Browsable(false)] [ReadOnly(true)] [Category("객체")] [DisplayName("종류")] [Description("드로잉 객체 종류")] public string Type { get { m_objectType = Arc3Point.ObjectType; return m_objectType; } set { m_objectType = value; } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Center[X,Y](mm)", 1, 7)] [Description("Center Of Drawing Object")] [TypeConverter(typeof(PointFConverter))] public PointF CenterPointF { get { lock (this) { return Center.Point; } } set { lock (this) { Center = new UnitPoint(value); } } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Radius", 2, 7)] [Description("Radius Of Arc")] public float Radius { get { return m_radius; } set { m_radius = value; P1 = HitUtil.PointOncircle(m_center, m_radius, HitUtil.DegressToRadians(m_startAngle)); P3 = HitUtil.PointOncircle(m_center, m_radius, HitUtil.DegressToRadians(m_endAngle)); } } [Browsable(false)] public PointF MiddlePoint { get { return m_center.Point; } set { m_center = new UnitPoint(value); } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Start Angle", 3, 7)] [Description("Start Angle")] public float StartAngle { get { return m_startAngle; } set { m_startAngle = value; P1 = HitUtil.PointOncircle(m_center, m_radius, HitUtil.DegressToRadians(value)); } } [Browsable(false)] [ReadOnly(false)] [Category("Geometry")] [DisplayName("End Angle")] [Description("End Angle")] public float EndAngle { get { return m_endAngle; } set { m_endAngle = value; P3 = HitUtil.PointOncircle(m_center, m_radius, HitUtil.DegressToRadians(value)); } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Start Point [X,Y](mm)", 1, 3)] [Description("Start Point")] [TypeConverter(typeof(PointFConverter))] public PointF PF1 { get { return P1.Point; } set { P1 = new UnitPoint(value); UpdateArcFrom3Points(); } } [Browsable(false)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("End Point [X,Y](mm)", 1, 3)] [Description("End Point")] [TypeConverter(typeof(PointFConverter))] public PointF PF2 { get { return P3.Point; } set { P3 = new UnitPoint(value); UpdateArcFrom3Points(); } } eDirection m_direction = eDirection.CCW; [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Direction", 5, 7)] [Description("unit : CW(ClockWise) / CCW(CounterClockWise)")] public eDirection Direction { get { return m_direction; } set { m_direction = value; } } bool m_reverse = false; [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Reverse", 5, 7)] [Description("Reverse")] public bool Reverse { get { return m_reverse; } set { m_reverse = value; } } bool m_lock = false; [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Lock", 6, 7)] [Description("Lock")] public bool Lock { get { return m_lock; } set { m_lock = value; } } bool m_RCCArc = false; [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("RCC Mode", 7, 7)] [Description("RCC Arc Mode")] public bool RCCArc { get { return m_RCCArc; } set { m_RCCArc = value; } } bool m_MadebyRCC = false; [Browsable(false)] [ReadOnly(false)] public bool MadebyRCC { // RCC 로 생성된 object 만 true 로 바꿔준다. 코드내에서만 사용함. // Ramping 에 대한 예외처리에 필요하다. get { return m_MadebyRCC; } set { m_MadebyRCC = value; } } float m_RCC_PowerRatio = 1; [Browsable(false)] [ReadOnly(false)] public float RCC_PowerRatio { // RCC 로 생성된 object 만 true 로 바꿔준다. 코드내에서만 사용함. // Ramping 에 대한 예외처리에 필요하다. get { return m_RCC_PowerRatio; } set { m_RCC_PowerRatio = value; } } [Browsable(false)] public static string ObjectType { get { return "Arc3p"; } } #endregion //PointF m_PF1; //PointF m_PF2; float m_angle; [Browsable(false)] public float Angle { get { return StartAngle - EndAngle; } set { m_angle = (float)value; } } public virtual IDrawObject Clone() { Arc3Point a = new Arc3Point(m_type); a.Copy(this); return a; } public RectangleF GetBoundingRect(ICanvas canvas) { float thWidth = Line.ThresholdWidth(canvas, Width, ThresholdPixel); if (thWidth < Width) thWidth = Width; RectangleF rect = RectangleF.Empty; // if one of the points is empty, then a straight line is drawn, so return bounding rect for a line if (m_p2.IsEmpty || m_p3.IsEmpty) rect = ScreenUtils.GetRect(m_p1, m_lastPoint, thWidth); if (rect.IsEmpty) { float r = m_radius + thWidth / 2; rect = HitUtil.CircleBoundingRect(m_center, r); if (Selected) { float w = (float)canvas.ToUnit(20); // include space for the 'extern' nodes rect.Inflate(w, w); } } // if drawing either angle then include the mouse point in the rectangle - this is to redraw (erase) the line drawn // from center point to mouse point //if (m_curPoint == eCurrentPoint.startAngle || m_curPoint == eCurrentPoint.endAngle) if (m_lastPoint.IsEmpty == false) rect = RectangleF.Union(rect, new RectangleF(m_lastPoint.Point, new SizeF(0, 0))); return rect; } void DrawArc(ICanvas canvas, RectangleF unitrect) { Color color = WeldingParameterIDEditor.weldingColorList[(int)WeldingParameterID - 1]; Pen pen = canvas.CreatePen(color, Width); bool inline = PointsInLine(); double sweep = GetSweep(StartAngle, EndAngle, Direction); if (inline == false) { canvas.DrawArc(canvas, pen, m_center, m_radius, StartAngle, (float)sweep); if (m_direction == eDirection.CCW) { DrawUtils.DrawArrowNode(canvas, P3, EndAngle + 90, pen); } else { DrawUtils.DrawArrowNode(canvas, P3, EndAngle - 90, pen); } } else { canvas.DrawLine(canvas, pen, P1, P2); canvas.DrawLine(canvas, pen, P1, P3); } if (Selected) { if (inline == false) { canvas.DrawArc(canvas, DrawUtils.SelectedPen, m_center, m_radius, StartAngle, (float)sweep); } else { canvas.DrawLine(canvas, DrawUtils.SelectedPen, P1, P2); canvas.DrawLine(canvas, DrawUtils.SelectedPen, P1, P3); } if (m_p1.IsEmpty == false) { DrawUtils.DrawNode(canvas, P1); UnitPoint anglepoint = StartAngleNodePoint(canvas); if (!anglepoint.IsEmpty) DrawUtils.DrawTriangleNode(canvas, anglepoint); anglepoint = EndAngleNodePoint(canvas); if (!anglepoint.IsEmpty) DrawUtils.DrawTriangleNode(canvas, anglepoint); anglepoint = RadiusNodePoint(canvas); if (!anglepoint.IsEmpty) DrawUtils.DrawTriangleNode(canvas, anglepoint); } if (m_p2.IsEmpty == false) DrawUtils.DrawNode(canvas, P2); if (m_p3.IsEmpty == false) DrawUtils.DrawNode(canvas, P3); } } bool PointsInLine() { double slope1 = HitUtil.LineSlope(P1, P2); double slope2 = HitUtil.LineSlope(P1, P3); return slope1 == slope2; } void Draw3P132(ICanvas canvas, RectangleF unitrect) { Color color = WeldingParameterIDEditor.weldingColorList[(int)WeldingParameterID - 1]; if (m_curPoint == eCurrentPoint.p3) { Pen pen = canvas.CreatePen(color, Width); canvas.DrawLine(canvas, pen, m_p1, m_p3); } if (m_curPoint == eCurrentPoint.p2 || m_curPoint == eCurrentPoint.done) { DrawArc(canvas, unitrect); } } void Draw3P123(ICanvas canvas, RectangleF unitrect) { Color color = WeldingParameterIDEditor.weldingColorList[(int)WeldingParameterID - 1]; if (m_curPoint == eCurrentPoint.p2) { Pen pen = canvas.CreatePen(color, Width); canvas.DrawLine(canvas, pen, m_p1, m_p2); } if (m_curPoint == eCurrentPoint.p3 || m_curPoint == eCurrentPoint.done) { DrawArc(canvas, unitrect); } } public virtual void Draw(ICanvas canvas, RectangleF unitrect) { if (m_type == eArcType.kArc3P132) Draw3P132(canvas, unitrect); if (m_type == eArcType.kArc3P123) Draw3P123(canvas, unitrect); } public void UpdateCenterNodeFromAngles() { float angle = StartAngle + SweepAngle / 2; P2 = HitUtil.PointOncircle(m_center, m_radius, HitUtil.DegressToRadians(angle)); } public void UpdateArcFrom3Points() { m_center = HitUtil.CenterPointFrom3Points(m_p1, m_p2, m_p3); m_radius = (float)HitUtil.Distance(m_center, m_p1); m_startAngle = (float)HitUtil.RadiansToDegrees(HitUtil.LineAngleR(m_center, m_p1, 0)); m_endAngle = (float)HitUtil.RadiansToDegrees(HitUtil.LineAngleR(m_center, m_p3, 0)); // find angle from P1 on line P1|P3 to P2. If this angle is 0-180 the direction is CCW else it is CW double includeAngle = (float)HitUtil.RadiansToDegrees(HitUtil.LineAngleR(m_center, m_p2, 0)); // double p1p3angle = HitUtil.RadiansToDegrees(HitUtil.LineAngleR(m_p1, m_p3, 0)); //double p1p2angle = HitUtil.RadiansToDegrees(HitUtil.LineAngleR(m_p1, m_p2, 0)); //double diff = p1p3angle - p1p2angle; // I know there is a problem with this logic, in some cases the arc does not follow the mouse, // but it will work for now. /* if (m_startAngle > includeAngle) { if ((m_endAngle - m_startAngle) * (m_endAngle - includeAngle) > 0) { m_direction = eDirection.CW; } else { m_direction = eDirection.CCW; } } else { if ((m_endAngle - m_startAngle) * (m_endAngle - includeAngle) > 0) { m_direction = eDirection.CCW; } else { m_direction = eDirection.CW; } }*/ // Direction = eDirection.kCCW; //if (diff < 0 || diff > 180) // Direction = eDirection.kCW; //if (p1p3angle == 0) //{ // if (diff < -180) // Direction = eDirection.kCCW; // else // Direction = eDirection.kCW; //} //if (p1p3angle == 90) //{ // if (diff < -180) // Direction = eDirection.kCCW; //} } void MoveMouse3P132(ICanvas canvas, UnitPoint point) { if (m_curPoint == eCurrentPoint.p1) { P2 = point; return; } if (m_curPoint == eCurrentPoint.p3) { m_p3 = point; return; } if (m_curPoint == eCurrentPoint.p2) { m_p2 = point; UpdateArcFrom3Points(); return; } } void MoveMouse3P123(ICanvas canvas, UnitPoint point) { if (m_curPoint == eCurrentPoint.p1) { m_p1 = point; return; } if (m_curPoint == eCurrentPoint.p2) { m_p2 = point; return; } if (m_curPoint == eCurrentPoint.p3) { m_p3 = point; UpdateArcFrom3Points(); return; } } eDrawObjectMouseDown MouseDown3P132(ICanvas canvas, UnitPoint point, ISnapPoint snappoint) { OnMouseMove(canvas, point); if (m_curPoint == eCurrentPoint.p1) { m_curPoint = eCurrentPoint.p3; return eDrawObjectMouseDown.Continue; } if (m_curPoint == eCurrentPoint.p3) { m_curPoint = eCurrentPoint.p2; return eDrawObjectMouseDown.Continue; } if (m_curPoint == eCurrentPoint.p2) { m_curPoint = eCurrentPoint.done; Selected = false; return eDrawObjectMouseDown.Done; } return eDrawObjectMouseDown.Done; } eDrawObjectMouseDown MouseDown3P123(ICanvas canvas, UnitPoint point, ISnapPoint snappoint) { OnMouseMove(canvas, point); if (m_curPoint == eCurrentPoint.p1) { m_curPoint = eCurrentPoint.p2; return eDrawObjectMouseDown.Continue; } if (m_curPoint == eCurrentPoint.p2) { m_curPoint = eCurrentPoint.p3; return eDrawObjectMouseDown.Continue; } if (m_curPoint == eCurrentPoint.p3) { m_curPoint = eCurrentPoint.done; Selected = false; return eDrawObjectMouseDown.Done; } return eDrawObjectMouseDown.Done; } UnitPoint StartAngleNodePoint(ICanvas canvas) { double r = Radius + canvas.ToUnit(8); return HitUtil.PointOncircle(m_center, r, HitUtil.DegressToRadians(StartAngle)); } UnitPoint EndAngleNodePoint(ICanvas canvas) { double r = Radius + canvas.ToUnit(8); return HitUtil.PointOncircle(m_center, r, HitUtil.DegressToRadians(EndAngle)); } UnitPoint RadiusNodePoint(ICanvas canvas) { double r = Radius + canvas.ToUnit(8); float angle = StartAngle + SweepAngle / 2; return HitUtil.PointOncircle(m_center, r, HitUtil.DegressToRadians(angle)); } public virtual void OnMouseMove(ICanvas canvas, UnitPoint point) { //m_lastPoint = point; if (m_type == eArcType.kArc3P132) MoveMouse3P132(canvas, point); if (m_type == eArcType.kArc3P123) MoveMouse3P123(canvas, point); } public virtual eDrawObjectMouseDown OnMouseDown(ICanvas canvas, UnitPoint point, ISnapPoint snappoint) { if (m_type == eArcType.kArc3P132) return MouseDown3P132(canvas, point, snappoint); if (m_type == eArcType.kArc3P123) return MouseDown3P123(canvas, point, snappoint); return eDrawObjectMouseDown.Done; } public virtual void OnMouseUp(ICanvas canvas, UnitPoint point, ISnapPoint snappoint) { } public virtual void OnKeyDown(ICanvas canvas, KeyEventArgs e) { if (e.KeyCode == Keys.D) { if (Direction == eDirection.CW) Direction = eDirection.CCW; else Direction = eDirection.CW; e.Handled = true; } } public virtual 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, thWidth)) return true; return HitUtil.IsPointInCircle(m_center, m_radius, point, thWidth / 2); } public virtual bool ObjectInRectangle(ICanvas canvas, RectangleF rect, bool anyPoint) { float r = m_radius + Width / 2; RectangleF boundingrect = HitUtil.CircleBoundingRect(m_center, r); if (anyPoint) { UnitPoint lp1 = new UnitPoint(rect.Left, rect.Top); UnitPoint lp2 = new UnitPoint(rect.Left, rect.Bottom); if (HitUtil.CircleIntersectWithLine(m_center, m_radius, lp1, lp2)) return true; lp1 = new UnitPoint(rect.Left, rect.Bottom); lp2 = new UnitPoint(rect.Right, rect.Bottom); if (HitUtil.CircleIntersectWithLine(m_center, m_radius, lp1, lp2)) return true; lp1 = new UnitPoint(rect.Left, rect.Top); lp2 = new UnitPoint(rect.Right, rect.Top); if (HitUtil.CircleIntersectWithLine(m_center, m_radius, lp1, lp2)) return true; lp1 = new UnitPoint(rect.Left, rect.Top); lp2 = new UnitPoint(rect.Right, rect.Top); if (HitUtil.CircleIntersectWithLine(m_center, m_radius, lp1, lp2)) return true; lp1 = new UnitPoint(rect.Right, rect.Top); lp2 = new UnitPoint(rect.Right, rect.Bottom); if (HitUtil.CircleIntersectWithLine(m_center, m_radius, lp1, lp2)) return true; } return rect.Contains(boundingrect); } [Browsable(false)] public virtual UnitPoint RepeatStartingPoint { get { return UnitPoint.Empty; } } public virtual INodePoint NodePoint(ICanvas canvas, UnitPoint point) { float thWidth = Line.ThresholdWidth(canvas, Width, ThresholdPixel); if (HitUtil.PointInPoint(P1, point, thWidth)) { m_lastPoint = P1; return new NodePointArc3PointPoint(this, eCurrentPoint.p1); } if (HitUtil.PointInPoint(P2, point, thWidth)) { m_lastPoint = P2; return new NodePointArc3PointPoint(this, eCurrentPoint.p2); } if (HitUtil.PointInPoint(P3, point, thWidth)) { m_lastPoint = P3; return new NodePointArc3PointPoint(this, eCurrentPoint.p3); } UnitPoint p = StartAngleNodePoint(canvas); if (HitUtil.PointInPoint(p, point, thWidth)) { m_lastPoint = p; return new NodePointArc3PointPoint(this, eCurrentPoint.startangle); } p = EndAngleNodePoint(canvas); if (HitUtil.PointInPoint(p, point, thWidth)) { m_lastPoint = p; return new NodePointArc3PointPoint(this, eCurrentPoint.endangle); } p = RadiusNodePoint(canvas); if (HitUtil.PointInPoint(p, point, thWidth)) { m_lastPoint = p; return new NodePointArc3PointPoint(this, eCurrentPoint.radius); } return null; } public virtual ISnapPoint SnapPoint(ICanvas canvas, UnitPoint point, List otherobj, Type[] runningsnaptypes, Type usersnaptype) { float thWidth = Line.ThresholdWidth(canvas, Width, ThresholdPixel); if (runningsnaptypes != null) { foreach (Type snaptype in runningsnaptypes) { /* if (snaptype == typeof(QuadrantSnapPoint)) { UnitPoint p = HitUtil.NearestPointOnCircle(m_center, m_radius, point, 90); if (p != UnitPoint.Empty && HitUtil.PointInPoint(p, point, thWidth)) return new QuadrantSnapPoint(canvas, this, p); } if (snaptype == typeof(CenterSnapPoint)) { if (HitUtil.PointInPoint(m_center, point, thWidth)) return new CenterSnapPoint(canvas, this, m_center); } * */ if (snaptype == typeof(VertextSnapPoint)) { if (HitUtil.PointInPoint(P1, point, thWidth)) return new VertextSnapPoint(canvas, this, P1); if (HitUtil.PointInPoint(P3, point, thWidth)) return new VertextSnapPoint(canvas, this, P3); } } return null; } if (usersnaptype == typeof(NearestSnapPoint)) { UnitPoint p = HitUtil.NearestPointOnCircle(m_center, m_radius, point, 0); if (p != UnitPoint.Empty) return new NearestSnapPoint(canvas, this, p); } if (usersnaptype == typeof(PerpendicularSnapPoint)) { UnitPoint p = HitUtil.NearestPointOnCircle(m_center, m_radius, point, 0); if (p != UnitPoint.Empty) return new PerpendicularSnapPoint(canvas, this, p); } if (usersnaptype == typeof(QuadrantSnapPoint)) { UnitPoint p = HitUtil.NearestPointOnCircle(m_center, m_radius, point, 90); if (p != UnitPoint.Empty) return new QuadrantSnapPoint(canvas, this, p); } if (usersnaptype == typeof(TangentSnapPoint)) { IDrawObject drawingObject = canvas.CurrentObject; UnitPoint p = UnitPoint.Empty; if (drawingObject is LineEdit) { UnitPoint mousepoint = point; point = ((LineEdit)drawingObject).P1; UnitPoint p1 = HitUtil.TangentPointOnCircle(m_center, m_radius, point, false); UnitPoint p2 = HitUtil.TangentPointOnCircle(m_center, m_radius, point, true); double d1 = HitUtil.Distance(mousepoint, p1); double d2 = HitUtil.Distance(mousepoint, p2); if (d1 <= d2) return new TangentSnapPoint(canvas, this, p1); else return new TangentSnapPoint(canvas, this, p2); } //if (p != PointF.Empty) return new TangentSnapPoint(canvas, this, p); } if (usersnaptype == typeof(CenterSnapPoint)) { return new CenterSnapPoint(canvas, this, m_center); } return null; } public virtual void Move(UnitPoint offset) { P1 += offset; P2 += offset; P3 += offset; UpdateArcFrom3Points(); m_lastPoint = m_center; } public void Rotate(float angle, UnitPoint center) { m_p1 = HitUtil.RotatePoint(angle, m_p1, center); m_p2 = HitUtil.RotatePoint(angle, m_p2, center); m_p3 = HitUtil.RotatePoint(angle, m_p3, center); UpdateArcFrom3Points(); } public void MakeLength(float distance) { } public virtual string GetInfoAsString() { return string.Format("{1:D3} {0}@{2}, r={3:f4}, A1={4:f4}, A2={5:f4}", this.Type, No + 1, Center.PosAsString(), Radius, StartAngle, EndAngle); } #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; } public void AfterSerializedIn() { UpdateArcFrom3Points(); } #endregion protected static int ThresholdPixel = 6; public enum eCurrentPoint { p1, p2, p3, startangle, endangle, radius, done, } [Browsable(false)] public eCurrentPoint CurrentPoint { get { return m_curPoint; } set { m_curPoint = value; } } protected eCurrentPoint m_curPoint = eCurrentPoint.p1; protected UnitPoint m_lastPoint = UnitPoint.Empty; } }