
BeginPackage["CReflector`"]

DelkaUsecky::usage=""

(* -------------------- *)


NastavDelkuUsecky::usage=""
NajdiPrusecikQu::usage=""
CUhelUsecekQu::usage=""
PrusecikUsecekQu::usage=""
MyMin::usage=""
VzdalenostBoduNT::usage=""
StredUsecky::usage=""
ProvedRotaciATranslaci::usage=""

(* -------------------------------------------------------------------------------- *)

NajdiPrusecikEx::usage=""
NajdiBodOdrazuEx::usage=""
NajdiBodLomuEx::usage=""
SledujPaprsekEx::usage=""
NakresliKonfiguraciEx::usage=""
GenerujObycejnyHranol::usage=""
GenerujXHranol::usage=""
GenerujDoubleXHranol::usage=""
Trojuhelnik::usage=""
ZalityTrojuhelnik::usage=""
ZalityTrojuhelnik2::usage=""

Begin["Private`"];



ClearAll[DelkaUsecky];
DelkaUsecky = Compile[{{A,_Real,1}, {B,_Real,1}},
              Sqrt[Power[B[[2]]-A[[2]],2]+Power[B[[1]]-A[[1]],2]]];



ClearAll[NastavDelkuUsecky];
NastavDelkuUsecky = Compile[{{A,_Real,1}, {B,_Real,1},delka},
 Module[{v1,v2,d},
    v1=B[[1]]-A[[1]];
    v2=B[[2]]-A[[2]];
    d=Sqrt[v1^2+v2^2];
    {A[[1]]+v1*delka/d,A[[2]]+v2*delka/d}
  ]
];



ClearAll[VzdalenostBoduNT];
VzdalenostBoduNT = Compile[{{A,_Real,1}, {B,_Real,1}},
  {Sqrt[Power[B[[2]] - A[[2]], 2] + Power[B[[1]] - A[[1]], 2]],1.}
];



Clear[CUhelUsecekQu];
CUhelUsecekQu = Compile[{{A, _Real, 1}, {B, _Real, 1},
{C, _Real, 1}, {D, _Real, 1}},
  Module[{a1, b1, a2, b2, delitel},
    a1 = B[[2]] - A[[2]];
    b1 = A[[1]] - B[[1]];
    a2 = D[[2]] - C[[2]];
    b2 = C[[1]] - D[[1]];
    delitel = a1*a2 + b1*b2;
    If[delitel == 0, Return[{Pi/2, 0.}]];
    {ArcTan[Abs[(a1*b2 - a2*b1)/delitel]], 0.}
  ]
];


ClearAll[NajdiBodOdrazuEx];
NajdiBodOdrazuEx=Compile[{{Paprsek,_Real,2},{Zrcadlo,_Real,2}}, Module[{vV,vN,vR},
  vV=Paprsek[[2]]-Paprsek[[1]];
  vN=NastavDelkuUsecky[{0,0},(Zrcadlo[[2]]-Zrcadlo[[1]]).{{0, 1}, {-1, 0}},1.]; (* jednotkovy vektor *)
  vR=vV-2*(vV.vN)*vN;
  {Paprsek[[2]], Paprsek[[2]]+vR, {Paprsek[[3,1]]*Zrcadlo[[3,2]], Paprsek[[3,2]]}}
 ]
];



ClearAll[NajdiBodLomuEx];
NajdiBodLomuEx=Compile[{{Paprsek,_Real,2},{Plocha,_Real,2}, {indexLomu,_Real,1}},
Module[{v,normala,r,n=indexLomu[[1]]/indexLomu[[2]], DetektorTotalnihoOdrazu},

  DetektorTotalnihoOdrazu=n*Sin[Pi/2-CUhelUsecekQu[Paprsek[[1]],Paprsek[[2]], Plocha[[1]],Plocha[[2]]]];

  If [DetektorTotalnihoOdrazu[[1]]>1,
           Return[NajdiBodOdrazuEx[Paprsek, {Plocha[[1]],Plocha[[2]],{1.,1.}}]];]; (* 100 % ucinnost *)

  v=NastavDelkuUsecky[{0,0},Paprsek[[2]]-Paprsek[[1]],1.]; (* jednotkovy vektor *)
  normala=NastavDelkuUsecky[{0,0},(Plocha[[2]]-Plocha[[1]]).{{0, 1}, {-1, 0}},1.]; (*jednotkovy vektor *)
  r=(Sign[normala.v]*Sqrt[1-n^2+(normala.v)^2*n^2]-(normala.v)*n)*normala+n*v;

  {Paprsek[[2]], Paprsek[[2]]+r, {Paprsek[[3,1]],indexLomu[[2]]}}
  ]
];

