/// <summary> /// Support allowing the user to move the angle control handles. /// </summary> /// <param name="view"></param> /// <param name="origRect"></param> /// <param name="newPoint"></param> /// <param name="whichHandle"></param> /// <param name="evttype"></param> /// <param name="min"></param> /// <param name="max"></param> public override void DoResize(GoView view, RectangleF origRect, PointF newPoint, int whichHandle, GoInputState evttype, SizeF min, SizeF max) { if ((whichHandle == 1039 || whichHandle == 1040) && (ResizesRealtime || evttype == GoInputState.Finish || evttype == GoInputState.Cancel)) { switch (whichHandle) { case 1039: { RectangleF bounds2 = Bounds; float num6 = bounds2.Width / 2f; float num7 = bounds2.Height / 2f; float num8 = bounds2.X + num6; float num9 = bounds2.Y + num7; float angle = GoStroke.GetAngle(newPoint.X - num8, newPoint.Y - num9); float num10 = SweepAngle - (angle - StartAngle); if (SweepAngle >= 0f) { if (num10 < 0f) { num10 += 360f; } } else if (num10 >= 0f) { num10 -= 360f; } SweepAngle = num10; StartAngle = angle; break; } case 1040: { RectangleF bounds = Bounds; float num = bounds.Width / 2f; float num2 = bounds.Height / 2f; float num3 = bounds.X + num; float num4 = bounds.Y + num2; float num5 = GoStroke.GetAngle(newPoint.X - num3, newPoint.Y - num4) - StartAngle; if (SweepAngle >= 0f) { if (num5 < 0f) { num5 += 360f; } } else if (num5 >= 0f) { num5 -= 360f; } SweepAngle = num5; break; } } } else { base.DoResize(view, origRect, newPoint, whichHandle, evttype, min, max); } }
public override void Paint(Graphics g, GoView view) { base.Paint(g, view); GoStroke s = this; if (mySeg >= s.PointsCount - 1) { mySeg = 0; } PointF a = s.GetPoint(mySeg); PointF b = s.GetPoint(mySeg + 1); float len = (float)Math.Sqrt((b.X - a.X) * (b.X - a.X) + (b.Y - a.Y) * (b.Y - a.Y)); float x = b.X; float y = b.Y; if (myDist >= len) { mySeg++; myDist = 0; } else if (len >= 1) { x = a.X + (b.X - a.X) * myDist / len; y = a.Y + (b.Y - a.Y) * myDist / len; } GoShape.DrawEllipse(g, view, null, Brushes.Red, x - 3, y - 3, 7, 7); }
public Lifeline(Color color, Color textColor) { Resizable = false; header = new GoTextNode(); header.Selectable = false; header.TopPort = null; // don't need these ports header.LeftPort = null; header.RightPort = null; header.BottomPort = null; header.Text = "name : class"; header.Label.TextColor = textColor; header.Label.Alignment = MiddleTop; header.Label.Wrapping = true; header.Label.WrappingWidth = 100; header.Label.Editable = false; header.Label.BackgroundColor = color; header.Shape.BrushColor = color; header.Shape.Pen = new Pen(textColor, 2); header.Position = new PointF(10, 10); Add(header); // will be this[0] GoStroke line = new GoStroke(); line.Selectable = false; Pen pen = new Pen(textColor, 2); pen.DashStyle = DashStyle.Dash; line.Pen = pen; line.AddPoint(new PointF()); line.AddPoint(new PointF()); Add(line); // will be this[1] LifelinePort port = new LifelinePort(); Add(port); // will be this[2] }
public Lifeline() { this.Resizable = false; GoTextNode header = new GoTextNode(); header.Selectable = false; header.TopPort = null; // don't need these ports header.LeftPort = null; header.RightPort = null; header.BottomPort = null; header.Text = "name : class"; header.Label.Alignment = MiddleTop; header.Label.Wrapping = true; header.Label.WrappingWidth = 100; header.Label.Editable = true; header.Shape.BrushColor = Color.LightGreen; header.Position = new PointF(10, 10); Add(header); // will be this[0] GoStroke line = new GoStroke(); line.Selectable = false; Pen pen = new Pen(Color.Black, 1); pen.DashStyle = DashStyle.Dash; line.Pen = pen; line.AddPoint(new PointF()); line.AddPoint(new PointF()); Add(line); // will be this[1] LifelinePort port = new LifelinePort(); Add(port); // will be this[2] }
/// <summary> /// A point is in this object only if it really is inside the section of the ellipse. /// </summary> /// <param name="p"></param> /// <returns></returns> public override bool ContainsPoint(PointF p) { if (!base.ContainsPoint(p)) { return(false); } RectangleF bounds = Bounds; float num = PenWidth / 2f; float num2 = bounds.Width / 2f; float num3 = bounds.Height / 2f; float num4 = bounds.X + num2; float num5 = bounds.Y + num3; num2 += num; num3 += num; if (num2 == 0f || num3 == 0f) { return(false); } float num6 = p.X - num4; float num7 = p.Y - num5; if (num6 * num6 / (num2 * num2) + num7 * num7 / (num3 * num3) > 1f) { return(false); } float angle = GoStroke.GetAngle(p.X - num4, p.Y - num5); float num8; float num9; if (SweepAngle < 0f) { num8 = StartAngle + SweepAngle; num9 = 0f - SweepAngle; } else { num8 = StartAngle; num9 = SweepAngle; } if (num9 > 360f) { return(true); } if (num8 + num9 > 360f) { if (!(angle >= num8)) { return(angle <= num8 + num9 - 360f); } return(true); } if (angle >= num8) { return(angle <= num8 + num9); } return(false); }
/// <summary> /// The closest point of a parallelogram that intersects with a given line /// is the closest such point of each of its four line segments. /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="result"></param> /// <returns></returns> public override bool GetNearestIntersectionPoint(PointF p1, PointF p2, out PointF result) { RectangleF bounds = Bounds; float shift = PenWidth / 2f; PointF[] points = getPoints(); PointF pointF = GoShape.ExpandPointOnEdge(points[0], bounds, shift); PointF pointF2 = GoShape.ExpandPointOnEdge(points[1], bounds, shift); PointF pointF3 = GoShape.ExpandPointOnEdge(points[2], bounds, shift); PointF pointF4 = GoShape.ExpandPointOnEdge(points[3], bounds, shift); float x = p1.X; float y = p1.Y; float num = 1E+21f; PointF pointF5 = default(PointF); if (GoStroke.NearestIntersectionOnLine(pointF, pointF2, p1, p2, out PointF result2)) { float num2 = (result2.X - x) * (result2.X - x) + (result2.Y - y) * (result2.Y - y); if (num2 < num) { num = num2; pointF5 = result2; } } if (GoStroke.NearestIntersectionOnLine(pointF2, pointF3, p1, p2, out result2)) { float num3 = (result2.X - x) * (result2.X - x) + (result2.Y - y) * (result2.Y - y); if (num3 < num) { num = num3; pointF5 = result2; } } if (GoStroke.NearestIntersectionOnLine(pointF3, pointF4, p1, p2, out result2)) { float num4 = (result2.X - x) * (result2.X - x) + (result2.Y - y) * (result2.Y - y); if (num4 < num) { num = num4; pointF5 = result2; } } if (GoStroke.NearestIntersectionOnLine(pointF4, pointF, p1, p2, out result2)) { float num5 = (result2.X - x) * (result2.X - x) + (result2.Y - y) * (result2.Y - y); if (num5 < num) { num = num5; pointF5 = result2; } } result = pointF5; return(num < 1E+21f); }
/// <summary> /// The closest intersection point of a polygon with a line is the /// closest such point for each of its segments. /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="result"></param> /// <returns></returns> /// <remarks> /// This currently does not always take into account any Pen width. /// </remarks> public override bool GetNearestIntersectionPoint(PointF p1, PointF p2, out PointF result) { RectangleF bounds = Bounds; float num = PenWidth / 2f; float num2 = 1E+21f; PointF pointF = default(PointF); checked { PointF result2; if (Style == GoPolygonStyle.Bezier) { for (int i = 3; i < myPointsCount; i += 3) { PointF point = GetPoint(i - 3); PointF point2 = GetPoint(i - 2); if (i + 3 >= myPointsCount) { i = myPointsCount - 1; } PointF point3 = GetPoint(i - 1); PointF point4 = GetPoint(i); if (GoStroke.BezierNearestIntersectionOnLine(point, point2, point3, point4, p1, p2, num, out result2)) { float num3 = (result2.X - p1.X) * (result2.X - p1.X) + (result2.Y - p1.Y) * (result2.Y - p1.Y); if (num3 < num2) { num2 = num3; pointF = result2; } } } } else { for (int j = 0; j < PointsCount; j++) { PointF a = GoShape.ExpandPointOnEdge(GetPoint(j), bounds, num); PointF b = GoShape.ExpandPointOnEdge(GetPoint((j + 1 < PointsCount) ? (j + 1) : 0), bounds, num); if (GoStroke.NearestIntersectionOnLine(a, b, p1, p2, out result2)) { float num4 = (result2.X - p1.X) * (result2.X - p1.X) + (result2.Y - p1.Y) * (result2.Y - p1.Y); if (num4 < num2) { num2 = num4; pointF = result2; } } } } result = pointF; return(num2 < 1E+21f); } }
/// <summary> /// Performs changes for undo and redo. /// </summary> /// <seealso cref="M:Northwoods.Go.GoObject.ChangeValue(Northwoods.Go.GoChangedEventArgs,System.Boolean)" /> public override void ChangeValue(GoChangedEventArgs e, bool undo) { switch (e.SubHint) { case 1001: { base.ChangeValue(e, undo); RectangleF rect = e.GetRect(!undo); RectangleF rect2 = e.GetRect(undo); if (rect.Width == rect2.Width && rect.Height == rect2.Height) { float dx = rect2.X - rect.X; float dy = rect2.Y - rect.Y; GoStroke.TranslatePoints(myPoints, dx, dy); } break; } case 1460: A = e.GetPoint(undo); break; case 1461: B = e.GetPoint(undo); break; case 1462: C = e.GetPoint(undo); break; case 1463: D = e.GetPoint(undo); break; case 1464: { PointF[] array = (PointF[])e.GetValue(undo); if (array != null) { SetPoints(array); } break; } case 1465: Orientation = (Orientation)e.GetValue(undo); break; default: base.ChangeValue(e, undo); break; } }
/// <summary> /// The bounding rectangle of a polygon is computed as the smallest /// rectangle that includes all of its points. /// </summary> /// <returns></returns> /// <remarks> /// If there are only zero or one points, the size will be zero. /// The computed bounds for Bezier-sided polygons are not necessarily the closest fitting. /// </remarks> protected override RectangleF ComputeBounds() { int pointsCount = PointsCount; if (pointsCount <= 0) { PointF position = base.Position; return(new RectangleF(position.X, position.Y, 0f, 0f)); } PointF point = GetPoint(0); float num = point.X; float num2 = point.Y; float num3 = point.X; float num4 = point.Y; checked { if (Style == GoPolygonStyle.Bezier) { for (int i = 3; i < myPointsCount; i += 3) { PointF point2 = GetPoint(i - 3); PointF point3 = GetPoint(i - 2); if (i + 3 >= myPointsCount) { i = myPointsCount - 1; } PointF point4 = GetPoint(i - 1); PointF point5 = GetPoint(i); RectangleF rectangleF = GoStroke.BezierBounds(point2, point3, point4, point5, 0.1f); num = Math.Min(num, rectangleF.X); num2 = Math.Min(num2, rectangleF.Y); num3 = Math.Max(num3, rectangleF.X + rectangleF.Width); num4 = Math.Max(num4, rectangleF.Y + rectangleF.Height); } } else { for (int j = 1; j < pointsCount; j++) { point = GetPoint(j); num = Math.Min(num, point.X); num2 = Math.Min(num2, point.Y); num3 = Math.Max(num3, point.X); num4 = Math.Max(num4, point.Y); } } return(new RectangleF(num, num2, num3 - num, num4 - num2)); } }
/// <summary> /// Determine the angle the port at the other end makes with this port. /// </summary> /// <param name="link"></param> /// <returns>the angle in degrees</returns> public virtual float GetAngle(IGoLink link) { if (link == null) { return(0f); } IGoPort goPort = link.GetOtherPort(this); if (goPort == null) { if (link.FromPort != null && link.FromPort.GoObject != null && link.FromPort.GoObject.Bounds == Bounds) { goPort = link.ToPort; } else if (link.ToPort != null && link.ToPort.GoObject != null && link.ToPort.GoObject.Bounds == Bounds) { goPort = link.FromPort; } } if (goPort == null) { return(0f); } GoObject goObject = goPort.GoObject; if (goObject == null) { return(0f); } PointF pointF = goObject.Center; PointF center = base.Center; GoLink goLink = link as GoLink; if (goLink == null) { GoLabeledLink goLabeledLink = link as GoLabeledLink; if (goLabeledLink != null) { goLink = goLabeledLink.RealLink; } } if (goLink != null && goLink.PointsCount > 0) { pointF = ((goLink.FromPort != goPort) ? goLink.GetPoint(checked (goLink.PointsCount - 1)) : goLink.GetPoint(0)); } return(GoStroke.GetAngle(pointF.X - center.X, pointF.Y - center.Y)); }
/// <summary> /// Performs changes for undo and redo. /// </summary> /// <seealso cref="M:Northwoods.Go.GoObject.ChangeValue(Northwoods.Go.GoChangedEventArgs,System.Boolean)" /> public override void ChangeValue(GoChangedEventArgs e, bool undo) { switch (e.SubHint) { case 1001: { base.ChangeValue(e, undo); RectangleF rect = e.GetRect(!undo); RectangleF rect2 = e.GetRect(undo); if (rect.Width == rect2.Width && rect.Height == rect2.Height) { float dx = rect2.X - rect.X; float dy = rect2.Y - rect.Y; GoStroke.TranslatePoints(myPoints, dx, dy); } break; } case 1431: A = e.GetPoint(undo); break; case 1432: B = e.GetPoint(undo); break; case 1433: C = e.GetPoint(undo); break; case 1434: { PointF[] array = (PointF[])e.GetValue(undo); if (array != null) { ResetPath(); myPoints = array; } break; } default: base.ChangeValue(e, undo); break; } }
// Assume the header is at the top, and the lifeline stroke and port extend down // from the middle of the bottom of the header. // The Lifeline's Activations are arranged vertically according to their Begin // and End step values. // The stroke and port are just tall enough to accomodate all Activations and all // Messages that connect to this Lifeline. public override void LayoutChildren(GoObject childchanged) { if (this.Initializing) { return; } if (this.Count < 3) { return; } GoObject header = this[0]; GoStroke line = this[1] as GoStroke; GoObject port = this[2]; PointF p = header.GetSpotLocation(MiddleBottom); // find last step of an Activation on this Lifeline or a Message connected to this Lifeline float maxend = 0; foreach (GoObject child in this) { Activation act = child as Activation; if (act != null) { act.SetSpotLocation(MiddleTop, GetStepPoint(act.Begin)); act.Height = Math.Max(10, (act.End - act.Begin) * MessageSpacing); maxend = Math.Max(maxend, act.End); } } foreach (IGoLink link in this.Port.Links) { Message msg = link as Message; if (msg != null) { maxend = Math.Max(maxend, msg.Step); } } // line connects to bottom of header line.SetPoint(0, p); line.SetPoint(1, new PointF(p.X, LineStart + maxend * MessageSpacing)); // port always starts at LineStart port.Bounds = new RectangleF(p.X - port.Width / 2, LineStart, port.Width, maxend * MessageSpacing); }
/// <summary> /// When the bounds change, update the points appropriately. /// </summary> /// <param name="old"></param> protected override void OnBoundsChanged(RectangleF old) { base.OnBoundsChanged(old); RectangleF bounds = Bounds; if (old.Width == bounds.Width && old.Height == bounds.Height) { float num = bounds.X - old.X; float num2 = bounds.Y - old.Y; if (num != 0f || num2 != 0f) { GoStroke.TranslatePoints(myPoints, num, num2); base.InvalidBounds = false; } } else { Changing(1434); GoStroke.RescalePoints(myPoints, old, bounds); base.InvalidBounds = false; Changed(1434, 0, null, old, 0, null, bounds); } }
/// <summary> /// Find the intersection points of a pie and the infinite line p1-p2 /// that is closest to point p1. /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="result"></param> /// <returns></returns> public override bool GetNearestIntersectionPoint(PointF p1, PointF p2, out PointF result) { RectangleF a = Bounds; float num = PenWidth / 2f; GoObject.InflateRect(ref a, num, num); float num2 = a.Width / 2f; float num3 = a.Height / 2f; float num4 = a.X + num2; float num5 = a.Y + num3; float num6 = p1.X - num4; float num7 = p1.Y - num5; float startAngle = StartAngle; float sweepAngle = SweepAngle; float num8 = startAngle + sweepAngle; if (num8 > 360f) { num8 -= 360f; } bool result2 = false; float num9 = 1E+21f; result = default(PointF); if (-0.01f < num6 && num6 < 0.01f) { num6 = 0.01f; } if (-0.01f < num7 && num7 < 0.01f) { num7 = 0.01f; } PointF result3; if (sweepAngle >= 360f) { if (GoEllipse.NearestIntersectionOnEllipse(a, p1, p2, out result3)) { float num10 = (p1.X - result3.X) * (p1.X - result3.X) + (p1.Y - result3.Y) * (p1.Y - result3.Y); if (num10 < num9) { result2 = true; result = result3; num9 = num10; } } } else if (sweepAngle + startAngle > 360f) { if (GoEllipse.NearestIntersectionOnArc(a, p1, p2, out result3, startAngle, 360f - startAngle)) { float num11 = (p1.X - result3.X) * (p1.X - result3.X) + (p1.Y - result3.Y) * (p1.Y - result3.Y); if (num11 < num9) { result2 = true; result = result3; num9 = num11; } } if (GoEllipse.NearestIntersectionOnArc(a, p1, p2, out result3, 0f, sweepAngle - (360f - startAngle))) { float num12 = (p1.X - result3.X) * (p1.X - result3.X) + (p1.Y - result3.Y) * (p1.Y - result3.Y); if (num12 < num9) { result2 = true; result = result3; num9 = num12; } } } else if (GoEllipse.NearestIntersectionOnArc(a, p1, p2, out result3, startAngle, sweepAngle)) { float num13 = (p1.X - result3.X) * (p1.X - result3.X) + (p1.Y - result3.Y) * (p1.Y - result3.Y); if (num13 < num9) { result2 = true; result = result3; num9 = num13; } } PointF pointAtAngle = GetPointAtAngle(startAngle); if (GoStroke.NearestIntersectionOnLine(new PointF(num4, num5), pointAtAngle, p1, p2, out result3)) { float num14 = (p1.X - result3.X) * (p1.X - result3.X) + (p1.Y - result3.Y) * (p1.Y - result3.Y); if (num14 < num9) { result2 = true; result = result3; num9 = num14; } } PointF pointAtAngle2 = GetPointAtAngle(num8); if (GoStroke.NearestIntersectionOnLine(new PointF(num4, num5), pointAtAngle2, p1, p2, out result3)) { float num15 = (p1.X - result3.X) * (p1.X - result3.X) + (p1.Y - result3.Y) * (p1.Y - result3.Y); if (num15 < num9) { result2 = true; result = result3; num9 = num15; } } return(result2); }
/// <summary> /// Return the index of the first point of a segment of this polygon /// that is close to a given point. /// </summary> /// <param name="pnt">A <c>PointF</c> in document coordinates</param> /// <param name="pickMargin"> /// the approximate distance from each line segment that is allowed, /// in addition to the width of the Pen; assumed to be non-negative /// </param> /// <returns> /// The zero-based index of the first point of a segment, /// or <c>-1</c> if no segment is near <paramref name="pnt" />. /// </returns> /// <remarks> /// This ignores the filled area and only considers the boundary /// defined by the polygon points that is drawn by the Pen /// (or if there is no Pen, what would be drawn if there were a Pen). /// For Bezier style polygons, this returns the index of the first of /// each set of points, e.g. 0, 3, 7, .... /// </remarks> public int GetSegmentNearPoint(PointF pnt, float pickMargin) { RectangleF bounds = Bounds; float num = Math.Max(PenWidth, 0.1f); float num2 = Math.Max(pickMargin, 0f); num += num2; if (pnt.X < bounds.X - num || pnt.X > bounds.X + bounds.Width + num || pnt.Y < bounds.Y - num || pnt.Y > bounds.Y + bounds.Height + num) { return(-1); } int pointsCount = PointsCount; if (pointsCount <= 1) { return(-1); } num -= num2 / 2f; checked { if (Style == GoPolygonStyle.Bezier && pointsCount >= 4) { num *= Math.Max(1f, Math.Max(bounds.Width, bounds.Height) / 1000f); for (int i = 3; i < pointsCount; i += 3) { int result = i - 3; PointF point = GetPoint(i - 3); PointF point2 = GetPoint(i - 2); if (i + 3 >= pointsCount) { i = pointsCount - 1; } PointF point3 = GetPoint(i - 1); PointF point4 = GetPoint(i); if (GoStroke.BezierContainsPoint(point, point2, point3, point4, num, pnt)) { return(result); } } } else { for (int j = 0; j < pointsCount - 1; j++) { PointF point5 = GetPoint(j); PointF point6 = GetPoint(j + 1); if (GoStroke.LineContainsPoint(point5, point6, num, pnt)) { return(j); } } } PointF point7 = GetPoint(pointsCount - 1); PointF point8 = GetPoint(0); if (point7 != point8 && GoStroke.LineContainsPoint(point7, point8, num, pnt)) { return(pointsCount - 1); } return(-1); } }
/// <summary> /// Performs changes for undo and redo. /// </summary> /// <seealso cref="M:Northwoods.Go.GoObject.ChangeValue(Northwoods.Go.GoChangedEventArgs,System.Boolean)" /> public override void ChangeValue(GoChangedEventArgs e, bool undo) { switch (e.SubHint) { case 1001: { base.ChangeValue(e, undo); RectangleF rect = e.GetRect(!undo); RectangleF rect2 = e.GetRect(undo); if (rect.Width == rect2.Width && rect.Height == rect2.Height) { float dx = rect2.X - rect.X; float dy = rect2.Y - rect.Y; GoStroke.TranslatePoints(myPoints, dx, dy); } break; } case 1401: if (undo) { InternalRemovePoint(e.OldInt); } else { InternalInsertPoint(e.OldInt, new PointF(e.NewRect.X, e.NewRect.Y)); } break; case 1402: if (undo) { InternalInsertPoint(e.OldInt, new PointF(e.OldRect.X, e.OldRect.Y)); } else { InternalRemovePoint(e.OldInt); } break; case 1403: if (undo) { InternalSetPoint(e.OldInt, new PointF(e.OldRect.X, e.OldRect.Y)); } else { InternalSetPoint(e.OldInt, new PointF(e.NewRect.X, e.NewRect.Y)); } break; case 1412: { PointF[] points = (PointF[])e.GetValue(undo); SetPoints(points); break; } case 1414: Style = (GoPolygonStyle)e.GetValue(undo); break; default: base.ChangeValue(e, undo); break; } }
/// <summary> /// Find the intersection point of the elliptical path defined by rectangle rect and an infinite /// line p1-p2 that is closest to point p1. /// </summary> /// <param name="rect"></param> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="result"></param> /// <returns></returns> public static bool NearestIntersectionOnEllipse(RectangleF rect, PointF p1, PointF p2, out PointF result) { if (rect.Width == 0f) { return(GoStroke.NearestIntersectionOnLine(new PointF(rect.X, rect.Y), new PointF(rect.X, rect.Y + rect.Height), p1, p2, out result)); } if (rect.Height == 0f) { return(GoStroke.NearestIntersectionOnLine(new PointF(rect.X, rect.Y), new PointF(rect.X + rect.Width, rect.Y), p1, p2, out result)); } float num = rect.Width / 2f; float num2 = rect.Height / 2f; float num3 = rect.X + num; float num4 = rect.Y + num2; float num5 = 9999f; if (p1.X > p2.X) { num5 = (p1.Y - p2.Y) / (p1.X - p2.X); } else if (p1.X < p2.X) { num5 = (p2.Y - p1.Y) / (p2.X - p1.X); } if (Math.Abs(num5) < 9999f) { float num6 = p1.Y - num4 - num5 * (p1.X - num3); if (num * num * (num5 * num5) + num2 * num2 - num6 * num6 < 0f) { result = default(PointF); return(false); } float num7 = (float)Math.Sqrt(num * num * (num5 * num5) + num2 * num2 - num6 * num6); float num8 = (0f - num * num * num5 * num6 + num * num2 * num7) / (num2 * num2 + num * num * (num5 * num5)) + num3; float num9 = (0f - num * num * num5 * num6 - num * num2 * num7) / (num2 * num2 + num * num * (num5 * num5)) + num3; float num10 = num5 * (num8 - num3) + num6 + num4; float num11 = num5 * (num9 - num3) + num6 + num4; float num12 = Math.Abs((p1.X - num8) * (p1.X - num8)) + Math.Abs((p1.Y - num10) * (p1.Y - num10)); float num13 = Math.Abs((p1.X - num9) * (p1.X - num9)) + Math.Abs((p1.Y - num11) * (p1.Y - num11)); if (num12 < num13) { result = new PointF(num8, num10); } else { result = new PointF(num9, num11); } } else { float num14 = num2 * num2; float num15 = num * num; float num16 = p1.X - num3; float num17 = num14 - num14 / num15 * (num16 * num16); if (num17 < 0f) { result = default(PointF); return(false); } float num18 = (float)Math.Sqrt(num17); float num19 = num4 + num18; float num20 = num4 - num18; float num21 = Math.Abs(num19 - p1.Y); float num22 = Math.Abs(num20 - p1.Y); if (num21 < num22) { result = new PointF(p1.X, num19); } else { result = new PointF(p1.X, num20); } } return(true); }
/// <summary> /// The closest point of a cylinder that intersects with a given line /// is the closest such point of each two line segments and two ellipses. /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="result"></param> /// <returns></returns> public override bool GetNearestIntersectionPoint(PointF p1, PointF p2, out PointF result) { RectangleF bounds = Bounds; float shift = PenWidth / 2f; PointF[] points = getPoints(); PointF a = GoShape.ExpandPointOnEdge(points[0], bounds, shift); PointF b = GoShape.ExpandPointOnEdge(points[1], bounds, shift); PointF a2 = GoShape.ExpandPointOnEdge(points[2], bounds, shift); PointF b2 = GoShape.ExpandPointOnEdge(points[3], bounds, shift); float num = 1E+21f; PointF pointF = default(PointF); RectangleF rect; RectangleF rect2; float startAngle; float startAngle2; if (Orientation == Orientation.Vertical) { rect = new RectangleF(bounds.X, bounds.Y, bounds.Width, MinorRadius * 2f); rect2 = new RectangleF(bounds.X, bounds.Y + bounds.Height - MinorRadius * 2f, bounds.Width, MinorRadius * 2f); startAngle = 180f; startAngle2 = 0f; } else { rect = new RectangleF(bounds.X, bounds.Y, MinorRadius * 2f, bounds.Height); rect2 = new RectangleF(bounds.X + bounds.Width - MinorRadius * 2f, bounds.Y, MinorRadius * 2f, bounds.Height); startAngle = 90f; startAngle2 = 270f; } if (GoEllipse.NearestIntersectionOnArc(rect, p1, p2, out PointF result2, startAngle, 180f)) { float num2 = (result2.X - p1.X) * (result2.X - p1.X) + (result2.Y - p1.Y) * (result2.Y - p1.Y); if (num2 < num) { num = num2; pointF = result2; } } if (Orientation == Orientation.Horizontal) { if (GoEllipse.NearestIntersectionOnArc(rect2, p1, p2, out result2, 270f, 90f)) { float num3 = (result2.X - p1.X) * (result2.X - p1.X) + (result2.Y - p1.Y) * (result2.Y - p1.Y); if (num3 < num) { num = num3; pointF = result2; } } if (GoEllipse.NearestIntersectionOnArc(rect2, p1, p2, out result2, 0f, 90f)) { float num4 = (result2.X - p1.X) * (result2.X - p1.X) + (result2.Y - p1.Y) * (result2.Y - p1.Y); if (num4 < num) { num = num4; pointF = result2; } } } else if (GoEllipse.NearestIntersectionOnArc(rect2, p1, p2, out result2, startAngle2, 180f)) { float num5 = (result2.X - p1.X) * (result2.X - p1.X) + (result2.Y - p1.Y) * (result2.Y - p1.Y); if (num5 < num) { num = num5; pointF = result2; } } if (GoStroke.NearestIntersectionOnLine(a, b, p1, p2, out result2)) { float num6 = (result2.X - p1.X) * (result2.X - p1.X) + (result2.Y - p1.Y) * (result2.Y - p1.Y); if (num6 < num) { num = num6; pointF = result2; } } if (GoStroke.NearestIntersectionOnLine(a2, b2, p1, p2, out result2)) { float num7 = (result2.X - p1.X) * (result2.X - p1.X) + (result2.Y - p1.Y) * (result2.Y - p1.Y); if (num7 < num) { num = num7; pointF = result2; } } result = pointF; return(num < 1E+21f); }
/// <summary> /// Find the intersection point of the elliptical path defined by rectangle rect and an infinite /// line p1-p2 that is closest to point p1 within the area from startAngle through the sweepAngle. /// </summary> /// <param name="rect"></param> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="result"></param> /// <param name="startAngle"></param> /// <param name="sweepAngle"></param> /// <returns></returns> public static bool NearestIntersectionOnArc(RectangleF rect, PointF p1, PointF p2, out PointF result, float startAngle, float sweepAngle) { float num = rect.Width / 2f; float num2 = rect.Height / 2f; float num3 = rect.X + num; float num4 = rect.Y + num2; float num5; float num6; if (sweepAngle < 0f) { num5 = startAngle + sweepAngle; num6 = 0f - sweepAngle; } else { num5 = startAngle; num6 = sweepAngle; } if (p1.X != p2.X) { float num7 = (!(p1.X > p2.X)) ? ((p2.Y - p1.Y) / (p2.X - p1.X)) : ((p1.Y - p2.Y) / (p1.X - p2.X)); float num8 = p1.Y - num4 - num7 * (p1.X - num3); float num9 = (float)Math.Sqrt(num * num * (num7 * num7) + num2 * num2 - num8 * num8); float num10 = (0f - num * num * num7 * num8 + num * num2 * num9) / (num2 * num2 + num * num * (num7 * num7)) + num3; float num11 = (0f - num * num * num7 * num8 - num * num2 * num9) / (num2 * num2 + num * num * (num7 * num7)) + num3; float num12 = num7 * (num10 - num3) + num8 + num4; float num13 = num7 * (num11 - num3) + num8 + num4; float num14 = GoStroke.GetAngle(num10 - num3, num12 - num4); float num15 = GoStroke.GetAngle(num11 - num3, num13 - num4); if (num14 < num5) { num14 += 360f; } if (num15 < num5) { num15 += 360f; } if (num14 > num5 + num6) { num14 -= 360f; } if (num15 > num5 + num6) { num15 -= 360f; } bool flag = num14 >= num5 && num14 <= num5 + num6; bool flag2 = num15 >= num5 && num15 <= num5 + num6; if (flag && flag2) { float num16 = Math.Abs((p1.X - num10) * (p1.X - num10)) + Math.Abs((p1.Y - num12) * (p1.Y - num12)); float num17 = Math.Abs((p1.X - num11) * (p1.X - num11)) + Math.Abs((p1.Y - num13) * (p1.Y - num13)); if (num16 < num17) { result = new PointF(num10, num12); } else { result = new PointF(num11, num13); } return(true); } if (flag && !flag2) { result = new PointF(num10, num12); return(true); } if (!flag && flag2) { result = new PointF(num11, num13); return(true); } result = default(PointF); return(false); } float num18 = (float)Math.Sqrt(num2 * num2 - num2 * num2 / (num * num) * ((p1.X - num3) * (p1.X - num3))); float num19 = num4 + num18; float num20 = num4 - num18; float num21 = GoStroke.GetAngle(p1.X - num3, num19 - num4); float num22 = GoStroke.GetAngle(p1.X - num3, num20 - num4); if (num21 < num5) { num21 += 360f; } if (num22 < num5) { num22 += 360f; } if (num21 > num5 + num6) { num21 -= 360f; } if (num22 > num5 + num6) { num22 -= 360f; } bool flag3 = num21 >= num5 && num21 <= num5 + num6; bool flag4 = num22 >= num5 && num22 <= num5 + num6; if (flag3 && flag4) { float num23 = Math.Abs(num19 - p1.Y); float num24 = Math.Abs(num20 - p1.Y); if (num23 < num24) { result = new PointF(p1.X, num19); } else { result = new PointF(p1.X, num20); } return(true); } if (flag3 && !flag4) { result = new PointF(p1.X, num19); return(true); } if (!flag3 && flag4) { result = new PointF(p1.X, num20); return(true); } result = default(PointF); return(false); }