2014-07-19 2 views
0

이전에 성공적으로 수행 한 작업을 다시 구현하려고하지만 바로 올바르게 처리하지 못했습니다.프랙탈 지형/하이트 맵 생성

사용중인 프랙탈 높이 맵 생성 알고리즘은 다음과 같습니다. 본질적으로 재귀적인 다이아몬드 사각 알고리즘. 완료까지는 잘 돌아가는 것처럼 보이지만 맵은 단지 '정답이 아닙니다.'.... 그것은 그리드의 모든 지점을 성공적으로 방문하여 색상을 결정하는 것처럼 보이지 않으며 맵에 잔여 '구조'가 있습니다. 그리드가 반복되는 방식과 관련이있는 것 같습니다. 나는 내가 보는 것을 생산할 수있는 문제가 어디서 어떻게 발생 하는지를 정확히 알지 못한다.

지금까지 IS가 코드,

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() 

당신은 그대로 그것을 실행하는 경우, 당신은이 쇼를에의 differnt 한 힘에 깊이를 변경, 색상 맵을 참조하고 마우스 오른쪽 매우 밤은 이유를 볼 수 다른 방법 - 값 256 이상 생성하는 데 걸릴

어떤 도움을 많이 주시면 감사하겠습니다.

답변

2

미안하지만 토플리스를 생성하는 또 다른 멋진 알고리즘을 공유하고 싶습니다. 다이아몬드와 스퀘어가 마음에 들지 않았다는 것을 깨닫고 사용하기 시작했습니다. Here 해고 및 여기 구현 :

#/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 위치를 추가하는 것을 잊었습니다.