Disegnare archi su una sfera e marcare i punti

  • Creatore
    Topic
  • #98180
    Up
    0
    Down
    ::


    Salve, ho un problema con l’utilizzo del pacchetto tikz e in particolare con il pacchetto tikz-3dplots. Il mio obiettivo è quello di disegnare una sfera con evidenziati alcuni punti, meridiani, paralleli e archi che collegano i diversi punti sulla sfera.
    Inizialmente ero partito da questo esempio Example: Spherical and cartesian grids, ma ho scoperto che ci sono alcuni bug nella nuova versione di tikz che non consentono di ottenere lo stesso risultato che si vede nell’esempio compilando il codice fornito.
    Quindi ho provato a utilizzare il pacchetto 3dplots e in questo modo sono riuscito a disegnare la sfera, i meridiani, i paralleli, il sistema di riferimento, ma non riesco a marcare i punti sulla sfera o a tracciare archi tra due punti che non stanno esattamente su un meridiano o un parallelo. Cercando sul web ho trovato questa discussione che fa al caso mio How can I draw an arc from point A -> B on a 3D sphere in TikZ?, ma putroppo combinando con 3dplots il codice del thread non riesco più a trovare alcuna corrispondenza sugli angoli di ciascun punto.
    Ciò che vorrei ottenere è una cosa del genere

    con in più gli archi che mettono in evidenza ad esempio l’angolo POQ.
    Quindi chiedo a voi se esiste un modo rapido di inserire i punti sulla sfera e di tracciare archi fra più punti sulla sfera e archi che indicano l’angolo tra due rette generiche.
    Grazie in anticipo.
    Inserisco qui il codice di ciò che ho realizzato finora e l’immagine ottenuta. Come potete vedere per ora l’arco rosso che non sta né su un meridiano né su un parallelo sono andato per tentativi (dopo mille tentativi) ruotando il sistema di riferimento e disegnando sul nuovo piano xy un arco di circonferenza specificato, ma è davvero impensabile fare sempre così

    `\documentclass{article}
    \usepackage{tikz}
    \usepackage{tikz-3dplot}

    \begin{document}

    %Angle Definitions
    %—————–

    %set the plot display orientation
    %synatax: \tdplotsetdisplay{\theta_d}{\phi_d}
    \tdplotsetmaincoords{65}{110}

    \pgfmathsetmacro{\rvec}{1.2}

    %DEFINISCO SECONDO PUNTO DEL TRIANGOLO
    \pgfmathsetmacro{\thetavecc}{55}
    \pgfmathsetmacro{\phivecc}{35}

    %DEFINISCO TERZO PUNTO DEL TRIANGOLO
    \pgfmathsetmacro{\thetaveccc}{39.7}
    \pgfmathsetmacro{\phiveccc}{55}

    \begin{tikzpicture}[scale=5,tdplot_main_coords]

    \shadedraw[tdplot_screen_coords,ball color = white] (0,0) circle (\rvec);

    %———————–
    \coordinate (O) at (0,0,0);

    \tdplotsetcoord{B}{\rvec}{\thetavecc}{\phivecc}

    \tdplotsetcoord{C}{\rvec}{\thetaveccc}{\phiveccc}

    %draw the main coordinate system axes
    \draw[thick,->] (0,0,0) — (1.7,0,0) node[anchor=north east]{$x$};
    \draw[thick,->] (0,0,0) — (0,1.7,0) node[anchor=north west]{$y$};
    \draw[thick,->] (0,0,0) — (0,0,1.7) node[anchor=south]{$z$};

    %%DISEGNA VETTORE DA O AD B
    \draw[-stealth,very thick,color=blue] (O) — (B);
    %
    %DISEGNA VETTORE DA O AD C
    \draw[-stealth,very thick,color=green!60!black] (O) — (C);

    %DISEGNA LE PROIEZIONI DI B
    \draw[dashed, color=blue] (O) — (Bxy);
    \draw[dashed, color=blue] (B) — (Bxy);

    %DISEGNA LE PROIEZIONI DI C
    \draw[dashed, color=green!60!black] (O) — (Cxy);
    \draw[dashed, color=green!60!black] (C) — (Cxy);

    \tdplotdrawarc{(O)}{0.3}{0}{\phivecc}{anchor=north}{$\lambda_A$}

    \tdplotsetthetaplanecoords{\phivecc}

    \tdplotdrawarc{(0,0,0)}{0.3}{90}{\thetavecc}{anchor=south west}{$\varphi_A$}

    \tdplotdrawarc{(O)}{0.7}{0}{\phiveccc}{anchor=north}{$\lambda_B$}

    \tdplotsetthetaplanecoords{\phiveccc}

    \tdplotdrawarc{(0,0,0)}{0.7}{90}{\thetaveccc}{anchor=south west}{$\varphi_B$}

    \draw[dashed] (\rvec,0,0) arc (0:360:\rvec);
    \draw[thick] (\rvec,0,0) arc (0:110:\rvec);
    \draw[thick] (\rvec,0,0) arc (0:-70:\rvec);

    \tdplotsetthetaplanecoords{35}
    \draw[thick,tdplot_rotated_coords] (\rvec,0,0) arc (0:151:\rvec);
    \draw[very thick,color=red,tdplot_rotated_coords] (\rvec,0,0) arc (0:55:\rvec);
    \draw[dashed,tdplot_rotated_coords] (\rvec,0,0) arc (180:-40:-\rvec);
    \draw[thick,tdplot_rotated_coords] (\rvec,0,0) arc (360:336:\rvec);

    \tdplotsetthetaplanecoords{55}
    \draw[thick,tdplot_rotated_coords] (\rvec,0,0) arc (0:147:\rvec);
    \draw[very thick,color=red,tdplot_rotated_coords] (\rvec,0,0) arc (0:40:\rvec);
    \draw[dashed,tdplot_rotated_coords] (\rvec,0,0) arc (180:-40:-\rvec);
    \draw[thick,tdplot_rotated_coords] (\rvec,0,0) arc (360:334:\rvec);

    \tdplotsetrotatedcoords{-79.1}{-120}{27.3}
    \draw[very thick,color=red,tdplot_rotated_coords] (\rvec,0,0) arc (0:21:\rvec);

    \end{tikzpicture}

    \end{document}

    `


