Archives du mot-clé BingMaps

Intégrer les services Bing Maps dans son application Metro Windows 8 en XAML/C# (3/3)

Suite et fin de cette série d’articles… Après une 1ère partie sur l’utilisation du contrôle Map dans une application Metro , puis une 2ème partie sur la recherche de localités via les services REST Bing Maps et le Search Charm , nous allons maintenant intégrer le calcul d’itinéraire et l’affichage des incidents de circulation.

Commençons par le plus simple, l’affichage des incidents de circulation. Bing Maps met à disposition un service REST permettant de récupérer ce type d’information. Suivez ce lien pour une documentation complète du service d’incidents.

L’URL de base du service Bing Maps est la suivante : http://dev.virtualearth.net/REST/v1/Traffic/Incidents/

Il faut ensuite ajouter un paramètre représentant la zone géographique. Une zone géographique est représentée par un rectangle (Latitude Sud, Longitude Ouest, Latitude Nord, Longitude Est).

On peut également ajouter des paramètres supplémentaires optionnels afin de filtrer les résultats (severity : gravité des incidents, type : type d’incidents).

Pour l’intégration de ces informations dans notre application Bing Maps Metro, nous allons nous connecter à l’évènement ViewChangeEnded du contrôle Map :

  1. < Maps : Map x : Name = »myMaps »
  2. Credentials = »Your Bing Maps Key »
  3. MapType = »Aerial »
  4. ShowTraffic = »True »
  5. ShowScaleBar = »False »
  6. ZoomLevel = »17″
  7. ViewChangeEnded = »myMaps_ViewChangeEnded »
  8. >
  9. < Maps : Map.Center >
  10. < Maps : Location Latitude = »48.830617″ Longitude = »2.261645″ />
  11. </ Maps : Map.Center >
  12. </ Maps : Map >

 

Pour ne pas surcharger la carte avec trop d’informations, nous n’afficherons les incidents que dans le cas où le niveau de zoom est supérieur à 10 et si l’option d’affichage du trafic est activée. A chaque modification de la vue (manipulation de la carte par l’utilisateur), nous supprimons tous les points d’intérêt représentant des incidents, pour ensuite ajouter les nouveaux :

  1. private List < Pushpin > incidentPushpins = new List < Pushpin >();
  2. private async void myMaps_ViewChangeEnded( object sender, ViewChangeEndedEventArgs e)
  3. {
  4. if (myMaps.ZoomLevel > 10 && myMaps.ShowTraffic == true )
  5. {
  6. foreach ( var item in incidentPushpins)
  7. {
  8. if (myMaps.Children.Contains(item))
  9. myMaps.Children.Remove(item);
  10. }
  11. incidentPushpins.Clear();
  12. }
  13. }

 

La zone géographique représentant le paramètre mapArea du service REST Bing Maps peut être composée de cette manière en utilisant la propriété TargetBounds du contrôle Map :

  1. string mapArea = myMaps.TargetBounds.South + « , » + myMaps.TargetBounds.West + « , » + myMaps.TargetBounds.North + « , » + myMaps.TargetBounds.East;

 

L’URL pour interroger le service de récupération des incidents de circulation est la suivante :

  1. string uri = « http://dev.virtualearth.net/REST/v1/Traffic/Incidents/ &raquo; + mapArea + « ?key= » + BingMapsKey;

 

Il nous faut maintenant instancier un objet HttpClient afin d’envoyer notre requête et de récupérer le résultat :

  1. HttpClient client = new HttpClient ();
  2. var result = await client.GetStringAsync(uri);

 

Le résultat est un flux Json contenant la liste des incidents dans la zone demandée :

{
    "authenticationResultCode": "ValidCredentials",
    "brandLogoUri": "http://dev.virtualearth.net/Branding/logo_powered_by.png",
    "copyright": "Copyright © 2012 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
    "resourceSets": [
        {
            "estimatedTotal": 2,
            "resources": [
                {
                    "__type": "TrafficIncident:http://schemas.microsoft.com/search/local/ws/rest/v1",
                    "point": {
                        "type": "Point",
                        "coordinates": [
                            48.81982,
                            2.32425
                        ]
                    },
                    "description": "entre Porte d'Orléans (E2) et Porte de Gentilly - Fermé.",
                    "end": "/Date(1342258789000)/",
                    "incidentId": 323566599,
                    "lastModified": "/Date(1342085989000)/",
                    "roadClosed": true,
                    "severity": 4,
                    "start": "/Date(1342085940000)/",
                    "toPoint": {
                        "type": "Point",
                        "coordinates": [
                            48.81912,
                            2.34364
                        ]
                    },
                    "type": 8,
                    "verified": true
                },
                {
                    "__type": "TrafficIncident:http://schemas.microsoft.com/search/local/ws/rest/v1",
                    "point": {
                        "type": "Point",
                        "coordinates": [
                            48.81982,
                            2.32425
                        ]
                    },
                    "description": "entre Porte d'Orléans (E2) et Porte de Gentilly - Travaux sur tronçon.",
                    "end": "/Date(1342389600000)/",
                    "incidentId": 322895570,
                    "lastModified": "/Date(1341847492000)/",
                    "roadClosed": false,
                    "severity": 2,
                    "start": "/Date(1341847260000)/",
                    "toPoint": {
                        "type": "Point",
                        "coordinates": [
                            48.81912,
                            2.34364
                        ]
                    },
                    "type": 9,
                    "verified": true
                }
            ]
        }
    ],
    "statusCode": 200,
    "statusDescription": "OK",
    "traceId": "468e0ef9b5694d3e81d26623bbf5a3fe|AMSM001106|02.00.138.500|"
}

Dans ce flux, nous devons récupérer et parcourir le tableau resources :

  1. var values = JsonValue .Parse(result);
  2. var incidents = values.GetObject()[ « resourceSets » ].GetArray()[0].GetObject()[ « resources » ].GetArray();
  3. foreach ( var item in incidents)
  4. {
  5. }

 

Pour chacun des incidents, récupérer sa description et ses coordonnées :

  1. var description = item.GetObject()[ « description » ].GetString();
  2. var coordinates = item.GetObject()[ « point » ].GetObject()[ « coordinates » ].GetArray();

 

Et pour terminer, créer un objet de type Pushpin, le positionner et l’ajouter à la carte, puis ajouter un tooltip :

  1. Location location = new Location (coordinates[0].GetNumber(), coordinates[1].GetNumber());
  2. Pushpin pushpin = new Pushpin () { Text = «  » };
  3. MapLayer .SetPosition(pushpin, location);
  4. myMaps.Children.Add(pushpin);
  5. ToolTipService .SetToolTip(pushpin, description);
  6. incidentPushpins.Add(pushpin);

 

Et voilà le résultat :

BingMaps1

 

Pour mieux identifier ces points d’intérêt comme étant des incidents, il est possible de personnaliser le style des contrôles Pushpin.

Nous allons ajouter cette image BingMaps3 dans notre solution :

