Calcolo della distanza geodetica tra due punti della superficie terrestre

La TerraDiversi anni fa, quando lavoravo al CNR, insieme a Bruno Fornari, un caro collega ed amico purtroppo scomparso, scrivemmo un programmino di “servizio” che utilizzammo per calcolare matrici di distanze terrestri (geodetiche).
Il programma è veramente semplice, più interessante è capire come si calcola la distanza tra due punti di una superficie sferica. Devo riconoscere che, al momento, ho avuto la sensazione che i miei studi scientifici non fossero serviti a molto, perché non avevo la più pallida idea di come si facesse! (Gli studi dell’OCSE-Pisa dicono il vero…) Per fortuna, i consigli di Bruno, fisico e scienziato di prim’ordine, mi hanno fornito la formula giusta.
Per il nostro scopo, non ci serviva una grande precisione, per cui l’assunto iniziale era che la terra fosse una sfera perfetta (in realtà non lo è, vi rimando ai link sotto per gli approfondimenti).
Dunque, osservando la figura in alto, diciamo che, in base alla trigonometria sferica (teorema di Eulero), tra i lati a, b e p del triangolo sferico ABP vale la relazione:

cos p = cos a cos b + sen a sen b cos φ

Ora, dette lat(A), lon(A), lat(B), lon(B), la latitudine e la longitudine dei punti A e B e, considerato che:

  • a = 90° – lat(B)
  • b = 90° – lat(A)
  • φ = lon(A)lon(B)

abbiamo tutti i dati per calcolare la lunghezza del lato p considerando il raggio della Terra approssimabile a R = 6371 km.

Ecco dunque il codice in linguaggio ANSI C:

dis_geod.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include 
/* Questa funzione calcola la distanza tra due punti 
sulla superficie terrestre, date le coordinate in
latitudine e longitudine espresse in
gradi decimali */
double disgeod (double latA, double lonA,
                double latB, double lonB)
{
      /* Definisce le costanti e le variabili */
      const double R = 6371;
      const double pigreco = 3.1415927;
      double lat_alfa, lat_beta;
      double lon_alfa, lon_beta;
      double fi;
      double p, d;
      /* Converte i gradi in radianti */
      lat_alfa = pigreco * latA / 180;
      lat_beta = pigreco * latB / 180;
      lon_alfa = pigreco * lonA / 180;
      lon_beta = pigreco * lonB / 180;
      /* Calcola l'angolo compreso fi */
      fi = fabs(lon_alfa - lon_beta);
      /* Calcola il terzo lato del triangolo sferico */
	  p = acos(sin(lat_beta) * sin(lat_alfa) + 
        cos(lat_beta) * cos(lat_alfa) * cos(fi));
      /* Calcola la distanza sulla superficie 
      terrestre R = ~6371 km */
      d = p * R;
      return(d);
}

Ed ecco il codice per il programma di interfaccia utente:

prodisge.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include 
#include "dis_geod.h"
double disgeod(double latA, double lonA, 
              double latB, double lonB);
void main (void)
{
	float latA, lonA, latB, lonB, distanza;
	printf("\n Inserisci la latitudine del punto A :\t");
	scanf ("%f", &latA);
	printf("\n Inserisci la longitudine del punto A :\t");
	scanf ("%f", &lonA);
	printf("\n Inserisci la latitudine del punto B :\t");
	scanf ("%f", &latB);
	printf("\n Inserisci la longitudine del punto B :\t");
	scanf ("%f", &lonB);
	distanza =  disgeod(latA, lonA, latB, lonB);
	printf("\n La distanza fra A e B e' : %f  km\n", distanza);
}

Ed ecco infine il risultato del calcolo della distanza fra Roma (lat: +41.91;, lon: +12.45) e Milano (lat: +45.48 lon: +09.18)

output del programma disgeod

Se provate il calcolo con altri programmi, potrete avere risultati un poco differenti, questo è dovuto alle approssimazioni usate per il raggio della Terra, per il valore di Π e per la conversione dei gradi sessagesimali in decimali.
Ovviamente, al programma originale fu aggiunto il codice necessario per costruire le matrici di distanze, che qui, per brevità, ho tagliato.

