C#中GraphicsPath.IsVisible()判断多边形内点返回结果异常问题
问题根因
你的判定结果不稳定是写法错误导致的:
- 你把
graphicsPath.AddPolygon(polygon)写在了Paint事件内部,每次窗体重绘(最小化还原、窗口移动、遮挡后恢复都会触发Paint),都会往同一个GraphicsPath实例里重复追加一个完全重合的正方形,从来没有清空过路径历史。- 首次触发Paint时,路径里只有1个正方形,
IsVisible判定(10,10)结果正常 - 第二次重绘时路径里叠加了第二个重合正方形,
GraphicsPath默认填充模式是FillMode.Alternate,偶数层的重叠区域会被判定为路径外部,同坐标就会返回"不在内部" - 后续每次重绘都会多叠加一层多边形,判定结果会随重绘次数来回跳变,完全不可预期
- 首次触发Paint时,路径里只有1个正方形,
- 你把
e.Graphics赋值给了类级别的全局变量g,这个对象仅在本次Paint执行周期内有效,缓存后也会引发绘制、判定相关的异常。 - 额外逻辑缺陷:你只检测矩形左上角点,就算路径逻辑正确,也只能证明左上角在多边形内,无法证明整个矩形都处于多边形内部。
修复方法
- 把固定多边形的初始化逻辑移到Paint事件外,比如窗体构造函数里一次性创建,不要在每次重绘时重复往路径里加图形。如果确实需要动态修改路径,添加新图形前必须先调用
graphicsPath.Reset()清空原有内容。 - 不要缓存Paint事件传入的
Graphics对象,每次Paint直接使用e.Graphics做绘制即可。 - 要判断整个矩形是否在多边形内部,直接调用
IsVisible的矩形参数重载,不要只判断单个角点。
修正后的核心代码如下:
private readonly GraphicsPath graphicsPath = new GraphicsPath(); // 矩形坐标变量,由鼠标事件更新 private int x = 10, y = 10; public Form1() { InitializeComponent(); // 一次性初始化多边形路径,不要放在Paint里重复添加 Point[] points = new Point[] { new Point(0, 0), new Point(50, 0), new Point(50, 50), new Point(0, 50), }; graphicsPath.AddPolygon(points); } private void Form1_Paint(object sender, PaintEventArgs e) { // 直接用事件传入的Graphics,不要缓存到全局变量 Graphics g = e.Graphics; Rectangle rect = new Rectangle(new Point(x, y), new Size(30,30)); g.FillRectangle(Brushes.Green, rect); g.DrawPolygon(Pens.Black, graphicsPath.PathPoints); // 直接判定整个矩形是否在路径可见区域内 if (graphicsPath.IsVisible(rect)) { this.Text = "矩形在多边形内部 " + rect.Location; } else { this.Text = "矩形不在多边形内部 " + rect.Location; } } // 记得释放非托管资源 protected override void OnFormClosed(FormClosedEventArgs e) { graphicsPath.Dispose(); base.OnFormClosed(e); }
注意:如果你的多边形是会动态变化的,必须在添加新图形前调用
graphicsPath.Reset()清空旧路径,否则还是会出现路径累积导致的判定错误。
内容的提问来源于stack exchange,提问作者fuvaji
相关产品推荐
相关产品推荐

