"""Built-in rotary-kiln generator for the generic Scene Recipe compiler.""" from __future__ import annotations import math from typing import Any def build_rotary_kiln( builder: Any, root: Any, prefix: str, parameters: dict[str, Any], ) -> None: length = float(parameters["length_m"]) diameter = float(parameters["outer_diameter_m"]) radius = diameter / 2 slope_angle = math.degrees(math.atan(float(parameters["slope_percent"]) / 100)) stations = int(parameters["support_stations"]) shell = builder.generated_material(prefix + "_shell", "#707780", 0.65, 0.3) metal = builder.generated_material(prefix + "_metal", "#303840", 0.8, 0.22) lining = builder.generated_material(prefix + "_lining", "#B56A3B", 0.0, 0.75) concrete = builder.generated_material(prefix + "_concrete", "#8D9398", 0.0, 0.9) material = builder.generated_material(prefix + "_bed", "#D35B26", 0.0, 0.8) builder.add_generated_geometry( prefix + "_shell_body", {"type": "cylinder", "radius": radius, "depth": length, "vertices": 96}, parent=root, material=shell, rotation_deg=(0, 90 + slope_angle, 0), ) builder.add_generated_geometry( prefix + "_lining_body", { "type": "cylinder", "radius": max(0.05, radius - float(parameters["shell_thickness_m"])), "depth": length * 0.995, "vertices": 96, }, parent=root, material=lining, rotation_deg=(0, 90 + slope_angle, 0), ) if parameters.get("material_bed", True): builder.add_generated_geometry( prefix + "_material_bed", { "type": "cylinder", "radius": max( 0.03, radius - float(parameters["shell_thickness_m"]) - float(parameters["lining_thickness_m"]), ), "depth": length * 0.97, "vertices": 64, }, parent=root, material=material, position=(0, 0, -radius * 0.25), rotation_deg=(0, 90 + slope_angle, 0), ) usable = length * 0.7 for index in range(stations): x = -usable / 2 + usable * index / (stations - 1) z = -x * math.tan(math.radians(slope_angle)) builder.add_generated_geometry( f"{prefix}_tyre_{index + 1:02d}", { "type": "torus", "major_radius": radius + diameter * 0.035, "minor_radius": max(0.04, diameter * 0.055), "major_segments": 64, "minor_segments": 16, }, parent=root, material=metal, position=(x, 0, z), rotation_deg=(0, 90 + slope_angle, 0), ) builder.add_generated_geometry( f"{prefix}_foundation_{index + 1:02d}", {"type": "box", "size": [diameter * 0.7, diameter * 1.8, radius * 0.8]}, parent=root, material=concrete, position=(x, 0, z - radius * 1.25), ) if parameters.get("drive_system", True): builder.add_generated_geometry( prefix + "_girth_gear", { "type": "torus", "major_radius": radius + diameter * 0.08, "minor_radius": max(0.05, diameter * 0.07), "major_segments": 72, "minor_segments": 16, }, parent=root, material=metal, position=(-length * 0.18, 0, length * 0.18 * math.tan(math.radians(slope_angle))), rotation_deg=(0, 90 + slope_angle, 0), ) builder.add_generated_geometry( prefix + "_drive_motor", {"type": "box", "size": [diameter * 0.55, diameter * 0.4, diameter * 0.4]}, parent=root, material=metal, position=(-length * 0.18, -radius * 1.45, -radius * 0.7), ) if parameters.get("hoods", True): for name, x in (("tail_hood", -length * 0.54), ("head_hood", length * 0.54)): builder.add_generated_geometry( prefix + "_" + name, {"type": "box", "size": [diameter * 0.65, diameter * 1.4, diameter * 1.55]}, parent=root, material=metal, position=(x, 0, -x * math.tan(math.radians(slope_angle))), ) if parameters.get("burner", True): builder.add_generated_geometry( prefix + "_burner", {"type": "cylinder", "radius": max(0.03, diameter * 0.055), "depth": diameter * 2.2, "vertices": 32}, parent=root, material=metal, position=(length * 0.57, 0, -length * 0.57 * math.tan(math.radians(slope_angle))), rotation_deg=(0, 90 + slope_angle, 0), ) if parameters.get("inspection_platform", True): builder.add_generated_geometry( prefix + "_inspection_platform", {"type": "box", "size": [diameter * 1.6, diameter * 0.9, 0.12]}, parent=root, material=metal, position=(length * 0.35, -radius * 1.2, -radius * 0.2), )