BingMaps2

 

Ensuite dans les ressources de la page MainPage nous ajoutons le ControlTemplate suivant :

  1. < ControlTemplate x : Key = »IncidentPushpin » TargetType = »Maps:Pushpin »>
  2. < Image Source = »Images/incident.png » Stretch = »None » HorizontalAlignment = »Left » />
  3. </ ControlTemplate >

 

Il nous faut maintenant appliquer ce template lorsque l’on crée les objets de type Pushpin :

  1. Pushpin pushpin = new Pushpin () { Text = «  » };
  2. pushpin.Template = Resources[ « IncidentPushpin » ] as ControlTemplate ;

 

Voici le code complet de la méthode myMaps_ViewChangeEnded :

  1. private async void myMaps_ViewChangeEnded( object sender, ViewChangeEndedEventArgs e)
  2. {
  3. if (myMaps.ZoomLevel > 10 && myMaps.ShowTraffic == true )
  4. {
  5. foreach ( var item in incidentPushpins)
  6. {
  7. if (myMaps.Children.Contains(item))
  8. myMaps.Children.Remove(item);
  9. }
  10. incidentPushpins.Clear();
  11. string mapArea = myMaps.TargetBounds.South + « , » + myMaps.TargetBounds.West + « , » + myMaps.TargetBounds.North + « , » + myMaps.TargetBounds.East;
  12. string uri = « http://dev.virtualearth.net/REST/v1/Traffic/Incidents/ &raquo; + mapArea + « ?key= » + BingMapsKey;
  13. JsonValue values = null ;
  14. try
  15. {
  16. HttpClient client = new HttpClient ();
  17. var result = await client.GetStringAsync(uri);
  18. values = JsonValue .Parse(result);
  19. }
  20. catch
  21. {
  22. MessageDialog dialog = new MessageDialog ( « Unable to find traffic incidents… » );
  23. dialog.ShowAsync();
  24. return ;
  25. }
  26. if (values == null )
  27. return ;
  28. var incidents = values.GetObject()[ « resourceSets » ].GetArray()[0].GetObject()[ « resources » ].GetArray();
  29. foreach ( var item in incidents)
  30. {
  31. var description = item.GetObject()[ « description » ].GetString();
  32. var coordinates = item.GetObject()[ « point » ].GetObject()[ « coordinates » ].GetArray();
  33. Location location = new Location (coordinates[0].GetNumber(), coordinates[1].GetNumber());
  34. Pushpin pushpin = new Pushpin () { Text = «  » };
  35. pushpin.Template = Resources[ « IncidentPushpin » ] as ControlTemplate ;
  36. MapLayer .SetPosition(pushpin, location);
  37. myMaps.Children.Add(pushpin);
  38. ToolTipService .SetToolTip(pushpin, description);
  39. incidentPushpins.Add(pushpin);
  40. }
  41. }
  42. }

 

Et le résultat en image :

BingMaps4

 

Nous allons maintenant développer la dernière fonctionnalité, qui est d’intégrer le calcul d’itinéraire. Pour consulter la documentation complète de l’API Routes des services Bing Maps, suivez ce lien .

L’URI de base pour calculer un itinéraire via les services Bing Maps est la suivante : http://dev.virtualearth.net/REST/v1/Routes/

Il faut ensuite ajouter des paramètres de type waypoint.n pour indiquer les différents points de passage. Un point de passage (début, intermédiaire, fin) est représenté soit par des coordonnées géographiques ou un requête (par exemple, une adresse).

Voici ici une URI qui nous permet de rechercher un itinéraire pour aller de Toulouse à Paris : http://dev.virtualearth.net/REST/V1/Routes/Driving?wp.0=toulouse&wp.1=paris&avoid=minimizeTolls&routePathOutput=points&key=XXXXXXXXXXXX

On remarque dans cette URI, le paramètre Driving. Ce paramètre permet d’indiquer le type de déplacement souhaité et peut prendre comme valeur driving, walking ou transit.

Le paramètre avoid permet d’indiquer comment nous voulons optimiser l’itinéraire. La valeur minimizeTolls indique d’éviter les péages autant que possible.

Et le paramètre routePathOutput permet d’indiquer si l’on veut la liste des points représentant le chemin de l’itinéraire (valeur points ou none).

Voici le format de la réponse Json :

