Geodeettiset leikkaukset & LiveGraphics3D
Veikko Keränen, Helmikuu 2006

SetDirectory["D:\M\
aanmittauksenMatematiikkaa\LiveGraphics3D"]

Off[General::spell]
Off[General::spell1]

Kaarileikkaus

Kuvion tilanteessa määritettävän pisteen laskennassa lähdetään liikkeelle ratkaisemalla lähtösivun suuntakulma ja pituus geodeettisella käänteistehtävällä.
Tätä ei kuitenkaan implementoida vielä tässä kokeilussa.

Seuraavassa on kaarileikkausta koskeva esimerkki interaktiivisen LiveGraphics3D -ohjelman käytöstä ja tarvittavan koodin kirjoittamisesta Mathematicalla.

LiveGraphics3D on ei-kaupallinen Java 1.1 appletti, jonka on kirjoittanut Martin Kraus. 
Tämän hetken uusin versio on peräisin lokakuulta 2005.

Muista aktivoida Java nettiselaimen options-valikossa, ennen kuin käytät tuotettuja nettisivuja.

Clear[x1, y1, x2, y2, s1p, s2p, xp, yp];
ratkaistavanPisteenPxyKoordinaatit = 
      Solve[{(((xp - x1))^2) + (((yp - y1))^2) == 
            (s1p^2), (((xp - x2))^2) + (((yp - y2))^2) == 
            (s2p^2)}, {xp, yp}]

Edellinen tulos näyttää melkoisen mutkikkaalta, joten koitetaan sieventää sitä

ratkaistavanPisteenPxyKoordinaatit = 
      ratkaistavanPisteenPxyKoordinaatit // Simplify

Ensimmäinen ratkaisu:

ratkaistavanPisteenPxyKoordinaatit[[1]]

Toinen ratkaisu:

ratkaistavanPisteenPxyKoordinaatit[[2]]

ratkP1 = {xp, yp}  /.  
        ratkaistavanPisteenPxyKoordinaatit[[1]]

ratkP2 = {xp, yp}  /.  
        ratkaistavanPisteenPxyKoordinaatit[[2]]