Download: (compilato per win32) prodisge.exe

Conclusioni:

Ormai, che i GPS ci parlano amichevolmente in auto, e Google Earth ci da tutte le informazioni che vogliamo con pochi click, programmini del genere sembrano della preistoria. Ma, a furia di avere sempre la “pappa pronta”, non ci annichiliremo un po’ troppo le meningi? Trovo che ogni tanto sarebbe bene fare qualche ripasso, tanto per capire anche come funziona ciò che si utilizza passivamente!

Riferimenti ed approfondimenti:

Librerie javascript Open-jACOB Draw2D: un tool per visual web applications?

esempio fatto con Open-jACOB Draw2DEro alla ricerca di qualche strumento web di tipo ajax-javascript che permettesse interattivamente di creare delle forme grafiche, di assegnargli delle proprietà, di ancorarle ad una griglia e ottenere un parsing xml del risultato, ed ho trovato Open-jACOB Draw2D.
Mi ha affascinato subito ed ora vi spiego il perché.
Per prima cosa, si tratta di un SDK composto da librerie javascript con licenza LGPL, nate dalle famose “DHTML graphics” del tedesco Walter Zorn.
Il lavoro di Andreas Herz, tedesco anche lui, è stato di implementare caratteristiche per la creazione di diagrammi di flusso e progettazione di circuiti elettrici, ma soprattutto di fornire allo strumento una maggiore flessibilità ed interattività (come p.e.: la gestione dei livelli di undo).
In realtà, queste librerie fanno anche parte di un progetto più complesso che si chiama Open-jACOB e ne costituiscono la componente grafica interattiva.
La cosa più accattivante secondo il mio punto di vista, è che il risultato è un prodotto compatibile con qualsiasi browser, senza alcun bisogno di plugin aggiuntivi perché tutta la grafica è gestita attraverso il DOM con dei DIV.
Niente SVG o CANVAS, semplicemente DIV opportunemente elaborati!
Qualcuno potrebbe obiettare che in questo modo la gestione delle forme vettoriali, a parte le linee e i rettangoli, risulta molto complessa e lenta ma lo scopo di questo strumento, come conferma l’autore, non è tanto quello della grafica vettoriale, piuttosto quello di un editor di diagrammi di flusso.
Invece, scavando un poco nel codice, e dalle demo on-line, io ci ho visto un interessante tool per lo sviluppo di applicazioni web interattive e “visual”. Vale a dire, combinando adeguatamente queste librerie javascript con del codice server-side, si potrebbe creare un framework RAD e WYSIWYG per lo sviluppo, totalmente Open source.
Questo tipo di framework, sia per la complessità, che per il tempo impiegato allo sviluppo, sono normalmente appannaggio di grosse ditte e le licenze sono invitabilmente di tipo commerciale.

Esempio pratico

Se la cosa incuriosice anche voi, qui potete provare una piccola demo delle potenzialità di Open-jACOB Draw2D con particolare riferimento allo sviluppo di applicazioni “visual”.
Ho ottenuto questa demo semplicemente abbinando alcune caratteristiche base dei veri esempi forniti dall’autore.

Conclusioni:

Complimenti ad Andreas Herz, davvero un bel lavoro! Credo proprio che continuerò a seguire questo progetto!

Riferimenti ed approfondimenti:

P4A framework: esempio di applicazione completa per la gestione delle fatture