{
    "authenticationResultCode": "ValidCredentials",
    "brandLogoUri": "http://dev.virtualearth.net/Branding/logo_powered_by.png",
    "copyright": "Copyright © 2012 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
    "resourceSets": [
        {
            "estimatedTotal": 1,
            "resources": [
                {
                    "__type": "Route:http://schemas.microsoft.com/search/local/ws/rest/v1",
                    "bbox": [
                        43.61451,
                        1.463354,
                        43.617219,
                        1.465543
                    ],
                    "id": "v63,i0,a2,cen-US,dAAAAAAAAAAA=,y0,s1,m1,o1,t4,wtYbgA6hMIQA=~A1rKBEkRzUwuAADgAaxvKz8A~QXZlbnVlIGR1IENvbW1hbmRhbnQgVGFpbGxhbmRpZXIsIDMxNTAwIFRvdWxvdXNl~~~,wQ3ngA/VPIQA=~A1rKBEkhH04uAADgAQAAgD8A~QXZlbnVlIEzDqW9uIEJsdW0sIDMxNTAwIFRvdWxvdXNl~~~,k1,u",
                    "distanceUnit": "Kilometer",
                    "durationUnit": "Second",
                    "routeLegs": [
                        {
                            "actualEnd": {
                                "type": "Point",
                                "coordinates": [
                                    43.614548,
                                    1.46396
                                ]
                            },
                            "actualStart": {
                                "type": "Point",
                                "coordinates": [
                                    43.616874,
                                    1.463354
                                ]
                            },
                            "endLocation": {
                                "bbox": [
                                    43.610703,
                                    1.456808,
                                    43.618429,
                                    1.471034
                                ],
                                "name": "Avenue Léon Blum, 31500 Toulouse",
                                "point": {
                                    "type": "Point",
                                    "coordinates": [
                                        43.614566,
                                        1.463921
                                    ]
                                },
                                "address": {
                                    "addressLine": "Avenue Léon Blum",
                                    "adminDistrict": "Midi-Pyrénées",
                                    "adminDistrict2": "Haute-Garonne",
                                    "countryRegion": "France",
                                    "formattedAddress": "Avenue Léon Blum, 31500 Toulouse",
                                    "locality": "Toulouse",
                                    "postalCode": "31500"
                                },
                                "confidence": "High",
                                "entityType": "RoadBlock",
                                "geocodePoints": [
                                    {
                                        "type": "Point",
                                        "coordinates": [
                                            43.614566,
                                            1.463921
                                        ],
                                        "calculationMethod": "Interpolation",
                                        "usageTypes": [
                                            "Display",
                                            "Route"
                                        ]
                                    }
                                ],
                                "matchCodes": [
                                    "Good"
                                ]
                            },
                            "itineraryItems": [
                                {
                                    "compassDirection": "southeast",
                                    "details": [
                                        {
                                            "compassDegrees": 114,
                                            "endPathIndices": [
                                                1
                                            ],
                                            "maneuverType": "DepartStart",
                                            "mode": "Driving",
                                            "names": [
                                                "Avenue du Commandant Taillandier"
                                            ],
                                            "roadType": "Street",
                                            "startPathIndices": [
                                                0
                                            ]
                                        }
                                    ],
                                    "exit": "",
                                    "iconType": "Auto",
                                    "instruction": {
                                        "maneuverType": "DepartStart",
                                        "text": "Depart Avenue du Commandant Taillandier toward Rue Benjamin Baillaud"
                                    },
                                    "maneuverPoint": {
                                        "type": "Point",
                                        "coordinates": [
                                            43.616874,
                                            1.463354
                                        ]
                                    },
                                    "sideOfStreet": "Unknown",
                                    "tollZone": "",
                                    "towardsRoadName": "Rue Benjamin Baillaud",
                                    "transitTerminus": "",
                                    "travelDistance": 0.078,
                                    "travelDuration": 8,
                                    "travelMode": "Driving"
                                },
                                {
                                    "compassDirection": "northeast",
                                    "details": [
                                        {
                                            "compassDegrees": 53,
                                            "endPathIndices": [
                                                5
                                            ],
                                            "maneuverType": "TurnLeft",
                                            "mode": "Driving",
                                            "names": [
                                                "Rue Benjamin Baillaud"
                                            ],
                                            "roadType": "Street",
                                            "startPathIndices": [
                                                1
                                            ]
                                        }
                                    ],
                                    "exit": "",
                                    "iconType": "Auto",
                                    "instruction": {
                                        "maneuverType": "TurnLeft",
                                        "text": "Turn left onto Rue Benjamin Baillaud"
                                    },
                                    "maneuverPoint": {
                                        "type": "Point",
                                        "coordinates": [
                                            43.6165,
                                            1.464191
                                        ]
                                    },
                                    "sideOfStreet": "Unknown",
                                    "tollZone": "",
                                    "transitTerminus": "",
                                    "travelDistance": 0.142,
                                    "travelDuration": 30,
                                    "travelMode": "Driving"
                                },
                                {
                                    "compassDirection": "southwest",
                                    "details": [
                                        {
                                            "compassDegrees": 214,
                                            "endPathIndices": [
                                                8
                                            ],
                                            "maneuverType": "TurnRight",
                                            "mode": "Driving",
                                            "names": [
                                                "Avenue Yves Brunaud"
                                            ],
                                            "roadType": "Highway",
                                            "startPathIndices": [
                                                5
                                            ]
                                        }
                                    ],
                                    "exit": "",
                                    "iconType": "Auto",
                                    "instruction": {
                                        "maneuverType": "TurnRight",
                                        "text": "Turn right onto Avenue Yves Brunaud"
                                    },
                                    "maneuverPoint": {
                                        "type": "Point",
                                        "coordinates": [
                                            43.617128,
                                            1.4655
                                        ]
                                    },
                                    "sideOfStreet": "Unknown",
                                    "tollZone": "",
                                    "transitTerminus": "",
                                    "travelDistance": 0.17,
                                    "travelDuration": 33,
                                    "travelMode": "Driving"
                                },
                                {
                                    "compassDirection": "southeast",
                                    "details": [
                                        {
                                            "compassDegrees": 270,
                                            "endPathIndices": [
                                                13
                                            ],
                                            "maneuverType": "EnterRoundabout",
                                            "mode": "Driving",
                                            "names": [
                                                "Rond-point du Capitaine Alfred Dreyfus"
                                            ],
                                            "roadType": "Highway",
                                            "startPathIndices": [
                                                8
                                            ]
                                        },
                                        {
                                            "compassDegrees": 143,
                                            "endPathIndices": [
                                                15
                                            ],
                                            "maneuverType": "ExitRoundabout",
                                            "mode": "Driving",
                                            "names": [
                                                "Boulevard des Crêtes"
                                            ],
                                            "roadType": "MajorRoad",
                                            "startPathIndices": [
                                                13
                                            ]
                                        }
                                    ],
                                    "exit": "2",
                                    "iconType": "Auto",
                                    "instruction": {
                                        "maneuverType": "EnterThenExitRoundabout",
                                        "text": "At roundabout, take 2nd exit onto Boulevard des Crêtes"
                                    },
                                    "maneuverPoint": {
                                        "type": "Point",
                                        "coordinates": [
                                            43.615653,
                                            1.46506
                                        ]
                                    },
                                    "sideOfStreet": "Unknown",
                                    "tollZone": "",
                                    "transitTerminus": "",
                                    "travelDistance": 0.168,
                                    "travelDuration": 33,
                                    "travelMode": "Driving"
                                },
                                {
                                    "compassDirection": "west",
                                    "details": [
                                        {
                                            "compassDegrees": 272,
                                            "endPathIndices": [
                                                17
                                            ],
                                            "maneuverType": "TurnRight",
                                            "mode": "Driving",
                                            "names": [
                                                "Avenue Léon Blum"
                                            ],
                                            "roadType": "MajorRoad",
                                            "startPathIndices": [
                                                15
                                            ]
                                        }
                                    ],
                                    "exit": "",
                                    "iconType": "Auto",
                                    "instruction": {
                                        "maneuverType": "TurnRight",
                                        "text": "Turn right onto Avenue Léon Blum"
                                    },
                                    "maneuverPoint": {
                                        "type": "Point",
                                        "coordinates": [
                                            43.614521,
                                            1.465543
                                        ]
                                    },
                                    "sideOfStreet": "Unknown",
                                    "tollZone": "",
                                    "transitTerminus": "",
                                    "travelDistance": 0.13,
                                    "travelDuration": 28,
                                    "travelMode": "Driving"
                                },
                                {
                                    "compassDirection": "west",
                                    "details": [
                                        {
                                            "compassDegrees": 272,
                                            "endPathIndices": [
                                                17
                                            ],
                                            "maneuverType": "ArriveFinish",
                                            "mode": "Driving",
                                            "names": [
                                                "Avenue Léon Blum"
                                            ],
                                           "roadType": "MajorRoad",
                                            "startPathIndices": [
                                                17
                                            ]
                                        }
                                    ],
                                    "exit": "",
                                    "hints": [
                                        {
                                            "hintType": null,
                                            "text": "The last intersection is Boulevard des Crêtes"
                                        },
                                        {
                                            "hintType": null,
                                            "text": "If you reach Avenue Yves Brunaud, you've gone too far"
                                        }
                                    ],
                                    "iconType": "Auto",
                                    "instruction": {
                                        "maneuverType": "ArriveFinish",
                                        "text": "Arrive at Avenue Léon Blum, 31500 Toulouse"
                                    },
                                    "maneuverPoint": {
                                        "type": "Point",
                                        "coordinates": [
                                            43.614548,
                                            1.46396
                                        ]
                                    },
                                    "sideOfStreet": "Unknown",
                                    "tollZone": "",
                                    "transitTerminus": "",
                                    "travelDistance": 0,
                                    "travelDuration": 0,
                                    "travelMode": "Driving"
                                }
                            ],
                            "startLocation": {
                                "bbox": [
                                    43.613011,
                                    1.45624,
                                    43.620737,
                                    1.470468
                                ],
                                "name": "Avenue du Commandant Taillandier, 31500 Toulouse",
                                "point": {
                                    "type": "Point",
                                    "coordinates": [
                                        43.616874,
                                        1.463354
                                    ]
                                },
                                "address": {
                                    "addressLine": "Avenue du Commandant Taillandier",
                                    "adminDistrict": "Midi-Pyrénées",
                                    "adminDistrict2": "Haute-Garonne",
                                    "countryRegion": "France",
                                    "formattedAddress": "Avenue du Commandant Taillandier, 31500 Toulouse",
                                    "locality": "Toulouse",
                                    "postalCode": "31500"
                                },
                                "confidence": "High",
                                "entityType": "RoadBlock",
                                "geocodePoints": [
                                    {
                                        "type": "Point",
                                        "coordinates": [
                                            43.616874,
                                            1.463354
                                        ],
                                        "calculationMethod": "Interpolation",
                                        "usageTypes": [
                                            "Display",
                                            "Route"
                                        ]
                                    }
                                ],
                                "matchCodes": [
                                    "Good"
                                ]
                            },
                            "travelDistance": 0.688,
                            "travelDuration": 133
                        }
                    ],
                    "routePath": {
                        "generalizations": [],
                        "line": {
                            "type": "LineString",
                            "coordinates": [
                                [
                                    43.616873,
                                    1.463354
                                ],
                                [
                                    43.6165,
                                    1.464191
                                ],
                                [
                                    43.617171,
                                    1.465092
                                ],
                                [
                                    43.617219,
                                    1.465162
                                ],
                                [
                                    43.617197,
                                    1.465269
                                ],
                                [
                                    43.617128,
                                    1.465499
                                ],
                                [
                                    43.61701,
                                    1.465419
                                ],
                                [
                                    43.616462,
                                    1.46521
                                ],
                                [
                                    43.615652,
                                    1.46506
                                ],
                                [
                                    43.615652,
                                    1.464968
                                ],
                                [
                                    43.61562,
                                    1.464877
                                ],
                                [
                                    43.61547,
                                    1.46484
                                ],
                                [
                                    43.6154,
                                    1.464942
                                ],
                                [
                                    43.615438,
                                    1.465129
                                ],
                                [
                                    43.615379,
                                    1.465172
                                ],
                                [
                                    43.614521,
                                    1.465542
                                ],
                                [
                                    43.61451,
                                    1.46543
                                ],
                                [
                                    43.614547,
                                    1.46396
                                ]
                            ]
                        }
                    },
                    "travelDistance": 0.688,
                    "travelDuration": 133
                }
            ]
        }
    ],
    "statusCode": 200,
    "statusDescription": "OK",
    "traceId": "74808b399c51451dab1758f61ddd1c04|AMSM002207|02.00.138.500|AMSMSNVM002460, AMSMSNVM001314, AMSMSNVM001313, AMSMSNVM001322, AMSMSNVM002154, AMSMSNVM001307, AMSMSNVM002153, AMSMSNVM002408, AMSMSNVM001859, AMSMSNVM001857, AMSMSNVM001321, AMSMSNVM001863"
}

