"""Tutorial 06 — Terrain and Optical Properties

Demonstrates the use of different optical properties and how to set properties individually for multi-component objects."""

import less
import numpy as np

# ── Create a scene ───────────────────────────────────────────────
scene = less.Scene()
scene.size = 10.0

# soil
scene.terrain = less.Terrain(property=less.Lambertian(reflectance=0.12))

# illumination
scene.illumination = less.Illumination(source=less.Sun(zenith=30, azimuth=150), atmosphere=less.NoAtmosphere())

# ── Corn (Prospect attribute)────────────────────────────────────
maize = less.Object("maize", mesh=less.examples.asset_path("maize.obj"))
maize.set_property(less.Prospect(cab=45, car=10, cw=0.012, cm=0.006, N=1.55))

# 3×3 grid placement
xs = np.linspace(2, 8, 3)
ys = np.linspace(2, 8, 3)
gx, gy = np.meshgrid(xs, ys)
positions = np.column_stack([gx.ravel(), gy.ravel(), np.zeros(9)])
scene.add(maize, positions=positions)
sensor = less.OpticalImager(
    less.Orthographic(image_size=512),
    bands=[650, 550, 450, 842],  # R, G, B, NIR
    quality=128,
)
image = scene.simulate(sensor)
image.save("06_maize_grid.png")

# ── Calculate NDVI ─────────────────────────────────────────────
data = image.data
nir = data[:, :, 3]  # 842 nm
red = data[:, :, 0]  # 650 nm
ndvi = (nir - red) / (nir + red + 1e-10)
print(f"NDVI range: {ndvi.min():.2f} ~ {ndvi.max():.2f}")

# ── Demonstrate different chlorophyll contents ───────────────────────────────────
for cab in [10, 30, 60]:
    maize.set_property(less.Prospect(cab=cab, car=10, cw=0.012, cm=0.006, N=1.55))
    img = scene.simulate(sensor)
    img.save(f"06_maize_cab{cab}.png")
    print(f"cab={cab}: saved 06_maize_cab{cab}.png")

print("Tutorial 06 Complete!")
