algorithm - Generating a pixel-based spiral gradient
问题描述
I have a program that creates pixel-based gradients (meaning it calculates the step in the gradient for each pixel, then calculates the colour at that step, then gives the pixel that colour).
I'd like to implement spiral gradients (such as below).
My program can create conic gradients (as below), where each pixel is assigned a step in the gradient according to the angle between it and the midpoint (effectively mapping the midpoint-pixel angle [0...2PI] to [0...1]).
It would seem to me that a spiral gradient is a conic gradient with some additional function applied to it, where the gradient step for a given pixel depends not only on the angle, but on some additional non-linear function applied to the euclidean distance between the midpoint and pixel.
I envisage that a solution would take the original (x, y)
pixel coordinate and displace it by some amounts in the x and y axes resulting in a new coordinate (x2, y2)
. Then, for each pixel, I'd simply calculate the angle between the midPoint and its new displaced coordinate (x2, y2)
and use this angle as the gradient step for that pixel. But it's this displacement function that I need help with... of course, there may be other, better ways.
Below is a simple white-to-black conic gradient. I show how I imagine the displacement would work, but its the specifics about this function (the non-linearity), that I'm unable to implement.
My code for conic gradient:
public void conicGradient(Gradient gradient, PVector midPoint, float angle) {
float rise, run;
double t = 0;
for (int y = 0, x; y < imageHeight; ++y) {
rise = midPoint.y - y;
run = midPoint.x;
for (x = 0; x < imageWidth; ++x) {
t = Functions.fastAtan2(rise, run) + Math.PI - angle;
// Ensure a positive value if angle is negative.
t = Functions.floorMod(t, PConstants.TWO_PI);
// Divide by TWO_PI to get value in range 0...1
step = t *= INV_TWO_PI;
pixels[imageWidth * y + x] = gradient.ColorAt(step); // pixels is 1D pixel array
run -= 1;
}
}
}
解决方案
By eye, it looks like after t = ... fastAtan2...
, you just need:
t += PConstants.TWO_PI * Math.sqrt( (rise*rise + run*run) / (imageWidth * imageWidth + imageHeight * imageHeight) )
This just adds the distance from the center to the angle, with appropriate scaling.
推荐阅读
- django - 使用模板显示用户的组名
- java - Spring boot:使用 xml 的构造函数注入给出“已经有 n 个 bean 方法”
- c# - Winform中DatagridView最后添加一个空行
- python - 带有 $ 或嵌套子句的 Mongodb 聚合
- ios - 离线卫星地图在 iOS 上加载太慢
- expression - 结果始终基于修复列 qlikview 表达式
- python - 使用python快速插入(冲突)许多行到postges-DB
- angular - 将自定义组件库中的数据注入其服务
- java - Java Socket 监听 PHP 客户端不工作
- python - 使用 networkx.algorithms.approximation.steinertree.steiner_tree 提取 Steiner 树时出错