You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中如何将GraphicsPath转换为单个多边形以适配FillPolygon?

解决SVG路径转FillPolygon的异常问题

问题根源

直接使用GraphicsPath.PathPoints调用FillPolygon异常的核心原因有两个:

  1. 曲线点干扰:SVG路径常包含贝塞尔曲线、圆弧等曲线段,PathPoints会包含这些曲线的控制点,而非构成多边形的直线顶点,直接使用会导致形状错误或参数异常。
  2. 多子路径冲突:单个SVG路径可能包含多个独立的子路径(比如多个闭合图形),FillPolygon仅支持单一闭合直线多边形的点集,混合多个子路径的点会引发逻辑错误。

解决方案

需要先将路径曲线转成直线段,再拆分每个子路径的点集,分别调用FillPolygon:

步骤1:展平曲线为直线段

使用GraphicsPath.Flatten()方法,将所有曲线段近似转换为连续的直线段,此时PathPoints中的点都是直线顶点。

步骤2:拆分独立子路径

通过PathTypes标记,拆分出每个子路径的点集,确保每个点集对应一个独立的多边形。

完整代码示例

if (obj is SvgPath o)
{
    var graphicsPath = new GraphicsPath();
    var start = PointF.Empty;
    foreach (var segment in o.PathData)
    {
        start = segment.AddToPath(graphicsPath, start, o.PathData);
    }

    // 1. 将曲线展平为直线段,消除控制点干扰
    graphicsPath.Flatten();

    // 2. 拆分每个子路径的点集
    List<List<PointF>> subPathPoints = new List<List<PointF>>();
    List<PointF> currentPoints = new List<PointF>();

    for (int i = 0; i < graphicsPath.PathPoints.Length; i++)
    {
        currentPoints.Add(graphicsPath.PathPoints[i]);

        // 判断当前点是否为子路径结束点
        bool isEndOfSubpath = ((graphicsPath.PathTypes[i] & PathPointType.CloseSubpath) != 0) 
                              || (i == graphicsPath.PathPoints.Length - 1)
                              || (i + 1 < graphicsPath.PathPoints.Length && (graphicsPath.PathTypes[i + 1] & PathPointType.Start) != 0);

        if (isEndOfSubpath)
        {
            // 确保子路径闭合(FillPolygon需要闭合多边形)
            if (currentPoints.Count > 1 && !currentPoints.First().Equals(currentPoints.Last()))
            {
                currentPoints.Add(currentPoints.First());
            }

            // 仅保留有效多边形(至少3个点)
            if (currentPoints.Count >= 3)
            {
                subPathPoints.Add(currentPoints);
            }
            currentPoints = new List<PointF>();
        }
    }

    // 3. 逐个填充每个子路径对应的多边形
    foreach (var points in subPathPoints)
    {
        g.FillPolygon(Brushes.Black, points.ToArray());
    }
}

关键细节说明

  • Flatten参数:Flatten()可传入精度参数(比如graphicsPath.Flatten(new Matrix(), 0.1f)),数值越小近似精度越高,但生成的点越多。
  • 子路径闭合:如果原SVG路径是开放的,手动添加起点到末尾可确保FillPolygon填充符合预期(FillPolygon默认会自动闭合,但手动闭合更可控)。
  • 点数量校验:多边形至少需要3个顶点,否则FillPolygon会抛出异常,代码中加入了判断避免报错。

内容的提问来源于stack exchange,提问作者Suresh Mandala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 22:05:41