Display of route

Jun 3, 2009 at 2:59 PM

Hello again, As mentioned I'm looking at the ppossibility of using VE in our app.  I've implemented routing from A to B by calling the ve routing service:

http://staging.dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc

I get a response, but the plotting just shows broken lines often off the streets. for the plotting I simply use:

 

 

 

<font size="2">

 

</font>

Shape shape = new Shape();

<font size="2">

shape.ShapeType = InfoStrat.VE.

</font>

VEShapeType.Polyline;<font size="2">

 

</font>

 

foreach (Georouting.ItineraryItem item in  response.Result.Legs[0].Itinerary)

{<font size="2">

shape.Points.Add(

</font>

new InfoStrat.VE.VELatLong(item.Location.Latitude, item.Location.Longitude));

}

<font size="2">

veMap.AddShape(shape,

</font>

"route");

 

Any ideas. Does it simply have to do with the staging service vs. the production service?

 

Thx again.

Coordinator
Jun 3, 2009 at 3:50 PM

Sorry, I don't know about why it might have broken lines.  Your code looks like it should work.  Try looking at the raw data in the Legs[0].Itinerary and seeing if there is anything funny about it.

Jun 18, 2009 at 11:15 AM

I've taken some time to look at this issue. The broken lines come about simply because they don't follow the curvature of the earth. I I keep Polyline.AltitudeMode = FromGround and add a few meters (say 10) to the altitude things are already better. However I cannot use veMap.AddShape as Shape has a collection of VELAtLon which doesn't contain altitude and it's only in the AddShape method  that you convert veLatLon to LatLonAlt.

However the main problem seems to be that the routing service's calculate route doesn't return enough points. But that's not your problem.

Jun 18, 2009 at 1:32 PM

I have just written some code to use the google routing service. This confirms the above. For a same departure and arrival, virtual earth return 9 points and google 90!. Maybe that's where the difference is between staging and production services provided by virtual earth. But how can I be cetain?

Coordinator
Jun 18, 2009 at 3:12 PM

VELatLong does have an altitude property and it is converted into LatLonAlt properly if it is set.

I'm pinging some contacts on the VE3D team to see if they have any guidance.

Coordinator
Jun 19, 2009 at 11:40 PM

Ok, got a response.  The current method described above creates a 3D line, which as you've found out is not satisfactory since it intersects the terrain.

There is a slightly different method which creates a 2D line that always overlays the terrain regardless of number of points.

This is the code sample they provided.  Polygon can be replaced with Polyline for our purposes.

                    LatLonAlt m_startingPos = LatLonAlt.CreateUsingDegrees(40, -122, 10000);
                  LatLonAlt endingPos = Host.Navigation.PointerPosition.Location;
                  Host.Geometry.RemoveGeometry("My Layer", "SelBox");
                  LatLonAlt[] points = new LatLonAlt[4];
                  points[0] = new LatLonAlt(m_startingPos.Latitude, m_startingPos.Longitude, 0);
                  points[1] = new LatLonAlt(m_startingPos.Latitude, endingPos.Longitude, 0);
                  points[2] = new LatLonAlt(endingPos.Latitude, endingPos.Longitude, 0);
                  points[3] = new LatLonAlt(endingPos.Latitude, m_startingPos.Longitude, 0);

                  PolyInfo style = PolyInfo.DefaultPolygon;
                  style.LineWidth = 2;
                  style.LineColor = Color.FromArgb(255, 0, 01);
                  style.Filled = false;
                  style.DashStyle = DashStyle.DashDot;

                  Host.Geometry.AddGeometry(new PolygonGeometry("My Layer", "SelBox", this, points, PolygonGeometry.PolygonFormat.Polygon2D, style));

The overload that takes Polygon2/Polyline2 will have the same effect.  The lines will draw on the ground, following the terrain exactly.

As for the number of points returned by VE vs. Google, VE's services reduces the number of point that would be in a straight line anyway.  Using the method above will follow the terrain and only need latitude and longitude for each point.

Jun 23, 2009 at 1:22 PM

Well, it does work much better but not perfect. I still get a few missing segments using the virtual earth routing service.

 

