joh*_*hnc 7 .net geometry intersection
我在Winform上的两个对象之间绘制了一个箭头.
确定我的鼠标当前是否在此行上方或附近悬停的最简单方法是什么.
我已经考虑过测试鼠标点是否与由两个点定义和外推的正方形相交,但是只有当这两个点具有非常相似的x或y值时,这才是可行的.
我也在想,这个问题可能更多地出现在线性代数领域而不是简单的三角学领域,虽然我确实记得矩阵的简单方面,但这个问题超出了我对线性代数的认识.
另一方面,如果.NET库可以处理该功能,甚至更好.
编辑 感谢您的回答,有一些非常好的,所有值得被标记为已回答.
我选择Coincoin的答案是被接受的,因为我喜欢它可以应用于绘制的任何形状,但最终实现了Tim Robinson的方程式,因为使用简单的方程而不是新建图形路径和笔似乎更有效,如我的情况我需要在onMouseMove上进行1-n个不同的关系(显然会有一些缓存和优化,但重点仍然存在)
等式的主要问题是它似乎将线条视为无限,因此我也添加了边界测试.
对于那些感兴趣的人来说,代码(初始剪切,我可能会稍微干掉它),如下所示
if (Math.Sqrt( Math.Pow(_end.X - _start.X, 2) +
Math.Pow(_end.Y - _start.Y, 2) ) == 0)
{
_isHovering =
new RectangleF(e.X, e.Y, 1, 1).IntersectsWith(_bounds);
}
else
{
float threshold = 10.0f;
float distance = (float)Math.Abs(
( ( (_end.X - _start.X) * (_start.Y - e.Y) ) -
( (_start.X - e.X) * (_end.Y - _start.Y) ) ) /
Math.Sqrt( Math.Pow(_end.X - _start.X, 2) +
Math.Pow(_end.Y - _start.Y, 2) ));
_isHovering = (
distance <= threshold &&
new RectangleF(e.X, e.Y, 1, 1).IntersectsWith(_bounds)
);
}
Run Code Online (Sandbox Code Playgroud)
和_bounds定义为:
_bounds = new Rectangle(
Math.Min(_start.X, _end.X),
Math.Min(_start.Y, _end.Y),
Math.Abs(_start.X - _end.X), Math.Abs(_start.Y - _end.Y));
Run Code Online (Sandbox Code Playgroud)
如果您想轻松地对任意绘制的形状进行命中测试,您可以创建一个包含绘图的路径,然后使用框架函数隐藏路径并进行可见性测试.
例如,这里我们创建一个带有一行的路径:
GraphicsPath path = new GraphicsPath();
path.AddLine(x1, y1, x2, y2);
path.CloseFigure();
Run Code Online (Sandbox Code Playgroud)
然后,加宽路径并为命中测试创建一个区域:
path.Widen(new Pen(Color.Black, 3));
region = new Region(path);
Run Code Online (Sandbox Code Playgroud)
最后,命中测试:
region.IsVisible(point);
Run Code Online (Sandbox Code Playgroud)
该方法的优点是它可以很容易地扩展到样条线,箭头,弧形,馅饼或几乎任何可用GDI +绘制的东西.通过提取它可以在逻辑HitTest
和Draw
逻辑中使用相同的路径.
这是将所有内容组合在一起的代码:
public GraphicsPath Path
{
get {
GraphicsPath path = new GraphicsPath();
path.AddLine(x1, y1, x2, y2);
path.CloseFigure();
return path;
}
}
bool HitTest(Point point)
{
using(Pen new pen = Pen(Color.Black, 3))
using(GraphicsPaht path = Path)
{
path.Widen(pen);
using(Region region = new Region(path))
return region.IsVisible(point);
}
}
void Draw(Graphics graphics)
{
using(Pen pen = new Pen(Color.Blue, 0))
using(GraphicsPaht path = Path)
graphics.DrawPath(pen, path);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
202 次 |
最近记录: |