如何绘制特定区域

Dan*_*med 3 .net c# graphics gdi+ paint

我是 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);
    }
Run Code Online (Sandbox Code Playgroud)

TaW*_*TaW 5

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

想到了三个解决方案:

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

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

  • 最简单的方法它仍然有点复杂,但只是温和的

解决方案3(创建一个区域并填充它)

您可以使用各种集合操作来组合称为 的区域Regions。您可以Region从 a构造a GraphicsPath。你可以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();
    .....

}
Run Code Online (Sandbox Code Playgroud)

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

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

GraphicsPaths和RegionsGDI 对象一样,应该丢弃!


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

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

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

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

最后,我们可以GraphicsPaths从 12 个弧中构造所有 12 个 (!)并随意组合它们。

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


解决方案 2(溢流)的注意事项

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

有关编写洪水填充的示例,请参阅这篇文章!