Streetside in Silverlight


Fig 1 – Streetside in Silverlight

A flood of announcements have been coming up over in Bing Land. You can try some of these out here: Bing Maps Explore

Significant is the “Bing Maps Silverlight Control Extended Modes Beta and Control 1.0.1.0″ coming just a week or two after initial release 1.0.0.0 of Bing Maps Silverlight Control. I have to get a handle on these names, so regretfully, let’s assume the military style – “BMSC.” These are separate from the the larger stable of Silverlight 4 Beta releases, recently announced.

Chris Pendleton’s Bing Blog (Why the urge to add “Bop” after this?) has some early detail on how to install, what is included, and how to make use of it.

What is included of note are two new map modes:

    BirdseyeMode.AddModeToNavigationBar(myMap);
    StreetsideMode.AddModeToNavigationBar(myMap);

Birdseye adds a pseudo 3D imagery mode that lets us move around in oblique space with realistic helicopter view angles. We are given tantalizing heading rotation capabilities, but limited to the compass quadrants, north, south, east, and west.

Streetside is the additional deep zoom street side photo views which afford zoom pan and a navigation run figure for hustling along the street. Streetside navigation includes circular heading, vertical pitch, and magnified zoom capabilities. Anyone used to the DeepZoom affects will find this familiar, but the running figure adds some travel legs to the process.

Neither of these modes are universal at this point. Here is the coverage extent shown in cyan for Streetside photos:


Fig 2 – Streetside current extent



Fig 3 – Streetside current extent at more detail

How to make use of these riches?

After downloading and replacing BMSC 1.0.0.0 with the new BMSC 1.0.1.0, I then installed the BMSCEM Beta and I’m ready to do some experiments. One thought that occurred to me was to add some streetside to a rout demonstration. The idea is to have an additional panel in a more prosaic geocode/route demo that will show streetside photos along the route path returned by the Bing Maps Web Services Route Service i.e. BMWSRS hmmmm? even the military might balk at this? Fig1 above shows how this might look in Road mode. This proceeds in several steps:

  1. Geocode with BMWSGS the start and end addresses
  2. Route between the two locations with BMWSRS
  3. Turn the resulting RoutePath into a MapPolyline with Pushpin images at start and end
  4. Add vehicle icon at the start
  5. Add some event handlers to allow users to drag the car icon constrained to the route path
  6. And finally connect the car icon position to streetside photos shown in the panel


Fig 4 – Streetside in Silverlight Aerial mode

In the sample you can see the navigation figure inside the streetside panel that lets users move inside the streetside photo space.

It is interesting to see how route path overlays are affected by the several map modes including Birdseye and Streetside. As you can see from the next couple of figures the Route MapPolyline does not pass through a transform to match either Birdseye or Streetside view.


Fig 5 – Streetside in Silverlight Birdseye mode
(note route path is shifted off to south by about 9 blocks)


Fig 6 – Streetside mode with heading rotated to see a route MapPolyline that is totally unrelated to the photo view

In Fig 5 and Fig 6 above, you can see that the streetside photos and Birdseye perspective are taking advantage of 3D perspective transforms, but the custom layer is aligned with the tilted road mode hidden behind the photo/image. It appears that visibility of other Map Layers will need to be part of a mode switch between Road or Aerial and Birdseye and Streetside.

Aside from that another interesting aspect of this example is the route constraint algorithm. The user fires a
MouseLeftButtonDown += car_MouseLeftButtonDown
event attached to the car icon to start the process which flags cardown mode true. However, the corresponding button up event is added to the MainMap rather than the icon.
MainMap.MouseLeftButtonUp += car_MouseLeftButtonUp;

This insures that the user can continue moving his mouse with the left down even while no longer over the car icon and that we can continue to lookup nearest point on route path for constraining our icon to the path.

private void car_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
cardown = true;
}

private void car_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (cardown) cardown = false;
}

The real action, though, takes place in the MainMap MouseMove event, where we find the nearest point on the route path, set the car map position, set the streetside view location, and finally calculate the streetside view heading from the segment vector:

