mirror of
https://gitlab.com/mobicoop/v3/service/matcher.git
synced 2026-01-01 14:22:40 +00:00
add graphhopper georouter
This commit is contained in:
139
src/modules/geography/infrastructure/graphhopper-georouter.ts
Normal file
139
src/modules/geography/infrastructure/graphhopper-georouter.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { HttpService } from '@nestjs/axios';
|
||||
import { GeorouterPort } from '../core/application/ports/georouter.port';
|
||||
import { GeorouterSettings } from '../core/application/types/georouter-settings.type';
|
||||
import { Path, PathType, Route } from '../core/domain/route.types';
|
||||
import { DefaultParamsProviderPort } from '../core/application/ports/default-params-provider.port';
|
||||
import { PARAMS_PROVIDER } from '../geography.di-tokens';
|
||||
import { catchError, lastValueFrom, map } from 'rxjs';
|
||||
import { AxiosError, AxiosResponse } from 'axios';
|
||||
import {
|
||||
GeorouterUnavailableException,
|
||||
RouteNotFoundException,
|
||||
} from '../core/domain/route.errors';
|
||||
|
||||
@Injectable()
|
||||
export class GraphhopperGeorouter implements GeorouterPort {
|
||||
private url: string;
|
||||
private urlArgs: string[];
|
||||
|
||||
constructor(
|
||||
private readonly httpService: HttpService,
|
||||
@Inject(PARAMS_PROVIDER)
|
||||
private readonly defaultParamsProvider: DefaultParamsProviderPort,
|
||||
) {
|
||||
this.url = defaultParamsProvider.getParams().GEOROUTER_URL;
|
||||
}
|
||||
|
||||
routes = async (
|
||||
paths: Path[],
|
||||
settings: GeorouterSettings,
|
||||
): Promise<Route[]> => {
|
||||
this.setDefaultUrlArgs();
|
||||
this.setSettings(settings);
|
||||
return [
|
||||
{
|
||||
type: PathType.DRIVER,
|
||||
distance: 1000,
|
||||
duration: 1000,
|
||||
fwdAzimuth: 280,
|
||||
backAzimuth: 100,
|
||||
distanceAzimuth: 900,
|
||||
points: [],
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
private setDefaultUrlArgs = (): void => {
|
||||
this.urlArgs = ['vehicle=car', 'weighting=fastest', 'points_encoded=false'];
|
||||
};
|
||||
|
||||
private setSettings = (settings: GeorouterSettings): void => {
|
||||
if (settings.detailedDuration) {
|
||||
this.urlArgs.push('details=time');
|
||||
}
|
||||
if (settings.detailedDistance) {
|
||||
this.urlArgs.push('instructions=true');
|
||||
} else {
|
||||
this.urlArgs.push('instructions=false');
|
||||
}
|
||||
if (!settings.points) {
|
||||
this.urlArgs.push('calc_points=false');
|
||||
}
|
||||
};
|
||||
|
||||
private getRoutes = async (paths: Path[]): Promise<Route[]> => {
|
||||
const routes = Promise.all(
|
||||
paths.map(async (path) => {
|
||||
const url: string = [
|
||||
this.getUrl(),
|
||||
'&point=',
|
||||
path.points
|
||||
.map((point) => [point.lat, point.lon].join('%2C'))
|
||||
.join('&point='),
|
||||
].join('');
|
||||
const route = await lastValueFrom(
|
||||
this.httpService.get(url).pipe(
|
||||
map((res) =>
|
||||
res.data ? this.createRoute(res, path.type) : undefined,
|
||||
),
|
||||
catchError((error: AxiosError) => {
|
||||
if (error.code == AxiosError.ERR_BAD_REQUEST) {
|
||||
throw new RouteNotFoundException(
|
||||
error,
|
||||
'No route found for given coordinates',
|
||||
);
|
||||
}
|
||||
throw new GeorouterUnavailableException(error);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return route;
|
||||
}),
|
||||
);
|
||||
return routes;
|
||||
};
|
||||
|
||||
private getUrl = (): string => [this.url, this.urlArgs.join('&')].join('');
|
||||
|
||||
private createRoute = (
|
||||
response: AxiosResponse<GraphhopperResponse>,
|
||||
type: PathType,
|
||||
): Route => undefined;
|
||||
}
|
||||
|
||||
type GraphhopperResponse = {
|
||||
paths: [
|
||||
{
|
||||
distance: number;
|
||||
weight: number;
|
||||
time: number;
|
||||
points_encoded: boolean;
|
||||
bbox: number[];
|
||||
points: GraphhopperCoordinates;
|
||||
snapped_waypoints: GraphhopperCoordinates;
|
||||
details: {
|
||||
time: number[];
|
||||
};
|
||||
instructions: GraphhopperInstruction[];
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
type GraphhopperCoordinates = {
|
||||
coordinates: number[];
|
||||
};
|
||||
|
||||
type GraphhopperInstruction = {
|
||||
distance: number;
|
||||
heading: number;
|
||||
sign: GraphhopperSign;
|
||||
interval: number[];
|
||||
text: string;
|
||||
};
|
||||
|
||||
enum GraphhopperSign {
|
||||
SIGN_START = 0,
|
||||
SIGN_FINISH = 4,
|
||||
SIGN_WAYPOINT = 5,
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Coordinates } from '../core/application/types/coordinates.type';
|
||||
import { DirectionEncoderPort } from '../core/application/ports/direction-encoder.port';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Coordinates } from '../core/domain/route.types';
|
||||
|
||||
@Injectable()
|
||||
export class PostgresDirectionEncoder implements DirectionEncoderPort {
|
||||
|
||||
Reference in New Issue
Block a user