Screenshot dell'applicazioneL’idea di realizzare questo esempio di applicazione in P4A è nata per comparare i tempi di sviluppo in un ambiente RAD di tipo WYSIWYG (MS Visual Basic) che genera desktop applications e un framework PHP che genera web applications. Dei vantaggi delle applicazioni web ho già scritto in un precedente articolo.
Il progetto è molto semplice: un programma che gestisce la fatturazione di una ditta che fa servizi, quindi senza magazzino.
Ho scelto questo progetto perché la realizzazione non presenta grosse difficoltà e può essere utile a qualcuno, ed anche perché ci sono dentro diversi aspetti che ricorrono anche in applicazioni più grandi, come ad esempio la gestione di tabelle master-detail e lo sviluppo di un report personalizzato in pdf.
Inoltre lo schema del database è pressoché identico a quello di un tutorial per l’approccio ai dati con Visual Basic .Net 2005 (Visual Basic 2005 passo-passo: Accesso ai dati),
in questo modo sarà più facile effettuare il confronto.
Va detto che non ho ancora realizzato l’equivalente in VB.Net, ma avendo una certa esperienza di VB6 posso dire quanto tempo avrei impiegato a realizzarlo: diciamo 2 giorni al massimo. Ebbene, considerando che la documentazione di P4A è piuttosto scarsa, che il framework non ha un’interfaccia grafica WYSIWYG con strumenti drag’n’drop e wizard per la creazione dei report, e infine, che non ho una conoscenza dello stesso paragonabile all’esperienza che ho con Visual Basic, mi sarei aspettato di impiegare come minimo il doppio del tempo, invece l’applicazione completa è stata realizzata in soli 2 giorni di lavoro nemmeno troppo assiduo (non c’erano clienti col fiato sul collo!).
Avessi voluto usare solo PHP e javascript, ci avrei messo davvero molto di più…!
Un buon risultato, visto che sappiamo quanto sia importante produrre applicazioni in breve tempo per tenere bassi i costi ed accontentare clienti sempre meno disposti ad investire grosse cifre sul software.

Quali sono le caratteristiche dell’esempio?

  • Una maschera per la gestione dell’intestazione della ditta
  • Una maschera per la gestione dell’anagrafica clienti (con ricerca per nome)
  • Una maschera per la gestione delle fatture divisa in dati fattura e dettaglio prestazioni
  • Una procedura di stampa della fattura in formato pdf
  • Una maschera per il riepilogo delle fatture emesse e la possibilità di filtraggio per periodo

Qualche screenshot…

maschera iniziale
maschera iniziale
intestazione della ditta
intestazione della ditta
anagrafica clienti
anagrafica clienti
gestione delle fatture: master
gestione delle fatture: master
gestione delle fatture: detail
gestione delle fatture: detail
stampa pdf
stampa pdf
riepilogo delle fatture
riepilogo delle fatture

 

Note tecniche:
Ho provato l’applicazione sia con P4A 2.1.7 che con l’ultima release 2.2.2.
Il funzionamento è corretto sia con PHP4.x e MySQL4.x che con PHP5.2.4 e MySQL5.0.x, in quest’ultimo caso però è necessario impostare la direttiva del php.ini: memory_limit = 64M, il default è 8M.
All’interno del pacchetto, nella directory ‘_private’ ci sono i dump .sql del database MySQL effettuati con phpMyAdmin e con Heidi, il nome del database deve essere: ‘base_app_invoices’.
Infine per la generazione del report in pdf, ho utilizzato la classe R&OS (pdf-php su Sourceforge), conosciuta anche come ezPdf e licenza di tipo Public Domain

Download:

Pacchetto zip completo di librerie R&OS

Conclusioni:

Se il rapporto 1:1 dei tempi di sviluppo con queste differenti tecnologie rimane lo stesso anche per applicazioni complesse, e constatato il vantaggio delle applicazioni web, è da considerare seriamente l’adozione di questo framework PHP fra i propri strumenti di lavoro.

Riferimenti ed approfondimenti:

P4A framework: in arrivo la versione 3 che si veste di Zend

P4A 2.2 logoGrandi novità in casa Crealabs: proprio mentre viene rilasciata la versione 2.2.0 che già introduce numerose ed interessanti caratteristiche, viene annunciata la tabella di marcia per lo sviluppo della rivoluzionaria versione 3.
La versione 2.2.0 (a cui ha già fatto seguito la 2.2.2) oltre a risolvere alcuni bugs, tra i quali il problema di un corretto salvataggio dei dati in tabelle con chiave primaria multipla, presenta le seguenti nuove caratteristiche:

  • Adozione di jQuery con tutti i vantaggi che derivano da questa potente libreria javascript
  • Implementazione di un sistema per la generazione di tooltip
  • Implementazione di un sistema di auto-completamento dei campi, per l’inserimento facilitato dei dati
  • Supporto per la costruzione di plugin personalizzati attraverso un helper system
  • Miglioramento della gestione di contenuti multimediali attraverso l’adozione di getID3

