Skip to content

Commit

Permalink
Merge pull request #90 from IGNF/develop
Browse files Browse the repository at this point in the history
Merge develop into master to create a 2.2.1
  • Loading branch information
azarz authored Sep 14, 2023
2 parents db5306b + 567579a commit 8ef3adf
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 46 deletions.
28 changes: 16 additions & 12 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# CHANGELOG

FIXED:
- Wrong geometry order on pgr results #88
- BBox check not working with negative coordinates #89

## 2.2.0

CHANGED:
Expand All @@ -10,12 +14,12 @@ CHANGED:

ADDED:
- A Github PR template was added
- A code of conduct was adapted from the contributor covenant
- A code of conduct was adapted from the contributor covenant
- A contributing was added

## 2.1.1

CHANGED:
CHANGED:
- reference de la doc à la branche master
- modification de la ci github pour prendre en compte la branche master

Expand All @@ -33,28 +37,28 @@ ADDED:
- Il est maintenant possible démarrer un administrateur sans services pré-configurés

CHANGED:
- La documentation de l'API d'administration a été grandement enrichie.
- La documentation de l'API d'administration a été grandement enrichie.
- La route /health a une réponse plus complète et est vraiment codée pour prendre en compte l'état de chaque service et chaque source disponibles.
- Les dossiers de sources et de resources des services peuvent maintenant être vide à l'initialisation.
- Les dossiers de sources et de resources des services peuvent maintenant être vide à l'initialisation.

DELETED:
- L'option onStart de la configuration admin est supprimée
- L'option onStart de la configuration admin est supprimée

## 2.0.0

ADDED:
- La classe Administrator permet de gérer le service via une API. Notamment la création, la suppression et la modification d'un service seront possible.
- Cette classe est configurée par un nouveau fichier de configuration.
- Les classes service* sont des interfaces pour permettre à l'administrateur de gérer les services associés. Elles permettent de gérer un service dans le même processus ou dans un nouveau (méthode conseillée).
- La classe Administrator permet de gérer le service via une API. Notamment la création, la suppression et la modification d'un service seront possible.
- Cette classe est configurée par un nouveau fichier de configuration.
- Les classes service* sont des interfaces pour permettre à l'administrateur de gérer les services associés. Elles permettent de gérer un service dans le même processus ou dans un nouveau (méthode conseillée).
- Ajout du moteur Valhalla pour les itinéraires et les isochrones
- Le module `wkt` a été remplacé par une implémentation interne
- Le format wkt est disponible pour le paramètre geometryFormat de l'API simple/1.0.0

CHANGED:
- L'option --configCheck au démarrage de Road2 n'a plus exactement le même comportement.
- Le fichier server.json permet maintenant de configurer l'administrateur et donc n'a plus le même contenu. Ce dernier est dans service.json.
- Les sources ne sont plus configurées dans le même fichier que les ressources. Chaque source est configurée dans son fichier. L'ensemble est placé dans un dossier de sources. Il peut y en avoir plusieurs.
- Les sources PGRouting et Valhalla ne sont plus configurées de la même manière : chaque source de ces types peut contenir plusieurs coûts.
- L'option --configCheck au démarrage de Road2 n'a plus exactement le même comportement.
- Le fichier server.json permet maintenant de configurer l'administrateur et donc n'a plus le même contenu. Ce dernier est dans service.json.
- Les sources ne sont plus configurées dans le même fichier que les ressources. Chaque source est configurée dans son fichier. L'ensemble est placé dans un dossier de sources. Il peut y en avoir plusieurs.
- Les sources PGRouting et Valhalla ne sont plus configurées de la même manière : chaque source de ces types peut contenir plusieurs coûts.

