defmodule Microwaveprop.Propagation.CommonVolumeTest do use ExUnit.Case, async: true alias Microwaveprop.Propagation.CommonVolume describe "in_common_volume?/4" do test "point at midpoint of two nearby stations is in the common volume" do pos1 = {32.9, -97.0} pos2 = {33.1, -96.8} midpoint = {33.0, -96.9} assert CommonVolume.in_common_volume?(pos1, pos2, midpoint, 400.0) end test "point far from both stations is not in the common volume" do pos1 = {32.9, -97.0} pos2 = {33.1, -96.8} far = {50.0, -50.0} refute CommonVolume.in_common_volume?(pos1, pos2, far, 400.0) end test "point inside circle-1 but outside circle-2 is not in the common volume" do pos1 = {33.0, -97.0} # ~900 km east so radius=400 circles don't overlap there pos2 = {33.0, -87.0} near_pos1 = {33.0, -96.5} assert CommonVolume.in_common_volume?(pos1, pos1, near_pos1, 400.0) refute CommonVolume.in_common_volume?(pos1, pos2, near_pos1, 400.0) end test "endpoints themselves are in the common volume when stations are < 2R apart" do pos1 = {32.9, -97.0} pos2 = {33.1, -96.8} assert CommonVolume.in_common_volume?(pos1, pos2, pos1, 400.0) assert CommonVolume.in_common_volume?(pos1, pos2, pos2, 400.0) end test "nothing is in the common volume when stations are > 2R apart" do pos1 = {33.0, -97.0} # ~2200 km east pos2 = {33.0, -73.0} refute CommonVolume.in_common_volume?(pos1, pos2, pos1, 400.0) end end describe "bounding_box/3" do test "returns min/max lat/lon covering the entire common volume" do pos1 = {32.9, -97.0} pos2 = {33.1, -96.8} bbox = CommonVolume.bounding_box(pos1, pos2, 400.0) # Sanity: midpoint is inside bbox assert bbox.min_lat <= 33.0 and bbox.max_lat >= 33.0 assert bbox.min_lon <= -96.9 and bbox.max_lon >= -96.9 # Bbox shouldn't extend past either individual circle bbox r_deg_lat = 400.0 / 111.32 assert bbox.min_lat >= (pos1 |> elem(0) |> min(elem(pos2, 0))) - r_deg_lat - 0.01 assert bbox.max_lat <= (pos1 |> elem(0) |> max(elem(pos2, 0))) + r_deg_lat + 0.01 end test "returns an empty bbox when the circles don't overlap" do pos1 = {33.0, -97.0} pos2 = {33.0, -73.0} bbox = CommonVolume.bounding_box(pos1, pos2, 400.0) assert bbox == :empty end end describe "area_km2/3" do test "two coincident circles -> area of full circle" do pos = {33.0, -97.0} r = 400.0 assert_in_delta CommonVolume.area_km2(pos, pos, r), :math.pi() * r * r, 1.0 end test "circles just touching -> small area compared to full circle" do # ~800 km apart, radius 400 -> barely overlapping pos1 = {33.0, -97.0} pos2 = {33.0, -88.48} area = CommonVolume.area_km2(pos1, pos2, 400.0) full = :math.pi() * 400.0 * 400.0 assert area >= 0.0 assert area / full < 0.01 end test "non-overlapping circles -> zero area" do pos1 = {33.0, -97.0} pos2 = {33.0, -73.0} assert CommonVolume.area_km2(pos1, pos2, 400.0) == 0.0 end test "partially overlapping circles -> positive area less than a full circle" do pos1 = {33.0, -97.0} # ~400 km apart -> roughly 1/2 circle overlap pos2 = {33.0, -92.7} area = CommonVolume.area_km2(pos1, pos2, 400.0) full = :math.pi() * 400.0 * 400.0 assert area > 0.0 assert area < full end end end