ClearAll[PrusecikUsecekQu];
PrusecikUsecekQu = Compile[{{A, _Real, 1}, {B, _Real, 1}, {C, _Real, 1}, {D, _Real, 1}},
  Module[{x1, x3, y1, y3, px, py, qx, qy, r, s},
    If[A == B || C == D, Return[{0. }]];
    If[First[CUhelUsecekQu[A, B, C, D]] == 0. , Return[{0. }]];
    x1 = A[[1]]; y1 = A[[2]];
    px = B[[1]] - x1; py = B[[2]] - y1;
    x3 = C[[1]]; y3 = C[[2]];
    qx = D[[1]] - x3; qy = D[[2]] - y3;
    r = - (- qy * x1 + qy * x3 + qx * y1 - qx * y3)/(py * qx - px * qy);
    If[ r <= 0. || r >= 1. , Return[{0. }]];
    s = -(- py * x1 + py * x3 + px * y1 - px * y3)/(py * qx - px * qy);
    If[ s <= 0. || s >= 1. , Return[{0. }]];
    A + r*{px, py}
  ]
];

ClearAll[MyMin];
MyMin[param_, ignorujSegment_]:=Module[{minVal},
  minVal=Null;
  minPos=Null;
  For[i=1,i<=Length[param],
    If[i!=ignorujSegment,
    If[TrueQ[param[[i]]==Null],
      Null,
      If[TrueQ[minVal<param[[i]]],
        Null,
        minPos=i;
        minVal=param[[i]];
      ];
    ];
    ];
  i++];
  minPos
];

ClearAll[NajdiPrusecikEx];
NajdiPrusecikEx[Paprsek_, PoleZrcadlovychSegmentu_, ignorujSegment_] :=
  Module[ {pruseciky,vzdalenosti, prusecik, ProdlouzenyPaprsek},
   ProdlouzenyPaprsek=NastavDelkuUsecky[Paprsek[[1]], Paprsek[[2]], 100];
   pruseciky=Table[PrusecikUsecekQu[Paprsek[[1]], ProdlouzenyPaprsek,
     PoleZrcadlovychSegmentu[[i, 1]], PoleZrcadlovychSegmentu[[i, 2]]]
     ,{i,1,Length[PoleZrcadlovychSegmentu]}];
  vzdalenosti=Table[If[Length[pruseciky[[i]]] == 1,
                        Null,
                        DelkaUsecky[Paprsek[[1]], pruseciky[[i]]]],
{i, 1, Length[pruseciky]}];
  prusecik=MyMin[vzdalenosti, ignorujSegment];
  If[TrueQ[prusecik==Null],
    Return[{0.,{0.,0.}}],
    Return[{prusecik, pruseciky[[prusecik]]}]
    ];
];

