2014-07-19 31 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位置添加到計算中點座標的結果中。