Require Export GeoCoq.Tarski_dev.Ch12_parallel_inter_dec.
Require Export GeoCoq.Tarski_dev.Annexes.Tagged_predicates.

Ltac image_6 A B P' H P:=
 let T:= fresh in assert (T:= l10_6_existence A B P' H);
 ex_and T P.

Ltac image A B P P':=
 let T:= fresh in assert (T:= l10_2_existence A B P);
 ex_and T P'.

Ltac perp A B C X :=
 match goal with
   | H:(~Col A B C) |- _ =>
    let T:= fresh in assert (T:= l8_18_existence A B C H);
    ex_and T X
 end.

Ltac parallel A B C D P :=
 match goal with
   | H:(A <> B) |- _ =>
    let T := fresh in assert(T:= parallel_existence A B P H);
    ex_and T C
 end.

Ltac par_strict :=
repeat
 match goal with
      | H: Par_strict ?A ?B ?C ?D |- _ =>
       let T := fresh in not_exist_hyp (Par_strict B A D C); assert (T := par_strict_comm A B C D H)  
      | H: Par_strict ?A ?B ?C ?D |- _ =>
       let T := fresh in not_exist_hyp (Par_strict C D A B); assert (T := par_strict_symmetry A B C D H)  
      | H: Par_strict ?A ?B ?C ?D |- _ =>
       let T := fresh in not_exist_hyp (Par_strict B A C D); assert (T := par_strict_left_comm A B C D H)   
      | H: Par_strict ?A ?B ?C ?D |- _ =>
       let T := fresh in not_exist_hyp (Par_strict A B D C); assert (T := par_strict_right_comm A B C D H) 
 end.

Ltac clean_trivial_hyps :=
  repeat
  match goal with
   | H:(Cong ?X1 ?X1 ?X2 ?X2) |- _ => clear H
   | H:(Cong ?X1 ?X2 ?X2 ?X1) |- _ => clear H
   | H:(Cong ?X1 ?X2 ?X1 ?X2) |- _ => clear H
   | H:(Bet ?X1 ?X1 ?X2) |- _ => clear H
   | H:(Bet ?X2 ?X1 ?X1) |- _ => clear H
   | H:(Col ?X1 ?X1 ?X2) |- _ => clear H
   | H:(Col ?X2 ?X1 ?X1) |- _ => clear H
   | H:(Col ?X1 ?X2 ?X1) |- _ => clear H
   | H:(Par ?X1 ?X2 ?X1 ?X2) |- _ => clear H
   | H:(Par ?X1 ?X2 ?X2 ?X1) |- _ => clear H
   | H:(Per ?X1 ?X2 ?X2)     |- _ => clear H
   | H:(Per ?X1 ?X1 ?X2)     |- _ => clear H
   | H:(Midpoint ?X1 ?X1 ?X1) |- _ => clear H
end.

Ltac show_distinct2 := unfold not;intro;treat_equalities; try (solve [intuition]).

Ltac symmetric A B A' :=
 let T := fresh in assert(T:= symmetric_point_construction A B);
 ex_and T A'.

Tactic Notation "Name" ident(X) "the" "symmetric" "of" ident(A) "wrt" ident(C) :=
 symmetric A C X.

Ltac sfinish := repeat match goal with
 | |- Bet ?A ?B ?C => Between; eBetween
 | |- Col ?A ?B ?C => Col;ColR
 | |- ~ Col ?A ?B ?C => Col
 | |- ~ Col ?A ?B ?C => intro;search_contradiction
 | |- Par ?A ?B ?C ?D => Par
 | |- Par_strict ?A ?B ?C ?D => Par
 | |- Perp ?A ?B ?C ?D => Perp
 | |- Perp_at ?A ?B ?C ?D ?E => Perp
 | |- Per ?A ?B ?C => Perp
 | |- Cong ?A ?B ?C ?D => Cong;eCong
 | |- Midpoint ?A ?B ?C => Midpoint
 | |- ?A<>?B => apply swap_diff;assumption
 | |- ?A<>?B => intro;treat_equalities; solve [search_contradiction]
 | |- ?G1 /\ ?G2 => split
 | |- _ => try assumption
end.

Ltac clean_reap_hyps :=
  clean_duplicated_hyps;
  repeat
  match goal with
   | H:(Parallelogram ?A ?B ?C ?D), H2 : Parallelogram ?B ?C ?D ?A |- _ => clear H2
   | H:(Parallelogram ?A ?B ?C ?D), H2 : Parallelogram ?C ?D ?A ?B |- _ => clear H2
   | H:(Parallelogram ?A ?B ?C ?D), H2 : Parallelogram ?D ?A ?B ?C |- _ => clear H2
   | H:(Parallelogram ?A ?B ?C ?D), H2 : Parallelogram ?D ?C ?B ?A |- _ => clear H2
   | H:(Parallelogram ?A ?B ?C ?D), H2 : Parallelogram ?C ?B ?A ?D |- _ => clear H2
   | H:(Parallelogram ?A ?B ?C ?D), H2 : Parallelogram ?B ?A ?D ?C |- _ => clear H2
   | H:(Parallelogram ?A ?B ?C ?D), H2 : Parallelogram ?A ?D ?C ?B |- _ => clear H2
   | H:(Par ?A ?B ?C ?D), H2 : Par ?A ?B ?D ?C |- _ => clear H2
   | H:(Par ?A ?B ?C ?D), H2 : Par ?C ?D ?A ?B |- _ => clear H2
   | H:(Par ?A ?B ?C ?D), H2 : Par ?C ?D ?B ?A |- _ => clear H2
   | H:(Par ?A ?B ?C ?D), H2 : Par ?D ?C ?B ?A |- _ => clear H2
   | H:(Par ?A ?B ?C ?D), H2 : Par ?D ?C ?A ?B |- _ => clear H2
   | H:(Par ?A ?B ?C ?D), H2 : Par ?B ?A ?C ?D |- _ => clear H2
   | H:(Par ?A ?B ?C ?D), H2 : Par ?B ?A ?D ?C |- _ => clear H2
   | H:(Par_strict ?A ?B ?C ?D), H2 : Par_strict ?A ?B ?D ?C |- _ => clear H2
   | H:(Par_strict ?A ?B ?C ?D), H2 : Par_strict ?C ?D ?A ?B |- _ => clear H2
   | H:(Par_strict ?A ?B ?C ?D), H2 : Par_strict ?C ?D ?B ?A |- _ => clear H2
   | H:(Par_strict ?A ?B ?C ?D), H2 : Par_strict ?D ?C ?B ?A |- _ => clear H2
   | H:(Par_strict ?A ?B ?C ?D), H2 : Par_strict ?D ?C ?A ?B |- _ => clear H2
   | H:(Par_strict ?A ?B ?C ?D), H2 : Par_strict ?B ?A ?C ?D |- _ => clear H2
   | H:(Par_strict ?A ?B ?C ?D), H2 : Par_strict ?B ?A ?D ?C |- _ => clear H2
   | H:(Perp ?A ?B ?C ?D), H2 : Perp ?A ?B ?D ?C |- _ => clear H2
   | H:(Perp ?A ?B ?C ?D), H2 : Perp ?C ?D ?A ?B |- _ => clear H2
   | H:(Perp ?A ?B ?C ?D), H2 : Perp ?C ?D ?B ?A |- _ => clear H2
   | H:(Perp ?A ?B ?C ?D), H2 : Perp ?D ?C ?B ?A |- _ => clear H2
   | H:(Perp ?A ?B ?C ?D), H2 : Perp ?D ?C ?A ?B |- _ => clear H2
   | H:(Perp ?A ?B ?C ?D), H2 : Perp ?B ?A ?C ?D |- _ => clear H2
   | H:(Perp ?A ?B ?C ?D), H2 : Perp ?B ?A ?D ?C |- _ => clear H2
   | H:(Perp_at ?X ?A ?B ?C ?D), H2 : Perp_at ?X ?A ?B ?D ?C |- _ => clear H2
   | H:(Perp_at ?X ?A ?B ?C ?D), H2 : Perp_at ?X ?C ?D ?A ?B |- _ => clear H2
   | H:(Perp_at ?X ?A ?B ?C ?D), H2 : Perp_at ?X ?C ?D ?B ?A |- _ => clear H2
   | H:(Perp_at ?X ?A ?B ?C ?D), H2 : Perp_at ?X ?D ?C ?B ?A |- _ => clear H2
   | H:(Perp_at ?X ?A ?B ?C ?D), H2 : Perp_at ?X ?D ?C ?A ?B |- _ => clear H2
   | H:(Perp_at ?X ?A ?B ?C ?D), H2 : Perp_at ?X ?B ?A ?C ?D |- _ => clear H2
   | H:(Perp_at ?X ?A ?B ?C ?D), H2 : Perp_at ?X ?B ?A ?D ?C |- _ => clear H2
   | H:(Per ?A ?B ?C), H2 : Per ?C ?B ?A |- _ => clear H2
   | H:(Midpoint ?A ?B ?C), H2 : Midpoint ?A ?C ?B |- _ => clear H2
   | H:(~Col ?A ?B ?C), H2 : (~Col ?B ?A ?C) |- _ => clear H2
   | H:(~Col ?A ?B ?C), H2 : (~Col ?B ?C ?A) |- _ => clear H2
   | H:(~Col ?A ?B ?C), H2 : (~Col ?C ?B ?A) |- _ => clear H2
   | H:(~Col ?A ?B ?C), H2 : (~Col ?C ?A ?B) |- _ => clear H2
   | H:(~Col ?A ?B ?C), H2 : (~Col ?A ?C ?B) |- _ => clear H2
   | H:(Col ?A ?B ?C), H2 : Col ?A ?C ?B |- _ => clear H2
   | H:(Col ?A ?B ?C), H2 : Col ?B ?A ?C |- _ => clear H2
   | H:(Col ?A ?B ?C), H2 : Col ?B ?C ?A |- _ => clear H2
   | H:(Col ?A ?B ?C), H2 : Col ?C ?B ?A |- _ => clear H2
   | H:(Col ?A ?B ?C), H2 : Col ?C ?A ?B |- _ => clear H2
   | H:(Bet ?A ?B ?C), H2 : Bet ?C ?B ?A |- _ => clear H2
   | H:(Cong ?A ?B ?C ?D), H2 : Cong ?A ?B ?D ?C |- _ => clear H2
   | H:(Cong ?A ?B ?C ?D), H2 : Cong ?C ?D ?A ?B |- _ => clear H2
   | H:(Cong ?A ?B ?C ?D), H2 : Cong ?C ?D ?B ?A |- _ => clear H2
   | H:(Cong ?A ?B ?C ?D), H2 : Cong ?D ?C ?B ?A |- _ => clear H2
   | H:(Cong ?A ?B ?C ?D), H2 : Cong ?D ?C ?A ?B |- _ => clear H2
   | H:(Cong ?A ?B ?C ?D), H2 : Cong ?B ?A ?C ?D |- _ => clear H2
   | H:(Cong ?A ?B ?C ?D), H2 : Cong ?B ?A ?D ?C |- _ => clear H2
   | H:(?A<>?B), H2 : (?B<>?A) |- _ => clear H2
end.

Ltac tag_hyps :=
  repeat
  match goal with
    | H : ?A <> ?B |- _ => apply Diff_Diff_tagged in H
    | H : Cong ?A ?B ?C ?D |- _ => apply Cong_Cong_tagged in H
    | H : Bet ?A ?B ?C |- _ => apply Bet_Bet_tagged in H
    | H : Col ?A ?B ?C |- _ => apply Col_Col_tagged in H
    | H : ~ Col ?A ?B ?C |- _ => apply NCol_NCol_tagged in H
    | H : Midpoint ?A ?B ?C |- _ => apply Mid_Mid_tagged in H
    | H : Per ?A ?B ?C |- _ => apply Per_Per_tagged in H
    | H : Perp_at ?X ?A ?B ?C ?D |- _ => apply Perp_in_Perp_in_tagged in H
    | H : Perp ?A ?B ?C ?D |- _ => apply Perp_Perp_tagged in H
    | H : Par_strict ?A ?B ?C ?D |- _ => apply Par_strict_Par_strict_tagged in H
    | H : Par ?A ?B ?C ?D |- _ => apply Par_Par_tagged in H
    | H : Parallelogram ?A ?B ?C ?D |- _ => apply Plg_Plg_tagged in H
  end.

Ltac permutation_intro_in_goal :=
 match goal with
 | |- Par ?A ?B ?C ?D => apply Par_cases
 | |- Par_strict ?A ?B ?C ?D => apply Par_strict_cases
 | |- Perp ?A ?B ?C ?D => apply Perp_cases
 | |- Perp_at ?X ?A ?B ?C ?D => apply Perp_in_cases
 | |- Per ?A ?B ?C => apply Per_cases
 | |- Midpoint ?A ?B ?C => apply Mid_cases
 | |- ~ Col ?A ?B ?C => apply NCol_cases
 | |- Col ?A ?B ?C => apply Col_cases
 | |- Bet ?A ?B ?C => apply Bet_cases
 | |- Cong ?A ?B ?C ?D => apply Cong_cases
 end.

Ltac perm_apply t :=
 permutation_intro_in_goal;
 try_or ltac:(apply t;solve [finish]).

Ltac assert_ncols :=
repeat
  match goal with
      | H:OS ?A ?B ?X ?Y |- _ =>
     not_exist_hyp_perm_ncol A B X;assert (~ Col A B X) by (apply(one_side_not_col123 A B X Y);finish)

      | H:OS ?A ?B ?X ?Y |- _ =>
     not_exist_hyp_perm_ncol A B Y;assert (~ Col A B Y) by (apply(one_side_not_col124 A B X Y);finish)

      | H:TS ?A ?B ?X ?Y |- _ =>
     not_exist_hyp_perm_ncol A B X;assert (~ Col A B X) by (apply(two_sides_not_col A B X Y);finish)

      | H:TS ?A ?B ?X ?Y |- _ =>
     not_exist_hyp_perm_ncol A B Y;assert (~ Col A B Y) by (apply(two_sides_not_col A B Y X);finish)

      | H:~ Coplanar ?A ?B ?C ?D |- _ =>
      let h := fresh in
      not_exist_hyp_perm4 A B C D;
      assert (h := ncop__ncols A B C D H);decompose [and] h;clear h;clean_reap_hyps

      | H:Par_strict ?A ?B ?C ?D |- _ =>
      let h := fresh in
      not_exist_hyp_perm4 A B C D;
      assert (h := par_strict_not_cols A B C D H);decompose [and] h;clear h;clean_reap_hyps

      | H:Parallelogram_strict ?A ?B ?C ?D |- _ =>
      let h := fresh in
      not_exist_hyp_perm4 A B C D;
      assert (h := plgs_not_col A B C D H);decompose [and] h;clear h;clean_reap_hyps
  end.

Section Quadrilateral_inter_dec_1.

Context `{TE:Tarski_euclidean}.

Lemma par_cong_mid_ts :
 forall A B A' B',
  Par_strict A B A' B' ->
  Cong A B A' B' ->
  TS A A' B B' ->
  exists M,  Midpoint M A A' /\ Midpoint M B B'.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.

(* Goal: and (@Par Tn A B C D) (@Par Tn A D B C) *)
assert(HH:= H1).
(* Goal: @InAngle Tn D A B C *)
unfold TS in HH.
assert(~ Col B A A').
spliter; assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
ex_and H5 M.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
exists M.

(* Goal: @InAngle Tn D A B C *)
assert(HH:= H).
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
unfold Par_strict in HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(HH:=(midpoint_existence A A')).
ex_and HH X.

prolong B X B'' B X.
assert(Midpoint X B B'').
(* Goal: @Midpoint Tn M B D' *)
(* Goal: @Midpoint Tn M B D *)
unfold Midpoint.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Cong Tn A B B C *)
Cong.

assert(Par_strict B A B'' A').
apply (midpoint_par_strict B A B'' A' X); auto.

assert(Col B'' B' A' /\ Col A' B' A').
apply(parallel_uniqueness B A B' A' B'' A' A').
(* Goal: @Par Tn B A D C *)
(* Goal: @Cong Tn B A D C *)
apply par_comm.
(* Goal: @Par Tn A B A' B' *)
(* Goal: not (@Par_strict Tn A B A' B') *)
(* Goal: @Cong Tn A B A' B' *)
unfold Par.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Par Tn A B A' B' *)
(* Goal: not (@Par_strict Tn A B A' B') *)
(* Goal: @Cong Tn A B A' B' *)
unfold Par.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(Cong A B A' B'').
eapply l7_13.
apply l7_2.
(* Goal: False *)
(* Goal: False *)
apply H11.
apply l7_2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
assert(Cong A' B' A' B'').
eapply cong_transitivity.
apply cong_symmetry.
(* Goal: False *)
(* Goal: not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D)) *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
apply H0.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(B' = B'' \/ Midpoint A' B' B'').
(* Goal: or (@eq (@Tpoint Tn) B D) (@Midpoint Tn A B D) *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
eapply l7_20.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Cong Tn A B B C *)
Cong.
induction H20.

subst B''.

assert(X = M).
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
eapply (l6_21 A A' B B'); Col.

(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
subst B'.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H10.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A B) (@Col Tn X C B)) *)
(* Goal: @Plg Tn A B C D *)
exists B.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
subst X.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
split; auto.

assert(TS A A' B B'').
(* Goal: @TS Tn B D A C *)
unfold TS.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
repeat split; auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply col_permutation_1.
eapply (col_transitivity_1 _ B'').
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst B''.
apply l7_2 in H20.
apply is_midpoint_id in H20.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
exists X.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.

unfold Midpoint in H11.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply bet_col in H11.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(OS A A' B' B'').
eapply l9_8_1.
apply l9_2.
apply H1.
apply l9_2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(TS A A' B' B'').
(* Goal: @TS Tn B D A C *)
unfold TS.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.

(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply col_permutation_1.
eapply (col_transitivity_1 _ B'').
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst B''.
apply l7_2 in H20.
apply is_midpoint_id in H20.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X B A')) *)
(* Goal: False *)
exists A'.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
unfold Midpoint in H20.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply l9_9 in H23.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
Qed.

Lemma par_cong_mid_os :
  forall A B A' B',
   Par_strict A B A' B' ->
   Cong A B A' B' ->
   OS A A' B B' ->
   exists M, Midpoint M A B' /\ Midpoint M B A'.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @InAngle Tn D A B C *)
assert(HH:= H).
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
unfold Par_strict in HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(HH:=(midpoint_existence A' B)).
ex_and HH X.
exists X.

prolong A X B'' A X.
assert(Midpoint X A B'').
(* Goal: @Midpoint Tn M B D' *)
(* Goal: @Midpoint Tn M B D *)
unfold Midpoint.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Cong Tn A B B C *)
Cong.

assert(~Col A B A').
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
apply H5.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X B A')) *)
(* Goal: False *)
exists A'.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.

assert(Par_strict  A B B'' A').
apply (midpoint_par_strict A B  B'' A' X).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply l7_2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(Col B'' B' A' /\ Col A' B' A').
apply (parallel_uniqueness B A B' A' B'' A' A').

(* Goal: @Par Tn B A D C *)
(* Goal: @Cong Tn B A D C *)
apply par_comm.
(* Goal: @Par Tn A B A' B' *)
(* Goal: not (@Par_strict Tn A B A' B') *)
(* Goal: @Cong Tn A B A' B' *)
unfold Par.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Par Tn B C A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
apply par_left_comm.
(* Goal: @Par Tn A B A' B' *)
(* Goal: not (@Par_strict Tn A B A' B') *)
(* Goal: @Cong Tn A B A' B' *)
unfold Par.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(Cong A B  B'' A').
eapply l7_13.
apply l7_2.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H9.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
assert(Cong A' B' A' B'').
eapply cong_transitivity.
apply cong_symmetry.
(* Goal: False *)
(* Goal: not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D)) *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
apply H0.
(* Goal: @Cong Tn A B B C *)
Cong.
assert(B' = B'' \/ Midpoint A' B' B'').
(* Goal: or (@eq (@Tpoint Tn) B D) (@Midpoint Tn A B D) *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
eapply l7_20.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Cong Tn A B B C *)
Cong.

induction H16.
subst B''.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply l7_2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(OS A A' X B'').

eapply (out_one_side_1 _ _ X B'').

(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H10.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply col_permutation_1.
eapply (col_transitivity_1 _ X).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst X.
apply is_midpoint_id in H6.
(* Goal: False *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
subst A'.
(* Goal: False *)
(* Goal: False *)
apply H5.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A B) (@Col Tn X C B)) *)
(* Goal: @Plg Tn A B C D *)
exists B.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
unfold Midpoint in H6.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply bet_col in H6.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Out Tn B M D *)
unfold Out.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst X.
apply cong_identity in H8.
subst B''.
(* Goal: False *)
(* Goal: False *)
unfold Par_strict in H11.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply H18.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X A B')) *)
(* Goal: False *)
exists A.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst B''.
(* Goal: False *)
(* Goal: False *)
unfold Par_strict in H11.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply H19.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X A B')) *)
(* Goal: False *)
exists A.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
unfold Midpoint in H8.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(TS A A' B' B'').
(* Goal: @TS Tn B D A C *)
unfold TS.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
apply H5.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X A B')) *)
(* Goal: False *)
exists A.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.

unfold OS in H17.
ex_and H17 T.
unfold TS in H18.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X B A')) *)
(* Goal: False *)
exists A'.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
unfold Midpoint in H16.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(TS A A' X B').
eapply l9_8_2.
apply l9_2.
apply H18.
apply one_side_symmetry.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(OS A A' X B).

eapply (out_one_side_1).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H10.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply col_permutation_1.
eapply (col_transitivity_1 _ X).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst X.
apply is_midpoint_id in H6.
(* Goal: False *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
subst A'.
(* Goal: False *)
(* Goal: False *)
apply H5.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A B) (@Col Tn X C B)) *)
(* Goal: @Plg Tn A B C D *)
exists B.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
unfold Midpoint in H6.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply bet_col in H6.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply col_trivial_2;Col.
(* Goal: @Out Tn B M D *)
unfold Out.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst X.
unfold TS in H19.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply H19.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
subst A'.
(* Goal: False *)
(* Goal: False *)
unfold Par_strict in H11.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @Midpoint Tn M B D *)
apply H22.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A B) (@Col Tn X C B)) *)
(* Goal: @Plg Tn A B C D *)
exists B.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
unfold Midpoint in H6.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(OS A A' X B').
eapply one_side_transitivity.
(* Goal: False *)
(* Goal: @Midpoint Tn M B D *)
apply H20.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply l9_9 in H19.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
Qed.

Lemma par_strict_cong_mid :
 forall A B A' B',
  Par_strict A B A' B' ->
  Cong A B A' B' ->
  exists M,  Midpoint M A A' /\ Midpoint M B B' \/
             Midpoint M A B' /\ Midpoint M B A'.
Proof.
(* Goal: @Cong Tn A B B C *)
intros A B A' B' HParS HCong.
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => or (and (@Midpoint Tn M A A') (@Midpoint Tn M B B')) (and (@Midpoint Tn M A B') (@Midpoint Tn M B A'))) *)
assert (HP:=parallel_uniqueness).
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => or (and (@Midpoint Tn M A A') (@Midpoint Tn M B B')) (and (@Midpoint Tn M A B') (@Midpoint Tn M B A'))) *)
destruct (midpoint_existence A A') as [M1 HM1].
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => or (and (@Midpoint Tn M A A') (@Midpoint Tn M B B')) (and (@Midpoint Tn M A B') (@Midpoint Tn M B A'))) *)
destruct (symmetric_point_construction B M1) as [B'' HB''].
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => or (and (@Midpoint Tn M A A') (@Midpoint Tn M B B')) (and (@Midpoint Tn M A B') (@Midpoint Tn M B A'))) *)
assert (HCol1 : Col B'' A' B').
(* Goal: @Per Tn C1 C2 D2 *)
  {
(* Goal: @Col Tn B'' A' B' *)
  assert (Col A' A' B' /\ Col B'' A' B'); try (spliter; Col).
  assert (HPar := par_strict_par A B A' B' HParS);
  apply HP with A B A'; Col; unfold Par_strict in HParS; spliter;
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
  apply l12_17 with M1; Col.
  }
assert (HCong1 : Cong A' B' A' B'')
  by (assert (H := l7_13 M1 A' B'' A B HM1 HB''); eCong).
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => or (and (@Midpoint Tn M A A') (@Midpoint Tn M B B')) (and (@Midpoint Tn M A B') (@Midpoint Tn M B A'))) *)
destruct (midpoint_existence A B') as [M2 HM2].
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => or (and (@Midpoint Tn M A A') (@Midpoint Tn M B B')) (and (@Midpoint Tn M A B') (@Midpoint Tn M B A'))) *)
destruct (symmetric_point_construction B M2) as [A'' HA''].
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => or (and (@Midpoint Tn M A A') (@Midpoint Tn M B B')) (and (@Midpoint Tn M A B') (@Midpoint Tn M B A'))) *)
assert (HCol2 : Col A'' A' B').
(* Goal: @Per Tn C1 C2 D2 *)
  {
(* Goal: @Col Tn A'' A' B' *)
  assert (Col B' A' B' /\ Col A'' A' B'); try (spliter; Col).
  assert (HPar := par_strict_par A B A' B' HParS);
  apply HP with A B B'; Col; unfold Par_strict in HParS; spliter;
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
  apply l12_17 with M2; Col.
  }
assert (HCong2 : Cong A' B' B' A'')
  by (assert (H := l7_13 M2 B' A'' A B HM2 HA''); eCong).
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => or (and (@Midpoint Tn M A A') (@Midpoint Tn M B B')) (and (@Midpoint Tn M A B') (@Midpoint Tn M B A'))) *)
elim (l7_20 A' B' B''); Col; intro HElim1; treat_equalities.

(* Goal: @Per Tn C1 C2 D2 *)
  {
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
  exists M1; left; Col.
  }


(* Goal: @Per Tn C1 C2 D2 *)
  {
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => or (and (@Midpoint Tn M A A') (@Midpoint Tn M B B')) (and (@Midpoint Tn M A B') (@Midpoint Tn M B A'))) *)
  elim (l7_20 B' A' A''); Cong; Col; intro HElim2; treat_equalities.

(* Goal: @Per Tn C1 C2 D2 *)
    {
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
    exists M2; right; Col.
    }

(* Goal: @Per Tn C1 C2 D2 *)
    {
    exfalso; destruct (outer_pasch B' A A' B'' M1) as [I [HAIB' HA''IM1]];
    unfold Midpoint in*; spliter; Between.
(* Goal: False *)
    assert (HM1I : M1 <> I).
(* Goal: @Per Tn C1 C2 D2 *)
      {
(* Goal: not (@eq (@Tpoint Tn) M1 I) *)
      intro; treat_equalities.
(* Goal: False *)
      show_distinct A M1; apply HParS; exists A; split; Col; assert_cols; ColR.
      }
(* Goal: False *)
    assert (HB''M1 : B'' <> M1).
(* Goal: @Per Tn C1 C2 D2 *)
      {
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
      intro; treat_equalities; apply HParS; exists B; assert_cols; Col.
      }
(* Goal: False *)
    elim (l5_2 B'' M1 I B); Between; intro HBM1I.

(* Goal: @Per Tn C1 C2 D2 *)
      {
(* Goal: False *)
      assert (HFalse : TS A B' B A'').
(* Goal: @Per Tn C1 C2 D2 *)
        {
(* Goal: @TS Tn A B' B A'' *)
        split; try (intro; apply HParS; exists B'; Col).
(* Goal: @TS Tn A B' A'' A' *)
        show_distinct B' A''; try (apply HParS; exists A; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
        show_distinct A' B'; try (apply HParS; exists A; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
        split; try (intro; apply HParS; exists A; split; Col; assert_cols; ColR).
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
        exists M2; assert_cols; Col.
        }
(* Goal: False *)
      apply l9_9 in HFalse; apply HFalse; clear HFalse.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
      exists A'; split.

(* Goal: @Per Tn C1 C2 D2 *)
        {
(* Goal: @TS Tn A B' B A' *)
        apply l9_2; apply l9_8_2 with B''.

(* Goal: @Per Tn C1 C2 D2 *)
          {
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
          show_distinct A' B'; try (apply HParS; exists A; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
          show_distinct B' B''; try (apply HParS; exists A; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
          split; try (intro; apply HParS; exists A; split; Col; assert_cols; ColR).
(* Goal: and (not (@Col Tn B A B')) (@ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T A B') (@Bet Tn B'' T B))) *)
          split; try (intro; apply HParS; exists B'; split; Col).
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T A B') (@Bet Tn B'' T B)) *)
          exists I; assert_cols; split; Col; eBetween.
          }

(* Goal: @Per Tn C1 C2 D2 *)
          {
(* Goal: @OS Tn A B' A' B'' *)
          apply l9_19 with B'; Col; try (intro; treat_equalities; apply HParS; exists A; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
          show_distinct A' B'; try (apply HParS; exists A; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
          show_distinct B' B''; try (apply HParS; exists A; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
          split; try (intro; apply HParS; exists A; split; Col; assert_cols; ColR).
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
          split; Col.
          }
        }

(* Goal: @Per Tn C1 C2 D2 *)
        {
(* Goal: @TS Tn A B' A'' A' *)
        show_distinct B' A''; try (apply HParS; exists A; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
        show_distinct A' B'; try (apply HParS; exists A; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
        split; try (intro; apply HParS; exists A; split; Col; assert_cols; ColR).
(* Goal: and (@Out Tn B' A' B'') (not (@Col Tn A B' A')) *)
        split; try (intro; apply HParS; exists A; Col).
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T A B') (@Bet Tn A'' T A')) *)
        exists B'; split; Col; Between.
        }
      }

(* Goal: @Per Tn C1 C2 D2 *)
      {
(* Goal: False *)
      assert (HFalse : OS A A' B B').
(* Goal: @Per Tn C1 C2 D2 *)
        {
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
        exists B''; split.

(* Goal: @Per Tn C1 C2 D2 *)
          {
(* Goal: @TS Tn A A' B B'' *)
          split; try (intro; apply HParS; exists A'; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
          show_distinct A' B'; try (apply HParS; exists A; Col).
(* Goal: and (not (@Col Tn B'' A A')) (@ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T A A') (@Bet Tn B' T B''))) *)
          show_distinct A' B''; try (apply HParS; exists A; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
          split; try (intro; apply HParS; exists A; split; Col; assert_cols; ColR).
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
          exists M1; assert_cols; Col.
          }

(* Goal: @Per Tn C1 C2 D2 *)
          {
(* Goal: and (@Out Tn B' A' B'') (not (@Col Tn A B' A')) *)
          split; try (intro; apply HParS; exists A; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
          show_distinct A' B'; try (apply HParS; exists A; Col).
(* Goal: and (not (@Col Tn B'' A A')) (@ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T A A') (@Bet Tn B' T B''))) *)
          show_distinct A' B''; try (apply HParS; exists A; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
          split; try (intro; apply HParS; exists A; split; Col; assert_cols; ColR).
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
          exists A'; Col.
          }
        }
(* Goal: False *)
      apply l9_9_bis in HFalse; apply HFalse; clear HFalse; apply l9_31.

(* Goal: @Per Tn C1 C2 D2 *)
        {
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
        apply l12_6; Col.
        }

(* Goal: @Per Tn C1 C2 D2 *)
        {
(* Goal: @OS Tn A B' A' B *)
        apply one_side_transitivity with B''.

(* Goal: @Per Tn C1 C2 D2 *)
          {
(* Goal: @OS Tn A B' A' B'' *)
          apply l9_19 with B'; Col; try (intro; treat_equalities; apply HParS; exists A; Col).
(* Goal: and (@Out Tn B' A' B'') (not (@Col Tn A B' A')) *)
          split; try (intro; apply HParS; exists A; Col).
(* Goal: @Out Tn B' A' B'' *)
          split; try (intro; treat_equalities; apply HParS; exists A; Col).
(* Goal: and (not (@eq (@Tpoint Tn) B'' B')) (or (@Bet Tn B' A' B'') (@Bet Tn B' B'' A')) *)
          split; try (intro; treat_equalities; apply HParS; exists A; Col); Between.
          }

(* Goal: @Per Tn C1 C2 D2 *)
          {
          assert_cols; apply l9_19 with I; Col; try ColR;
          try (intro; treat_equalities; apply HParS; exists A; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
          show_distinct A' B'; try (apply HParS; exists A; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
          show_distinct B' B''; try (apply HParS; exists A; Col).
(* Goal: and (@Out Tn I B'' B) (not (@Col Tn A B' B'')) *)
          split; try (intro; apply HParS; exists A; split; Col; assert_cols; ColR).
(* Goal: @Out Tn I B'' B *)
          split; try (intro; treat_equalities; Col).
(* Goal: and (not (@eq (@Tpoint Tn) B I)) (or (@Bet Tn I B'' B) (@Bet Tn I B B'')) *)
          split; try (intro; treat_equalities; apply HParS; assert_cols; exists B'; Col).
(* Goal: or (@Bet Tn I B'' B) (@Bet Tn I B B'') *)
          eBetween.
          }
        }
      }
    }
  }
Qed.

Lemma par_strict_cong_mid1 :
 forall A B A' B',
  Par_strict A B A' B' ->
  Cong A B A' B' ->
  (TS A A' B B'  /\ exists M,  Midpoint M A A' /\ Midpoint M B B') \/ 
  (OS A A' B B' /\ exists M, Midpoint M A B' /\ Midpoint M B A').
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @InAngle Tn D A B C *)
assert(HH:= H).
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
unfold Par_strict in HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
destruct (cop__one_or_two_sides A A' B B').
(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
Cop.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X B A')) *)
(* Goal: False *)
exists A'.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X A B')) *)
(* Goal: False *)
exists A.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
assert(HH:=par_cong_mid_ts A B A' B' H H0 H5).
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D)) *)
ex_and HH M.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
exists M.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
split; assumption.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')) *)
assert(HH:=par_cong_mid_os A B A' B' H H0 H5).
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D)) *)
ex_and HH M.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
exists M.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
split; assumption.
Qed.

Lemma par_cong_mid :
 forall A B A' B',
  Par A B A' B' ->
  Cong A B A' B' ->
  exists M,  Midpoint M A A' /\ Midpoint M B B' \/
             Midpoint M A B' /\ Midpoint M B A'.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B D')) *)
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D')) *)
(* Goal: @Midpoint Tn M B D *)
induction H.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply par_strict_cong_mid; try assumption.
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => or (and (@Midpoint Tn M A A') (@Midpoint Tn M B B')) (and (@Midpoint Tn M A B') (@Midpoint Tn M B A'))) *)
apply col_cong_mid.
(* Goal: @Par Tn A B A' B' *)
(* Goal: not (@Par_strict Tn A B A' B') *)
(* Goal: @Cong Tn A B A' B' *)
unfold Par.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
unfold Par_strict in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X A B')) *)
(* Goal: False *)
exists A.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma ts_cong_par_cong_par :
 forall A B A' B',
 TS A A' B B' ->
 Cong A B A' B' ->
 Par A B A' B' ->
 Cong A B' A' B /\ Par A B' A' B.
Proof.
(* Goal: forall (A B A' B' : @Tpoint Tn) (_ : @TS Tn A A' B B') (_ : @Cong Tn A B A' B') (_ : @Par Tn A B A' B'), and (@Cong Tn A B' A' B) (@Par Tn A B' A' B) *)
intros A B A' B' HTS HCong HPar.
(* Goal: and (@Cong Tn A B' A' B) (@Par Tn A B' A' B) *)
assert(HAB : A <> B) by (intro; treat_equalities; unfold TS in *; spliter; Col).
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
destruct (par_cong_mid A B A' B') as [M HM]; Col.
(* Goal: or (@Plg Tn A B C D) (@Plg Tn A B D C) *)
elim HM; clear HM; intro HM; destruct HM as [HMid1 HMid2].

(* Goal: @Per Tn C1 C2 D2 *)
  {
(* Goal: and (@Cong Tn A B' A' B) (@Par Tn A B' A' B) *)
  assert(HAB' : A <> B') by (intro; treat_equalities; unfold TS in HTS; spliter; Col).
(* Goal: and (@Cong Tn A B' A' B) (@Par Tn A B' A' B) *)
  split; try apply l7_13 with M; try apply l12_17 with M; Midpoint.
  }

(* Goal: @Per Tn C1 C2 D2 *)
  {
(* Goal: and (@Cong Tn A B' A' B) (@Par Tn A B' A' B) *)
  assert(HAA' : A <> A') by (intro; treat_equalities; unfold TS in HTS; spliter; Col).
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D) *)
  assert (HFalse := HTS); apply l9_9 in HFalse; exfalso; apply HFalse; clear HFalse.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
  unfold TS in HTS; spliter; apply l12_6; apply par_not_col_strict with B; Col.
  assert (Par  A A' B' B); Par; apply l12_17 with M; Midpoint.
  }
Qed.

Lemma plgs_cong :
 forall A B C D,
 Parallelogram_strict A B C D ->
 Cong A B C D /\ Cong A D B C.
Proof.
(* Goal: forall (A B C D : @Tpoint Tn) (_ : @Parallelogram_strict Tn A B C D), and (@Par_strict Tn A B C D) (@Par_strict Tn A D B C) *)
intros A B C D HPara.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
destruct HPara as [HTS [HCong HPar]]; split; Col.
(* Goal: @Cong Tn A B B C *)
destruct (ts_cong_par_cong_par A B C D) as [HCong' HPar']; Cong.
Qed.

Lemma plg_cong :
 forall A B C D,
  Parallelogram A B C D ->
 Cong A B C D /\ Cong A D B C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B D')) *)
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D')) *)
(* Goal: @Midpoint Tn M B D *)
induction H.
(* Goal: and (@Cong Tn A B C D) (@Cong Tn A D B C) *)
(* Goal: and (@Cong Tn A B C D) (@Cong Tn A D B C) *)
apply plgs_cong.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: and (@Cong Tn A B C D) (@Cong Tn A D B C) *)
apply plgf_cong.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma rmb_cong :
 forall A B C D,
  Rhombus A B C D ->
  Cong A B B C /\ Cong A B C D /\ Cong A B D A.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: and (@Cong Tn A B B C) (and (@Cong Tn A B C D) (@Cong Tn A B D A)) *)
unfold Rhombus in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (@Cong Tn A B B C) (and (@Cong Tn A B C D) (@Cong Tn A B D A)) *)
assert(HH:= plg_to_parallelogram A B C D H).
(* Goal: and (@Cong Tn A B B C) (and (@Cong Tn A B C D) (@Cong Tn A B D A)) *)
assert(HH1:= plg_cong A B C D HH).
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (@Cong Tn A B B C) (and (@Cong Tn A B C D) (@Cong Tn A B D A)) *)
repeat split; trivial.
(* Goal: @Cong Tn A B B C *)
apply cong_transitivity with B C; Cong.
Qed.

Lemma rmb_per:
 forall A B C D M,
  Midpoint M A C ->
  Rhombus A B C D ->
  Per A M D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
assert(HH:=H0).
unfold Rhombus in HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (@Par Tn A B C D) (@Par Tn A D B C) *)
assert(HH:=H1).
unfold Plg in HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
ex_and H4 M'.
assert(M = M').
eapply l7_17.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
subst M'.
unfold Per.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A B) (@Col Tn X C B)) *)
(* Goal: @Plg Tn A B C D *)
exists B.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
apply l7_2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply rmb_cong in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Cong Tn A B B C *)
Cong.
Qed.

Lemma per_rmb :
 forall A B C D M,
  Plg A B C D ->
  Midpoint M A C ->
  Per A M B ->
  Rhombus A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
unfold Per in H1.
ex_and H1 D'.
(* Goal: @InAngle Tn D A B C *)
assert(HH:=H).
unfold Plg in HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
ex_and H4 M'.
assert(M = M').
eapply l7_17.
(* Goal: False *)
(* Goal: not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D)) *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
apply H0.
(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.
subst M'.
(* Goal: @Midpoint Tn M B D *)
assert(D = D').
eapply symmetric_point_uniqueness.
(* Goal: False *)
(* Goal: False *)
apply H5.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Midpoint Tn M B D *)
subst D'.
(* Goal: @Rhombus Tn A B C D *)
unfold Rhombus.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
assert(Cong A D B C).
(* Goal: @Parallelogram Tn B A D C *)
(* Goal: @Per Tn B C D *)
apply plg_to_parallelogram in H.
assert(HH:=plg_cong A B C D H).
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
eapply cong_transitivity.
apply H2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma perp_rmb :
 forall A B C D,
  Plg A B C D ->
  Perp A C B D ->
  Rhombus A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D)) *)
assert(HH:=midpoint_existence A C).
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D)) *)
ex_and HH M.
apply (per_rmb A B C D M).
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply perp_in_per.
unfold Plg in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
ex_and H2 M'.
assert(M = M').
eapply l7_17.
apply H1.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
subst M'.
assert(Perp A M B M).
eapply perp_col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst M.
apply is_midpoint_id in H1.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
subst C.
apply perp_not_eq_1 in H0.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.
apply perp_sym.
eapply perp_col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst M.
apply is_midpoint_id in H3.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
apply perp_not_eq_2 in H0.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.
apply perp_sym.
(* Goal: False *)
(* Goal: not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D)) *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
apply H0.
unfold Midpoint in H3.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply bet_col in H3.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
unfold Midpoint in H2.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply bet_col in H2.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
apply perp_left_comm in H4.
apply perp_perp_in in H4.
apply perp_in_comm.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma plg_conga1 : forall A B C D, A <> B -> A <> C -> Plg A B C D -> CongA B A C D C A.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
apply cong3_conga; auto.
(* Goal: @Cong_3 Tn B A C D C A *)
assert(HH := plg_to_parallelogram A B C D H1).
(* Goal: @Cong_3 Tn B A C D C A *)
apply plg_cong in HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Cong Tn A B B C *)
repeat split; Cong.
Qed.

Lemma os_cong_par_cong_par :
 forall A B A' B',
  OS A A' B B' ->
  Cong A B A' B' ->
  Par A B A' B' ->
 Cong A A' B B' /\ Par A A' B B'.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.

(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
induction H1.

(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
assert(A <> B /\ A <> A').
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
unfold OS in H.
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
ex_and H C.
(* Goal: and (not (@eq (@Tpoint Tn) A B)) (not (@eq (@Tpoint Tn) C B)) *)
(* Goal: @InAngle Tn D A B C *)
unfold TS in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
subst B.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
subst A'.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
assert(HH:= (par_strict_cong_mid1 A B A' B' H1 H0 )).
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
induction HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
apply l9_9 in H4.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
ex_and H5 M.
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
assert(HH:= mid_par_cong A B B' A' M H2 H3).
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
assert(Cong A B B' A' /\ Cong A A' B' B /\ Par A B B' A' /\ Par A A' B' B).
(* Goal: and (@Cong Tn A B B' A') (and (@Cong Tn A A' B' B) (and (@Par Tn A B B' A') (@Par Tn A A' B' B))) *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
apply HH.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Cong Tn A B B C *)
Cong.
(* Goal: @Par Tn C B A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
Par.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
unfold OS in H.
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
ex_and H C.
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
unfold TS in H5.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
(* Goal: False *)
(* Goal: False *)
apply H5.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
Qed.

Lemma plgs_permut :
 forall A B C D,
  Parallelogram_strict A B C D ->
  Parallelogram_strict B C D A.
Proof.
(* Goal: forall (A B C D : @Tpoint Tn) (_ : @Parallelogram_strict Tn A B C D), and (@Par_strict Tn A B C D) (@Par_strict Tn A D B C) *)
intros A B C D HPara.
(* Goal: and (@Par_strict Tn A B C D) (@Par_strict Tn A D B C) *)
destruct HPara as [HTS [HCong HPar]].
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
destruct (ts_cong_par_cong_par A B C D) as [HCong' HPar']; Col.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
destruct (par_cong_mid A B C D) as [M HM]; Col.
(* Goal: or (@Plg Tn A B C D) (@Plg Tn A B D C) *)
elim HM; clear HM; intro HM; destruct HM as [HMid1 HMid2].

(* Goal: @Per Tn C1 C2 D2 *)
  {
(* Goal: @Parallelogram_strict Tn B C D A *)
  assert (HAM : A <> M) by (intro; treat_equalities; unfold TS in HTS; spliter; Col).
(* Goal: @Parallelogram_strict Tn B C D A *)
  assert (HCM : C <> M) by (intro; treat_equalities; unfold TS in HTS; spliter; Col).
(* Goal: @Parallelogram_strict Tn B C D A *)
  assert (HBD : B <> D) by (assert (H:=not_two_sides_id B A C); intro; treat_equalities; Col).
(* Goal: @Parallelogram_strict Tn B C D A *)
  destruct HTS as [HAC [HABC HTS]]; assert_cols.
(* Goal: @Parallelogram_strict Tn B C D A *)
  repeat try (split; Cong; Par; try (intro; apply HABC; ColR)).
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn C T A)) *)
  unfold Midpoint in *; spliter; exists M; split; Col; Between.
  }

(* Goal: @Per Tn C1 C2 D2 *)
  {
(* Goal: and (@Par_strict Tn A B C D) (@Par_strict Tn A D B C) *)
  assert(HAB : A <> B) by (intro; treat_equalities; unfold TS in HTS; spliter; Col).
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D) *)
  assert(HAC : A <> C) by (intro; treat_equalities; unfold TS in HTS; spliter; Col).
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D) *)
  assert (HFalse := HTS); apply l9_9 in HFalse; exfalso; apply HFalse; clear HFalse.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
  unfold TS in HTS; spliter; apply l12_6; apply par_not_col_strict with B; Col.
(* Goal: @Par Tn A C B D *)
  assert (Par A C D B); Par; apply l12_17 with M; Midpoint.
  }
Qed.

Lemma plg_permut :
 forall A B C D,
  Parallelogram A B C D ->
  Parallelogram B C D A.
Proof.
(* Goal: forall (A B C D : @Tpoint Tn) (_ : @Parallelogram_strict Tn A B C D), and (@Par_strict Tn A B C D) (@Par_strict Tn A D B C) *)
intros A B C D HPara.
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D)) *)
elim HPara; clear HPara; intro HPara.

(* Goal: @Per Tn C1 C2 D2 *)
  {
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
  left; apply plgs_permut; Col.
  }

(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
  {right; apply plgf_permut; Col.
  }
Qed.

Lemma plgs_mid :
 forall A B C D,
  Parallelogram_strict A B C D ->
  exists M, Midpoint M A C /\ Midpoint M B D.
Proof.
(* Goal: forall (A B C D : @Tpoint Tn) (_ : @Parallelogram_strict Tn A B C D), and (@Par_strict Tn A B C D) (@Par_strict Tn A D B C) *)
intros A B C D HPara.
(* Goal: and (@Par_strict Tn A B C D) (@Par_strict Tn A D B C) *)
destruct HPara as [HTS [HCong HPar]].
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
destruct (par_cong_mid A B C D) as [M HM]; Col.
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D)) *)
elim HM; clear HM; intro HM; destruct HM as [HMid1 HMid2]; try (exists M; Col).
(* Goal: and (@Par_strict Tn A B C D) (@Par_strict Tn A D B C) *)
assert(HAB : A <> B) by (intro; treat_equalities; unfold TS in HTS; spliter; Col).
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D) *)
assert(HAC : A <> C) by (intro; treat_equalities; unfold TS in HTS; spliter; Col).
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D) *)
assert (HFalse := HTS); apply l9_9 in HFalse; exfalso; apply HFalse; clear HFalse.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
unfold TS in HTS; spliter; apply l12_6; apply par_not_col_strict with B; Col.
(* Goal: @Par Tn A C B D *)
assert (Par A C D B); Par; apply l12_17 with M; Midpoint.
Qed.

Lemma plg_mid :
 forall A B C D,
  Parallelogram A B C D ->
  exists M, Midpoint M A C /\ Midpoint M B D.
Proof.
(* Goal: forall (A B C D : @Tpoint Tn) (_ : @Parallelogram_strict Tn A B C D), and (@Par_strict Tn A B C D) (@Par_strict Tn A D B C) *)
intros A B C D HPara.
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D)) *)
elim HPara; clear HPara; intro HPara.

(* Goal: @Per Tn C1 C2 D2 *)
  {
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
  apply plgs_mid; Col.
  }

(* Goal: @Per Tn C1 C2 D2 *)
  {
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
  apply plgf_mid; Col.
  }

Qed.

Lemma plg_mid_2 :
 forall A B C D I,
  Parallelogram A B C D ->
  Midpoint I A C ->
  Midpoint I B D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Midpoint Tn I B D *)
elim (plg_mid A B C D).
(* Goal: forall (x : @Tpoint Tn) (_ : and (@Midpoint Tn x A C) (@Midpoint Tn x B D)), @Midpoint Tn I B D *)
(* Goal: @Parallelogram Tn A B C D *)
intros I' HI'.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Midpoint Tn I B D *)
(* Goal: @Parallelogram Tn A B C D *)
treat_equalities.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.


Lemma plgs_not_comm :
  forall A B C D,
   Parallelogram_strict A B C D ->
 ~ Parallelogram_strict A B D C /\ ~ Parallelogram_strict B A C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Parallelogram_strict Tn B A D C *)
unfold Parallelogram_strict in *.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
assert(HH:=
ts_cong_par_cong_par A B C D H H4 H3).
(* Goal: @Parallelogram Tn A B C D *)
spliter.

(* Goal: False *)
(* Goal: not (and (@TS Tn B C A D) (and (@Par Tn B A C D) (@Cong Tn B A C D))) *)
assert(Par_strict A D C B).
(* Goal: @Par_strict Tn C B A D *)
(* Goal: False *)
induction H6.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

(* Goal: @Par_strict Tn C B A D *)
(* Goal: False *)
unfold Par_strict.
(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
repeat split; Cop.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
unfold TS in *.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: False *)
apply l12_6 in H7.
(* Goal: False *)
apply l9_9 in H0.
(* Goal: False *)
(* Goal: not (and (@TS Tn B C A D) (and (@Par Tn B A C D) (@Cong Tn B A C D))) *)
apply one_side_symmetry in H7.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.

(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
assert(HH:=ts_cong_par_cong_par A B C D H H4 H3).
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
apply par_symmetry in H6.

(* Goal: False *)
assert(Par_strict C B A D).
(* Goal: @Par_strict Tn C B A D *)
(* Goal: False *)
induction H6.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Par_strict Tn C B A D *)
(* Goal: False *)
unfold Par_strict.
(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
repeat split; Cop.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
unfold TS in *.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: False *)
apply H13.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: False *)
apply l12_6 in H7.
(* Goal: False *)
apply l9_9 in H0.
(* Goal: False *)
apply invert_one_side in H7.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
Qed.

Lemma plg_not_comm :
 forall A B C D,
 A <> B ->
 Parallelogram A B C D ->
 ~ Parallelogram A B D C /\ ~ Parallelogram B A C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Parallelogram Tn A B C D *)
unfold Parallelogram.
(* Goal: @Par_strict Tn A D B C *)
induction H0.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
induction H1.
(* Goal: False *)
(* Goal: False *)
(* Goal: not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D)) *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
apply plgs_not_comm in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
unfold Parallelogram_strict in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
unfold Parallelogram_flat in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D)) *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
apply par_symmetry in H2.
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
induction H2.
(* Goal: False *)
(* Goal: False *)
(* Goal: not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D)) *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
unfold Par_strict in H2.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H10.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
exists D; Col.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
unfold TS in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D)) *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
apply H0.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
assert(~ Parallelogram_strict A B D C /\ ~ Parallelogram_strict B A C D).
(* Goal: and (not (@Parallelogram_strict Tn A B D C)) (not (@Parallelogram_strict Tn B A C D)) *)
(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
apply plgs_not_comm.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
induction H1.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
unfold Parallelogram_strict in H0.
(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
unfold Parallelogram_flat in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
unfold TS in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
assert(~ Parallelogram_flat A B D C /\ ~ Parallelogram_flat B A C D).
(* Goal: and (not (@Parallelogram_flat Tn A B D C)) (not (@Parallelogram_flat Tn B A C D)) *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
apply plgf_not_comm.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
induction H3.
(* Goal: False *)
(* Goal: False *)
unfold Parallelogram_strict in H3.
(* Goal: False *)
(* Goal: False *)
unfold Parallelogram_flat in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: False *)
unfold TS in H3.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: False *)
(* Goal: not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D)) *)
apply H3.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: False *)
(* Goal: not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D)) *)
apply plgf_not_comm in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
induction H3.
(* Goal: False *)
(* Goal: False *)
unfold Parallelogram_strict in H3.
(* Goal: False *)
(* Goal: False *)
unfold Parallelogram_flat in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: False *)
unfold TS in H3.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
Qed.

Lemma parallelogram_to_plg : forall A B C D, Parallelogram A B C D -> Plg A B C D.
Proof.
(* Goal: forall (A B C D : @Tpoint Tn) (_ : @Parallelogram_strict Tn A B C D), and (@Par_strict Tn A B C D) (@Par_strict Tn A D B C) *)
intros A B C D HPara.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
destruct (plg_mid A B C D) as [M HM]; Col.
(* Goal: @Plg Tn A B C D *)
split; try (exists M; Col).
elim HPara; clear HPara; intro HPara; try (apply plgs_diff in HPara; spliter; Col);
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
unfold Parallelogram_flat in HPara; spliter; Col.
Qed.

Lemma parallelogram_equiv_plg : forall A B C D, Parallelogram A B C D <-> Plg A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @InAngle Tn D A B C *)
apply parallelogram_to_plg.
(* Goal: @Parallelogram Tn A B C D' *)
(* Goal: @Midpoint Tn M B D *)
apply plg_to_parallelogram.
Qed.

Lemma plg_conga : forall A B C D, A <> B /\ A <> C /\ B <> C -> Parallelogram A B C D -> CongA A B C C D A /\ CongA B C D D A B.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
assert(Cong A B C D /\ Cong A D B C).
apply plg_cong.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
assert(HH:= plg_mid A B C D H0).
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D)) *)
ex_and HH M.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
apply cong3_conga; auto.
(* Goal: @Cong Tn A B B C *)
repeat split; Cong.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
apply cong3_conga; auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
eapply symmetric_point_uniqueness;
apply l7_2.
(* Goal: False *)
(* Goal: False *)
apply H5.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Cong Tn A B B C *)
repeat split; Cong.
Qed.

Lemma half_plgs :
 forall A B C D P Q M,
  Parallelogram_strict A B C D ->
  Midpoint P A B ->
  Midpoint Q C D ->
  Midpoint M A C ->
  Par P Q A D /\ Midpoint M P Q /\ Cong A D P Q.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @InAngle Tn D A B C *)
assert(HH:=H).
apply plgs_mid in HH.
ex_and HH M'.
assert(M=M').
eapply l7_17.
apply H2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
subst M'.
clear H3.

prolong P M Q' P M.
assert(Midpoint M P Q').
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Cong Tn A B B C *)
Cong.
assert(Midpoint Q' C D).
eapply symmetry_preserves_midpoint.
apply H2.
(* Goal: False *)
(* Goal: False *)
apply H6.
(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.
(* Goal: False *)
(* Goal: not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D)) *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
apply H0.
assert(Q=Q').
eapply l7_17.
apply H1.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
subst Q'.
(* Goal: @InAngle Tn D A B C *)
assert(HH:=H).
unfold Parallelogram_strict in HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(Cong A P D Q).
eapply cong_cong_half_1.
(* Goal: False *)
(* Goal: not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D)) *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
apply H0.
apply l7_2.
apply H1.
(* Goal: @Cong Tn A B B C *)
Cong.

assert(Par A P Q D).
eapply par_col_par_2.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst P.
(* Goal: False *)
(* Goal: @Col Tn C M B *)
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply is_midpoint_id in H0.
(* Goal: False *)
(* Goal: False *)
subst B.
induction H9.
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A D) (@Midpoint Tn M B C)) *)
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
unfold Par_strict in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
unfold Midpoint in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply bet_col in H0.
apply col_permutation_5.
(* Goal: False *)
(* Goal: not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D)) *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
apply H0.
(* Goal: @Par Tn A D B C *)
apply par_symmetry.
(* Goal: @Par Tn B C A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
apply par_left_comm.
eapply par_col_par_2.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst Q.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
apply cong_identity in H11.
subst P.
(* Goal: False *)
(* Goal: @Col Tn C M B *)
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply is_midpoint_id in H0.
(* Goal: False *)
(* Goal: False *)
subst B.
induction H9.
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A D) (@Midpoint Tn M B C)) *)
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
unfold Par_strict in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.
(* Goal: @Col Tn M B C *)
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
unfold Midpoint in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply bet_col in H1.
(* Goal: @Col Tn B A C *)
(* Goal: not (@Col Tn C B D) *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply col_permutation_2.
apply H1.
(* Goal: @Par Tn B C A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
apply par_left_comm.
(* Goal: @Par Tn C B A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
Par.


assert(Cong A D P Q /\ Par A D P Q).
apply(os_cong_par_cong_par A P D Q).

unfold TS in H8.
(* Goal: and (not (@Col Tn A B D)) (and (not (@Col Tn C B D)) (@ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)))) *)
assert(~ Col B A C).
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(OS A D P B).
eapply out_one_side_1.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
assert(Col P B D).
eapply (col_transitivity_1 _ A).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst P.
(* Goal: False *)
(* Goal: @Col Tn C M B *)
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply is_midpoint_id in H0.
(* Goal: False *)
(* Goal: False *)
subst B.
apply cong_symmetry in H10.
apply cong_identity in H10.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: False *)
(* Goal: False *)
apply H14.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
unfold Midpoint in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply bet_col in H0.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

(* Goal: @InAngle Tn D A B C *)
assert(HH:=H).
apply plgs_permut in HH.
unfold Parallelogram_strict in HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
unfold TS in H18.
assert(~ Col C B D).
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @Midpoint Tn M B D *)
apply H22.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply col_permutation_1.
eapply (col_transitivity_1 _ P).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst P.
(* Goal: False *)
(* Goal: @Midpoint Tn M B D *)
apply H22.
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
unfold Midpoint in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply bet_col in H0.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
unfold Midpoint in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst P.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
apply cong_symmetry in H11.
apply cong_identity in H11;

unfold TS in H8.
subst Q.
apply l7_2 in H1.
apply is_midpoint_id in H1.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: False *)
(* Goal: False *)
apply H14.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
subst B.
apply cong_symmetry in H10.
apply cong_identity in H10;
unfold Par_strict in H12.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: False *)
(* Goal: False *)
apply H13.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(OS A D Q C).
eapply out_one_side_1.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
apply H14.
eapply (col_transitivity_1 _ Q).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst Q.
apply l7_2 in H1.
apply is_midpoint_id in H1.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: False *)
(* Goal: False *)
apply H14.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn M B C *)
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
unfold Midpoint in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply bet_col in H1.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply col_trivial_2;Col.

(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst Q.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
apply cong_identity in H11.
subst P.
unfold OS in H16.
ex_and H16 K.
unfold TS in H11.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: False *)
apply H11.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
apply cong_identity in H10.
(* Goal: False *)
(* Goal: False *)
subst B.
(* Goal: False *)
(* Goal: False *)
apply H14.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

(* Goal: @Col Tn M B C *)
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
unfold Midpoint in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
Between.

assert(OS A D B C).

apply ts_cong_par_cong_par in H9.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

induction H18.
apply l12_6.
unfold Par_strict in *.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
repeat split; Cop.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
apply H21.
ex_and H22 X.
exists X.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
(* Goal: False *)
(* Goal: False *)
apply H13.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
repeat split; auto.
(* Goal: @Cong Tn A B B C *)
Cong.
eapply one_side_transitivity.
apply H16.
eapply one_side_transitivity.
apply H18.
apply one_side_symmetry.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Par Tn C B A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
Par.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply par_symmetry in H14.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
split; auto.
Qed.

Lemma plgs_two_sides :
 forall A B C D,
 Parallelogram_strict A B C D ->
 TS A C B D /\ TS B D A C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: and (@TS Tn A C B D) (@TS Tn B D A C) *)
assert(HH:= plgs_mid A B C D H).
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D)) *)
ex_and HH M.
(* Goal: @InAngle Tn D A B C *)
unfold Parallelogram_strict in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

(* Goal: @TS Tn B D A C *)
unfold TS.
(* Goal: and (not (@Col Tn A B D)) (and (not (@Col Tn C B D)) (@ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)))) *)
assert(~Col B A C).
(* Goal: and (not (@eq (@Tpoint Tn) A B)) (not (@eq (@Tpoint Tn) C B)) *)
(* Goal: @InAngle Tn D A B C *)
unfold TS in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Plg Tn A B C D *)
assert(B <> D).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: and (not (@Col Tn A B D)) (and (not (@Col Tn C B D)) (@ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)))) *)
assert(HH:=one_side_reflexivity A C B H4).
(* Goal: False *)
(* Goal: and (not (@Col Tn A B D)) (and (not (@Col Tn C B D)) (@ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)))) *)
apply l9_9 in H.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: and (not (@eq (@Tpoint Tn) A B)) (not (@eq (@Tpoint Tn) C B)) *)
(* Goal: @InAngle Tn D A B C *)
unfold TS in H.
(* Goal: and (not (@Col Tn A B D)) (and (not (@Col Tn C B D)) (@ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)))) *)
assert(~ Col B A C).
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: not (@Col Tn C B D) *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
assert(Col M A B).
(* Goal: @Col Tn M B C *)
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
unfold Midpoint in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply bet_col in H1.
(* Goal: @Col Tn O A A' *)
ColR.

(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.
(* Goal: @Col Tn B A C *)
(* Goal: not (@Col Tn C B D) *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply col_permutation_2.
(* Goal: @Col Tn C B A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
eapply (col_transitivity_1 _ M).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst M.
(* Goal: False *)
(* Goal: @Col Tn C M B *)
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply is_midpoint_id in H0.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
subst C.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
unfold Midpoint in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn A M C *)
(* Goal: @Col Tn A M B *)
(* Goal: not (@Col Tn C B D) *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply bet_col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
assert(Col M B C).
(* Goal: @Col Tn M B C *)
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
unfold Midpoint in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply bet_col in H1.
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: False *)
(* Goal: False *)
apply H6.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply col_permutation_1.
(* Goal: @Col Tn C B A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
eapply (col_transitivity_1 _ M).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst M.
(* Goal: False *)
(* Goal: @Col Tn C M B *)
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply l7_2 in H0.
(* Goal: False *)
(* Goal: @Col Tn C M B *)
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply is_midpoint_id in H0.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
subst C.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
unfold Midpoint in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply bet_col in H0.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
exists M.
(* Goal: and (@Col Tn M B D) (@Bet Tn A M C) *)
unfold Midpoint in *.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply bet_col in H1.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
Qed.

Lemma plgs_par_strict :
 forall A B C D,
  Parallelogram_strict A B C D ->
  Par_strict A B C D /\ Par_strict A D B C.
Proof.
(* Goal: forall (A B C D : @Tpoint Tn) (_ : @Parallelogram_strict Tn A B C D), and (@Par_strict Tn A B C D) (@Par_strict Tn A D B C) *)
intros A B C D HPara.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
destruct (plgs_mid A B C D) as [M [HMid1 HMid2]]; Col.
(* Goal: and (@Par_strict Tn A B C D) (@Par_strict Tn A D B C) *)
destruct HPara as [HTS [HCong HPar]].
(* Goal: and (@Par_strict Tn A B C D) (@Par_strict Tn A D B C) *)
assert(HAB : A <> B) by (intro; treat_equalities; unfold TS in HTS; spliter; Col).
(* Goal: and (@Par_strict Tn A B C D) (@Par_strict Tn A D B C) *)
assert(HAC : A <> D) by (intro; treat_equalities; unfold TS in HTS; spliter; Col).
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
unfold TS in HTS; spliter; split; try apply par_not_col_strict with C; Col.
(* Goal: @Par Tn A D B C *)
assert (Par A D C B); Par; apply l12_17 with M; Midpoint.
Qed.

Lemma plgs_half_plgs_aux :
 forall A B C D P Q,
  Parallelogram_strict A B C D ->
  Midpoint P A B ->
  Midpoint Q C D ->
  Parallelogram_strict A P Q D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @InAngle Tn D A B C *)
assert(HH:= H).
apply plgs_mid in HH.
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D)) *)
ex_and HH M.
assert(HH:=half_plgs A B C D P Q M H H0 H1 H2).
(* Goal: @Parallelogram Tn A B C D *)
spliter.

(* Goal: @InAngle Tn D A B C *)
assert(HH:=H).
apply plgs_par_strict in HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(HH:=par_cong_mid P Q A D H4 (cong_symmetry A D P Q H6)).
ex_and HH N.
induction H9.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
unfold Par_strict in H7.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: False *)
apply H13.
exists N.

assert(A <> P).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst P.
apply l7_3 in H9.
subst N.
(* Goal: False *)
(* Goal: @Col Tn C M B *)
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply is_midpoint_id in H0.
(* Goal: False *)
(* Goal: False *)
subst B.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.

assert(D <> Q).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst Q.
apply l7_3 in H10.
subst N.
apply l7_2 in H1.
apply is_midpoint_id in H1.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.

(* Goal: and (@Col Tn M B D) (@Bet Tn A M C) *)
unfold Midpoint in *.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply bet_col in H0.
apply bet_col in H9.
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply bet_col in H1.
apply bet_col in H10.
(* Goal: @Col Tn O A A' *)
ColR.

(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(A <> P).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst P.
(* Goal: False *)
(* Goal: @Col Tn C M B *)
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply is_midpoint_id in H0.
(* Goal: False *)
(* Goal: False *)
subst B.
unfold Par_strict in H7.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.

assert(D <> Q).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst Q.
apply l7_2 in H1.
apply is_midpoint_id in H1.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
unfold Par_strict in H7.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.

eapply mid_plgs.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
unfold Par_strict in H7.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply H16.
exists Q.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
unfold Midpoint in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn C M A *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply bet_col in H0.
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: @Col Tn M B C *)
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
unfold Midpoint in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply bet_col in H1.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
apply l7_2.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H10.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma plgs_comm2 :
 forall A B C D,
  Parallelogram_strict A B C D ->
  Parallelogram_strict B A D C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @InAngle Tn D A B C *)
assert(HH:= H).
(* Goal: @Parallelogram_strict Tn B A D C *)
apply plgs_two_sides in HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Parallelogram_strict Tn B A D C *)
unfold Parallelogram_strict in *.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Par Tn B A D C *)
(* Goal: @Cong Tn B A D C *)
apply par_comm.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Cong Tn A B B C *)
Cong.
Qed.

Lemma plgf_comm2 :
 forall A B C D,
  Parallelogram_flat A B C D ->
  Parallelogram_flat B A D C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Parallelogram_flat Tn B A D C *)
unfold Parallelogram_flat in *.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
repeat split; Col.
(* Goal: @Cong Tn A B B C *)
Cong.
(* Goal: @Cong Tn A B B C *)
Cong.
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
induction H3.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
right; assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
left; assumption.
Qed.

Lemma plg_comm2 :
 forall A B C D,
  Parallelogram A B C D ->
  Parallelogram B A D C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B D')) *)
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D')) *)
(* Goal: @Midpoint Tn M B D *)
induction H.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Parallelogram_strict Tn B A D C *)
(* Goal: @Parallelogram Tn B A D C *)
apply plgs_comm2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: @Parallelogram_flat Tn B A D C *)
apply plgf_comm2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma par_preserves_conga_os :
 forall A B C D P , Par A B C D -> Bet A D P -> D <> P -> OS A D B C -> CongA B A P C D P.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
assert(HH:= H2).
unfold OS in HH.
ex_and HH T.
(* Goal: False *)
(* Goal: False *)
unfold TS in *.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

prolong C D C' C D.

assert(C' <> D).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst C'.
apply cong_symmetry in H10.
apply cong_identity in H10.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

assert(CongA B A D C' D A).
eapply l12_21_a.
apply (l9_8_2 _ _ C).
(* Goal: @TS Tn B D A C *)
unfold TS.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
repeat split; auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.
apply bet_col in H9.
(* Goal: @Col Tn O A A' *)
ColR.

(* Goal: @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D) *)
exists D.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply one_side_symmetry.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

(* Goal: @Par Tn A D B C *)
apply par_symmetry.
eapply (par_col_par_2 _ C).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.

apply bet_col in H9.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Par Tn A D B C *)
apply par_symmetry.
(* Goal: @Par Tn C B A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
Par.

(* Goal: False *)
assert(A <> B).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
subst B.
(* Goal: False *)
(* Goal: False *)
(* Goal: not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D)) *)
apply H3.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

assert(CongA B A D B A P).
assert(A <> D).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
eapply (out_conga B A D B A D).
apply conga_refl.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
apply out_trivial.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
apply out_trivial.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
apply out_trivial.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
(* Goal: @Out Tn B M D *)
unfold Out.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
repeat split; auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst P.
apply between_identity in H0.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
apply conga_right_comm.

assert(CongA C D P C' D A).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
eapply l11_14; auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
Between.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
eapply conga_trans.
apply conga_sym.
(* Goal: False *)
(* Goal: False *)
apply H14.
eapply conga_trans.
apply H12.
apply conga_sym.
apply conga_left_comm.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma cong3_par2_par :
 forall A B C A' B' C', A <> C -> Cong_3 B A C B' A' C' -> Par B A B' A' -> Par B C B' C' ->
 Par A C A' C' \/ ~ Par_strict B B' A A' \/ ~Par_strict B B' C C'.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.

assert(HH0:=par_distinct B A B' A' H1).
assert(HH1:=par_distinct B C B' C' H2).
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(HH:=midpoint_existence B B').
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D)) *)
ex_and HH M.

prolong A M A'' A M.
prolong C M C'' C M.

assert(Midpoint M A A'').
(* Goal: @Cong Tn A B B C *)
split; Cong.
assert(Midpoint M C C'').
(* Goal: @Cong Tn A B B C *)
split; Cong.

assert(Par B A B' A'').
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply (l12_17 _ _ _ _ M); assumption.

assert(Par B C B' C'').
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply (l12_17 _ _ _ _ M); assumption.

assert(Par  A C A'' C'').
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply (l12_17 _ _ _ _ M);assumption.

assert(Par B' A' B' A'').
eapply par_trans.
(* Goal: @Par Tn A D B C *)
apply par_symmetry.
apply H1.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(Par B' C' B' C'').
eapply par_trans.
(* Goal: @Par Tn A D B C *)
apply par_symmetry.
apply H2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.


assert(Col B' A' A'').
unfold Par in H17.
induction H17.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
apply H17.
exists B'.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

assert(Col B' C' C'').
unfold Par in H18.
induction H18.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
apply H18.
exists B'.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

assert(Cong B A B' A'').
eapply l7_13.
apply l7_2.
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply H7.
apply l7_2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(Cong B C B' C'').
eapply l7_13.
apply l7_2.
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply H7.
apply l7_2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

unfold Cong_3 in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(A' = A'' \/ Midpoint B' A' A'').
(* Goal: or (@eq (@Tpoint Tn) B D) (@Midpoint Tn A B D) *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
eapply l7_20.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Cong Tn A B B C *)
apply cong_transitivity with B A; Cong.

assert(C' = C'' \/ Midpoint B' C' C'').
(* Goal: or (@eq (@Tpoint Tn) B D) (@Midpoint Tn A B D) *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
eapply l7_20.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Cong Tn A B B C *)
apply cong_transitivity with B C; Cong.

induction H25.

induction H26.
subst A''.
subst C''.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
right; left.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
apply H27.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
exists M.
(* Goal: and (@Col Tn M B D) (@Bet Tn A M C) *)
unfold Midpoint in *.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
apply bet_col in H7.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
subst.
apply bet_col in H8.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

induction H26.

subst C''.
clean_duplicated_hyps.
clean_trivial_hyps.

(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right; right.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
apply H15.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
exists M.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
unfold Midpoint in H7.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply bet_col in  H7.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
unfold Midpoint in H13.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply bet_col in  H13.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

assert(Par A' C' A'' C'').

apply(l12_17 A' C' A'' C'' B').

(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst C'.
assert(A'' = C'').
eapply l7_9.
apply l7_2.
apply H25.
apply l7_2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
subst C''.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
eapply l7_9.
apply H12.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply H25.
apply H26.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
eapply par_trans.
apply H16.
(* Goal: @Par Tn C B A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
Par.
Qed.



Lemma square_perp_rectangle : forall A B C D,
 Rectangle A B C D ->
 Perp A C B D ->
 Square A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Square Tn A B C D *)
assert (Rhombus A B C D).
(* Goal: @Rhombus Tn A B C D *)
(* Goal: @Square Tn A B C D *)
apply perp_rmb.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply H. assumption.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
apply Rhombus_Rectangle_Square;auto.
Qed.

Lemma plgs_half_plgs :
 forall A B C D P Q,
  Parallelogram_strict A B C D ->
  Midpoint P A B -> Midpoint Q C D ->
  Parallelogram_strict A P Q D /\ Parallelogram_strict B P Q C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
eapply plgs_half_plgs_aux.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply plgs_comm2 in H.
eapply plgs_half_plgs_aux.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
Midpoint.
Midpoint.
Qed.

Lemma parallel_2_plg :
  forall A B C D,
  ~ Col A B C ->
  Par A B C D ->
  Par A D B C ->
  Parallelogram_strict A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
assert (Cong A B C D /\ Cong B C D A /\
        TS B D A C /\ TS A C B D)
  by (apply l12_19;Par).
(* Goal: @Parallelogram_strict Tn A B C D *)
unfold Parallelogram_strict; intuition.
Qed.

Lemma par_2_plg :
  forall A B C D,
  ~ Col A B C ->
  Par A B C D ->
  Par A D B C ->
  Parallelogram A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Parallelogram Tn A B C D *)
assert (H2 := parallel_2_plg A B C D H H0 H1).
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply Parallelogram_strict_Parallelogram; assumption.
Qed.

Lemma plg_cong_1 : forall A B C D, Parallelogram A B C D -> Cong A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Cong Tn A D B C *)
apply plg_cong in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma plg_cong_2 : forall A B C D, Parallelogram A B C D -> Cong A D B C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Cong Tn A D B C *)
apply plg_cong in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma plgs_cong_1 : forall A B C D, Parallelogram_strict A B C D -> Cong A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Cong Tn A D B C *)
apply plgs_cong in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma plgs_cong_2 : forall A B C D, Parallelogram_strict A B C D -> Cong A D B C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Cong Tn A D B C *)
apply plgs_cong in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma Plg_perm :
  forall A B C D,
  Parallelogram A B C D ->
  Parallelogram A B C D /\ Parallelogram B C D A /\ Parallelogram C D A B /\Parallelogram D A B C /\ 
  Parallelogram A D C B /\ Parallelogram D C B A /\ Parallelogram C B A D /\ Parallelogram B A D C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
split; try assumption.
(* Goal: and (@Parallelogram Tn B C D A) (and (@Parallelogram Tn C D A B) (and (@Parallelogram Tn D A B C) (and (@Parallelogram Tn A D C B) (and (@Parallelogram Tn D C B A) (and (@Parallelogram Tn C B A D) (@Parallelogram Tn B A D C)))))) *)
split; try (apply plg_permut; assumption).
(* Goal: and (@Parallelogram Tn C D A B) (and (@Parallelogram Tn D A B C) (and (@Parallelogram Tn A D C B) (and (@Parallelogram Tn D C B A) (and (@Parallelogram Tn C B A D) (@Parallelogram Tn B A D C))))) *)
split; try (do 2 apply plg_permut; assumption).
(* Goal: and (@Parallelogram Tn D A B C) (and (@Parallelogram Tn A D C B) (and (@Parallelogram Tn D C B A) (and (@Parallelogram Tn C B A D) (@Parallelogram Tn B A D C)))) *)
split; try (do 3 apply plg_permut; assumption).
(* Goal: and (@Parallelogram Tn A D C B) (and (@Parallelogram Tn D C B A) (and (@Parallelogram Tn C B A D) (@Parallelogram Tn B A D C))) *)
split; try (apply plg_comm2; do 3 apply plg_permut; assumption).
(* Goal: and (@Parallelogram Tn D C B A) (and (@Parallelogram Tn C B A D) (@Parallelogram Tn B A D C)) *)
split; try (apply plg_comm2; do 2 apply plg_permut; assumption).
(* Goal: and (@Parallelogram Tn C B A D) (@Parallelogram Tn B A D C) *)
split; try (apply plg_comm2; apply plg_permut; assumption).
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply plg_comm2; assumption.
Qed.

Lemma plg_not_comm_1 :
  forall A B C D : Tpoint,
  A <> B ->
  Parallelogram A B C D -> ~ Parallelogram A B D C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
assert (HNC := plg_not_comm A B C D H H0); spliter; assumption.
Qed.

Lemma plg_not_comm_2 :
  forall A B C D : Tpoint,
  A <> B ->
  Parallelogram A B C D -> ~ Parallelogram B A C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
assert (HNC := plg_not_comm A B C D H H0); spliter; assumption.
Qed.

End Quadrilateral_inter_dec_1.

Ltac assert_cols :=
repeat
 match goal with
      | H:Bet ?X1 ?X2 ?X3 |- _ =>
     not_exist_hyp_perm_col X1 X2 X3;assert (Col X1 X2 X3) by (apply bet_col;apply H)

      | H:Midpoint ?X1 ?X2 ?X3 |- _ =>
     not_exist_hyp_perm_col X1 X2 X3;let N := fresh in assert (N := midpoint_col X2 X1 X3 H)

      | H:Out ?X1 ?X2 ?X3 |- _ =>
     not_exist_hyp_perm_col X1 X2 X3;let N := fresh in assert (N := out_col X1 X2 X3 H)

      | H:Par ?X1 ?X2 ?X1 ?X3 |- _ =>
     not_exist_hyp_perm_col X1 X2 X3;let N := fresh in assert (N := par_id X1 X2 X3 H)
      | H:Par ?X1 ?X2 ?X3 ?X1 |- _ =>
     not_exist_hyp_perm_col X1 X2 X3;let N := fresh in
     assert (N := par_id X1 X2 X3 (par_right_comm X1 X2 X3 X1 H))
      | H:Par ?X2 ?X1 ?X1 ?X3 |- _ =>
     not_exist_hyp_perm_col X1 X2 X3;let N := fresh in
     assert (N := par_id X1 X2 X3 (par_left_comm X2 X1 X1 X3 H))
      | H:Par ?X2 ?X1 ?X3 ?X1 |- _ =>
     not_exist_hyp_perm_col X1 X2 X3;let N := fresh in
     assert (N := par_id X1 X2 X3 (par_comm X2 X1 X3 X1 H))
 end.

Ltac permutation_intro_in_hyps_aux :=
 repeat
 match goal with
 | H : Plg_tagged ?A ?B ?C ?D |- _ => apply Plg_tagged_Plg in H; apply Plg_perm in H; spliter
 | H : Par_tagged ?A ?B ?C ?D |- _ => apply Par_tagged_Par in H; apply Par_perm in H; spliter
 | H : Par_strict_tagged ?A ?B ?C ?D |- _ => apply Par_strict_tagged_Par_strict in H; apply Par_strict_perm in H; spliter
 | H : Perp_tagged ?A ?B ?C ?D |- _ => apply Perp_tagged_Perp in H; apply Perp_perm in H; spliter
 | H : Perp_in_tagged ?X ?A ?B ?C ?D |- _ => apply Perp_in_tagged_Perp_in in H; apply Perp_in_perm in H; spliter
 | H : Per_tagged ?A ?B ?C |- _ => apply Per_tagged_Per in H; apply Per_perm in H; spliter
 | H : Mid_tagged ?A ?B ?C |- _ => apply Mid_tagged_Mid in H; apply Mid_perm in H; spliter
 | H : NCol_tagged ?A ?B ?C |- _ => apply NCol_tagged_NCol in H; apply NCol_perm in H; spliter
 | H : Col_tagged ?A ?B ?C |- _ => apply Col_tagged_Col in H; apply Col_perm in H; spliter
 | H : Bet_tagged ?A ?B ?C |- _ => apply Bet_tagged_Bet in H; apply Bet_perm in H; spliter
 | H : Cong_tagged ?A ?B ?C ?D |- _ => apply Cong_tagged_Cong in H; apply Cong_perm in H; spliter
 | H : Diff_tagged ?A ?B |- _ => apply Diff_tagged_Diff in H; apply Diff_perm in H; spliter
 end.

Ltac permutation_intro_in_hyps := clean_reap_hyps; clean_trivial_hyps; tag_hyps; permutation_intro_in_hyps_aux.

Ltac assert_cols_aux :=
repeat
 match goal with
      | H:Bet ?X1 ?X2 ?X3 |- _ =>
     not_exist_hyp (Col X1 X2 X3);assert (Col X1 X2 X3) by (apply bet_col;apply H) 

      | H:Midpoint ?X1 ?X2 ?X3 |- _ =>
     not_exist_hyp (Col X1 X2 X3);let N := fresh in assert (N := midpoint_col X2 X1 X3 H)

      | H:Out ?X1 ?X2 ?X3 |- _ =>
     not_exist_hyp (Col X1 X2 X3);let N := fresh in assert (N := out_col X1 X2 X3 H)

      | H:Par ?X1 ?X2 ?X1 ?X3 |- _ =>
     not_exist_hyp (Col X1 X2 X3);let N := fresh in assert (N := par_id X1 X2 X3 H)
      | H:Par ?X1 ?X2 ?X1 ?X3 |- _ =>
     not_exist_hyp (Col X1 X2 X3);let N := fresh in assert (N := par_id_1 X1 X2 X3 H)
      | H:Par ?X1 ?X2 ?X1 ?X3 |- _ =>
     not_exist_hyp (Col X1 X2 X3);let N := fresh in assert (N := par_id_2 X1 X2 X3 H)
      | H:Par ?X1 ?X2 ?X1 ?X3 |- _ =>
     not_exist_hyp (Col X1 X2 X3);let N := fresh in assert (N := par_id_3 X1 X2 X3 H)
      | H:Par ?X1 ?X2 ?X1 ?X3 |- _ =>
     not_exist_hyp (Col X1 X2 X3);let N := fresh in assert (N := par_id_4 X1 X2 X3 H)
      | H:Par ?X1 ?X2 ?X1 ?X3 |- _ =>
     not_exist_hyp (Col X1 X2 X3);let N := fresh in assert (N := par_id_5 X1 X2 X3 H)

      | H:Par ?X1 ?X2 ?X3 ?X4, H2:Col ?X1 ?X2 ?X5, H3:Col ?X3 ?X4 ?X5 |- _ =>
     not_exist_hyp (Col X1 X2 X3);let N := fresh in assert (N := not_strict_par1 X1 X2 X3 X4 X5 H H2 H3)
 end.

Ltac assert_cols_perm := permutation_intro_in_hyps; assert_cols_aux; clean_reap_hyps.

Ltac not_exist_hyp_perm_cong A B C D := not_exist_hyp (Cong A B C D); not_exist_hyp (Cong A B D C);
                                        not_exist_hyp (Cong B A C D); not_exist_hyp (Cong B A D C);
                                        not_exist_hyp (Cong C D A B); not_exist_hyp (Cong C D B A);
                                        not_exist_hyp (Cong D C A B); not_exist_hyp (Cong D C B A).

Ltac assert_congs_1 :=
repeat
 match goal with
      | H:Midpoint ?X1 ?X2 ?X3 |- _ =>
      let h := fresh in
      not_exist_hyp_perm_cong X1 X2 X1 X3;
      assert (h := midpoint_cong X2 X1 X3 H)

      | H1:Midpoint ?M1 ?A1 ?B1, H2:Midpoint ?M2 ?A2 ?B2, H3:Cong ?A1 ?B1 ?A2 ?B2 |- _ => 
      let h := fresh in
      not_exist_hyp_perm_cong A1 M1 A2 M2;
      assert (h := cong_cong_half_1 A1 M1 B1 A2 M2 B2 H1 H2 H3)

      | H:Parallelogram ?X1 ?X2 ?X3 ?X4 |- _ =>
      let h := fresh in
      not_exist_hyp_perm_cong X1 X2 X3 X4;
      assert (h := plg_cong_1 X1 X2 X3 X4 H)

      | H:Parallelogram_strict ?X1 ?X2 ?X3 ?X4 |- _ =>
      let h := fresh in
      not_exist_hyp_perm_cong X1 X2 X3 X4;
      assert (h := plgs_cong_1 X1 X2 X3 X4 H)
  end.

Ltac assert_congs_2 :=
repeat
 match goal with
      | H1:Midpoint ?M1 ?A1 ?B1, H2:Midpoint ?M2 ?A2 ?B2, H3:Cong ?A1 ?B1 ?A2 ?B2 |- _ => 
      let h := fresh in
      not_exist_hyp_perm_cong A1 M1 A2 M2;
      assert (h := cong_cong_half_2 A1 M1 B1 A2 M2 B2 H1 H2 H3)

      | H:Parallelogram ?X1 ?X2 ?X3 ?X4 |- _ =>
      let h := fresh in
      not_exist_hyp_perm_cong X1 X4 X2 X3;
      assert (h := plg_cong_2 X1 X2 X3 X4 H);clean_reap_hyps

      | H:Parallelogram_strict ?X1 ?X2 ?X3 ?X4 |- _ =>
      let h := fresh in
      not_exist_hyp_perm_cong X1 X4 X2 X3;
      assert (h := plgs_cong_2 X1 X2 X3 X4 H);clean_reap_hyps
  end.

Ltac assert_congs_perm := permutation_intro_in_hyps; assert_congs_1; assert_congs_2; clean_reap_hyps.

Ltac not_exist_hyp_perm_para A B C D := not_exist_hyp (Parallelogram A B C D); not_exist_hyp (Parallelogram B C D A);
                                        not_exist_hyp (Parallelogram C D A B); not_exist_hyp (Parallelogram D A B C);
                                        not_exist_hyp (Parallelogram A D C B); not_exist_hyp (Parallelogram D C B A);
                                        not_exist_hyp (Parallelogram C B A D); not_exist_hyp (Parallelogram B A D C).

Ltac not_exist_hyp_perm_para_s A B C D := not_exist_hyp (Parallelogram_strict A B C D);
                                          not_exist_hyp (Parallelogram_strict B C D A);
                                          not_exist_hyp (Parallelogram_strict C D A B);
                                          not_exist_hyp (Parallelogram_strict D A B C);
                                          not_exist_hyp (Parallelogram_strict A D C B);
                                          not_exist_hyp (Parallelogram_strict D C B A);
                                          not_exist_hyp (Parallelogram_strict C B A D);
                                          not_exist_hyp (Parallelogram_strict B A D C).

Ltac assert_paras_aux :=
repeat
 match goal with
      | H:Parallelogram_strict ?X1 ?X2 ?X3 ?X4 |- _ =>
      let h := fresh in
      not_exist_hyp_perm_para X1 X2 X3 X4;
      assert (h := Parallelogram_strict_Parallelogram X1 X2 X3 X4 H)

      | H:Plg ?X1 ?X2 ?X3 ?X4 |- _ =>
      let h := fresh in
      not_exist_hyp_perm_para X1 X2 X3 X4;
      assert (h := plg_to_parallelogram X1 X2 X3 X4 H)

      | H:(~ Col ?X1 ?X2 ?X3), H2:Par ?X1 ?X2 ?X3 ?X4, H3:Par ?X1 ?X4 ?X2 ?X3 |- _ =>
      let h := fresh in
      not_exist_hyp_perm_para_s X1 X2 X3 X4;
      assert (h := parallel_2_plg X1 X2 X3 X4 H H2 H3)
  end.

Ltac assert_paras_perm := permutation_intro_in_hyps; assert_paras_aux; clean_reap_hyps.

Ltac not_exist_hyp_perm_npara A B C D := not_exist_hyp (~Parallelogram A B C D); not_exist_hyp (~Parallelogram B C D A);
                                         not_exist_hyp (~Parallelogram C D A B); not_exist_hyp (~Parallelogram D A B C);
                                         not_exist_hyp (~Parallelogram A D C B); not_exist_hyp (~Parallelogram D C B A);
                                         not_exist_hyp (~Parallelogram C B A D); not_exist_hyp (~Parallelogram B A D C).

Ltac assert_nparas_1 :=
 repeat
 match goal with
      | H:(?X1<>?X2), H2:Parallelogram ?X1 ?X2 ?X3 ?X4 |- _ =>
      let h := fresh in
      not_exist_hyp_perm_npara X1 X2 X4 X3;
      assert (h := plg_not_comm_1 X1 X2 X3 X4 H H2)
  end.

Ltac assert_nparas_2 :=
 repeat
 match goal with
      | H:(?X1<>?X2), H2:Parallelogram ?X1 ?X2 ?X3 ?X4 |- _ =>
      let h := fresh in
      not_exist_hyp_perm_npara X2 X1 X3 X4;
      assert (h := plg_not_comm_2 X1 X2 X3 X4 H H2)
  end.

Ltac assert_nparas_perm := permutation_intro_in_hyps; assert_nparas_1; assert_nparas_2; clean_reap_hyps.

Ltac diag_plg_intersection M A B C D H :=
 let T := fresh in assert(T:= plg_mid A B C D H);
 ex_and T M.

Tactic Notation "Name" ident(M) "the" "intersection" "of" "the" "diagonals" "(" ident(A) ident(C) ")" "and" "(" ident(B) ident(D) ")" "of" "the" "parallelogram" ident(H) :=
 diag_plg_intersection M A B C D H.

Ltac assert_diffs :=
repeat
 match goal with
      | H:(~Col ?X1 ?X2 ?X3) |- _ =>
      let h := fresh in
      not_exist_hyp3 X1 X2 X1 X3 X2 X3;
      assert (h := not_col_distincts X1 X2 X3 H);decompose [and] h;clear h;clean_reap_hyps 

      | H:(~Bet ?X1 ?X2 ?X3) |- _ =>
      let h := fresh in
      not_exist_hyp2 X1 X2 X2 X3;
      assert (h := not_bet_distincts X1 X2 X3 H);decompose [and] h;clear h;clean_reap_hyps
      | H:Bet ?A ?B ?C, H2 : ?A <> ?B |-_ =>
      let T:= fresh in (not_exist_hyp_comm A C);
        assert (T:= bet_neq12__neq A B C H H2);clean_reap_hyps
      | H:Bet ?A ?B ?C, H2 : ?B <> ?A |-_ =>
      let T:= fresh in (not_exist_hyp_comm A C);
        assert (T:= bet_neq21__neq A B C H H2);clean_reap_hyps
      | H:Bet ?A ?B ?C, H2 : ?B <> ?C |-_ =>
      let T:= fresh in (not_exist_hyp_comm A C);
        assert (T:= bet_neq23__neq A B C H H2);clean_reap_hyps
      | H:Bet ?A ?B ?C, H2 : ?C <> ?B |-_ =>
      let T:= fresh in (not_exist_hyp_comm A C);
        assert (T:= bet_neq32__neq A B C H H2);clean_reap_hyps

      | H:Cong ?A ?B ?C ?D, H2 : ?A <> ?B |-_ =>
      let T:= fresh in (not_exist_hyp_comm C D);
        assert (T:= cong_diff A B C D H2 H);clean_reap_hyps
      | H:Cong ?A ?B ?C ?D, H2 : ?B <> ?A |-_ =>
      let T:= fresh in (not_exist_hyp_comm C D);
        assert (T:= cong_diff_2 A B C D H2 H);clean_reap_hyps
      | H:Cong ?A ?B ?C ?D, H2 : ?C <> ?D |-_ =>
      let T:= fresh in (not_exist_hyp_comm A B);
        assert (T:= cong_diff_3 A B C D H2 H);clean_reap_hyps
      | H:Cong ?A ?B ?C ?D, H2 : ?D <> ?C |-_ =>
      let T:= fresh in (not_exist_hyp_comm A B);
        assert (T:= cong_diff_4 A B C D H2 H);clean_reap_hyps

      | H:Le ?A ?B ?C ?D, H2 : ?A <> ?B |-_ =>
      let T:= fresh in (not_exist_hyp_comm C D);
        assert (T:= le_diff A B C D H2 H);clean_reap_hyps
      | H:Le ?A ?B ?C ?D, H2 : ?B <> ?A |-_ =>
      let T:= fresh in (not_exist_hyp_comm C D);
        assert (T:= le_diff A B C D (swap_diff B A H2) H);clean_reap_hyps
      | H:Lt ?A ?B ?C ?D |-_ =>
      let T:= fresh in (not_exist_hyp_comm C D);
        assert (T:= lt_diff A B C D H);clean_reap_hyps

      | H:Midpoint ?I ?A ?B, H2 : ?A<>?B |- _ =>
      let T:= fresh in (not_exist_hyp2 I B I A);
       assert (T:= midpoint_distinct_1 I A B H2 H);
       decompose [and] T;clear T;clean_reap_hyps
      | H:Midpoint ?I ?A ?B, H2 : ?B<>?A |- _ =>
      let T:= fresh in (not_exist_hyp2 I B I A);
       assert (T:= midpoint_distinct_1 I A B (swap_diff B A H2) H);
       decompose [and] T;clear T;clean_reap_hyps

      | H:Midpoint ?I ?A ?B, H2 : ?I<>?A |- _ =>
      let T:= fresh in (not_exist_hyp2 I B A B);
       assert (T:= midpoint_distinct_2 I A B H2 H);
       decompose [and] T;clear T;clean_reap_hyps
      | H:Midpoint ?I ?A ?B, H2 : ?A<>?I |- _ =>
      let T:= fresh in (not_exist_hyp2 I B A B);
       assert (T:= midpoint_distinct_2 I A B (swap_diff A I H2) H);
       decompose [and] T;clear T;clean_reap_hyps

      | H:Midpoint ?I ?A ?B, H2 : ?I<>?B |- _ =>
      let T:= fresh in (not_exist_hyp2 I A A B);
       assert (T:= midpoint_distinct_3 I A B H2 H);
       decompose [and] T;clear T;clean_reap_hyps
      | H:Midpoint ?I ?A ?B, H2 : ?B<>?I |- _ =>
      let T:= fresh in (not_exist_hyp2 I A A B);
       assert (T:= midpoint_distinct_3 I A B (swap_diff B I H2) H);
       decompose [and] T;clear T;clean_reap_hyps

      | H:Per ?A ?B ?C, H2 : ?A<>?B |- _ =>
      let T:= fresh in (not_exist_hyp_comm A C);
        assert (T:= per_distinct A B C H H2); clean_reap_hyps
      | H:Per ?A ?B ?C, H2 : ?B<>?A |- _ =>
      let T:= fresh in (not_exist_hyp_comm A C);
        assert (T:= per_distinct A B C H (swap_diff B A H2)); clean_reap_hyps
      | H:Per ?A ?B ?C, H2 : ?B<>?C |- _ =>
      let T:= fresh in (not_exist_hyp_comm A C);
        assert (T:= per_distinct_1 A B C H H2); clean_reap_hyps
      | H:Per ?A ?B ?C, H2 : ?C<>?B |- _ =>
      let T:= fresh in (not_exist_hyp_comm A C);
        assert (T:= per_distinct_1 A B C H (swap_diff C B H2)); clean_reap_hyps

      | H:Perp ?A ?B ?C ?D |- _ =>
      let T:= fresh in (not_exist_hyp2 A B C D);
       assert (T:= perp_distinct A B C D H);
       decompose [and] T;clear T;clean_reap_hyps
      | H:Perp_at ?X ?A ?B ?C ?D |- _ =>
      let T:= fresh in (not_exist_hyp2 A B C D);
       assert (T:= perp_in_distinct X A B C D H);
       decompose [and] T;clear T;clean_reap_hyps
      | H:Out ?A ?B ?C |- _ =>
      let T:= fresh in (not_exist_hyp2 A B A C);
       assert (T:= out_distinct A B C H);
       decompose [and] T;clear T;clean_reap_hyps

      | H:TS ?A ?B ?C ?D |- _ =>
      let h := fresh in
      not_exist_hyp6 A B A C A D B C B D C D;
      assert (h := ts_distincts A B C D H);decompose [and] h;clear h;clean_reap_hyps
      | H:OS ?A ?B ?C ?D |- _ =>
      let h := fresh in
      not_exist_hyp5 A B A C A D B C B D;
      assert (h := os_distincts A B C D H);decompose [and] h;clear h;clean_reap_hyps
      | H:~ Coplanar ?A ?B ?C ?D |- _ =>
      let h := fresh in
      not_exist_hyp6 A B A C A D B C B D C D;
      assert (h := ncop_distincts A B C D H);decompose [and] h;clear h;clean_reap_hyps

      | H:CongA ?A ?B ?C ?A' ?B' ?C' |- _ =>
      let T:= fresh in (not_exist_hyp_comm A B);
        assert (T:= conga_diff1 A B C A' B' C' H);clean_reap_hyps
      | H:CongA ?A ?B ?C ?A' ?B' ?C' |- _ =>
      let T:= fresh in (not_exist_hyp_comm B C);
        assert (T:= conga_diff2 A B C A' B' C' H);clean_reap_hyps
      | H:CongA ?A ?B ?C ?A' ?B' ?C' |- _ =>
      let T:= fresh in (not_exist_hyp_comm A' B');
        assert (T:= conga_diff45 A B C A' B' C' H);clean_reap_hyps
      | H:CongA ?A ?B ?C ?A' ?B' ?C' |- _ =>
      let T:= fresh in (not_exist_hyp_comm B' C');
        assert (T:= conga_diff56 A B C A' B' C' H);clean_reap_hyps

      | H:(InAngle ?P ?A ?B ?C) |- _ =>
      let h := fresh in
      not_exist_hyp3 A B C B P B;
      assert (h := inangle_distincts A B C P H);decompose [and] h;clear h;clean_reap_hyps
      | H:LeA ?A ?B ?C ?D ?E ?F |- _ =>
      let h := fresh in
      not_exist_hyp4 A B B C D E E F;
      assert (h := lea_distincts A B C D E F H);decompose [and] h;clear h;clean_reap_hyps
      | H:LtA ?A ?B ?C ?D ?E ?F |- _ =>
      let h := fresh in
      not_exist_hyp4 A B B C D E E F;
      assert (h := lta_distincts A B C D E F H);decompose [and] h;clear h;clean_reap_hyps
      | H:(Acute ?A ?B ?C) |- _ =>
      let h := fresh in
      not_exist_hyp2 A B B C;
      assert (h := acute_distincts A B C H);decompose [and] h;clear h;clean_reap_hyps
      | H:(Obtuse ?A ?B ?C) |- _ =>
      let h := fresh in
      not_exist_hyp2 A B B C;
      assert (h := obtuse_distincts A B C H);decompose [and] h;clear h;clean_reap_hyps
      | H:SuppA ?A ?B ?C ?D ?E ?F |- _ =>
      let h := fresh in
      not_exist_hyp4 A B B C D E E F;
      assert (h := suppa_distincts A B C D E F H);decompose [and] h;clear h;clean_reap_hyps

      | H:(Orth_at ?X ?A ?B ?C ?U ?V) |- _ =>
      let h := fresh in
      not_exist_hyp4 A B A C B C U V;
      assert (h := orth_at_distincts A B C U V X H);decompose [and] h;clear h;clean_reap_hyps
      | H:(Orth ?A ?B ?C ?U ?V) |- _ =>
      let h := fresh in
      not_exist_hyp4 A B A C B C U V;
      assert (h := orth_distincts A B C U V H);decompose [and] h;clear h;clean_reap_hyps

      | H:Inter ?A ?B ?C ?D ?X |- _ =>
      let T:= fresh in (not_exist_hyp2 A B C D);
       assert (T:= inter_distincts A B C D X H);decompose [and] T;clear T;clean_reap_hyps

      | H:Par_strict ?A ?B ?C ?D |- _ =>
      let T:= fresh in (not_exist_hyp6 A B A C A D B C B D C D);
       assert (T:= par_strict_distinct A B C D H);
       decompose [and] T;clear T;clean_reap_hyps
      | H:Par ?A ?B ?C ?D |- _ =>
      let T:= fresh in (not_exist_hyp2 A B C D);
       assert (T:= par_distincts A B C D H);decompose [and] T;clear T;clean_reap_hyps
      | H:Perp ?A ?B ?C ?D |- _ =>
      let T:= fresh in (not_exist_hyp2 A B C D);
       assert (T:= perp_distinct A B C D H);
       decompose [and] T;clear T;clean_reap_hyps
      | H:Perp_at ?X ?A ?B ?C ?D |- _ =>
      let T:= fresh in (not_exist_hyp2 A B C D);
       assert (T:= perp_in_distinct X A B C D H);
       decompose [and] T;clear T;clean_reap_hyps
      | H:Out ?A ?B ?C |- _ =>
      let T:= fresh in (not_exist_hyp2 A B A C);
       assert (T:= out_distinct A B C H);
       decompose [and] T;clear T;clean_reap_hyps

      | H:SumA ?A ?B ?C ?D ?E ?F ?G ?I ?J |- _ =>
      let h := fresh in
      not_exist_hyp6 A B B C D E E F G I I J;
      assert (h := suma_distincts A B C D E F G I J H);decompose [and] h;clear h;clean_reap_hyps

      | H:TriSumA ?A ?B ?C ?D ?E ?F |- _ =>
      let h := fresh in
      not_exist_hyp5 A B B C A C D E E F;
      assert (h := trisuma_distincts A B C D E F H);decompose [and] h;clear h;clean_reap_hyps

      | H:SAMS ?A ?B ?C ?D ?E ?F |- _ =>
      let h := fresh in
      not_exist_hyp4 A B B C D E E F;
      assert (h := sams_distincts A B C D E F H);decompose [and] h;clear h;clean_reap_hyps

      | H:Parallelogram_strict ?A ?B ?C ?D |- _ =>
      let T := fresh in
      not_exist_hyp6 A B B C C D D A A C B D;
       assert (T:= plgs_diff A B C D H);decompose [and] T;clear T;clean_reap_hyps
 end.

Hint Resolve parallelogram_strict_not_col
             parallelogram_strict_not_col_2
             parallelogram_strict_not_col_3
             parallelogram_strict_not_col_4 : col.

Hint Resolve plg_cong_1 plg_cong_2 plgs_cong_1 plgs_cong_2 : cong.

Section Quadrilateral_inter_dec_2.

Context `{TE:Tarski_euclidean}.

Lemma parallelogram_strict_midpoint : forall A B C D I,
  Parallelogram_strict A B C D ->
  Col I A C ->
  Col I B D ->
  Midpoint I A C /\ Midpoint I B D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
assert (T:=Parallelogram_strict_Parallelogram A B C D H).
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
assert (HpF := plg_mid A B C D T).
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
elim HpF; intros I' HI;spliter;clear HpF.
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
assert (H01 : Col A C I).
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
 Col.
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
assert (H02 : Col D B I).
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
 Col.
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
assert (H03 : ~Col A D C).
(* Goal: not (@Col Tn A D C) *)
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
 apply parallelogram_strict_not_col_3 in H.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
 Col.
(* Goal: @InAngle Tn D A B C *)
unfold Parallelogram_strict in H.
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
decompose [and] H.
(* trouver unicité intersection *)
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
assert (H8 := two_sides_not_col A C B D H4).
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
assert (MDB:D<>B).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
 assert (Col A I' C).
(* Goal: @Col Tn A I' C *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
  assert (H9 := midpoint_bet A I' C H2).
(* Goal: @Col Tn A I' C *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
  assert (H10 := bet_col A I' C H9).
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
  assumption.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
 assert (H11 : ~ Col A C D).
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
  Col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
 assert (H12 := l7_2 I' B D H3).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
 assert (H13 : Col A C I').
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
  Col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
 apply (midpoint_distinct A C I' D B H11 H13 H12).
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
assert (H11 : Col D B I').
(* Goal: @Col Tn D B I' *)
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
 assert (H14 := midpoint_bet B I' D H3).
(* Goal: @Col Tn D B I' *)
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
 assert (H15 := bet_col B I' D H14).
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
 Col.
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
assert (H12 : Col A C I').
(* Goal: @Col Tn A C I' *)
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
 assert (H14 := midpoint_bet A I' C H2).
(* Goal: @Col Tn A C I' *)
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
 assert (H15 := bet_col A I' C H14).
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
 Col.
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
apply not_col_permutation_5 in H03.
(* Goal: and (@Midpoint Tn I A C) (@Midpoint Tn I B D) *)
assert (H13 := l6_21 A C D B I I' H03 MDB H01 H12 H02 H11).
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
 rewrite H13;assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
 subst;assumption.
Qed.

Lemma rmb_perp :
 forall A B C D,
  A <> C -> B <> D ->
  Rhombus A B C D ->
  Perp A C B D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: and (@Par Tn A B C D) (@Par Tn A D B C) *)
assert(HH:= H1).
unfold Rhombus in HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply plg_to_parallelogram in H2.
apply plg_mid in H2.
ex_and H2 M.
(* Goal: and (@Par Tn A B C D) (@Par Tn A D B C) *)
assert(HH:= H1).
eapply (rmb_per _ _ _ _ M) in HH.
apply per_perp_in in HH.

apply perp_in_perp_bis in HH.
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
induction HH.
apply perp_not_eq_1 in H5.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.
(* Goal: and (@Col Tn M B D) (@Bet Tn A M C) *)
unfold Midpoint in *.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
eapply perp_col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply perp_sym.
apply perp_left_comm.
eapply perp_col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
apply perp_left_comm.
apply perp_sym.
(* Goal: False *)
(* Goal: False *)
apply H5.
apply bet_col in H4.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
apply bet_col in H2.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst M.
apply is_midpoint_id in H2.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst M.
apply l7_2 in H4.
apply is_midpoint_id in H4.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma rect_permut : forall A B C D, Rectangle A B C D -> Rectangle B C D A.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Rectangle Tn B A D C *)
unfold Rectangle in *.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Parallelogram Tn B A D C *)
(* Goal: @Per Tn B C D *)
apply plg_to_parallelogram in H.
(* Goal: @Plg Tn B C D A *)
(* Goal: @Cong Tn B D C A *)
apply plg_permut in H.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Cong Tn A B B C *)
apply parallelogram_to_plg in H.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Cong Tn A B B C *)
Cong.
Qed.

Lemma rect_comm2 : forall A B C D, Rectangle A B C D -> Rectangle B A D C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Rectangle Tn B A D C *)
unfold Rectangle in *.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Parallelogram Tn B A D C *)
(* Goal: @Per Tn B C D *)
apply plg_to_parallelogram in H.

(* Goal: and (@Plg Tn B A D C) (@Cong Tn B D A C) *)
apply plg_comm2 in H.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @InAngle Tn D A B C *)
apply parallelogram_to_plg.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Cong Tn A B B C *)
Cong.
Qed.

Lemma rect_per1 : forall A B C D, Rectangle A B C D -> Per B A D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
unfold Rectangle in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(HH:= midpoint_existence A B).
ex_and HH P.
assert(HH:= midpoint_existence C D).
ex_and HH Q.
(* Goal: @InAngle Tn D A B C *)
assert(HH:=H).
unfold Plg in HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
ex_and H4 M.
(* Goal: @Parallelogram Tn B A D C *)
(* Goal: @Per Tn B C D *)
apply plg_to_parallelogram in H.
(* Goal: or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B D')) *)
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D')) *)
(* Goal: @Midpoint Tn M B D *)
induction H.

assert(HH:=half_plgs A B C D P Q M H H1 H2 H4).
(* Goal: @Parallelogram Tn A B C D *)
spliter.
assert(Per A P Q).
eapply (per_col _  _ M).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst M.
apply is_midpoint_id in H7.
subst Q.
apply cong_identity in H8.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
assert(B = C).
eapply symmetric_point_uniqueness.
apply l7_2.
(* Goal: False *)
(* Goal: False *)
apply H5.
Midpoint.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
subst C.
(* Goal: @InAngle Tn D A B C *)
unfold Parallelogram_strict in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (not (@eq (@Tpoint Tn) A B)) (not (@eq (@Tpoint Tn) C B)) *)
(* Goal: @InAngle Tn D A B C *)
unfold TS in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H9.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Per Tn C D A *)
apply l8_2.
unfold Per.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A B) (@Col Tn X C B)) *)
(* Goal: @Plg Tn A B C D *)
exists B.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
eapply (cong_cong_half_1 _ M _ _ M) in H0.
(* Goal: @Cong Tn A B B C *)
Cong.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
unfold Midpoint in H7.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn A M C *)
(* Goal: @Col Tn A M B *)
(* Goal: not (@Col Tn C B D) *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply bet_col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

(* Goal: False *)
assert(A <> B).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
subst B.
apply l7_3 in H1.
subst P.
(* Goal: @InAngle Tn D A B C *)
unfold Parallelogram_strict in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (not (@eq (@Tpoint Tn) A B)) (not (@eq (@Tpoint Tn) C B)) *)
(* Goal: @InAngle Tn D A B C *)
unfold TS in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

assert(A <> P).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst P.
apply is_midpoint_id in H1.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.

apply perp_in_per.
apply perp_in_comm.
apply perp_perp_in.

apply perp_sym.
apply perp_left_comm.
eapply cop_par_perp__perp.
(* Goal: False *)
(* Goal: False *)
apply H6.
apply per_perp_in in H9.
apply perp_in_perp_bis in H9.
induction H9.
apply perp_not_eq_1 in H9.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.
apply perp_sym.
eapply perp_col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H9.
(* Goal: @Col Tn M B C *)
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
unfold Midpoint in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn A M C *)
(* Goal: @Col Tn A M B *)
(* Goal: not (@Col Tn C B D) *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply bet_col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

(* Goal: @Par_strict Tn C B A D *)
(* Goal: False *)
induction H6.
unfold Par_strict in H6.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
Cop.
(* Goal: or (and (@eq (@Tpoint Tn) A D) (@eq (@Tpoint Tn) B C)) (and (@eq (@Tpoint Tn) A B) (@eq (@Tpoint Tn) D C)) *)
unfold Parallelogram_flat in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(A = B /\ C = D \/ A = D /\ C = B).
apply(midpoint_cong_uniqueness A C B D M).
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
split; assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
induction H10.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: False *)
subst B.
(* Goal: @Per Tn C D A *)
apply l8_2.
apply l8_5.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
apply l8_5.
Qed.

Lemma rect_per2 : forall A B C D, Rectangle A B C D -> Per A B C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
apply rect_comm2 in H.
eapply rect_per1.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
Qed.

Lemma rect_per3 : forall A B C D, Rectangle A B C D -> Per B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
apply rect_permut in H.
apply rect_comm2 in H.
eapply rect_per1.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
Qed.

Lemma rect_per4 : forall A B C D, Rectangle A B C D -> Per A D C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
apply rect_comm2 in H.
eapply rect_per2.
(* Goal: @Rectangle Tn A B C D *)
apply rect_permut.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
Qed.

Lemma plg_per_rect1 : forall A B C D, Plg A B C D -> Per D A B -> Rectangle A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.

assert(HH:= midpoint_existence A B).
ex_and HH P.
assert(HH:= midpoint_existence C D).
ex_and HH Q.
(* Goal: @InAngle Tn D A B C *)
assert(HH:=H).
unfold Plg in HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
ex_and H4 M.
(* Goal: @Parallelogram Tn B A D C *)
(* Goal: @Per Tn B C D *)
apply plg_to_parallelogram in H.
(* Goal: or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B D')) *)
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D')) *)
(* Goal: @Midpoint Tn M B D *)
induction H.

assert(HH:=half_plgs A B C D P Q M H H1 H2 H4).
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(A <> D /\ P <> Q).
(* Goal: @Par_strict Tn C B A D *)
(* Goal: False *)
induction H6.
unfold Par_strict in H6.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
unfold Par in H6.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
split; assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
split; assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

(* Goal: False *)
assert(A <> B).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
subst B.
(* Goal: @InAngle Tn D A B C *)
unfold Parallelogram_strict in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (not (@eq (@Tpoint Tn) A B)) (not (@eq (@Tpoint Tn) C B)) *)
(* Goal: @InAngle Tn D A B C *)
unfold TS in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
assert(A <> P).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst P.
apply is_midpoint_id in H1.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.

assert(Perp P Q A B).
apply (cop_par_perp__perp A D P Q A B).
(* Goal: @Par Tn C B A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
Par.
apply per_perp_in in H0.
apply perp_in_comm in H0.
apply perp_in_perp_bis in H0.
(* Goal: @Par_strict Tn A D B C *)
induction H0.
apply perp_right_comm.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply perp_not_eq_1 in H0.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
assert_cols.
(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
Cop.

assert(Perp P M A B).
eapply perp_col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst M.
apply is_midpoint_id in H7.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: False *)
(* Goal: False *)
apply H13.
unfold Midpoint in H7.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply bet_col in H7.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

assert(Perp A P P M).
eapply perp_col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply perp_sym.
(* Goal: False *)
(* Goal: False *)
apply H14.
(* Goal: @Col Tn M B C *)
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
unfold Midpoint in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply bet_col in H1.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

assert(Per A P M).
apply perp_comm in H15.
apply perp_perp_in in H15.
apply perp_in_comm in H15.
apply perp_in_per in H15.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

(* Goal: @Rectangle Tn A B C D *)
unfold Rectangle.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @InAngle Tn D A B C *)
apply parallelogram_to_plg .
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

apply l8_2 in H16.
unfold Per in H16.
ex_and H16 B'.
assert(B = B').
eapply symmetric_point_uniqueness.
apply H1.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: False *)
(* Goal: False *)
subst B'.

(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
unfold Midpoint in H4.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
unfold Midpoint in H5.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
eapply l2_11.
(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.
(* Goal: False *)
(* Goal: False *)
apply H5.
(* Goal: @Cong Tn A B B C *)
Cong.
(* Goal: @Cong Tn A B B C *)
apply cong_transitivity with A M; Cong.
(* Goal: @Cong Tn A B B C *)
apply cong_transitivity with B M; Cong.

(* Goal: @Rectangle Tn A B C D *)
unfold Rectangle.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @InAngle Tn D A B C *)
apply parallelogram_to_plg.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

(* Goal: or (and (@eq (@Tpoint Tn) A D) (@eq (@Tpoint Tn) B C)) (and (@eq (@Tpoint Tn) A B) (@eq (@Tpoint Tn) D C)) *)
unfold Parallelogram_flat in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(D = A \/ B = A).
apply (l8_9 D A B).
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
induction H10.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
apply cong_symmetry in H8.
apply cong_identity in H8.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
subst C.
(* Goal: @Cong Tn A B B C *)
Cong.
(* Goal: False *)
(* Goal: False *)
subst B.
apply cong_symmetry in H7.
apply cong_identity in H7.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: @Cong Tn A B B C *)
Cong.
Qed.

Lemma plg_per_rect2 : forall A B C D, Plg A B C D -> Per C B A -> Rectangle A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Rectangle Tn A B C D *)
apply rect_comm2.
(* Goal: @Rectangle Tn A B C D *)
apply plg_per_rect1.
(* Goal: @Plg Tn A B C D *)
(* Goal: @InAngle Tn D A B C *)
apply parallelogram_to_plg.
(* Goal: @Parallelogram Tn B A D C *)
(* Goal: @Per Tn B C D *)
apply plg_to_parallelogram in H.
(* Goal: @Parallelogram Tn B A D C *)
(* Goal: @Per Tn B C D *)
apply plg_comm2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma plg_per_rect3 : forall A B C D, Plg A B C D -> Per A D C -> Rectangle A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Rectangle Tn A B C D *)
apply rect_permut.
(* Goal: @Rectangle Tn A B C D *)
apply plg_per_rect1.
(* Goal: @Plg Tn A B C D *)
(* Goal: @InAngle Tn D A B C *)
apply parallelogram_to_plg.
(* Goal: @Parallelogram Tn B A D C *)
(* Goal: @Per Tn B C D *)
apply plg_to_parallelogram in H.
(* Goal: @Parallelogram Tn D A B C *)
(* Goal: @Per Tn C D A *)
apply plg_permut.
(* Goal: @Parallelogram Tn C D A B *)
(* Goal: @Per Tn C D A *)
apply plg_sym.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Per Tn C D A *)
apply l8_2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma plg_per_rect4 : forall A B C D, Plg A B C D -> Per B C D -> Rectangle A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Rectangle Tn A B C D *)
apply rect_comm2.
(* Goal: @Rectangle Tn B A D C *)
apply plg_per_rect3.
(* Goal: @Plg Tn A B C D *)
(* Goal: @InAngle Tn D A B C *)
apply parallelogram_to_plg.
(* Goal: @Parallelogram Tn B A D C *)
(* Goal: @Per Tn B C D *)
apply plg_to_parallelogram in H.
(* Goal: @Parallelogram Tn B A D C *)
(* Goal: @Per Tn B C D *)
apply plg_comm2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma plg_per_rect : forall A B C D, Plg A B C D -> (Per D A B \/ Per C B A \/ Per A D C \/ Per B C D) -> Rectangle A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Par_strict Tn A D B C *)
induction H0.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply plg_per_rect1; assumption.
(* Goal: @Par_strict Tn A D B C *)
induction H0.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply plg_per_rect2; assumption.
(* Goal: @Par_strict Tn A D B C *)
induction H0.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply plg_per_rect3; assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply plg_per_rect4; assumption.
Qed.

