using System; using System.Collections.Generic; using System.Drawing; namespace HotelPms.Share.Windows.GraphicsApi { /// /// 重ねる判断 /// public static class Overlap { /// /// 線(a)と線(b) /// /// 線aの開始頂点 /// 線aの終了頂点 /// /// /// public static bool LineLine(Point a1, Point a2, Point b1, Point b2 ) { // b1->b2向量 与 a1->b1向量的向量积 var ua_t = (b2.X - b1.X) * (a1.Y - b1.Y) - (b2.Y - b1.Y) * (a1.X - b1.X); // a1->a2向量 与 a1->b1向量的向量积 var ub_t = (a2.X - a1.X) * (a1.Y - b1.Y) - (a2.Y - a1.Y) * (a1.X - b1.X); // a1->a2向量 与 b1->b2向量的向量积 var u_b = (b2.Y - b1.Y) * (a2.X - a1.X) - (b2.X - b1.X) * (a2.Y - a1.Y); // u_b == 0时,角度为0或者180 平行或者共线不属于相交 if (u_b != 0) { var ua = ua_t / u_b; var ub = ub_t / u_b; if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) { return true; } } return false; } /// /// 矩形と矩形 /// /// /// /// public static bool RectRect(Rectangle r1, Rectangle r2) { return !(r1.Right < r2.Left || r1.Bottom < r2.Top || r2.Right < r1.Left || r2.Bottom < r1.Top); } /// /// 矩形と矩形 /// /// /// /// public static bool RectRect2(Rectangle a, Rectangle b) { var a_min_x = a.X; var a_min_y = a.Y; var a_max_x = a.X + a.Width; var a_max_y = a.Y + a.Height; var b_min_x = b.X; var b_min_y = b.Y; var b_max_x = b.X + b.Width; var b_max_y = b.Y + b.Height; return a_min_x <= b_max_x && a_max_x >= b_min_x && a_min_y <= b_max_y && a_max_y >= b_min_y; } /// /// 線と矩形 /// /// /// /// /// public static bool LineRect(Point a1, Point a2, Rectangle b) { var r0 = new Point(b.Left, b.Top); var r1 = new Point(b.Left, b.Bottom); var r2 = new Point(b.Right, b.Bottom); var r3 = new Point(b.Right, b.Top); if (LineLine(a1, a2, r0, r1)) return true; if (LineLine(a1, a2, r1, r2)) return true; if (LineLine(a1, a2, r2, r3)) return true; if (LineLine(a1, a2, r3, r0)) return true; return false; } /// /// 線とポリコン /// /// /// /// /// public static bool LinePolygon(Point a1, Point a2, IList b ) { var length = b.Count; for (var i = 0; i < length; ++i) { var b1 = b[i]; var b2 = b[(i + 1) % length]; if (LineLine(a1, a2, b1, b2)) return true; } return false; } /// /// ポイント イン ポリコン /// /// /// /// public static bool PointInPolygon(Point point, IList polygon) { //* 射线法判断点是否在多边形内 //* 点射线(向右水平)与多边形相交点的个数为奇数则认为该点在多边形内 //* 点射线(向右水平)与多边形相交点的个数为偶数则认为该点不在多边形内 bool inside = false; int x = point.X; int y = point.Y; // use some raycasting to test hits // https://github.com/substack/point-in-polygon/blob/master/index.js var length = polygon.Count; for (int i = 0, j = length - 1; i < length; j = i++) { int xi = polygon[i].X, yi = polygon[i].Y, xj = polygon[j].X, yj = polygon[j].Y; bool intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); // (yi > y) != (yj > y)表示此条边的两个端点的y值一个大于这个点的y一个小于这个点的y // (x < (xj - xi) * (y - yi) / (yj - yi) + xi) 这个看起来像是求投影呢,还没搞明白 if (intersect) { inside = !inside; } } return inside; } /// /// 矩形とポリコン /// /// /// /// public static bool RectPolygon(Rectangle a, IList b) { var r0 = new Point(a.Left, a.Top); var r1 = new Point(a.Left, a.Bottom); var r2 = new Point(a.Right, a.Bottom); var r3 = new Point(a.Right, a.Top); // 矩形的每条边与多边形是否相交 if (LinePolygon(r0, r1, b)) return true; if (LinePolygon(r1, r2, b)) return true; if (LinePolygon(r2, r3, b)) return true; if (LinePolygon(r3, r0, b)) return true; // 走到这可以检测出两个图形无交点 // 检测是否矩形包含多边形,如果多边形上存在一个点在矩形内,则相交 int l = b.Count; for (int i = 0; i < l; ++i) { if (PointInPolygon(b[i], new Point[] { r0, r1, r2, r3 })) return true; } // 检测是否多边形包含矩形,如果矩形上存在一个点在多边形内,则相交 if (PointInPolygon(r0, b)) return true; if (PointInPolygon(r1, b)) return true; if (PointInPolygon(r2, b)) return true; if (PointInPolygon(r3, b)) return true; return false; } /// /// ポリコンとポリコン /// /// /// /// public static bool PolygonPolygon(IList a, IList b) { int i, l; // a的每条边与b的每条边做相交检测 for (i = 0, l = a.Count; i < l; ++i) { var a1 = a[i]; var a2 = a[(i + 1) % l]; if (LinePolygon(a1, a2, b)) return true; } // 判断两个多边形的包含关系 for (i = 0, l = b.Count; i < l; ++i) { if (PointInPolygon(b[i], a)) return true; } // 判断两个多边形的包含关系 for (i = 0, l = a.Count; i < l; ++i) { if (PointInPolygon(a[i], b)) return true; } return false; } /// /// 计算两点之间的距离 /// /// /// /// /// /// public static double lineSpace(double x1, double y1, double x2, double y2) { double lineLength = 0; lineLength = Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); return lineLength; } /// /// 点到线段距离 /// /// 線の開始頂点x /// 線の開始頂点y /// 線の終了頂点x /// 線の終了頂点y /// 点x /// 点y /// public static double PointToLine(double x1, double y1, double x2, double y2, double x0, double y0) { double space = 0; double a, b, c; a = lineSpace(x1, y1, x2, y2);// 线段的长度 b = lineSpace(x1, y1, x0, y0);// (x1,y1)到点的距离 c = lineSpace(x2, y2, x0, y0);// (x2,y2)到点的距离 if (c <= 0.000001 || b <= 0.000001) { space = 0; return space; } if (a <= 0.000001) { space = b; return space; } if (c * c >= a * a + b * b) { space = b; return space; } if (b * b >= a * a + c * c) { space = c; return space; } double p = (a + b + c) / 2;// 半周长 double s = Math.Sqrt(p * (p - a) * (p - b) * (p - c));// 海伦公式求面积 space = 2 * s / a;// 返回点到线的距离(利用三角形面积公式求高) return space; } } }