特定区域怎么画

How to paint a certain area

我不熟悉用 c# 绘图和绘画,我正在尝试制作一个简单的程序,它有 3 个相交的圆圈 (A、B、C)。我想做的是画一个(根据我得到的结果)。

例如:如果结果是1我想填充黄色边框区域,如果我得到4我想填充绿色边框区域等等。

我绘制这些圆圈的代码:

private void button1_Click(object sender, EventArgs e)
    {
        Graphics A = this.CreateGraphics();
        Graphics B = this.CreateGraphics();
        Graphics C = this.CreateGraphics();
        Pen Bluepen = new Pen(Color.Blue, 2);
        Pen RedPen = new Pen(Color.Red, 2);
        Pen BlackPen = new Pen(Color.Black, 2);
        A.DrawEllipse(Bluepen,100, 100, 150, 150);
        B.DrawEllipse(RedPen, 195, 100, 150, 150);
        C.DrawEllipse(BlackPen, 145, 190, 150, 150);
    }

由于你是这个话题的新手,我必须告诉你:这比人们希望的要难得多。

想到了三种解决方案:

  • 构造一个 GraphicsPath,你可以从三个 Arcs 中填充。要计算圆弧,您需要拥有的矩形,还需要扫描角和起始角。这需要相当多的数学运算..

  • 绘制成 Bitmap 后,您可以填充要着色的区域。这仅适用于您可以从中提取每个像素的当前颜色的位图,不适用于在控件上绘制..

  • 最简单的方法还是有点复杂,但只是轻微的

方案三(创建区域并填充)

您可以使用各种集合操作 来组合称为Regions 的区域。您可以从 GraphicsPath 构建 Region。你可以通过添加一个椭圆来构造一个GraphicsPath。你可以剪辑一个Graphics对象的绘图区域到Region

让我们试试:

private void panel1_Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    g.SmoothingMode = SmoothingMode.AntiAlias;

    Rectangle r1 = new Rectangle(100, 100, 150, 150);
    Rectangle r2 = new Rectangle(195, 100, 150, 150);
    Rectangle r3 = new Rectangle(145, 190, 150, 150);
    GraphicsPath gp1 = new GraphicsPath();
    GraphicsPath gp2 = new GraphicsPath();
    GraphicsPath gp3 = new GraphicsPath();
    gp1.AddEllipse(r1);
    gp2.AddEllipse(r2);
    gp3.AddEllipse(r3);
    Region r_1 = new Region(gp1);
    Region r_2 = new Region(gp2);
    Region r_3 = new Region(gp3);

    r_1.Intersect(r_2);   // just two of five..
    r_1.Exclude(r_3);     // set operations supported!

    g.SetClip(r_1, CombineMode.Replace);
    g.Clear(Color.Magenta);    // fill the remaining region
    g.ResetClip();

    g.DrawEllipse(Pens.Red, r1);
    g.DrawEllipse(Pens.Blue, r2);
    g.DrawEllipse(Pens.Green, r3);

   // finally dispose of all Regions and GraphicsPaths!!
    r_1.Dispose();
    gp1.Dispose();
    .....

}

请注意区域操作会改变当前区域;如果你想填充更多的区域,你需要恢复更改的区域!

另请注意,我在任何 persistent 绘图所属的位置进行绘制:在 Paint 事件中并且我使用其 e.Graphics 对象..

GraphicsPaths 因为 Regions 是 GDI 对象,应该被处理掉!


解决方案 1 的注释(通过数学创建 GraphicsPath)

整个数学相当复杂。通过做一些假设,任务可以大大简化:让我们假设圆圈的大小相同。此外,我们首先只看两个圆圈,具有相同的 y 位置。最后,圆圈形成对称图形。 (顺便说一句,他们没有:红色圆圈应该有 x=190,绿色圆圈应该有 y=186,45..)

获取两个交点以及扫角并不难。

接下来可以使用Matrix将两个点绕整个图形的中心旋转120°;有关示例,请参见 。现在我们有六点;我们仍然需要更小的后掠角,这也是通过简单的数学计算得到的。

终于可以把12条弧线全部构造成12(!)GraphicsPaths,随意组合。

好的部分是我们既可以填充也可以绘制这些路径。但是,代码相当广泛..


关于解决方案 2(floodfill)的注释

虽然您不能直接在控件上进行填充,但您可以在位图中准备结果,然后使用 Graphics.DrawImage 在控件上显示该图像。

有关填充填充代码的示例,请参阅