"""Tutorial 11 - Triangle-mesh scenes: an autumn forest and a maize field."""
import numpy as np
import less


def autumn_forest():
    scene = less.Scene()
    scene.size = 50.0
    scene.terrain = less.Terrain(property=less.Lambertian(reflectance=0.08))
    scene.illumination = less.Illumination(
        source=less.Sun(zenith=40, azimuth=150), atmosphere=less.NoAtmosphere())
    leaves = {
        "golden": less.Prospect(cab=10, car=20, cbrown=0.15, cw=0.012, cm=0.009, N=1.8),
        "orange": less.Prospect(cab=3, car=12, canth=8, cbrown=0.25, cw=0.010, cm=0.008, N=1.7),
        "red": less.Prospect(cab=2, car=5, canth=30, cbrown=0.15, cw=0.011, cm=0.009, N=1.8),
        "dark_red": less.Prospect(cab=1, car=3, canth=40, cbrown=0.35, cw=0.009, cm=0.010, N=2.0),
        "yellow_green": less.Prospect(cab=20, car=15, cbrown=0.05, cw=0.013, cm=0.009, N=1.7),
    }
    groups = less.place.random_split(scene, counts=[12] * len(leaves), min_dist=3.0, seed=42)
    for (name, leaf), positions in zip(leaves.items(), groups):
        tree = less.Object(f"ash_{name}", mesh=less.asset_path("FREX.obj"))
        tree.set_property("leaves", leaf)
        tree.set_property("stem_branch", less.Lambertian(reflectance=0.06))
        n = len(positions)
        scene.add(tree, positions=positions,
                  scales=less.place.uniform_scale(n, lo=0.6, hi=1.5, seed=len(name)),
                  rotations=less.place.random_rotation(n, seed=len(name)))
    print("Forest LAI:", round(scene.measure(less.LAIMeasurement(property_filter=less.Prospect)), 2))
    scene.simulate(less.OpticalImager(
        less.Orthographic(image_size=256), bands=[630, 532, 465], quality=32)).save("11_forest_nadir.png")
    scene.simulate(less.OpticalImager(
        less.Perspective(resolution=256, fov=35, position=(25, 60, 45), target=(25, 25, 6)),
        bands=[630, 532, 465], quality=32)).save("11_forest_oblique.png")


def maize_field():
    scene = less.Scene()
    scene.size = 10.0
    scene.terrain = less.Terrain(property=less.Lambertian(reflectance=0.15))
    scene.illumination = less.Illumination(
        source=less.Sun(zenith=30, azimuth=150), atmosphere=less.NoAtmosphere())
    maize = less.Object("maize", mesh=less.asset_path("maize.obj"))
    maize.set_property(less.Prospect(cab=45, car=10, cw=0.012, cm=0.006, N=1.55))
    positions = less.place.grid(scene, spacing=(0.75, 0.40), jitter=0.04, margin=0.3, seed=42)
    n = len(positions)
    rng = np.random.default_rng(42)
    plants = scene.add(maize, positions=positions, scales=rng.uniform(0.9, 1.1, n),
                       rotations=rng.uniform(0, 360, n))
    print(n, "maize plants, LAI =", round(scene.measure(less.LAIMeasurement()), 2))
    sensor = less.OpticalImager(less.Orthographic(image_size=128), bands=[650, 550, 450], quality=32)
    scene.simulate(sensor).save("11_maize_mature.png")
    plants.set_scale(np.full(n, 0.3))
    scene.update_instances()
    scene.simulate(sensor).save("11_maize_seedling.png")


if __name__ == "__main__":
    autumn_forest()
    maize_field()
