N点渐变画笔多边形填充

N-point gradient brush polygon fill

是否可以填充一个 N 边形,例如一个 4 点多边形,每个点都有不同的颜色,并使用 GDI+ 进行颜色混合?我正在寻找这样的东西:

但对于 4 点形状。

在尝试了 Hans 使用路径填充的想法后,我认为这实际上是解决这个问题的最佳方法。

然而,GraphicsPathClipping 和边界矩形都没有被使用。相反,我们使用一个带有点数组的特殊重载;这些点与 PathGradientBrushSurroundColors 属性 匹配;这样颜色就不会像往常一样径向变化,而是固定在角点上..

这里有六个例子:

颜色列表并非完全取自光谱:

List<Color> colors = new List<Color>()
    { Color.Blue, Color.Lime, Color.Red, Color.Magenta , Color.MediumOrchid,
      Color.MediumSeaGreen, Color.LightSeaGreen, Color.LightSteelBlue, Color.DarkCyan};

我用一个简单的结构来保存一个 Point 和一个 Color:

struct cPoint
{
    public Point pt; 
    public Color col;
    public cPoint(int x, int y, Color c)
    { pt = new Point(x,y); col = c;}
}

我的表格有一个 PictureBox 和一个 NumericUpDown。 NuD 调用 pictureBox.Paint:

private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
    pictureBox1.Invalidate();
}

..调用两个函数:

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    points = getPolyList(colors.Take( (int) numericUpDown1.Value).ToList(),
                         pictureBox2.ClientSize);
    DrawPolyGradient(e.Graphics, points, pictureBox2.ClientRectangle);
}

cPoints 的列表是用简单的三角函数创建的,它适用于正多边形:

List<cPoint> getPolyList(List<Color> colors, Size size)
{
    int number = colors.Count;
    List<cPoint> cPoints = new List<cPoint>();

    int x2 = size.Width / 2;
    int y2 = size.Height / 2;

    for (int i = 0; i < number; i++)
    {
        double a = Math.PI / 180f * (i * 360d / number - 90);
        int x = x2 + (int)( Math.Cos(a) * (x2 - 15)); // don't overdraw
        int y = y2 + (int)( Math.Sin(a) * (x2 - 15)); // don't overdraw
        cPoints.Add(new cPoint(x, y, colors[i]));
    }
    return cPoints;
}

绘图代码在其自身的函数中:

void DrawPolyGradient(Graphics G,  List<cPoint> cPoints, Rectangle bounds)
{
    int r = 0; int g = 0; int b = 0; int c = cPoints.Count;
    foreach (Color col in cPoints.Select(x => x.col))
    { r += col.R; g += col.G; b += col.B; }
    Color centercolor = Color.FromArgb(r / c, r / c, r / c);

    PathGradientBrush brush = new PathGradientBrush(cPoints.Select(x => x.pt).ToArray());

    brush.CenterPoint = new PointF(bounds.Width / 2, bounds.Height / 2);
    brush.CenterColor = centercolor;

    brush.SurroundColors = cPoints.Select(x => x.col).ToArray();

    G.FillRectangle(brush, bounds);
}
  • 首先计算 CenterColor
  • 并设置 CenterPoint
  • 接下来它使用 overload 创建一个特殊的 PathGradientBrush,它不采用 GraphicsPath 而采用 Point 数组!

  • 这些点会对应到画笔的SurroundColors

尤其是我的第一个想法是用简单的 LinearGradientBrush 连接沿边缘的点,无法产生更大的数字。许多这些线会错过中间角落的影响。

无法添加评论,因此对@TaW 解决方案添加了一个小修复:

Color centercolor = Color.FromArgb(r / c, r / c, r / c);

应该是

Color centercolor = Color.FromArgb(r / c, g / c, b / c);