Closed ftomassetti closed 8 years ago
@tcld I fixed the PR according to your suggestion
I just noticed that the ocean-map is not used, I think the function works on the whole generated world. Is that intended?
Is armonize missing an h? ;)
@psi29a I was wondering if that was the case... I just saw the someone over the internet used the word "armonize" like I did but perhaps he was a creative foreigner like me :)
If you could add a #TODO: numpy
or similar, I would say this is fine. And maybe add an 'h' in front of 'armonize' unless that actually is a word I don't know. (As psi said.^^)
renamed
TODO added
I have to admit that I don't fully understand what the loop body does. It looks to me like it isn't as much smoothing the ocean floor as it is making it shallower (below midpoint) respectively deeper (above midpoint).
@tcld it affects only ocean points which are deep enough (it ignores point above shallow_sea) and what it does it make the elevation very close to midpoint. In this way we have no huge variations in the elevation for ocean tiles. You can someone look at it as a cheap way to perform antialias.
But it does make the ocean much more shallow where it was deep before, doesn't it? Maybe we should instead make use of the anti_alias()-method worldengine already heavily uses? It is a very expensive method but it is kind of made for this job.
Well we would need to adapt it to use a mask. With this method the deepest points should remain deeper than midpoint and the most shallow should remain higher than midpoint, we just reduce the variation. We could rescale it after to have a lower absolute value but I am not sure that would be helpful.
Looks like numpy.logical_and() is the key...
import numpy as np
def harmonize_ocean(ocean, elevation, ocean_level):
"""
The goal of this function is to make the ocean floor less noisy.
The underwater erosion should cause the ocean floor to be more uniform
"""
height, width = elevation.shape
shallow_sea = ocean_level * 0.85
midpoint = shallow_sea / 2.0
for y in range(height):
for x in range(width):
e = elevation[y, x]
if ocean[y, x] and e < shallow_sea:
# TODO: use numpy to avoid the loop
if e < midpoint:
e = midpoint - ((midpoint - e) / 5.0)
else:
e = midpoint + ((e - midpoint) / 5.0)
elevation[y, x] = e
def harmonize_ocean_np(ocean, elevation, ocean_level):
"""
The goal of this function is to make the ocean floor less noisy.
The underwater erosion should cause the ocean floor to be more uniform
"""
shallow_sea = ocean_level * 0.85
midpoint = shallow_sea / 2.0
lt = elevation_np < shallow_sea
a = np.logical_and(lt, ocean)
elevation[a] = midpoint - ((midpoint - elevation[a]) / 5.0)
gt = elevation_np > shallow_sea
a = np.logical_and(lt, ocean)
elevation[a] = midpoint - ((midpoint - elevation[a]) / 5.0)
ocean = np.random.rand(2,2) > 0.5;
elevation = np.random.rand(2,2);
elevation_np = elevation
ocean_level = float(np.random.rand(1,1));
print "ocean: "
print ocean
print "elevation: "
print elevation
print "ocean_level = " +str(ocean_level)
harmonize_ocean(ocean, elevation, ocean_level);
print "--------------------------------"
print "elevation: "
print elevation
harmonize_ocean_np(ocean, elevation_np, ocean_level);
print "--------------------------------"
print "elevation_np: "
print elevation_np
So, on this very small sample data, I got the same result between the two versions of code:
In [33]: execfile('harm.py')
ocean:
[[ True False]
[False False]]
elevation:
[[ 0.78725756 0.86435022]
[ 0.69927748 0.13072007]]
ocean_level = 0.345082907826
--------------------------------
elevation:
[[ 0.78725756 0.86435022]
[ 0.69927748 0.13072007]]
--------------------------------
elevation_np:
[[ 0.78725756 0.86435022]
[ 0.69927748 0.13072007]]
Ah, this is a great idea. Although I think the heart of your code (and the parts @ftomassetti would be interested in) should be slightly altered:
valid = numpy.logical_and(elevation_np < shallow_sea, ocean) # all tiles that need to be worked on
lt = numpy.logical_and(elevation_np < midpoint, valid)
elevation[lt] = midpoint - ((midpoint - elevation[lt]) / 5.0)
gt = numpy.logical_and(elevation_np >= midpoint, valid)
elevation[gt] = midpoint + ((elevation[gt] - midpoint) / 5.0)
There were some mistakes in your version. I also renamed the variables and tried to make clear what is being done.
Your small example passed since you didn't move below midpoint. The shallower waters were handled correctly by your code.
I hadn't caught the elevation < shallow_sea part, but I realize the missing >= part.
Good catches!
Thank you guys, I tried incorporating your suggestions (a.k.a. copying and pasting the code you gently provided...)
Ok, blessed images fixed, script for generating blessed images corrected. Time to merge (also because otherwise tests would fail given I have updated the blessed images)
Awesome work guys! :)
This is a simple approach to solve the issue of noisy ocean floors (issue #60)