线段是否与矩形相交

// 判断点在有向直线的左侧还是右侧.
// 返回值:-1: 点在线段左侧; 0: 点在线段上; 1: 点在线段右侧
int PointAtLineLeftRight(CPoint ptStart, CPoint ptEnd, CPoint ptTest)
{
 ptStart.x -= ptTest.x;
 ptStart.y -= ptTest.y;
 ptEnd.x -= ptTest.x;
 ptEnd.y -= ptTest.y;

 int nRet = ptStart.x * ptEnd.y - ptStart.y * ptEnd.x;
 if (nRet == 0)
  return 0;
 else if (nRet > 0)
  return 1;
 else if (nRet < 0)
  return -1;

 return 0;
}

// 判断两条线段是否相交
BOOL IsTwoLineIntersect(CPoint ptLine1Start, CPoint ptLine1End, CPoint ptLine2Start, CPoint ptLine2End)
{
 int nLine1Start = PointAtLineLeftRight(ptLine2Start, ptLine2End, ptLine1Start);
 int nLine1End = PointAtLineLeftRight(ptLine2Start, ptLine2End, ptLine1End);
 if (nLine1Start * nLine1End > 0)
  return FALSE;

 int nLine2Start = PointAtLineLeftRight(ptLine1Start, ptLine1End, ptLine2Start);
 int nLine2End = PointAtLineLeftRight(ptLine1Start, ptLine1End, ptLine2End);

 if (nLine2Start * nLine2End > 0)
  return FALSE;

 return TRUE;
}

// 判断线段是否与矩形相交
BOOL IsLineIntersectRect(CPoint ptStart, CPoint ptEnd, CRect rect)
{
 // Two point both are in rect
 if (rect.PtInRect(ptStart) && rect.PtInRect(ptEnd))
  return TRUE;

 // One point is in rect, another not.
 if (rect.PtInRect(ptStart) && !rect.PtInRect(ptEnd))
  return TRUE;
 if (!rect.PtInRect(ptStart) && rect.PtInRect(ptEnd))
  return TRUE;

 // Two point both aren't in rect
 if (IsTwoLineIntersect(ptStart, ptEnd, CPoint(rect.left, rect.top), CPoint(rect.left, rect.bottom)))
  return TRUE;
 if (IsTwoLineIntersect(ptStart, ptEnd, CPoint(rect.left, rect.bottom), CPoint(rect.right, rect.bottom)))
  return TRUE;
 if (IsTwoLineIntersect(ptStart, ptEnd, CPoint(rect.right, rect.bottom), CPoint(rect.right, rect.top)))
  return TRUE;
 if (IsTwoLineIntersect(ptStart, ptEnd, CPoint(rect.left, rect.top), CPoint(rect.right, rect.top)))
  return TRUE;

 return FALSE;
}

// 测试代码:
const int RECTSIZE = 20;
void CMainFrame::OnPaint()
{
 CPaintDC dc(this); // device context for painting
 
 // TODO: Add your message handler code here
 
 CRect rcClient;
 GetClientRect(rcClient);
 CDC memDC;
 memDC.CreateCompatibleDC(&dc);
 CBitmap memBmp;
 memBmp.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
 CBitmap *pOldBmp = memDC.SelectObject(&memBmp);
 
 memDC.FillSolidRect(rcClient, RGB(255, 255, 255));
 
 // Draw rect
 CPoint pt;
 GetCursorPos(&pt);
 ScreenToClient(&pt);

 CRect rect;
 rect.left = pt.x - RECTSIZE / 2;
 rect.top = pt.y - RECTSIZE / 2;
 rect.right = rect.left + RECTSIZE;
 rect.bottom = rect.top + RECTSIZE;

 memDC.Draw3dRect(rect, RGB(0, 0, 0), RGB(0, 0, 0));

 // Draw line
 CPoint pt1(300, 200);
 CPoint pt2(500, 350);
 if (IsLineIntersectRect(pt1, pt2, rect))
  DrawArrowLine(memDC.m_hDC, &pt1, &pt2, 30, xAngle, RGB(128, 0, 255));
 else
  DrawArrowLine(memDC.m_hDC, &pt1, &pt2, 30, xAngle, RGB(0, 0, 0));

 dc.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY);
 memDC.SelectObject(pOldBmp);


 // Do not call CWnd::OnPaint() for painting messages
}

