如何合并带Z序效果的自相交GraphicsPath为单个图形对象?
实现带Z序视觉效果的单GraphicsPath自相交图形
需要创建具有Z序视觉效果的带边框自相交图形:后绘制的路径覆盖前路径的重叠区域,且两个路径各自保留完整边框。当前分开绘制两个GraphicsPath可实现预期效果,但合并为单个路径后,填充和边框均不符合需求。
现有实现(分开绘制,效果正确)
private void Example1(PaintEventArgs e) { Brush brush = new SolidBrush(Color.FromArgb(200, Color.LightBlue)); GraphicsPath path1 = new GraphicsPath(FillMode.Winding); path1.AddLines(new Point[] { new Point(400, 200), new Point(400, 300), new Point(100, 300), new Point(100, 400), new Point(500, 400), new Point(500, 100) }); e.Graphics.FillPath(brush, path1); e.Graphics.DrawPath(Pens.Blue, path1); GraphicsPath path2 = new GraphicsPath(FillMode.Winding); path2.AddLines(new Point[] { new Point(500, 100), new Point(200, 100), new Point(200, 500), new Point(300, 500), new Point(300, 200), new Point(400, 200) }); e.Graphics.FillPath(brush, path2); e.Graphics.DrawPath(Pens.Blue, path2); }
合并路径后的问题(效果不符合预期)
合并路径后,系统会按FillMode规则计算整体填充区域,边框也会变成整个路径的外轮廓,丢失了两个路径的独立边框和Z序覆盖效果:
private void Example2(PaintEventArgs e) { Brush brush = new SolidBrush(Color.FromArgb(200, Color.LightBlue)); GraphicsPath path1 = new GraphicsPath(FillMode.Winding); path1.AddLines(new Point[] { new Point(400, 200), new Point(400, 300), new Point(100, 300), new Point(100, 400), new Point(500, 400), new Point(500, 100) }); GraphicsPath path2 = new GraphicsPath(FillMode.Winding); path2.AddLines(new Point[] { new Point(500, 100), new Point(200, 100), new Point(200, 500), new Point(300, 500), new Point(300, 200), new Point(400, 200) }); path1.AddPath(path2, true); e.Graphics.FillPath(brush, path1); e.Graphics.DrawPath(Pens.Blue, path1); }
简便解决方案:单个GraphicsPath+子路径遍历绘制
将两个路径作为独立子路径存入单个GraphicsPath,绘制时遍历每个子路径分别填充和描边,既保留单个对象的可操作性(统一变换),又还原分开绘制的视觉效果:
步骤1:封装遍历绘制方法
public static void DrawPathWithZOrder(Graphics g, Brush brush, Pen pen, GraphicsPath path) { using (GraphicsPathIterator iterator = new GraphicsPathIterator(path)) { using (GraphicsPath subPath = new GraphicsPath()) { bool isClosed; while (iterator.NextSubpath(subPath, out isClosed)) { g.FillPath(brush, subPath); g.DrawPath(pen, subPath); subPath.Reset(); } } } }
步骤2:创建包含子路径的单个GraphicsPath
private void Example3(PaintEventArgs e) { Brush brush = new SolidBrush(Color.FromArgb(200, Color.LightBlue)); GraphicsPath combinedPath = new GraphicsPath(FillMode.Winding); // 添加第一个子路径 combinedPath.StartFigure(); combinedPath.AddLines(new Point[] { new Point(400, 200), new Point(400, 300), new Point(100, 300), new Point(100, 400), new Point(500, 400), new Point(500, 100) }); combinedPath.CloseFigure(); // 添加第二个子路径 combinedPath.StartFigure(); combinedPath.AddLines(new Point[] { new Point(500, 100), new Point(200, 100), new Point(200, 500), new Point(300, 500), new Point(300, 200), new Point(400, 200) }); combinedPath.CloseFigure(); // 统一变换示例(可选) e.Graphics.TranslateTransform(50, 50); // 使用自定义方法绘制,还原Z序和独立边框 DrawPathWithZOrder(e.Graphics, brush, Pens.Blue, combinedPath); }
原理说明
StartFigure()和CloseFigure()将两条路径标记为GraphicsPath中的独立子路径GraphicsPathIterator负责遍历每个子路径,分别执行填充和描边,完全复刻分开绘制的视觉效果- 单个
combinedPath可直接应用平移、缩放等变换,满足“单个图形对象处理”的需求
内容的提问来源于stack exchange,提问作者stenio
相关产品推荐
相关产品推荐

