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 NodePointLine : INodePoint { public enum ePoint { P1, P2, } static bool m_angleLocked = false; Line m_owner; Line 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 NodePointLine(Line owner, ePoint id) { m_owner = owner; m_clone = m_owner.Clone() as Line; 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) { if (System.Windows.Forms.Control.ModifierKeys == Keys.Control) pos = HitUtil.OrthoPointD(OtherPoint(m_pointId), pos, 45); if (m_angleLocked || System.Windows.Forms.Control.ModifierKeys == (Keys)(Keys.Control | Keys.Shift)) pos = HitUtil.NearestPointOnLine(m_owner.P1, m_owner.P2, pos, true); 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_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; return m_owner.P1; } protected UnitPoint OtherPoint(ePoint currentpointid) { if (currentpointid == ePoint.P1) return GetPoint(ePoint.P2); return GetPoint(ePoint.P1); } protected void SetPoint(ePoint pointid, UnitPoint point, Line line) { if (pointid == ePoint.P1) line.P1 = point; if (pointid == ePoint.P2) line.P2 = point; } } public class Line : DrawObjectBase, IDrawObject, ISerialize { UnitPoint m_p1, m_p2; [Browsable(false)] public UnitPoint Center { get { return new UnitPoint(MiddlePoint); } set { MiddlePoint = ((UnitPoint)value).Point; } } [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; } } public static string ObjectType { get { return "Line"; } } public Line() { } public Line(UnitPoint point, UnitPoint endpoint, float width, Color color) { P1 = point; P2 = endpoint; Width = width; Color = color; Selected = false; } public override void InitializeFromModel(UnitPoint point, DrawingLayer layer, ISnapPoint snap) { P1 = P2 = point; 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(Line acopy) { base.Copy(acopy); P1 = acopy.P1; P2 = acopy.P2; Type = acopy.Type; m_no = acopy.m_no; //마킹객체에 대한 속성 복사 ScannerParamNo = acopy.ScannerParamNo; Enabled = acopy.Enabled; Selected = acopy.Selected; WeldingParameterID = acopy.WeldingParameterID; m_objectOffset = acopy.m_objectOffset; m_reverse = acopy.m_reverse; m_lock = acopy.m_lock; m_tag = acopy.m_tag; m_PMU_ID = acopy.m_PMU_ID; m_visionOffset = acopy.m_visionOffset; m_alignType = acopy.m_alignType; m_alignID = acopy.m_alignID; m_alignOffset = acopy.m_alignOffset; m_MadebyRCC = acopy.m_MadebyRCC; m_RCC_PowerRatio = acopy.m_RCC_PowerRatio; } #region IDrawObject Members #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; } } bool m_reverse = false; [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Reverse", 4, 6)] [Description("Reverse")] [XmlSerializable] 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", 5, 6)] [Description("Lock")] [XmlSerializable] public bool Lock { get { return m_lock; } set { m_lock = 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; } } int m_tag = 0; [Browsable(false)] [ReadOnly(false)] [CustomSortedCategory("Misc", 4, 6)] [CustomSortedDisplayName("Tag", 1, 1)] [Description("Tag")] [XmlSerializable] public int Tag { get { return m_tag; } set { m_tag = value; } } int m_PMU_ID = 0; [Browsable(false)] [ReadOnly(false)] [Category("Misc")] [DisplayName("PMU_ID")] [Description("PMU_ID")] [XmlSerializable] public int PMU_ID { get { return m_PMU_ID; } set { m_PMU_ID = value; } } 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)] [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; } } PointF m_objectOffset = new PointF(); [Browsable(false)] [ReadOnly(false)] [Category("Pen")] [DisplayName("Object Offset")] [Description("Offset for Shot position when wleding, Expert Use Only")] [TypeConverter(typeof(PointFConverter))] [XmlSerializable] public PointF ObjectOffset { get { return m_objectOffset; } set { m_objectOffset = value; } } PointF m_visionOffset = new PointF(); [Browsable(false)] [ReadOnly(false)] [CustomSortedCategory("Vision Align", 4, 6)] [CustomSortedDisplayName("Vision Offset", 4, 4)] [Description("Vision Offset")] [TypeConverter(typeof(PointFConverter))] [XmlSerializable] public PointF VisionOffset { get { return m_visionOffset; } set { m_visionOffset = 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", 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; } } PointF m_alignOffset = new PointF(); [Browsable(false)] [ReadOnly(false)] [Category("Vision Align")] [DisplayName("Align Offset")] [Description("Align Offset")] [TypeConverter(typeof(PointFConverter))] [XmlSerializable] public PointF AlignOffset { get { return m_alignOffset; } set { m_alignOffset = value; } } #endregion #region 드로잉 객체에 대한 속성 int m_no; [Browsable(false)] [XmlSerializable] public int No { get { return m_no; } set { m_no = value; } } [Browsable(false)] [ReadOnly(true)] [Category("1. 객체")] [DisplayName("종류")] [Description("드로잉 객체 종류")] [XmlSerializable] public string Type { get; set; } = Line.ObjectType; [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Start[X,Y](mm)", 1, 6)] [Description("Starting Point Of Drawing Object")] [TypeConverter(typeof(PointFConverter))] [XmlSerializable] public PointF PF1 { get { lock (this) { return P1.Point; } } set { lock (this) { P1 = new UnitPoint(value); } } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("End[X,Y](mm)", 2, 6)] [Description("Starting Point Of Drawing Object")] [TypeConverter(typeof(PointFConverter))] [XmlSerializable] public PointF PF2 { get { lock (this) { return P2.Point; } } set { lock (this) { P2 = new UnitPoint(value); } } } [Browsable(false)] [ReadOnly(false)] [Category("2. Geometry")] [DisplayName("3.중심점[X,Y](mm)")] [Description("드로잉 객체의 중심점")] [TypeConverter(typeof(PointFConverter))] public PointF MiddlePoint { get { return HitUtil.LineMidpoint(P1, P2).Point; } set { PointF offset = new PointF(); offset.X = (value.X - MiddlePoint.X); offset.Y = (value.Y - MiddlePoint.Y); Move(new UnitPoint(offset)); } } [Browsable(false)] [ReadOnly(false)] [Category("Geometry")] [DisplayName("4.각도(˚)")] [Description("드로잉 객체의 각도")] public float Angle { get { return (float)Math.Round(HitUtil.RadiansToDegrees(HitUtil.LineAngleR(P1, P2, 0)), 3); } set { float angle = value - Angle; Rotate(angle, Center); } } [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(P1, P2, 0); } } } [Browsable(true)] [ReadOnly(false)] [CustomSortedCategory("Geometry", 3, 6)] [CustomSortedDisplayName("Line Length(mm)", 3, 6)] [Description("Length of Drawing Object")] public double Distance { get { return Math.Round(HitUtil.Distance(P1, P2), 3); } set { double distance = value; MakeLength((float)distance); } } public virtual IDrawObject Clone() { Line l = new Line(); l.Copy(this); return l; } public RectangleF GetBoundingRect(ICanvas canvas) { float thWidth = ThresholdWidth(canvas, Width); return ScreenUtils.GetRect(P1, P2, thWidth); } public UnitPoint m_bufferP; public void ClearDrawing(ICanvas canvas, RectangleF unitrect) { Color color = Color.White; Pen pen = canvas.CreatePen(color, Width); canvas.DrawLine(canvas, pen, P1, P2); if (Highlighted) { canvas.DrawLine(canvas, DrawUtils.SelectedPen, P1, P2); } if (Selected) { canvas.DrawLine(canvas, DrawUtils.SelectedPen, P1, P2); if (P1.IsEmpty == false) { DrawUtils.DrawNode(canvas, P1); } if (P2.IsEmpty == false) { DrawUtils.DrawTriangleNode(canvas, P2); } } } public virtual void Draw(ICanvas canvas, RectangleF unitrect) { Color color = WeldingParameterIDEditor.weldingColorList[(int)WeldingParameterID - 1]; Pen pen = canvas.CreatePen(color, Width); canvas.DrawLine(canvas, pen, P1, P2); DrawUtils.DrawArrowNode(canvas, P2, Angle, pen); if (Highlighted) { canvas.DrawLine(canvas, DrawUtils.SelectedPen, P1, P2); } if (Selected) { canvas.DrawLine(canvas, DrawUtils.SelectedPen, P1, P2); if (P1.IsEmpty == false) { DrawUtils.DrawNode(canvas, P1); } if (P2.IsEmpty == false) { DrawUtils.DrawTriangleNode(canvas, P2); } } } UnitPoint MidPoint(ICanvas canvas, UnitPoint p1, UnitPoint p2, UnitPoint hitpoint) { UnitPoint mid = HitUtil.LineMidpoint(p1, p2); float thWidth = ThresholdWidth(canvas, Width); if (HitUtil.CircleHitPoint(mid, thWidth, hitpoint)) return mid; return UnitPoint.Empty; } public bool PointInObject(ICanvas canvas, UnitPoint point) { float thWidth = ThresholdWidth(canvas, Width); return HitUtil.IsPointInLine(P1, P2, point, thWidth); } public bool ObjectInRectangle(ICanvas canvas, RectangleF rect, bool anyPoint) { RectangleF boundingrect = GetBoundingRect(canvas); if (anyPoint) return HitUtil.LineIntersectWithRect(P1, P2, rect); return rect.Contains(boundingrect); } public virtual void OnMouseMove(ICanvas canvas, UnitPoint point) { if (System.Windows.Forms.Control.ModifierKeys == Keys.Control) point = HitUtil.OrthoPointD(P1, point, 45); P2 = point; } public virtual eDrawObjectMouseDown OnMouseDown(ICanvas canvas, UnitPoint point, ISnapPoint snappoint) { Selected = false; if (snappoint is PerpendicularSnapPoint && snappoint.Owner is Line) { Line src = snappoint.Owner as Line; P2 = HitUtil.NearestPointOnLine(src.P1, src.P2, P1, true); return eDrawObjectMouseDown.DoneRepeat; } if (snappoint is PerpendicularSnapPoint && snappoint.Owner is SnowMan) { SnowMan src = snappoint.Owner as SnowMan; P2 = HitUtil.NearestPointOnLine(src.P1, src.P2, P1, true); return eDrawObjectMouseDown.DoneRepeat; } if (snappoint is PerpendicularSnapPoint && snappoint.Owner is Dot) { Dot src = snappoint.Owner as Dot; P2 = HitUtil.NearestPointOnCircle(src.P1, src.Width, P1, 0); return eDrawObjectMouseDown.DoneRepeat; } if (snappoint is PerpendicularSnapPoint && snappoint.Owner is Spline) { Spline src = snappoint.Owner as Spline; P2 = HitUtil.NearestPointOnCircle(src.Center, src.Radius, P1, 0); return eDrawObjectMouseDown.DoneRepeat; } if (snappoint is PerpendicularSnapPoint && snappoint.Owner is Arc) { Arc src = snappoint.Owner as Arc; P2 = HitUtil.NearestPointOnCircle(src.Center, src.Radius, P1, 0); return eDrawObjectMouseDown.DoneRepeat; } if (System.Windows.Forms.Control.ModifierKeys == Keys.Control) point = HitUtil.OrthoPointD(P1, point, 45); P2 = point; return eDrawObjectMouseDown.DoneRepeat; } public void OnMouseUp(ICanvas canvas, UnitPoint point, ISnapPoint snappoint) { } public virtual void OnKeyDown(ICanvas canvas, KeyEventArgs e) { } [Browsable(false)] public UnitPoint RepeatStartingPoint { get { return P2; } } public INodePoint NodePoint(ICanvas canvas, UnitPoint point) { float thWidth = ThresholdWidth(canvas, Width); if (HitUtil.CircleHitPoint(P1, thWidth, point)) { return new NodePointLine(this, NodePointLine.ePoint.P1); } if (HitUtil.CircleHitPoint(P2, thWidth, point)) { return new NodePointLine(this, NodePointLine.ePoint.P2); } return null; } public ISnapPoint SnapPoint(ICanvas canvas, UnitPoint point, List otherobjs, Type[] runningsnaptypes, Type usersnaptype) { float thWidth = ThresholdWidth(canvas, Width); if (runningsnaptypes != null) { foreach (Type snaptype in runningsnaptypes) { if (snaptype == typeof(VertextSnapPoint)) { if (HitUtil.CircleHitPoint(P1, thWidth, point)) return new VertextSnapPoint(canvas, this, P1); if (HitUtil.CircleHitPoint(P2, thWidth, point)) return new VertextSnapPoint(canvas, this, P2); } if (snaptype == typeof(MidpointSnapPoint)) { UnitPoint p = MidPoint(canvas, P1, P2, point); if (p != UnitPoint.Empty) return new MidpointSnapPoint(canvas, this, p); } if (snaptype == typeof(IntersectSnapPoint)) { Line otherline = Utils.FindObjectTypeInList(this, otherobjs, typeof(Line)) as Line; if (otherline == null) continue; UnitPoint p = HitUtil.LinesIntersectPoint(P1, P2, otherline.P1, otherline.P2); if (p != UnitPoint.Empty) return new IntersectSnapPoint(canvas, this, p); } } return null; } if (usersnaptype == typeof(MidpointSnapPoint)) return new MidpointSnapPoint(canvas, this, HitUtil.LineMidpoint(P1, P2)); if (usersnaptype == typeof(IntersectSnapPoint)) { Line otherline = Utils.FindObjectTypeInList(this, otherobjs, typeof(Line)) as Line; if (otherline == null) return null; UnitPoint p = HitUtil.LinesIntersectPoint(P1, P2, otherline.P1, otherline.P2); if (p != UnitPoint.Empty) return new IntersectSnapPoint(canvas, this, p); } if (usersnaptype == typeof(VertextSnapPoint)) { double d1 = HitUtil.Distance(point, P1); double d2 = HitUtil.Distance(point, P2); if (d1 <= d2) return new VertextSnapPoint(canvas, this, P1); return new VertextSnapPoint(canvas, this, P2); } if (usersnaptype == typeof(NearestSnapPoint)) { UnitPoint p = HitUtil.NearestPointOnLine(P1, P2, point); if (p != UnitPoint.Empty) return new NearestSnapPoint(canvas, this, p); } if (usersnaptype == typeof(PerpendicularSnapPoint)) { UnitPoint p = HitUtil.NearestPointOnLine(P1, P2, point); if (p != UnitPoint.Empty) return new PerpendicularSnapPoint(canvas, this, p); } 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; } public void Rotate(float angle, UnitPoint center) { // UnitPoint mid = Center; P1 = HitUtil.RotatePoint(angle, P1, center); P2 = HitUtil.RotatePoint(angle, P2, center); } public void MakeLength(float distance) { /*float slope =0; double gapX =0; double gapY = 0; if (P1.X != P2.X) { slope = (float)((P2.Y - P1.Y) / (P2.X - P1.X)); gapX= distance / (2 * Math.Sqrt(Math.Pow(slope, 2) + 1)); gapY = (distance * slope) / (2 * Math.Sqrt(Math.Pow(slope, 2) + 1)); } else { gapY = distance * 0.5; } PointF pt1 = new PointF(); PointF pt2 = new PointF(); //수정-안오산-161017-길이 수정시 방향 전환 오류 수정 if(P1.X>P2.X) { pt1.X = (float)(MiddlePoint.X + gapX); pt2.X = (float)(MiddlePoint.X - gapX); } else { pt1.X = (float)(MiddlePoint.X - gapX); pt2.X = (float)(MiddlePoint.X + gapX); } if (P1.Y > P2.Y) { pt1.Y= (float)(MiddlePoint.Y - gapY); pt2.Y = (float)(MiddlePoint.Y + gapY); } else { pt1.Y = (float)(MiddlePoint.Y + gapY); pt2.Y = (float)(MiddlePoint.Y - gapY); } P1 = new UnitPoint(pt1.X, pt1.Y); P2 = new UnitPoint(pt2.X, pt2.Y); */ // 시작점을 기준으로 길이 조절. float x, y; double delta; if (P1.X == P2.X) { delta = P1.Y < P2.Y ? distance : -distance; P2 = new UnitPoint(P2.X, P1.Y + delta); } else if (P1.Y == P2.Y) { delta = P1.X < P2.X ? distance : -distance; P2 = new UnitPoint(P1.X + delta, P2.Y); } else { float slope = (float)((P2.Y - P1.Y) / (P2.X - P1.X)); delta = (Math.Sqrt(Math.Pow(distance, 2) / (1 + Math.Pow(slope, 2)))); x = (P2.X > P1.X) ? (float)P1.X + (float)delta : (float)P1.X - (float)delta; y = (slope * (x - (float)P1.X)) + (float)P1.Y; P2 = new UnitPoint(x, y); } } public virtual string GetInfoAsString() { return string.Format("{1:D3} {0}@{2},{3} - L={4:f4} <{5:f4}", this.Type, No + 1, P1.PosAsString(), P2.PosAsString(), Distance, Angle); } #endregion #endregion public void ExtendLineToPoint(UnitPoint newpoint) { UnitPoint newlinepoint = HitUtil.NearestPointOnLine(P1, P2, newpoint, true); if (HitUtil.Distance(newlinepoint, P1) < HitUtil.Distance(newlinepoint, P2)) P1 = newlinepoint; else P2 = newlinepoint; } #region ISerialize Interface public 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() { } #endregion } public class LineEdit : Line, IObjectEditInstance { protected PerpendicularSnapPoint m_perSnap; protected TangentSnapPoint m_tanSnap; protected bool m_tanReverse = false; protected bool m_singleLineSegment = true; public LineEdit() : base() { } public LineEdit(bool singleLine) : base() { m_singleLineSegment = singleLine; if (m_singleLineSegment) Type = "Line"; else Type = "PolyLine"; } public override void InitializeFromModel(UnitPoint point, DrawingLayer layer, ISnapPoint snap) { base.InitializeFromModel(point, layer, snap); m_perSnap = snap as PerpendicularSnapPoint; m_tanSnap = snap as TangentSnapPoint; } public override void OnMouseMove(ICanvas canvas, UnitPoint point) { if (m_perSnap != null) { MouseMovePerpendicular(canvas, point); return; } if (m_tanSnap != null) { MouseMoveTangent(canvas, point); return; } base.OnMouseMove(canvas, point); } public override eDrawObjectMouseDown OnMouseDown(ICanvas canvas, UnitPoint point, ISnapPoint snappoint) { if (m_tanSnap != null && System.Windows.Forms.Control.MouseButtons == MouseButtons.Right) { ReverseTangent(canvas); return eDrawObjectMouseDown.Continue; } if (m_perSnap != null || m_tanSnap != null) { if (snappoint != null) point = snappoint.SnapPoint; OnMouseMove(canvas, point); if (m_singleLineSegment) return eDrawObjectMouseDown.Done; return eDrawObjectMouseDown.DoneRepeat; } eDrawObjectMouseDown result = base.OnMouseDown(canvas, point, snappoint); if (m_singleLineSegment) return eDrawObjectMouseDown.Done; return eDrawObjectMouseDown.DoneRepeat; } public override void OnKeyDown(ICanvas canvas, KeyEventArgs e) { if (e.KeyCode == Keys.R && m_tanSnap != null) { ReverseTangent(canvas); e.Handled = true; } } protected virtual void MouseMovePerpendicular(ICanvas canvas, UnitPoint point) { if (m_perSnap.Owner is Line) { Line src = m_perSnap.Owner as Line; P1 = HitUtil.NearestPointOnLine(src.P1, src.P2, point, true); P2 = point; } if (m_perSnap.Owner is SnowMan) { SnowMan src = m_perSnap.Owner as SnowMan; P1 = HitUtil.NearestPointOnLine(src.P1, src.P2, point, true); P2 = point; } if (m_perSnap.Owner is Dot) { Dot src = m_perSnap.Owner as Dot; P1 = HitUtil.NearestPointOnCircle(src.P1, src.Width, point, 0); P2 = point; } if (m_perSnap.Owner is Spline) { IArc src = m_perSnap.Owner as IArc; P1 = HitUtil.NearestPointOnCircle(src.Center, src.Radius, point, 0); P2 = point; } if (m_perSnap.Owner is IArc) { IArc src = m_perSnap.Owner as IArc; P1 = HitUtil.NearestPointOnCircle(Center, src.Radius, point, 0); P2 = point; } } protected virtual void MouseMoveTangent(ICanvas canvas, UnitPoint point) { if (m_tanSnap.Owner is IArc) { IArc src = m_tanSnap.Owner as IArc; P1 = HitUtil.TangentPointOnCircle(Center, src.Radius, point, m_tanReverse); P2 = point; if (P1 == UnitPoint.Empty) P2 = P1 = Center; } } protected virtual void ReverseTangent(ICanvas canvas) { m_tanReverse = !m_tanReverse; MouseMoveTangent(canvas, P2); canvas.Invalidate(false); } public void Copy(LineEdit acopy) { base.Copy(acopy); m_perSnap = acopy.m_perSnap; m_tanSnap = acopy.m_tanSnap; m_tanReverse = acopy.m_tanReverse; m_singleLineSegment = acopy.m_singleLineSegment; } public override IDrawObject Clone() { LineEdit l = new LineEdit(false); l.Copy(this); return l; } #region IObjectEditInstance public IDrawObject GetDrawObject() { return new Line(P1, P2, Width, Color) { Type = Type }; } #endregion } }