Lemma rect_per : forall A B C D, Rectangle A B C D -> Per B A D /\ Per A B C /\ Per B C D /\ Per A D C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply (rect_per1 A B C D); assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply (rect_per2 A B C D); assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply (rect_per3 A B C D); assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply (rect_per4 A B C D); assumption.
Qed.

Lemma plgf_rect_id : forall A B C D, Parallelogram_flat A B C D -> Rectangle A B C D -> A = D /\ B = C \/ A = B /\ D = C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: or (and (@eq (@Tpoint Tn) A D) (@eq (@Tpoint Tn) B C)) (and (@eq (@Tpoint Tn) A B) (@eq (@Tpoint Tn) D C)) *)
unfold Parallelogram_flat in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: or (and (@eq (@Tpoint Tn) A D) (@eq (@Tpoint Tn) B C)) (and (@eq (@Tpoint Tn) A B) (@eq (@Tpoint Tn) D C)) *)
assert(Per B A D /\ Per A B C /\ Per B C D /\ Per A D C).

(* Goal: and (@Per Tn B A D) (and (@Per Tn A B C) (and (@Per Tn B C D) (@Per Tn A D C))) *)
(* Goal: or (and (@eq (@Tpoint Tn) A D) (@eq (@Tpoint Tn) B C)) (and (@eq (@Tpoint Tn) A B) (@eq (@Tpoint Tn) D C)) *)
apply rect_per.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

