2023-08-13 23:12:01 +02:00
|
|
|
/**
|
|
|
|
conversion de données gpx
|
|
|
|
conversion de données exif
|
|
|
|
**/
|
|
|
|
import * as fs from 'node:fs';
|
2023-08-14 09:39:49 +02:00
|
|
|
// @ts-ignore
|
|
|
|
import path from "node:path";
|
2023-08-14 10:33:57 +02:00
|
|
|
// @ts-ignore
|
2023-08-14 09:39:49 +02:00
|
|
|
import minimist from 'minimist';
|
2023-08-13 23:12:01 +02:00
|
|
|
|
2023-08-14 09:39:49 +02:00
|
|
|
// configs
|
|
|
|
let sequence_name: string = '3596977'
|
2023-08-14 12:22:05 +02:00
|
|
|
let folders_list_txt: any = [
|
|
|
|
// "3596249",
|
2023-08-14 10:33:57 +02:00
|
|
|
// "3596253", "3596977",
|
|
|
|
// "3675557", "3675577", "3716345", "4456921", "4457241", "4457257", "4457273", "4457289", "4457689", "4457705", "4539913", "4539929", "4539945", "4559529",
|
|
|
|
// "4559545", "4559561", "4559577", "4559593", "4559609", "4559625", "4559641", "4559657", "4559673", "4559689", "4559705", "4559721", "4559737", "4559753",
|
|
|
|
// "4559769", "4559785", "4559801", "4559817", "4559833", "4559849", "4559865", "4904153", "4904233", "4904249", "4904265", "4904281", "4904297", "4904313",
|
|
|
|
// "4904329", "4904345", "4904361", "4904377", "4904393", "5192937", "5193161", "5193177", "5193193", "5193209", "5193225", "5193321", "5193337", "5193417",
|
|
|
|
// "5193433", "5193449", "5201385", "5213385", "5213481", "5213529", "5234665", "5234857", "5234889", "5235001", "5324265", "5775977", "5775993", "5776009",
|
|
|
|
// "5776025", "6081417", "6081433", "6081449", "6081465", "6081689", "6081705", "6092281", "6092313", "6101305", "6102457", "6102473", "6102489", "6102521",
|
|
|
|
// "6102537", "6102569", "6127433", "6133465", "6242729", "6329129", "6329177", "6329241", "6329305", "6329321", "6738633", "6738809", "6738953", "6752761",
|
2023-08-14 12:22:05 +02:00
|
|
|
// "6752889",
|
|
|
|
// "6752905",
|
2023-08-14 16:25:24 +02:00
|
|
|
"6752921",
|
2023-08-14 12:22:05 +02:00
|
|
|
"6752937",
|
|
|
|
// "6752953", "6760985", "6761049", "6761289", "6794633", "7325929", "7326457", "7328265", "7330009", "7330025",
|
2023-08-14 10:33:57 +02:00
|
|
|
// "7330041",
|
2023-08-14 12:22:05 +02:00
|
|
|
// "7330057"
|
|
|
|
]
|
2023-08-14 12:47:17 +02:00
|
|
|
|
|
|
|
let enable_write_gpx_file = true;
|
2023-08-14 10:33:57 +02:00
|
|
|
let folder = "/home/poule/encrypted/stockage-syncable/photos/imagerie kartaview carto tel/kartaview_export_storage/share2tykayn/"
|
2023-08-14 12:22:05 +02:00
|
|
|
let dossier_gpx: string = "./output_gpx"
|
2023-08-14 10:33:57 +02:00
|
|
|
let file_gpx: string = "3596249_d875a_60a0f9bf38f99.txt"
|
2023-08-13 23:12:01 +02:00
|
|
|
|
2023-08-14 10:33:57 +02:00
|
|
|
let mini_arguments: any = minimist(process.argv.slice(2))
|
2023-08-14 09:39:49 +02:00
|
|
|
console.log('mini_arguments', mini_arguments)
|
|
|
|
|
2023-08-14 10:33:57 +02:00
|
|
|
if (mini_arguments['sequence']) {
|
2023-08-14 09:39:49 +02:00
|
|
|
sequence_name = mini_arguments['sequence']
|
|
|
|
}
|
2023-08-14 10:33:57 +02:00
|
|
|
if (mini_arguments['folder']) {
|
|
|
|
folder = mini_arguments['folder']
|
|
|
|
}
|
|
|
|
if (mini_arguments['gpx-output']) {
|
|
|
|
dossier_gpx = mini_arguments['gpx-output']
|
|
|
|
}
|
|
|
|
if (mini_arguments['gpx-input']) {
|
|
|
|
file_gpx = mini_arguments['gpx-input']
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let dossier_photo: string = folder + "photo"
|
|
|
|
let dossier_gpx_input: string = folder + "metadata_file"
|
|
|
|
let path_gpx_input: string = dossier_gpx_input + "/" + sequence_name + "/" + file_gpx
|
|
|
|
|
|
|
|
if (mini_arguments['gpx-input-path']) {
|
|
|
|
path_gpx_input = mini_arguments['gpx-input-path']
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let gpxData: any = {}
|
|
|
|
let tableKartaviewTrace: any = []
|
|
|
|
|
2023-08-13 23:12:01 +02:00
|
|
|
|
2023-08-14 10:33:57 +02:00
|
|
|
function makeGpxFromKartaview(tableKartaviewTrace: any) {
|
|
|
|
|
|
|
|
console.log('make gpx')
|
2023-08-14 09:39:49 +02:00
|
|
|
let track_points: string = '';
|
2023-08-14 12:47:17 +02:00
|
|
|
|
2023-08-13 23:12:01 +02:00
|
|
|
tableKartaviewTrace.forEach((elem: any) => {
|
2023-08-14 16:25:24 +02:00
|
|
|
// console.log('elem', elem)
|
|
|
|
// console.log('elem', elem[6] *1000)
|
|
|
|
let utc_time = new Date(elem[6] * 1000)
|
2023-08-14 12:47:17 +02:00
|
|
|
|
2023-08-14 16:25:24 +02:00
|
|
|
// console.log('utc_time', utc_time.toISOString())
|
2023-08-14 09:39:49 +02:00
|
|
|
track_points = `${track_points}<trkpt lat="${elem[0]}" lon="${elem[1]}">
|
2023-08-14 12:47:17 +02:00
|
|
|
<ele>${elem[2]}</ele>
|
|
|
|
<time>${utc_time.toISOString()}</time>
|
2023-08-14 09:39:49 +02:00
|
|
|
</trkpt>
|
|
|
|
`
|
2023-08-13 23:12:01 +02:00
|
|
|
})
|
|
|
|
|
2023-08-14 09:39:49 +02:00
|
|
|
let content = `<?xml version='1.0' encoding='UTF-8'?>
|
|
|
|
<gpx version="1.1" creator="JOSM GPX export" xmlns="http://www.topografix.com/GPX/1/1"
|
|
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
|
|
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
|
|
|
|
<metadata>
|
|
|
|
<desc>trace_gpx_de_demo</desc>
|
|
|
|
<author>
|
|
|
|
<name>somebody</name>
|
|
|
|
</author>
|
|
|
|
<copyright author="somebody">
|
|
|
|
<year>2023</year>
|
|
|
|
<license>https://creativecommons.org/licenses/by-sa/2.5</license>
|
|
|
|
</copyright>
|
|
|
|
<keywords>nada</keywords>
|
|
|
|
</metadata>
|
|
|
|
<trk>
|
|
|
|
<trkseg>
|
|
|
|
${track_points}
|
|
|
|
</trkseg>
|
|
|
|
</trk>
|
|
|
|
</gpx>`
|
2023-08-13 23:12:01 +02:00
|
|
|
|
|
|
|
return content;
|
|
|
|
}
|
|
|
|
|
2023-08-14 16:25:24 +02:00
|
|
|
function reduceGpxPointsToInterval(sequence_name: any) {
|
|
|
|
|
|
|
|
let photos_count_in_sequence = photo_folders_counter[sequence_name].length
|
|
|
|
let interval = Math.round(gpxData[sequence_name].length / photos_count_in_sequence)
|
|
|
|
let ii = 1;
|
|
|
|
console.log('--------- sequence_name', sequence_name)
|
2023-08-14 16:31:58 +02:00
|
|
|
console.log('--------- interval: prendre une donnée gps tous les ', interval, 'points de la trace de séquence')
|
|
|
|
let jj=0
|
|
|
|
let photo_counter = 0
|
|
|
|
gpxData[sequence_name].forEach((elem: any) => {
|
|
|
|
// only work on an interval of files to assign gps coordinates
|
|
|
|
jj++
|
|
|
|
ii--
|
|
|
|
if(ii<=0){
|
|
|
|
// set the gps coordinates to the picture in sequence
|
|
|
|
let timestamp = elem[6] * 1000
|
|
|
|
let lat = elem[0]
|
|
|
|
let lon = elem[1]
|
|
|
|
let date = new Date(timestamp)
|
|
|
|
let iso = date.toISOString()
|
|
|
|
console.log('* point de trace n°', jj)
|
|
|
|
console.log('* lat, lon', lat,lon)
|
|
|
|
console.log('* date iso', iso)
|
|
|
|
ii =interval*1
|
|
|
|
photo_counter++
|
|
|
|
|
|
|
|
let file_photo_name = photo_folders_counter[sequence_name][photo_counter]
|
|
|
|
console.log('file_photo_name to apply exif data', file_photo_name)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
2023-08-14 16:32:17 +02:00
|
|
|
console.log('DONE for sequence_name', sequence_name)
|
2023-08-14 16:25:24 +02:00
|
|
|
}
|
2023-08-13 23:12:01 +02:00
|
|
|
|
2023-08-14 16:25:24 +02:00
|
|
|
function openKartaviewTxtGPX(filepath: any, sequence_name: string) {
|
2023-08-14 10:33:57 +02:00
|
|
|
console.log('filepath', filepath)
|
2023-08-14 12:22:05 +02:00
|
|
|
let boom = filepath.split('/')
|
|
|
|
let fileName = boom[boom.length - 1]
|
|
|
|
console.log('fileName', fileName)
|
2023-08-13 23:12:01 +02:00
|
|
|
fs.readFile(filepath, 'utf8', (err, data) => {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
const gpx_content = data;
|
|
|
|
let lines = gpx_content.split('\n')
|
|
|
|
console.log('lines.length', lines.length)
|
2023-08-14 09:39:49 +02:00
|
|
|
|
2023-08-14 10:33:57 +02:00
|
|
|
let tableKartaviewTrace: any = [];
|
|
|
|
|
2023-08-14 09:39:49 +02:00
|
|
|
// loop on all lines, only take the lines that contain :g:
|
2023-08-13 23:12:01 +02:00
|
|
|
lines.forEach((elem: any) => {
|
|
|
|
if (elem.indexOf(":g:") > -1) {
|
2023-08-14 09:39:49 +02:00
|
|
|
// do stuff on gpxData to enrich it
|
2023-08-13 23:12:01 +02:00
|
|
|
let boom = elem.split(':')
|
2023-08-14 12:47:17 +02:00
|
|
|
let timestamp = boom[0]
|
|
|
|
|
2023-08-13 23:12:01 +02:00
|
|
|
let gpsmodel = boom[2]
|
|
|
|
let gps = gpsmodel.split(';')
|
2023-08-14 12:47:17 +02:00
|
|
|
gps.push(timestamp)
|
2023-08-13 23:12:01 +02:00
|
|
|
tableKartaviewTrace.push(gps)
|
2023-08-14 16:25:24 +02:00
|
|
|
// let date = new Date(boom[0] * 1000)
|
2023-08-14 12:22:05 +02:00
|
|
|
// console.log('*', date, gps[0], gps[1])
|
2023-08-13 23:12:01 +02:00
|
|
|
}
|
|
|
|
})
|
2023-08-14 16:25:24 +02:00
|
|
|
gpxData[sequence_name] = [...tableKartaviewTrace]
|
|
|
|
|
|
|
|
|
|
|
|
// console.log('gpxData', gpxData)
|
2023-08-14 10:33:57 +02:00
|
|
|
let content_gpx = makeGpxFromKartaview(tableKartaviewTrace)
|
2023-08-13 23:12:01 +02:00
|
|
|
|
2023-08-14 12:47:17 +02:00
|
|
|
|
|
|
|
if (enable_write_gpx_file) {
|
|
|
|
|
|
|
|
writeFile('' + fileName + '_trace.gpx', content_gpx)
|
|
|
|
}
|
2023-08-14 16:25:24 +02:00
|
|
|
if(Object.keys(gpxData).length === folders_list_txt.length){
|
|
|
|
gather()
|
|
|
|
}
|
2023-08-13 23:12:01 +02:00
|
|
|
// console.log('gpx_content', gpx_content)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-08-14 09:39:49 +02:00
|
|
|
let cwd = path.dirname(process.cwd()) + '/' + path.basename(process.cwd())
|
|
|
|
|
|
|
|
let expandedFileList: any = []
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get a list of all files in a path
|
|
|
|
* @param folderPath
|
|
|
|
*/
|
2023-08-14 10:33:57 +02:00
|
|
|
async function getAllFilesInFolder(folderPath: string) {
|
2023-08-14 09:39:49 +02:00
|
|
|
let filesList: any = []
|
|
|
|
|
2023-08-14 10:33:57 +02:00
|
|
|
console.log('reading folder ', folderPath)
|
|
|
|
filesList = fs.readdirSync(folderPath);
|
|
|
|
// console.log('readSubdirectories - files', folderPath, filesList.length)
|
|
|
|
|
|
|
|
// filesList.forEach((subDirOrFile:any) => {
|
|
|
|
// const newFullPath = cwd + '/' + subDirOrFile
|
|
|
|
//
|
|
|
|
// if (fs.existsSync(newFullPath)) {
|
|
|
|
// const s = fs.statSync(newFullPath)
|
|
|
|
//
|
|
|
|
// if (s.isFile()) {
|
|
|
|
// expandedFileList.push(cwd + '/' + subDirOrFile)
|
|
|
|
// console.log('add file', cwd + '/' + subDirOrFile)
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// })
|
|
|
|
return filesList;
|
2023-08-14 09:39:49 +02:00
|
|
|
|
2023-08-13 23:12:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function mapExifDataOnListOfFilesFromGpxData(listOfFiles: any, gpxData: any) {
|
|
|
|
listOfFiles.forEach((elem: any) => {
|
|
|
|
// find corresponding timestamp
|
|
|
|
// add exif info
|
|
|
|
// save file
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-08-14 09:39:49 +02:00
|
|
|
function writeFile(fileName: string, fileContent: any) {
|
|
|
|
console.log('write file', fileName)
|
|
|
|
return fs.writeFile(
|
|
|
|
`${dossier_gpx}/${fileName}`,
|
|
|
|
fileContent,
|
|
|
|
'utf8',
|
|
|
|
(err) => {
|
|
|
|
if (err) {
|
|
|
|
console.log(`Error writing file: ${err}`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-08-14 16:25:24 +02:00
|
|
|
let photo_folders_counter: any = {}
|
|
|
|
|
2023-08-14 12:47:17 +02:00
|
|
|
function listPhotos(sequence_number: string) {
|
|
|
|
let photo_folder = dossier_photo + '/' + sequence_number;
|
|
|
|
|
|
|
|
let gps_points = gpxData[sequence_number]
|
2023-08-14 16:25:24 +02:00
|
|
|
// console.log('gps_points', gps_points)
|
2023-08-14 12:47:17 +02:00
|
|
|
// pour réconcilier les données, on divise la trace en part égales du nombre de photos présentes dans la séquence.
|
|
|
|
|
|
|
|
getAllFilesInFolder(photo_folder)
|
2023-08-14 12:22:05 +02:00
|
|
|
.then(listOfFiles => {
|
|
|
|
|
2023-08-14 16:25:24 +02:00
|
|
|
// console.log('listOfFiles', listOfFiles)
|
|
|
|
photo_folders_counter[sequence_number] = listOfFiles
|
2023-08-14 12:22:05 +02:00
|
|
|
|
|
|
|
})
|
|
|
|
}
|
2023-08-14 09:39:49 +02:00
|
|
|
|
2023-08-14 10:33:57 +02:00
|
|
|
async function getGPXAndEnrichExifOfPhotosInFolder(sequence_number: string) {
|
|
|
|
|
|
|
|
// get metadata txt file in metadata folder
|
|
|
|
getAllFilesInFolder(dossier_gpx_input + '/' + sequence_number)
|
|
|
|
.then(listOfFiles => {
|
2023-08-14 12:47:17 +02:00
|
|
|
|
2023-08-14 10:33:57 +02:00
|
|
|
console.log('listOfFiles', listOfFiles)
|
|
|
|
listOfFiles?.forEach((file: string) => {
|
2023-08-14 16:25:24 +02:00
|
|
|
openKartaviewTxtGPX(dossier_gpx_input + '/' + sequence_number + '/' + file, sequence_number)
|
2023-08-14 12:47:17 +02:00
|
|
|
|
2023-08-14 10:33:57 +02:00
|
|
|
})
|
|
|
|
}, err => {
|
|
|
|
throw new Error(err)
|
|
|
|
})
|
|
|
|
|
2023-08-14 12:47:17 +02:00
|
|
|
listPhotos(sequence_number)
|
|
|
|
|
2023-08-14 16:25:24 +02:00
|
|
|
|
2023-08-14 10:33:57 +02:00
|
|
|
}
|
|
|
|
|
2023-08-14 12:22:05 +02:00
|
|
|
console.log('dossiers à traiter: ', folders_list_txt.length)
|
2023-08-14 10:33:57 +02:00
|
|
|
folders_list_txt.forEach((elem: string) => {
|
2023-08-14 16:25:24 +02:00
|
|
|
getGPXAndEnrichExifOfPhotosInFolder(elem).then(r => {
|
|
|
|
console.log('r', r)
|
|
|
|
}
|
|
|
|
)
|
2023-08-14 10:33:57 +02:00
|
|
|
})
|
2023-08-14 09:39:49 +02:00
|
|
|
|
2023-08-14 16:25:24 +02:00
|
|
|
|
|
|
|
function gather() {
|
|
|
|
|
|
|
|
|
|
|
|
// console.log('gpxData', gpxData)
|
|
|
|
console.log('sequences', folders_list_txt)
|
|
|
|
folders_list_txt.forEach((sequence: string) => {
|
|
|
|
|
|
|
|
reduceGpxPointsToInterval(sequence)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|