Theory Angles

(* ---------------------------------------------------------------------------- *)
subsection ‹Angle between two vectors›
(* ---------------------------------------------------------------------------- *)

text ‹In this section we introduce different measures of angle between two vectors (represented by complex numbers).›

theory Angles
imports More_Transcendental Canonical_Angle More_Complex
begin

(* ---------------------------------------------------------------------------- *)
subsubsection ‹Oriented angle›
(* ---------------------------------------------------------------------------- *)

text ‹Oriented angle between two vectors (it is always in the interval $(-\pi, \pi]$).›
definition ang_vec ("") where
  [simp]: " z1 z2  Arg z2 - Arg z1"

lemma ang_vec_bounded:
  shows "-pi <  z1 z2   z1 z2  pi"
  by (simp add: canon_ang(1) canon_ang(2))

lemma ang_vec_sym:
  assumes " z1 z2  pi"
  shows " z1 z2 = -  z2 z1"
  using assms
  unfolding ang_vec_def
  using canon_ang_uminus[of "Arg z2 - Arg z1"]
  by simp

lemma ang_vec_sym_pi:
  assumes " z1 z2 = pi"
  shows " z1 z2 =  z2 z1"
  using assms
  unfolding ang_vec_def
  using canon_ang_uminus_pi[of "Arg z2 - Arg z1"]
  by simp

lemma ang_vec_plus_pi1:
  assumes " z1 z2 > 0"
  shows " z1 z2 + pi =  z1 z2 - pi"
proof (rule canon_ang_eqI)
  show " x::int.  z1 z2 - pi - ( z1 z2 + pi) = 2 * real_of_int x * pi"
    by (rule_tac x="-1" in exI) auto
next
  show "- pi <  z1 z2 - pi   z1 z2 - pi  pi"
    using assms
    unfolding ang_vec_def
    using canon_ang(1)[of "Arg z2 - Arg z1"] canon_ang(2)[of "Arg z2 - Arg z1"]
    by auto
qed

lemma ang_vec_plus_pi2:
  assumes " z1 z2  0"
  shows " z1 z2 + pi =  z1 z2 + pi"
proof (rule canon_ang_id)
  show "- pi <  z1 z2 + pi   z1 z2 + pi  pi"
    using assms
    unfolding ang_vec_def
    using canon_ang(1)[of "Arg z2 - Arg z1"] canon_ang(2)[of "Arg z2 - Arg z1"]
    by auto
qed

lemma ang_vec_opposite1:
  assumes "z1  0"
  shows " (-z1) z2 =  z1 z2 - pi"
proof-
  have " (-z1) z2 = Arg z2 - (Arg z1 + pi)"
    unfolding ang_vec_def
    using arg_uminus[OF assms] 
    using canon_ang_arg[of z2, symmetric]
    using canon_ang_diff[of "Arg z2" "Arg z1 + pi", symmetric]
    by simp
  moreover
  have " z1 z2 - pi = Arg z2 - Arg z1 - pi"
    using canon_ang_id[of pi, symmetric]
    using canon_ang_diff[of "Arg z2 - Arg z1" "pi", symmetric]
    by simp_all
  ultimately
  show ?thesis
    by (simp add: field_simps)
qed

lemma ang_vec_opposite2:
  assumes "z2  0"
  shows " z1 (-z2) =  z1 z2 + pi"
  unfolding ang_vec_def
  using arg_mult[of "-1" "z2"] assms
  using arg_complex_of_real_negative[of "-1"]
  using canon_ang_diff[of "Arg (-1) + Arg z2" "Arg z1", symmetric]
  using canon_ang_sum[of "Arg z2 - Arg z1" "pi", symmetric]
  using canon_ang_id[of pi] canon_ang_arg[of z1]
  by (auto simp: algebra_simps)
  

lemma ang_vec_opposite_opposite:
  assumes "z1  0" and "z2  0"
  shows " (-z1) (-z2) =  z1 z2"