Dans ce flux Json nous avons l’objet bbox qui va nous permettre de centrer la carte sur la zone géographique de l’itinéraire via la méthode SetView :

  1. var values = JsonValue .Parse(result);
  2. // bbox represents the Bounding box of route : SouthLatitude, WestLongitude, NorthLatitude, and EastLongitude
  3. var bbox = values.GetObject()[ « resourceSets » ].GetArray()[0]
  4. .GetObject()[ « resources » ].GetArray()[0]
  5. .GetObject()[ « bbox » ].GetArray();
  6. var southLat = bbox[0].GetNumber();
  7. var westLong = bbox[1].GetNumber();
  8. var northLat = bbox[2].GetNumber();
  9. var eastLong = bbox[3].GetNumber();
  10. // center map on boundingbox of route
  11. var rect = new LocationRect ( new Location (northLat, westLong), new Location (southLat, eastLong));
  12. CurrentMap.SetView(rect);

 

Dans le flux Json nous retrouvons également les valeurs travelDistance et travelDuration, ainsi que distanceUnit et durationUnit. Nous avons ici accès aux informations de temps de parcours et de la distance totale.

Ensuite 2 objets nous intéresse particulièrement dans le cadre de notre recherche d’itinéraire. Tout d’abord l’objet routePath, qui lui même contient un objet line avec les coordonnées de notre parcours :

  1. var coordinates = values.GetObject()[ « resourceSets » ].GetArray()[0]
  2. .GetObject()[ « resources » ].GetArray()[0]
  3. .GetObject()[ « routePath » ]
  4. .GetObject()[ « line » ]
  5. .GetObject()[ « coordinates » ].GetArray();

 

Avec ces coordonnées nous allons pouvoir construire un objet MapPolyline pour représenter le parcours sur la carte. Un objet MapPolyline est composé d’un objet LocationCollection, d’une couleur et d’une taille :

  1. var locationCollection = new LocationCollection ();
  2. foreach ( var coordinate in coordinates)
  3. {
  4. var latitude = coordinate.GetArray()[0].GetNumber();
  5. var longitude = coordinate.GetArray()[1].GetNumber();
  6. var location = new Bing.Maps. Location (latitude, longitude);
  7. locationCollection.Add(location);
  8. }
  9. MapPolyline polyline = new MapPolyline ();
  10. polyline.Locations = locationCollection;
  11. polyline.Color = Windows.UI. Colors .Blue;
  12. polyline.Width = 5;

Ce type d’objet doit être ajouté à la carte par l’intermédiaire d’un layer de type MapShapeLayer :

  1. MapShapeLayer shapeLayer = new MapShapeLayer ();
  2. shapeLayer.Shapes.Add(polyline);
  3. CurrentMap.ShapeLayers.Add(shapeLayer);

 

Voici le résultat que l’on obtient après ajout de l’objet MapPolyline :

BingMaps5

 

Il nous reste à positionner les différentes étapes de l’itinéraire.

Dans le flux Json nous retrouvons la liste de ces étapes au niveau du tableau itineraryItems :

  1. var itineraryItems = values.GetObject()[ « resourceSets » ].GetArray()[0]
  2. .GetObject()[ « resources » ].GetArray()[0]
  3. .GetObject()[ « routeLegs » ].GetArray()[0]
  4. .GetObject()[ « itineraryItems » ].GetArray();

