# Sample Function: Perlin Noise in 2D
# ===================================

# Here we use `pyvista.core.utilities.features.sample_function()` to sample
# Perlin noise over a region to generate random terrain.
# Perlin noise is atype of gradient noise often used by visual effects
# artists to increase the appearance of realism in computer graphics.
# Source: Perlin Noise Wikipedia
# The development of Perlin Noise has allowed computer graphics artists
# to better represent the complexity of natural phenomena in visual
# effects for the motion picture industry.
import pyvista as pv

# Generate Perlin Noise over a StructuredGrid
# ===========================================

# Feel free to change the values of `freq` to change the shape of
# the "mountains".  For example, lowering the frequency will make the
# terrain seem more like hills rather than mountains.
freq = [0.689, 0.562, 0.683]
noise = pv.perlin_noise(1, freq, (0, 0, 0))
sampled = pv.sample_function(noise, bounds=(-10, 10, -10, 10, -10, 10), dim=(500, 500, 1))

# Warp by scalar
# ==============

# Here we warp by scalar to give the terrain some height based on the
# value of the Perlin noise.  This is necessary to the terrain its shape.
mesh = sampled.warp_by_scalar('scalars')
mesh = mesh.extract_surface(algorithm=None)

# clean and smooth a little to reduce Perlin noise artifacts
mesh = mesh.smooth(n_iter=100, inplace=False, relaxation_factor=1)

# This makes the "water" level look flat.
z = mesh.points[:, 2]
diff = z.max() - z.min()

# water level at 70%  (change this to change the water level)
water_percent = 0.7
water_level = z.max() - water_percent * diff
mesh.points[z < water_level, 2] = water_level

# Show the terrain as a contour plot
# make the water blue
rng = z.max() - z.min()
clim = (z.max() - rng * 1.65, z.max())

pl = pv.Plotter()
pl.add_mesh(
    mesh,
    scalars=z,
    cmap='gist_earth',
    n_colors=10,
    show_scalar_bar=False,
    smooth_shading=True,
    clim=clim,
)
pl.show()

# Show the terrain with custom lighting and shadows
pl = pv.Plotter(lighting=None)
pl.add_light(
    pv.Light(
        position=(3, 1, 0.5),
        show_actor=True,
        positional=True,
        cone_angle=90,
        intensity=1.2,
    )
)
pl.add_mesh(
    mesh,
    scalars=z,
    cmap='gist_earth',
    show_scalar_bar=False,
    smooth_shading=True,
    clim=clim,
)
pl.enable_shadows = True
pl.show()

# ----------------------------------------------------------------------
# Generated by sphinx-examples-as-code https://github.com/pyvista/sphinx-examples-as-code