proof-
  have " (-z1) (-z2) =  z1 z2 + pi - pi"
    using ang_vec_opposite1[OF assms(1)]
    using ang_vec_opposite2[OF assms(2)]
    using canon_ang_id[of pi, symmetric]
    by simp_all
  also have "... =  z1 z2"
    by (subst canon_ang_diff[symmetric], simp)
  finally
  show ?thesis
    by (metis ang_vec_def canon_ang(1) canon_ang(2) canon_ang_id)
qed

lemma ang_vec_opposite_opposite':
  assumes "z1  z" and "z2  z"
  shows " (z - z1) (z - z2) =  (z1 - z) (z2 - z)"
using ang_vec_opposite_opposite[of "z - z1" "z - z2"] assms
by (simp add: field_simps del: ang_vec_def)

text ‹Cosine, scalar product and the law of cosines›

lemma cos_cmod_scalprod:
  shows "cmod z1 * cmod z2 * (cos ( z1 z2)) = Re (scalprod z1 z2)"
proof (cases "z1 = 0  z2 = 0")
  case True
  thus ?thesis
    by auto
next
  case False
  thus ?thesis
    by (simp add: cos_diff cos_arg sin_arg field_simps)
qed

lemma cos0_scalprod0:
  assumes "z1  0" and "z2  0"
  shows "cos ( z1 z2) = 0  scalprod z1 z2 = 0"
  using assms
  using cnj_mix_real[of z1 z2]
  using cos_cmod_scalprod[of z1 z2]
  by (auto simp add: complex_eq_if_Re_eq)

lemma ortho_scalprod0:
  assumes "z1  0" and "z2  0"
  shows " z1 z2 = pi/2   z1 z2 = -pi/2  scalprod z1 z2 = 0"
  using cos0_scalprod0[OF assms]
  using ang_vec_bounded[of z1 z2]
  using cos_0_iff_canon[of " z1 z2"]
  by (metis cos_minus cos_pi_half divide_minus_left)

lemma law_of_cosines:
  shows "(cdist B C)2 = (cdist A C)2 + (cdist A B)2 - 2*(cdist A C)*(cdist A B)*(cos ( (C-A) (B-A)))"
proof-
  let ?a = "C-B" and ?b = "C-A" and ?c = "B-A"
  have "?a = ?b - ?c"
    by simp
  hence "(cmod ?a)2 = (cmod (?b - ?c))2"
    by metis
  also have "... = Re (scalprod (?b-?c) (?b-?c))"
    by (simp add: cmod_square)
  also have "... = (cmod ?b)2 + (cmod ?c)2 - 2*Re (scalprod ?b ?c)"
    by (simp add: cmod_square field_simps)
  finally
  show ?thesis
    using cos_cmod_scalprod[of ?b ?c]
    by simp
qed

(* ---------------------------------------------------------------------------- *)
subsubsection ‹Unoriented angle›
(* ---------------------------------------------------------------------------- *)

text ‹Convex unoriented angle between two vectors (it is always in the interval $[0, pi]$).›
definition ang_vec_c ("∠c") where
  [simp]:"∠c z1 z2  abs ( z1 z2)"

lemma ang_vec_c_sym:
  shows "∠c z1 z2 = ∠c z2 z1"
  unfolding ang_vec_c_def
  using ang_vec_sym_pi[of z1 z2] ang_vec_sym[of z1 z2]
  by (cases " z1 z2 = pi") auto

lemma ang_vec_c_bounded: "0  ∠c z1 z2  ∠c z1 z2  pi"
  using canon_ang(1)[of "Arg z2 - Arg z1"] canon_ang(2)[of "Arg z2 - Arg z1"]
  by auto

text ‹Cosine and scalar product›

lemma cos_c_: "cos (∠c z1 z2) = cos ( z1 z2)"
  unfolding ang_vec_c_def
  by (smt cos_minus)

lemma ortho_c_scalprod0:
  assumes "z1  0" and "z2  0"
  shows "∠c z1 z2 = pi/2  scalprod z1 z2 = 0"
