计算不完美的圆
calculating not perfect circles
我想创建一个 "not perfect circles" 的生成器,圆圈有点扭曲且更随机,但看起来仍然有点像圆圈或云。
这就是我所说的不完美的圆:
我想创建一个函数来获取 "not perfect circle" 的最大和最小比例并获取其所有点。我知道圆的公式:
X^2+Y^2=R^2 但我想不出一种方法让它更随机一些。有人有什么想法吗?
编辑:尝试用点画一个完美的圆,但行不通:
for (int step = 0; step < 300; ++step) {
double t = step / 300 * 2 * Math.PI;
c.drawPoint(300+(float)(33 * Math.cos(t)), 300+(float)(33 * Math.sin(t)), p);
}
编辑 2:
for (int step = 0; step < 20; ++step) {
double t = step / 20.0 * 2 * Math.PI;
double imperfectR = 50.0+randInt(10, 50);
//I do it here?
points[step]=new PointF();
points[step].set((300+(float)(imperfectR * Math.cos(t))), 300+(float)(imperfectR * Math.sin(t)));
if(step==0){
pp.moveTo(points[step].x, points[step].y);
}
else
pp.quadTo(points[step-1].x, points[step-1].y,points[step].x, points[step].y);
}
编辑 3:
double t=0;
for (int i = 0; i < points.length/4; i++) {
if(t==1){
t=0;
}
t+=0.10;
double imperfectR=0.5*((2*points[i+1].y)+(-points[i].y+points[i+2].y)*t+(2*points[i].y-5*points[i+1].y+4*points[i+2].y-points[i+3].y)*(t*t)+((-points[i].y+3*points[i+1].y-3*points[i+2].y+points[i+3].y)*(t*t*t)));
newPoints[i].set((300+(float)(imperfectR * Math.cos(t))), 300+(float)(imperfectR * Math.sin(t)));
t+=0.10;
imperfectR=0.5*((2*points[i+1].y)+(-points[i].y+points[i+2].y)*t+(2*points[i].y-5*points[i+1].y+4*points[i+2].y-points[i+3].y)*(t*t)+((-points[i].y+3*points[i+1].y-3*points[i+2].y+points[i+3].y)*(t*t*t)));
newPoints[i+1].set((300+(float)(imperfectR * Math.cos(t))), 300+(float)(imperfectR * Math.sin(t)));
t+=0.10;
imperfectR=0.5*((2*points[i+1].y)+(-points[i].y+points[i+2].y)*t+(2*points[i].y-5*points[i+1].y+4*points[i+2].y-points[i+3].y)*(t*t)+((-points[i].y+3*points[i+1].y-3*points[i+2].y+points[i+3].y)*(t*t*t)));
newPoints[i+2].set((300+(float)(imperfectR * Math.cos(t))), 300+(float)(imperfectR * Math.sin(t)));
t+=0.10;
imperfectR=0.5*((2*points[i+1].y)+(-points[i].y+points[i+2].y)*t+(2*points[i].y-5*points[i+1].y+4*points[i+2].y-points[i+3].y)*(t*t)+((-points[i].y+3*points[i+1].y-3*points[i+2].y+points[i+3].y)*(t*t*t)));
newPoints[i+3].set((300+(float)(imperfectR * Math.cos(t))), 300+(float)(imperfectR * Math.sin(t)));
if(i==0){
pp.moveTo(newPoints[i].x, newPoints[i].y);
}
pp.lineTo(newPoints[i].x, newPoints[i].y);
pp.lineTo(newPoints[i+1].x, newPoints[i+1].y);
pp.lineTo(newPoints[i+2].x, newPoints[i+2].y);
pp.lineTo(newPoints[i+3].x, newPoints[i+3].y);
}
pp.close();
另一种更容易绘制的圆方程是其参数形式之一:
x = R * cos(t);
y = R * sin(t);
其中R
是公称半径,t
是0
和2 * pi
之间的参数。所以,你可以像这样在 'perfect' 圆的圆周上画点:
for (int step = 0; step < NSTEPS; ++step) {
double t = step / (double) NSTEPS * 2 * pi;
drawPoint(R * cos(t), R * sin(t));
}
您可以按照@nikis 的建议,通过在圆的半径上添加一个随机量来制作圆 'imperfect':
for (int step = 0; step < NSTEPS; ++step) {
double t = step / (double) NSTEPS * 2 * pi;
double imperfectR = R + randn(); // Normally distributed random
drawPoint(imperfectR * cos(t), imperfectR * sin(t));
}
但是,这可能会给您带来尖尖的形状,因为没有任何东西可以使 step
和 step + 1
处的半径相似。不失一般性,可以将上面的代码重写为:
for (int step = 0; step < NSTEPS; ++step) {
double t = step / (double) NSTEPS * 2 * pi;
double imperfectR = f(t);
drawPoint(imperfectR * cos(t), imperfectR * sin(t));
}
其中 f(t)
是为参数 t
生成半径的某个函数。现在,您完全可以为 t
选择任何函数,但您可能希望选择在圆上连续的函数,即没有 f(t)
突然改变值的点。
这里有很多选择。我上面建议的例子是建议使用余弦函数的总和:
double f(double t) {
double f = 0;
for (int i = 0; i < N; ++i) {
f += A[i] * cos(i * t + w[i]);
}
return f;
}
其中 A
和 w
是随机选择的值; A[0]
应设置为 R
。这里的重点是余弦函数的周期是2 * pi
,所以f(alpha) = f(alpha + 2 * pi)
,满足连续的要求。
然而,这绝不是唯一的选择。你也许可以选择像高斯核之和这样的东西,它将 'bumps' 以 w[i]
为中心,在圆周上扩展 sigma[i]
:
double f(double t) {
double f = 0;
for (int i = 0; i < N; ++i) {
f += A[i] * exp(-Math.pow(t-w[i], 2) / sigma[i]);
}
return f;
}
(这不太行,它不处理 t
的回绕)
您需要尝试一下,看看什么样的函数和什么样的随机选择值可以为您提供所需的形状。
我想创建一个 "not perfect circles" 的生成器,圆圈有点扭曲且更随机,但看起来仍然有点像圆圈或云。
这就是我所说的不完美的圆:
我想创建一个函数来获取 "not perfect circle" 的最大和最小比例并获取其所有点。我知道圆的公式: X^2+Y^2=R^2 但我想不出一种方法让它更随机一些。有人有什么想法吗?
编辑:尝试用点画一个完美的圆,但行不通:
for (int step = 0; step < 300; ++step) {
double t = step / 300 * 2 * Math.PI;
c.drawPoint(300+(float)(33 * Math.cos(t)), 300+(float)(33 * Math.sin(t)), p);
}
编辑 2:
for (int step = 0; step < 20; ++step) {
double t = step / 20.0 * 2 * Math.PI;
double imperfectR = 50.0+randInt(10, 50);
//I do it here?
points[step]=new PointF();
points[step].set((300+(float)(imperfectR * Math.cos(t))), 300+(float)(imperfectR * Math.sin(t)));
if(step==0){
pp.moveTo(points[step].x, points[step].y);
}
else
pp.quadTo(points[step-1].x, points[step-1].y,points[step].x, points[step].y);
}
编辑 3:
double t=0;
for (int i = 0; i < points.length/4; i++) {
if(t==1){
t=0;
}
t+=0.10;
double imperfectR=0.5*((2*points[i+1].y)+(-points[i].y+points[i+2].y)*t+(2*points[i].y-5*points[i+1].y+4*points[i+2].y-points[i+3].y)*(t*t)+((-points[i].y+3*points[i+1].y-3*points[i+2].y+points[i+3].y)*(t*t*t)));
newPoints[i].set((300+(float)(imperfectR * Math.cos(t))), 300+(float)(imperfectR * Math.sin(t)));
t+=0.10;
imperfectR=0.5*((2*points[i+1].y)+(-points[i].y+points[i+2].y)*t+(2*points[i].y-5*points[i+1].y+4*points[i+2].y-points[i+3].y)*(t*t)+((-points[i].y+3*points[i+1].y-3*points[i+2].y+points[i+3].y)*(t*t*t)));
newPoints[i+1].set((300+(float)(imperfectR * Math.cos(t))), 300+(float)(imperfectR * Math.sin(t)));
t+=0.10;
imperfectR=0.5*((2*points[i+1].y)+(-points[i].y+points[i+2].y)*t+(2*points[i].y-5*points[i+1].y+4*points[i+2].y-points[i+3].y)*(t*t)+((-points[i].y+3*points[i+1].y-3*points[i+2].y+points[i+3].y)*(t*t*t)));
newPoints[i+2].set((300+(float)(imperfectR * Math.cos(t))), 300+(float)(imperfectR * Math.sin(t)));
t+=0.10;
imperfectR=0.5*((2*points[i+1].y)+(-points[i].y+points[i+2].y)*t+(2*points[i].y-5*points[i+1].y+4*points[i+2].y-points[i+3].y)*(t*t)+((-points[i].y+3*points[i+1].y-3*points[i+2].y+points[i+3].y)*(t*t*t)));
newPoints[i+3].set((300+(float)(imperfectR * Math.cos(t))), 300+(float)(imperfectR * Math.sin(t)));
if(i==0){
pp.moveTo(newPoints[i].x, newPoints[i].y);
}
pp.lineTo(newPoints[i].x, newPoints[i].y);
pp.lineTo(newPoints[i+1].x, newPoints[i+1].y);
pp.lineTo(newPoints[i+2].x, newPoints[i+2].y);
pp.lineTo(newPoints[i+3].x, newPoints[i+3].y);
}
pp.close();
另一种更容易绘制的圆方程是其参数形式之一:
x = R * cos(t);
y = R * sin(t);
其中R
是公称半径,t
是0
和2 * pi
之间的参数。所以,你可以像这样在 'perfect' 圆的圆周上画点:
for (int step = 0; step < NSTEPS; ++step) {
double t = step / (double) NSTEPS * 2 * pi;
drawPoint(R * cos(t), R * sin(t));
}
您可以按照@nikis 的建议,通过在圆的半径上添加一个随机量来制作圆 'imperfect':
for (int step = 0; step < NSTEPS; ++step) {
double t = step / (double) NSTEPS * 2 * pi;
double imperfectR = R + randn(); // Normally distributed random
drawPoint(imperfectR * cos(t), imperfectR * sin(t));
}
但是,这可能会给您带来尖尖的形状,因为没有任何东西可以使 step
和 step + 1
处的半径相似。不失一般性,可以将上面的代码重写为:
for (int step = 0; step < NSTEPS; ++step) {
double t = step / (double) NSTEPS * 2 * pi;
double imperfectR = f(t);
drawPoint(imperfectR * cos(t), imperfectR * sin(t));
}
其中 f(t)
是为参数 t
生成半径的某个函数。现在,您完全可以为 t
选择任何函数,但您可能希望选择在圆上连续的函数,即没有 f(t)
突然改变值的点。
这里有很多选择。我上面建议的例子是建议使用余弦函数的总和:
double f(double t) {
double f = 0;
for (int i = 0; i < N; ++i) {
f += A[i] * cos(i * t + w[i]);
}
return f;
}
其中 A
和 w
是随机选择的值; A[0]
应设置为 R
。这里的重点是余弦函数的周期是2 * pi
,所以f(alpha) = f(alpha + 2 * pi)
,满足连续的要求。
然而,这绝不是唯一的选择。你也许可以选择像高斯核之和这样的东西,它将 'bumps' 以 w[i]
为中心,在圆周上扩展 sigma[i]
:
double f(double t) {
double f = 0;
for (int i = 0; i < N; ++i) {
f += A[i] * exp(-Math.pow(t-w[i], 2) / sigma[i]);
}
return f;
}
(这不太行,它不处理 t
的回绕)
您需要尝试一下,看看什么样的函数和什么样的随机选择值可以为您提供所需的形状。