Astuces DotNet (Sébastien Courtois)

24/04/2009

[Virtual Earth] Développement Microsoft Virtual Earth Web Services – Part 4 : Route Service

Filed under: .NET, Débutant, Virtual Earth — Étiquettes : , , , , , — sebastiencourtois @ 15:01

Liens des posts précédents :

  1. Introduction à Microsoft Virtual Earth (Part 1)
  2. Géocoding / Géocoding Inverse (Part 2)
  3. Récupération des images satellites (Part 3)
  4. Calcul d’itinéraires (Part 4)

Suite de notre grande exploration du Web Service Virtual Earth. Aujourd’hui, nous allons nous intéresser au calcul d’itinéraire. Cette fonctionnalité de Virtual Earth permet de calculer le trajet entre une série de point de contrôles (Waypoints). Il est possible de régler les options du calcul d’itinéraire (type de déplacement, trajet le plus rapide, le plus court …).

Comme d’habitude, il faut ajouter faire “Add Service Reference” avec l’adresse : http://staging.dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc 

Remarque : Afin de fonctionner, il est nécessaire régler certains paramètres WCF de ce service. Dans le fichier app.config (ou web.config ou encore ServiceReference.clientconfig selon le type de projet) de l’application, dans la partie contenant les Binding WCF, il faut trouver le binding lié à RouteService (en général : <binding name="BasicHttpBinding_IRouteService") puis modifier l’attribut maxReceivedMessageSize (mettre la valeur 9000000 à la place de celle par défaut) et l’attribut maxBufferSize (mettre la valeur 9000000 à la place de celle par défaut). Cela est du au fait que RouteService renvoie un nombre d’informations supérieur à ce dont WCF est habitué à manipuler.

Ce service contient une classe principale RouteServiceClient  qui contient deux méthodes :

      • CalculateRoute(RouteRequest request) : Calcul d’un itinéraire entre plusieurs points
      • CalculateRoutesFromMajorRoads(MajorRoutesRequest request) : Calcul d’itinéraires partant des routes principales vers un point d’arrivée spécifié (carte d’accès).

 


  • Calcul d’un itinéraire entre plusieurs points

Le calcul d’itinéraire entre plusieurs points à besoin de deux informations : Les points de passages et là façons de calculer le trajet. Ces deux informations sont contenues dans la classe RouteRequest qui sera passer en paramètre de la méthode CalculateRoute de RouteServiceClient.

Les points de passages doivent être fournis dans la propriété WayPoints de  RouteRequest. Cette propriété prend un tableau de WayPoint, un WayPoint n’étant composé que d’une localisation GPS (latitude/longitude/altitude) et d’une propriété Description pour donner un titre au point de passage.

Les options de calcul d’itinéraire se trouvent dans la propriété Options. Cette propriété est de type RouteOptions et contient les champs suivantes :

Nom de la propriété Description
Mode Type de déplacement.
Enumération TravelMode :
Driving : Voiture (par défaut)
Walking : A pied (ne marche pas pour tous les pays)
Optimization Méthode de calcul du trajet. Marche en combinaison avec TrafficUsage
Enumération RouteOptimization :

MinimizeDistance : Distance minimale
MinimizeTime : Temps minimal

RoutePathType Type de données brutes renvoyées (en plus des données d’itinéraires)
Enumération RoutePathType :
None : Aucune donnée (par défaut)
Points : Un ensemble de points décrivant le chemin de la route.
TrafficUsage Type d’adaptation du trajet en fonction du trafic
Enumération TrafficUsage :

None : On ne tient pas compte du trafic (par défaut)

TrafficBasedRouteAndTime : On change le trajet pour minimiser le temps si nécessaire

TrafficBasedTime : On ne change pas la route mais on tient compte du trafic lors du calcul du trajet.

Combinaisons de Optimization et TrafficUsage :

Optimization TrafficUsage Description

MinimizeDistance

None

Trajet le plus direct (en distance) sans prendre en compte le trafic.

MinimizeDistance

TrafficBasedRouteAndTime

Une Exception lancée. Je pense que c’est du au fait que changer la route d’un trajet le plus direct en fonction du trafic => trajet plus long => incohérence.

MinimizeDistance

TrafficBasedTime

Trajet le plus direct (en distance) en tenant compte du trafic dans les calculs de durée (le trajet n’est pas changé… on passera dans les bouchons quand même :)).

MinimizeTime

None

Trajet le plus rapide (en temps) sans prendre en compte le trafic.