proof-
  have " z1 z2 = pi / 2   z1 z2 = - pi / 2  ∠c z1 z2 = pi/2"
    unfolding ang_vec_c_def
    using arctan 
    by force
  thus ?thesis
    using ortho_scalprod0[OF assms]
    by simp
qed

(* ---------------------------------------------------------------------------- *)
subsubsection ‹Acute angle›
(* ---------------------------------------------------------------------------- *)

text ‹Acute or right angle (non-obtuse) between two vectors (it is always in the interval $[0, \frac{\pi}{2}$]).
We will use this to measure angle between two circles, since it can always be acute (or right).›

definition acute_ang where
  [simp]: "acute_ang α = (if α > pi / 2 then pi - α else α)"

definition ang_vec_a ("∠a") where
  [simp]: "∠a z1 z2  acute_ang (∠c z1 z2)"

lemma ang_vec_a_sym:
  "∠a z1 z2 = ∠a z2 z1"
  unfolding ang_vec_a_def
  using ang_vec_c_sym
  by auto

lemma ang_vec_a_opposite2:
  "∠a z1 z2 = ∠a z1 (-z2)"
proof(cases "z2  = 0")
  case True
  thus ?thesis
    by (metis minus_zero)
next
  case False
  thus ?thesis
  proof(cases " z1 z2 < -pi / 2")
    case True
    hence " z1 z2 < 0"
      using pi_not_less_zero
      by linarith
    have "∠a z1 z2 = pi +  z1 z2"
      using True  z1 z2 < 0
      unfolding ang_vec_a_def ang_vec_c_def ang_vec_a_def abs_real_def
      by auto
    moreover
    have "∠a z1 (-z2) = pi +  z1 z2"
      unfolding ang_vec_a_def ang_vec_c_def abs_real_def
      using canon_ang(1)[of "Arg z2 - Arg z1"] canon_ang(2)[of "Arg z2 - Arg z1"]
      using ang_vec_plus_pi2[of z1 z2] True  z1 z2 < 0 z2  0
      using ang_vec_opposite2[of z2 z1]
      by auto
    ultimately
    show ?thesis
      by auto
  next
    case False
    show ?thesis
    proof (cases " z1 z2  0")
      case True
      have "∠a z1 z2 = -  z1 z2"
        using ¬  z1 z2 < - pi / 2 True
        unfolding ang_vec_a_def ang_vec_c_def ang_vec_a_def abs_real_def
        by auto
      moreover
      have "∠a z1 (-z2) = -  z1 z2"
        using ¬  z1 z2 < - pi / 2 True
        unfolding ang_vec_a_def ang_vec_c_def abs_real_def
        using ang_vec_plus_pi2[of z1 z2]
        using canon_ang(1)[of "Arg z2 - Arg z1"] canon_ang(2)[of "Arg z2 - Arg z1"]
        using z2  0 ang_vec_opposite2[of z2 z1]
        by auto
      ultimately
      show ?thesis
        by simp
    next
      case False
      show ?thesis
      proof (cases " z1 z2 < pi / 2")
        case True
        have "∠a z1 z2 =  z1 z2"
          using ¬  z1 z2  0 True
          unfolding ang_vec_a_def ang_vec_c_def ang_vec_a_def abs_real_def
          by auto
        moreover
        have "∠a z1 (-z2) =  z1 z2"
          using ¬  z1 z2  0 True
          unfolding ang_vec_a_def ang_vec_c_def abs_real_def
          using ang_vec_plus_pi1[of z1 z2]
          using canon_ang(1)[of "Arg z2 - Arg z1"] canon_ang(2)[of "Arg z2 - Arg z1"]
          using z2  0 ang_vec_opposite2[of z2 z1]
          by auto
        ultimately
        show ?thesis
          by simp
      next
        case False
        have " z1 z2 > 0"
          using False
          by (metis less_linear less_trans pi_half_gt_zero)
        have "∠a z1 z2 = pi -  z1 z2"
          using False  z1 z2 > 0
          unfolding ang_vec_a_def ang_vec_c_def ang_vec_a_def abs_real_def
          by auto
        moreover
        have "∠a z1 (-z2) = pi -  z1 z2"
          unfolding ang_vec_a_def ang_vec_c_def abs_real_def
          using False  z1 z2 > 0
          using ang_vec_plus_pi1[of z1 z2]
          using canon_ang(1)[of "Arg z2 - Arg z1"] canon_ang(2)[of "Arg z2 - Arg z1"]
          using z2  0 ang_vec_opposite2[of z2 z1]
          by auto
        ultimately
        show ?thesis
          by auto
      qed
    qed
  qed
