Skip to content

Commit

Permalink
Fixing compression if timestamps are not available. #701
Browse files Browse the repository at this point in the history
  • Loading branch information
bpatrik committed Aug 26, 2023
1 parent 68a033e commit 51fe554
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 36 deletions.
23 changes: 10 additions & 13 deletions src/backend/middlewares/MetaFileMWs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import {NextFunction, Request, Response} from 'express';
import * as fs from 'fs';
import {Config} from '../../common/config/private/Config';
import {GPXProcessing} from '../model/fileprocessing/GPXProcessing';
import {ErrorCodes, ErrorDTO} from '../../common/entities/Error';
import {Logger} from '../Logger';

const LOG_TAG = 'MetaFileMWs';

export class MetaFileMWs {
public static async compressGPX(
req: Request,
res: Response,
next: NextFunction
req: Request,
res: Response,
next: NextFunction
): Promise<void> {
if (!req.resultPipe) {
return next();
Expand All @@ -20,7 +22,7 @@ export class MetaFileMWs {
const fullPath = req.resultPipe as string;
try {
const compressedGPX = GPXProcessing.generateConvertedPath(
fullPath,
fullPath,
);

// check if converted photo exist
Expand All @@ -34,14 +36,9 @@ export class MetaFileMWs {
return next();
}
} catch (err) {

return next(
new ErrorDTO(
ErrorCodes.METAFILE_ERROR,
'Error during compressingGPX: ' + fullPath,
err
)
);
// Graceful degradation if compression fails
Logger.warn(LOG_TAG, 'Error during compressingGPX, using original file: ' + fullPath);
return res.redirect(req.originalUrl.slice(0, -1 * '\\bestFit'.length));
}
// not converted and won't be now
return res.redirect(req.originalUrl.slice(0, -1 * '\\bestFit'.length));
Expand Down
50 changes: 27 additions & 23 deletions src/backend/model/fileprocessing/GPXProcessing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {ProjectPath} from '../../ProjectPath';
import {Config} from '../../../common/config/private/Config';
import {SupportedFormats} from '../../../common/SupportedFormats';

type gpxEntry = { '$': { lat: string, lon: string }, ele?: string[], time: string[], extensions?: unknown };
type gpxEntry = { '$': { lat: string, lon: string }, ele?: string[], time?: string[], extensions?: unknown };

export class GPXProcessing {
private static readonly GPX_FLOAT_ACCURACY = 6;
Expand All @@ -22,24 +22,24 @@ export class GPXProcessing {

public static generateConvertedPath(filePath: string): string {
return path.join(
ProjectPath.TranscodedFolder,
ProjectPath.getRelativePathToImages(path.dirname(filePath)),
path.basename(filePath)
+ '_' + Config.MetaFile.GPXCompressing.minDistance + 'm' +
Config.MetaFile.GPXCompressing.minTimeDistance + 'ms' +
Config.MetaFile.GPXCompressing.maxMiddleDeviance + 'm' +
path.extname(filePath));
ProjectPath.TranscodedFolder,
ProjectPath.getRelativePathToImages(path.dirname(filePath)),
path.basename(filePath)
+ '_' + Config.MetaFile.GPXCompressing.minDistance + 'm' +
Config.MetaFile.GPXCompressing.minTimeDistance + 'ms' +
Config.MetaFile.GPXCompressing.maxMiddleDeviance + 'm' +
path.extname(filePath));
}

public static async isValidConvertedPath(
convertedPath: string
convertedPath: string
): Promise<boolean> {
const origFilePath = path.join(
ProjectPath.ImageFolder,
path.relative(
ProjectPath.TranscodedFolder,
convertedPath.substring(0, convertedPath.lastIndexOf('_'))
)
ProjectPath.ImageFolder,
path.relative(
ProjectPath.TranscodedFolder,
convertedPath.substring(0, convertedPath.lastIndexOf('_'))
)
);


Expand All @@ -54,7 +54,7 @@ export class GPXProcessing {


static async compressedGPXExist(
filePath: string
filePath: string
): Promise<boolean> {
// compressed gpx path
const outPath = GPXProcessing.generateConvertedPath(filePath);
Expand All @@ -70,7 +70,7 @@ export class GPXProcessing {
}

public static async compressGPX(
filePath: string,
filePath: string,
): Promise<string> {
// generate compressed gpx path
const outPath = GPXProcessing.generateConvertedPath(filePath);
Expand Down Expand Up @@ -105,8 +105,8 @@ export class GPXProcessing {
const Δλ = (lon2 - lon1) * Math.PI / 180;

const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

const d = R * c; // in metres
Expand All @@ -116,11 +116,12 @@ export class GPXProcessing {
if (i === 0 || i >= list.length - 1) { // always keep the first and last items
return true;
}
const timeDelta = (Date.parse(list[i].time[0]) - Date.parse(list[i - 1].time[0])); // mill sec.
const timeDelta = (Date.parse(list[i]?.time?.[0]) - Date.parse(list[i - 1]?.time?.[0])); // mill sec.
const dist = distance(list[i - 1], list[i]); // meters

return !(timeDelta < Config.MetaFile.GPXCompressing.minTimeDistance &&
dist < Config.MetaFile.GPXCompressing.minDistance);
// if time is not available, consider it as all points are created the same time
return !((isNaN(timeDelta) || timeDelta < Config.MetaFile.GPXCompressing.minTimeDistance) &&
dist < Config.MetaFile.GPXCompressing.minDistance);
};

const postFilter = (i: number, list: gpxEntry[]) => {
Expand All @@ -133,9 +134,11 @@ export class GPXProcessing {
$: {
lat: avg(list[i - 1].$.lat, list[i + 1].$.lat),
lon: avg(list[i - 1].$.lon, list[i + 1].$.lon)
},
time: list[i].time
}
};
if (list[i].time) {
modPoint.time = list[i].time;
}

const deviation = distance(modPoint, list[i]); // meters
return !(deviation < Config.MetaFile.GPXCompressing.maxMiddleDeviance); // keep if deviation is too big
Expand All @@ -162,6 +165,7 @@ export class GPXProcessing {
}
}
}
throw new Error('ds');
await fsp.writeFile(outPath, (new xml2js.Builder({renderOpts: {pretty: false}})).buildObject(gpxObj));

return outPath;
Expand Down

0 comments on commit 51fe554

Please sign in to comment.