如何计算Bitmap内点a到外部点b的线段与Bitmap边界交点c的坐标
解决方案
核心问题分析
你现有代码只默认处理了线段向x轴正方向延伸碰到Bitmap右边界的场景,没有考虑左边界、上边界、下边界三种相交场景,也没有处理坐标差的符号问题,因此仅单方向有效。
通用解法:参数射线求交法
我们用参数方程描述从a点出发向b点延伸的射线,分别计算与四个边界的交点,取离a最近的有效交点即可:
- 射线参数方程:对于任意t≥0,射线上的点坐标为
- x = a.x + t * (b.x - a.x)
- y = a.y + t * (b.y - a.y)
t的大小代表点距离a点的远近,t越小越靠近a
- 分别计算射线与Bitmap四个边界相交的t值:
- 右边界(x = bm.Width):
t_xmax = (bm.Width - a.x) / (b.x - a.x) - 左边界(x = 0):
t_xmin = (0 - a.x) / (b.x - a.x) - 下边界(y = bm.Height):
t_ymax = (bm.Height - a.y) / (b.y - a.y) - 上边界(y = 0):
t_ymin = (0 - a.y) / (b.y - a.y)
- 右边界(x = bm.Width):
- 筛选所有t>0的有效值(t≤0代表交点在a点背向b的一侧,无效),取最小的t值代入参数方程,得到的就是线段ab与Bitmap边界的交点c
完整实现代码
// 定义点结构,可替换为你项目中的PointF类型 (double x, double y) a = ...; // 内部点 (double x, double y) b = ...; // 外部点 Bitmap bm = ...; List<double> validTs = new List<double>(); // 计算和左右边界的交t double dx = b.x - a.x; if (Math.Abs(dx) > 1e-6) // 避免除以0,兼容完全垂直的线段 { double tXmax = (bm.Width - a.x) / dx; if (tXmax > 0) validTs.Add(tXmax); double tXmin = (0 - a.x) / dx; if (tXmin > 0) validTs.Add(tXmin); } // 计算和上下边界的交t double dy = b.y - a.y; if (Math.Abs(dy) > 1e-6) // 避免除以0,兼容完全水平的线段 { double tYmax = (bm.Height - a.y) / dy; if (tYmax > 0) validTs.Add(tYmax); double tYmin = (0 - a.y) / dy; if (tYmin > 0) validTs.Add(tYmin); } // 取最小的有效t,就是最近的交点 double minT = validTs.Min(); (double x, double y) c = (a.x + minT * dx, a.y + minT * dy); // 绘制线段 using (Graphics g = Graphics.FromImage(bm)) { g.DrawLine(new Pen(Color.Gray), (float)a.x, (float)a.y, (float)c.x, (float)c.y); }
内容的提问来源于stack exchange,提问作者MusicGrotesque TV
相关产品推荐
相关产品推荐