ClearAll[NajdiPrusecikQu];
NajdiPrusecikQu=Compile[{{Paprsek,_Real,2},{PoleZrcadlovychSegmentu,_Real,3},
                         {ignorujSegment, _Integer}},
  Module[ {pruseciky,vzdalenosti, prusecik, ProdlouzenyPaprsek, NejlepsiVysledek},
(*    Print["Paprsek=", Paprsek]; *)
   ProdlouzenyPaprsek=NastavDelkuUsecky[Paprsek[[1]], Paprsek[[2]], 20];

   pruseciky=Table[PrusecikUsecekQuX[Paprsek[[1]], ProdlouzenyPaprsek,
      PoleZrcadlovychSegmentu[[i, 1]], PoleZrcadlovychSegmentu[[i, 2]]]
      ,{i,1,Length[PoleZrcadlovychSegmentu]}];

(*    Print["pruseciky=", pruseciky]; *)
   vzdalenosti=Table[If[pruseciky[[i,3]] == 1.,
                      VzdalenostBoduNT[Paprsek[[1]], {pruseciky[[i,1]],pruseciky[[i,2]]}],
                      {0.,0.}
                      ],{i, 1, Length[pruseciky]}];

(*    Print["vzdalenosti=", vzdalenosti]; *)
   prusecik=0;
   NejlepsiVysledek=100000.0;

   For[i=0,i<Length[vzdalenosti],
    If[i!=ignorujSegment,
    If[vzdalenosti[[i]] != {0.,0.},
      If[NejlepsiVysledek>vzdalenosti[[i,1]],
        prusecik=i;NejlepsiVysledek=vzdalenosti[[i,1]];
        ]]],
        i++];

  If[prusecik==0,
  {0.,0.,0.},
  {prusecik,pruseciky[[prusecik,1]],pruseciky[[prusecik,2]]}]
  ]
];

ClearAll[StredUsecky];
StredUsecky = Compile[{{A,_Real,1}, {B,_Real,1}}, .5*(A+B)];



ClearAll[ProvedRotaciATranslaci];
ProvedRotaciATranslaci = Compile[{{A,_Real,1}, {B,_Real,1}, theta},
  Module[{x3, y3},
    x3 = B[[1]] - A[[1]];
    y3 = B[[2]] - A[[2]];
    { x3*Cos[theta] - y3*Sin[theta] + A[[1]],
      x3*Sin[theta] + y3*Cos[theta] + A[[2]] }
  ]
];



ClearAll[SledujPaprsekEx];
SledujPaprsekEx[Paprsek_, PoleOptickychSegmentu_, iterace_, ignorujSegment_]:=Module[{PomX, PomY},
  If[iterace>Global`MaxIterationNumber, Return[{{0.,0.},{0.,0.},{0.,0.}}]];

  PomX=NajdiPrusecikEx[Paprsek, PoleOptickychSegmentu, ignorujSegment];
  If[PomX[[1]]==0.,
      Return[{{0.,0.},{0.,0.},{0.,0.}}]];

  AppendTo[Global`paprskyProGrafiku, {Paprsek[[1]], PomX[[2]]}];
  Switch[PoleOptickychSegmentu[[PomX[[1]],3,1]],

  0., (* paprsek dopadl na terc *)
      Return[{Paprsek[[1]], PomX[[2]], Paprsek[[3]]}];,

  1., (* paprsek dopadl na zrcadlovou plochu *)
      PomY=NajdiBodOdrazuEx[{Paprsek[[1]],PomX[[2]],Paprsek[[3]]},PoleOptickychSegmentu[[PomX[[1]]]]];
      Return[SledujPaprsekEx[PomY, PoleOptickychSegmentu,iterace+1,PomX[[1]]]];
      ,

   2., (* paprsek dopadl na pruhlednou plochu *)
      Module[{indexPaprsku, indexyRozhrani},
      indexPaprsku=Paprsek[[3,2]]; (* Print["indexPaprsku=", indexPaprsku]; *)
      indexyRozhrani=PoleOptickychSegmentu[[PomX[[1]],4]];

      If[indexPaprsku==indexyRozhrani[[1]],
         PomY=NajdiBodLomuEx[{Paprsek[[1]],PomX[[2]],Paprsek[[3]]},
            PoleOptickychSegmentu[[PomX[[1]]]],indexyRozhrani];,
            If[indexPaprsku==indexyRozhrani[[2]],
              PomY=NajdiBodLomuEx[{Paprsek[[1]],PomX[[2]],Paprsek[[3]]},
                PoleOptickychSegmentu[[PomX[[1]]]],{indexyRozhrani[[2]],indexyRozhrani[[1]]}];,
                Print["!!!!!!!!! renonc v indexech lomu !!!!!!!!!!!!!!!!!!!!!!!!"]]];

      Return[SledujPaprsekEx[PomY,PoleOptickychSegmentu,iterace+1,PomX[[1]]]];
      ];
      ,
  _,Module[{},Print["Neznamy typ segmentu"]; Return[{{0.,0.},{0.,0.},{0.,0.}}];]];
];