(* Goal: or (and (@eq (@Tpoint Tn) A D) (@eq (@Tpoint Tn) B C)) (and (@eq (@Tpoint Tn) A B) (@eq (@Tpoint Tn) D C)) *)
assert(HH:=l8_9 A B C H6 H).
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
induction HH.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: False *)
(* Goal: False *)
subst B.
(* Goal: and (@eq (@Tpoint Tn) A A) (@eq (@Tpoint Tn) D C) *)
(* Goal: or (and (@eq (@Tpoint Tn) A D) (@eq (@Tpoint Tn) B C)) (and (@eq (@Tpoint Tn) A B) (@eq (@Tpoint Tn) D C)) *)
apply cong_symmetry in H2.
(* Goal: and (@eq (@Tpoint Tn) A A) (@eq (@Tpoint Tn) D C) *)
(* Goal: or (and (@eq (@Tpoint Tn) A D) (@eq (@Tpoint Tn) B C)) (and (@eq (@Tpoint Tn) A B) (@eq (@Tpoint Tn) D C)) *)
apply cong_identity in H2.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: and (@eq (@Tpoint Tn) A A) (@eq (@Tpoint Tn) C C) *)
split; reflexivity.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: False *)
(* Goal: False *)
subst B.
(* Goal: and (@eq (@Tpoint Tn) A D) (@eq (@Tpoint Tn) C C) *)
apply cong_identity in H3.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: and (@eq (@Tpoint Tn) A A) (@eq (@Tpoint Tn) C C) *)
split; reflexivity.
Qed.

