2014-07-19 38 views
0

我试图重新实现的东西我做了一个成功的前一段时间,但我只是没有得到它完全正确..分形地形/高度图代

我使用的分形高度图生成算法基本上是递归菱形平方算法。它似乎运行良好,但地图产生的结果并不是很正确......它似乎没有成功访问网格中的每一个点来确定颜色,并且地图上有残留的“结构”这似乎与网格递归的方式有关。我不确定究竟在哪里/如何产生我所看到的问题。

我到目前为止是代码,

import matplotlib.pyplot as plt 
import matplotlib.cm as cm 
from math import sqrt 
from collections import namedtuple 
import random 

Coord=namedtuple('Coord','x y') 

class Grid(object): 
    '''grid handedness, 0,0=topleft max,max=bottomr right'''  

    def __init__(self,x,y): 
     self.size_x=x 
     self.size_y=y 
     self.data=[ [0 for _ in xrange(x)] for _ in xrange(y) ] 

    def _render_to_text(self): 
     print '\n\n' 
     for row in self.data: 
      print [ int(n) for n in row ] 

    def _render_to_colormap(self): 
     plt.imshow(self.data, interpolation='nearest',cmap=cm.gist_rainbow) 
     plt.show() 

    def render(self): 
     self._render_to_colormap() 
     #self._render_to_text() 

    def make(self,coordinate,value): 
     self.data[coordinate.x][coordinate.y]=value 

    def make_new(self,coordinate,value): 
     if self.data[coordinate.x][coordinate.y]==0: 
      self.make(coordinate,value) 

    def get(self,coordinate): 
     return self.data[coordinate.x][coordinate.y] 

class FractalHeightmap(object): 
    '''populates a 'grid' with a fractal heightmap''' 
    def __init__(self,grid,rng_seed,roughness, 
       corner_seeds=[(0,100),(0,100),(0,100),(0,100)], 
       max_depth=3): 
     self.grid=grid 
     self.max_depth=max_depth 
     self._set_initial_corners(corner_seeds) 
     self.roughness=roughness 
     self.generate_heightmap([Coord(0,0), 
           Coord(self.grid.size_x-1,0), 
           Coord(0,self.grid.size_y-1), 
           Coord(self.grid.size_x-1,self.grid.size_y-1)],1 
           ) 

    def _set_initial_corners(self,corner_seeds): 
     tl,tr,bl,br=corner_seeds 
     seeds=[[tl,tr],[bl,br]] 
     for x_idx,x in enumerate([0,self.grid.size_x-1]): 
      for y_idx,y in enumerate([0,self.grid.size_y-1]): 
       try: 
        minval,maxval=seeds[x_idx][y_idx] 
        val=minval+(random.random()*(maxval-minval)) 
       except ValueError: 
        val=seeds[x_idx][y_idx] 
       self.grid.make_new(Coord(x,y),val) 

    def generate_heightmap(self,corners,depth): 
     '''corners = (Coord(),Coord(),Coord(),Coord()/tl/tr/bl/br''' 
     if depth>self.max_depth: return 

     # 
     tl,tr,bl,br=corners 
     center=Coord((tr.x-tl.x)/2,(br.y-tr.y)/2) 

     #define edge center coordinates 
     top_c=Coord(tl.x+((tr.x-tl.x)/2),tl.y) 
     left_c=Coord(tl.x,tl.y+((bl.y-tl.y)/2)) 
     right_c=Coord(tr.x,tr.y+((br.y-tr.y)/2)) 
     bot_c=Coord(bl.x+((br.x-bl.x)/2),bl.y) 

     #calc the center and edge_center heights 
     avg=sum([self.grid.get(tl), 
       self.grid.get(tr), 
       self.grid.get(bl), 
       self.grid.get(br)] 
       )/4.0 ###NOTE, we can choose to use the current corners, the new edge-centers, or all 
       #currenty we use the current corners 
       #then do the edge centers 
     offset=((random.random())-.5)*self.roughness 
     self.grid.make_new(center,avg+offset) 

     #top_c 
     avg=sum([self.grid.get(tl), 
       self.grid.get(tr)] 
       )/2.0 
     offset=((random.random())-.5)*self.roughness 
     self.grid.make_new(top_c,avg+offset) 

     #left_c 
     avg=sum([self.grid.get(tl), 
       self.grid.get(bl)] 
       )/2.0 
     offset=((random.random())-.5)*self.roughness 
     self.grid.make_new(left_c,avg+offset) 

     #right_c   
     avg=sum([self.grid.get(tr), 
       self.grid.get(br)] 
       )/2.0 
     offset=((random.random())-.5)*self.roughness 
     self.grid.make_new(right_c,avg+offset) 

     #bot_c 
     avg=sum([self.grid.get(bl), 
       self.grid.get(br)] 
       )/2.0 
     offset=((random.random())-.5)*self.roughness 
     self.grid.make_new(bot_c,avg+offset) 

     self.generate_heightmap((tl,top_c,left_c,center),depth+1) 
     self.generate_heightmap((top_c,tr,center,right_c),depth+1) 
     self.generate_heightmap((left_c,center,bl,bot_c),depth+1) 
     self.generate_heightmap((center,right_c,bot_c,br),depth+1) 