MinimizeTime

TrafficBasedRouteAndTime

Trajet le plus rapide (en temps) en tenant compte du trafic et en le modifiant le cas échéant.

MinimizeTime

TrafficBasedTime

Trajet le plus rapide (en temps) en tenant compte du trafic dans les calculs de temps de trajet (la route n’est pas modifié en fonction du trafic).

Un petit code vaut mieux qu’un long discours : (les variables positionWinwise, positionMSFUniv, positionMSF sont des coordonnées géographiques calculées avant ce code)

RouteServiceClient rsc = new RouteServiceClient();
RouteRequest rq = new RouteRequest();
rq.Credentials = new VETutorial.RouteService.Credentials();
rq.Credentials.Token = token;
rq.Culture = "fr-FR";
rq.Waypoints = new Waypoint[]
{
	new Waypoint() 
	{ 					
		Description = "Winwise (Départ)", 
		Location = new VETutorial.RouteService.Location() 
		{
			Longitude = positionWinwise.Longitude,
			Latitude = positionWinwise.Latitude,
		}
	}, 
	new Waypoint() 
	{ 
		Description = "Microsoft France (Rue de l'université)", 
		Location =  new VETutorial.RouteService.Location() 
		{
			Longitude = positionMSFUniv.Longitude,
			Latitude = positionMSFUniv.Latitude,
		}
	}, 
	new Waypoint() 
	{ 
		Description = "Microsoft France (Rue du québec)", 
		Location =  new VETutorial.RouteService.Location() 
		{
			Longitude = positionMSF.Longitude,
			Latitude = positionMSF.Latitude,
		}
	},
};
rq.Options = new RouteOptions()
{
	Mode = TravelMode.Driving,
	Optimization = RouteOptimization.MinimizeTime,
	RoutePathType = RoutePathType.Points,
	TrafficUsage = TrafficUsage.TrafficBasedRouteAndTime,
};
RouteResponse routeResult = rsc.CalculateRoute(rq);

Comme vous pouvez voir dans ce code, on peut définir des informations supplémentaires comme les données d’authentifications ou encore la culture (langue) du résultat.

En réponse à l’appel de la méthode CalculateRoute, on obtient une classe de réponse de type RouteResponse contenant un champ ResponseSummary (déjà décrit dans les posts précédents) et un champ Result de type RouteResult contenant les informations sur le trajet.

La classe RouteResult fonctionne en arborescence :

Un RouteResult contient des Legs: Un Leg  est un trajet entre deux points de passages. Si plusieurs points de passages alors plusieurs Legs dans le RouteResult

Un Leg contient un tableau d’ItineraryItem (dans la propriété Itinerary) : Un ItineraryItem contient les informations entre deux changements de directions.

Chaque RouteResult, Leg et ItineraryItem contient une propriété Summary contenant le rectangle de leur localisation (propriété BoundingRectangle) ainsi que le temps de parcours en secondes (propriété TimeInSeconds) et la longueur de ce parcours dans la propriété Distance (par défaut en KM mais réglable dans la propriété UserProfile de la requête).

En dehors de ces données, la classe RouteResult contient aussi les données brutes du chemin dans la propriété RoutePath. Il contient un tableau de points géographiques représentant le trajet à faire. Cette propriété est la raison pour laquelle les données renvoyés par le service sont énormes. N’activer cette propriété que si nécessaire (désactivé par défaut : propriété RoutePathType de la requête).

La classe Leg a aussi deux propriétés spécifiques : ActualStart, ActualEnd. Ces propriétés indiquent les positions géographiques de départ et d’arrivés du Leg.

La classe ItineraryItem contient les propriétés suivantes :

Nom de la propriété Description
CompassDirection Orientation du déplacement (chaines de caractères “Nord” …)
Hints Indication permettant de mieux repérer le changement de direction (exemple : “la rue précédente est …”)
Location Position du changement de direction
ManeuverType Type de changement (tourner à gauche, droite, demi tour …)
Text Texte en format XML indiquant le changement à faire (Exemple : “<VirtualEarth:Action>Quitter</VirtualEarth:Action> <VirtualEarth:RoadName>Rue Gaillon</VirtualEarth:RoadName>”)
Warnings Danger sur la route. Lié aux infos traffic, cette propriété indique s’il y a un évènement sur votre trajet (accident, travaux …)

Voici le code d’affichage d’un trajet :