Lemma cop_perp3__perp :
 forall A B C D,
  Coplanar A B C D ->
  Perp A B B C ->
  Perp B C C D ->
  Perp C D D A ->
  Perp D A A B.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
assert (Par A B C D)
 by (apply (l12_9 A B C D B C); Perp; Cop).
assert (Perp A B D A)
 by (apply (cop_par_perp__perp C D A B D A); Perp; Par; Cop).
(* Goal: @Perp Tn D A A B *)
auto using perp_sym, perp_left_comm.
Qed.

Lemma cop_perp3__rect :
 forall A B C D,
  Coplanar A B C D ->
  Perp A B B C ->
  Perp B C C D ->
  Perp C D D A ->
  Rectangle A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
assert (~ Col A B C)
 by (assert_diffs; apply per_not_col; Perp).
assert (Par A B C D)
 by (apply (l12_9 A B C D B C); Perp; Cop).
assert (Perp D A A B)
 by (eapply cop_perp3__perp;eauto).
assert (Par A D B C)
 by (apply (l12_9 A D B C A B); Perp; Cop).
assert (Parallelogram_strict A B C D)
 by (apply (parallel_2_plg); auto).
(* Goal: @Rectangle Tn A B C D *)
apply plg_per_rect1.
(* Goal: @Plg Tn A B C D *)
(* Goal: @InAngle Tn D A B C *)
apply parallelogram_to_plg.
(* Goal: @Parallelogram Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply Parallelogram_strict_Parallelogram.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Per Tn D A B *)
Perp.
Qed.