Regarding the number of points, I suggest you try this as an example and forward to your friends if you get the same result as me (I have chosen NY only because it may have better GIS info).

The start of the track seems to be OK, but then it's all over the place!

start location:: 40.644632134160233 / -74.103277135907049

end location:: 40.708518028284395 / -74.017532940244919

call to routing service (using the service def: http://staging.dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc?wsdl):

 

        public static Georouting.RouteResult GetRoute(Geocoding.GeocodeLocation loc1, Geocoding.GeocodeLocation loc2) 
        {
            try
            {

                Georouting.RouteServiceClient routeService = new VE.Georouting.RouteServiceClient();

                Georouting.RouteRequest req = new VE.Georouting.RouteRequest();

                Georouting.MajorRoutesRequest mreq = new VE.Georouting.MajorRoutesRequest();

                // Set the credentials using a valid Virtual Earth token
                string token = GetToken();
                req.Credentials = new Georouting.Credentials();
                req.Credentials.Token = token;

                Georouting.Waypoint[] wps = new VE.Georouting.Waypoint[2];
                wps[0] = new VE.Georouting.Waypoint();
                wps[0].Location = new VE.Georouting.Location();
                wps[0].Location.Latitude = loc1.Latitude;
                wps[0].Location.Longitude = loc1.Longitude;
                wps[1] = new VE.Georouting.Waypoint();
                wps[1].Location = new VE.Georouting.Location();
                wps[1].Location.Latitude = loc2.Latitude;
                wps[1].Location.Longitude = loc2.Longitude;

                req.Waypoints = wps;
                req.Options = new VE.Georouting.RouteOptions();
                req.Options.Optimization = VE.Georouting.RouteOptimization.MinimizeDistance;
                req.Options.RoutePathType = VE.Georouting.RoutePathType.Points;
                req.Options.Mode = VE.Georouting.TravelMode.Driving;

                req.UserProfile = new VE.Georouting.UserProfile();
                req.UserProfile.DistanceUnit = VE.Georouting.DistanceUnit.Kilometer;

                Georouting.RouteResponse response = routeService.CalculateRoute(req);

                if (response.Result != null)
                    return response.Result;

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            return null;
        }


    }
 
and for drawing the route something like:
 
            PolyInfo polylineStyle = PolyInfo.DefaultPolyline;
            polylineStyle.LineWidth = 4;
            polylineStyle.AltitudeMode = AltitudeMode.FromGround;

            <font size="2" color="#2b91af"><font size="2" color="#2b91af">

List

</font></font>
<font size="2" color="#2b91af">

 

</font>

<LatLonAlt> lla = new List<LatLonAlt>();

	//use the above Result presuming it return a leg.
                foreach (ItinerayItem item in Result.Legs[0].Itinerary)
                    lla.Add(new LatLonAlt(item.Location.Latitude * Math.PI / 180.0, item.Location.Longitude * Math.PI / 180.0, 0));

                this.GlobeControl.Host.Geometry.AddGeometry(
                    new PolylineGeometry("route", Guid.NewGuid().ToString(), null, lla.ToArray(), PolylineGeometry.PolylineFormat.Polyline2D, polylineStyle));

Aug 18, 2009 at 4:44 PM
Edited Aug 18, 2009 at 6:06 PM

I tried using microsoft's polyline solution described above, but all my shapes end up at the north pole.  My coordinates appear to be valid for a location in the US (lats are around 34 and longs are around -87).  

Has anyone run into this problem before?

 

-Woops, disregard that question, I wasn't getting the correct double values from parsing the file.

Sep 6, 2010 at 11:55 AM

Hi all,

I am trying to draw a polyline after making the route request but I cannot use the class PolyInfo.

How does it work? How can I integrated in my solution?

Thanks in advanced,

Pau Bustillo

Sep 6, 2010 at 2:10 PM

Hi All!

I've solved the issue by including the dlls of MapPoint that are in the project InfoStrat.

The problem I have now is when I compile the solution that appears these error:

Error 2 The type 'System.Windows.Forms.Control' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. 

Map.GlobeControl.Host.Geometry.AddGeometry(

new PolylineGeometry("route", Guid.NewGuid().ToString(), null, lla.ToArray(), PolylineGeometry.PolylineFormat

.Polyline2D, polylineStyle));

I can type the whole line without errors, but when I press F5 I get the error.

Thanks in advanced,

Pau



Coordinator
Sep 6, 2010 at 4:33 PM

Since the error message says "You must add a reference to assembly 'System.Windows.Forms" I have to ask the obvious -- did you add a reference to System.Windows.Forms? :)

