/// <summary> /// 计算矩形外某个点与矩形中点的连线,与矩形的相交点。 /// </summary> /// <param name="rect"></param> /// <param name="outerPoint"></param> /// <returns></returns> public static Point CalcCrossPoint(Rect rect, Point outerPoint) { //单元测试: //var res = CalcCrossPoint(new Point(300, 150), new Rect(0, 0, 200, 100)); //if (res != new Point(200, 100)) throw new NotSupportedException(); //res = CalcCrossPoint(new Point(100, 200), new Rect(0, 0, 200, 100)); //if (res != new Point(100, 100)) throw new NotSupportedException(); //res = CalcCrossPoint(new Point(100, -100), new Rect(0, 0, 200, 100)); //if (res != new Point(100, 0)) throw new NotSupportedException(); var area = GetRectArea(rect, outerPoint); Line line1 = new Line { A = rect.GetCenterPoint(), B = outerPoint }; Line line2 = new Line(); switch (area) { case RectLineDirection.Left: line2.A = rect.TopLeft; line2.B = rect.BottomLeft; break; case RectLineDirection.Top: line2.A = rect.TopLeft; line2.B = rect.TopRight; break; case RectLineDirection.Right: line2.A = rect.TopRight; line2.B = rect.BottomRight; break; case RectLineDirection.Bottom: line2.A = rect.BottomRight; line2.B = rect.BottomLeft; break; default: break; } Point point = CalcCrossPoint(line1, line2); point.X = Round(point.X); point.Y = Round(point.Y); return point; }
/// <summary> /// 返回矩形中心点与指定点的向量,与矩形相交的点。 /// 简单地认为,这个点即是矩形边上最靠近指定点的点。 /// </summary> /// <param name="rect"></param> /// <param name="point"></param> /// <returns></returns> public static Point NearestPointOnLine(Rect rect, Point point) { Point res = point; if (rect.Contains(res)) { var center = rect.GetCenterPoint(); //没有斜率 if (res.Y == center.Y) { if (res.X < center.X) { res = RectAlgorithm.GetRectAbsolute(rect, new Point(0, 0.5)); } else { res = RectAlgorithm.GetRectAbsolute(rect, new Point(1, 0.5)); } return res; } else { //使用向量继续向该方向延长。 Vector v = new Vector(res.X - center.X, res.Y - center.Y); v *= 10000; while (true) { res += v; if (!rect.Contains(res)) break; } } } res = CalcCrossPoint(rect, point); return res; }
/// <summary> /// 按照中心点与四个角的连线,把空间分为四个区域。 /// 返回点所在的区域。 /// </summary> /// <param name="rect"></param> /// <param name="point"></param> /// <returns></returns> public static RectLineDirection GetRectArea(Rect rect, Point point) { var c = rect.GetCenterPoint(); var fromAngle = AngleFromCenter(c, point); var tl = AngleFromCenter(c, rect.TopLeft); var tr = AngleFromCenter(c, rect.TopRight); var br = AngleFromCenter(c, rect.BottomRight); var bl = AngleFromCenter(c, rect.BottomLeft); if (fromAngle > tl && fromAngle <= tr) { return RectLineDirection.Top; } else if (fromAngle > tr && fromAngle <= br) { return RectLineDirection.Right; } else if (fromAngle > br && fromAngle <= bl) { return RectLineDirection.Bottom; } else { return RectLineDirection.Left; } }