Console.WriteLine("--- Itinéraire  ---");
Console.WriteLine("Temps de calcul : "+ sw.Elapsed);
int i = 1;				
foreach (var leg in routeResult.Result.Legs)
{							
	var duree = new TimeSpan(0,0,(int)leg.Summary.TimeInSeconds);
	Console.WriteLine("-----    Partie " + i + " ------");
	Console.WriteLine("De (" + leg.ActualStart.Latitude +","+leg.ActualStart.Longitude+") à (" + leg.ActualEnd.Latitude +","+leg.ActualEnd.Longitude+")");
	Console.WriteLine("Distance " + leg.Summary.Distance + " km");
	Console.WriteLine("Temps estimé : " + duree.Hours + " h " + duree.Minutes + " min " + duree.Seconds+ " sec");
	Console.WriteLine("************ TRAJET ************");
	int j = 1;
	double distanceDone = 0;
	foreach (var turn in leg.Itinerary)
	{			
		var duree2 = new TimeSpan(0, 0, (int)turn.Summary.TimeInSeconds);
		string HumanInfos = StripXMLFromText(turn.Text);
		Console.WriteLine("Indication " + j + " " + (distanceDone) + " km ["+duree2.Hours+":" + duree2.Minutes + ":" + duree2.Seconds+ "] : " + HumanInfos);
		distanceDone += turn.Summary.Distance;
		j++;
	}
	Console.WriteLine("----- Fin Partie " + i + " -----");
	i++;
}

Le résultat obtenu est le suivant :

— Itinéraire  —

Temps de calcul : 00:00:04.3373465

—–    Partie 1 ——

De (48,868681,2,334231) à (48,861122,2,309237)

Distance 2,788 km

Temps estimé : 0 h 7 min 46 sec

************ TRAJET ************

Indication 1 0 km [0:0:11] : Quitter Rue Gaillon

Indication 2 0,13 km [0:0:49] : Prendre à gauche Avenue de l’Opéra

Indication 3 0,156 km [0:0:53] : Tourner à droite Rue Saint-Roch

Indication 4 0,569 km [0:1:17] : Tourner à droite Rue de Rivoli

Indication 5 1,215 km [0:0:5] : Continuer tout droit Place de la Concorde

Indication 6 1,257 km [0:0:9] : Continuer à gauche Place de la Concorde

Indication 7 1,338 km [0:0:58] : Au rond-point prendre 4

Indication 8 1,61 km [0:0:57] : Prendre à droite Pont de la Concorde

Indication 9 1,835 km [0:1:17] : Tourner à droite Quai d’Orsay

Indication 10 2,531 km [0:0:6] : Continuer à droite Quai d’Orsay

Indication 11 2,584 km [0:0:2] : Tourner à gauche Quai d’Orsay

Indication 12 2,61 km [0:0:56] : Continuer tout droit Rue Surcouf

Indication 13 2,777 km [0:0:6] : Tourner à droite Rue de l’Université

Indication 14 2,788 km [0:0:0] : Arrivée Microsoft France (Rue de l’université)

—– Fin Partie 1 —–

—–    Partie 2 ——

De (48,861122,2,309237) à (48,6900826,2,2157051)

Distance 33,094 km

Temps estimé : 0 h 33 min 46 sec

************ TRAJET ************

Indication 1 0 km [0:0:36] : Quitter Rue de l’Université

Indication 2 0,28 km [0:0:28] : Tourner à droite Rue Malar

Indication 3 0,439 km [0:1:9] : Tourner à gauche Quai d’Orsay

Indication 4 0,685 km [0:2:26] : Continuer tout droit Quai Branly

Indication 5 2,079 km [0:1:27] : Le nom de la voie change Quai de Grenelle

Indication 6 2,877 km [0:2:34] : Le nom de la voie change Quai André Citroën

Indication 7 4,109 km [0:0:33] : Au rond-point prendre 1

Indication 8 4,378 km [0:0:55] : Le nom de la voie change Quai d’Issy-les-Moulin

eaux

Indication 9 4,925 km [0:5:21] : Voie Ad/15 prendre à gauche Boulevard Périphéri

que Lyon

Indication 10 10,008 km [0:2:57] : Prendre à droite E15 Nantes-Bordeaux/Aéroport

Orly-Rungis/Évry-Lyon

Indication 11 12,67 km [0:2:14] : Prendre à droite E15 Véhicules Lents-Toutes Di

rections

Indication 12 15,678 km [0:2:11] : Continuer à gauche E15