Un bel passo in avanti rispetto alle precedenti versioni, non c’è dubbio! Ma Giardina e Balliano non si sono adagiati sugli allori e si sono messi subito all’opera per costruire la rivoluzionaria versione 3.
Cosa c’è di rivoluzionario? ‘semplicemente’ questo:

  • Compatibilità solo per PHP5 (viene perduta la compatibilità con l’obsoleto PHP4)
  • Nuovo sistema di generazione di widget, con un vasto pacchetto di disponibilità e un supporto multi-browser garantito
  • Adozione di diverse caratteristiche di Zend Framework
  • Sostituzione di ADOdb con Zend_DB
  • Definitivamente risolti i problemi di compatibilità con i vari RDBMS utilizzabili (MySQL, PostgreSQL, Oracle, SQLite)
  • Sostituzione del sistema interno di formattazione e parsing delle date con Zend_Date
  • Sostituzione delle librerie interne per la localizzazione con Zend_locale
  • Sostituzione dell’attuale sistema di traduzione con Zend_Translate
  • Una nuova libreria ottimizzata in php5 per la gestione delle thumbnail sostituisce phpThumb
  • Abbandono dell’utilizzo del pacchetto PEAR

Conclusioni:

L’annunciato P4A versione 3 si veste dunque di Zend framework, e questo non può che fare bene! Il guadagno sarà in termini di compatibilità, robustezza, stabilità e probabilmente anche in performance.
Ci auguriamo che, a scapito di una perdita di compatibilità forse parziale con le vecchie versioni del framework, il nuovo strumento mantenga comunque quelle caratteristiche di semplicità ed immediatezza operativa che sono stati i cavalli di battaglia delle prime versioni.
D’altra parte in informatica tutto è in continua e rapida evoluzione, nessuno di noi può smettere di aggiornarsi, tanto più negli aspetti legati ai linguaggi di programmazione e ai loro ambienti, altrimenti saremmo ancora alle prese con COBOL-CICS (anche se pare che qualche dinosauro di questo tipo sopravviva ancora!)

Riferimenti ed approfondimenti:

PHP: un semplice datagrid per applicazioni web

Esempio di datagridE’ piuttosto frequente, quando si sviluppano applicazioni web, di dover presentare i dati di una query in un datagrid, ovvero in una tabella HTML. In tutti questi casi, può essere comodo avere già pronta una classe che formatta i dati nella tabella e scrive per noi il codice HTML. Questa classe che ho scritto, pur essendo molto semplice e spartana, presenta alcune caratteristiche interessanti:

  • Il codice generato è XHTML valido
  • La presentazione è gestita da fogli stile CSS, quindi facilmente personalizzabile
  • E’ possibile, tramite il passaggio di parametri, creare una colonna aggiuntiva di link per azioni tipo “modifica”, o “dettaglio”
  • E’ possibile visualizzare o nascondere la colonna contenente la chiave primaria
  • Aspetto gradevole e alternanza di colorazione delle singole righe per una più facile lettura dei dati

Attenzione: il codice di questa classe non è più disponibile per obsolescenza

Riferimenti ed approfondimenti:

PHP: Come creare un array di etichette da una tabella dati

Può capitare di dover generare report di etichette, per esempio codici a barre, da una tabella normalizzata contenente i valori delle quantità in un campo. A noi, però, serve poter stampare tante etichette quanto è il valore ‘quantità’ di ogni singolo pezzo.
Ora, sebbene normalmente sia sufficiente, per ogni record, ciclare tante volte per il valore del campo quantità, in certi casi potrebbe essere comodo avere una funzione che fa questo per noi. In particolar modo quando è necessario utilizzare parecchie volte questa procedura.

Immaginiamo di avere una tabella come la seguente, risultato magari di una SELECT

rifnomecodiceqta
a001chiodichd0013
a001vitivt0012
a002rivettirvt0014
a002puntept0011