Lemma conga_to_par_os : forall A B C D P , Bet A D P -> OS A D B C -> CongA B A P C D P
                                           -> Par A B C D.
Proof.
(* Goal: forall (A B C D P : @Tpoint Tn) (_ : @Bet Tn A D P) (_ : @OS Tn A D B C) (_ : @CongA Tn B A P C D P), @Par Tn A B C D *)
intros A B C D P HBet HOS HCongA.
(* Goal: @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
assert_diffs.
(* Goal: @Par Tn A B C D *)
apply par_right_comm, l12_22_b with P; trivial.
  apply l6_6, bet_out; Between.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply invert_one_side, col_one_side with D; Col.
Qed.

Lemma plg_par : forall A B C D, A <> B -> B <> C -> Parallelogram A B C D -> Par A B C D /\ Par A D B C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: and (@Par Tn A B C D) (@Par Tn A D B C) *)
assert(HH:= H1).
(* Goal: and (@Par Tn A B C D) (@Par Tn A D B C) *)
apply plg_mid in HH.
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D)) *)
ex_and HH M.

(* Goal: and (@Par Tn A B C D) (@Par Tn A D B C) *)
assert(HH:=l12_17 A B C D M H H2 H3).
(* Goal: and (@Par Tn A B C D) (@Par Tn A D B C) *)
apply l7_2 in H2.
(* Goal: and (@Par Tn A B C D) (@Par Tn A D B C) *)
assert(HH1:=l12_17 B C D A M H0 H3 H2).
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Par Tn A D B C *)
apply par_symmetry.
(* Goal: @Par Tn C B A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
Par.
Qed.

Lemma plg_par_1 : forall A B C D, A <> B -> B <> C -> Parallelogram A B C D -> Par A B C D.
Proof with finish.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Parallelogram Tn A B C D *)
assert (HPar := plg_par A B C D H H0 H1); spliter...
Qed.