Indication 13 19,625 km [0:7:10] : Prendre à droite E5/E50

Indication 14 30,882 km [0:0:54] : 9 prendre à droite Chartres Par RN/Les Ulis/Z

.A. de Courtaboeuf/Villejust

Indication 15 31,465 km [0:0:31] : Prendre à droite D118

Indication 16 31,913 km [0:0:15] : Prendre à droite

Indication 17 32,063 km [0:0:36] : Tourner à droite Avenue de la Baltique

Indication 18 32,32 km [0:1:29] : Tourner à droite Avenue du Québec

Indication 19 33,094 km [0:0:0] : Arrivée Microsoft France (Rue du québec)

—– Fin Partie 2 —–

J’avoue que c’est moins sexy qu’une belle carte en 3D avec le chemin en surbrillance mais c’est mieux que rien. Je vais essayer de voir comment afficher ce trajet sur une carte (avec le RoutePath de RouteResult je pense). Sujet d’un prochain post.


  • Calcul d’itinéraires depuis des routes principales

Le principe de la méthode CalculateRoutesFromMajorRoads est de fournir les trajet allant (ou revenant) d’un point nommé Destination vers les grands axes routiers. Au niveau de la requête, la plupart des propriétés décrites ci dessus fonctionnent avec la classe MajorRoutesRequest. Deux différences toutefois :

La propriété Waypoints disparait au profit d’une propriété Destination ne permettant de définir qu’un WayPoint.

La propriété Options devient du type MajorRoutesOptions et cela ajoute un nouveau paramètre d’options : la propriété booléenne ReturnRoutes indique si on souhaite calculer les routes entre la destination et les routes majeurs (true) où si l’on souhaite uniquement les points d’entrées sur les routes majeures les plus proches (false. valeur par défaut).

MajorRoutesRequest mrr = new MajorRoutesRequest();
mrr.Credentials = new VETutorial.RouteService.Credentials();
mrr.Credentials.Token = token;
mrr.Destination = new Waypoint()
{
	Description = "Winwise (Départ)",
	Location = new VETutorial.RouteService.Location()
	{
		Longitude = positionWinwise.Longitude,
		Latitude = positionWinwise.Latitude,
	}
};
mrr.Culture = "fr-FR";
mrr.Options = new MajorRoutesOptions()
{			  
	Mode = TravelMode.Driving,
	Optimization = RouteOptimization.MinimizeTime,
	RoutePathType = RoutePathType.Points,
	TrafficUsage = TrafficUsage.TrafficBasedRouteAndTime,
	ReturnRoutes = true
};
MajorRoutesResponse MRresult = rsc.CalculateRoutesFromMajorRoads(mrr);

Au niveau de la réponse, on reste sur les mêmes types de données. On a ainsi la propriété Routes contenant des RouteResult (décrit plus haut) donnant les itinéraires entre le point destination et une route majeure. La propriété StartingPoints est un tableau de positions géographiques indiquant les entrées sur les routes majeures environnantes.

Ici se conclut ce post sur les calculs d’itinéraire sous Virtual Earth. Il ne reste plus qu’un service à découvrir : Le SearchService puis nous terminerons par une belle application WPF reprenant tout ce que l’on a appris aux cours de ces 5 posts.

N’hésitez pas à mettre des commentaires pour enrichir ces tutoriaux.

4 commentaires »

  1. […] [Virtual Earth] Développement Microsoft Virtual Earth Web Services – Part 4 : Route&nbs… […]

    Ping par [Virtual Earth] Développement Microsoft Virtual Earth Web Services – Part 1 « Astuces DotNet (Sébastien Courtois) — 24/04/2009 @ 15:59

  2. […] par [Virtual Earth] Développement Microsoft Virtual Earth Web Services – Part 4 : Route Ser… | 24/04/2009 | […]

    Ping par [Virtual Earth] Développement Microsoft Virtual Earth Web Services – Part 2 : Géocoding Service « Astuces DotNet (Sébastien Courtois) — 24/04/2009 @ 16:00

  3. […] par [Virtual Earth] Développement Microsoft Virtual Earth Web Services – Part 4 : Route Ser… | 24/04/2009 | […]

    Ping par [Virtual Earth] Développement Microsoft Virtual Earth Web Services – Part 3 : Imagery Service « Astuces DotNet (Sébastien Courtois) — 24/04/2009 @ 16:01


RSS feed for comments on this post. TrackBack URI

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

Propulsé par WordPress.com.

%d blogueurs aiment cette page :