Visualizzazione 18 filoni di risposte
  • Autore
    Risposte
    • #98181
      Up
      0
      Down
      ::

      Squall” post=97676Quindi chiedo a voi se esiste un modo rapido di inserire i punti sulla sfera e di tracciare archi fra più punti sulla sfera e archi che indicano l’angolo tra due rette generiche.

      Per questo tipo di disegni, secondo me si può usare TikZ solo in un caso: si hanno eccellenti doti matematiche e si conosce già come sfruttarle con TikZ.

      Quindi, no: non esiste un metodo rapido.

      Ciao
      Claudio

    • #98182
      Up
      0
      Down
      ::


      Ok, grazie lo stesso.
      Cercando meglio ho trovato il pacchetto ps 3dplot che mi risulta un po’ più intuitivo nel mio caso in quanto definisce cerchi ed ellissi con il centro e il piano nel quale sono contenuti, quindi il problema si sposta sul trovare le coordinate dei vettori che definiscono il piano, ma questo è un problema di geometria che si risolve.

    • #98183
      Liverpool
      Partecipante
        Up
        0
        Down
        ::


        Bene, ma la prossima volta, se posti un codice così tecnico e così lungo, per favore spiega cosa fa ogni singola riga. Sinceramente ho iniziato a guardarlo ma mi sono arreso perché avrei perso troppo tempo a cercare di interpretarlo.
        Quello che dici sulla normale al piano è vero, ma sono curioso di sapere come affronterai il problema del tratteggio per le parti di arco in secondo piano.
        Cosa intendi per “inserire i punti sulla sfera”? Vuoi dire disegnare il pallino? Puoi usare l’istruzione [tt]circle[/tt] di TikZ (ovviamente se usi pst-3dplot questo suggerimento non ti serve più).

        Ciao

      • #98184
        Up
        0
        Down
        ::


        Ok, mi scuso per non aver commentato il codice, la prossima volta provvederò a farlo. Il tratteggio per le parti di arco in secondo piano lo posso fare bene disegnando due archi di ellisse di cui uno tratteggiato e l’altro con linea continua (si può definire l’angolo di inizio e di fine dell’ellisse).
        Per inserire i punti sulla sfera si, intendo disegnare il pallino e inserire la lettera. Conoscete una funzione analoga a circle di TikZ?
        Grazie

      • #98185
        Up
        0
        Down
        ::

        Squall” post=97704Per inserire i punti sulla sfera si, intendo disegnare il pallino e inserire la lettera. Conoscete una funzione analoga a circle di TikZ?

        L’istruzione [tt]circle[/tt] è di TikZ: `\draw[radius=2pt](0,0)circle ;`

        Ciao
        Claudio

      • #98186
        Up
        0
        Down
        ::


        Scusate per le domande forse stupide, so di conoscere poco latex.
        Quindi posso usare la funzione circle anche dentro una pspicture caricando anche il pacchetto TikZ? Altrimenti come potrei fare?

      • #98187
        Up
        0
        Down
        ::

        Squall” post=97706Quindi posso usare la funzione circle anche dentro una pspicture caricando anche il pacchetto TikZ? Altrimenti come potrei fare?

        Abbi pazienza: mi ero perso il passaggio dove dicevi di passare a pst-3dplot.

        In realtà non è consigliabile mescolare TikZ e PSTricks: naturalmente anche PSTricks mette a disposizione comandi per disegnare cerchi (pscircle molto probabilmente). Ovviamente è altamente consigliabile leggere la documentazione relativa ai pacchetti che stai utilizzando 😉

        Ciao
        Claudio

      • #98188
        robitex
        Amministratore del forum
          Up
          0
          Down
          ::


          Forse potrebbe esserci una soluzione alternativa: asymptote http://asymptote.sourceforge.net/ :
          si tratta di un programma per la grafica vettoriale programmata che forse è più adatto per il 3d, e che si integra bene con LaTeX.
          Da qualche anno è compreso in TeX Live.

          Per esempio:
          http://asymptote.sourceforge.net/gallery/near_earth.pdf
          R.

        • #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.
          • #98190
            OldClaudio
            Partecipante
              Up
              0
              Down
              ::


              Wow! Scusate l’esclamazione molto anglo, ma non me ne viene una migliore.:smile:

              Bravo, bravissimo.

              Visto che l’appetito vie mangiando, saresti anche capace di disegnare una lossodromia fra due punti dati?

              Geometricamente parlando la lossodromia è il percorso sulla sfere che unisce due punti mantenendo un angolo costante rispetto ai meridiani che via via interseca; è chiaro che la lossodromia che unisce due punti sull’equatore è l’arco minore di equatore che li unisce; è altrettanto chiaro che la lossodromia che unisce due punti sullo stesso meridiano è l’arco minore di meridiano che li unisce.

              Non è altrettanto evidente che la lossodromia che unisce due punti collocati diversamente dalle due situazioni descritte sopra è un arco di spirale giacente sulla sfera che va avvolgendosi attorno ai due poli: si srotola dal polo S e poi sale avvolgendosi attorno al polo N (o viceversa). Un costruzione geometrica semplice può essere visualizzata pensando al cilindro tangente alla sfera lungo l’equatore; un’elica a pendenza costante sul cilindro si proietta su una lossodromia sulla sfera; infatti le generatrici del cilindro si proiettano sui meridiani e l’elica che ha pendenza costante sulla superficie cilindrica forma un angolo costante con le generatrici del cilindro. la proiezione centrale della superficie cilindrica sulla superficie sferica è conforme, per cui gli angoli si conservano ed ecco che la proiezione dell’elica è una linea che forma angoli costanti con i meridiani, cioè una lossodromia.

              Spiegazione superflua per Liverpool che lo sa certamente, ma se qualche altro lettore non conoscesse la lossodromia, quella è la spiegazione.

              Sempre per chi non lo sapesse, la lossodromia è il percorso che si fa in nave o in aereo mantenendo una rotta costante, il che è comodo per il timoniere o per il pilota, ma non è il percorso più breve, che è costituito dal percorso ortodromico più difficile da seguire perché bisogna cambiare continuamente rotta; è ovvio che oggi con gli strumenti moderni basati sul GPS, il problema non sussiste più, ma per chi pratica la nautica e usa il timone a mano il problema si pone sui viaggi piuttosto lunghi. Il povero Cristoforo Colombo non conosceva queste cose e sia all’andata sia al ritorno ha seguito rotte ben lontane dall’essere ottimali. La proiezione di Mercatore di un paio di secoli successiva ai viaggi di C.C. ha facilitato molto la determinazione della rotta lossodromica, ma per seguire le rotte ortodromiche c’è voluto il trasporto aereo a lunga distanza.

            • #98191
              Liverpool
              Partecipante
                Up
                0
                Down
                ::

                OldClaudio” post=98957Visto che l’appetito vie mangiando, saresti anche capace di disegnare una lossodromia fra due punti dati?

                Grazie Claudio, la lossodromia credo sia un po’ più fastidiosa e forse è un lavoro più adatto a pgfplots. Ci penserò.

                Per venire incontro alle richieste dell’OP, ho aggiunto un pic [tt]coordinata[/tt] che si usa in questo modo:
                `\pic [posizione={latitudine}{longitudine}, raggio=1] {coordinata=P};`
                Il pic genera un nodo di tipo coordinata di nome P nella posizione assegnata. Anche in questo caso il raggio è facoltativo. La coordinata così generata può essere successivamente utilizzata nel disegno, ad esempio per marcare dei punti o aggiungere delle etichette. L’utilità consiste nella trasformazione automatica delle coordinate geografiche in coordinate cartesiane.

                Ho aggiornato l’intervento precedente con le modifiche al codice. Faccio notare che, per disegnare un pallino nel sistema di riferimento della tela bisogna specificare l’unità di misura del raggio, altrimenti il pallino viene disegnato sul piano [xy].

              • #98192
                OldClaudio
                Partecipante
                  Up
                  0
                  Down
                  ::


                  Disegnando anche i paralleli, cosa che ritengo utilissima, il disegno risulta un po’ confuso se si vedono le linee sul retro della sfera; lo so che è difficile, ma si possono elininare gli archi posteriori di meridiani e paralleli?

                  Il codice è bellissimo e il risultato anche, sebbene l’eliminazione degli archi posteriori lo renderebbe ancora più bello.

                  Complimenti, davvero.

                • #98193
                  Liverpool
                  Partecipante
                    Up
                    0
                    Down
                    ::

                    OldClaudio” post=98972Disegnando anche i paralleli, cosa che ritengo utilissima, il disegno risulta un po’ confuso se si vedono le linee sul retro della sfera; lo so che è difficile, ma si possono elininare gli archi posteriori di meridiani e paralleli?

                    Tratteggiare o nascondere le parti visibili non è banale, soprattutto se si vuole realizzare una soluzione che vada bene con qualunque sistema di riferimento (leggi proiezione). In tal caso, magari per pigrizia, credo che la soluzione più semplice sia appoggiarsi all’opzione [tt]surf[/tt] di pgfplots per disegnare la sfera. Lo svantaggio è che gli archi saranno solo approssimati sul reticolo.
                    `\documentclass

                    {standalone}
                    \usepackage{pgfplots}
                    \pgfplotsset{compat=1.11}

                    % 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}{}
                    }
                    }

                    \begin{document}
                    \begin{tikzpicture}
                    \begin{axis} [x={(\xx,\xy)}, y={(\yx,\yy)}, z={(\zx,\zy)},
                    anchor=origin, at={(0,0)}, disabledatascaling, hide axis]
                    % disegna la sfera con i meridiani e paralleli
                    \addplot3 [surf, z buffer=sort, fill opacity=0.6, white, faceted color=blue!40, very thin,
                    samples=19, samples y=37, variable=\u, variable y=\v,
                    domain=0:180, y domain=0:360]
                    ({cos(u)*sin(v)}, {sin(u)*sin(v)}, {cos(v)});
                    % disegna l'arco
                    \pic [partenza={30}{-50}, arrivo={30}{90}, red] {ortodromia};
                    \pic [posizione={30}{-50}] {coordinata=A};
                    \pic [posizione={30}{90}] {coordinata=B};
                    \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{axis}
                    \end{tikzpicture}
                    \end{document}`

                    [attachment=1234]ortodromia1.png[/attachment]

                    Attachments:
                    You must be logged in to view attached files.
                  • #98194
                    OldClaudio
                    Partecipante
                      Up
                      0
                      Down
                      ::


                      Gli archi saranno solo approssimati, ma il tutto è una meraviglia.

                      Bravo, bravissimo.

                    • #98195
                      Liverpool
                      Partecipante
                        Up
                        0
                        Down
                        ::

                        OldClaudio” post=98957Visto che l’appetito vie mangiando, saresti anche capace di disegnare una lossodromia fra due punti dati?

                        Forse siamo un po’ OT e per questo chiedo scusa a @Squall. Questo regalo è tutto per @OldClaudio.
                        Allo stesso modo dell’ortodromia ho definito un pic [tt]lossodromia[/tt] che genera la curva lossodromica tra due punti assegnati sulla sfera. Il codice usa solo i comandi di TikZ, ma per disegnare la sfera mi sono appoggiato a pgfplots, che non è necessario. Il pic utilizza l’istruzione [tt]plot[/tt] di TikZ con i valori di default (25 campioni), ma è possibile passare al comando le opzioni [tt]smooth[/tt], [tt]hobby[/tt] oppure [tt]samples=[/tt] per migliorare le caratteristiche del tratto. Non l’ho fatto a priori per non appesantire il risultato quando non è necessario. La curva sembra funzionare correttamente. Forse le formule si potrebbero semplificare un po’ ma per il momento va bene così.
                        Il cuore è il comando:
                        `\pic [partenza={latitudine A}{longitudine A}, arrivo={latitudine B}{longitudine B}] {lossodromia};`
                        nel quale, come di consueto, la latitudine 0 corrisponde al piano [xy] e la longitudine 0 al semipiano [xz] di ascisse positive. Non è possibile scegliere come punto di partenza o di arrivo uno dei due poli, ma è possibile prendere un punto di latitudine molto vicina (ad esempio 89.98°). Non è nemmeno possibile prendere due punti sullo stesso meridiano, ma in tal caso la lossodromia coincide con l’ortodromia e si può usare quel codice. Volendo si può pensare di affinare il codice per includere questi casi particolari.
                        Anche qui è possibile utilizzare la chiave [tt]raggio[/tt] che è un alias per la chiave [tt]scale[/tt] e accetta solo numeri adimensionali che vengono interpretati come fattore di scala della lunghezza del versore dell’asse delle ascisse.
                        `\documentclass

                        {standalone}
                        \usepackage{pgfplots}
                        \pgfplotsset{compat=1.11}

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

                        \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}},
                        declare function={
                        s(\x) = ln( (1+tan(\x/2)) / (1-tan(\x/2))) );
                        lat(\x) = 2*atan( tanh( (\m*(\x-\lonA) + s(\latA))/2) ) );
                        },
                        lossodromia/.pic={
                        % riferimento http://homepages-fb.thm.de/boergens/marken/marke062/marke062_loxo.pdf
                        \pgfmathsetmacro{\latA}{\pgfkeysvalueof{/tikz/latA}}
                        \pgfmathsetmacro{\lonA}{\pgfkeysvalueof{/tikz/lonA}}
                        \pgfmathsetmacro{\latB}{\pgfkeysvalueof{/tikz/latB}}
                        \pgfmathsetmacro{\lonB}{\pgfkeysvalueof{/tikz/lonB}}
                        \pgfmathsetmacro{\m}{(s(\latB)-s(\latA)) / (\lonB-\lonA)}
                        \draw [variable=\t, domain=\lonA:\lonB, pic actions]
                        plot (
                        {abs(\t)!=90 ? cos(\t)*cos(lat(\t)) : 0},
                        {abs(\t)!=90 ? sin(\t)*cos(lat(\t)) : 0},
                        {abs(\t)!=90 ? sin(lat(\t)) : sin(\t)});
                        },
                        coordinata/.pic={
                        \pgftransformshift{
                        \pgfpointspherical{90-\pgfkeysvalueof{/tikz/lonA}}{\pgfkeysvalueof{/tikz/latA}}{1}
                        }
                        \pgfnode{coordinate}{center}{}{#1}{}
                        }
                        }

                        \begin{document}
                        \begin{tikzpicture}
                        \begin{axis} [x={(\xx,\xy)}, y={(\yx,\yy)}, z={(\zx,\zy)}, hide axis]
                        % disegna i meridiani e i paralleli
                        \addplot3 [surf, z buffer=sort, fill opacity=0.6, white, faceted color=blue!40,
                        samples=19, samples y=37, variable=\u, variable y=\v,
                        domain=0:180, y domain=0:360]
                        ({cos(u)*sin(v)}, {sin(u)*sin(v)}, {cos(v)});
                        % disegna il contorno della sfera
                        \draw [blue!40] (0,0,0) circle ({2cm/cos(atan(1/sqrt(2)))});
                        % disegna la lossodromia
                        \pic [partenza={-10}{20}, arrivo={89.98}{360}, smooth, samples=50, red] {lossodromia};
                        % definisce le coordinate dei punti di partenza e arrivo
                        \pic [posizione={-10}{20}, x={(\xx,\xy)}, y={(\yx,\yy)}, z={(\zx,\zy)}] {coordinata=A};
                        \pic [posizione={89.98}{360}, x={(\xx,\xy)}, y={(\yx,\yy)}, z={(\zx,\zy)}] {coordinata=B};
                        % traccia i pallini in corrispondenza degli estremi della curva
                        \fill (A) circle (1pt)
                        (B) circle (1pt);
                        % disegna gli assi coordinati
                        \draw [-latex] (1,0,0) — (1.5,0,0);
                        \draw [-latex] (0,1,0) — (0,1.5,0);
                        \draw [-latex] (0,0,1) — (0,0,1.5);
                        \end{axis}
                        \end{tikzpicture}
                        \end{document}`

                        [attachment]C:\fakepath\lossodromia.png[/attachment]

                        Il codice, come anche quello dell’ortodromia, al momento presenta un bug: quando usato all’interno dell’ambiente [tt]axis[/tt] di pgfplots per disegnare la sfera passando come opzioni i versori degli assi coordinati, i pallini (e nel caso dell’ortodromia la curva), potrebbero essere tracciati fuori asse per alcune combinazioni di assi coordinati. Il problema nasce dal fatto che il sistema di riferimento viene specificato due volte: una per l’ambiente [tt]axis[/tt] e l’altra per i pic. Se qualcuno mi aiuta a risolverlo, gli sono grato.

                        Ciao

                      • #98196
                        Liverpool
                        Partecipante
                          Up
                          0
                          Down
                          ::

                          OldClaudio” post=98957Visto che l’appetito vie mangiando, saresti anche capace di disegnare una lossodromia fra due punti dati?

                          Forse siamo un po’ OT e per questo chiedo scusa a @Squall. Questo regalo è tutto per @OldClaudio.
                          Allo stesso modo dell’ortodromia ho definito un pic [tt]lossodromia[/tt] che genera la curva lossodromica tra due punti assegnati sulla sfera. Il codice usa solo i comandi di TikZ, ma per disegnare la sfera mi sono appoggiato a pgfplots, che non è necessario. Il pic utilizza l’istruzione [tt]plot[/tt] di TikZ con i valori di default (25 campioni), ma è possibile passare al comando le opzioni [tt]smooth[/tt], [tt]hobby[/tt] oppure [tt]samples=[/tt] per migliorare le caratteristiche del tratto. Non l’ho fatto a priori per non appesantire il risultato quando non è necessario.
                          Il cuore è il comando:
                          `\pic [partenza={latitudine A}{longitudine A}, arrivo={latitudine B}{longitudine B}] {lossodromia};`
                          nel quale, come di consueto, la latitudine 0 corrisponde al piano [xy] e la longitudine 0 al semipiano [xz] di ascisse positive. La latitudine va da -90 al polo sud a 90 al polo nord; la longitudine va da -180 (ovest) a 180 (est). Non è possibile scegliere come punto di partenza o di arrivo uno dei due poli, ma è possibile prendere un punto di latitudine molto vicina (ad esempio 89.99°). Non è nemmeno possibile prendere due punti sullo stesso meridiano, ma in tal caso la lossodromia coincide con l’ortodromia e si può usare quel codice. Volendo si può pensare di affinare il codice per includere questi casi particolari.
                          Anche qui è possibile utilizzare la chiave [tt]raggio[/tt] che è un alias per la chiave [tt]scale[/tt] e accetta solo numeri adimensionali che vengono interpretati come fattore di scala della lunghezza del versore dell’asse delle ascisse.
                          Se le coordinate vengono inserite correttamente, il codice disegna il più breve tra tutti i tratti possibili. In alternativa, si può usare l’opzione [tt]demo[/tt]: in tal caso il codice disegna la curva che passa per i due punti e per tutti i punti di longitudine intermedia. Per fare un esempio: se la longitudine del punto di partenza è -178 e quella del punto di arrivo è 178, di default il codice disegna la curva che si estende su soli 4° di longitudine, mentre con l’opzione [tt]demo[/tt] disegna la curva che si estende su 356° di longitudine, passando per il meridiano di Greenwich.

                          `\documentclass

                          {standalone}
                          \usepackage{pgfplots}
                          \pgfplotsset{compat=1.11}

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

                          \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}},
                          /lossodromia/esteso/.initial=1,
                          demo/.code={\tikzset{/lossodromia/esteso=0}},
                          declare function={
                          s(\x) = ln( (sin(\x)+1)/cos(\x) );
                          S(\x) = \m*(\x-\lonA) + s(\latA);
                          % s e S sono due espressioni della stessa funzione
                          },
                          lossodromia/.pic={
                          % riferimento http://homepages-fb.thm.de/boergens/marken/marke062/marke062_loxo.pdf
                          \pgfmathsetmacro{\latA}{\pgfkeysvalueof{/tikz/latA}}
                          \pgfmathsetmacro{\lonA}{\pgfkeysvalueof{/tikz/lonA}}
                          \pgfmathsetmacro{\latB}{\pgfkeysvalueof{/tikz/latB}}
                          \pgfmathsetmacro{\lonB}{\pgfkeysvalueof{/tikz/lonB}}
                          \pgfmathparse{\lonB-\lonA>180 && \pgfkeysvalueof{/lossodromia/esteso}==1 ? 360 : 0}
                          \pgfmathsetmacro{\lonB}{\lonB – \pgfmathresult}
                          \pgfmathparse{\lonA-\lonB>180 && \pgfkeysvalueof{/lossodromia/esteso}==1 ? 360 : 0}
                          \pgfmathsetmacro{\lonA}{\lonA – \pgfmathresult}
                          \pgfmathsetmacro{\m}{(s(\latB)-s(\latA)) / (\lonB-\lonA)}
                          \draw [variable=\t, domain=\lonA:\lonB, pic actions]
                          plot ({cos(\t)/cosh(S(\t))}, {sin(\t)/cosh(S(\t))}, {tanh(S(\t))});
                          },
                          coordinata/.pic={
                          \pgftransformshift{
                          \pgfpointspherical{90-\pgfkeysvalueof{/tikz/lonA}}{\pgfkeysvalueof{/tikz/latA}}{1}
                          }
                          \pgfnode{coordinate}{center}{}{#1}{}
                          }
                          }

                          \begin{document}
                          \begin{tikzpicture}
                          \begin{axis} [x={(\xx,\xy)}, y={(\yx,\yy)}, z={(\zx,\zy)},
                          anchor=origin, at={(0,0)}, disabledatascaling, hide axis]
                          % disegna i meridiani e i paralleli
                          \addplot3 [surf, z buffer=sort, fill opacity=0.6, white, faceted color=blue!40,
                          samples=19, samples y=37, variable=\u, variable y=\v,
                          domain=0:180, y domain=0:360]
                          ({cos(u)*sin(v)}, {sin(u)*sin(v)}, {cos(v)});
                          % disegna il contorno della sfera
                          \draw [blue!40] (0,0,0) circle ({2cm*sqrt(3/2)});
                          % disegna la lossodromia
                          \pic [partenza={-10}{20}, arrivo={89.99}{360}, smooth, samples=50, demo, red] {lossodromia};
                          % definisce le coordinate dei punti di partenza e arrivo
                          \pic [posizione={-10}{20}] {coordinata=A};
                          \pic [posizione={89.99}{360}] {coordinata=B};
                          % traccia i pallini in corrispondenza degli estremi della curva
                          \fill (A) circle (1pt)
                          (B) circle (1pt);
                          % disegna gli assi coordinati
                          \draw [-latex] (1,0,0) — (1.5,0,0);
                          \draw [-latex] (0,1,0) — (0,1.5,0);
                          \draw [-latex] (0,0,1) — (0,0,1.5);
                          \end{axis}
                          \end{tikzpicture}
                          \end{document}`

                          [attachment=1239]lossodromia.jpg[/attachment]

                          Il codice, come anche quello dell’ortodromia, al momento presenta un bug: quando usato all’interno dell’ambiente [tt]axis[/tt] di pgfplots per disegnare la sfera passando come opzioni i versori degli assi coordinati, i pallini (e nel caso dell’ortodromia la curva) potrebbero essere tracciati fuori asse per alcune combinazioni di assi coordinati. Il problema nasce dal fatto che il sistema di riferimento viene specificato due volte: una per l’ambiente [tt]axis[/tt] e l’altra per i pic. Se qualcuno mi aiuta a risolverlo, gli sono grato.

                          Ciao

                          Edit: bug risolto con la chiave [tt]disabledatascaling[/tt]. Ho aggiornato conseguentemente il codice.

                          Attachments:
                          You must be logged in to view attached files.
                        • #98197
                          OldClaudio
                          Partecipante
                            Up
                            0
                            Down
                            ::


                            Un regalo bellissimo!
                            Veramente bello; ammiro la tua pazienza nello studiarti il problema e la tua bravura nell’usare pgf sia nella versione tikz sia nella versione pgfplots.
                            Da parte mia ci ho pensato tanto, ma non sono arrivato mai a niente; sono dotato in matematica, ma non abbastanza; già, ricordo che l’esame di geometria proiettiva non è stato uno dei miei migliori; nemmeno uno dei peggiori, ma non all’altezza di altre parti della matematica superiore che studiavamo ad ingegneria ai miei tempi

                            Faccio tesoro del tuo codice, e se qualcuno aggiusta il piccolo baco che ancora resta, tanto meglio.

                            Un articoletto per ArsTeXnica 19…? 😉
                            La scadenza è il 31 gennaio; il kit per gli autori si scarica dal link

                            https://github.com/GuITeX/atkit/archive/v2.2.1.zip

                            Grazie mille
                            Claudio

                          • #98198
                            Liverpool
                            Partecipante
                              Up
                              0
                              Down
                              ::

                              OldClaudio” post=99081Faccio tesoro del tuo codice, e se qualcuno aggiusta il piccolo baco che ancora resta, tanto meglio.

                              Problema risolto con la chiave [tt]disabledatascaling[/tt]. Ho aggiornato entrambi i codici e ho semplificato la formula che dà la latitudine del cursore in funzione della longitudine, passando alle funzioni iperboliche. Ovviamente è possibile ricavare anche la longitudine in funzione della latitudine, ma dal punto di vista grafico servono più campioni per avere una curvatura dolce (perché l’elica si arrotola intorno ai poli ed è preferibile avere più nodi equidistanti in longitudine piuttosto che in latitudine), perciò ho scelto questa versione.

                            • #98199
                              OldClaudio
                              Partecipante
                                Up
                                0
                                Down
                                ::


                                Grazie anche della correzione che elimina il piccolo baco che era ancor nel codice precedente.

                                Aspetto l’articolo 😉

                                Ancora Grazie mille
                                Claudio

                            Visualizzazione 18 filoni di risposte
                            • Devi essere connesso per rispondere a questo topic.

                            Go to top