Dans une étape d’itinéraire, nous récupérons les coordonnées du point de manœuvre et les instructions. Nous utilisons un incrément afin de représenter le numéro de l’étape sur l’objet Pushpin :

  1. int stepCounter = 1;
  2. foreach ( var item in itineraryItems)
  3. {
  4. var step = item.GetObject()[ « instruction » ].GetObject()[ « text » ].GetString();
  5. var point = item.GetObject()[ « maneuverPoint » ].GetObject()[ « coordinates » ].GetArray();
  6. var latitude = point[0].GetNumber();
  7. var longitude = point[1].GetNumber();
  8. var location = new Location (latitude, longitude);
  9. Pushpin pushpin = new Pushpin () { Text = stepCounter.ToString() };
  10. MapLayer .SetPosition(pushpin, location);
  11. CurrentMap.Children.Add(pushpin);
  12. ToolTipService .SetToolTip(pushpin, step);
  13. }

 

Et voici le résultat :

BingMaps6

 

On peut ensuite mettre en place un UserControl qui va nous permettre de saisir les adresses de départ, de destination et afficher les instructions dans une ListView :

BingMaps7

 

L’archive suivante contient la solution complète au format VS 2012 RC :

Dans cette archive vous retrouverez les exemples décrits dans les 3 articles.

Il vous faudra éditer le fichier App.xaml afin de renseigner le paramètre BingMapsKey avec votre propre clé :

  1. < x : String x : Key = »BingMapsKey »> Your Bing Maps Key </ x : String >

Intégrer les services Bing Maps dans son application Metro Windows 8 en XAML/C# (2/3)

Cet article fait suite à une 1ère partie dans laquelle nous avons mis en place une application Metro intégrant une carte Bing Maps.

Dans cette 2ème partie je vous propose de découvrir comment utiliser les services REST de Bing Maps afin d’intégrer des fonctionnalités de recherche de localités. Afin d’être “Metro Compliant” nous nous intègrerons au Search Charm de Windows 8.

Pour une documentation complète des services REST Bing Maps je vous invite à consulter la documentation en ligne sur MSDN.

Pour retrouver la position d’un lieu, Bing Maps met à disposition plusieurs services web : recherche par adresse, par requête, par point.

1 premier web service permet de retrouver une localisation à partir d’une adresse. Nous devons donc fournir à ce web service des paramètres tels que le pays, le code postal, la ville ou encore la rue. Voici un exemple d’URL permettant de retrouver la place du capitole à Toulouse : http://dev.virtualearth.net/REST/v1/Locations/FR/31000/toulouse/place%20du%20capitole?maxResults=5&key=XXXXXXXXX

Notez le paramètre key : vous devez indiquer ici la clé d’accès aux services Bing Maps, que vous vous êtes créés depuis le portail.

Voici la réponse à cette requête au format json :

[BuildActivity(HostEnvironmentOption.All)]
{
    "authenticationResultCode": "ValidCredentials",
    "brandLogoUri": "http://dev.virtualearth.net/Branding/logo_powered_by.png",
    "copyright": "Copyright © 2012 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
    "resourceSets": [
        {
            "estimatedTotal": 1,
            "resources": [
                {
                    "__type": "Location:http://schemas.microsoft.com/search/local/ws/rest/v1",
                    "bbox": [
                        43.60056228242932,
                        1.4366889613939073,
                        43.608287717570676,
                        1.4509130386060924
                    ],
                    "name": "Place du Capitole, 31000 Toulouse",
                    "point": {
                        "type": "Point",
                        "coordinates": [
                            43.604425,
                            1.443801
                        ]
                    },
                    "address": {
                        "addressLine": "Place du Capitole",
                        "adminDistrict": "Midi-Pyrénées",
                        "adminDistrict2": "Haute-Garonne",
                        "countryRegion": "France",
                        "formattedAddress": "Place du Capitole, 31000 Toulouse",
                        "locality": "Toulouse",
                        "postalCode": "31000"
                    },
                    "confidence": "High",
                    "entityType": "RoadBlock",
                    "geocodePoints": [
                        {
                            "type": "Point",
                            "coordinates": [
                                43.604425,
                                1.443801
                            ],
                            "calculationMethod": "Interpolation",
                            "usageTypes": [
                                "Display",
                                "Route"
                            ]
                        }
                    ],
                    "matchCodes": [
                        "Good"
                    ]
                }
            ]
        }
    ],
    "statusCode": 200,
    "statusDescription": "OK",
    "traceId": "985f20b23f014beb91b6fda5ee2c4c46|BL2M002306|02.00.138.500|BL2MSNVM001813, BL2MSNVM001263"
}

Ici la requête a renvoyé un seul résultat, dans lequel nous retrouvons un objet de type Point avec les coordonnées (43.604425, 1.443801).

Un petit coup de Bing Maps pour vérifier l’exactitude de ces coordonnées…


bingmaps1

Pour consulter la documentation détaillée de ce service de localisation par adresse, suivez ce lien.

Le second service de recherche de localisation se fait par requête. Une requête est tout simplement un champ texte que l’on soumet au service pour qu’il nous retourne les résultats correspondants. On peut par exemple effectuer la recherche d’un monument (ex: “Tour Eiffel”) ou encore d’une adresse (ex: “place du capitole, toulouse”).

En voici un exemple : http://dev.virtualearth.net/REST/v1/Locations?query=place%20du%20capitole%20toulouse&maxResults=5&key=XXXXXXXXX

Nous allons utiliser ce dernier service dans notre application et nous intégrer dans le charm de recherche de Windows 8 afin d’obtenir le résultat ci-dessous :


bingmaps2

Pour implémenter le charm de recherche, nous devons tout d’abord le déclarer au niveau du Manifest de l’application. Double-cliquez sur le fichier Package.appxmanifest, puis cliquez sur l’onglet Declarations. Dans la liste “Available Declarations” sélectionnez Search puis cliquez sur Add :


bingmaps3

Notre application est composée d’une unique page, MainPage, contenant la carte Bing Maps. C’est donc cette page qui traitera les recherches qu’effectue l’utilisateur.

Dans la classe MainPage, ajoutez une méthode SearchLocation qui prend en paramètre la requête de l’utilisateur :

[BuildActivity(HostEnvironmentOption.All)]
private async void SearchLocation(string query)
{
 
}

Pour interroger le service REST Bing Maps nous allons utiliser un client HTTP, via la classe HttpClient de l’espace de nom System.Net.Http. Cette classe possède une méthode GetStringAsync, prenant en paramètre une Uri et renvoyant une chaine de caractère représentant la réponse :

[BuildActivity(HostEnvironmentOption.All)]
string uri = "http://dev.virtualearth.net/REST/v1/Locations/" + query + "?maxResults=1&key=XXXXXXXXXXXXX";
 
var client = new HttpClient();
var result = await client.GetStringAsync(uri);

Dans notre variable result nous avons un flux json sous cette forme :

