N点渐变画笔多边形填充
N-point gradient brush polygon fill
是否可以填充一个 N 边形,例如一个 4 点多边形,每个点都有不同的颜色,并使用 GDI+ 进行颜色混合?我正在寻找这样的东西:
但对于 4 点形状。
在尝试了 Hans 使用路径填充的想法后,我认为这实际上是解决这个问题的最佳方法。
然而,GraphicsPath
、Clipping
和边界矩形都没有被使用。相反,我们使用一个带有点数组的特殊重载;这些点与 PathGradientBrush
的 SurroundColors
属性 匹配;这样颜色就不会像往常一样径向变化,而是固定在角点上..
这里有六个例子:
颜色列表并非完全取自光谱:
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);
是否可以填充一个 N 边形,例如一个 4 点多边形,每个点都有不同的颜色,并使用 GDI+ 进行颜色混合?我正在寻找这样的东西:
但对于 4 点形状。
在尝试了 Hans 使用路径填充的想法后,我认为这实际上是解决这个问题的最佳方法。
然而,GraphicsPath
、Clipping
和边界矩形都没有被使用。相反,我们使用一个带有点数组的特殊重载;这些点与 PathGradientBrush
的 SurroundColors
属性 匹配;这样颜色就不会像往常一样径向变化,而是固定在角点上..
这里有六个例子:
颜色列表并非完全取自光谱:
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);