GenerujObycejnyHranol[{x_, y_, DelkaHranolu_, uhel_, orientace_}] :=
  Module[{b},
    b = Tan[uhel]*DelkaHranolu;
    If[orientace == 1.,
      {{{x, y}, {x + DelkaHranolu, y}, {2., 0.}, {1., 1.52}},
        {{x, y}, {x + DelkaHranolu, y - b}, {2., 0.}, {1., 1.52}},
        {{x + DelkaHranolu, y}, {x + DelkaHranolu, y - b}, {2., 0.}, {1.,
            1.52}}},
      {{{x, y}, {x + DelkaHranolu, y}, {2., 0.}, {1., 1.52}},
        {{x, y - b}, {x + DelkaHranolu, y}, {2., 0.}, {1., 1.52}},
        {{x, y - b}, {x, y}, {2., 0.}, {1., 1.52}}}
      ]
]

GenerujXHranol[{x_, y_, DelkaHranolu_, uhel_}] :=
  Module[{b},
    b = Tan[Abs[uhel]]*DelkaHranolu;
    If[uhel > 0.,
      { {{x, y}, {x + DelkaHranolu, y - b}, {2., 0.}, {1., 1.52}},
        {{x + DelkaHranolu, y}, {x + DelkaHranolu, y - b}, {2., 0.}, {1., 1.52}}},
      { {{x, y - b}, {x + DelkaHranolu, y}, {2., 0.}, {1., 1.52}},
        {{x, y - b}, {x, y}, {2., 0.}, {1., 1.52}}}
      ]
]


GenerujDoubleXHranol[{x_, y_, DelkaHranolu_, TloustkaHranolu_, uhel1_, uhel2_}] :=
 Module[{b,c, Vysledek},
 b = Tan[Abs[uhel1]]*DelkaHranolu;
 c = Tan[Abs[uhel2]]*DelkaHranolu;

 If[uhel1 > 0.,
  If[uhel2 > 0.,
  {
 {{x, y}, {x + DelkaHranolu, y - b}, {2., 0.}, {1., 1.52}},
 {{x + DelkaHranolu, y}, {x + DelkaHranolu, y - b}, {2., 0.}, {1., 1.52}},
 {{x, y+TloustkaHranolu}, {x+DelkaHranolu, y+TloustkaHranolu+c}, {2., 0.}, {1., 1.52}},
 {{x+DelkaHranolu,y+TloustkaHranolu},{x+DelkaHranolu,y+TloustkaHranolu+c}, {2., 0.}, {1., 1.52}}
 },
  {
 {{x, y}, {x + DelkaHranolu, y - b}, {2., 0.}, {1., 1.52}},
 {{x + DelkaHranolu, y}, {x + DelkaHranolu, y - b}, {2., 0.}, {1., 1.52}},
 {{x, y+TloustkaHranolu+c}, {x+DelkaHranolu, y+TloustkaHranolu}, {2., 0.}, {1., 1.52}},
 {{x,y+TloustkaHranolu+c},{x,y+TloustkaHranolu}, {2., 0.}, {1., 1.52}}
 }
  ],
  If[uhel2 > 0.,
 {
 {{x, y - b}, {x + DelkaHranolu, y}, {2., 0.}, {1., 1.52}},
 {{x, y - b}, {x, y}, {2., 0.}, {1., 1.52}},
 {{x, y+TloustkaHranolu}, {x+DelkaHranolu, y+TloustkaHranolu+c}, {2., 0.}, {1., 1.52}},
 {{x+DelkaHranolu,y+TloustkaHranolu},{x+DelkaHranolu,y+TloustkaHranolu+c}, {2., 0.}, {1., 1.52}}
 },
 {
 {{x, y - b}, {x + DelkaHranolu, y}, {2., 0.}, {1., 1.52}},
 {{x, y - b}, {x, y}, {2., 0.}, {1., 1.52}},
 {{x, y+TloustkaHranolu+c}, {x+DelkaHranolu, y+TloustkaHranolu}, {2., 0.}, {1., 1.52}},
 {{x,y+TloustkaHranolu+c},{x,y+TloustkaHranolu}, {2., 0.}, {1., 1.52}}
 }
 ]
 ]
]


