(* Compute the polar coordinates of a point given in *)
(* Cartesian coordinates.                            *)
fromCartesian2Polar[ q_ ] := 
Module [
{ x , y , r , t , res },
(
x = q[[ 1 ]] ;
y = q[[ 2 ]] ;

r = Sqrt[ x x + y y ] ;

If [ r > 0 ,
If [ x < 0  ,
If [ y ≥ 0 ,
t = Pi - ArcCos[ Abs[ x ] / r ] ,
t = Pi + ArcCos[ Abs[ x ] / r ]
],
If [ y ≥ 0 ,
t =   ArcSin[              y / r ] ,
t =-ArcSin[ Abs[ y ] / r ] 
]
] ,
(
r = 0 ;
t = 0 
)
] ;

res = { r , t } ;
res
) 
] ;

(* Compute the Cartesian coordinates of a point given *)
(* in Polar coordinates.                              *)
fromPolar2Cartesian[ q_ ] := 
Module [
{ x , y , r , t , res },
(
r = q[[ 1 ]] ;
t = q[[ 2 ]] ;

x = r Cos[ t ] ;
y = r Sin[ t ] ;

res = { x , y } ;
res
) 
] ;

(* Map a point from a p-domain to the canonical domain. *)
fromPDomain2Canonical[ q_ , nu_ ] := 
Module [
{ r , t , s ,b , res },
(
r = q[[ 1 ]] ;
t = q[[ 2 ]] ;

s = r^{nu / 4} ;
b =( nu / 4 ) t ;

res = Append[ s , b ] ;
res
) 
] ;

(* Map a point from the canonical domain to a p-domain. *)
fromCanonical2PDomain[ q_ , nu_  ] := 
Module [
{ r , t , s , b , res },
(
r = q[[ 1 ]] ;
t = q[[ 2 ]] ;

s = r^{4 / nu} ;
b = ( 4 / nu ) t ;

res = Append[  s , b ] ;
res
) 
] ;

(* The h map - the double reflection of type 1 *)
hFunc1[ x_ , y_ ] :=
Module [
{ res  } ,
(
res = { 1 - x , -y } ;
res
)
] ;

(* The h map - the double reflection of type 2 *)
hFunc2[ x_ , y_ ] :=
Module [
{ res  } ,
(
res = { Sqrt[2] - x , -y } ;
res
)
] ;

(* Map a point from a p-domain to another p-domain - type 1 - upper . *)
fromPDomain2PDomain1U[ p_ , nu_ , i_ , nv_ , j_ ] := 
Module [
{ r , t , s , b , x , y , res },
(
(* Compute the polar coordinates of the given point. *)
{ r , t } = fromCartesian2Polar[ p ] ;

(* Apply a rotation of (Pi (i+1) / nu) degrees to the point. *) 
 t =  t - ( ( Pi ( i + 1 ) )/ nu ) ;

(* Map the point to the canonical domain *)
{ r , t } = fromPDomain2Canonical[ { r , t } , nu ] ;

(* Apply a rotation of ( Pi / 4 ) degrees to the point. *) 
 t =  t + ( Pi / 4 ) ;

(* Compute the Cartesian coordinates of the point. *)
{ x , y } = fromPolar2Cartesian[ { r , t } ] ;

(* Apply a rotation of 180 degrees and center (0.5,0) to ( x , y ). *)
{ x , y } = hFunc1[ x , y ] ;

(* Compute the polar coordinates of the given point. *)
{ s , b } = fromCartesian2Polar[ { x , y } ] ;

(* Apply a rotation of ( Pi / 4 ) degrees to the point. *) 
 b =  b + ( Pi / 4 ) ;

(* Map the point to the target p-domain. *)
{ s , b } = fromCanonical2PDomain[ { s , b } , nv ] ;

(* Apply a rotation of ( Pi (j-1) / nv) degrees to the point. *)
b = b + ( ( Pi ( j - 1 ) ) / nv ) ;

(* Compute the Cartesian coordinates of the point. *)
{ x , y } = fromPolar2Cartesian[ { s , b } ] ;

res = { x  ,y  } ;
res
) 
] ;