Point p = e.GetPosition(MainMap);
Microsoft.Maps.MapControl.Location LL = MainMap.ViewportPointToLocation(p);

 if(cardown) {
  Segment s = FindNearestSeg(LL, routePts);

  MapLayer.SetPosition(car, s.nearestPt);
  StreetviewMap.Mode.Center = s.nearestPt;
  double dx = (s.linePt2.Longitude - s.linePt1.Longitude);
  double dy = (s.linePt2.Latitude - s.linePt1.Latitude);
  double angle = 0;

  if (dx > 0) angle = (Math.PI * 0.5) - Math.Atan(dy / dx);
  else if (dx < 0) angle = (Math.PI * 1.5) - Math.Atan(dy / dx);
  else if (dy > 0) angle = 0;
  else if (dy < 0) angle = Math.PI;
  else angle = 0.0;// the 2 points are equal  
  angle *= (180 / Math.PI);
  HeadingText.Text = String.Format("{0,10:0.000000}", angle);
  StreetviewMap.Heading = angle;

}

Here is some code adapted from my venerable Bowyer and Woodwark “Programmer’s Geometry” book. Yes, they used to have books for this type of algorithm. Bascially the code loops through each segment and finds the nearest perpindicular point of intersection using parametric lines. Since I’m only comparing for the least distance, I don’t need to use the Math.Sqrt function to get actual distances.

private Segment FindNearestSeg(Location LL, LocationCollection routePts){

  Segment s = new Segment();
  double dist = Double.MaxValue;
  double d = 0;
  double t = 0;

  int pos = 0;
  Location pt0 = new Location();
  foreach (Location pt1 in routePts)
  {
    if (pos++ > 0)
    {
      double XKJ = pt0.Longitude - LL.Longitude;
      double YKJ = pt0.Latitude - LL.Latitude;
      double XLK = pt1.Longitude - pt0.Longitude;
      double YLK = pt1.Latitude - pt0.Latitude;
      double denom = XLK * XLK + YLK * YLK;
      if (denom == 0)
      {
        d = (XKJ * XKJ + YKJ * YKJ);
      }
      else
      {
        t = -(XKJ * XLK + YKJ * YLK) / denom;
        t = Math.Min(Math.Max(t, 0.0), 1.0);
         double xf = XKJ + t * XLK;
         double yf = YKJ + t * YLK;
        d = xf * xf + yf * yf;
      }
      if (d < dist)
      {
        dist = d;
        s.nearestPt = new Location(pt0.Latitude + t * YLK, pt0.Longitude + t * XLK);
        s.linePt1 = new Location(pt0.Latitude, pt0.Longitude);
        s.linePt2 = new Location(pt1.Latitude, pt1.Longitude);
      }
    }
    pt0 = pt1;
  }

  return s;

}

Here is a small class to hold the results of the minimal distance segment and intersect point:

public class Segment    
{
 public Location linePt1 { get; set; }
 public Location linePt2 { get; set; }
 public Location nearestPt { get; set; }
}

All of this is fired with each mouse move event to scan through the route path nodes and get the segment nearest to the current user position. That this all works smoothly is another testimony to the advantage of CLR over Javascript on the client.

The resulting Segment then holds the segment end points and the intersection point. The intersection point is available for placing the car icon position as well as the StreetviewMap.Mode.Center in our Streetside panel. The additional segment endpoints are handy for calculating the heading of the streetside view direction. This is used to point along the vector direction of the path segment by calculating the compass direction and applying it to the StreetviewMap.Heading = angle;

The result slides the car icon along our route path while updating the Streetside View panel with a StreetviewMap heading in the same direction as the route.

Unfortunately, the Streetview loading is currently too slow to do a film strip down the route, which is too bad as my next idea was an animated route with concurrent streetside views from whatever direction (angular delta) set in Streetside View by the user. Of course the run navigator does a good job of moving in heading direction, it’s just not in my control. If I can get control of this navigator, I would try a run navigate along a route leg until reaching a waypt, and then turn to a new heading before starting navigation run again for the next route leg.

