(* ========================================================================= *)
(* The law of cosines, of sines, and sum of angles of a triangle. *)
(* ========================================================================= *)
needs "Multivariate/transcendentals.ml";;
prioritize_vector();;
(* ------------------------------------------------------------------------- *)
(* Angle between vectors (always 0 <= angle <= pi). *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Traditional geometric notion of angle (but always 0 <= theta <= pi). *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Lemmas (more than we need for this result). *)
(* ------------------------------------------------------------------------- *)
let VANGLE = prove
(`!x y:real^N. x dot y = norm(x) * norm(y) * cos(vangle x y)`,
let ANGLE_EQ_PI = prove
(`!A B C:real^N. angle(A,B,C) = pi ==> dist(A,C) = dist(A,B) + dist(B,C)`,
REPEAT GEN_TAC THEN REWRITE_TAC[angle] THEN
DISCH_THEN(MP_TAC o MATCH_MP
VANGLE_EQ_PI) THEN
REWRITE_TAC[VECTOR_ARITH `a + x % (b - c) = vec 0 <=> a = x % (c - b)`] THEN
GEN_REWRITE_TAC (funpow 3 LAND_CONV) [
NORM_SUB] THEN
REWRITE_TAC[GSYM
NORM_TRIANGLE_EQ] THEN
REWRITE_TAC[VECTOR_ARITH `(B - A) + (C - B):real^N = C - A`] THEN
REWRITE_TAC[dist;
NORM_SUB]);;
let ANGLE = prove
(`!A B C. (A - C) dot (B - C) = dist(A,C) * dist(B,C) * cos(angle(A,C,B))`,
REWRITE_TAC[angle; dist; GSYM
VANGLE]);;
(* ------------------------------------------------------------------------- *)
(* The law of cosines. *)
(* ------------------------------------------------------------------------- *)
let LAW_OF_COSINES = prove
(`!A B C:real^N.
dist(B,C) pow 2 = dist(A,B) pow 2 + dist(A,C) pow 2 -
&2 * dist(A,B) * dist(A,C) * cos(angle(B,A,C))`,
REPEAT GEN_TAC THEN
REWRITE_TAC[angle; ONCE_REWRITE_RULE[
NORM_SUB] dist; GSYM
VANGLE;
NORM_POW_2] THEN
VECTOR_ARITH_TAC);;
(* ------------------------------------------------------------------------- *)
(* The law of sines. *)
(* ------------------------------------------------------------------------- *)
let LAW_OF_SINES = prove
(`!A B C:real^N.
sin(angle(A,B,C)) * dist(B,C) = sin(angle(B,A,C)) * dist(A,C)`,
REPEAT GEN_TAC THEN MATCH_MP_TAC
REAL_POW_EQ THEN EXISTS_TAC `2` THEN
SIMP_TAC[
SIN_ANGLE_POS;
DIST_POS_LE;
REAL_LE_MUL; ARITH] THEN
REWRITE_TAC[
REAL_POW_MUL; MATCH_MP
(REAL_ARITH `x + y = &1 ==> x = &1 - y`) (SPEC_ALL
SIN_CIRCLE)] THEN
ASM_CASES_TAC `A:real^N = B` THEN ASM_REWRITE_TAC[
ANGLE_REFL;
COS_PI2] THEN
RULE_ASSUM_TAC(ONCE_REWRITE_RULE[GSYM
VECTOR_SUB_EQ]) THEN
RULE_ASSUM_TAC(REWRITE_RULE[GSYM
NORM_EQ_0]) THEN
FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_RING
`~(a = &0) ==> a pow 2 * x = a pow 2 * y ==> x = y`)) THEN
ONCE_REWRITE_TAC[
DIST_SYM] THEN REWRITE_TAC[GSYM dist] THEN
GEN_REWRITE_TAC (RAND_CONV o LAND_CONV o ONCE_DEPTH_CONV) [
DIST_SYM] THEN
REWRITE_TAC[REAL_RING
`a * (&1 - x) * b = c * (&1 - y) * d <=>
a * b - a * b * x = c * d - c * d * y`] THEN
REWRITE_TAC[GSYM
REAL_POW_MUL; GSYM
ANGLE] THEN
REWRITE_TAC[
REAL_POW_MUL; dist;
NORM_POW_2] THEN
REWRITE_TAC[
DOT_LSUB;
DOT_RSUB;
DOT_SYM] THEN CONV_TAC REAL_RING);;
(* ------------------------------------------------------------------------- *)
(* Hence the sum of the angles of a triangle. *)
(* ------------------------------------------------------------------------- *)
let COS_MINUS1_LEMMA = prove
(`!x. cos(x) = -- &1 /\ &0 <= x /\ x < &3 * pi ==> x = pi`,
REPEAT STRIP_TAC THEN
SUBGOAL_THEN `?n. integer n /\ x = n * pi`
(X_CHOOSE_THEN `nn:real` (CONJUNCTS_THEN2 ASSUME_TAC SUBST_ALL_TAC)) THEN
REWRITE_TAC[GSYM
SIN_EQ_0] THENL
[MP_TAC(SPEC `x:real`
SIN_CIRCLE) THEN ASM_REWRITE_TAC[] THEN
CONV_TAC REAL_RING;
ALL_TAC] THEN
SUBGOAL_THEN `?n. nn = &n` (X_CHOOSE_THEN `n:num` SUBST_ALL_TAC) THENL
[FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [
REAL_MUL_POS_LE]) THEN
SIMP_TAC[
PI_POS; REAL_ARITH `&0 < p ==> ~(p < &0) /\ ~(p = &0)`] THEN
ASM_MESON_TAC[
INTEGER_POS;
REAL_LT_LE];
ALL_TAC] THEN
MATCH_MP_TAC(REAL_RING `n = &1 ==> n * p = p`) THEN
REWRITE_TAC[REAL_OF_NUM_EQ] THEN
MATCH_MP_TAC(ARITH_RULE `n < 3 /\ ~(n = 0) /\ ~(n = 2) ==> n = 1`) THEN
RULE_ASSUM_TAC(SIMP_RULE[
REAL_LT_RMUL_EQ;
PI_POS;
REAL_OF_NUM_LT]) THEN
ASM_REWRITE_TAC[] THEN CONJ_TAC THEN DISCH_THEN SUBST_ALL_TAC THEN
REPEAT(POP_ASSUM MP_TAC) THEN SIMP_TAC[
COS_0;
REAL_MUL_LZERO;
COS_NPI] THEN
REAL_ARITH_TAC);;
let TRIANGLE_ANGLE_SUM = prove
(`!A B C:real^N. ~(A = B) /\ ~(A = C) /\ ~(B = C)
==> angle(B,A,C) + angle(A,B,C) + angle(B,C,A) = pi`,