Lemma plg_par_2 : forall A B C D, A <> B -> B <> C -> Parallelogram A B C D -> Par A D B C.
Proof with finish.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Parallelogram Tn A B C D *)
assert (HPar := plg_par A B C D H H0 H1); spliter...
Qed.

Lemma plgs_pars_1: forall A B C D : Tpoint, Parallelogram_strict A B C D -> Par_strict A B C D.
Proof with finish.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Parallelogram Tn A B C D *)
assert (HPar := plgs_par_strict A B C D H); spliter...
Qed.

Lemma plgs_pars_2: forall A B C D : Tpoint, Parallelogram_strict A B C D -> Par_strict A D B C.
Proof with finish.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Parallelogram Tn A B C D *)
assert (HPar := plgs_par_strict A B C D H); spliter...
Qed.

End Quadrilateral_inter_dec_2.

Ltac not_exist_hyp_perm_par A B C D := not_exist_hyp (Par A B C D); not_exist_hyp (Par A B D C);
                                       not_exist_hyp (Par B A C D); not_exist_hyp (Par B A D C);
                                       not_exist_hyp (Par C D A B); not_exist_hyp (Par C D B A);
                                       not_exist_hyp (Par D C A B); not_exist_hyp (Par D C B A).

Ltac not_exist_hyp_perm_pars A B C D := not_exist_hyp (Par_strict A B C D); not_exist_hyp (Par_strict A B D C);
                                        not_exist_hyp (Par_strict B A C D); not_exist_hyp (Par_strict B A D C);
                                        not_exist_hyp (Par_strict C D A B); not_exist_hyp (Par_strict C D B A);
                                        not_exist_hyp (Par_strict D C A B); not_exist_hyp (Par_strict D C B A).

Ltac assert_pars_1 :=
 repeat
 match goal with
      | H:Par_strict ?X1 ?X2 ?X3 ?X4 |- _ =>
      let h := fresh in
      not_exist_hyp_perm_par X1 X2 X3 X4;
      assert (h := par_strict_par X1 X2 X3 X4 H)

      | H:Par ?X1 ?X2 ?X3 ?X4, H2:Col ?X1 ?X2 ?X5, H3:(~Col ?X3 ?X4 ?X5) |- _ =>
      let h := fresh in
      not_exist_hyp_perm_pars X1 X2 X3 X4;
      assert (h := par_not_col_strict X1 X2 X3 X4 X5 H H2 H3)

      | H: ?X1 <> ?X2, H2:?X2 <> ?X3, H3:Parallelogram ?X1 ?X2 ?X3 ?X4 |- _ =>
      let h := fresh in
      not_exist_hyp_perm_par X1 X2 X3 X4;
      assert (h := plg_par_1 X1 X2 X3 X4 H H2 H3)

      | H:Parallelogram_strict ?X1 ?X2 ?X3 ?X4 |- _ =>
      let h := fresh in
      not_exist_hyp_perm_pars X1 X2 X3 X4;
      assert (h := plgs_pars_1 X1 X2 X3 X4 H)
  end.

Ltac assert_pars_2 :=
 repeat
 match goal with
      | H: ?X1 <> ?X2, H2:?X2 <> ?X3, H3:Parallelogram ?X1 ?X2 ?X3 ?X4 |- _ =>
      let h := fresh in
      not_exist_hyp_perm_par X1 X4 X2 X3;
      assert (h := plg_par_2 X1 X2 X3 X4 H H2 H3)

      | H:Parallelogram_strict ?X1 ?X2 ?X3 ?X4 |- _ =>
      let h := fresh in
      not_exist_hyp_perm_pars X1 X4 X2 X3;
      assert (h := plgs_pars_2 X1 X2 X3 X4 H)
  end.

Ltac assert_pars_perm := permutation_intro_in_hyps; assert_pars_1; assert_pars_2; clean_reap_hyps.

Hint Resolve plg_par_1 plg_par_2 plgs_pars_1 plgs_pars_2 : par.

Section Quadrilateral_inter_dec_3.

