之前遇到一个数学问题,如何判断某一线段是否穿过封闭区域?由于很急,在网上胡乱找了一下解决方案,但是没有解决到实际问题。
已知:矩形的四个顶点,线段的起始点,
求:判断线段是否经过改矩形。(如图,红线穿过封闭区域,绿线不穿过封闭区域。)
问题类似于
如何判断某一线段是否穿过封闭区域?
道理就是那个道理,我在那里拿的图。
由于时间关系,我就叫同事帮我写个通用方法,他略微思索,百度了一下,觉得用中学知识就可以解决这个问题,欣然就答应了。代码如下:
public static bool IsPassThroughRect(List<Vector2> VectList, Vector2 begin, Vector2 end)
//求直线公式
double k, b;
k = (begin.y - end.y) / (begin.x - end.x);
b = begin.y - begin.x * k;
int count = 0;
for (int i = 0; i < VectList.Count; i++)
if ((VectList[i].y - k * VectList[i].x - b) > 0)
count++;
count--;
if (count == 4 || count == -4)
return false;
return true;
他给我解释了一下:
将直线写成y=kx+b的形式,将图形的所有顶点坐标带入y-kx-b。
如果得到的结果同时大于零或者同时小于零,说明图形的所有顶点都在直线的同侧,即直线不过图形。否则说明图形的顶点分布在直线两侧,直线过图形。
主要是思想就是中学知识:
(1)y-kx-b=0 点刚好在直线上。
(2)y-kx-b>0 点在直线上方。
(3)y-kx-b<0 点在直线下方。
我看了一下,好像是这个道理,直接将参数传进去,测试了一下,结果发现,这个道理虽然是这个道理,但是所用的知识是点与线的关系。这里的需求是线段与矩形的关系,如果是线段的话,这样是不满足需求的。
发现这个问题的时候,都十点半了,其他同事都下班了,看见主程还在,遂问了一下是否有类似的通用方法,结果真有!
代码如下:
/// <summary>
/// 线段与矩形是否相交
/// </summary>
/// <param name="linePointX1"></param>
/// <param name="linePointY1"></param>
/// <param name="linePointX2"></param>
/// <param name="linePointY2"></param>
/// <param name="rectangleLeftTopX"></param>
/// <param name="rectangleLeftTopY"></param>
/// <param name="rectangleRightBottomX"></param>
/// <param name="rectangleRightBottomY"></param>
/// <returns></returns>
public static bool isLineIntersectRectangle(float linePointX1,
float linePointY1,
float linePointX2,
float linePointY2,
float rectangleLeftTopX,
float rectangleLeftTopY,
float rectangleRightBottomX,
float rectangleRightBottomY)
float lineHeight = linePointY1 - linePointY2;
float lineWidth = linePointX2 - linePointX1; // 计算叉乘
float c = linePointX1 * linePointY2 - linePointX2 * linePointY1;
if ((lineHeight * rectangleLeftTopX + lineWidth * rectangleLeftTopY + c >= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleRightBottomY + c <= 0)
|| (lineHeight * rectangleLeftTopX + lineWidth * rectangleLeftTopY + c <= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleRightBottomY + c >= 0)
|| (lineHeight * rectangleLeftTopX + lineWidth * rectangleRightBottomY + c >= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleLeftTopY + c <= 0)
|| (lineHeight * rectangleLeftTopX + lineWidth * rectangleRightBottomY + c <= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleLeftTopY + c >= 0))
if (rectangleLeftTopX > rectangleRightBottomX)
float temp = rectangleLeftTopX;
rectangleLeftTopX = rectangleRightBottomX;
rectangleRightBottomX = temp;
if (rectangleLeftTopY < rectangleRightBottomY)
float temp1 = rectangleLeftTopY;
rectangleLeftTopY = rectangleRightBottomY;
rectangleRightBottomY = temp1;
if ((linePointX1 < rectangleLeftTopX && linePointX2 < rectangleLeftTopX)
|| (linePointX1 > rectangleRightBottomX && linePointX2 > rectangleRightBottomX)
|| (linePointY1 > rectangleLeftTopY && linePointY2 > rectangleLeftTopY)
|| (linePointY1 < rectangleRightBottomY && linePointY2 < rectangleRightBottomY))
return false;
return true;
return false;
他说他也是在网上扒下来的,我没细想,直接改成通用方法,传入我的参数,测试了几次,发现问题解决了。愉快下班!!!
今天发现(判断线段和矩形是否相交 )这篇文章好像就是原文,只是他是用JavaScript写的。大概就是扒的他了吧!
如何判断两个线段\矩形相交?
首先来判断两个线段的情况:假设有两个线段A和B,左右端点分别为A1,A2和B1,B2,分别考虑下面两种情况
1. 线段A在线段B的左边,即A1 A2
2. 线段A在线段B的右边,即A1> B1,那么 A,B不相交的条件是 B1 B2
那么将上面两种情况综合起来考虑就是Min(A2,B2) - Max(A1,B1) =0,那么X就是相交的区域大小。
这里的矩形指的是边与坐标轴平行的矩形,可用x和y上最大最小值表示。
判断是否相交,先快速排斥,再做跨立,通过向量的叉积判断矩形的四个顶点是否在线段的两侧,是说明有交集。
(如果判断与矩形的边是否有交集的话,可判断线段是否
Description
You are to write a program that has to decide whether a given line segment intersects a given rectangle.
An example:
line: start point: (4,9)
end point: (11,2)
rect...
判断线段AB是否与矩形范围有交集这里的矩形指的是边与坐标轴平行的矩形,可用x和y上最大最小值表示。判断是否相交,先快速排斥,再做跨立,通过向量的叉积判断矩形的四个顶点是否在线段的两侧,是说明有交集。(如果判断与矩形的边是否有交集的话,可判断线段是否与矩形的每条边是否有交集,线段与线段的交集判断。)这里在介绍另外一种方法,降维的方法:例如,有线段AB和矩形MN,如图所示:通过M和N点的y坐标计算直线AB上的D和C点,B和C点中取y值小的点B,A和D点中取y值大的点D,最后确定了线段BD在x轴上的投影GH,矩形
bool clipLine( // true if any part of line in imgRect
cv::Rect imgRect, // rectangle to clip to
cv::Point& pt1, // first endpoint of line overwritten
cv::Point& pt2 // second endpoint of line,
在这个示例中,我们首先定义了一个由四个点组成的正方形(x和y分别代表正方形四个角上的x和y坐标)。然后,我们使用了plt.plot函数来绘制这个正方形,并设置linestyle参数为'-'(实线),marker参数为's'(正方形)。
通过设置mec参数(marker edge color)为'blue',我们指定了边界颜色为蓝色。而通过设置mfc参数(marker face color)为'none',我们将内部颜色设置为透明,实现了空心效果。
最后,我们通过设置坐标轴范围和调用plt.show()来显示图形。您可以根据需要调整参数和样式来满足您的要求。