However, I just discovered that by adding a ViewChangeEnd event to my streetview panel,
StreetviewMap.ViewChangeEnd += car_Update;,
I can use the Center location to update my car location.
MapLayer.SetPosition(car, StreetviewMap.Mode.Center);
Now I can hustle down the street with the Streetside Navigation runner, and at least have my car location shown on the map. Cool!


Summary

Streetview and Birdseye are nice additions to the list of map modes. They have some restrictions in availability, but where they are available, add some useful features. My experiment just scratches the surface available with Silverlight Control Extension Modes.

Here are a few problems that surfaced with my example:

  1. The routepath returned by RouteService can be just slightly off the route traveled and consequently the Streetside location will be incorrect. Also setting StreetviewMap.Mode.Center to a location will snap to the closest street photo even if it is off route at an intersection. This appears as a series of streetviews for streets crossed by a route instead of on the route desired. At least that’s my theory for the occasional odd view of lawns instead of the street ahead.
  2. Map children layers are not automatically transformed to these new views and mode change events will need to manipulate visibility of custom layers.
  3. I had to turn off drag on the Streetview panel so that users can do normal streetview pan and zoom.
  4. It is necessary to check for a valid streetside photo. If the route runs off streetside coverage, the last valid streetside view location remains in the panel regardless of the new icon positions.

Obviously “alternate reality” continues to converge with “ordinary reality” at a steady pace, at least in web mapping worlds.

Here comes the LiDAR!


QCoherent LiDAR Server
Fig 1 – LiDAR Server in Silverlight MapControl

Online LiDAR is reaching critical mass and there are a lot of interesting projects.

PAMAP is one example with LiDAR covering all of Western Pennsylvania, which due to the Alleghenies, has a good deal of interesting topography at 3.2 ft resolution. Unfortunately, the Get Capabilities shows that this is another of those no spherical mercator, EPSG:3857, WMS services. Meaning the image doesn’t line up with underlying web map services.

PAMAP LiDAR in Silverlight View
Fig 2 – PAMAP LiDAR WMS

The GEON website is another LiDAR project offering access to LiDAR sets via opentopography.org or OpenTopography Portal

Here is a view of a GeoEarthScope ISB LiDAR 0.5 m data set shown on GoogleEarth

GoogleEarth LiDAR
Fig 3 – GoogleEarth view of OpenTopography ISB LiDAR data (unfiltered)

In addition to providing raw data and GoogleEarth kml views, GEON has received NSF ClueE funding for a Cloud based service:

On Demand LiDAR
“The project will study dynamic strategies for provisioning such applications by doing a performance evaluation of alternative strategies for serving very large data sets. The cloud platforms that will be used in the project will be the Google-IBM CluE cluster and the HP-Intel-Yahoo cluster, both of which have been assembled in collaboration with NSF for cloud computing research. The LiDAR processing application hosted at the OpenTopography portal has been selected as the representative application for this study. The application allows users to (i) subset remote sensing data (stored as point cloud data sets), (ii) process it using different algorithms, and (iii) visualize the output. The project will study alternative implementations for each stepusing database technology as well as Hadoop (www.hadoop.org) and run a series of performance evaluation experiments. Cloud platforms with thousands of processors and access to hundreds of terabytes of storage provide a natural environment for implementing OpenTopography processing routines, which are highly data-parallel in nature.”

Looks like they hit all the sweet spots. Of course you don’t need to have access to specialized NSF funded Google-IBM CluE clusters to play. Amazon’s Elastic MapReduce lets ‘poor folk’ have a crack at Hadoop playgounds too.

On a less esoteric note, I pointed my new Silverlight MapControl CTP WMS viewer at a LiDAR Server project by QCoherent. QCoherent is nearly a neighbor with their office down the street a mile or two from me here in Colorado. I don’t really use their LiDAR software (I’m the online only sort), but I was fascinated to learn that they have a new LiDAR Server for providing WMS access to LiDAR data.

