1)我有一个线段列表(由它们的两个端点和一个宽度定义。)
2)这些线段在面板中绘制
3)当我的鼠标移动(Panel.MouseMove事件)时,我循环遍历线段列表
4)Foreach:
gPath.Reset();
Pen Pen = new Pen(Color.White, 20);
gPath.AddLine(P1, P2);
return gPath.IsOutlineVisible(cursorPos, Pen);
5)如果我变为真,那么我知道我的光标悬停在当前线段上。
这适用于约300行左右。当我达到1,000时,我的程序会慢慢停止(分析显示它是由IsOutlineVisible引起的)。那么,有什么方法可以提高我的命中测试算法的性能吗?我不知道IsOutlineVisible的效率如何,所以我不想实现该方法已经使用的任何优化。有什么想法吗?
修改
在深入研究我的数据后,我注意到一些线条非常大。例如:
endpoint1 =(16000,-16000)
endpoint2 =(5041448,-32868734)
(是的,其中一个坐标是负数千万......)
我验证了对一个这样的线段的命中测试足以让我的程序暂停,(IsOutlineVisible需要2-3秒才能完成测试,并且只要光标移动就会运行测试......)
我应该在发布之前对此进行更彻底的测试。感谢所有响应(如果我最终处理数千行,那么2d空间索引是一个很好的建议)。
P.S。如果有人知道为什么一个大的线段对于IsOutlineVisible来说是个大问题,那就太棒了。
答案 0 :(得分:0)
试试这个:
public Line GetHotSpottedLine(Point mousePos){
var line = lines.Where(line =>
{
Point p1 = new Point(Math.Min(line.P1.X, line.P2.X), Math.Min(line.P1.Y, line.P2.Y));
Point p2 = new Point(Math.Max(line.P1.X, line.P2.X), Math.Max(line.P1.Y, line.P2.Y));
return mousePos.X >= p1.X && mousePos.X <= p2.X && mousePos.Y >= p1.Y && mousePos.Y <= p2.Y;
}).FirstOrDefault(line => {
using (GraphicsPath gp = new GraphicsPath())
{
gp.AddLine(line.P1, line.P2);
//You can declare your pen outside and this pen should be used to draw your lines.
using (Pen p = new Pen(Color.Red, 20))
{
return gp.IsOutlineVisible(mousePos, p);
}
}
});
return line;
}
public class Line{
public Point P1 { get; set; }
public Point P2 { get; set; }
}
List<Line> lines = new List<Line>();
这取决于您希望如何使用lines
,如果您想要绘制它们,我们必须注意drawing
而非detecting the hovered line
的效果,在这种情况下是,{ {1}}是你的问题。我想我们可以在这里使用一些drawing
。无论如何,我测试了Thread
行,它可以正常工作(在1000
中绘制所有行)而不使用任何线程。
答案 1 :(得分:0)
IsOutlineVisible调用Gdi +,可能会减慢它的速度。
public bool GraphicsPath.IsOutlineVisible(PointF pt, Pen pen, Graphics graphics)
{
int num;
if (pen == null)
{
throw new ArgumentNullException("pen");
}
int status = SafeNativeMethods.Gdip.GdipIsOutlineVisiblePathPoint(new HandleRef(this, this.nativePath), pt.X, pt.Y, new HandleRef(pen, pen.NativePen), new HandleRef(graphics, (graphics != null) ? graphics.NativeGraphics : IntPtr.Zero), out num);
if (status != 0)
{
throw SafeNativeMethods.Gdip.StatusException(status);
}
return (num != 0);
}
除此之外,这些命中测试不使用优化,例如构建所有使用的图形元素的索引。为了提高性能,我会尝试