判断任意多边形与矩形的相交(线段与矩形相交或线段与线段相交)
来源:互联网 发布:对网络与新媒体的认识 编辑:程序博客网 时间:2024/05/17 00:19
任意多边形与矩形的相交,其实就是判断多条线段是否与这个矩形相交,再简单点就是判断线段是否与矩形的每一条边相交了。那现在,我们先来看看判断一条线段与矩形的其中一条线段的相交的情况(上方水平线):
(图形中的a/b=d/c如果看不明白的,我也无语了,回去翻下几何图形的那中学课本。)图中已知的是红色的线段,就是要检测的线段,其起点就是star,重点是end,其坐标是已知的。图中的蓝色线是辅助理解的线。而图中的y0,x1,x2是矩形的其中一条线的参数,那,下面我们从代码去理解一下:(Vector2其实就是point的类型,具体请看文章末尾的备注)
/// <summary> /// (检测点是否在点数组连接的线段上)Check point hits polyline with specified accuracy /// </summary> /// <param name="point">要检测的点</param> /// <param name="vertices">被检测的点数组</param> /// <param name="accuracy">检测精确度</param> /// <returns> /// (如果点与点数组连接成的线段碰撞则返回true,否则返回false)Returns true if point hists line otherwise - false /// </returns> public static bool PointInLine(Vector2 point, Vector2[] vertices, float accuracy) { if (point == null || (vertices == null || vertices.Length < 2)) return false; Rect pointRect = new Rect(); pointRect.Width = accuracy*2; pointRect.Height = accuracy*2; pointRect.Center = point; return LineIntersectRect(vertices, pointRect); }其中point参数就是要检测的点,vertices是被检测的线段集合,accuracy是其精确性,如果为0,则精确到点,如果存在一定的模糊性,可以给这个参数赋值。(做图形开发的时候,鼠标点要精确到某条线上,那要求太高了,因此,一般会设置其精确值,这个值越小越精确。)从这段代码中可以理解成N条线段vertices去检测是否与这个存在一定精确性的矩形相交,那下面看看这个函数LineIntersectRect的代码:
/// <summary> /// (检测矩形的4条边是否与点数组连接的线段相交)Check intersection of polyline with rectangular area /// </summary> /// <param name="vertices">点数据集合</param> /// <param name="rect">矩形</param> /// <returns> /// (如果矩形与点数组连接的线段相交则返回true,否则返回false)Returns true if polyline intersects rectangular area, otherwise - false /// </returns> public static bool LineIntersectRect(Vector2[] vertices, Rect rect) { if ((vertices == null || vertices.Length < 2) || rect == Rect.Empty) return false; for (int i = 0; i < vertices.Length - 1; i++) { if (CheckRectLine(vertices[i], vertices[i + 1], rect)) return true; } return false; }这段代码很好理解,就是从数组中每2点去检测其是否与这个矩形相交。下面就看看CheckRectLine检测其线段与矩形检测的代码:
/// <summary> /// (检测2个点连接的线段是否与矩形相交)Checks intersection of line with rectangular area /// </summary> /// <param name="start">线段起点</param> /// <param name="end">线段终点</param> /// <param name="rect">矩形</param> /// <returns> /// (如果线段与矩形相交,则返回true,否则返回false)Returns true if line intersects with rectangle otherwise - false /// </returns> private static bool CheckRectLine(Vector2 start, Vector2 end, Rect rect) { bool result = false; if (rect.Contains(start) || rect.Contains(end)) result = true; else { result |= CheckRectLineH(start, end, rect.LeftTop.Y, rect.LeftTop.X, rect.RightBottom.X); result |= CheckRectLineH(start, end, rect.RightBottom.Y, rect.LeftTop.X, rect.RightBottom.X); result |= CheckRectLineV(start, end, rect.LeftTop.X, rect.LeftTop.Y, rect.RightBottom.Y); result |= CheckRectLineV(start, end, rect.RightBottom.X, rect.LeftTop.Y, rect.RightBottom.Y); } return result; }线段与矩形是否相交的方法就变成了线段与矩形的4条边是否相交进行检测。这里,该方法CheckRectLineH是水平方向上的检测,就是检测矩形的上边线与下边线,那CheckRectLineV就是检测矩形的左边线和右边线了。我们先来看下CheckRectLineH这个函数的代码,然后再看看图来进行分析:
/// <summary> /// 水平方向上的检测 /// </summary> /// <param name="start">直线开始点</param> /// <param name="end">直线结束点</param> /// <param name="y0">点的Y坐标</param> /// <param name="x1">点的X坐标</param> /// <param name="x2">线x=x2的垂直线</param> /// <returns></returns> private static bool CheckRectLineH(Vector2 start, Vector2 end, float y0, float x1, float x2) { //直线在点的上方 if ((y0 < start.Y) && (y0 < end.Y)) return false; //直线在点的下方 if ((y0 > start.Y) && (y0 > end.Y)) return false; //水平直线 if (start.Y == end.Y) { //水平直线与点处于同一水平。 if (y0 == start.Y) { //直线在点的左边 if ((start.X < x1) && (end.X < x1)) return false; //直线在x2垂直线右边 if ((start.X > x2) && (end.X > x2)) return false; //直线的部分或者全部处于点与x2垂直线之间 return true; } else//水平直线与点不处于同一水平。 { return false; } } //斜线 float x = (end.X - start.X) * (y0 - start.Y) / (end.Y - start.Y) + start.X; return ((x >= x1) && (x <= x2)); }
看完代码,我们再看最开始时候的图,协助分析,我们可以想到这个函数其实就是检测X1与Y0的交点与X2与Y0的交点是否与红色线段是否相交,如果相交,则判断其交点是否在x1与x2之间的范围。(根据调用的参数,可以知道其正好就是上下边线)我们根据图的理解,可以得出:
a=(end.X - start.X),b=(end.Y - start.Y),c=(y0 - start.Y),d=start.X+x。从而可以得出
x = (end.X - start.X) * (y0 - start.Y) / (end.Y - start.Y) + start.X。
同理,CheckRectLineV的分析刚好是x和Y倒转过来。下面贴出代码:(分析就不再细说了)
private static bool CheckRectLineV(Vector2 start, Vector2 end, float x0, float y1, float y2) { if ((x0 < start.X) && (x0 < end.X)) return false; if ((x0 > start.X) && (x0 > end.X)) return false; if (start.X == end.X) { if (x0 == start.X) { if ((start.Y < y1) && (end.Y < y1)) return false; if ((start.Y > y2) && (end.Y > y2)) return false; return true; } else { return false; } } float y = (end.Y - start.Y) * (x0 - start.X) / (end.X - start.X) + start.Y; return ((y >= y1) && (y <= y2)); }备注:这里由于是用Vortex2D的源码进行分析的,其中Vector2其实就是point的类型,只是该Vector2封装了更多的方法而已。其Rect的类型也不是系统的Rect,也是Vortex2D自己封装了更多方法的Rect类型,如果大家在使用该部分代码时,有编译出错的情况,请注意自行修改。这里提出的是一个思路。懂得了这个思路,自然就懂得如何修改各自的代码。
原创作品出自努力偷懒,转载请说明文章出处:http://blog.csdn.net/kfarvid或 http://www.cnblogs.com/kfarvid/
- 判断任意多边形与矩形的相交(线段与矩形相交或线段与线段相交)
- 判断任意多边形与矩形的相交(线段与矩形相交或线段与线段相交)
- poj1410判断线段与矩形是否相交(判断线段相交)
- 线段 矩形 矩形与矩形 相交
- 线段是否与矩形相交
- poj 1410 矩形与线段相交判断
- 线段与矩形 是否相交 矩形与矩形
- 线段是否与矩形相交zt
- poj1410 Intersection 线段与矩形相交
- poj 1410 线段与矩形相交
- POJ 1410 Intersection (判断线段与矩形是否相交)
- POJ 1410 Intersection (判断线段是否与矩形相交)
- POJ 1410 Intersection(判断线段与矩形是否相交)
- UVA 191 || Intersection (判断线段是否与矩形相交
- poj 1410 Intersection 【判断线段 与矩形面是否相交】
- POJ 1410 Intersection(判断线段与矩形是否相交)
- 判断两个线段\矩形相交
- POJ1410Intersection【判断线段与矩形相交+点在矩形内的简单判定】
- find 命令
- SQL 2005数据库结构显示--数据字典
- [转]Ultra Fractal教程系列40——蒙版的学习06——添加一个蒙版图层
- hdu 4020(一个水题)
- Find 备忘
- 判断任意多边形与矩形的相交(线段与矩形相交或线段与线段相交)
- [转]Ultra Fractal教程系列41——蒙版的学习07——编辑蒙版
- memcached之memcached介绍
- X64 和 X86有什么区别
- JSF运行时出现javax.servlet.jsp.JspException: Cannot find FacesContext处理方法
- flex自定义加载进度条
- 23种设计模式 UML 类图及对应示例代码 (二)
- JAVA里的常用正则表达式验证
- [转]Ultra Fractal教程系列42——蒙版的学习08——渲染图片