[BuildActivity(HostEnvironmentOption.All)]
{
    "authenticationResultCode": "ValidCredentials",
    "brandLogoUri": "http://dev.virtualearth.net/Branding/logo_powered_by.png",
    "copyright": "Copyright © 2012 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
    "resourceSets": [
        {
            "estimatedTotal": 1,
            "resources": [
                {
                    "__type": "Location:http://schemas.microsoft.com/search/local/ws/rest/v1",
                    "bbox": [
                        43.60056228242932,
                        1.4366889613939073,
                        43.608287717570676,
                        1.4509130386060924
                    ],
                    "name": "Place du Capitole, 31000 Toulouse",
                    "point": {
                        "type": "Point",
                        "coordinates": [
                            43.604425,
                            1.443801
                        ]
                    },
                    "address": {
                        "addressLine": "Place du Capitole",
                        "adminDistrict": "Midi-Pyrénées",
                        "adminDistrict2": "Haute-Garonne",
                        "countryRegion": "France",
                        "formattedAddress": "Place du Capitole, 31000 Toulouse",
                        "locality": "Toulouse",
                        "postalCode": "31000"
                    },
                    "confidence": "High",
                    "entityType": "RoadBlock",
                    "geocodePoints": [
                        {
                            "type": "Point",
                            "coordinates": [
                                43.604425,
                                1.443801
                            ],
                            "calculationMethod": "Interpolation",
                            "usageTypes": [
                                "Display",
                                "Route"
                            ]
                        }
                    ],
                    "matchCodes": [
                        "Good"
                    ]
                }
            ]
        }
    ],
    "statusCode": 200,
    "statusDescription": "OK",
    "traceId": "4558270dcc9949f0a5790553ede6281c|BL2M002301|02.00.138.500|BL2MSNVM002816, BL2MSNVM002809, BL2MSNVM003152, BL2MSNVM003206, BL2MSNVM001262"
}

Pour parcourir ce flux Json, nous pouvons utiliser les classes de l’espace de nom Windows.Data.Json, et notamment la classe JsonValue qui possède une méthode Parse :

[BuildActivity(HostEnvironmentOption.All)]
JsonValue value = Windows.Data.Json.JsonValue.Parse(result);

Une fois que nous avons notre objet JsonValue, il nous faut le parcourir pour récupérer le nom et les coordonnées des différents résultats de localisation. L’analyse du flux json présenté ci-dessus, nous permet d’en déduire le code suivant :

[BuildActivity(HostEnvironmentOption.All)]
var resources = value.GetObject()["resourceSets"].GetArray()[0].GetObject()["resources"].GetArray();
 
foreach (var item in resources)
{
    var name = item.GetObject()["name"].GetString();
 
    var coordinates = item.GetObject()["point"].GetObject()["coordinates"].GetArray();
 
    var latitude = coordinates[0].GetNumber();
    var longitude = coordinates[1].GetNumber();
    
}

Il ne reste plus qu’à créer un objet de type Location, l’objet Pushpin associé, de l’ajouter à la carte et de le positionner :

[BuildActivity(HostEnvironmentOption.All)]
var location = new Bing.Maps.Location(latitude, longitude);
 
Pushpin pushpin = new Pushpin() { Text = "!" };

MapLayer.SetPosition(pushpin, location);
ToolTipService.SetToolTip(pushpin, name);
myMaps.Children.Add(pushpin);

Le code complet de la méthode SearchLocation :

[BuildActivity(HostEnvironmentOption.All)]
private async void SearchLocation(string query)
{
    myMaps.Children.Clear();
 
    string uri = "http://dev.virtualearth.net/REST/v1/Locations/" + query + "?maxResults=1&key=XXXXXXXXX";
 
    try
    {
        var client = new HttpClient();
        var result = await client.GetStringAsync(uri);
 
        JsonValue value = Windows.Data.Json.JsonValue.Parse(result);
 
        var resources = value.GetObject()["resourceSets"].GetArray()[0].GetObject()["resources"].GetArray();
 
        Location firstLocation = null;
 
        foreach (var item in resources)
        {
            var name = item.GetObject()["name"].GetString();
 
            var coordinates = item.GetObject()["point"].GetObject()["coordinates"].GetArray();
 
            var latitude = coordinates[0].GetNumber();
            var longitude = coordinates[1].GetNumber();
 
            var location = new Bing.Maps.Location(latitude, longitude);
 
            Pushpin pushpin = new Pushpin() { Text = "!" };
 
            MapLayer.SetPosition(pushpin, location);
            ToolTipService.SetToolTip(pushpin, name);
            myMaps.Children.Add(pushpin);
 
            if (firstLocation == null && resources.Count == 1)
                firstLocation = location;
        }
 
        myMaps.SetView(firstLocation, 10, 10, TimeSpan.FromMilliseconds(1000));
    }
    catch 
    {
        MessageDialog dialog = new MessageDialog("Unable to find location");
        dialog.ShowAsync();
    }
}

L’évènement levé par une recherche utilisateur via le charm sera levé dans la classe App. Dans la classe MainPage, il nous faut ajouter un point d’entrée, qui permettra à l’application d’activer la recherche. Ajoutez une méthode statique Activate, qui récupère l’instance en cours de la page MainPage et qui appelle la méthode SearchLocation :

[BuildActivity(HostEnvironmentOption.All)]
public static void Activate(string queryText)
{
    var frame = Window.Current.Content as Frame;
 
    if (frame == null)
    {
        MainPage page = new MainPage();
        page.SearchLocation(queryText);
        Window.Current.Content = page;
    }
    else if (!(frame.Content is MainPage))
    {
        frame.Navigate(typeof(MainPage), queryText);
    }
    else
    {
        var mainPage = (MainPage)frame.Content;
        mainPage.SearchLocation(queryText);
    }
 
    Window.Current.Activate();
}

La dernière étape consiste à récupérer l’évènement levé lorsque l’utilisateur effectue une recherche depuis le Charm et à appeler la méthode Activate que nous venons d’écrire. Pour se brancher sur la recherche, il suffit d’implémenter la méthode OnSearchActivated dans la classe App :

[BuildActivity(HostEnvironmentOption.All)]
protected override void OnSearchActivated(SearchActivatedEventArgs args)
{
    MainPage.Activate(args.QueryText);
}

Vous pouvez maintenant tester la recherche. Déployer l’application, afficher le Charm et effectuer votre recherche.

Pour afficher le panel de recherche depuis notre application nous pouvons ajouter dans la page MainPage le bouton suivant dans le contrôle AppBar (à côté du bouton My Location) :

[BuildActivity(HostEnvironmentOption.All)]

Voici le résultat visuel :


Bingmaps5

Et pour activer le panel de recherche depuis le code, il faut utiliser la classe Windows.ApplicationModel.Search.SearchPane comme ceci :

[BuildActivity(HostEnvironmentOption.All)]
private void btnSearch_Click(object sender, RoutedEventArgs e)
{
    Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().Show();
}

