首页 > 代码库 > 分形应用:造山

分形应用:造山

一、分形山脉

  1、山脉原型:

    分形是具有自相似性的图形,即它们都具有最初的原型。如果山脉是分形,那它的原型又是什么?容易想到的是简单的三角形。一个立起的三角形,俨然山的抽象。

  2、递归迭代:

    那三角形又是如何能一步一步地内部迭代而逼近一座山呢?在1978年,Loren Carpenter 就解决了这个问题。他以简单而机械的方法:递归分割、中点置换,绘制了如下图形。

技术分享

    相关网址http://www.cnblogs.com/szlongman/archive/2009/07/25/1530993.html

  3、准备工作:

    使三维立体图形在二维平面上呈现的方法:斜二测画法

    建立一个从三维空间向二维空间的映射

 技术分享

x0 = y - x * cos(θ)

y0 = x * sin(θ) - z

  4、一种实现:

    ①在xoy平面取三个点,使之能构成一个三角形;

    ②n次迭代,每个三角形的三边中点在z轴方向上平移(max * rnd() * rough^n)个单位,形成新的3个点,新的3点与原来的3点将重新构成4个新的小三角形(max:山的最大高度,rnd():随机函数,返回[-1,1]rough:陡峭程度,取值[0,1])

    ③给各个三角形填充颜色,可以根据三角形的重心的高度三点的竖坐标的平均值,填充不同的颜色。

    注:各三角形的公共边的中点应保证只有一次纵移,避免形成的山体破碎。

一、山脉地形

  1、另一种想法:

    人的视觉感官只能察觉物体的三面,所以实际上山体只须要呈现它的一个面向我们的表面,就足见效果。在这里山体,未有其体,只是一幅实际意义上的地形图。

/**地形接口**/

public interface Terrain {

  public double getAltitude (double i, double j);

  public RGB getColor (double i, double j);

}

public class RGB {

  private double r, g, b;

  public RGB (double r, double g, double b) {

    this.r = r;

    this.g = g;

    this.b = b;

  }

  public RGB add (RGB rgb) {

    return new RGB (r + rgb.r, g + rgb.g, b + rgb.b);

  }

  public RGB subtract (RGB rgb) {

    return new RGB (r - rgb.r, g - rgb.g, b - rgb.b);

  }

  public RGB scale (double scale) {

    return new RGB (r * scale, g * scale, b * scale);

  }

  private int toInt (double value) {

    return (value < 0.0) ? 0 : (value > 1.0) ? 255 :

      (int) (value * 255.0);

  }

  public int toRGB () {

    return (0xff << 24) | (toInt (r) << 16) |

      (toInt (g) << 8) | toInt (b);

  }

}

 

    地形图再去掉颜色,仅保留 由横、纵坐标向竖坐标的映射关系,这样抽象而成几何立体图形,就是一张简单曲面。一个简单的方法是:创建一个二维数组,保存该映射关系。由行、列标对应横、纵坐标,数组存储该点处的海拔高度的对应值。

  2、然后便是运用算法,为整个数组赋值。

    Diamond-Square算法:

    i :为方格的四个顶点赋初值;

    ii : n次执行时,计算该方格四个顶点的平均值+?X(= rnd() * rough^n),赋予中心点;

    iii : 同理以平均值+?X为剩余的四个中点赋值;

    iiii : 分别选取恰被分割成的四个方格,执行ii、iii、iii;

 

技术分享    为整个数组赋完值后,再确定一个由海拔到颜色的映射,就可以在画图形了。

public class FractalTerrain implements Terrain {

  ……

  public double getAltitude (double i, double j) {

    ……

  }

  private RGB blue = new RGB (0.0, 0.0, 1.0);

  private RGB green = new RGB (0.0, 1.0, 0.0);

  private RGB white = new RGB (1.0, 1.0, 1.0);

  public RGB getColor (double i, double j) {

    double a = getAltitude (i, j);

    if (a < .5)

      return blue.add (green.subtract (blue).scale ((a - 0.0) / 0.5));

    else

      return green.add (white.subtract (green).scale ((a - 0.5) / 0.5));

  }

}

 

 

    画图可以选择从数组一次取出三点,画三角形,颜色为三角形重心处的对应颜色;或是每次取单点,画出该点;……

    为数组赋值的算法可以很自由的替换,甚至各处的颜色可以不直接与海拔相关,而与所处方位(即横、纵坐标)相关。

    相关网址http://www.javaworld.com/article/2076745/learn-java/3d-graphic-java--render-fractal-landscapes.html

 

 

分形应用:造山