LiDAR Server is a WMS middle tier server that provides online access to LiDAR datasets with on the fly styling, tinning, and contouring.

  • WMS compliant map server
  • Multiple representations of LiDAR data: points, TIN, contours, etc.
  • Unique layers for each representation
  • Multiple ways of filtering and colorizing data (implemented through styles in the WMS)
  • High performance on-the-fly tinning engine
  • High performance on-the-fly contouring engine

It wasn’t much of a stretch to add a few of LiDAR Server sample urls to my Silverlight viewer and go exploring. The WMS is 1.3.0 compliant and does publish EPSG:3785 (now deprecated in favor of EPSG:3857), so Virtual Earth alignment is possible. Basically the GetCapabilities exposes four layers – Boundaries, Points, Contours, and TIN. Each of these layers has a series of selectable styles such as All or Ground Elevation, Classification, Intensity, and Return which are simply preset style coloring. The layers are queryable which means GetFeatureInfo requests are active.

Here are some examples using the Silverlight WMS Viewer:

LiDAR Server
Fig 4 – LiDAR Server Vancouver TIN AllElevation Building Footprints

I’ve turned down opacity slightly so the Aerial MapMode can just be seen beneath. Its interesting to note the footprint against the aerial imagery and see how well orthrectification worked, or not. Tough in the middle of hirise towers. Dark blue is Elevation (Z): -14.01

LiDAR Server
Fig 5 – LiDAR Server Vancouver TIN AllElevation Building Footprints + Contours

LiDAR Server
Fig 6 – LiDAR Server Cumberland TIN GroundElevation – Bare Earth

LiDAR Server
Fig 7 – LiDAR Server Cumberland TIN AllClassification

LiDAR Server
Fig 8 – LiDAR Server Cumberland Contour AutoGround

Note that all the heavy lifting is done by LiDAR Server. The Silverlight Viewer merely takes advantage of the exposed WMS service to show various sets of layers over Virtual Earth base. When I get around to it I’ll be adding other base as well: OSM, Yahoo, OpenAerial etc. I was surprised at the speed of the ‘on the fly’ TIN and contouring capability. The OpenGL 1.3 capable video card requirement prohibits use in an Amazon Cloud sense, since EC2 instances are all headless, i.e. graphic cards not expected anytime soon.

LiDAR is obviously a 3D oriented resource and at present Silverlight is 2D only. Too bad. Although there is a 2.5D capability in Silverlight 3.0 beta that lets a MapControl surface be twisted out of screen plane, this doesn’t help much with topography explorations. Since the Javascript VE SDK does allow a 3D mode it could drape images over terrain just like GoogleEarth. I assume Silverlight is headed toward 3D like WPF, but I’m just speculating. If any Microsoftee reads this please put in a good word for 3D Silverlight real soon now.

Keep in mind, however, that the actual WMS output is imagery, png or jpg, not mesh. In the GoogleEarth kml example the LiDAR is ground clamped <GroundOverlay> png images. In other words all the increased clarity of 0.5m resolution LiDAR is an illusion based on shaded imagery draped over existing Google terrain at whatever resolution it maintains. Of course Google and Microsoft are in a race to provide the highest resolution DEM available so it is possible 1m PAMAP is already included.

I’m sure there are other significant online LiDAR projects out there, and I haven’t even looked at BIM LiDAR which is heating up as well.

Summary
Looking forward to national submeter coverage!

"Bing" chatter


Sound of Found
Bing Chatter – “The sound of found: Bing?”

Wait found what? Where’s the Bing? We Bing You decide.

Seems a bit late to be rebranding “Virtual Earth.” I know “Virtual Earth” is a long name but there was at least some symmetry with “Google Earth.”

Oops .. maybe that’s a problem?

Bing maps for enterprise

In the same vein as Fortune Cookie Bing: “Disease”
Google Language Bing =>冰 冰 => “Ice”
Babelfish Bing => 堆 堆 => “Piling”

I guess Chinese translation tools aren’t commutative. Babel, Piling, Ice, Bing, Bam for the Enterprise?

Do I detect a bit of embarrassment: rebranding-microsoft-virtual-earth-to …