代码之家  ›  专栏  ›  技术社区  ›  SpoocyCrep

计算非完美圆

  •  1
  • SpoocyCrep  · 技术社区  · 11 年前

    我想创建一个“不完美的圆”的生成器,这些圆有点扭曲,更随机,但看起来仍然有点像圆或云。

    这就是我所说的不完美的圆: enter image description here

    我想创建一个函数,获取“非完美圆”的最大和最小比例,并获取其所有点。我知道圆的公式: 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();
    
    1 回复  |  直到 10 年前
        1
  •  3
  •   Andy Turner    11 年前

    圆的另一个更容易绘制的方程是其参数形式之一:

    x = R * cos(t);
    y = R * sin(t);
    

    哪里 R 是标称半径 t 是介于之间的参数 0 2 * pi 。因此,您可以在圆周上画一个“完美”圆,如下所示:

    for (int step = 0; step < NSTEPS; ++step) {
      double t = step / (double) NSTEPS * 2 * pi;
      drawPoint(R * cos(t), R * sin(t));
    }
    

    您可以按照@nikis的建议,通过在圆的半径上添加一个随机数量,使圆变得“不完美”:

    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) 是某个函数生成参数的半径 。现在,您可以为 ,但您可能希望选择在圆上连续的东西,即没有点 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) 满足连续性要求。

    然而,这远不是唯一的选择。你可以选择像高斯核之和这样的东西,将“凸点”放在 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;
    }
    

    (这不太管用,它无法处理 )

    你需要四处走走,看看什么样的函数,什么样的随机选择的值给了你想要的形状。