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

如何在C# Bitmap中高效创建带镂空的圆形图形?

大量圆形布尔运算(基底减多圆)的性能优化问题

我正在开发一个程序,需要生成大量圆形(最少10个,支持指数级扩展),核心逻辑是:以一个圆形为基底,其余圆形均从基底中「减去」,最终效果类似边缘被咬过的饼干。

当前实现中,我用Vector2数组或List定义每个圆形的区域与周长,再找出基底圆形和待减圆形区域中匹配的向量并从基底移除。当圆形数量在100、甚至1000以内时速度尚可,但达到10000个时速度极慢(需数分钟),数量更多时甚至要数小时。


当前核心实现代码

周长定义方法

public override void DefinePerimeter()
{
    perimeter = new List<Vector2>();

    // 计算一个象限的周长点,通过镜像得到完整圆形
    for(float i = 0; i < 90; i += resolutionFactor)
    {
        float cos = radius * MathF.Cos(i);
        float sin = radius * MathF.Sin(i);

        perimeter.Add(new Vector2((int)(center.X + cos), (int)(center.Y - sin)));
        perimeter.Add(new Vector2((int)(center.X - cos), (int)(center.Y - sin)));
        perimeter.Add(new Vector2((int)(center.X - cos), (int)(center.Y + sin)));
        perimeter.Add(new Vector2((int)(center.X + cos), (int)(center.Y + sin)));
    }
    perimeter = RemoveDuplicates(perimeter); // 移除重复的Vector2
}

区域定义方法

if (perimeterDefined == true && perimeter.Count>1)
{
    Vector2 yBounds = Bounding.GetYBounds(perimeter);
    if(yBounds.Y-yBounds.X>0)
    {
        List<Vector2> yLevel = new List<Vector2>();
        for (int i = (int)yBounds.X; i < (int)yBounds.Y; i++)
        {
            yLevel.Clear();
            yLevel = perimeter.FindAll(x => x.Y == i);
            // 备注:原本想把周长和区域定义合并成一个方法
            // DefinePerimeter已经能找到每个y层级的边界,只需在循环中添加中间区域即可
            if (yLevel.Count > 0)
            {
                Vector2 xBounds = Bounding.GetXBounds(yLevel);
                for (int j = (int)xBounds.X; j < (int)xBounds.Y; j++)
                {
                    area.Add(new Vector2(j, i));
                }
            }
        }
        areaDefined = true;
    }
    else if(yBounds.Y-yBounds.X==0)
    {
        area.Add(new Vector2(yBounds.Y, yBounds.Y));
    }
}
else if (perimeterDefined == true && perimeter.Count == 1)
{
    area.Add(perimeter[0]);
}
else
{
    Console.WriteLine("Error: Perimeter not defined!");
}

边界计算方法

GetXBounds逻辑与GetYBounds一致,仅需将x和y互换:

public static Vector2 GetYBounds(List<Vector2> range)
{
        return new Vector2(range.Min(x => (int)x.Y), range.Max(x => (int)x.Y));
}

性能瓶颈与尝试过的优化

目前区域定义的性能开销极大。我曾尝试过一种优化思路:不生成完整区域,仅通过待减圆形的半径和位置,直接计算基底区域中需要移除的Vector2,但速度提升并不明显。

希望能得到针对性的性能优化建议,若有细节需要补充请告知!

谢谢!:)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 15:44:57