""" Geometry operations for RF propagation calculations. NumPy-dependent modules (haversine, intersection, reflection) are imported lazily so pure-Python modules (diffraction, los) remain available even when NumPy is not installed. """ from app.geometry.diffraction import knife_edge_loss from app.geometry.los import check_los_terrain, fresnel_radius def __getattr__(name): """Lazy import for NumPy-dependent geometry functions.""" _numpy_exports = { "haversine_distance", "haversine_batch", "points_to_local_coords", "line_segments_intersect_batch", "line_intersects_polygons_batch", "calculate_reflection_points_batch", "find_best_reflection_path", } if name in _numpy_exports: if name in ("haversine_distance", "haversine_batch", "points_to_local_coords"): from app.geometry.haversine import haversine_distance, haversine_batch, points_to_local_coords return locals()[name] elif name in ("line_segments_intersect_batch", "line_intersects_polygons_batch"): from app.geometry.intersection import line_segments_intersect_batch, line_intersects_polygons_batch return locals()[name] elif name in ("calculate_reflection_points_batch", "find_best_reflection_path"): from app.geometry.reflection import calculate_reflection_points_batch, find_best_reflection_path return locals()[name] raise AttributeError(f"module 'app.geometry' has no attribute {name!r}") __all__ = [ "haversine_distance", "haversine_batch", "points_to_local_coords", "line_segments_intersect_batch", "line_intersects_polygons_batch", "calculate_reflection_points_batch", "find_best_reflection_path", "knife_edge_loss", "check_los_terrain", "fresnel_radius", ]