N[fromPDomain2PDomain1U[ {-1.5874 , 0},3 , 2 , 6 , 4 ]]

(* Map a point from a p-domain to another p-domain - type 1 - lower . *)
fromPDomain2PDomain1L[ p_ , nu_ , i_ , nv_ , j_ ] := 
Module [
{ r , t , s , b , x , y , res },
(
(* Compute the polar coordinates of the given point. *)
{ r , t } = fromCartesian2Polar[ p ] ;

(* Apply a rotation of (Pi (i+1) / nu) degrees to the point. *) 
 t =  t - ( ( Pi ( i - 1 ) )/ nu ) ;

(* Map the point to the canonical domain *)
{ r , t } = fromPDomain2Canonical[ { r , t } , nu ] ;

(* Apply a rotation of ( Pi / 4 ) degrees to the point. *) 
 t =  t - ( Pi / 4 ) ;

(* Compute the Cartesian coordinates of the point. *)
{ x , y } = fromPolar2Cartesian[ { r , t } ] ;

(* Apply a rotation of 180 degrees and center (0.5,0) to ( x , y ). *)
{ x , y } = hFunc1[ x , y ] ;

(* Compute the polar coordinates of the given point. *)
{ s , b } = fromCartesian2Polar[ { x , y } ] ;

(* Apply a rotation of ( Pi / 4 ) degrees to the point. *) 
 b =  b - ( Pi / 4 ) ;

(* Map the point to the target p-domain. *)
{ s , b } = fromCanonical2PDomain[ { s , b } , nv ] ;

(* Apply a rotation of ( Pi (j-1) / nv) degrees to the point. *)
b = b + ( ( Pi ( j + 1 ) ) / nv ) ;

(* Compute the Cartesian coordinates of the point. *)
{ x , y } = fromPolar2Cartesian[ { s , b } ] ;

res = { x  ,y  } ;
res
) 
] ;

N[fromPDomain2PDomain1L[ {0.5 , 0.866025},6 , 4 , 3 , 2 ]]

(* Map a point from a p-domain to another p-domain - type 2. *)
fromPDomain2PDomain2[ p_ , nu_ , i_ , nv_ , j_ ] := 
Module [
{ r , t , s , b , x , y , res },
(
(* Compute the polar coordinates of the given point. *)
{ r , t } = fromCartesian2Polar[ p ] ;

(* Apply a rotation of (Pi (i+1) / nu) degrees to the point. *) 
 t =  t - ( ( Pi i  )/ nu ) ;

(* Map the point to the canonical domain *)
{ r , t } = fromPDomain2Canonical[ { r , t } , nu ] ;

(* Compute the Cartesian coordinates of the point. *)
{ x , y } = fromPolar2Cartesian[ { r , t } ] ;

(* Apply a rotation of 180 degrees and center (0.5,0) to ( x , y ). *)
{ x , y } = hFunc2[ x , y ] ;

(* Compute the polar coordinates of the given point. *)
{ s , b } = fromCartesian2Polar[ { x , y } ] ;

(* Map the point to the target p-domain. *)
{ s , b } = fromCanonical2PDomain[ { s , b } , nv ] ;

(* Apply a rotation of ( Pi (j-1) / nv) degrees to the point. *)
b = b + ( ( Pi j ) / nv ) ;

(* Compute the Cartesian coordinates of the point. *)
{ x , y } = fromPolar2Cartesian[ { s , b } ] ;

res = { x  ,y  } ;
res
) 
] ;

N[fromPDomain2PDomain2[ {-1.5874010519681996, 0},3 , 3 , 4 , 1 ]]

N[ Sqrt[2]^{4/3}]

(* Testing the cocycle condition - Assume that the common *)
(* quadrilateral is given by the vertices [v , u , w, t ] *)
(* in counterclockwise order.                             *)

(* Transition function from Omega_{vu} to Omega_{uv} *)
phiUV[ x_ , y_ ] :=
Module[
{ u , v , res } ,
(
{ u , v } = fromPDomain2PDomain1U[ { x , y } , 3 , 2 , 6 , 4 ] ;

res = { u , v } ;
res
)
] ;