if __name__ == '__main__': 
    g_size=32 #//must be power of 2 
    g=Grid(g_size+1,g_size+1) 
    f=FractalHeightmap(g,1,10,max_depth=sqrt(g_size)) 
    g.render() 

,如果你运行它就是你应该看到的颜色表,看看为什么它不是,完全正确的,不断变化的深度为2显示它在不同的充权力不同的方式 - 值256和以上需要一段时间来生成

任何帮助非常赞赏。

回答

2

对不起的话题,但我想分享另一个很好的算法来生成一个地形,我开始使用后,我意识到我不喜欢钻石和广场。 Here a descrption and here an implementation:

#/usr/bin/python 
#coding=UTF-8 

import random,math 

class HillGrid: 

    def __init__(self,KRADIUS =(1.0/5.0),ITER=200,SIZE=40): 
     self.KRADIUS = KRADIUS 
     self.ITER = ITER 
     self.SIZE = SIZE 

     self.grid = [[0 for x in range(self.SIZE)] for y in range(self.SIZE)] 

     self.MAX = self.SIZE * self.KRADIUS 
     for i in range(self.ITER): 
      self.step() 

    def dump(self): 
     for ele in self.grid: 
      s = '' 
      for alo in ele: 
       s += '%s ' % str(alo) 
      print s 

    def __getitem__(self,n): 
     return self.grid[n] 

    def step(self): 
     point = [random.randint(0,self.SIZE-1),random.randint(0,self.SIZE-1)] 
     radius = random.uniform(0,self.MAX) 

     x2 = point[0] 
     y2 = point[1]  

     for x in range(self.SIZE): 
      for y in range(self.SIZE): 

       z = (radius**2) - (math.pow(x2-x,2) + math.pow(y2-y,2)) 
       if z >= 0: 
        self.grid[x][y] += int(z) 


if __name__ == '__main__': 
    h = HillGrid(ITER=50,SIZE = 20) 
    h.dump() 
+0

至少相关的话题!我会看看它。 因为我不想生成逼真的地形,只是一个具有分形生成高度图属性的数据集。所以要么是好的,而你发布的代码会少一些;) –

+0

我认为它应该能够完成这项工作,我用这个代替了钻石和方形,因为它很容易调整,并且随着钻石和方形的出现,我得到了丑陋的边框^^ – lelloman

0

我回答了我自己的问题,经过了一段时间,通过电网,因为它正在建立。

中心点的计算是不正确的,

中心坐标=((tr.x-tl.x)/ 2,(br.y-tr.y)/ 2)

应已经

中心坐标=(tl.x +((tr.x-tl.x)/ 2),tr.y +((br.y-tr.y)/ 2))

第一版本忘记将子网格原点的x/y位置添加到计算中点坐标的结果中。