Nous en avons terminé pour la recherche d’un lieu. Dans la 3ème partie nous verrons comment récupérer et afficher la liste des incidents d’une zone géographique, ainsi que la recherche d’itinéraire.

En attendant, si vous recherchez plus d’informations sur le développement Windows 8, et plus particulièrement sur le Charm de recherche, je vous invite à consulter (en anglais) cet article de la MSDN, ainsi que les recommandations pour l’implémentation de ce Charm.

Et enfin, du côté des ressources françaises, retrouvez sur le site de la communauté Windows 8 une série d’articles sur l’implémentation des Charms.

Intégrer les services Bing Maps dans son application Metro Windows 8 en XAML/C# (1/3)

Dans cet article en 3 parties (eh oui, finalement c’est 3 parties, et non 2…), je vous propose de découvrir comment utiliser le contrôle Bing Maps ainsi que les services REST Bing Maps dans une application Metro Windows 8 en XAML/C#.

Concernant la documentation, vous retrouvez sur la MSDN une section consacrée à l’utilisation du contrôle Bing Maps dans une application Metro et une autre section consacrée à l’utilisation des services REST Bing Maps.

Afin d’utiliser les services BingMaps, vous devez vous procurer une clé d’accès à ces services. Pour créer cette clé, ça se passe sur le portail BingMaps et voici la marche à suivre.

Maintenant que nous avons tous les prérequis, nous pouvons commencer…

Dans cette série d’article, nous allons découvrir :

  • comment insérer et manipuler une carte BingMaps dans une application Metro Windows 8 :
    • Changer de vue
    • Afficher le trafic
    • Centrer la carte par rapport à des coordonnées
    • Afficher, customiser, interagir avec des points d’intérêts comme ma localisation, des étapes d’un itinéraire, des incidents
  • comment utiliser les services REST afin de :
    • rechercher la localisation d’une adresse,
    • retrouver un itinéraire
    • retrouver la liste des incidents d’une zone

Voici le résultat que nous obtiendrons :

bingmaps1

Pour commencer, ouvrez Visual Studio 2012, et créez un nouveau projet vide de type Windows Metro style :

bingmaps2

2ème étape, il faut ajouter une référence vers le SDK Bing Maps, que vous avez préalablement installé…

bingmaps3

Une fois la référence ajoutée, si vous compilez le projet vous avez une erreur qui indique que la compilation “Any CPU” n’est pas supportée, ainsi qu’un Waring indiquant qu’il faut ajouter une référence vers Microsoft.VCLibs.

Allez dans les propriétés de compilation afin de sélectionner une nouvelle architecture cible, x86 par exemple, puis ajouter une référence vers l’assembly Microsoft.VCLibs qui correspond au Microsoft Visual C++ Runtime Package.

Nous sommes maintenant prêts à intégrer une carte dans notre application!

Ouvrez la page MainPage.xaml et ajoutez un contrôle de type Map à l’intérieur du contrôle Grid :

bingmaps4

Avant de pouvoir exécuter votre application, il vous faut tout d’abord nommer le contrôle Map et lui fournir la clé que vous avez précédemment créée :

  1. <Grid Background= »{StaticResource ApplicationPageBackgroundThemeBrush}« >
  2. <Maps:Map x:Name= »myMaps » Credentials= »XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX » />
  3. </Grid>

 

Une fois ces informations renseignées, vous pouvez exécutez l’application. Le contrôle Map intègre de base la navigation à la souris, au clavier et au touch :

bingmaps5

Pour une description complète de la classe Map, je vous invite à consulter sa page MSDN associée.

Voici ici un exemple qui permet, depuis le code XAML :

  • d’afficher la carte en vue aérienne,
  • d’afficher les informations de trafic,
  • de masquer la légende de l’échelle,
  • d’initialiser la carte avec un zoom de niveau 17
  • de centrer la carte sur le point de coordonnées (48.830617, 2.261645)
  1. <Maps:Map x:Name= »myMaps »
  2.                       Credentials= »XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX »
  3.                       MapType= »Aerial »
  4.                       ShowTraffic= »True »
  5.                       ShowScaleBar= »False »
  6.                       ZoomLevel= »17″>
  7. <Maps:Map.Center>
  8. <Maps:Location Latitude= »48.830617″ Longitude= »2.261645″ />
  9. </Maps:Map.Center>
  10. </Maps:Map>
  11. </Grid>

 

Maintenant, nous allons ajouter une AppBar qui va permettre à l’utilisateur :

  • de modifier le type de carte,
  • afficher/masquer le trafic,
  • centrer la carte sur la localisation de l’utilisateur et afficher un point d’intérêt

Tout d’abord, il faut ajouter les styles ci-dessous dans les ressources de la page. Ces styles vont nous permettre d’avoir de jolis boutons Metro pour notre barre d’application!

  1. <Style x:Key= »TrafficAppBarButtonStyle » TargetType= »Button » BasedOn= »{StaticResource AppBarButtonStyle}« >
  2. <Setter Property= »AutomationProperties.AutomationId » Value= »TrafficAppBarButton »/>
  3. <Setter Property= »AutomationProperties.Name » Value= »Traffic »/>
  4. <Setter Property= »Content » Value= »⚠ »/>
  5. </Style>
  6. <Style x:Key= »AerialAppBarButtonStyle » TargetType= »Button » BasedOn= »{StaticResource AppBarButtonStyle}« >
  7. <Setter Property= »AutomationProperties.AutomationId » Value= »AerialAppBarButton »/>
  8. <Setter Property= »AutomationProperties.Name » Value= »Aerial »/>
  9. <Setter Property= »Content » Value= »✈ »/>
  10. </Style>
  11. <Style x:Key= »RoadAppBarButtonStyle » TargetType= »Button » BasedOn= »{StaticResource AppBarButtonStyle}« >
  12. <Setter Property= »AutomationProperties.AutomationId » Value= »RoadAppBarButton »/>
  13. <Setter Property= »AutomationProperties.Name » Value= »Road »/>
  14. <Setter Property= »Content » Value= »⛙ »/>
  15. </Style>
  16. <Style x:Key= »BirdseyeAppBarButtonStyle » TargetType= »Button » BasedOn= »{StaticResource AppBarButtonStyle}« >
  17. <Setter Property= »AutomationProperties.AutomationId » Value= »BirdseyeAppBarButton »/>
  18. <Setter Property= »AutomationProperties.Name » Value= »Birdseye »/>
  19. <Setter Property= »Content » Value= » »/>
  20. </Style>
  21. <Style x:Key= »MyLocationAppBarButtonStyle » TargetType= »Button » BasedOn= »{StaticResource AppBarButtonStyle}« >
  22. <Setter Property= »AutomationProperties.AutomationId » Value= »MyLocationAppBarButton »/>
  23. <Setter Property= »AutomationProperties.Name » Value= »My Location »/>
  24. <Setter Property= »Content » Value= » »/>
  25. </Style>

