Permalink
Browse files

Switch full planet simulation to hex grid

Selection is broken for now.
  • Loading branch information...
tps12 committed Jan 14, 2014
1 parent e5bfa3e commit 2f49be89c5d36a5ca1b8236e9aa6044d51ee4a9d
Showing with 52 additions and 123 deletions.
  1. +16 −48 planetdisplay.py
  2. +34 −43 planetsimulation.py
  3. +0 −25 tectonics.ui
  4. +2 −7 tectonicspresenter.py
View
@@ -1,9 +1,9 @@
from math import sin, cos, pi
from PySide.QtCore import Qt
from PySide.QtGui import QColor, QImage, QPainter, QWidget, QSizePolicy
from PySide.QtGui import QColor, QGridLayout, QImage, QPainter, QWidget, QSizePolicy
from projection import *
from sphereview import SphereView
def redbluescale(v):
r = 255 - 255 * v
@@ -181,20 +181,18 @@ def rockcolor(tile):
class PlanetDisplay(QWidget):
dt = 0.01
_projections = [Mercator, Sinusoidal, Flat]
_colorfunctions = [climatecolor, color, elevationcolor, rockcolor, subductioncolor, thicknesscolor]
def __init__(self, sim, selecthandler):
QWidget.__init__(self)
self._sim = sim
self._screen = None
self._rotate = 0
self._projection = 0
self._aspect = self._colorfunctions.index(elevationcolor)
self._select = selecthandler
self.selected = None
self.dirty = True
self.setLayout(QGridLayout())
self.invalidate()
@property
def rotate(self):
@@ -203,16 +201,7 @@ def rotate(self):
@rotate.setter
def rotate(self, value):
self._rotate = value
self._dirty = True
@property
def projection(self):
return self._projection
@projection.setter
def projection(self, value):
self._projection = value
self._dirty = True
self._screen.rotate(self._rotate)
@property
def aspect(self):
@@ -221,38 +210,17 @@ def aspect(self):
@aspect.setter
def aspect(self, value):
self._aspect = value
self._dirty = True
def mousePressEvent(self, e):
pos = e.pos().toTuple()
size = self._screen.size().toTuple()
self._select(self._projections[self._projection].unproject(size, self._sim.tiles, self.rotate, pos))
self.invalidate()
def tilecolor(self, tile):
return QColor(*self._colorfunctions[self._aspect](tile))
return self._colorfunctions[self._aspect](tile)
def paintEvent(self, e):
surface = QPainter()
surface.begin(self)
if (self._sim.dirty or self._dirty or
self._screen == None or self._screen.size() != surface.device().size()):
self._screen = QImage(surface.device().width(), surface.device().height(),
QImage.Format_RGB32)
size = self._screen.width(), self._screen.height()
self._screen.fill(QColor(255,255,255).rgb())
screen = QPainter()
screen.begin(self._screen)
self._projections[self._projection].project(screen, size, self._sim.tiles, self.rotate, self.tilecolor, Qt.black)
screen.end()
self._dirty = False
surface.drawImage(0, 0, self._screen)
surface.end()
def invalidate(self):
if self._screen is not None:
self._screen.deleteLater()
self._screen = SphereView(
self._sim.grid,
{ v: self.tilecolor(t) for (v, t) in self._sim.tiles.iteritems() },
self)
self._screen.rotate(self._rotate)
self.layout().addWidget(self._screen)
View
@@ -4,7 +4,8 @@
import random
from time import time
from adjacency import *
from grid import Grid
from hexadjacency import *
from climatemethod import climate
from erodemethod import erode
from movemethod import move
@@ -57,23 +58,20 @@ def __init__(self, r, dt):
tilearea = 4 * pi * r**2
degrees = 2
initt.start('building grid')
self.tiles = []
for lat in range(-89, 91, degrees):
r = cos(lat * pi/180)
row = []
d = 2 / r
lon = d/2
while lon <= 180:
flat = float(lat)
row = ([Tile(flat, -lon)] +
row +
[Tile(flat, lon)])
lon += d
self.tiles.append(row)
grid = Grid()
while grid.size < 6:
grid = Grid(grid)
grid.populate()
self._grid = grid
self.tiles = {}
for v in self._grid.faces:
x, y, z = v
lat = 180/pi * atan2(y, sqrt(x*x + z*z))
lon = 180/pi * atan2(-x, z)
self.tiles[v] = Tile(lat, lon)
initt.start('building indexes')
@@ -88,10 +86,6 @@ def __init__(self, r, dt):
# a 50M km^2 continent has a 50/50 chance of splitting in a given step
self._splitnum = 25e6/tilearea
xmax = max([len(self.tiles[i]) for i in range(len(self.tiles))])
dimensions = xmax, len(self.tiles)
# initial location
p = (0, 1, 0)
@@ -108,7 +102,7 @@ def __init__(self, r, dt):
shape = Shape(shape, p, o, v).projection()
self._shapes = [Group([t for lat in self.tiles for t in lat if shape.contains(t.vector)], v)]
self._shapes = [Group([t for t in self.tiles.itervalues() if shape.contains(t.vector)], v)]
# initial landmass starts at elevation based on distance from center
c = self._indexedtiles[self._index.nearest(p)[0]]
@@ -129,7 +123,7 @@ def __init__(self, r, dt):
else:
t.emptyocean(self.seafloor())
for t in [t for lat in self.tiles for t in lat]:
for t in self.tiles.itervalues():
t.climate = None
initt.done()
@@ -141,22 +135,24 @@ def __init__(self, r, dt):
self.dirty = True
@property
def grid(self):
return self._grid
@staticmethod
def seafloor():
return igneous.extrusive(0.5)
def initindexes(self):
self._indexedtiles = []
for lat in self.tiles:
for t in lat:
self._indexedtiles.append(t)
for t in self.tiles.itervalues():
self._indexedtiles.append(t)
self.adj = Adjacency(self.tiles)
self.adj = Adjacency(self._grid)
self._tileadj = dict()
for y in range(len(self.tiles)):
for x in range(len(self.tiles[y])):
self._tileadj[self.tiles[y][x]] = [self.tiles[j][i] for i, j in self.adj[(x,y)]]
for v in self._grid.faces:
self._tileadj[self.tiles[v]] = set([self.tiles[nv] for nv in self.adj[v]])
self._index = PointTree(dict([[self._indexedtiles[i].vector, i]
for i in range(len(self._indexedtiles))]))
@@ -253,27 +249,22 @@ def update(self):
stept.start('"simulating" climate')
seasons = [0.1*v for v in range(-10,10,5) + range(10,-10,-5)]
climatetiles = {}
for y in range(len(self.tiles)):
for x in range(len(self.tiles[y])):
climatetiles[(x,y)] = self.tiles[y][x]
c = climate(climatetiles, self.adj, seasons, self.cells, self.spin, self.tilt, self.temprange, self._life, self._climatemappings, self._climateprof)
c = climate(self.tiles, self.adj, seasons, self.cells, self.spin, self.tilt, self.temprange, self._life, self._climatemappings, self._climateprof)
if self._climateprof:
self._climateprof.dump_stats('climate.profile')
for y in range(len(self.tiles)):
for x in range(len(self.tiles[y])):
self.tiles[y][x].climate = c[(x,y)]['classification']
for v, tile in self.tiles.iteritems():
tile.climate = c[v]['classification']
stept.start('determining erosion')
erosion = erode(climatetiles, self.adj)
erosion = erode(self.tiles, self.adj)
for t in [t for lat in self.tiles for t in lat]:
for t in self.tiles.itervalues():
t.erode(erosion, self._erode)
for t in [t for lat in self.tiles for t in lat]:
for t in self.tiles.itervalues():
# if the tile is in at least one shape, apply the erosion materials
if len(overlapping[t]) > 0:
if len(erosion[t].materials) > 0:
@@ -303,18 +294,18 @@ def update(self):
stept.start('performing random intrusions')
for t in [t for lat in self.tiles for t in lat]:
for t in self.tiles.itervalues():
if t.subduction > 0:
if random.random() < 0.1:
t.intrude(igneous.intrusive(max(0, min(1, random.gauss(0.85, 0.15)))))
t.transform(metamorphic.contact(t.substance[1], t.intrusion))
stept.start('applying regional metamorphism')
for t in [t for lat in self.tiles for t in lat]:
for t in self.tiles.itervalues():
t.transform(metamorphic.regional(t.substance[1], t.subduction > 0))
for t in [t for lat in self.tiles for t in lat]:
for t in self.tiles.itervalues():
t.cleartemp()
stept.start('merging overlapping shapes')
View
@@ -139,31 +139,6 @@
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="projection">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Mercator</string>
</property>
</item>
<item>
<property name="text">
<string>Sinusoidal</string>
</property>
</item>
<item>
<property name="text">
<string>Flat</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
View
@@ -78,9 +78,6 @@ def __init__(self, view, uistack, listitemclass):
self._view.aspect.setCurrentIndex(self._display.aspect)
self._view.aspect.currentIndexChanged[int].connect(self.aspect)
self._view.projection.setCurrentIndex(self._display.projection)
self._view.projection.currentIndexChanged[int].connect(self.project)
self._view.pause.setVisible(False)
self._uistack = uistack
@@ -101,10 +98,7 @@ def rotate(self, value):
def aspect(self, value):
self._display.aspect = value
self._view.content.update()
def project(self, value):
self._display.projection = value
self._display.invalidate()
self._view.content.update()
def load(self):
@@ -157,4 +151,5 @@ def tick(self):
self._view.ticks.setNum(self._ticks)
self._view.continents.setNum(self._model.continents)
self._view.percent.setNum(self._model.land)
self._display.invalidate()
self._view.content.update()

0 comments on commit 2f49be8

Please sign in to comment.