\(\(\( (*\(\(\ \)\(ALLA\ OLEVA\ TEKSTIN\ \((\(Text\)\([\)\(\(StyleForm\)\([\)\("P1", \  ... \)\)\)\)\()\)\)\ KÄYTTÖÄ\ KOSKEVA\ KOKEILU\ EI\ TUOTTANUT\ TOIVOTTUA\ TULOSTA, \ 
JOTEN\ TEKSTIN\ KÄYTÖSTÄ\ TÄYTYI\ \(\(LUOPUA\)\(.\)\)\ *) \)\(
\)\(
\)\( (*\ 
independentVariables = {x1 -> 2. , y1 -> 8. , x2 -> \(-3. \), y2 -> 10. , 
          s1p -> \ 10, 
          s2p -> 
            12}; 

dependentVariables = {depP1x -> ratkP1[\([1]\)], depP1y -> ratkP1[\([2]\)], 
          depP2x -> ratkP2[\([1]\)], 
          depP2y -> ratkP2[\([2]\)]}; 

myGraph = 
        Graphics3D[{{RGBColor[1, 0, 0], Thickness[0.02], 
              Line[{{x1, y1, 0}, {x2, y2, 
                    0}}]}, 
PointSize[ .04], 
            Point[{x1, y1, 0}], Point[{x2, y2, 0}], PointSize[0.03], 
            Point[{depP1x, depP1y, 0}], Point[{depP2x, depP2y, 0}], 
            Line[Table[{x1, y1, 0} + s1p*{Cos[phi], Sin[phi], 0}, {phi, 0. , 
                  2\ Pi + 0.00001, 2\ Pi/64. }]], 
            Line[Table[{x2, y2, 0} + s2p*{Cos[phi], Sin[phi], 0}, {phi, 0. , 
                  2\ Pi + 0.00001, 2\ Pi/64. }]], 
Text[
              StyleForm["P1", FontFamily -> "Courier", 
                FontSize -> 12, FontWeight -> "Bold"], {x1, 
                y1 - 1, 0}], 
Text[
              StyleForm["P2", FontFamily -> "Courier", 
                FontSize -> 12, FontWeight -> "Bold"], {x2, 
                y2 - 1, 0}]}, Boxed -> False, 
          ViewPoint -> {0, 0, 4}, ViewVertical -> {0, 1, 0}, 
          PlotRange -> {{\(-10\), 10}, {\(-10\), 20}, {\(-1\), 
                1}}]; 


      Show[myGraph //. 
          Join[independentVariables, 
            dependentVariables]];\ *) \)\)\)

Clear[x1, y1, x2, y2, s1p, s2p, xp, yp];
(etaisyydet€s1P€s2P = 
          Solve[{(((xp - x1))^2) + (((yp - y1))^2) == 
                (s1p^2), (((xp - x2))^2) + (((yp - y2))^2) == 
                (s2p^2)}, {s1p, s2p}]) // InputForm

etaisyydet€s1P€s2P[[4]] // InputForm

ratkP1[[1]] /. { x1 -> 5. , y1 -> 8. , 
        x2 -> -3. , y2 -> 10. , s1p ->  10, 
        s2p -> 12}
ratkP1[[2]] /. { x1 -> 5. , y1 -> 8. , 
        x2 -> -3. , y2 -> 10. , s1p ->  10, 
        s2p -> 12}

independentVariables = {x1 -> 5. , y1 -> 8. , 
          x2 -> -3. , y2 -> 10. , s1p ->  10, 
          s2p -> 12, depP1x -> 1.1886966994857475`, 
          depP1y -> -1.2452132020570061`};

    
\(\(\(dependentVariables = {s1p -> 
            Sqrt[x1^2 - 2*x1*depP1x + depP1x^2 + y1^2 - 2*y1*depP1y + 
                depP1y^2], 
          s2p -> 
            Sqrt[x2^2 - 2*x2*depP1x + depP1x^2 + y2^2 - 2*y2*depP1y + 
                depP1y^2], 
depP1x -> ratkP1[\([1]\)], 
          depP1y -> ratkP1[\([2]\)], depP2x -> ratkP2[\([1]\)], 
          depP2y -> ratkP2[\([2]\)]};\)\(
\)
    \)\)
\(\(\(myGraph = 
        Graphics3D[{{RGBColor[1, 0, 1], Thickness[0.01], 
              Line[{{x1, y1, 0}, {x2, y2, 0}}]}, 
{RGBColor[
                0, 0, 1], Thickness[0.008], 
              Line[{{x1, y1, 0}, {depP1x, depP1y, 
                    0}}]}, 
{RGBColor[ .5,  .5,  .5], 
              Thickness[0.005], 
              Line[{{x1, y1, 0}, {depP2x, depP2y, 
                    0}}]}, 
{RGBColor[0, 0, 1], 
              Thickness[0.008], 
              Line[{{x2, y2, 0}, {depP1x, depP1y, 
                    0}}]}, 
{RGBColor[ .5,  .5,  .5], 
              Thickness[0.005], 
              Line[{{x2, y2, 0}, {depP2x, depP2y, 
                    0}}]}, 
{PointSize[ .04], 
              RGBColor[1, 0, 0], Point[{x1, y1, 0}]}, {PointSize[ .04], 
              RGBColor[1, 0, 0], Point[{x2, y2, 0}]}, {PointSize[0.03], 
              RGBColor[0, 0, 1], 
              Point[{depP1x, depP1y, 0}]}, {PointSize[0.03], 
              RGBColor[ .5,  .5,  .5], Point[{depP2x, depP2y, 0}]}, 
            Line[Table[{x1, y1, 0} + s1p*{Cos[phi], Sin[phi], 0}, {phi, 0. , 
                  2\ Pi + 0.00001, 2\ Pi/64. }]], 
            Line[Table[{x2, y2, 0} + s2p*{Cos[phi], Sin[phi], 0}, {phi, 0. , 
                  2\ Pi + 0.00001, 2\ Pi/64. }]]}, Boxed -> False, 
          ViewPoint -> {0, 0, 4}, ViewVertical -> {0, 1, 0}, 
          PlotRange -> {{\(-10\), 15}, {\(-5\), 25}, {\(-1\), 
                1}}];\)\(
\)
    \)\)
Show[
        myGraph //. 
          Join[independentVariables, dependentVariables]];

SetDirectory["D:\M\
aanmittauksenMatematiikkaa\LiveGraphics3D"]

Tarkistetaan vielä, että hakemisto/talletus -polku on varmasti oikein:

Directory[]

Näitä hakemistopolkuja ei nyt käytetä kuitenkaan, koska InputForm -muotoiset tekstit täytyy (kokeilujen perusteella) kopioida suoraan html-sivuille.

myGraph // InputForm

ratkP1[[1]] // InputForm

ratkP1[[2]] // InputForm

ratkP2[[1]] // InputForm

ratkP2[[2]] // InputForm

LiveForm ja WriteLiveForm mahdollista myöhäisempää käyttöä varten

LiveForm[graphics_, animOpts___] := 
        Module[{graphics3d = 
              Switch[graphics, _ContourGraphics, 
                  Graphics3D[SurfaceGraphics[graphics]], _DensityGraphics, 
                  Graphics3D[SurfaceGraphics[graphics]], _SurfaceGraphics, 
                  Graphics3D[graphics], _, graphics] //. 
                SequenceForm[x___] :> 
                  StringForm[StringJoin[Table["``", {Length[{x}]}]], x]}, 
          Switch[graphics3d, _List, HoldForm[ShowAnimation][
              Map[LiveForm, graphics3d], 
              InputForm[N[Flatten[{animOpts}]]]], _, 
            InputForm[N[graphics3d]]]];

WriteLiveForm[filename_, graphics_, animOpts___] := 
        Module[{ps, x}, ps = Unprotect[Real]; 
          Format[x_Real, InputForm] := 
            OutputForm[
              NumberForm[x, 5, 
                NumberFormat -> (If[#3 == "", #1, 
                        SequenceForm[#1, "*^", #3]] &)]]; 
          Protect @@ ps; 
WriteString[filename, 
            ToString[LiveForm[graphics, animOpts], 
              CharacterEncoding -> None]]; 
          Close[filename]; 
ps = Unprotect[Real]; 
          Format[x_Real, InputForm] =. ; Protect @@ ps;];

LiveForm[myGraph]

Ajatus erillisen .m -tiedoston tekemisestä ei näytä toimivan, joten nettisivu tulee ilmeisesti rakentaa aina erikseen Mathematican InputForm -muotoisista symbolisista lausekkeista:

WriteLiveForm["kaarileikkaus.m", myGraph, independentVariables, 
      dependentVariables]

Geodeettisen käänteistehtävän funktioita

Clear[
        geodeettinenKäänteistehtäväKulmaGon];
geodeettinenKäänteistehtäväKulmaGon[{x1_, y1_}, {x2_, y2_}] :=  ((200/π))*
            ArcTan[x2 - x1, y2 - y1] // N;

{x1, y1} = {2, 8};
{x2, y2} = {-3, -10};
t12PositTaiNegat = 
      geodeettinenKäänteistehtäväKulmaGon[{x1, y1}, {x2, y2}]

Clear[positiivinenKulmaGon];
positiivinenKulmaGon[t_] := 
      t  /;  t ≥  
          0;       
positiivinenKulmaGon[t_] := 
      t  +  400;

t12  =  positiivinenKulmaGon[t12PositTaiNegat]

Clear[
        geodeettinenKäänteistehtäväPituus];
geodeettinenKäänteistehtäväPituus[{x1_, y1_}, {x2_, 
          y2_}] := (Sqrt[(((x2 - x1))^2) + (((y2 - y1))^2)]) // N

s12 = 
      geodeettinenKäänteistehtäväPituus[{x1, y1}, {x2, y2}]

Seuraavaksi ratkaistaan lähtöpisteen 1 kulma a1 kosinilauseella:

		 \(TraditionalForm\`α\_1 = 
        arccos(\(s\_12\^2\  + \ \((s\_\(1  p\))\)\^2\  - \ \((s\_\(2  p\))\)\^2\)\/\(2  s\_12\ *\ \ s\_\(1  p\)\))\)

Clear[kosinilause];
kosinilause[s12_, s1p_, 
          s2p_] := ((200/π))*
            ArcCos[(((s12^2) + (s1p^2) - (s2p^2))/(2  s12*s1p))] // 
          N;
kosinilause[{x1_, y1_}, {x2_, y2_}, s1p_, 
        s2p_] := ((200/π))*
          ArcCos[(((((geodeettinenKäänteistehtäväPituus[{x1, y1}, {x2, y2}]))^2) + (s1p^2) - (s2p^2))/(2  geodeettinenKäänteistehtäväPituus[{x1, y1}, {x2, y2}]*s1p))] // N

s1p = 10;
s2p = 12;
α1 = kosinilause[s12, s1p, s2p]

Suuntakulma lähtöpisteeltä 1 määritettävälle pisteelle P on nyt (Subscript[t, 1  p]) = (Subscript[t, 12]) + (Subscript[α, 1])

Clear[summaKulmaGon ];
summaKulmaGon [t_, α_] := 
        t + α  /;  
          t + α   <  400;
summaKulmaGon [t_, α_] := t + α  - 400;

t1p  =  summaKulmaGon[t12, α1]

summaKulmaGon[250, 250]

Geodeettinen päätehtävä:

{x1, y1} = {2, 8};
{x1, y1}  +  {s1p*Cos[t1p*π/200], 
        s1p*Sin[t1p*π/200]}

{x1 + s1p*Cos[t1p*π/200], y1 + s1p*Sin[t1p*π/200]}

Tarkistetaan laskelmat vielä lopuksi kaarileikkauksen nimen mukaisesti. Ratkaistaan siis etäisyyksiä (säteitä) vastaavien kaarien (ympyröiden) leikkauspisteet:

Clear[kaarileikkaus];
kaarileikkaus[{x1_, y1_}, {x2_, y2_}, s1p_, s2p_] := 
        NSolve[{(((xp - x1))^2) + (((yp - y1))^2) == 
              (s1p^2), (((xp - x2))^2) + (((yp - y2))^2) == 
              (s2p^2)}, {xp, yp}];

kaarileikkaus[{2, 8}, {-3, -10}, 10, 12]