Visualizzazione post con etichetta Java. Mostra tutti i post
Visualizzazione post con etichetta Java. Mostra tutti i post

mercoledì 10 gennaio 2018

Rotazioni con quaternioni

I quaternioni sono oggetti matematici 4 dimensionali (aw+bx+cy+dz) costituiti da una parte scalare (detta anche reale) ed una parte vettoriale a 3 dimensioni (detta immaginaria). Il loro uso in informatica e' legata al calcolo della rotazione di oggetti in 3 dimensioni e la rappresentazione geometrica del quaternione e' dato da un vettore da (0,0,0) (b,c,d) attorno al quale si sviluppa una rotazione di valore a. (il vettore rotazione nel caso non lo sia deve essere normalizzato). Un documento di lettura abbastanza semplice si puo' trovare a questo link



i vantaggi sono:

0) i quaternioni sono ottimali per calcolare le rotazioni nello spazio. Per invece individuare la posizione di un punto dello spazio e' piu' semplice la definizione cartesiana o con gli angoli di Eulero

1) rispetto ad una rotazione con gli angoli di Eulero (dove sono necessari 9 parametri) con i quaternioni sono sufficienti 4 parametri

2) la rotazione tramite gli angoli di Eulero e' data dalla successione combinata di rotazioni attorno ai tre assi cartesiani con un ordine non preordinato (per esempio si puo' ruotare prima x che su y ma lo stesso risultato puo' essere ottenuto anche invertendo l'ordine). La rotazione tramite quaternioni e' univoca in quanto quella ottimale

3) legato al punto 2 la rotazione con i quaternioni non e' soggetta a gimbal lock

Per effettuare una rotazione si utilizza una estensione del metodo per i numeri complessi in 2D.
Si crea un quaterione (R) che descriva la rotazione e poi si applica al vettore desiderato(P) con la regola RPR-1

la moltiplicazione dei tre quaternioni segue una regola un po' particolare che si riassume come



Questa codice e' stato ripreso da questo link

---------------------------------------
        //coordinate del punto da ruotare
        float x_old = 0;
        float y_old = 1;
        float z_old = 1;
        
        //angolo di rotazione
        float angle = (float) Math.toRadians(45.0);
        
        // vettore di rotazione
        float xi = 1;
        float yi = 1;
        float zi = 1;
        
        float norma = (float) Math.sqrt((xi*xi)+(yi*yi)+(zi*zi));
        
        xi = xi/norma;
        yi = yi/norma;
        zi = zi/norma;

        double w = Math.cos(angle/2.0);
        double x = xi*Math.sin(angle/2.0);
        double y = yi*Math.sin(angle/2.0);
        double z = zi*Math.sin(angle/2.0);

        float x_new = (float) ((1 - 2*y*y -2*z*z)*x_old + (2*x*y + 2*w*z)*y_old + (2*x*z-2*w*y)*z_old);
        float y_new = (float) ((2*x*y - 2*w*z)*x_old + (1 - 2*x*x - 2*z*z)*y_old + (2*y*z + 2*w*x)*z_old);
        float z_new = (float) ((2*x*z + 2*w*y)*x_old + (2*y*z - 2*w*x)*y_old + (1 - 2*x*x - 2*y*y)*z_old);
                
        System.out.println(Double.toString(x_new));
        System.out.println(Double.toString(y_new));
        System.out.println(Double.toString(z_new));
---------------------------------------


Rotazione di un cubo di spigolo 1 orientato come gli asse e con spigolo in (0,0,0) di 45° attorno ad un vettore (0,0,0)(1,1,1). Dati rappresentati con Geogebra (nella tabella a fianco i valori dei punti ruotati)


martedì 20 giugno 2017

OBDSIM in Java




Per prima cosa si scarica IntelliJ Idea Commumity Edition e si importa i progetto File/New/Project from existing sources/Maven e si clicca sulla radice del progetto





poi da File/Project Structure si clicca su Libraries e si aggiunge la libreria jar bluecove che fornisce le librerie non presenti nel progetto preso da GitHub



Una volta cliccato Run si deve cliccare Edit Configuration, si preme + e si crea una Application.
Si imposta la classe Main e siamo quindi pronti a lanciare il progetto. Per creare il file .jar (in modo da non avere bisogno dell'IDE) si va in File/Project Structure/Artifacts si clicca + si aggiunge come JAR

java -cp obdsim.jar so.mwil.obdsim.Main

Si telnetta su

telnet 127.0.0.1 35000

e si richiedono i dati dei giri motore con

010C

il sistema risponde sempre al solito modo (non e' random) ovvero ripetendo il comando inviato con poi il codice 41 0C (codice di risposta) e 4b0 (il numero di giri in esadecimale ovvero 1200 che va diviso per 4 per ottenere gli RPM link)

010C
41 0C 4b0

Se Centos e' obbligatorio sbloccare la porta 35000, che e' filtrata dal firewall, con i comandi

firewall-cmd --zone=public --add-port=2888/tcp


lunedì 5 maggio 2014

JDK 8 e WIndows XP

Installando JDK8 su Windows XP, l'installer ha generato questo errore ovvero non e' stata trovata la chiave di registor RegDeleteKeyExA in ADVAPI32.DLL


Dopo un po' di ricerche ho trovato sul sito Oracle che JDK8 non supporta Windows XP e che quindi si deve rimanere sulla versione precedente

martedì 14 gennaio 2014

Compressione SMS in Android (2)

Riprendendo dalla puntata precedente, in questo caso la compressione non e' orientata ai caratteri ma si basa sull'ottimizzare il numero di bit per comprimere il dato. Come gia' detto l'obbiettivo e' trasferire informazioni geografiche quindi coordinate lat/long che possono essere descritte come numeri in virgola mobile (non e' previsto avere segni di separazione perche' sara' solo la posizione a determinare la distinzione tra un dato ed il successivo)

Una coordinata in gradi decimali (se non ho sbagliato) necessita' di almeno 5 decimali per avere una precisione al secondo di arco in grado sessagesimali.
La logica e' piu' o meno questa:
1) si prende il numero in virgola mobile e lo si converte nella sua rappresentazione binaria (come stringa)
2) si divide la stringa in pezzi da 7 bit (per il formato SMS)
3) si prendono solo i primi 5 gruppi di 7 bit (il resto dell'informazione e' ridondante)
4) i 7 bit vengono convertiti in un intero (0-127) e quindi nel corrispondente caratttere della tabella SMS
5) il percorso inverso per la riconversione in float

il vantaggio non e' drammatico. Si descrive un numero che puo' essere scritto con 8 caratteri in 5 gruppi da 7 bit (quindi il messaggio occupa circa 0.62 dell'originale, ovvero 1.6 dipende da punto si vede)
Questi sono i passaggi

-------------------------------------------------------------------
Messaggio originale :43.26432
100000001000101101000011101010100111100110111011101011011100000
Messaggio compresso : ¡"h:S
100000001000101101000011101010100110000000000000000000000000000
Messaggio decompresso : 43.26431846618652
-------------------------------------------------------------------
ed ecco il codice

--------------------------------------------------------------

package sms_compr;

import java.math.BigInteger;

/**
 *
 * @author l.innocenti
 */
public class Sms_compr {
    private static int valore;
    private static String reverse = "";
    private static String passaggio = "";
    
    

     static private int converti_sms(char carattere)
    {
       int codice=0;
       switch (carattere)
            {
             case '@': codice=0;break;
             case '£': codice=1;break;
             case '$': codice=2;break;
             case '¥': codice=3;break;
             case 'è': codice=4;break;
             case 'é': codice=5;break;
             case 'ù': codice=6;break;
             case 'ì': codice=7;break;
             case 'ò': codice=8;break;
             case 'Ç': codice=9;break;
             case '\n': codice=10;break;
             case 'Ø': codice=11;break;
             case 'ø': codice=12;break;
             case '\r': codice=13;break;
             case 'Å': codice=14;break;
             case 'å': codice=15;break;
             case 'Δ': codice=16;break;
             case '_': codice=17;break;
             case 'Φ': codice=18;break;
             case 'Γ': codice=19;break;
             case 'Λ': codice=20;break;
             case 'Ω': codice=21;break;
             case 'Π': codice=22;break;
             case 'Ψ': codice=23;break;
             case 'Σ': codice=24;break;
             case 'Θ': codice=25;break;
             case 'Ξ': codice=26;break;
             //case '': codice=27;break;
             case 'Æ': codice=28;break;
             case 'æ': codice=29;break;
             case 'ß': codice=30;break;
             case 'É': codice=31;break;
             case ' ': codice=32;break;
             case '!': codice=33;break;
             case '"': codice=34;break;
             case '#': codice=35;break;
             case '¤': codice=36;break;
             case '%': codice=37;break;
             case '&': codice=38;break;
             case '\'': codice=39;break;
             case '(': codice=40;break;
             case ')': codice=41;break;
             case '*': codice=42;break;
             case '+': codice=43;break;
             case ',': codice=44;break;
             case '-': codice=45;break;
             case '.': codice=46;break;
             case '/': codice=47;break;
             case '0': codice=48;break;
             case '1': codice=49;break;
             case '2': codice=50;break;
             case '3': codice=51;break;
             case '4': codice=52;break;
             case '5': codice=53;break;
             case '6': codice=54;break;
             case '7': codice=55;break;
             case '8': codice=56;break;
             case '9': codice=57;break;
             case ':': codice=58;break;
             case ';': codice=59;break;
             case '<': codice=60;break;
             case '=': codice=61;break;
             case '>': codice=62;break;
             case '?': codice=63;break;
             case '¡': codice=64;break;
             case 'A': codice=65;break;
             case 'B': codice=66;break;
             case 'C': codice=67;break;
             case 'D': codice=68;break;
             case 'E': codice=69;break;
             case 'F': codice=70;break;
             case 'G': codice=71;break;
             case 'H': codice=72;break;
             case 'I': codice=73;break;
             case 'J': codice=74;break;
             case 'K': codice=75;break;
             case 'L': codice=76;break;
             case 'M': codice=77;break;
             case 'N': codice=78;break;
             case 'O': codice=79;break;
             case 'P': codice=80;break;
             case 'Q': codice=81;break;
             case 'R': codice=82;break;
             case 'S': codice=83;break;
             case 'T': codice=84;break;
             case 'U': codice=85;break;
             case 'V': codice=86;break;
             case 'W': codice=87;break;
             case 'X': codice=88;break;
             case 'Y': codice=89;break;
             case 'Z': codice=90;break;
             case 'Ä': codice=91;break;
             case 'Ö': codice=92;break;
             case 'Ñ': codice=93;break;
             case 'Ü': codice=94;break;
             case '§': codice=95;break;
             case '¿': codice=96;break;
             case 'a': codice=97;break;
             case 'b': codice=98;break;
             case 'c': codice=99;break;
             case 'd': codice=100;break;
             case 'e': codice=101;break;
             case 'f': codice=102;break;
             case 'g': codice=103;break;
             case 'h': codice=104;break;
             case 'i': codice=105;break;
             case 'j': codice=106;break;
             case 'k': codice=107;break;
             case 'l': codice=108;break;
             case 'm': codice=109;break;
             case 'n': codice=110;break;
             case 'o': codice=111;break;
             case 'p': codice=112;break;
             case 'q': codice=113;break;
             case 'r': codice=114;break;
             case 's': codice=115;break;
             case 't': codice=116;break;
             case 'u': codice=117;break;
             case 'v': codice=118;break;
             case 'w': codice=119;break;
             case 'x': codice=120;break;
             case 'y': codice=121;break;
             case 'z': codice=122;break;
             case 'ä': codice=123;break;
             case 'ö': codice=124;break;
             case 'ñ': codice=125;break;
             case 'ü': codice=126;break;
             case 'à': codice=127;break;
       }
       return codice;
    }

    public static void main(String[] args) {
         char[] sms = new char[128];
        

        sms[0] = '@';
        sms[1] = '£';
        sms[2] = '$';
        sms[3] = '¥';
        sms[4] = 'è';
        sms[5] = 'é';
        sms[6] = 'ù';
        sms[7] = 'ì';
        sms[8] = 'ò';
        sms[9] = 'Ç';
        sms[10] = '\n';
        sms[11] = 'Ø';
        sms[12] = 'ø';
        sms[13] = '\r';
        sms[14] = 'Å';
        sms[15] = 'å';
        sms[16] = 'Δ';
        sms[17] = '_';
        sms[18] = 'Φ';
        sms[19] = 'Γ';
        sms[20] = 'Λ';
        sms[21] = 'Ω';
        sms[22] = 'Π';
        sms[23] = 'Ψ';
        sms[24] = 'Σ';
        sms[25] = 'Θ';
        sms[26] = 'Ξ';
        //sms[27] = '';
        sms[28] = 'Æ';
        sms[29] = 'æ';
        sms[30] = 'ß';
        sms[31] = 'É';
        sms[32] = ' ';
        sms[33] = '!';
        sms[34] = '"';
        sms[35] = '#';
        sms[36] = '¤';
        sms[37] = '%';
        sms[38] = '&';
        sms[39] = '\'';
        sms[40] = '(';
        sms[41] = ')';
        sms[42] = '*';
        sms[43] = '+';
        sms[44] = ',';
        sms[45] = '-';
        sms[46] = '.';
        sms[47] = '/';
        sms[48] = '0';
        sms[49] = '1';
        sms[50] = '2';
        sms[51] = '3';
        sms[52] = '4';
        sms[53] = '5';
        sms[54] = '6';
        sms[55] = '7';
        sms[56] = '8';
        sms[57] = '9';
        sms[58] = ':';
        sms[59] = ';';
        sms[60] = '<';
        sms[61] = '=';
        sms[62] = '>';
        sms[63] = '?';
        sms[64] = '¡';
        sms[65] = 'A';
        sms[66] = 'B';
        sms[67] = 'C';
        sms[68] = 'D';
        sms[69] = 'E';
        sms[70] = 'F';
        sms[71] = 'G';
        sms[72] = 'H';
        sms[73] = 'I';
        sms[74] = 'J';
        sms[75] = 'K';
        sms[76] = 'L';
        sms[77] = 'M';
        sms[78] = 'N';
        sms[79] = 'O';
        sms[80] = 'P';
        sms[81] = 'Q';
        sms[82] = 'R';
        sms[83] = 'S';
        sms[84] = 'T';
        sms[85] = 'U';
        sms[86] = 'V';
        sms[87] = 'W';
        sms[88] = 'X';
        sms[89] = 'Y';
        sms[90] = 'Z';
        sms[91] = 'Ä';
        sms[92] = 'Ö';
        sms[93] = 'Ñ';
        sms[94] = 'Ü';
        sms[95] = '§';
        sms[96] = '¿';
        sms[97] = 'a';
        sms[98] = 'b';
        sms[99] = 'c';
        sms[100] = 'd';
        sms[101] = 'e';
        sms[102] = 'f';
        sms[103] = 'g';
        sms[104] = 'h';
        sms[105] = 'i';
        sms[106] = 'j';
        sms[107] = 'k';
        sms[108] = 'l';
        sms[109] = 'm';
        sms[110] = 'n';
        sms[111] = 'o';
        sms[112] = 'p';
        sms[113] = 'q';
        sms[114] = 'r';
        sms[115] = 's';
        sms[116] = 't';
        sms[117] = 'u';
        sms[118] = 'v';
        sms[119] = 'w';
        sms[120] = 'x';
        sms[121] = 'y';
        sms[122] = 'z';
        sms[123] = 'ä';
        sms[124] = 'ö';
        sms[125] = 'ñ';
        sms[126] = 'ü';
        sms[127] = 'à';
        double lat = 43.26432; //64 bit
        String stringa;
        String compressa = "";
        
        System.out.println("Messaggio originale :"+ lat);

        //convert il double in una stringa con la conversione binaria del dato
        stringa = Long.toBinaryString(Double.doubleToRawLongBits(lat));
        System.out.println(stringa);
        
        //divide il dato in pezzi da 7 bit
        //per mandare il dato via SMS con la tabella caratteri SMS
        String b1 = stringa.substring(0, 7);
        String b2 = stringa.substring(7, 14);
        String b3 = stringa.substring(14, 21);
        String b4 = stringa.substring(21, 28);
        String b5 = stringa.substring(28, 35);
        //String b6 = stringa.substring(35, 42);
        //String b7 = stringa.substring(42, 49);
        //String b8 = stringa.substring(49, 56);
      
        //convert il valore binario a base 7 in intero
        int d1 = Integer.parseInt(b1, 2);
        int d2 = Integer.parseInt(b2, 2);
        int d3 = Integer.parseInt(b3, 2);
        int d4 = Integer.parseInt(b4, 2);
        int d5 = Integer.parseInt(b5, 2);
        //int d6 = Integer.parseInt(b6, 2);
        //int d7 = Integer.parseInt(b7, 2);
        //int d8 = Integer.parseInt(b8, 2);
        
        //usando la tabella di compressione prende i primi 5 gruppi di 7 bit
        //e li codifica come SMS
        //compressa = compressa + sms[d1]+sms[d2]+sms[d3]+sms[d4]+sms[d5]+sms[d6]+sms[d7]+sms[d8];
        compressa = compressa + sms[d1]+sms[d2]+sms[d3]+sms[d4]+sms[d5];
        System.out.println("Messaggio compresso : "+compressa);
        
        for (int t=0; t<compressa.length();t++)
            {
            valore = converti_sms(compressa.charAt(t));
            String v = Integer.toBinaryString(valore);
           reverse = new StringBuffer(v).toString();
           //System.out.println(reverse);


        

            while ((reverse.length() %7) != 0)
                {
                reverse = "0"+reverse ;
                }
            passaggio = passaggio + reverse;
            //System.out.println("a "+reverse);

            }
        

        
        passaggio = passaggio + "0000000000000000000000000000";
        System.out.println(passaggio);

        
        double doubleVal = Double.longBitsToDouble(new BigInteger(passaggio, 2).longValue());
        System.out.println("Messaggio decompresso : "+doubleVal);
        
        
        
    }
    
}

Compressione SMS in Android

Per la solita applicazione su cui sto lavorando adesso, sarebbe utile effettuare la compressione dei dati di un SMS per trasportare la maggiore quantita' di informazioni. Ho fatto un paio di prove, la prima e' questa basata semplicemente sulla compressione dei caratteri

Fonte Wikipedia


I dati previsti sono numerici con alcuni segni di interpunzione per cui l'intero set di caratteri puo' essere descritto con un set di 16 caratteri (4 bit). I dati trasportati sono coordinate geografiche, informazioni sul tempo, dati di antenne e stato della batteria
Considerando che la tavola dei caratteri piu' semplice per gli SMS racchiude 7 bit c'e' un discreto guadagno (un fattore di 1.75)

Attualmente gli SMS permettono di inviare 1120 bit, ovvero 160 caratteri con la tabella a 7 bit e 140 con la tabella ad 8 bit.(le tabelle dei codici SMS non sono confrontabili con quelle ASCII)

Usando il codice riportato dopo il salto e' stata effettuata una prova codificando

---------------------------------------------
Messaggio : 12.3455;43.123123;22;-45;13:23:21 12/03/2013
Lungh. messaggio 44
Valore numerici convertiti a 7 bit 72 22 11 85 39 120 34 98 72 120 17 58 45 116 33 30 68 7 97 71 84 0 23 2 72 127 127 
Messaggio compresso a 7 Bit tabella GSM : HΠØU'x"bHx_:-t!ßDìaGT@Ψ$Hàà
Lungh.Mess.Compresso 27
Messaggio Decompresso :12.3455;43.123123;22;-45;13:23:21 12/03/2013   
---------------------------------------------

Come si osserva che il messaggio e' compresso con un fatto di circa 1.7 (il limite teorico di 1.75 non e' raggiunto per una serie di aggiustamenti nel passare da 4 a 7 bit)


lunedì 9 settembre 2013

Http Client in Java/Android

Un breve esempio di come realizzare una connessione automatica in protocollo HTTP mediante Java/Android


-------------------------------------------------------------------------------------
package httpclient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;


public class Httpclient {

    public static void main(String[] args) throws IOException {
    try {
        URL url = new URL("http://www.google.it/");
               
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.arpat.toscana.it", 8080));
        HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy);
        //se non c'e' proxy commentare la riga superiore e decommentare quella inferiore
        //HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        
        //decommentare le due righe successive per mostrare il codice di errore HTTP
        //ritornato dal server
        //int code = connection.getResponseCode();
        //System.out.println(Integer.toString(code));
        
        BufferedReader read = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        String line;
        line = read.readLine();
        String html = "";
        while(line!=null) {
            html += line;
            line = read.readLine();
        }
        System.out.println(html);
} catch(MalformedURLException ex) {
} catch(IOException ioex) {
}
    }
    
}

sabato 25 maggio 2013

Codici a barre CODE 39

Con una leggera modifica al programma presentato a questo post e'possibile creare dei codici a barre in formato Code 39 usando la libreria ZXing in Java

Le modifiche sono evidenziate in giallo

Il risultato e' qualcosa di simile (il codice e' 003)



---------------------------------------
package qrcode;

import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Hashtable;

import com.google.zxing.client.j2se.MatrixToImageWriter;


/**
 *
 * @author l.innocenti
 */
public class QrCode {

    public static void main(String[] args) {
        Charset charset = Charset.forName("UTF-8");
        CharsetEncoder encoder = charset.newEncoder();
        byte[] b = null;
            try {
                // Convert a string to UTF-8 bytes in a ByteBuffer
                ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(args[0]));
                b = bbuf.array();
            } catch (CharacterCodingException e) {
                System.out.println(e.getMessage());
            }

            String data;
            try {
                data = new String(b, "UTF-8");
                // get a byte matrix for the data
                BitMatrix matrix = null;
                int h = 100;
                int w = 300;
                com.google.zxing.Writer writer = new MultiFormatWriter();
                try {
                    Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>(2);
                    hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
                    matrix = writer.encode(data,
                    com.google.zxing.BarcodeFormat.CODE_39, w, h, hints);
                } catch (com.google.zxing.WriterException e) {
                    System.out.println(e.getMessage());
                }

                // change this path to match yours (this is my mac home folder, you can use: c:\\qr_png.png if you are on windows)
                        String filePath = args[0]+".png";
                File file = new File(filePath);
                try {
                    MatrixToImageWriter.writeToFile(matrix, "PNG", file);
                    System.out.println("printing to " + file.getAbsolutePath());
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            } catch (UnsupportedEncodingException e) {
                System.out.println(e.getMessage());
            }
            }
}

lunedì 20 maggio 2013

Installare Oracle JDK in automatico su Debian

Per utilizzare Android Studio e' richiesto l'Oracle Java SDK

Su Debian l'installazione di questo componente di solito viene fatta in modo manuale


Frugando qua e la' ho trovato questo link che permette l'installazione di Oracle SdK in modo automatico sfruttando i repository PPA di Ubuntu

echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu precise main" | tee -a /etc/apt/sources.list
echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu precise main" | tee -a /etc/apt/sources.list
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EEA14886
apt-get update
apt-get install oracle-java7-installer

Non e' elegante ma a me ha funzionato

sabato 18 maggio 2013

Android Studio su Linux





A differenza della versione per Windows, l'installazione di Android Studio su Debian e' nettamente piu' lineare. L'aspetto da sottolineare e' la richiesta di avere installato Oracle JDK e non OpenJDK

martedì 12 marzo 2013

Esempio di utilizzo di Itext in Java

Presento adesso un esempio reale dell'utilizzo della libreria IText per la creazione di pettorali per una corsa podistica.
La caratteristica dei pettorali era quella di dover contenere, oltre al numero, anche il relativo QrCode. Il pettorale e' quindi determinato dalla sovrapposizione di una immagine di base con i logo, il QrCode ed il numero. Il tutto e' gia' formattato per andare direttamente in tipografia (il foglio in formato Super A3 comprende 4 numeri che saranno successivamente tagliati)

Immagine di fondo

QrCode


Il risultato finale

Il codice per la generazione dei Pdf e' il seguente. Si deve precisare che le immagini dei QrCode erano gia' state create con il programma presentato in un precedente post e viene usato un font speciale (CITYB.ttf)
----------------------------------------------------------------------

package pettorale;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;

/**
 *
 * @author l.innocenti
 */
public class Pettorale {
    private static PdfWriter writer;
    

    public static void main(String[] args) throws BadElementException, MalformedURLException, IOException {
        
    //String numero = args[0];
    String  numero = "175";
    int inizio = Integer.parseInt(numero);
    
    BufferedOutputStream out = null;
    try {
        out = new BufferedOutputStream (new FileOutputStream (new File ("Pettorale_"+numero+"_"+Integer.toString(inizio+3) +".pdf")));
        } catch (FileNotFoundException e) {
          e.printStackTrace();
        }
    
        //Definisce le dimensioni del foglio come SuperA3 (45x32 cm)
        //Itext usa una unita'  di misura in punti tipografici 
        //1 cm = 28.35 unita' per cui le dimesioni del foglio sono
        //45 cm = 1285 u
        //32 cm = 907 u
        Rectangle pagina = new Rectangle(1275, 907);
        Document doc = new Document (pagina,0,0,0,0);

        try
        {
            writer = PdfWriter.getInstance (doc, out);
            doc.open ();
            PdfContentByte canvas = writer.getDirectContent();
            
            //inserisce lo sfondo 
            Image pettorale = Image.getInstance("pettorale/vuoto.png");
            pettorale.setAbsolutePosition(0f, 0f);
            pettorale.scalePercent(24.5f);
            doc.add(pettorale);

            //inserisce il QrCode del numero del pettorale
            Image qrcode = Image.getInstance("qrcode/"+Integer.toString(inizio) +".png");
            qrcode.setAbsolutePosition(475f, 620f);
            qrcode.scalePercent(120f);
            doc.add(qrcode);
            
            //2° numero
            qrcode = Image.getInstance("qrcode/"+Integer.toString(inizio+1) +".png");
            qrcode.setAbsolutePosition(1125f, 620f);
            qrcode.scalePercent(120f);
            doc.add(qrcode);
            
            //3° numero
            qrcode = Image.getInstance("qrcode/"+Integer.toString(inizio+2) +".png");
            qrcode.setAbsolutePosition(475f, 170f);
            qrcode.scalePercent(120f);
            doc.add(qrcode);

            //4° numero
            qrcode = Image.getInstance("qrcode/"+Integer.toString(inizio+3) +".png");
            qrcode.setAbsolutePosition(1125f, 170f);
            qrcode.scalePercent(120f);
            doc.add(qrcode);

            
            //scrive il numero del pettorale alla giusta posizione
           //1° numero 
           if (inizio <10) {
                absText(Integer.toString(inizio),270,625);
            }
            if ((inizio >=10) && (inizio <= 99)) {
                absText(Integer.toString(inizio),235,625);
            }
            if ((inizio >=100) && (inizio <= 999)) {
               absText(Integer.toString(inizio),150,625);
            }
            
            //2°numero
            if (inizio+1 <10) {
               absText(Integer.toString(inizio+1),920,625);
            }
            if ((inizio+1 >=10) && (inizio+1 <= 99)) {
                absText(Integer.toString(inizio+1),885,625);
            }
            if ((inizio+1 >=100) && (inizio+1 <= 999)) {
               absText(Integer.toString(inizio+1),790,625);
            }

            //3°numero
            if (inizio+2 <10) {
               absText(Integer.toString(inizio+2),270,165);
            }
            if ((inizio+2 >=10) && (inizio+2 <= 99)) {
               absText(Integer.toString(inizio+2),235,165);
            }
            if ((inizio+2 >=100) && (inizio+2 <= 999)) {
               absText(Integer.toString(inizio+2),150,165);
            }
            
            //4°numero
            if (inizio+3 <10) {
               absText(Integer.toString(inizio+3),920,165);
            }
            if ((inizio+3 >=10) && (inizio+3 <= 99)) {
               absText(Integer.toString(inizio+3),885,165);
            }
            if ((inizio+3 >=100) && (inizio+3 <= 999)) {
               absText(Integer.toString(inizio+3),790,165);
            }

     
        }
        catch (DocumentException e)
        {
            System.out.println ("Fatal PDF error: " + e);
        }

        doc.close ();

    }
    
    private static void absText(String text, int x, int y) {
    try {
      PdfContentByte cb = writer.getDirectContent();
      BaseFont slam = BaseFont.createFont("CITYB.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
      cb.saveState();
      cb.beginText();
      cb.moveText(x, y);
      cb.setFontAndSize(slam, 200);
      cb.showText(text);
      cb.endText();
      cb.restoreState();
    } catch (DocumentException | IOException e) {
    }
  }
}
----------------------------------------------------------------------


giovedì 7 marzo 2013

Creare file Jar con Eclipse

Per creare un file jar in Eclipse si deve prima cliccare sulla radice del progetto sulla finestra di sinistra e selezionare Export


Successivamente deve essere selezionato Runnable Jar File



Nell'ultima finestra, dal primo menu a tendina, deve essere selezionata la classe di lancio




Creare file Jar con Netbeans

Per ottenere dei file jar da distribuire di una propria applicazione da NetBeans e' sufficiente effettuare una Build del progetto (F11)

In questo modo viene creata una sottodirectory build nella quale sono contenuti tutti i file (librerie comprese) necessari per la redistribuzione dell'eseguibile


Creazione automatica QrCode in Java/Netbeans

Per generare QrCode in modo automatico in modo semplice si puo' utilizzare il metodo presentato a questo indirizzo

 Si deve scaricare la libreria XZing e si devono aggiungere al progetto le librerie core e javase contenute nelle sottodirectory del file zip


il codice e' stato modificato in modo da accettare in input sulla riga di comando (nella variabile args) il contenuto del QrCode. Questa motiva permette mediante una procedura batch di creare in automatico quanti QrCode si desiderino

-----------------------------------------
package qrcode;


import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Hashtable;

import com.google.zxing.client.j2se.MatrixToImageWriter;


/**
 *
 * @author l.innocenti
 */
public class QrCode {

    public static void main(String[] args) {
        Charset charset = Charset.forName("UTF-8");
        CharsetEncoder encoder = charset.newEncoder();
        byte[] b = null;
            try {
                // Convert a string to UTF-8 bytes in a ByteBuffer
                ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(args[0]));
                b = bbuf.array();
            } catch (CharacterCodingException e) {
                System.out.println(e.getMessage());
            }

            String data;
            try {
                data = new String(b, "UTF-8");
                // get a byte matrix for the data
                BitMatrix matrix = null;
                int h = 100;
                int w = 100;
                com.google.zxing.Writer writer = new MultiFormatWriter();
                try {
                    Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>(2);
                    hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
                    matrix = writer.encode(data,
                    com.google.zxing.BarcodeFormat.QR_CODE, w, h, hints);
                } catch (com.google.zxing.WriterException e) {
                    System.out.println(e.getMessage());
                }

                // change this path to match yours (this is my mac home folder, you can use: c:\\qr_png.png if you are on windows)
                        String filePath = args[0]+".png";
                File file = new File(filePath);
                try {
                    MatrixToImageWriter.writeToFile(matrix, "PNG", file);
                    System.out.println("printing to " + file.getAbsolutePath());
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            } catch (UnsupportedEncodingException e) {
                System.out.println(e.getMessage());
            }
            }
}
-----------------------------------------
Il risultato e' una immagine Png con nome uguale al contenuto del QrCode 
Per creare in automatico 1000 numeri QrCode di numeri progressivi si puo' creare un file batch su Windows con la seguente linea
-------------------------------------------------------------

FOR /L %%A IN (1,1,1000) DO java -jar Qrcode.jar %%A
-------------------------------------------------------------

mentre in Linux
-------------------------------------------------------------

#!/bin/bash
for i in {1..1000}
do
   java -jar Qrcode.jar $i
done
--------------------------------------------------------------


Debugger integrato ESP32S3

Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede  nell'ID USB della porta Jtag. Nel modulo...