Sep 7, 2010 at 8:19 AM

Sorry, I was sleeped when I made the question... It's obviously solved.

Thanks

Sep 28, 2010 at 1:07 PM
Edited Sep 28, 2010 at 1:09 PM

I got it working after a morning researching. I struggeld with various things so I would like to post my working code. This code sets a start and end point en draws it on the map.

Thanks for all the information in this codeplex project. I'm really missing some how to's to get things started. Hopefully someone can use my code and save a lot of time:)

 

 

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.MapPoint.Rendering3D;
using Microsoft.MapPoint.Rendering3D.Utility;
using SurfaceApplication1.GeocodeService;
using SurfaceApplication1.SearchService;
using SurfaceApplication1.ImageryService;
using SurfaceApplication1.RouteService;

using InfoStrat;
using InfoStrat.VE;
using Microsoft.MapPoint.Geometry;

using System.Text.RegularExpressions;


namespace SurfaceApplication1
{
    class MapsHandler
    {

        public void CreateRoute(VEMap surfaceMap)
        {

            RouteRequest routeRequest = new RouteRequest();

            // Set the credentials using a valid Bing Maps key
            routeRequest.Credentials = new RouteService.Credentials();
            routeRequest.Credentials.ApplicationId = "Your ID";
            

            // Set the start, stop, and end points
            Waypoint[] waypoints = new Waypoint[2];
            waypoints[0] = new Waypoint();
            waypoints[0].Description = "Start";
            waypoints[0].Location = new RouteService.Location();
            waypoints[0].Location.Latitude = 53.209322;
            waypoints[0].Location.Longitude = 6.564331;
            //waypoints[1] = new Waypoint();
            //waypoints[1].Description = "Stop";
            //waypoints[1].Location = new RouteService.Location();
            //waypoints[1].Location.Latitude = 43.89;
            //waypoints[1].Location.Longitude = -79.13;
            waypoints[1] = new Waypoint();
            waypoints[1].Description = "End";
            waypoints[1].Location = new RouteService.Location();
            waypoints[1].Location.Latitude = 51.822198;
            waypoints[1].Location.Longitude = 5.74585;

            routeRequest.Waypoints = waypoints;

            // Make the calculate route request
            RouteServiceClient routeService = new RouteServiceClient("BasicHttpBinding_IRouteService");

            RouteResponse routeResponse = routeService.CalculateRoute(routeRequest);

            
            PolyInfo polylineStyle = PolyInfo.DefaultPolyline;
            polylineStyle.LineWidth = 4;
            polylineStyle.AltitudeMode = AltitudeMode.FromGround;

            StringBuilder latLongBuilder = new StringBuilder();
            List<LatLonAlt> lla = new List<LatLonAlt>();

            foreach (var point in routeResponse.Result.RoutePath.Points){
                lla.Add(new LatLonAlt(point.Latitude * Math.PI / 180.0, point.Longitude * Math.PI / 180.0, 0));
                latLongLatBuilder.Append(point.Latitude + "-" + point.Longitude + "\n");
            }

            surfaceMap.GlobeControl.Host.Geometry.AddGeometry(new PolylineGeometry("route", Guid.NewGuid().ToString(),
                                                                                   null, lla.ToArray(),
                                                                                   PolylineGeometry.PolylineFormat.
                                                                                   Polyline2D, polylineStyle));
            using (StreamWriter outfile =
            new StreamWriter(@"c:\LatLong.txt"))
            {
                outfile.Write(latLongBuilder.ToString());
            }         
        }
    }
}

 

Coordinator
Sep 28, 2010 at 4:31 PM

Thanks for sharing rburgundy!