(* uhel \in <0,60\Deg> *)

Trojuhelnik[{P_, velikost_, uhel_}]:=Module[{A,B,C},

A=velikost*{Cos[Pi/2+uhel],Sin[Pi/2+uhel]}+P;
B=velikost*{Cos[Pi/2+uhel+2/3Pi],Sin[Pi/2+uhel+2/3Pi]}+P;
C=velikost*{Cos[Pi/2+uhel+4/3Pi],Sin[Pi/2+uhel+4/3Pi]}+P;

{{A,B,{2., 0.}, {1., 1.52}},{B,C,{2., 0.}, {1., 1.52}},{C,A,{2., 0.}, {1., 1.52}}}
]

ZalityTrojuhelnik[{P_, velikost_, uhel_}]:=Module[{A,B,C},

A=velikost*{Cos[Pi/2+uhel],Sin[Pi/2+uhel]}+P;
B=velikost*{Cos[Pi/2+uhel+2/3Pi],Sin[Pi/2+uhel+2/3Pi]}+P;
C=velikost*{Cos[Pi/2+uhel+4/3Pi],Sin[Pi/2+uhel+4/3Pi]}+P;

{{A,B,{2., 0.}, {1.492, 1.52}},{B,C,{2., 0.}, {1.492, 1.52}},{C,A,{2., 0.}, {1.492, 1.52}}}
]

ZalityTrojuhelnik2[{P_, velikost_, uhel_}]:=Module[{A,B,C},

A=velikost*{Cos[Pi/2+uhel],Sin[Pi/2+uhel]}+P;
B=velikost*{Cos[Pi/2+uhel+2/3Pi],Sin[Pi/2+uhel+2/3Pi]}+P;
C=velikost*{Cos[Pi/2+uhel+4/3Pi],Sin[Pi/2+uhel+4/3Pi]}+P;

{{A,B,{2., 0.}, {1.492, 2.4173}},{B,C,{2., 0.}, {1.492, 2.4173}},{C,A,{2., 0.}, {1.492, 2.4173}}}
]


ClearAll[NakresliKonfiguraciEx];
NakresliKonfiguraciEx[PoleOptickychSegmentu_,PolePaprsku_]:=Module[{GR, TR},
  GR=Graphics[Table[
    Switch[PoleOptickychSegmentu[[i,3,1]],
    0.,{Thickness[0.01], Line[{PoleOptickychSegmentu[[i,1]],PoleOptickychSegmentu[[i,2]]}]},
    1.,{Thickness[0.005],Line[{PoleOptickychSegmentu[[i,1]],PoleOptickychSegmentu[[i,2]]}]},
    2.,{Thickness[.005], RGBColor[0, 1, 1],
       Line[{PoleOptickychSegmentu[[i,1]],PoleOptickychSegmentu[[i,2]]}]}],
    {i,1,Length[PoleOptickychSegmentu]}]];

  TR=Graphics[Table[{RGBColor[1, 0, 0],
      Line[{PolePaprsku[[i,1]], PolePaprsku[[i,2]]}]},{i,1,Length[PolePaprsku]}]];

  Show[GR, TR,
      AspectRatio -> Automatic,
      Axes -> Automatic,
      AxesLabel -> {"x", "y"},
      PlotRange->Global`vyrezGrafu,
      DisplayFunction -> $DisplayFunction];
];



End[ ]
EndPackage[ ]

