我正在开发一个使用 Juce 库来显示图形的项目。到目前为止,我一直在使用该库的 API 函数来生成线性和径向渐变,但这是该库支持的仅有的两种类型的渐变。我现在需要生成一种不同类型的渐变,一种遵循正凸多边形的形状。这里的关键词是 REGULAR,意思是一个多边形,所有边的长度相同,所有顶点都位于一个圆上。
对于五边形的情况,这里有一张图片可以更好地显示我想要得到的结果: http ://www.filterforge.com/wiki/index.php/Polygonal_Gradient
对于我的应用程序,我希望能够指定具有任意数量边的多边形渐变。(五边形、六边形、八边形等……)
鉴于 API 的限制,我可以产生所需结果的唯一方法是逐像素填充表面矩阵,以数学方式计算每个像素的 R、G、B、A 分量的值。
这是我到目前为止的代码:
void render_surface(unsigned char *surface_data,
int width, int height, int linestride,
int num_vertices, t_rgba *color1, t_rgba *color2)
{
const double center_x = 0.5 * width;
const double center_y = 0.5 * height;
const double radius = 0.5 * MIN(width, height);
int x, y;
for (y = height; --y >= 0;) {
uint32_t *line = (uint32_t *)data;
data += linestride;
const double dy = y - center_y;
for (x = width; --x >= 0;) {
const double dx = x - center_x;
double rho = hypot(dx, dy);
rho /= radius; // normalize radius
// constrain
rho = CLIP(rho, 0.0, 1.0);
// interpolate
double a = color2->alpha + (color1->alpha - color2->alpha) * rho;
double r = color2->red + (color1->red - color2->red ) * rho;
double g = color2->green + (color1->green - color2->green) * rho;
double b = color2->blue + (color1->blue - color2->blue ) * rho;
// premultiply alpha
r *= a;
g *= a;
b *= a;
#if LITTLE_ENDIAN
*line++ = ((unsigned int)((256.0 * (1.0 - DBL_EPSILON)) * a) << 24) // alpha
| ((unsigned int)((256.0 * (1.0 - DBL_EPSILON)) * r) << 16) // red
| ((unsigned int)((256.0 * (1.0 - DBL_EPSILON)) * g) << 8) // green
| (unsigned int)((256.0 * (1.0 - DBL_EPSILON)) * b); // blue
#else
*line++ = ((unsigned int)((256.0 * (1.0 - DBL_EPSILON)) * b) << 24) // blue
| ((unsigned int)((256.0 * (1.0 - DBL_EPSILON)) * g) << 16) // green
| ((unsigned int)((256.0 * (1.0 - DBL_EPSILON)) * r) << 8) // red
| (unsigned int)((256.0 * (1.0 - DBL_EPSILON)) * a); // alpha
#endif
}
}
}
上面的代码产生了一个径向渐变,与我使用一个 API 函数可以产生的渐变类型相同。然而,这似乎是解决问题的一个很好的起点。
surface_data - 是一个 8 位值矩阵,表示红色、绿色、蓝色和 Alpha 分量的像素强度。
num_vertices - 是我们希望多边形渐变具有的顶点数(在单个圆上等距分布)。
color1 - 渐变的起始颜色。
color2 - 渐变的结束颜色。
我想知道如何以相同的方式填充表面,创建多边形渐变而不是径向渐变。
谢谢你的帮助。
- 路易吉
稍微重新考虑一下这个问题......如果我们将坐标系的原点视为多边形的中心,归结为找到一个方程,使得对于笛卡尔坐标中的任何输入点,输出是到最近的距离多边形的一侧。
我的直觉告诉我,一定有某种封闭形式的解决方案,因为:
对于一个圆圈,
rho = sqrt(dx*dx + dy*dy);
给我们到圆心的径向距离,可以将其视为具有无限边的多边形。
对于一个正方形,
fmax(fabs(dx), fabs(dy));
给我们距离正方形最近边的切比雪夫距离,可以将其视为具有 4 个边的多边形。
所以,我认为这两个公式的某种组合应该给出中间案例,这将解决最初的问题。
我完全不按照这些思路思考吗?
- 路易吉