(* Transition function from Omega_{vt} to Omega_{tv} *)
phiTV[ x_ , y_ ] :=
Module[
{ u , v , res } ,
(
{ u , v } = fromPDomain2PDomain1L[ { x , y } , 3 , 4 , 5 , 6 ] ;

res = { u , v } ;
res
)
] ;

(* Transition function from Omega_{vw} to Omega_{wv} *)
phiWV[ x_ , y_ ] :=
Module[
{ u , v , res } ,
(
{ u , v } = fromPDomain2PDomain2[ { x , y } , 3 , 3 , 4 , 1 ] ;

res = { u  , v } ;
res
)
] ;

(* Transition function from Omega_{uv} to Omega_{vu} *)
phiVU[ x_ , y_ ] :=
Module[
{ u , v , res } ,
(
{ u , v } = fromPDomain2PDomain1L[ { x , y } , 6 , 4 , 3 , 2 ] ;

res = { u  , v } ;
res
)
] ;

(* Transition function from Omega_{uw} to Omega_{wu} *)
phiWU[ x_ , y_ ] :=
Module[
{ u , v , res } ,
(
{ u , v } = fromPDomain2PDomain1U[ { x , y } , 6 , 2 , 4 , 2 ] ;

res = { u  , v } ;
res
)
] ;

(* Transition function from Omega_{ut} to Omega_{tu} *)
phiTU[ x_ , y_ ] :=
Module[
{ u , v , res } ,
(
{ u , v } = fromPDomain2PDomain2[ { x , y } , 6 , 3 , 5 , 7 ] ;

res = { u  , v } ;
res
)
] ;

(* Transition function from Omega_{wt} to Omega_{tw} *)
phiTW[ x_ , y_ ] :=
Module[
{ u , v , res } ,
(
{ u , v } = fromPDomain2PDomain1U[ { x , y } , 4 , 0 , 5 , 8 ] ;

res = { u  , v } ;
res
)
] ;

(* Transition function from Omega_{wu} to Omega_{uw} *)
phiUW[ x_ , y_ ] :=
Module[
{ u , v , res } ,
(
{ u , v } = fromPDomain2PDomain1L[ { x , y } , 4 , 2 , 6 , 2 ] ;

res = { u  , v } ;
res
)
] ;

(* Transition function from Omega_{wv} to Omega_{vw} *)
phiVW[ x_ , y_ ] :=
Module[
{ u , v , res } ,
(
{ u , v } = fromPDomain2PDomain2[ { x , y } , 4 , 1 , 3 , 3 ] ;

res = { u  , v } ;
res
)
] ;

(* Transition function from Omega_{tv} to Omega_{vt} *)
phiVT[ x_ , y_ ] :=
Module[
{ u , v , res } ,
(
{ u , v } = fromPDomain2PDomain1U[ { x , y } , 5 , 6 , 3 , 4 ] ;

res = { u  , v } ;
res
)
] ;

(* Transition function from Omega_{tw} to Omega_{wt} *)
phiWT[ x_ , y_ ] :=
Module[
{ u , v , res } ,
(
{ u , v } = fromPDomain2PDomain1U[ { x , y } , 5 , 8 , 4 , 0 ] ;

res = { u  , v } ;
res
)
] ;

(* Transition function from Omega_{tu} to Omega_{ut} *)
phiUT[ x_ , y_ ] :=
Module[
{ u , v , res } ,
(
{ u , v } = fromPDomain2PDomain2[ { x , y } , 5 , 7 , 6 , 3 ] ;

res = { u  , v } ;
res
)
] ;

(* Testing the cocycle condition - refer to Slide 37 of Lecture 14 *)

{ x1 , y1 } = phiTW[ 0.5 , 0.5 ]

{ x2 , y2 } = phiUW[ 0.5 , 0.5 ]

{ x3 , y3 } = phiTU[ x2 , y2 ]

{ x4 , y4 } = phiVW[ 0.5 , 0.5 ]

{ x5 , y5 } = phiTV[ x4 , y4 ]