FIXED:
- Les reprojections des isochrones fonctionnent
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "road2",
"version": "2.2.0",
"version": "2.2.1",
"description": "Calcul d'itinéraire",
"author": "RDEV - IGN",
"main": "src/js/road2.js",
Expand Down
28 changes: 14 additions & 14 deletions src/js/geography/projectionManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ module.exports = class ProjectionManager {
* @function
* @name isProjectionLoaded
* @description Savoir si une projection est disponible dans l'instance de proj4
* @param {string} id - ID de la projection
* @param {string} id - ID de la projection
*
*/
isProjectionLoaded (id) {
Expand All @@ -93,7 +93,7 @@ module.exports = class ProjectionManager {
* @function
* @name getProjectionParameters
* @description Récupérer les paramètres d'une projection
* @param {string} id - ID de la projection
* @param {string} id - ID de la projection
*
*/
getProjectionParameters (id) {
Expand All @@ -107,7 +107,7 @@ module.exports = class ProjectionManager {
* @function
* @name isProjectionChecked
* @description Savoir si une projection a été validé durant l'étape de vérification
* @param {string} id - ID de la projection
* @param {string} id - ID de la projection
*
*/
isProjectionChecked (id) {
Expand Down Expand Up @@ -171,12 +171,12 @@ module.exports = class ProjectionManager {
return false;
}

if (bboxArray[1] >= bboxArray[3]) {
if (Number(bboxArray[1]) >= Number(bboxArray[3])) {
LOGGER.error("Mauvaise configuration : Xmin est supérieur ou égal à Xmax");
return false;
}

if (bboxArray[2] >= bboxArray[4]) {
if (Number(bboxArray[2]) >= Number(bboxArray[4])) {
LOGGER.error("Mauvaise configuration : Ymin est supérieur ou égal à Ymax");
return false;
}
Expand All @@ -191,7 +191,7 @@ module.exports = class ProjectionManager {
* @function
* @name checkProjectionDirectory
* @description Vérifier les projections d'un dossier
* @param {string} projectionDirectory - Chemin absolu d'un dossier de projections
* @param {string} projectionDirectory - Chemin absolu d'un dossier de projections
*
*/
checkProjectionDirectory(projectionDirectory) {
Expand Down Expand Up @@ -230,7 +230,7 @@ module.exports = class ProjectionManager {

} else {
LOGGER.fatal("Mauvaise configuration: Dossier de projections inexistant : " + projectionDirectory);
return false;
return false;
}

}
Expand All @@ -241,7 +241,7 @@ module.exports = class ProjectionManager {
* @function
* @name checkProjectionFile
* @description Vérifier les projections d'un fichier
* @param {string} projectionFile - Chemin absolu d'un fichier de projections
* @param {string} projectionFile - Chemin absolu d'un fichier de projections
*
*/
checkProjectionFile(projectionFile) {
Expand Down Expand Up @@ -308,7 +308,7 @@ module.exports = class ProjectionManager {
if (!configuration) {
LOGGER.error("La configuration de la projection est vide");
return false;
}
}

// id de la projection
if (!configuration.id) {
Expand All @@ -323,7 +323,7 @@ module.exports = class ProjectionManager {
LOGGER.error("La configuration de la projection n'a pas de parametres");
return false;
} else {

if (typeof configuration.parameters !== "string") {
LOGGER.error("Les parametres de la projection ne sont pas une string");
return false;
Expand Down Expand Up @@ -361,7 +361,7 @@ module.exports = class ProjectionManager {
*
* @function
* @name flushCheckedProjection
* @description Vider la liste des projections déjà vérifiées
* @description Vider la liste des projections déjà vérifiées
*
*/
flushCheckedProjection() {
Expand Down Expand Up @@ -401,12 +401,12 @@ module.exports = class ProjectionManager {
if (!Array.isArray(contentDir)) {
LOGGER.error("Erreur lors de la lecture du dossier " + directory);
return false;
}
}

if (contentDir.length === 0) {
LOGGER.error("Le dossier " + directory + " ne contient aucun fichier.");
return false;
}
}

for (let i = 0; i < contentDir.length; i++) {
let pathFile = directory + "/" + contentDir[i];
Expand Down Expand Up @@ -501,7 +501,7 @@ module.exports = class ProjectionManager {
if (!configuration) {
LOGGER.error("La configuration de la projection est vide");
return false;
}
}

// id de la projection
if (!configuration.id) {
Expand Down
65 changes: 46 additions & 19 deletions src/js/sources/pgrSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,27 +43,27 @@ module.exports = class pgrSource extends Source {

// Constructeur parent
super(sourceJsonObject.id, "pgr", sourceJsonObject.description, sourceJsonObject.projection, sourceJsonObject.bbox);

// Stockage de la configuration
this._configuration = sourceJsonObject;

// Base de données PGRouting
this._base = base;

// Schéma contenant les données dans la base
// Schéma contenant les données dans la base
this._schema = sourceJsonObject.storage.base.schema;

// Attributs par défaut sur les voies dans la base
// Attributs par défaut sur les voies dans la base
this._defaultAttributes = new Array();

// Attributs disponibles sur les voies dans la base
// Attributs disponibles sur les voies dans la base
this._otherAttributes = new Array();

// Coûts disponibles
// Coûts disponibles
this._costs = {};

// TODO : à l'exemple des ressources, faire une fonction init() pour chaque source appelée dans le sourceManager
// --
// --
if (sourceJsonObject.storage.base.attributes) {

// Création des tableaux d'attributs
Expand Down Expand Up @@ -91,7 +91,7 @@ module.exports = class pgrSource extends Source {

}

// Initialisation des coûts disponibles
// Initialisation des coûts disponibles
for (let i = 0; i < sourceJsonObject.costs.length; i++) {
if (!this._costs[sourceJsonObject.costs[i].profile]) {
Object.defineProperty(this._costs, sourceJsonObject.costs[i].profile, { value: new Object(), configurable: true, enumerable: true, writable: true });
Expand All @@ -104,7 +104,7 @@ module.exports = class pgrSource extends Source {
Object.defineProperty(this._costs[sourceJsonObject.costs[i].profile][sourceJsonObject.costs[i].costType], "rcostColumn", { value: sourceJsonObject.costs[i].rcostColumn, configurable: true, enumerable: true, writable: true });
}

// --
// --

}

Expand Down Expand Up @@ -247,7 +247,7 @@ module.exports = class pgrSource extends Source {
pgrRequest.coordinates = coordinatesTable;

// --- waysAttributes
// attributes est déjà vide, on met les attributs par défaut s'il y en a
// attributes est déjà vide, on met les attributs par défaut s'il y en a
if (this._defaultAttributes.length !== 0) {
attributes = this._defaultAttributesString;
LOGGER.debug("default attributes: " + attributes);
Expand All @@ -258,7 +258,7 @@ module.exports = class pgrSource extends Source {

// S'il existe des attributs disponibles mais non par défaut, on complète avec les attributs demandés
if (this._otherAttributes.length !== 0 ) {

// TODO : refaire cette partie, et donc la manière dont l'info est stockée dans la classe
if (request.waysAttributes.length !== 0) {
let requestedAttributes = new Array();
Expand Down Expand Up @@ -470,7 +470,7 @@ module.exports = class pgrSource extends Source {
}

const queryString = `SELECT * FROM ${this._schema}.generateIsochrone(ARRAY ${point}, $1, $2, $3, $4, $5)`;

const SQLParametersTable = [
request.costValue,
request.direction,
Expand Down Expand Up @@ -791,6 +791,10 @@ module.exports = class pgrSource extends Source {
turf.lineSlice(legStart, legStop, leg.geometry),
{precision: 6}
).geometry.coordinates;
// Reverse geometry order if end point closer to start of geometry than end
if (turf.distance(legStart, turf.point(leg.geometry.coordinates[0]) > turf.distance(legStop, turf.point(leg.geometry.coordinates[0])))) {
leg.geometry.coordinates.reverse();
}

routeGeometry.coordinates.push(...leg.geometry.coordinates);
}
Expand Down Expand Up @@ -912,6 +916,14 @@ module.exports = class pgrSource extends Source {
{precision: 6}
).geometry.coordinates;

// Reverse geometry order if end point closer to start of geometry than end
if (
turf.distance(stepStart, turf.point(currentPgrRouteStep.geometry.coordinates[0]) >
turf.distance(stepEnd, turf.point(currentPgrRouteStep.geometry.coordinates[0])))
) {
currentPgrRouteStep.geometry.coordinates.reverse();
}

// On n'enlève les valeurs dupliquées que si la linestring est plus longue que 2 points
if (currentPgrRouteStep.geometry.coordinates.length > 2) {
currentPgrRouteStep.geometry.coordinates = turf.cleanCoords(currentPgrRouteStep.geometry).coordinates
Expand All @@ -921,17 +933,25 @@ module.exports = class pgrSource extends Source {
// Troncature de la géométrie : cas de début de leg
else if (k === 0){
let stepStart = turf.point(response.waypoints[j].location);
let stepEnd = turf.point(gisManager.arraysIntersection(
currentPgrRouteLeg.steps[k + 1].geometry.coordinates,
currentPgrRouteStep.geometry.coordinates
)[0]);
currentPgrRouteStep.geometry.coordinates = turf.truncate(
turf.lineSlice(
stepStart,
gisManager.arraysIntersection(
currentPgrRouteLeg.steps[k + 1].geometry.coordinates,
currentPgrRouteStep.geometry.coordinates
)[0],
stepEnd,
currentPgrRouteStep.geometry
),
{precision: 6}
).geometry.coordinates;
// Reverse geometry order if end point closer to start of geometry than end
if (
turf.distance(stepStart, turf.point(currentPgrRouteStep.geometry.coordinates[0]) >
turf.distance(stepEnd, turf.point(currentPgrRouteStep.geometry.coordinates[0])))
) {
currentPgrRouteStep.geometry.coordinates.reverse();
}

// On n'enlève les valeurs dupliquées que si la linestring est plus longue que 2 points
if (currentPgrRouteStep.geometry.coordinates.length > 2) {
Expand Down Expand Up @@ -988,10 +1008,17 @@ module.exports = class pgrSource extends Source {
turf.lineSlice(
common_point,
stepEnd,
currentPgrRouteStep.geometry
currentPgrRouteStep.geometry
),
{precision: 6}
).geometry.coordinates;
// Reverse geometry order if end point closer to start of geometry than end
if (
turf.distance(common_point, turf.point(currentPgrRouteStep.geometry.coordinates[0]) >
turf.distance(stepEnd, turf.point(currentPgrRouteStep.geometry.coordinates[0])))
) {
currentPgrRouteStep.geometry.coordinates.reverse();
}

// On n'enlève les valeurs dupliquées que si la linestring est plus longue que 2 points
if (currentPgrRouteStep.geometry.coordinates.length > 2) {
Expand Down Expand Up @@ -1105,15 +1132,15 @@ module.exports = class pgrSource extends Source {
LOGGER.debug(point);
}

let rawGeometry = null;
let rawGeometry = null;

try {
rawGeometry = JSON.parse(pgrResponse.rows[0].geometry);
} catch(error) {
LOGGER.debug(error);
throw errorManager.createError("Impossible de parser la réponse de PGRouting");
}

// Création d'un objet Polygon à partir de la géométrie brute
if (rawGeometry === null) {
// Potentiellement le cas où il n'y a pas d'isochrone car costValue trop faible
Expand Down

0 comments on commit 8ef3adf

Please sign in to comment.