import argparse
from collections.abc import Sequence
from pathlib import Path
from openworld_radio_twin.compiler import compile_scene_sync
from openworld_radio_twin.config import get_settings
def _add_server_arguments(parser: argparse.ArgumentParser) -> None:
settings = get_settings()
parser.add_argument("--host", default=settings.host)
parser.add_argument("--port", type=int, default=settings.port)
parser.add_argument("--reload", action="store_true")
def _serve(args: argparse.Namespace) -> None:
try:
import uvicorn
except ImportError as exc:
raise SystemExit(
"The web server is not installed; install 'openworld-radio-twin[web]'"
) from exc
uvicorn.run(
"openworld_radio_twin.main:app",
host=args.host,
port=args.port,
reload=args.reload,
)
def _compile(args: argparse.Namespace) -> None:
xml_path = compile_scene_sync(
latitude=args.latitude,
longitude=args.longitude,
radius_m=args.radius,
output=args.output,
buildings=args.buildings,
building_source=args.building_source,
terrain=args.terrain,
material_profile=args.material_profile,
terrain_resolution_m=args.terrain_resolution,
receiver_height_m=args.receiver_height,
receiver_cell_size=tuple(args.receiver_cell_size),
voxel_pitch_m=args.voxel_pitch,
if_exists=args.if_exists,
)
print(xml_path)
def _parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(prog="owrt", description="OpenWorld Radio Twin")
_add_server_arguments(parser)
commands = parser.add_subparsers(dest="command")
serve = commands.add_parser("serve", help="Run the web application")
_add_server_arguments(serve)
serve.set_defaults(handler=_serve)
scene = commands.add_parser("scene", help="Compile reusable geographic scenes")
scene_commands = scene.add_subparsers(dest="scene_command", required=True)
compile_parser = scene_commands.add_parser("compile", help="Compile a geographic scene")
compile_parser.add_argument("--lat", dest="latitude", type=float, required=True)
compile_parser.add_argument("--lon", dest="longitude", type=float, required=True)
compile_parser.add_argument("--radius", type=float, required=True)
compile_parser.add_argument("--output", type=Path, required=True)
compile_parser.add_argument("--buildings", choices=("auto", "none"), default="auto")
compile_parser.add_argument(
"--building-source",
default="auto",
help=(
"auto (Netherlands: 3dbag), global (Overture/OSM), "
"3dbag, overture, osm, or installed source ID"
),
)
compile_parser.add_argument(
"--terrain", choices=("elevation", "flat", "none"), default="elevation"
)
compile_parser.add_argument("--material-profile", choices=("itu", "uniform"), default="itu")
compile_parser.add_argument("--terrain-resolution", type=float, default=5.0)
compile_parser.add_argument("--receiver-height", type=float, default=1.5)
compile_parser.add_argument(
"--receiver-cell-size",
type=float,
nargs=2,
metavar=("EAST_M", "NORTH_M"),
default=(10.0, 10.0),
)
compile_parser.add_argument("--voxel-pitch", type=float, default=3.0)
compile_parser.add_argument(
"--if-exists", choices=("reuse", "error", "replace"), default="reuse"
)
compile_parser.set_defaults(handler=_compile)
return parser
[docs]
def main(argv: Sequence[str] | None = None) -> None:
parser = _parser()
args = parser.parse_args(argv)
if not hasattr(args, "handler"):
_serve(args)
return
args.handler(args)
if __name__ == "__main__":
main()