void CMainFrame::OnMouseMove(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 Invalidate();

 CWnd::OnMouseMove(nFlags, point);
}

BOOL CMainFrame::OnEraseBkgnd(CDC* pDC)
{
 // TODO: Add your message handler code here and/or call default

 return TRUE;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
判断线段矩形是否相交可以分为两种情况: 1. 线段的两个端点都在矩形内部: 这种情况比较简单,只需要判断线段的两个端点是否都在矩形内部即可。可以通过比较端点的坐标与矩形的边界坐标来实现。如果两个端点都在矩形内部,则线段矩形相交。 2. 线段的两个端点不都在矩形内部: 这种情况稍微复杂一些,需要判断线段是否矩形的四条边相交。可以将矩形的四条边分别表示成直线方程,然后判断线段是否与这些直线相交。如果线段矩形的任意一条边相交,则线段矩形相交。 下面是一段示例代码,演示了如何判断线段矩形相交: ```c++ #include <iostream> using namespace std; struct Point { double x, y; }; struct Segment { Point start, end; }; struct Rectangle { Point leftTop, rightBottom; }; // 计算两点间的距离 double distance(Point p1, Point p2) { double dx = p1.x - p2.x; double dy = p1.y - p2.y; return sqrt(dx * dx + dy * dy); } // 判断是否矩形内部 bool inRectangle(Point p, Rectangle rect) { return p.x >= rect.leftTop.x && p.x <= rect.rightBottom.x && p.y >= rect.leftTop.y && p.y <= rect.rightBottom.y; } // 判断线段是否矩形相交 bool isIntersect(Segment seg, Rectangle rect) { // 判断线段两个端点是否都在矩形内部 if (inRectangle(seg.start, rect) && inRectangle(seg.end, rect)) { return true; } // 判断线段是否矩形的四条边相交 Point p1 = rect.leftTop; Point p2 = {rect.rightBottom.x, rect.leftTop.y}; Point p3 = rect.rightBottom; Point p4 = {rect.leftTop.x, rect.rightBottom.y}; Segment edge1 = {p1, p2}; Segment edge2 = {p2, p3}; Segment edge3 = {p3, p4}; Segment edge4 = {p4, p1}; Segment edges[] = {edge1, edge2, edge3, edge4}; for (int i = 0; i < 4; i++) { Segment edge = edges[i]; // 判断线段是否与边相交 double d1 = (seg.end.x - seg.start.x) * (edge.start.y - seg.start.y) - (seg.end.y - seg.start.y) * (edge.start.x - seg.start.x); double d2 = (seg.end.x - seg.start.x) * (edge.end.y - seg.start.y) - (seg.end.y - seg.start.y) * (edge.end.x - seg.start.x); if (d1 * d2 <= 0) { double d3 = (edge.end.x - edge.start.x) * (seg.start.y - edge.start.y) - (edge.end.y - edge.start.y) * (seg.start.x - edge.start.x); double d4 = (edge.end.x - edge.start.x) * (seg.end.y - edge.start.y) - (edge.end.y - edge.start.y) * (seg.end.x - edge.start.x); if (d3 * d4 <= 0) { return true; } } } return false; } int main() { Segment seg = {{1, 1}, {3, 3}}; Rectangle rect = {{2, 2}, {4, 4}}; if (isIntersect(seg, rect)) { cout << "线段矩形相交" << endl; } else { cout << "线段矩形相交" << endl; } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值