bingmaps6
Et enfin, voici le code l’AppBar à ajouter dans la MainPage :

  1. <Page.BottomAppBar>
  2. <AppBar>
  3. <Grid>
  4. <StackPanel Orientation= »Horizontal »>
  5. <Button Click= »btnTraffic_Click » Style= »{StaticResource TrafficAppBarButtonStyle} » />
  6. <Button Click= »btnAerial_Click » Style= »{StaticResource AerialAppBarButtonStyle} » />
  7. <Button Click= »btnRoad_Click » Style= »{StaticResource RoadAppBarButtonStyle} » />
  8. <Button Click= »btnBirdseye_Click » Style= »{StaticResource BirdseyeAppBarButtonStyle} » />
  9. </StackPanel>
  10. <StackPanel Orientation= »Horizontal » HorizontalAlignment= »Right »>
  11. <Button Click= »btnMyLocation_Click » Style= »{StaticResource MyLocationAppBarButtonStyle} » />
  12. </StackPanel>
  13. </Grid>
  14. AppBar>
  15. Page.BottomAppBar>

 

Pour les changements de vue de la carte, il suffit de modifier la propriété MapType du contrôle Map et de lui affecter une valeur de l’énumération Bing.Maps.MapType comme ceci :

  1. private void btnAerial_Click(object sender, RoutedEventArgs e)
  2. {
  3. myMaps.MapType = Bing.Maps.MapType.Aerial;
  4. }
  5. private void btnRoad_Click(object sender, RoutedEventArgs e)
  6. {
  7. myMaps.MapType = Bing.Maps.MapType.Road;
  8. }
  9. private void btnBirdseye_Click(object sender, RoutedEventArgs e)
  10. {
  11. myMaps.MapType = Bing.Maps.MapType.Birdseye;
  12. }

 

Pour afficher/masquer le trafic, il suffit de modifier la valeur de la propriété ShowTraffic :

  1. private void btnTraffic_Click(object sender, RoutedEventArgs e)
  2. {
  3. myMaps.ShowTraffic = !myMaps.ShowTraffic;
  4. }

 

Pour utiliser l’API de géolocalisation, il faut tout d’abord autoriser l’application à le faire. Depuis l’explorateur de solution, ouvrez le fichier Package.appxmanifest, puis dans l’onglet Capabilities, cochez la case Location :

bingmaps7

Pour plus d’informations sur la notion de Capabilities, je vous invite à consulter l’article correspondant sur la MSDN.

Pour utiliser l’API de géolocalisation, nous avons besoin d’une instance de la classe Geolocator dans l’espace de nom Windows.Devices.Geolocation. Cette classe possède une propriété LocationStatus que nous pouvons utiliser de cette manière :

  1. var geolocator = new Geolocator();
  2. if (geolocator.LocationStatus == PositionStatus.NotAvailable)
  3. {
  4.     MessageDialog dialog = new MessageDialog(« Location service not available »);
  5.     dialog.ShowAsync();
  6.     return;
  7. }

 

Ensuite, pour localiser l’utilisateur et ainsi récupérer les coordonnées géographiques, il faut utiliser la méthode GetGeopositionAsync comme ceci :

  1. Geoposition position = await geolocator.GetGeopositionAsync();

 

La méthode GetGeopositionAsync retourne un objet de type GeoPosition (ou plutôt IAsyncOperation), grâce auquel nous pouvons récupérer la latitude et la longitude.

Pour utiliser des coordonnées géographiques sur le contrôle Map, nous avons besoin d’un objet de type Location de l’espace de nom Bing.Maps.Location :

  1. Location location = new Bing.Maps.Location(position.Coordinate.Latitude, position.Coordinate.Longitude);

 

Un point d’intérêt sur un contrôle de type Map est représenté par un objet de type Pushpin, qu’il faut positionner via la classe MapLayer, puis l’ajouter à la collection Children du contrôle Map :

  1. Pushpin pushpin = new Pushpin() { Text = « ! » };
  2. MapLayer.SetPosition(pushpin, location);
  3. myMaps.Children.Add(pushpin);

 

Enfin, nous pouvons centrer la carte sur ce point d’intérêt et y ajouter un tooltip :

  1. ToolTipService.SetToolTip(pushpin, « My location »);
  2. myMaps.SetView(location, 12);

 

Ici nous utilisons la méthode SetView de l’objet Map pour centrer la carte sur les coordonnées géographiques spécifiées. Le second paramètre permet de définir le niveau de zoom. Le contrôle animera la carte automatiquement pour obtenir ce niveau de zoom et cette position.

Voici le code complet de la méthode de recherche de localisation :

  1. private async void btnMyLocation_Click(object sender, RoutedEventArgs e)
  2. {
  3.     Geoposition position = null;
  4.     try
  5.     {
  6.         var geolocator = new Geolocator();
  7.         if (geolocator.LocationStatus == PositionStatus.NotAvailable)
  8.         {
  9.             MessageDialog dialog = new MessageDialog(« Location service not available »);
  10.             dialog.ShowAsync();
  11.             return;
  12.         }
  13.         position = await geolocator.GetGeopositionAsync();
  14.     }
  15.     catch
  16.     {
  17.         MessageDialog dialog = new MessageDialog(« Unable to find your location »);
  18.         dialog.ShowAsync();
  19.         return;
  20.     }
  21.     if (position == null)
  22.         return;
  23.     Location location = new Bing.Maps.Location(position.Coordinate.Latitude, position.Coordinate.Longitude);
  24.     Pushpin pushpin = new Pushpin() { Text = « ! » };
  25.     MapLayer.SetPosition(pushpin, location);
  26.     myMaps.Children.Add(pushpin);
  27.     ToolTipService.SetToolTip(pushpin, « My location »);
  28.     myMaps.SetView(location, 12);
  29. }
  30. }

 

bingmaps8

Dans la 2ème et 3ème partie de cet article, nous découvrirons les services REST Bing Maps qui vont nous permettre d’intégrer la recherche d’adresse, d’itinéraire et d’incidents.

En attendant, si vous avez besoin de plus de détails sur certaines notions non détaillées dans cet article (mots clés async/await, notion de style et d’AppBar…) je vous invite à consulter les articles présents sur le site de la communautés des Développeurs Windows 8.

Et si vous avez des questions sur le développement Windows 8, n’hésitez pas à les poster sur le groupe Facebook de la communauté Windows 8.

La géolocalisation dans vos applications avec les services BingMaps

Bing_Maps_blue20logo1-300x82BingMaps met à disposition des développeurs des services et des API leurs permettant d’intégrer des fonctionnalités de géolocalisation dans leurs applications Web, Silverlight, WPF, Metro…

Je vous invite demain, jeudi 21 juin, à 12h30, à La Cantine de Toulouse pour un Techlunch qui vous fera découvrir ces différents services. Je vous présenterai notamment l’intégration des services Bing Maps dans une application Windows 8 Metro.

Il n’est pas trop tard pour vous inscrire!