qed

lemma ang_vec_a_opposite1:
  shows "∠a z1 z2 = ∠a (-z1) z2"
  using ang_vec_a_sym[of "-z1" z2] ang_vec_a_opposite2[of z2 z1] ang_vec_a_sym[of z2 z1]
  by auto

lemma ang_vec_a_scale1:
  assumes "k  0"
  shows "∠a (cor k * z1) z2 = ∠a z1 z2"
proof (cases "k > 0")
  case True
  thus ?thesis
    unfolding ang_vec_a_def ang_vec_c_def ang_vec_def
    using arg_mult_real_positive[of k z1]
    by auto
next
  case False
  hence "k < 0"
    using assms
    by auto
  thus ?thesis
    using arg_mult_real_negative[of k z1]
    using ang_vec_a_opposite1[of z1 z2]
    unfolding ang_vec_a_def ang_vec_c_def ang_vec_def
    by simp
qed

lemma ang_vec_a_scale2:
  assumes "k  0"
  shows "∠a z1 (cor k * z2) = ∠a z1 z2"
  using ang_vec_a_sym[of z1 "complex_of_real k * z2"]
  using ang_vec_a_scale1[OF assms, of z2 z1]
  using ang_vec_a_sym[of z1 z2]
  by auto

lemma ang_vec_a_scale:
  assumes "k1  0" and "k2  0"
  shows "∠a (cor k1 * z1) (cor k2 * z2) = ∠a z1 z2"
  using ang_vec_a_scale1[OF assms(1)] ang_vec_a_scale2[OF assms(2)]
  by auto

lemma ang_a_cnj_cnj:
  shows "∠a z1 z2 = ∠a (cnj z1) (cnj z2)"
