Blocage sur codage d'un fichier ASCII de structure Tomtom OV2

Pour toutes les discussions javascript, jQuery et autres frameworks
Répondre
Jpe54
Messages : 68
Enregistré le : 10 mars 2017, 14:11

Blocage sur codage d'un fichier ASCII de structure Tomtom OV2

Message par Jpe54 » 14 mai 2024, 15:47

Bonjour,

Je souhaite générer en javascript la structure d'un fichier de Points d'intérêt au format ov2 de Tomtom contenant : Longitude Latitude Texte libre en ASCII)

Voici le cahier des charges utilisé selon informations techniques :

Chaque entrée d’un simple fichier OV2 personnalisé est la suivante.
1 octet : type (toujours 2)
4 octets : longueur de cet enregistrement en octets (y compris les champs T et L)
4 octets : coordonnée de longitude du point d’intérêt
4 octets : coordonnée de latitude du point d’intérêt
13 octets : chaîne ASCII terminée par un caractère nul spécifiant le nom du point d’intérêt
Les coordonnées sont stockées sous forme d’entiers de 4 octets représentant une longitude ou une latitude WGS84, multiplié par 100 000 et arrondi à l’entier le plus proche.
Ainsi, une coordonnée X doit toujours être une valeur comprise entre -18 000 000 et +18 000 000, et une coordonnée Y doit être une valeur comprise entre -9 000 000 et +9 000 000

+=+=+=+

Dans le codage joint je bute sur 3 points :
1- Quelque soit la source, avant traitement, disposer d'une chaine en ASCII de manière à n'avoir qu'un seul code Hexadécimal pour les caractères accentués
2- Gérer éventuellement une taille variable du buffer pour une chaine terminée par un seul caractère Nul
3- Codage correct de la longueur - variable - de chaque enregistrement en octets (y compris les champs T et L)

A titre d'exemple la chaine ASCII en texte et le contenu "complet" Hexadécimale attendu - qui contient latitude et longitude avant la chaine ASCII - dans le fichier formaté OV2 : (en rouge le code Hexa de "a" et "à")

[I3] Moulin a Maree (Tregastel)
02 2D 00 00 00 99 AC FA FF 83 80 4A 00 5B 49 33 5D 20 4D 6F 75 6C 69 6E 20 61 20 4D 61 72 65 65 20 28 54 72 65 67 61 73 74 65 6C 29 00

[I3] Moulin à Marée (Trégastel)
02 2D 00 00 00 99 AC FA FF 84 80 4A 00 5B 49 33 5D 20 4D 6F 75 6C 69 6E 20 E0 20 4D 61 72 E9 65 20 28 54 72 E9 67 61 73 74 65 6C 29 00

Merci par avance de toute remarque...

Bien amicalement,

Code : Tout sélectionner

 // Résultat attendu avec longitude latitude et poiName :
console.log("Héxadécimal attendu pour la chaine :");
console.log("[I3] Moulin a Maree (Tregastel)");
console.log("02 2D 00 00 00 99 AC FA FF 83 80 4A 00 5B 49 33 5D 20 4D 6F 75 6C 69 6E 20 61 20 4D 61 72 65 65 20 28 54 72 65 67 61 73 74 65 6C 29 00");
// console.log("022D00000099ACFAFF83804A005B49335D204D6F756C696E2061204D61726565202854726567617374656C2900");

console.log("Héxadécimal attendu pour la chaine :");
console.log("[I3] Moulin à Marée (Trégastel)");
console.log("02 2D 00 00 00 99 AC FA FF 84 80 4A 00 5B 49 33 5D 20 4D 6F 75 6C 69 6E 20 E0 20 4D 61 72 E9 65 20 28 54 72 E9 67 61 73 74 65 6C 29 00");
// console.log("022D00000099ACFAFF84804A005B49335D204D6F756C696E20E0204D6172E96520285472E967617374656C2900");

		
// Example à traiter en ASCII
const longitude = -3.490315;
const latitude = 48.825641;
// Test sans Accents
const poiName = "[I3] Moulin a Maree (Tregastel)";
// Test Avec Accents
// const poiName = "[I3] Moulin à Marée (Trégastel)";

// Appel function
const ov2Data = encodeOV2(longitude, latitude, poiName);

// Traitement Hexadécimale pour faciliter la lecture 
let HexaAvecEspaces = insererEspaceTousLesDeuxCaracteres(ov2Data.toUpperCase());
console.log(HexaAvecEspaces); 
// Correspondance Affichage texte
const asciiString = hexToAscii(ov2Data);
console.log(asciiString); 

// *************************************************************
function encodeOV2(longitude, latitude, name) {
    // Convertir les coordonnées en entiers de 4 octets
    const x = Math.round(longitude * 100000);
    const y = Math.round(latitude * 100000);

    // Créer un tableau tampon pour stocker les données
	// ==============================================================
	// -------- REVOIR 1  > A ajuster selon chaine à traiter
	// ==============================================================
	const buffer = new ArrayBuffer(14 + name.length);
	// --------------------------------------------------------------
    const view = new DataView(buffer);

    // Remplir le tableau tampon avec les valeurs appropriées
    view.setUint8(0, 2); // Type (toujours 2)
	// ==============================================================
	// -------- REVOIR 2 Comment déterminer variable à la place de 45 ?
	// ==============================================================
    view.setUint32(1, 45, true); // Longueur totale (y compris les champs T et L)
	// -------------------- A REVOIR --------------------------------
	
    view.setInt32(5, x, true); // Coordonnée de longitude
    view.setInt32(9, y, true); // Coordonnée de latitude

    // Copier le nom du point d'intérêt en ASCII dans le tableau tampon
	// ==============================================================
	// ------- REVOIR 2 > Imposer ASCII TextDecoder('ascii') ou TextEncoder('ascii')
	// ==============================================================
    const nameBytes = new TextEncoder().encode(name);
	// -------------------------------------------------------------
	// const nameBytes = new TextEncoder().encode(encodeURIComponent(name));
	// const nameBytes = new TextEncoder('ascii').encode((name));
	console.log(nameBytes.length);
    for (let i = 0; i < nameBytes.length; i++) {
        view.setUint8(13 + i, nameBytes[i]);
    }
	view.setUint8(13 + nameBytes.length, 0); // Caractère nul de fin
	
    // Convertir le tableau tampon en une chaîne hexadécimale
    let result = '';
    for (let i = 0; i < buffer.byteLength; i++) {
        result += view.getUint8(i).toString(16).padStart(2, '0');
    }
    return result;
}

function hexToAscii(hex) {
    let str = '';
    for (let i = 0; i < hex.length; i += 2) {
        const charCode = parseInt(hex.substr(i, 2), 16);
        str += String.fromCharCode(charCode);
    }
    return str;
}

function insererEspaceTousLesDeuxCaracteres(hex) {
    return hex.split(/(.{2})/).filter(Boolean).join(" ");
}

Avatar du membre
webmaster
Administrateur du site
Messages : 611
Enregistré le : 28 févr. 2017, 15:19

Re: Blocage sur codage d'un fichier ASCII de structure Tomtom OV2

Message par webmaster » 14 mai 2024, 19:54

Bonjour

La première question sur les caractères accentués est la plus simple en JS
Il faut utiliser les regexp
c'est facile
par exemple pour les e accents

Code : Tout sélectionner

libelle=libelle.replace(/[èëéê]/g,"e")
libelle=libelle.replace(/[à]/g,"a")
TJS : 25 ans et mon livre Tout JavaScript chez Dunod
https://www.toutjavascript.com/livre/index.php

Jpe54
Messages : 68
Enregistré le : 10 mars 2017, 14:11

Re: Blocage sur codage d'un fichier ASCII de structure Tomtom OV2

Message par Jpe54 » 15 mai 2024, 12:03

Bonjour,

Merci de votre réponse mais ce n'est pas utilisable dcar un fichier OV2 accepte tous les caractères ASCII, de fait il faut pouvoir écrire et restituer toute la gamme étendue, dont les é è ë ê et à.

Je continue mes recherches...

Avatar du membre
webmaster
Administrateur du site
Messages : 611
Enregistré le : 28 févr. 2017, 15:19