Simuliamo di aver immagazzinato la query in un array multidimensionale associativo, attraverso l’istruzione mysql_fetch_array:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$data=array
(
    0 => array
        (
            'rif' => 'a001',
            'nome' => 'chiodi',
            'codice' => 'chd001',
            'qta' => 3
        ),
    1 => array
        (
            'rif' => 'a001',
            'nome' => 'viti',
            'codice' => 'vt001',
            'qta' => 2
        ),
    2 => array
        (
            'rif' => 'a002',
            'nome' => 'rivetti',
            'codice' => 'rvt001',
            'qta' => 4
        ),
    3 => array
        (
            'rif' => 'a002',
            'nome' => 'punte',
            'codice' => 'pt001',
            'qta' => 1
        )
);

Lo sviluppo della funzione prevede, come dati di input: l’array dei dati, il nome del campo che contiene le quantità, e il nome dei due campi in base ai quali ordinare l’array.
Ovviamente è possibile modificare questo codice per permettere l’ordinamento con un maggior numero di chiavi. In output la funzione fornisce l’array delle etichette già ordinato.

Vediamo il codice:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function labelmaker($table,$qty,
                    $order1,$order2,
                    $typeorder1=SORT_ASC,
                    $typeorder2=SORT_ASC)
{
  $newdata=array(); // array di appoggio
  $max=count($table);
  for($i=0;$i<$max;$i++){
    foreach ($table[$i] as $k => $value) {
      if($k==$qty && $value>1)
      {
        $q=$table[$i][$k];
        $table[$i][$k]=1;
        for($j=1;$j<$q;$j++)
        {
          array_push($newdata, $table[$i]);
        }
      }
    }
  }
//Unione dei due array
  $res = array_merge($table, $newdata);
// Ottiene un array di colonne per le chiavi
  foreach ($res as $key => $row) {
      $arrorder1[$key] = $row[$order1];
      $arrorder2[$key] = $row[$order2];
  }
// Ordina l'array in base alle chiavi
  array_multisort($arrorder1, $typeorder1,
        $arrorder2, $typeorder2, $res);
    return $res;
}

Note: la funzione accetta l’array in input passato come valore, e restituisce un nuovo array. Questo comporta inevitabilmente un consumo di memoria, in considerazione del fatto che
l’algoritmo prevede anche l’utilizzo di un array di ‘appoggio’, è bene utilizzare questa procedura per una mole di dati ragionevole!

Infine, la funzione viene fornita ‘as is’, senza controllo di errori, né prove efficaci in produzione.

Ecco come viene richiamata:

$lblarr= labelmaker($data,"qta",
         "rif","nome",SORT_ASC,SORT_ASC);

Mostriamo il risultato:

echo '<pre>';
print_r($lblarr);
echo '</pre>';

E questo è il risultato:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
Array
(
    [0] => Array
        (
            [rif] => a001
            [nome] => chiodi
            [codice] => chd001
            [qta] => 1
        )
    [1] => Array
        (
            [rif] => a001
            [nome] => chiodi
            [codice] => chd001
            [qta] => 1
        )
    [2] => Array
        (
            [rif] => a001
            [nome] => chiodi
            [codice] => chd001
            [qta] => 1
        )
    [3] => Array
        (
            [rif] => a001
            [nome] => viti
            [codice] => vt001
            [qta] => 1
        )
    [4] => Array
        (
            [rif] => a001
            [nome] => viti
            [codice] => vt001
            [qta] => 1
        )
    [5] => Array
        (
            [rif] => a002
            [nome] => punte
            [codice] => pt001
            [qta] => 1
        )
    [6] => Array
        (
            [rif] => a002
            [nome] => rivetti
            [codice] => rvt001
            [qta] => 1
        )
    [7] => Array
        (
            [rif] => a002
            [nome] => rivetti
            [codice] => rvt001
            [qta] => 1
        )
    [8] => Array
        (
            [rif] => a002
            [nome] => rivetti
            [codice] => rvt001
            [qta] => 1
        )
    [9] => Array
        (
            [rif] => a002
            [nome] => rivetti
            [codice] => rvt001
            [qta] => 1
        )
)

Conclusioni:

Questa funzione può costituire il prototipo per tutti i casi in
cui si ha la necessità di produrre stampe di etichette, da assegnare a singoli pezzi,
in modo direttamente proporzionale ad un certo quantitativo definito in tabella.

Riferimenti ed approfondimenti: