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;
}
}
}