Re: Blocage sur codage d'un fichier ASCII de structure Tomtom OV2

Message par webmaster » 15 mai 2024, 13:52

Alors je n'ai pas compris le point 1 "de manière à n'avoir qu'un seul code Hexadécimal pour les caractères accentués"
TJS : 25 ans et mon livre Tout JavaScript chez Dunod
https://www.toutjavascript.com/livre/index.php

Jpe54
Messages : 68
Enregistré le : 10 mars 2017, 14:11

Re: Blocage sur codage d'un fichier ASCII de structure Tomtom OV2

Message par Jpe54 » 08 juin 2024, 08:31

En fait le décodage de la chaine texte est à faire avec les codes caractères...

Code : Tout sélectionner

// Suite de la portion de code proposé après codage des coordonnées de latitude...
// Décodage des codes caractère de la chaine name
let nameBytes = [];
for (let j = 0; j < name.length; j++) {
    let charCode = name.charCodeAt(j);
    nameBytes.push(charCode);
    view.setUint8(13 + j, nameBytes[j]);
}
// Caractère nul de fin
view.setUint8(13 + nameBytes.length, 0);
// Convertion du tableau tampon en une chaîne hexadécimale
for (let k = 0; k < buffer.byteLength; k++) {
    result += view.getUint8(k).toString(16).padStart(2, "0");
}

//    Remettre en service dans le code complet >  }

// Encodage hexToAscii en texte ASCII attendu comme fichier PI TomTom OV2
for (let l = 0; l < result.length; l += 2) {
    const charCode = parseInt(result.substr(l, 2), 16);
    str += String.fromCharCode(charCode);
}
// Créez un tableau d'octets à partir de la chaîne de caractères
const byteArray = new Uint8Array(str.length);
for (let m = 0; m < str.length; m++) {
    byteArray[m] = str.charCodeAt(m) & 0xff;
}
// Créez un Blob IMPRATIVEMENT encodage Windows-1252 (ANSI)
const blob = new Blob([byteArray], { type: "text/plain;charset=windows-1252" });

// Ici Proposer téléchargement du fichier blob ainsi codé en utilisant API fileLayer HTML5 
Bon usage de ces informations.

elenagilbert
Messages : 3
Enregistré le : 23 août 2024, 05:12

Re: Blocage sur codage d'un fichier ASCII de structure Tomtom OV2

Message par elenagilbert » 23 août 2024, 05:17

Que diriez-vous d'utiliser normalize('NFKC') pour convertir les caractères Unicode en leurs formes compatibles avant l'encodage?
Retro Bowl College

Oliviajsdkf
Messages : 3
Enregistré le : 01 avr. 2024, 05:20

Re: Blocage sur codage d'un fichier ASCII de structure Tomtom OV2

Message par Oliviajsdkf » 06 nov. 2024, 02:39

function toHexString(byteArray) {
return Array.from(byteArray)
.map(b => ('0' + b.toString(16)).slice(-2))
.join(' ').toUpperCase();
}

function createOV2Entry(longitude, latitude, name) {
const type = 2; // Type fixe
const nameBytes = new TextEncoder().encode(name);
const nullByte = new Uint8Array([0]);

// Calcul de la longueur de l'enregistrement
const recordLength = 1 + 4 + 4 + 13 + 1; // T + L + Longitude + Latitude + Nom + NUL
const longitudeInt = Math.round(longitude * 100000);
const latitudeInt = Math.round(latitude * 100000);
temple run 2
const buffer = new Uint8Array(recordLength);

buffer[0] = type; // Type
buffer.set(new Uint32Array([recordLength]), 1); // Longueur
buffer.set(new Uint32Array([longitudeInt]), 5); // Longitude
buffer.set(new Uint32Array([latitudeInt]), 9); // Latitude
buffer.set(nameBytes, 13); // Nom
buffer.set(nullByte, 13 + nameBytes.length); // NUL

return toHexString(buffer);
}

// Exemple d'utilisation
const entry = createOV2Entry(-3.9999, 48.9999, "Moulin à Marée (Trégastel)");
console.log(entry);

Répondre