using System;
|
using System.Collections.Generic;
|
using System.Drawing;
|
|
namespace HotelPms.Share.Windows.GraphicsApi
|
{
|
/// <summary>
|
/// 重ねる判断
|
/// </summary>
|
public static class Overlap
|
{
|
/// <summary>
|
/// 線(a)と線(b)
|
/// </summary>
|
/// <param name="a1">線aの開始頂点</param>
|
/// <param name="a2">線aの終了頂点</param>
|
/// <param name="b1"></param>
|
/// <param name="b2"></param>
|
/// <returns></returns>
|
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;
|
}
|
|
|
/// <summary>
|
/// 矩形と矩形
|
/// </summary>
|
/// <param name="r1"></param>
|
/// <param name="r2"></param>
|
/// <returns></returns>
|
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);
|
}
|
|
/// <summary>
|
/// 矩形と矩形
|
/// </summary>
|
/// <param name="a"></param>
|
/// <param name="b"></param>
|
/// <returns></returns>
|
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;
|
}
|
|
/// <summary>
|
/// 線と矩形
|
/// </summary>
|
/// <param name="a1"></param>
|
/// <param name="a2"></param>
|
/// <param name="b"></param>
|
/// <returns></returns>
|
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;
|
}
|
|
/// <summary>
|
/// 線とポリコン
|
/// </summary>
|
/// <param name="a1"></param>
|
/// <param name="a2"></param>
|
/// <param name="b"></param>
|
/// <returns></returns>
|
public static bool LinePolygon(Point a1, Point a2, IList<Point> 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;
|
}
|
|
/// <summary>
|
/// ポイント イン ポリコン
|
/// </summary>
|
/// <param name="point"></param>
|
/// <param name="polygon"></param>
|
/// <returns></returns>
|
public static bool PointInPolygon(Point point, IList<Point> 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;
|
}
|
|
/// <summary>
|
/// 矩形とポリコン
|
/// </summary>
|
/// <param name="a"></param>
|
/// <param name="b"></param>
|
/// <returns></returns>
|
public static bool RectPolygon(Rectangle a, IList<Point> 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;
|
}
|
|
/// <summary>
|
/// ポリコンとポリコン
|
/// </summary>
|
/// <param name="a"></param>
|
/// <param name="b"></param>
|
/// <returns></returns>
|
public static bool PolygonPolygon(IList<Point> a, IList<Point> 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;
|
}
|
|
/// <summary>
|
/// 计算两点之间的距离
|
/// </summary>
|
/// <param name="x1"></param>
|
/// <param name="y1"></param>
|
/// <param name="x2"></param>
|
/// <param name="y2"></param>
|
/// <returns></returns>
|
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;
|
|
}
|
|
/// <summary>
|
/// 点到线段距离
|
/// </summary>
|
/// <param name="x1">線の開始頂点x</param>
|
/// <param name="y1">線の開始頂点y</param>
|
/// <param name="x2">線の終了頂点x</param>
|
/// <param name="y2">線の終了頂点y</param>
|
/// <param name="x0">点x</param>
|
/// <param name="y0">点y</param>
|
/// <returns></returns>
|
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;
|
}
|
}
|
}
|