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(" ");
}