Re: Disegnare archi su una sfera e marcare i punti

#98189
Liverpool
Partecipante
    Up
    0
    Down
    ::


    Riapro questa vecchia conversazione perché, approfittando delle festività, ho messo su una bozza di soluzione. Se non ricordo male il problema di tracciare l’arco di cerchio massimo tra due punti di una sfera era già stato sollevato come curiosità da @OldClaudio, perciò rispondo qui in una sola volta.
    La soluzione sembra funzionare correttamente, ma non ci metterei le mani sul fuoco perché mi sembra “troppo semplice”, perciò se qualcuno fosse interessato a dargli un’occhiata, farebbe cosa gradita alla comunità.
    Il cuore del codice è il pic [tt]ortodromia[/tt] che richiede almeno due opzioni: [tt]partenza[/tt] per le coordinate del punto di partenza e [tt]arrivo[/tt] per le coordinate del punto di arrivo. Le coordinate vanno espresse in gradi nella forma [tt]={latitudine}{longitudine}[/tt]. La latitudine 0 corrisponde al piano [xy], la longitudine 0 al semipiano [xz] di ascisse positive. Va da se che i punti non possono essere antipodali oppure coincidenti, altrimenti il problema è indeterminato. Una terza chiave facoltativa, [tt]raggio[/tt], permette di variare il raggio della sfera e deve essere espressa come multiplo dell’unità di misura (credo dell’asse x), cioè come numero adimensionale. Inoltre l’opzione [tt]opposto[/tt] permette di tracciare l’arco più lungo dello stesso cerchio massimo tra i due punti. Infine è possibile passare ulteriori opzioni di tracciatura relative al colore o al tipo di linea.

    Il codice non richiede alcuna libreria opzionale e può essere riassunto in questi passi:
    1) trasformazione delle coordinate geografiche in coordinate cartesiane per i due punti che indichiamo con A e B
    2) determinazione del vettore OP complanare con OA e OB e ortogonale a OA
    3) determinazione del versore OC parallelo ed equiverso ad OP
    4) tracciatura dell’arco sul piano cartesiano avente gli assi coordinati paralleli a OA e OC (l’asse z è ininfluente perché l’arco è sempre tracciato sul piano [xy]).

    Se qualcuno trova degli errori oppure vuole semplicemente migliorare il codice, è il benvenuto.

    P.S.: se si conoscono due punti non degeneri dello stesso cerchio, si può comunque costruire una semicirconferenza o una circonferenza spezzandola in due archi contigui.

    `\documentclass{standalone}
    \usepackage{tikz}

    % componenti dei versori degli assi coordinati
    % rispetto alla base della tela
    \pgfmathsetlengthmacro{\xx}{-1cm*sqrt(3)/2}
    \pgfmathsetlengthmacro{\xy}{-0.5cm}
    \pgfmathsetlengthmacro{\yx}{1cm*sqrt(3)/2}
    \pgfmathsetlengthmacro{\yy}{-0.5cm}
    \pgfmathsetlengthmacro{\zx}{0cm}
    \pgfmathsetlengthmacro{\zy}{1cm}

    \tikzset{
    latA/.initial=0,
    lonA/.initial=0,
    latB/.initial=0,
    lonB/.initial=0,
    partenza/.style 2 args={latA=#1, lonA=#2},
    arrivo/.style 2 args={latB=#1, lonB=#2},
    posizione/.style 2 args={latA=#1, lonA=#2},
    raggio/.initial=1,
    raggio/.code={\tikzset{/tikz/scale=#1}},
    lungo/.initial=0,
    opposto/.code={\tikzset{/tikz/lungo=1}},
    ortodromia/.pic={
    % conversione delle coordinate geografiche in cartesiane
    \pgfmathsetmacro{\Ax}{cos(\pgfkeysvalueof{/tikz/latA})*cos(\pgfkeysvalueof{/tikz/lonA})}
    \pgfmathsetmacro{\Ay}{cos(\pgfkeysvalueof{/tikz/latA})*sin(\pgfkeysvalueof{/tikz/lonA})}
    \pgfmathsetmacro{\Az}{sin(\pgfkeysvalueof{/tikz/latA})}
    \pgfmathsetmacro{\Bx}{cos(\pgfkeysvalueof{/tikz/latB})*cos(\pgfkeysvalueof{/tikz/lonB})}
    \pgfmathsetmacro{\By}{cos(\pgfkeysvalueof{/tikz/latB})*sin(\pgfkeysvalueof{/tikz/lonB})}
    \pgfmathsetmacro{\Bz}{sin(\pgfkeysvalueof{/tikz/latB})}
    % prodotto scalare (OA\cdot OB)
    \pgfmathsetmacro{\ps}{\Ax*\Bx + \Ay*\By + \Az*\Bz}
    % vettore OP complanare con OA e OB e ortogonale al primo
    \pgfmathsetmacro{\Px}{-\Ax*\ps + \Bx}
    \pgfmathsetmacro{\Py}{-\Ay*\ps + \By}
    \pgfmathsetmacro{\Pz}{-\Az*\ps + \Bz}
    % versore CP parallelo a OP
    \pgfmathsetmacro{\Cx}{\Px/sqrt((\Px)^2 + (\Py)^2 + (\Pz)^2)}
    \pgfmathsetmacro{\Cy}{\Py/sqrt((\Px)^2 + (\Py)^2 + (\Pz)^2)}
    \pgfmathsetmacro{\Cz}{\Pz/sqrt((\Px)^2 + (\Py)^2 + (\Pz)^2)}
    % angolo tra i due vettori OA e OB
    \pgfmathsetmacro{\angolo}{acos(\ps)-360*\pgfkeysvalueof{/tikz/lungo}}
    \draw [x={(\Ax*\xx+\Ay*\yx+\Az*\zx, \Ax*\xy+\Ay*\yy+\Az*\zy)},
    y={(\Cx*\xx+\Cy*\yx+\Cz*\zx, \Cx*\xy+\Cy*\yy+\Cz*\zy)}, pic actions]
    (1,0,0) arc (0:\angolo:1);
    },
    coordinata/.pic={
    \pgftransformshift{
    \pgfpointspherical{90-\pgfkeysvalueof{/tikz/lonA}}{\pgfkeysvalueof{/tikz/latA}}{1}
    }
    \pgfnode{coordinate}{center}{}{#1}{}
    }
    }

    % stile usato per le linee dei meridiani e paralleli
    \tikzset{griglia/.style={blue!40, very thin}}

    \begin{document}
    \begin{tikzpicture} [x={(\xx,\xy)}, y={(\yx,\yy)}, z={(\zx,\zy)}]
    % disegna i meridiani e i paralleli
    \foreach \i in {0,10,…,170}{
    \pic [partenza={0}{\i}, arrivo={90}{\i}, griglia] {ortodromia};
    \pic [partenza={0}{\i}, arrivo={90}{\i}, opposto, griglia] {ortodromia};
    }
    \foreach \i in {-80,-70,…,80}
    \draw [griglia] (0,0,{sin(\i)}) circle ({cos(\i)});
    % disegna l'arco
    \pic [partenza={30}{-50}, arrivo={30}{90}, red] {ortodromia};
    \pic [posizione={30}{-50}] {coordinata=A};
    \pic [posizione={30}{90}] {coordinata=B};
    % marca i due punti
    \fill (A) circle (0.8pt)
    (B) circle (0.8pt);
    % assi coordinati
    \draw [-latex] (1,0,0) — (2,0,0);
    \draw [-latex] (0,1,0) — (0,2,0);
    \draw [-latex] (0,0,1) — (0,0,2);
    \end{tikzpicture}
    \end{document}`

    [attachment=1225]prova3_2014-12-29.png[/attachment]

    Attachments:
    You must be logged in to view attached files.

    Go to top