Context `{TE:Tarski_euclidean}.

Lemma par_cong_cong : forall A B C D, Par A B C D -> Cong A B C D -> Cong A C B D \/ Cong A D B C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.

(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
induction(eq_dec_points A B).
(* Goal: False *)
(* Goal: False *)
subst B.
(* Goal: or (@Cong Tn A C A D) (@Cong Tn A D A C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply cong_symmetry in H0.
(* Goal: or (@Cong Tn A C A D) (@Cong Tn A D A C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply cong_identity in H0.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Cong Tn A B B C *)
Cong.

(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
induction(eq_dec_points A D).
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.

(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
assert(B = C \/ Midpoint A B C).
(* Goal: or (@eq (@Tpoint Tn) B D) (@Midpoint Tn A B D) *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
eapply l7_20.
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
unfold Par in H.
(* Goal: or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B D')) *)
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D')) *)
(* Goal: @Midpoint Tn M B D *)
induction H.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
(* Goal: False *)
(* Goal: @Midpoint Tn M B D *)
unfold Par_strict in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X A B')) *)
(* Goal: False *)
exists A.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Cong Tn A B B C *)
Cong.
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
induction H2.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
subst C.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Cong Tn A B B C *)
Cong.
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
unfold Midpoint in H2.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Cong Tn A B B C *)
Cong.

(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
assert(HH:=par_cong_mid A B C D H H0).
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D)) *)
ex_and HH M.
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
induction H3.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.

(* Goal: @Cong Tn A D B C *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
assert(HH:=mid_par_cong A B C D M H1 H2 H3 H4).
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Cong Tn A B B C *)
Cong.

(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
induction(eq_dec_points A C).
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
subst C.
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
assert(B = D \/ Midpoint A B D).
(* Goal: or (@eq (@Tpoint Tn) B D) (@Midpoint Tn A B D) *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
eapply l7_20.
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
unfold Par in H.
(* Goal: or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B D')) *)
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D')) *)
(* Goal: @Midpoint Tn M B D *)
induction H.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
(* Goal: False *)
(* Goal: @Midpoint Tn M B D *)
unfold Par_strict in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply H7.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X A B')) *)
(* Goal: False *)
exists A.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Cong Tn A B B C *)
Cong.
(* Goal: @Parallelogram Tn A B C D *)
induction H4.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: @Cong Tn A B B C *)
Cong.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
unfold Midpoint in H4.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: @Cong Tn A B B C *)
Cong.

(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Cong Tn A C B D *)
assert(HH:=mid_par_cong A B D C M H1 H4 H3 H5).
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Cong Tn A B B C *)
Cong.
Qed.

Lemma col_cong_cong : forall A B C D, Col A B C -> Col A B D -> Cong A B C D -> Cong A C B D \/ Cong A D B C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.

(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
induction(eq_dec_points A B).
(* Goal: False *)
(* Goal: False *)
subst B.
(* Goal: or (@Cong Tn A C A D) (@Cong Tn A D A C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply cong_symmetry in H1.
(* Goal: and (@Col Tn A B C) (and (@Col Tn A B C) (and (@Cong Tn A B C C) (and (@Cong Tn A C C B) (or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B C)))))) *)
(* Goal: and (@Col Tn A B C) (and (@Col Tn A B D) (and (@Cong Tn A B C D) (and (@Cong Tn A D C B) (or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B D)))))) *)
apply cong_identity in H1.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Cong Tn A B B C *)
Cong.

(* Goal: and (@Col Tn A B C) (and (@Col Tn A B D) (and (@Cong Tn A B C D) (and (@Cong Tn A D C B) (or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B D)))))) *)
induction(eq_dec_points C D).
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: and (@Col Tn A B C) (and (@Col Tn A B C) (and (@Cong Tn A B C C) (and (@Cong Tn A C C B) (or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B C)))))) *)
(* Goal: and (@Col Tn A B C) (and (@Col Tn A B D) (and (@Cong Tn A B C D) (and (@Cong Tn A D C B) (or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B D)))))) *)
apply cong_identity in H1.
(* Goal: False *)
(* Goal: False *)
subst B.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: @Cong Tn A B B C *)
Cong.

(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply par_cong_cong.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: @Col Tn O A A' *)
repeat split; Col; ColR.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma par_cong_cop :
  forall A B C D, Par A B C D -> Cong A B C D -> Coplanar A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: or (@Plg Tn A B C D) (@Plg Tn A B D C) *)
destruct (par_cong_mid A B C D) as [M HM]; trivial.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
exists M; right.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
destruct HM as [[]|[]]; [left|right]; split; Col.
Qed.

Lemma par_cong_plg :
  forall A B C D, Par A B C D -> Cong A B C D -> Plg A B C D \/ Plg A B D C.
Proof.
(* Goal: @Cong Tn A B B C *)
intros A B C D HPar HCong.
(* Goal: or (@Plg Tn A B C D) (@Plg Tn A B D C) *)
destruct (par_cong_mid A B C D) as [M HM]; trivial.
(* Goal: or (@Plg Tn A B C D) (@Plg Tn A B D C) *)
elim HM; clear HM; intro HM; destruct HM as [HMid1 HMid2].

(* Goal: @Per Tn C1 C2 D2 *)
  {
(* Goal: @Plg Tn A B C D *)
  left; split; try (exists M; Col).
  elim (eq_dec_points A C); intro HAC; treat_equalities; Col; right;
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
  intro; treat_equalities; apply par_distincts in HPar; spliter; Col.
  }

(* Goal: @Per Tn C1 C2 D2 *)
  {
(* Goal: @Plg Tn A B C D *)
  right; split; try (exists M; Col).
  elim (eq_dec_points A D); intro HAD; treat_equalities; Col; right;
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
  intro; treat_equalities; apply par_distincts in HPar; spliter; Col.
  }
Qed.

Lemma par_cong_plg_2 :
  forall A B C D,
  Par A B C D ->
  Cong A B C D ->
  Parallelogram A B C D \/ Parallelogram A B D C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
assert (HElim : Plg A B C D \/ Plg A B D C)
  by (apply par_cong_plg; assumption).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
elim HElim; intro.

(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
  left; apply plg_to_parallelogram; assumption.

(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
  right; apply plg_to_parallelogram; assumption.
Qed.

Lemma par_cong3_rect : forall A B C D, A <> C \/ B <> D -> Par A B C D -> Cong A B C D -> Cong A D B C -> Cong A C B D -> Rectangle A B C D \/ Rectangle A B D C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
unfold Par in H0.
(* Goal: @Par_strict Tn A D B C *)
induction H0.

(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
assert(HH:=par_strict_cong_mid1 A B C D H0 H1).

(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
induction HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Rectangle Tn A B C D *)
unfold Rectangle.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
split; auto.
(* Goal: @Plg Tn A B C D' *)
(* Goal: @Midpoint Tn M B D *)
unfold Plg.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
split; auto.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
ex_and H5 M.

(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: @Rectangle Tn A B C D *)
unfold Rectangle.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
split; auto.
(* Goal: @Plg Tn A B C D' *)
(* Goal: @Midpoint Tn M B D *)
unfold Plg.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
split; auto.

(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A D) (@Midpoint Tn M B C)) *)
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
unfold Par_strict in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H9.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X A B')) *)
(* Goal: False *)
exists A.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
exists M.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
split; auto.

(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Rectangle Tn A B C D *)
unfold Rectangle.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
split; auto.

(* Goal: @Plg Tn A B C D *)
(* Goal: @InAngle Tn D A B C *)
apply parallelogram_to_plg.
(* Goal: @Parallelogram Tn A B C D *)
unfold Parallelogram.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: @Parallelogram_flat Tn A B C D *)
unfold Parallelogram_flat.

(* Goal: and (@Col Tn A B C) (and (@Col Tn A B D) (and (@Cong Tn A B C D) (and (@Cong Tn A D C B) (or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B D)))))) *)
induction(eq_dec_points C D).
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: and (@Col Tn A B C) (and (@Col Tn A B C) (and (@Cong Tn A B C C) (and (@Cong Tn A C C B) (or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B C)))))) *)
(* Goal: and (@Col Tn A B C) (and (@Col Tn A B D) (and (@Cong Tn A B C D) (and (@Cong Tn A D C B) (or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B D)))))) *)
apply cong_identity in H1.
(* Goal: False *)
(* Goal: False *)
subst B.
(* Goal: @Cong Tn A B B C *)
repeat split; Col; Cong.
(* Goal: @Col Tn O A A' *)
repeat split; Col; Cong; ColR.
Qed.

Lemma pars_par_pars : forall A B C D, Par_strict A B C D -> Par A D B C -> Par_strict A D B C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Par_strict Tn A D B C *)
induction H0.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
repeat split; Cop.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
ex_and H4 X.
(* Goal: False *)
(* Goal: @Midpoint Tn M B D *)
unfold Par_strict in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
apply H8.
(* Goal: @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
exists C.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
Qed.

Lemma pars_par_plg : forall A B C D, Par_strict A B C D -> Par A D B C -> Plg A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Plg Tn A B C D *)
assert(Par_strict A D B C).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
apply pars_par_pars; auto.

(* Goal: @Plg Tn A B C D *)
assert(Par A B C D).
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

(* Goal: @Plg Tn A B C D *)
assert(A <> B /\ C <> D /\ A <> D /\ B <> C).
(* Goal: and (not (@eq (@Tpoint Tn) A B)) (and (not (@eq (@Tpoint Tn) C D)) (and (not (@eq (@Tpoint Tn) A D)) (not (@eq (@Tpoint Tn) B C)))) *)
(* Goal: @Plg Tn A B C D *)
apply par_distinct in H0.
(* Goal: and (not (@eq (@Tpoint Tn) A B)) (and (not (@eq (@Tpoint Tn) C D)) (and (not (@eq (@Tpoint Tn) A D)) (not (@eq (@Tpoint Tn) B C)))) *)
(* Goal: @Plg Tn A B C D *)
apply par_distinct in H2.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

(* Goal: @Plg Tn A B C D *)
assert(A <> C).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
subst C.
(* Goal: False *)
(* Goal: @Midpoint Tn M B D *)
unfold Par_strict in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H9.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X A B')) *)
(* Goal: False *)
exists A.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.

(* Goal: @Plg Tn A B C D *)
assert(B <> D).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: False *)
(* Goal: @Midpoint Tn M B D *)
unfold Par_strict in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H10.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A B) (@Col Tn X C B)) *)
(* Goal: @Plg Tn A B C D *)
exists B.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.

(* Goal: @Plg Tn A B C D' *)
(* Goal: @Midpoint Tn M B D *)
unfold Plg.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.

(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D)) *)
assert(HH:=midpoint_existence A C).
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D)) *)
ex_and HH M.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
exists M.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Midpoint Tn M B D *)
prolong B M D' B M.
(* Goal: @Midpoint Tn M B D *)
assert(Midpoint M B D').
(* Goal: @Midpoint Tn M B D' *)
(* Goal: @Midpoint Tn M B D *)
unfold Midpoint.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
split; auto.
(* Goal: @Cong Tn A B B C *)
Cong.
(* Goal: @Midpoint Tn M B D *)
assert(Plg A B C D').
(* Goal: @Plg Tn A B C D' *)
(* Goal: @Midpoint Tn M B D *)
unfold Plg.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B D')) *)
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D')) *)
(* Goal: @Midpoint Tn M B D *)
induction H.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.

(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
exists M.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
split; auto.

(* Goal: @Midpoint Tn M B D *)
assert(Parallelogram A B C D').
(* Goal: @Parallelogram Tn A B C D' *)
(* Goal: @Midpoint Tn M B D *)
apply plg_to_parallelogram.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Midpoint Tn M B D *)
assert(HH:=plg_par A B C D' H3 H6 H14).
(* Goal: @Parallelogram Tn A B C D *)
spliter.

(* Goal: @Midpoint Tn M B D *)
assert(~Col C A B).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: @Midpoint Tn M B D *)
unfold Par_strict in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @Midpoint Tn M B D *)
apply H20.
(* Goal: @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
exists C.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.

(* Goal: @Midpoint Tn M B D *)
assert(Col C C D /\ Col D' C D).

(* Goal: and (@Col Tn C C D) (@Col Tn D' C D) *)
(* Goal: @Midpoint Tn M B D *)
apply (parallel_uniqueness A B C D C D' C H2).
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

(* Goal: @Midpoint Tn M B D *)
assert(A <> D').
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: @Midpoint Tn M B D *)
subst D'.
(* Goal: False *)
(* Goal: False *)
unfold Par_strict in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @Midpoint Tn M B D *)
apply H22.
(* Goal: @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
exists C.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.

(* Goal: @Midpoint Tn M B D *)
assert(HH:=mid_par_cong A B C D' M H3 H20 H9 H12).
(* Goal: @Parallelogram Tn A B C D *)
spliter.

(* Goal: @Midpoint Tn M B D *)
assert(Col A A D /\ Col D' A D).
(* Goal: and (@Col Tn A A D) (@Col Tn D' A D) *)
(* Goal: @Midpoint Tn M B D *)
apply (parallel_uniqueness B C A D A D' A).

(* Goal: @Par Tn C B A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
Par.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Par Tn B C A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
apply par_left_comm.
(* Goal: @Par Tn C B A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
Par.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

(* Goal: @Midpoint Tn M B D *)
assert(D = D').

(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
eapply (l6_21 A D C D D D'); Col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: @Midpoint Tn M B D *)
unfold Par_strict in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @Midpoint Tn M B D *)
apply H30.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X A B')) *)
(* Goal: False *)
exists A.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
(* Goal: @Midpoint Tn M B D *)
subst D'.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma not_par_pars_not_cong : forall O A B A' B', Out O A B -> Out O A' B' -> Par_strict A A' B B' -> ~Cong A A' B B'.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.

(* Goal: False *)
assert(A <> B).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
subst B.
(* Goal: False *)
(* Goal: False *)
unfold Par_strict in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: False *)
apply H5.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X A B')) *)
(* Goal: False *)
exists A.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.

(* Goal: False *)
assert(A' <> B').
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
subst B'.
(* Goal: False *)
(* Goal: False *)
unfold Par_strict in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: False *)
apply H6.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X B A')) *)
(* Goal: False *)
exists A'.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.

(* Goal: False *)
assert(O <> A).
(* Goal: not (@eq (@Tpoint Tn) O A) *)
(* Goal: False *)
unfold Out in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.

(* Goal: False *)
assert(O <> A').
(* Goal: not (@eq (@Tpoint Tn) O A') *)
(* Goal: False *)
unfold Out in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.

(* Goal: False *)
assert(~Col O A A').
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: @Col Tn O A A' *)
apply out_col in H.
(* Goal: @Col Tn O A A' *)
apply out_col in H0.
(* Goal: False *)
(* Goal: False *)
assert(Col O B A').
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: False *)
(* Goal: False *)
unfold Par_strict in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: False *)
apply H11.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A B) (@Col Tn X A' B')) *)
(* Goal: False *)
exists O.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Col Tn O A A' *)
ColR.

(* Goal: False *)
assert(OS A B A' B').

apply(out_one_side_1 _ _  _ _ O).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply H7.
(* Goal: @Col Tn O A A' *)
apply out_col in H.
(* Goal: @Col Tn O A A' *)
apply out_col in H0.
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: @Col Tn O A A' *)
apply out_col in H.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

(* Goal: False *)
assert(Par A A' B B').
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

(* Goal: False *)
assert(HH:=os_cong_par_cong_par A A' B B' H8 H2 H9).
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
unfold Par in H11.
(* Goal: False *)
induction H11.
(* Goal: False *)
(* Goal: False *)
unfold Par_strict in H11.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: False *)
apply H14.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A B) (@Col Tn X A' B')) *)
(* Goal: False *)
exists O.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Col Tn O A A' *)
apply out_col in H.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Col Tn O A A' *)
apply out_col in H0.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply H7.
(* Goal: @Col Tn O A A' *)
apply out_col in H.
(* Goal: @Col Tn O A A' *)
apply out_col in H0.
(* Goal: @Col Tn O A A' *)
ColR.
Qed.

Lemma plg_uniqueness : forall A B C D D', Parallelogram A B C D -> Parallelogram A B C D' -> D = D'.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
apply plg_mid in H.
apply plg_mid in H0.
ex_and H M.
ex_and H0 M'.
assert(M = M').
eapply l7_17.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
subst M'.
eapply symmetric_point_uniqueness.
apply H1.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma plgs_trans_trivial : forall A B C D B', Parallelogram_strict A B C D -> Parallelogram_strict C D A B' 
                                             -> Parallelogram A B B' A.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
apply plgs_permut in H.
apply plgs_permut in H.
assert (B = B').
eapply plg_uniqueness.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: False *)
(* Goal: False *)
subst B'.
apply plg_trivial.
apply plgs_diff in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma par_strict_trans : forall A B C D E F, Par_strict A B C D -> Par_strict C D E F -> Par A B E F.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
eapply par_trans.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma plgs_pseudo_trans : forall A B C D E F, Parallelogram_strict A B C D -> Parallelogram_strict C D E F -> Parallelogram A B F E.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.

induction(eq_dec_points A E).
subst E.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
eapply (plgs_trans_trivial A B C D); assumption.

apply plgs_diff in H.
apply plgs_diff in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

clean_duplicated_hyps.

prolong D C D' D C.

assert(C <> D').
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: @Midpoint Tn M B D *)
subst D'.
apply cong_symmetry in H14.
apply cong_identity in H14.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.

assert(HH1:=plgs_par_strict A B C D H).
assert(HH2:=plgs_par_strict C D E F H0).
(* Goal: @Parallelogram Tn A B C D *)
spliter.

apply par_strict_symmetry in H18.

assert(HH1:= l12_6 C D A B H18).
assert(HH2:= l12_6 C D E F H16).


assert(CongA A D D' B C D').
apply par_preserves_conga_os.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Par Tn C B A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
Par.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply invert_one_side.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(CongA E D D' F C D').
apply par_preserves_conga_os.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Par Tn C B A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
Par.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply invert_one_side.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(~ Col A C D).
apply (par_strict_not_col_2 B).
(* Goal: @Par Tn C B A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
Par.

assert(~ Col E C D).
apply (par_strict_not_col_2 F).
(* Goal: @Par Tn C B A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
Par.

induction (cop_dec C D A E).

assert(HH:=cop__one_or_two_sides C D A E H24 H22 H23).

assert(CongA A D E B C F).

(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
induction HH.

assert(TS C D A F).
apply l9_2.
eapply l9_8_2.
apply l9_2.
apply H25.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(TS C D B F).
eapply l9_8_2.
apply H26.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

apply(l11_22a A D E D' B C F D').
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
eapply col_two_sides.
(* Goal: @Col Tn A M C *)
(* Goal: @Col Tn A M B *)
(* Goal: not (@Col Tn C B D) *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply bet_col.
apply H2.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: @Midpoint Tn M B D *)
subst D'.
apply between_identity in H2.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.
apply invert_two_sides.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
eapply (col_two_sides _ D).
apply bet_col in H2.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply conga_comm.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

apply(l11_22b A D E D' B C F D').
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
eapply col_one_side.
(* Goal: @Col Tn A M C *)
(* Goal: @Col Tn A M B *)
(* Goal: not (@Col Tn C B D) *)
(* Goal: @ex (@Tpoint Tn) (fun T : @Tpoint Tn => and (@Col Tn T B D) (@Bet Tn A T C)) *)
apply bet_col.
apply H2.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: @Midpoint Tn M B D *)
subst D'.
apply between_identity in H2.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.
apply invert_one_side.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
eapply (col_one_side _ D).
apply bet_col in H2.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
eapply one_side_transitivity.
apply one_side_symmetry.
apply HH1.
apply one_side_symmetry.
eapply one_side_transitivity.
apply one_side_symmetry.
apply HH2.
apply one_side_symmetry.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
apply conga_comm.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(HP0:=plgs_cong A B C D H).
assert(HP1:=plgs_cong C D E F H0).
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply cong_symmetry in H27.

assert(HP:=cong2_conga_cong A D E B C F H25 H29 H27).
(**************)

assert(Par A B E F).
eapply par_trans.
(* Goal: @Par Tn A D B C *)
apply par_symmetry.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
apply H18.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

induction(col_dec A E F).
induction H30.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
(* Goal: False *)
(* Goal: @Midpoint Tn M B D *)
apply H30.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X A B')) *)
(* Goal: False *)
exists A.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: @Parallelogram_flat Tn A B C D *)
unfold Parallelogram_flat.
(* Goal: @Cong Tn A B B C *)
repeat split; Cong.
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: @Cong Tn A B B C *)
apply cong_transitivity with C D; Cong.

induction(eq_dec_points A F).
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
subst F.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst E.

apply cong_symmetry in H27.

assert(HQ:=par_strict_cong_mid C A D B H17 H27).
ex_and HQ M.
induction H35.
(* Goal: and (@Col Tn M B D) (@Bet Tn A M C) *)
unfold Midpoint in *.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

apply H16.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
exists M.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
split; Col.
(* Goal: and (@Col Tn M B D) (@Bet Tn A M C) *)
unfold Midpoint in *.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply H19.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
exists M.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(Par A E B F \/ ~ Par_strict D C A B \/ ~ Par_strict D C E F).

(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
eapply(cong3_par2_par ); auto.
(* Goal: @Cong Tn A B B C *)
repeat split; Cong.
(* Goal: @Par Tn B A D C *)
(* Goal: @Cong Tn B A D C *)
apply par_comm.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Par Tn A D B C *)
apply par_symmetry.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

induction H32.
(* Goal: @Parallelogram Tn A B C D' *)
(* Goal: @Midpoint Tn M B D *)
apply plg_to_parallelogram.
apply pars_par_plg.

assert(Par A B F E).
eapply par_trans.
(* Goal: @Par Tn A D B C *)
apply par_symmetry.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
apply H18.
apply par_right_comm.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
induction H33.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
apply H31.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
induction H32.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
apply H32.
apply par_strict_left_comm.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
apply H32.
apply par_strict_left_comm.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
destruct (par_cong_plg_2 A B E F); auto.
(* Goal: @Par Tn C B A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
apply par_trans with C D; Par.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
apply cong_transitivity with C D; apply plgs_cong_1; assumption.
exfalso.

assert (OS A E B F).
(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
apply (cop3_osp__os A D E); Cop.
assert (~ Col D A B) by (apply (par_strict_not_col_2 C), H18).
apply osp_transitivity with C.
(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
  apply cop2_os__osp with A D; [|Cop..|Side].
(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
  intro; apply H24, coplanar_perm_12, coplanar_trans_1 with B; Col; Cop.
(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
apply cop2_os__osp with D E; [|Cop..|Side].
(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
intro; apply H24, coplanar_perm_12, coplanar_trans_1 with C; Col; Cop.

apply (l9_9 A E B F); [|assumption].
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
  apply one_side_not_col123 in H26; Col.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
  apply one_side_not_col124 in H26; Col.
apply plg_mid in H25.
destruct H25 as [M []].
exists M; split; [Col|Between].
Qed.



Lemma plgf_plgs_trans : forall A B C D E F, A <> B -> Parallelogram_flat A B C D -> Parallelogram_strict C D E F -> Parallelogram_strict A B F E.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.

(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
induction(eq_dec_points A D).
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: @Par_strict Tn A D B C *)
induction H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply cong_symmetry in H4.
apply cong_identity in H4.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
subst C.
(* Goal: @Parallelogram_strict Tn B A D C *)
(* Goal: @Parallelogram Tn B A D C *)
apply plgs_comm2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

induction(eq_dec_points B C).
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
subst C.
(* Goal: @Par_strict Tn A D B C *)
induction H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply cong_identity in H5.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: @Parallelogram_strict Tn B A D C *)
(* Goal: @Parallelogram Tn B A D C *)
apply plgs_comm2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(HH:=plgs_par_strict C D E F H1).
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(HH:=plgs_cong C D E F H1).
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(HH2:= l12_6 C D E F H4).

assert(HOS := HH2).
induction HH2.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

unfold TS in H9.
assert(~ Col F C D).
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
unfold TS in H8.
assert(~ Col E C D).
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(D <> E).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst E.
(* Goal: False *)
(* Goal: False *)
apply H13.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
assert(HH0:=H0).

induction HH0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

prolong D C D' D C.

assert(D <> D').
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: @Midpoint Tn M B D *)
subst D'.
apply between_identity in H22.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

assert(C <> D').
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: @Midpoint Tn M B D *)
subst D'.
apply cong_symmetry in H23.
apply cong_identity in H23.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.


assert(CongA E D D' F C D').

apply(par_preserves_conga_os D E F C D').
(* Goal: @Par Tn A D B C *)
apply par_symmetry.
(* Goal: @Par Tn B C A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
apply par_left_comm.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: @Midpoint Tn M B D *)
subst D'.
apply cong_symmetry in H23.
apply cong_identity in H23.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.
apply invert_one_side.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
induction(eq_dec_points A C).
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
subst C.
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
assert(B=D \/ Midpoint A B D).
(* Goal: or (@eq (@Tpoint Tn) B D) (@Midpoint Tn A B D) *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
eapply l7_20.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Cong Tn A B B C *)
Cong.
(*induction H21.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.*)
induction H27.
induction H21.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.

unfold Parallelogram_strict.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.

apply l9_2.

eapply (l9_8_2  _ _ D).
(* Goal: @TS Tn B D A C *)
unfold TS.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H10.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H10.
(* Goal: @Col Tn O A A' *)
ColR.

(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A A') (@Col Tn X A B')) *)
(* Goal: False *)
exists A.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Bet Tn B M D *)
apply midpoint_bet.
apply l7_2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
eapply l12_6.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
eapply (par_col_par_2 _ D).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
unfold Midpoint in H27.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply bet_col in H27.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
apply par_right_comm.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Cong Tn A B B C *)
apply cong_transitivity with A D; Cong.

induction(eq_dec_points B D).
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.

assert(A=C \/ Midpoint B A C).
(* Goal: or (@eq (@Tpoint Tn) B D) (@Midpoint Tn A B D) *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
eapply l7_20.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Cong Tn A B B C *)
Cong.

induction H28.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.

(* Goal: @Parallelogram_strict Tn B A D C *)
(* Goal: @Parallelogram Tn B A D C *)
apply plgs_comm2.
unfold Parallelogram_strict.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
apply l9_2.

eapply (l9_8_2 _ _ C).
(* Goal: @TS Tn B D A C *)
unfold TS.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
apply H13.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: False *)
apply H13.
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Col Tn X A B) (@Col Tn X C B)) *)
(* Goal: @Plg Tn A B C D *)
exists B.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Bet Tn B M D *)
apply midpoint_bet.
apply l7_2.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
eapply l12_6.
apply par_strict_symmetry.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
eapply (par_col_par_2 _ C).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
unfold Midpoint in H28.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
apply bet_col in H28.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Par Tn B C A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
apply par_left_comm.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Cong Tn A B B C *)
apply cong_transitivity with C B; Cong.

assert(HH:=plgf_bet A B D C H0).

assert(CongA A D E B C F).

(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
induction HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
eapply out_conga.
apply conga_comm.
apply H26.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
eapply (l5_1 _ C).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
Between.
Between.
apply out_trivial.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst E.
(* Goal: False *)
(* Goal: False *)
apply H13.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.

assert(Bet D C B).
eapply outer_transitivity_between.
apply H29.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.

eapply (l5_2 D);
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

apply out_trivial.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst F.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H10.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

induction H29.

(* Goal: @Parallelogram Tn A B C D *)
spliter.

eapply (out_conga D' D E D' C F).
apply conga_comm.
apply H26.
(* Goal: @Out Tn B M D *)
unfold Out.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
repeat split;auto.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: or (@Bet Tn I B'' B) (@Bet Tn I B B'') *)
eBetween.
apply out_trivial.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst E.
(* Goal: False *)
(* Goal: False *)
apply H13.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
repeat split; auto.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.

eapply (bet3_cong3_bet A B C D D');
auto;
(* Goal: @Cong Tn A B B C *)
Cong.
apply out_trivial.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst F.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H10.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

induction H29.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

eapply l11_13.

apply conga_comm.
apply H26.

(* Goal: @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
assert_diffs.
(* Goal: or (@Bet Tn I B'' B) (@Bet Tn I B B'') *)
eBetween.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
(* Goal: or (@Bet Tn I B'' B) (@Bet Tn I B B'') *)
eBetween.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.

(* Goal: @Parallelogram Tn A B C D *)
spliter.

eapply l11_13.

apply conga_comm.

apply H26.
(* Goal: @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
assert_diffs.
(* Goal: or (@Bet Tn I B'' B) (@Bet Tn I B B'') *)
eBetween.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
(* Goal: @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
assert_diffs.
(* Goal: or (@Bet Tn I B'' B) (@Bet Tn I B B'') *)
eBetween.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.


assert(Cong A E B F).

(* Goal: @Cong Tn A B B C *)
eapply(cong2_conga_cong A D E B C F H29);Cong.
assert(Cong_3 E A D F B C).
(* Goal: @Cong Tn A B B C *)
repeat split; Cong.

assert(Par A B E F).
eapply (par_trans A B C D E F).
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
repeat split; auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(CongA E A D F B C).
apply cong3_conga.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst E.
(* Goal: False *)
(* Goal: False *)
apply H13.
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

assert(OS A B E F).
eapply l12_6.
induction H32.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
assert(Col A B E).
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
(* Goal: False *)
(* Goal: False *)
apply H13.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
eapply (col3 A B); Col.

assert(Par A E F B).

(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
(* Goal: or (@Rectangle Tn A B C D) (@Rectangle Tn A B D C) *)
induction HH.

prolong A B A' A B.

apply (conga_to_par_os _ _ _ _ A');
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
apply conga_comm.
eapply l11_13.
apply conga_comm.
apply H33.
(* Goal: or (@Bet Tn I B'' B) (@Bet Tn I B B'') *)
eBetween.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
subst A'.
apply between_identity in H36.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: or (@Bet Tn I B'' B) (@Bet Tn I B B'') *)
eBetween.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
subst A'.
apply cong_symmetry in H37.
apply cong_identity in H37.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.

induction H35.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

prolong A B A' A B.
apply (conga_to_par_os _ _ _ _ A');
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
apply conga_comm.
eapply l11_13.
apply conga_comm.
apply H33.
(* Goal: or (@Bet Tn I B'' B) (@Bet Tn I B B'') *)
eBetween.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
subst A'.
apply between_identity in H37.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: or (@Bet Tn I B'' B) (@Bet Tn I B B'') *)
eBetween.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
subst A'.
apply cong_symmetry in H38.
apply cong_identity in H38.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.


induction H35.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
prolong A B A' A B.

apply (conga_to_par_os _ _ _ _ A');
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
apply conga_comm.

eapply out_conga.
apply conga_comm.
apply H33.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
repeat split; auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
subst A'.
apply between_identity in H37.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: or (@Bet Tn I B'' B) (@Bet Tn I B B'') *)
eBetween.
apply out_trivial.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst E.
(* Goal: False *)
(* Goal: False *)
apply H13.
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
repeat split; auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
subst A'.
apply cong_symmetry in H38.
apply cong_identity in H38.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
eapply (bet3_cong3_bet D _ _ A);
auto;
(* Goal: @Cong Tn A B B C *)
Cong.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
apply out_trivial.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst F.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H10.
(* Goal: @Col Tn O A A' *)
ColR.

(* Goal: @Parallelogram Tn A B C D *)
spliter.
prolong A B A' A C.

apply (conga_to_par_os _ _ _ _ A');
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
apply conga_comm.

eapply out_conga.
apply conga_comm.
apply H33.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
repeat split; auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
subst A'.
apply between_identity in H37.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.

assert(Bet B C A').

(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
eapply (bet_cong_bet A); auto.
(* Goal: or (@Bet Tn I B'' B) (@Bet Tn I B B'') *)
eBetween.
(* Goal: @Cong Tn A B B C *)
Cong.
(* Goal: or (@Bet Tn I B'' B) (@Bet Tn I B B'') *)
eBetween.
apply out_trivial.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst E.
(* Goal: False *)
(* Goal: False *)
apply H13.
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
(* Goal: and (@Cong Tn A A' B B') (@Par Tn A A' B B') *)
subst A'.
apply cong_symmetry in H38.
apply cong_identity in H38.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.

(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
eapply (bet_cong_bet A); auto.
(* Goal: or (@Bet Tn I B'' B) (@Bet Tn I B B'') *)
eBetween.
(* Goal: @Cong Tn A B B C *)
Cong.
apply out_trivial.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst F.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H10.
(* Goal: @Col Tn O A A' *)
ColR.

assert(Plg A B F E).
apply pars_par_plg.
induction H32.
apply par_strict_right_comm.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
assert(Col A B E).
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: False *)
(* Goal: False *)
apply H13.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
eapply (col3 A B); Col.
(* Goal: @Par Tn C B A D' *)
(* Goal: @Col Tn A A D' *)
(* Goal: @Midpoint Tn M B D *)
Par.
apply plg_to_parallelogram in H36.
induction H36.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
unfold Parallelogram_flat in H36.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

assert(Col A B E).
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
(* Goal: False *)
(* Goal: False *)
apply H13.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
eapply (col3 A B); Col.
Qed.

Lemma plgf_plgf_plgf: forall A B C D E F, A <> B -> Parallelogram_flat A B C D -> Parallelogram_flat C D E F
                                          -> Parallelogram_flat A B F E.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
assert(C <> D).
(* Goal: False *)
(* Goal: False *)
unfold Parallelogram_flat in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: and (@eq (@Tpoint Tn) A D) (@eq (@Tpoint Tn) C C) *)
apply cong_identity in H3.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
assert(E <> F).
(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
unfold Parallelogram_flat in H1.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst F.
apply cong_identity in H4.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.

assert(HH:=plgs_existence C D H2).
ex_and HH D'.
ex_and H4 C'.

assert(Parallelogram_strict A B C' D').
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
eapply (plgf_plgs_trans A B C D); auto.
assert(Parallelogram_strict E F C' D').
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
eapply (plgf_plgs_trans E F C D); auto.

apply plgf_sym.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
assert(Parallelogram A B F E).
eapply plgs_pseudo_trans.
(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.
apply plgs_sym.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
induction H7.
induction H7.
unfold TS in H7.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Parallelogram_flat Tn B A D C *)
unfold Parallelogram_flat in *.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
(* Goal: False *)
(* Goal: @Plg Tn A B C D *)
apply H10.

assert(Col C D A).
(* Goal: @Col Tn O A A' *)
ColR.
assert(Col C D B).
(* Goal: @Col Tn O A A' *)
ColR.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply (col3 C D); Col.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma plg_pseudo_trans : forall A B C D E F, Parallelogram A B C D -> Parallelogram C D E F -> Parallelogram A B F E \/ (A = B /\ C = D /\ E = F /\ A = E).
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
induction(eq_dec_points A B).
(* Goal: False *)
(* Goal: False *)
subst B.
(* Goal: or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B D')) *)
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D')) *)
(* Goal: @Midpoint Tn M B D *)
induction H.
(* Goal: @InAngle Tn D A B C *)
unfold Parallelogram_strict in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (not (@eq (@Tpoint Tn) A B)) (not (@eq (@Tpoint Tn) C B)) *)
(* Goal: @InAngle Tn D A B C *)
unfold TS in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
assert(C = D).
assert(HH:=plgf_trivial_neq A C D H).
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: @Par_strict Tn A D B C *)
induction H0.
(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
unfold Parallelogram_strict in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
unfold TS in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Col Tn B A D *)
(* Goal: @Col Tn B A D *)
(* Goal: @Cong Tn A B A D *)
(* Goal: or (@Cong Tn A A B D) (@Cong Tn A D B A) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply False_ind.
(* Goal: False *)
(* Goal: not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D)) *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
apply H0.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
assert(E=F).
assert(HH:=plgf_trivial_neq C E F H0).
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
subst F.
induction (eq_dec_points A E).
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
repeat split; auto.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
apply plg_trivial1.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.


assert(C <> D).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: or (not (@eq (@Tpoint Tn) A C)) (not (@eq (@Tpoint Tn) B D')) *)
(* Goal: @ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A C) (@Midpoint Tn M B D')) *)
(* Goal: @Midpoint Tn M B D *)
induction H.
(* Goal: @InAngle Tn D A B C *)
unfold Parallelogram_strict in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: and (not (@eq (@Tpoint Tn) A B)) (not (@eq (@Tpoint Tn) C B)) *)
(* Goal: @InAngle Tn D A B C *)
unfold TS in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: @Col Tn B A C *)
(* Goal: @Cong Tn A B A C *)
(* Goal: or (@Cong Tn A C B A) (@Cong Tn A A B C) *)
(* Goal: or (@Cong Tn A C B D) (@Cong Tn A D B C) *)
apply H4.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
apply plgf_sym in H.
apply plgf_trivial_neq in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.

assert(E <> F).
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
subst F.
(* Goal: @Par_strict Tn A D B C *)
induction H0.
(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
unfold Parallelogram_strict in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: and (not (or (@Parallelogram_strict Tn A B D C) (@Parallelogram_flat Tn A B D C))) (not (or (@Parallelogram_strict Tn B A C D) (@Parallelogram_flat Tn B A C D))) *)
unfold TS in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: False *)
apply H5.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
apply plgf_sym in H0.
apply plgf_trivial_neq in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.

(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Par_strict Tn A D B C *)
induction H; induction H0.
eapply plgs_pseudo_trans.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Perp Tn A C B D *)
(* Goal: @Square Tn A B C D *)
apply H.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
apply plgs_sym.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
apply (plgf_plgs_trans F E D C);auto.
(* Goal: @Parallelogram_flat Tn B A D C *)
apply plgf_comm2.
apply plgf_sym.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram_strict Tn B A D C *)
(* Goal: @Parallelogram Tn B A D C *)
apply plgs_comm2.
apply plgs_sym.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
apply (plgf_plgs_trans A B C D E F); auto.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
apply  (plgf_plgf_plgf A B C D E F); auto.
Qed.

Lemma Square_Rhombus : forall A B C D,
 Square A B C D -> Rhombus A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @Rhombus Tn A B C D *)
unfold Rhombus.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Cong Tn A B B C *)
apply Square_Parallelogram in H.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Cong Tn A B B C *)
apply parallelogram_to_plg in H.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Cong Tn A B B C *)
unfold Square in H.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
tauto.
Qed.

Lemma plgs_in_angle : forall A B C D, Parallelogram_strict A B C D -> InAngle D A B C.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @InAngle Tn D A B C *)
assert(Plg A B C D).
(* Goal: @Plg Tn A B C D *)
(* Goal: @InAngle Tn D A B C *)
apply parallelogram_to_plg.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.

(* Goal: @InAngle Tn D A B C *)
unfold Parallelogram_strict in H.
(* Goal: @InAngle Tn D A B C *)
unfold Plg in H0.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @InAngle Tn D A B C *)
ex_and H1 M.

(* Goal: @InAngle Tn D A B C *)
assert(A <> B /\ C <> B).
(* Goal: and (not (@eq (@Tpoint Tn) A B)) (not (@eq (@Tpoint Tn) C B)) *)
(* Goal: @InAngle Tn D A B C *)
unfold TS in H.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

split;
intro;
subst B;
apply H;
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.
(* Goal: @Parallelogram Tn A B C D *)
spliter.

(* Goal: @InAngle Tn D A B C *)
assert(HH:=H).
(* Goal: @InAngle Tn D A B C *)
unfold TS in HH.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @InAngle Tn D A B C *)
ex_and H9 T.

(* Goal: @InAngle Tn D A B C *)
unfold InAngle.
(* Goal: and (@Midpoint Tn M A C) (@Midpoint Tn M B D') *)
(* Goal: @Midpoint Tn M B D *)
repeat split; auto.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply l7_3 in H4.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst M.
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply midpoint_bet in H1.
(* Goal: False *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply H7.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
apply bet_col in H1.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
Col.

(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
exists M.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
split.
(* Goal: @Bet Tn B M D *)
apply midpoint_bet.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
(* Goal: or (@eq (@Tpoint Tn) M B) (@Out Tn B M D) *)
right.

(* Goal: @Out Tn B M D *)
unfold Out.
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
repeat split.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst M.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
unfold Midpoint in H4.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
apply cong_symmetry in H11.
(* Goal: False *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
apply cong_identity in H11.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
apply between_identity in H10.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst T.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
intro.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst D.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
apply between_identity in H10.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
subst T.
(* Goal: False *)
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
contradiction.
(* Goal: or (@Bet Tn B M D) (@Bet Tn B D M) *)
left.
(* Goal: @Bet Tn B M D *)
apply midpoint_bet.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
Qed.

Lemma par_par_cong_cong_parallelogram :
 forall A B C D,
 B<>D ->
 Cong A B C D ->
 Cong B C D A ->
 Par B C A D ->
 Par A B C D ->
 Parallelogram A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
assert (Parallelogram A B C D \/ Parallelogram A B D C)
 by (apply par_cong_plg_2;finish).
assert (Parallelogram B C A D \/ Parallelogram B C D A)
 by (apply par_cong_plg_2;finish).
(* Goal: @Parallelogram Tn A B C D *)
induction H4.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Parallelogram Tn A B C D *)
induction H5.
(* Goal: @Parallelogram Tn A B C D *)
(* Goal: @Parallelogram Tn A B C D *)
apply Plg_perm in H4.
(* Goal: @Parallelogram Tn A B C D *)
apply Plg_perm in H5.
(* Goal: @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
assert_diffs.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Parallelogram Tn A B C D *)
(* Goal: @Parallelogram Tn A B C D *)
apply plg_not_comm in H8.
(* Goal: @Parallelogram Tn A B C D *)
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
intuition.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
auto.
(* Goal: @Parallelogram Tn A B C D *)
apply Plg_perm in H5.
(* Goal: @Parallelogram Tn A B C D *)
spliter.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
Qed.

Lemma degenerated_rect_eq : forall A B C, Rectangle A B B C -> A = C.
Proof.
(* Goal: forall (A B C : @Tpoint Tn) (_ : @Rectangle Tn A B B C), @eq (@Tpoint Tn) A C *)
intros A B C HRect.
(* Goal: @eq (@Tpoint Tn) A C *)
apply Rectangle_Parallelogram in HRect; apply plg_mid in HRect.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
destruct HRect as [M [HMid1 HMid2]]; treat_equalities; auto.
Qed.

Lemma rect_2_rect : forall A B C1 C2 D1 D2,
  A <> B ->
  Rectangle A B C1 D1 ->
  Rectangle A B C2 D2 ->
  Rectangle C1 D1 D2 C2.
Proof.
(* Goal: forall (A B C1 C2 D1 D2 : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)) (_ : @Rectangle Tn A B C1 D1) (_ : @Rectangle Tn A B C2 D2), @Rectangle Tn C1 D1 D2 C2 *)
intros A B C1 C2 D1 D2 HDiff HRect1 HRect2.
(* Goal: @Midpoint Tn I B D *)
(* Goal: @Parallelogram Tn A B C D *)
elim (eq_dec_points C1 C2); intro HC1C2; treat_equalities.

(* Goal: @Per Tn C1 C2 D2 *)
  {
(* Goal: @Rectangle Tn C1 D1 D2 C1 *)
  apply Rectangle_Parallelogram in HRect1; apply plg_mid in HRect1.
(* Goal: @Rectangle Tn C1 D1 D2 C1 *)
  apply Rectangle_Parallelogram in HRect2; apply plg_mid in HRect2.
(* Goal: @Rectangle Tn C1 D1 D2 C1 *)
  destruct HRect1 as [M [HMid1 HMid2]]; destruct HRect2 as [M' [HMid3 HMid4]].
(* Goal: @Plg Tn A B C D *)
(* Goal: @InAngle Tn D A B C *)
  treat_equalities; split; Cong; apply parallelogram_to_plg.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
  apply plg_trivial; intro; treat_equalities; auto.
  }

(* Goal: @Per Tn C1 C2 D2 *)
  {
  elim (eq_dec_points B C1); intro HBC1; elim (eq_dec_points B C2); intro HBC2;
  treat_equalities; [intuition|apply degenerated_rect_eq in HRect1; treat_equalities|
                     apply degenerated_rect_eq in HRect2; treat_equalities|];
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
  apply rect_comm2; auto; apply rect_comm2; do 2 (apply rect_permut); auto.
(* Goal: @Rectangle Tn D2 C2 C1 D1 *)
  assert (HPara1 := HRect1); apply Rectangle_Parallelogram in HPara1.
(* Goal: @Rectangle Tn D2 C2 C1 D1 *)
  assert (HPara2 := HRect2); apply Rectangle_Parallelogram in HPara2.

(* Goal: @Rectangle Tn D2 C2 C1 D1 *)
  assert (HNC1 : ~ Col A B C1) by (apply rect_per2 in HRect1; apply per_not_col; auto).
(* Goal: @Rectangle Tn D2 C2 C1 D1 *)
  assert (HNC2 : ~ Col A B C2) by (apply rect_per2 in HRect2; apply per_not_col; auto).
(* Goal: @Rectangle Tn D2 C2 C1 D1 *)
  apply plg_per_rect2.

(* Goal: @Per Tn C1 C2 D2 *)
    {
    elim HPara1; clear HPara1; intro HPara1;
    [|unfold Parallelogram_flat in HPara1; spliter; intuition].
    elim HPara2; clear HPara2; intro HPara2;
    [|unfold Parallelogram_flat in HPara2; spliter; intuition].
    apply parallelogram_to_plg; apply plgs_pseudo_trans with B A;
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
    apply plgs_comm2; auto; do 2 (apply plgs_permut); auto.
    }

(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
  elim (cop_dec A B C1 C2); intro HCop.

(* Goal: @Per Tn C1 C2 D2 *)
    {
    apply perp_per_1; auto; apply perp_sym; apply cop_par_perp__perp with A B; Cop;
    apply plg_par_1 in HPara2; Par; clear HPara1; clear HPara2.
(* Goal: @Perp Tn A B C2 C1 *)
    apply rect_per2 in HRect1; apply rect_per2 in HRect2.
(* Goal: @Perp Tn A B C2 C1 *)
    assert (HCol : Col C1 C2 B) by (apply cop_per2__col with A; Perp; Cop).
(* Goal: @Per Tn D A B *)
    apply perp_col0 with B C1; Col; apply per_perp in HRect1; Perp.
    }

(* Goal: @Per Tn C1 C2 D2 *)
    {
(* Goal: @Parallelogram Tn A B C D *)
    apply rect_per in HRect1; apply rect_per in HRect2; spliter.
(* Goal: @Per Tn C1 C2 D2 *)
    destruct (eq_dec_points C2 D2); [subst; Perp|].
    assert (HOrth : Orth_at C2 B C1 C2 C2 D2);
      [|destruct HOrth as [_ [_ [_ [_ HOrth]]]]; apply HOrth; Col; Cop].
(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
    apply l11_61_bis with B A; Perp; Cop.
(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
    apply l11_60_bis; Perp; Cop.
(* Goal: @Coplanar Tn A A' B B' *)
(* Goal: not (@Col Tn B A A') *)
(* Goal: not (@Col Tn B' A A') *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
(* Goal: or (and (@TS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A A') (@Midpoint Tn M B B')))) (and (@OS Tn A A' B B') (@ex (@Tpoint Tn) (fun M : @Tpoint Tn => and (@Midpoint Tn M A B') (@Midpoint Tn M B A')))) *)
    apply ncop__ncol with A; Cop.
    }
  }
Qed.

Lemma ncol123_plg__plgs : forall A B C D,
  ~ Col A B C -> Parallelogram A B C D -> Parallelogram_strict A B C D.
Proof.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
intros A B C D HNC H; induction H; auto.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
exfalso; apply HNC; unfold Parallelogram_flat in *; spliter; Col.
Qed.

Lemma ncol124_plg__plgs : forall A B C D,
  ~ Col A B D -> Parallelogram A B C D -> Parallelogram_strict A B C D.
Proof.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
intros A B C D HNC H; induction H; auto.
(* Goal: @Col Tn B A C *)
(* Goal: @ex (@Tpoint Tn) (fun X : @Tpoint Tn => and (@Bet Tn A X C) (or (@eq (@Tpoint Tn) X B) (@Out Tn B X D))) *)
exfalso; apply HNC; unfold Parallelogram_flat in *; spliter; Col.
Qed.

Lemma ncol134_plg__plgs : forall A B C D,
  ~ Col A C D -> Parallelogram A B C D -> Parallelogram_strict A B C D.
Proof.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
intros A B C D HNC H; induction H; auto.
(* Goal: @Col Tn O A A' *)
exfalso; apply HNC; unfold Parallelogram_flat in *; spliter; assert_diffs; ColR.
Qed.

Lemma ncol234_plg__plgs : forall A B C D,
  ~ Col B C D -> Parallelogram A B C D -> Parallelogram_strict A B C D.
Proof.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
intros A B C D HNC H; induction H; auto.
(* Goal: @Col Tn O A A' *)
exfalso; apply HNC; unfold Parallelogram_flat in *; spliter; assert_diffs; ColR.
Qed.

Lemma ncol123_plg__pars1234 : forall A B C D,
  ~ Col A B C -> Parallelogram A B C D -> Par_strict A B C D.
Proof.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
intros; apply plgs_pars_1; apply ncol123_plg__plgs; auto.
Qed.

Lemma ncol124_plg__pars1234 : forall A B C D,
  ~ Col A B D -> Parallelogram A B C D -> Par_strict A B C D.
Proof.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
intros; apply plgs_pars_1; apply ncol124_plg__plgs; auto.
Qed.

Lemma ncol134_plg__pars1234 : forall A B C D,
  ~ Col A C D -> Parallelogram A B C D -> Par_strict A B C D.
Proof.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
intros; apply plgs_pars_1; apply ncol134_plg__plgs; auto.
Qed.

Lemma ncol234_plg__pars1234 : forall A B C D,
  ~ Col B C D -> Parallelogram A B C D -> Par_strict A B C D.
Proof.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
intros; apply plgs_pars_1; apply ncol234_plg__plgs; auto.
Qed.

Lemma ncol123_plg__pars1423 : forall A B C D,
  ~ Col A B C -> Parallelogram A B C D -> Par_strict A D B C.
Proof.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
intros; apply plgs_pars_2; apply ncol123_plg__plgs; auto.
Qed.

Lemma ncol124_plg__pars1423 : forall A B C D,
  ~ Col A B D -> Parallelogram A B C D -> Par_strict A D B C.
Proof.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
intros; apply plgs_pars_2; apply ncol124_plg__plgs; auto.
Qed.

Lemma ncol134_plg__pars1423 : forall A B C D,
  ~ Col A C D -> Parallelogram A B C D -> Par_strict A D B C.
Proof.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
intros; apply plgs_pars_2; apply ncol134_plg__plgs; auto.
Qed.

Lemma ncol234_plg__pars1423 : forall A B C D,
  ~ Col B C D -> Parallelogram A B C D -> Par_strict A D B C.
Proof.
(* Goal: not (@eq (@Tpoint Tn) D B) *)
(* Goal: @Parallelogram Tn A B C D *)
intros; apply plgs_pars_2; apply ncol234_plg__plgs; auto.
Qed.

Lemma sac_plg : forall A B C D, Saccheri A B C D -> Parallelogram A B C D.
Proof.
(* Goal: forall (A B C D : @Tpoint Tn) (_ : @Saccheri Tn A B C D), @Rectangle Tn A B C D *)
intros A B C D H.
(* Goal: @Parallelogram Tn A B C D *)
assert (T:=sac__par_strict1234 A B C D H).
(* Goal: @Parallelogram Tn A B C D *)
assert (U:=sac__par1423 A B C D H).
(* Goal: @Parallelogram Tn A B C D *)
assert (V:=sac__par1234 A B C D H).
(* Goal: @Parallelogram Tn A B C D *)
apply par_2_plg;eauto using par_strict_not_col_1.
Qed.

Lemma sac_rectangle : forall A B C D, Saccheri A B C D -> Rectangle A B C D.
Proof.
(* Goal: forall (A B C D : @Tpoint Tn) (_ : @Saccheri Tn A B C D), @Rectangle Tn A B C D *)
intros A B C D H.
(* Goal: @Rectangle Tn A B C D *)
assert (Parallelogram A B C D) by (apply sac_plg;auto).
(* Goal: @Rectangle Tn A B C D *)
apply parallelogram_to_plg in H0.
(* Goal: @Rectangle Tn A B C D *)
apply plg_per_rect1.
(* Goal: @Plg Tn A B C D *)
(* Goal: @Per Tn D A B *)
assumption.
(* Goal: @Per Tn D A B *)
unfold Saccheri in H.
(* Goal: @Per Tn D A B *)
spliter;finish.
Qed.

Lemma exists_square : forall A B, A<>B -> exists C D,  Square A B C D.
Proof.
(* Goal: forall (A B : @Tpoint Tn) (_ : not (@eq (@Tpoint Tn) A B)), @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
intros.
(* Goal: @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
destruct (exists_cong_per A B A B) as [C [HC1 HC2]].
(* Goal: @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
assert_diffs.
(* Goal: @Per Tn D A B *)
destruct (per__ex_saccheri B C A) as [D HSac]; Perp.
(* Goal: @ex (@Tpoint Tn) (fun C : @Tpoint Tn => @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D)) *)
exists C.
(* Goal: @ex (@Tpoint Tn) (fun D : @Tpoint Tn => @Square Tn A B C D) *)
exists D.
(* Goal: @Square Tn A B C D *)
assert (Rectangle B C D A) by (apply sac_rectangle;auto).
(* Goal: and (@Bet Tn A M C) (or (@eq (@Tpoint Tn) M B) (@Out Tn B M D)) *)
unfold Square;split.
(* Goal: @Rectangle Tn A B C D *)
(* Goal: @Cong Tn A B B C *)
auto using rect_permut.
(* Goal: @Cong Tn A B B C *)
Cong.
Qed.

End Quadrilateral_inter_dec_3.

Section Quadrilateral_inter_dec_2D.

(* Goal: @Per Tn C1 C2 D2 *)
Context `{T2D:Tarski_2D}.
(* Goal: @Per Tn C1 C2 D2 *)
Context `{TE:@Tarski_euclidean Tn TnEQD}.

Lemma perp3__perp :
 forall A B C D,
  Perp A B B C ->
  Perp B C C D ->
  Perp C D D A ->
  Perp D A A B.
Proof.
(* Goal: forall (A B C D : @Tpoint Tn) (_ : @Perp Tn A B B C) (_ : @Perp Tn B C C D) (_ : @Perp Tn C D D A), @Rectangle Tn A B C D *)
intros A B C D.
(* Goal: forall (_ : @Perp Tn A B B C) (_ : @Perp Tn B C C D) (_ : @Perp Tn C D D A), @Perp Tn D A A B *)
apply cop_perp3__perp, all_coplanar.
Qed.

Lemma perp3__rect :
 forall A B C D,
  Perp A B B C ->
  Perp B C C D ->
  Perp C D D A ->
  Rectangle A B C D.
Proof.
(* Goal: forall (A B C D : @Tpoint Tn) (_ : @Perp Tn A B B C) (_ : @Perp Tn B C C D) (_ : @Perp Tn C D D A), @Rectangle Tn A B C D *)
intros A B C D.
(* Goal: forall (_ : @Perp Tn A B B C) (_ : @Perp Tn B C C D) (_ : @Perp Tn C D D A), @Rectangle Tn A B C D *)
apply cop_perp3__rect, all_coplanar.
Qed.

End Quadrilateral_inter_dec_2D.