unfolding ang_vec_a_def ang_vec_c_def ang_vec_def
proof(cases "Arg z1  pi  Arg z2  pi")
  case True
  thus "acute_ang ¦Arg z2 - Arg z1¦ = acute_ang ¦Arg (cnj z2) - Arg (cnj z1)¦"
    using arg_cnj_not_pi[of z1] arg_cnj_not_pi[of z2]
    apply (auto simp del:acute_ang_def)
    proof(cases "Arg z2 - Arg z1 = pi")
      case True
      thus "acute_ang ¦Arg z2 - Arg z1¦ = acute_ang ¦Arg z1 - Arg z2¦"
        using  canon_ang_uminus_pi[of "Arg z2 - Arg z1"]
        by (auto simp add:field_simps)
    next
      case False
      thus "acute_ang ¦Arg z2 - Arg z1¦ = acute_ang ¦Arg z1 - Arg z2¦"
        using  canon_ang_uminus[of "Arg z2 - Arg z1"]
        by (auto simp add:field_simps)
    qed
  next
    case False
    thus "acute_ang ¦Arg z2 - Arg z1¦ = acute_ang ¦Arg (cnj z2) - Arg (cnj z1)¦"
    proof(cases "Arg z1 = pi")
      case False
      hence "Arg z2 = pi"
        using ¬ (Arg z1  pi  Arg z2  pi)
        by auto
      thus ?thesis
        using False
        using arg_cnj_not_pi[of z1] arg_cnj_pi[of z2]
        apply (auto simp del:acute_ang_def)
      proof(cases "Arg z1 > 0")
          case True
          hence "-Arg z1  0"
            by auto
          thus "acute_ang ¦pi - Arg z1¦ = acute_ang ¦pi + Arg z1¦"
            using True canon_ang_plus_pi1[of "Arg z1"]
            using Arg_bounded[of z1] canon_ang_plus_pi2[of "-Arg z1"]
            by (auto simp add:field_simps)
        next
          case False
          hence "-Arg z1  0"
             by simp
          thus "acute_ang ¦pi - Arg z1¦ = acute_ang ¦pi + Arg z1¦"
          proof(cases "Arg z1 = 0")
            case True
            thus ?thesis
              by (auto simp del:acute_ang_def)
          next
            case False
            hence "-Arg z1 > 0"
              using -Arg z1  0
              by auto
            thus ?thesis
            using False canon_ang_plus_pi1[of "-Arg z1"]
            using Arg_bounded[of z1] canon_ang_plus_pi2[of "Arg z1"]
            by (auto simp add:field_simps)
        qed
      qed
    next
      case True
      thus ?thesis
        using arg_cnj_pi[of z1]
        apply (auto simp del:acute_ang_def)
      proof(cases "Arg z2 = pi")
        case True
        thus "acute_ang ¦Arg z2 - pi¦ = acute_ang ¦Arg (cnj z2) - pi¦"
          using arg_cnj_pi[of z2]
          by auto
      next
        case False
        thus "acute_ang ¦Arg z2 - pi¦ = acute_ang ¦Arg (cnj z2) - pi¦"
          using arg_cnj_not_pi[of z2]
          apply (auto simp del:acute_ang_def)
        proof(cases "Arg z2 > 0")
          case True
          hence "-Arg z2  0"
            by auto
          thus "acute_ang ¦Arg z2 - pi¦ = acute_ang ¦- Arg z2 - pi¦"
            using True canon_ang_minus_pi1[of "Arg z2"]
            using Arg_bounded[of z2] canon_ang_minus_pi2[of "-Arg z2"]
            by (auto simp add: field_simps)
        next
          case False
          hence "-Arg z2  0"
             by simp
          thus "acute_ang ¦Arg z2 - pi¦ = acute_ang ¦- Arg z2 - pi¦"
          proof(cases "Arg z2 = 0")
            case True
            thus ?thesis
              by (auto simp del:acute_ang_def)
          next
            case False
            hence "-Arg z2 > 0"
              using -Arg z2  0
              by auto
            thus ?thesis
            using False canon_ang_minus_pi1[of "-Arg z2"]
            using Arg_bounded[of z2] canon_ang_minus_pi2[of "Arg z2"]
            by (auto simp add:field_simps)
        qed
      qed
    qed
  qed
qed

text ‹Cosine and scalar product›

lemma ortho_a_scalprod0:
  assumes "z1  0" and "z2  0"
  shows "∠a z1 z2 = pi/2  scalprod z1 z2 = 0"
  unfolding ang_vec_a_def
  using assms ortho_c_scalprod0[of z1 z2]
  by auto

declare ang_vec_c_def[simp del]

lemma cos_a_c: "cos (∠a z1 z2) = abs (cos (∠c z1 z2))"
proof-
  have "0  ∠c z1 z2" "∠c z1 z2  pi"
    using ang_vec_c_bounded[of z1 z2]
    by auto
  show ?thesis
  proof (cases "∠c z1 z2 = pi/2")
    case True
    thus ?thesis
      unfolding ang_vec_a_def acute_ang_def
      by (smt cos_pi_half pi_def pi_half)
  next
    case False
    show ?thesis
    proof (cases "∠c z1 z2 < pi / 2")
      case True
      thus ?thesis
        using 0  ∠c z1 z2
        using cos_gt_zero_pi[of "∠c z1 z2"]
        unfolding ang_vec_a_def
        by simp
    next
      case False
      hence "∠c z1 z2 > pi/2"
        using ∠c z1 z2  pi/2
        by simp
      hence "cos (∠c z1 z2) < 0"
        using ∠c z1 z2  pi
        using cos_lt_zero_on_pi2_pi[of "∠c z1 z2"] 
        by simp
      thus ?thesis
        using ∠c z1 z2 > pi/2
        unfolding ang_vec_a_def
        by simp
    qed
  qed
qed

end